给程序加壳就是给程序动手术,一点也马虎不得,稍微一不留神就出问题.
本人一直学习使用c/c++做壳,所以bambam就是最好的参考(源码下载中有所有源码).

学习的过程就是读别人的代码,确实原理上不难,但实际一操作还挺麻烦的.这里讲一个给bambam调错的亲身经历吧.


背景:
bambam是bedrock根据bigboot的文章做的一个壳,代码写的很不错了.但他有的地方处理的不太合理.TLS是这个壳一个亮点,他使用了tls代理技术,巧妙的处理了tls,这个东西还是很实用的,尽管99%的程序不用他.borland编译的程序都有tls,但多数都是0,所以其实也没用.但如果这16个字节处理不好也会有问题.

下面是bambam的代码,
inline void FinaliseTlsStuff()
{
  PIMAGE_DOS_HEADER pDosHdr;
  PIMAGE_NT_HEADERS pNtHdr;
  DWORD dwKatSup;
  LONG lJmp;

  pDosHdr = (PIMAGE_DOS_HEADER)dwLoadAddress;
  lJmp = pDosHdr->e_lfanew;
  dwKatSup = (DWORD)pDosHdr;
  dwKatSup += lJmp;

  pNtHdr = (PIMAGE_NT_HEADERS)dwKatSup;

  if(pNtHdr->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_TLS].VirtualAddress != 0)
  {
        gev.tlsOriginal.AddressOfIndex = (DWORD*)dwTlsSlotIndex;

    void* pvTlsData;
    
    __asm
    {
      mov ecx, DWORD PTR dwTlsSlotIndex;
      mov edx, DWORD PTR fs:[02ch]
      mov ecx, DWORD PTR [edx+ecx*4]
      mov pvTlsData, ecx
    }

    int size = gev.tlsOriginal.EndAddressOfRawData - gev.tlsOriginal.StartAddressOfRawData;

    CopyMemory(pvTlsData, (void*)gev.tlsOriginal.StartAddressOfRawData, size);
    FillMemory((void*)gev.tlsOriginal.EndAddressOfRawData, gev.tlsOriginal.SizeOfZeroFill, 0);
  }
  fSafeToCallback = true;
  if(fDelayedTlsCallback)
  {
    TlsCallback(tlsDllHandle, tlsReason, tlsReserved);
  }
}

看上去这个代码写的很漂亮,而且运行起来也没问题,至少在windows9x-2003都可以很好的工作.但其实里面有个bug.

发现bug:
bug发现的很偶然,因为一般运行的时候都没问题.但有一次我在stub中开了一个线程,又在这个线程中开了第二个线程,这样的壳在win2000系列的平台是没问题的,但在win98下会报错.而且只有delphi的程序报错.

起初我以为是stub中线程的错误,就反覆修改,但还是同样的报错.就这样让我郁闷了很长时间.我觉的问题和tls有关,但就是找不到问题.

注意,win98下tls也是先启动的,所以可以确认win98是有tls支持的.

我甚至pediy一个exe,没有tls,他就不报错了.所以现在可以确定bug就在这段代码中.说实话,找这个bug很郁闷,因为很多的地方很难猜测系统运行的过程,因为系统loader报的错,就是olly能做的也很有限了.

只能从代码入手,一点点的看,突然,你可以看到有一个地方似乎有点古怪,gev.tlsOriginal.AddressOfIndex = (DWORD*)dwTlsSlotIndex; 实际上语法是没有问题的,但dwTlsSlotIndex是变量,能这么搞吗?当然可以这样做,其他的地方这样赋值很多,但这里似乎是错误的,应该改为gev.tlsOriginal.AddressOfIndex = (DWORD)&dwTlsSlotIndex;, 这样win98下就ok了.

这个问题修改是成功了,但我心理还是有些疑问,为什么win2000,xp就没事呢?

总结:
打壳就是动手术,一点都不能马虎,否则出了问题不好解决,主要是症状不好调试.这个文章写了我真实的经历,献给那些自己动手做壳的人吧.

  • 标 题:加壳要细心,我给bambam调错纪实
  • 作 者:wwwddd

exetools 论坛里面说了一个bug:
---------------------------------------------
First bug in stub:

Code:

hMod = LoadLibrary((LPCSTR)dwTemp);

if(hMod != INVALID_HANDLE_VALUE)

LoadLibrary return NULL in case of error, not INVALID_HANDLE_VALUE (-1)

---------------------------------------------

我找到一几个bug:
1.在对 stub 进行重定位处理时,有行代码错行了。

2.在 转换stub 中thunk 值时,搜索地址的方法有错漏。

3. 没有对pe文件中的多余数据(pe section 中未标明的)进行保留处理。

4. 没有对 stub 的VOffset 和 ROffset 进行对齐处理

5. 对 stub 的输入表起始地址处理有错