通过全局变量和自擦除代码来防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日