通过全局变量和自擦除代码来防Dump(2)
通过全局变量和自擦除代码来防Dump(2)
write by 九天雁翎(JTianLing) -- www.jtianling.com
《通过全局变量和自擦除代码来防Dump 》中我提到了用WriteProcessMemory来完成代码段的自擦除,其实这并不是什么好的手段,因为使用了Win32 API,对于分析你代码的人来说,这是明摆着告诉对方你要干什么,破解手段在原文中也提到了不少。其实,当时我去搜寻WriteMemroy API但是并不存在的时候,我就在想,为什么微软不提供,并且,同样的,有ReadProcessMemory但是有ReadMemory,为什么要使用的时候都需要通过GetCurrentProcess()作为第一参数这样奇怪的形式,这个MS一贯的作风不符。这两个函数只在WinCE中有提供,普通Windows并没有,其实后来仔细想想就想通了,因为读写另外的进程的内存你必须要通过额外API,所以有这样的API给你来使用,但是读写自己的内存根本就不需要别的特殊的API,自己进程访问和改写自己进程中的数据是没有限制的。因此,需要做自擦除的操作仅仅需要memcpy或者memset就可以了!
下面是改进的示例:
 1 #include "windows.h"
 2 #include "tchar.h"
 3 
 4 void Run()
 5 {
 6     // begin of the func
 7     DWORD ldwBegin = 0;
 8     __asm
 9     {
10         call $+5
11         pop eax
12         mov ldwBegin, eax
13     }
14     DWORD ldwOldPro = 0;
15     // Must have this step
16     if(!VirtualProtect((void*)ldwBegin, 1000, PAGE_EXECUTE_READWRITE, &ldwOldPro))
17     {
18         printf( "VirtualProtectEx failed (%d)./n", GetLastError() );
19         return;
20     }
21 
22     MessageBox(NULL, _T("Right"), _T("Hello World"), MB_OK);
23 
24         // begin of the func
25     DWORD ldwEnd = 0;
26     __asm
27     {
28         call $+5
29         pop eax
30         mov ldwEnd, eax
31     }
32 
33     DWORD ldwFuncLen = ldwEnd - ldwBegin;
34     BYTE *lpbyRand = new BYTE[ldwFuncLen];
35 
36     DWORD ldwWritten = 0;
37     memcpy((void*)ldwBegin, lpbyRand, ldwFuncLen);
38 
39     delete[] lpbyRand;
40 }
41 
42 int main(int argc, char* argv[])
43 {
44     Run();
45     MessageBox(NULL, _T("OK"), _T("OK"), MB_OK);
46 
47     return 0;
48 }
49 
50
这样做后,就没有办法简单的将memcpy挂上使其无效化来使得擦除无效,而且,从发现你的目的的难度上来讲也更加大一些,毕竟memcpy这种函数使用的频率太高了,你可能因为各种原因使用它,而不仅仅是反Dump的目的。这也加大了分析的难度:)
write by 九天雁翎(JTianLing) -- www.jtianling.com
Posted By 九天雁翎 at 九天雁翎的博客 on 2009年02月09日