邪恶八进制信息安全团队技术讨论组's Archiver

cawan 2006-10-2 12:43

[原创]Debug Build与Release Build的一些差别

文章作者:cawan
信息来源:邪恶八进制信息安全团队([url]www.eviloctal.com[/url])

debug build和release build在被CreateProcess装载出后,各自在.rdata和.data的memory protection是有所不同的。先看看debug build的。如果用CreateProcess把checkme的debug build装载后,检查text string “Check me !” 的地址,发现memory protection是PAGE_READONLY(0x02) 。读出没有问题,写入出错。代码如下:

#include<stdio.h>
#include<windows.h>

int main()
{
  STARTUPINFO startupinfo;
  PROCESS_INFORMATION processinfo;
  char olddata[20];
  char newdata[]="cawan";
  char filename[]="c:\\changeme_debug.exe";
  //char filename[]="c:\\changeme_release.exe";
  unsigned long bytewrite;
  BOOL status;
  DWORD oldprotect;

  memset(&startupinfo,0,sizeof(STARTUPINFO));
  memset(&processinfo,0,sizeof(PROCESS_INFORMATION));
  startupinfo.cb=sizeof(STARTUPINFO);

  BOOL bRes=CreateProcess(filename,0,0,0,FALSE,CREATE_SUSPENDED,0,0,&startupinfo,&processinfo);
  if (bRes==0)
    return 0;

  status=VirtualProtectEx(processinfo.hProcess,(LPVOID)0x004153d4,10,0x08,&oldprotect);
    printf("\nProtect Status: %x",status);
    printf("\nOld Protect: %x",oldprotect);
  
  status=ReadProcessMemory(processinfo.hProcess,(LPVOID)0x004153d4,olddata,20,0);
    printf("\nRead Status: %x",status);

  status=WriteProcessMemory(processinfo.hProcess,(LPVOID)0x004153d4,newdata,10,&bytewrite);
    printf("\nWrite Status: %x",status);  

  ResumeThread(processinfo.hThread);
  
  printf("\nOld Data: %s",olddata);

  printf("\n");

  return 0;
}

输出如下:

Protect Status: 1
Old Protect: 2
Read Status: 1
Write Status: 1
Old Data: Change me!

代码里的0x004153d4是”Change me !” 的地址,可用ollydebug取得。输出里的”Old Protect” 就是原本的memory protection,0x02代表PAGE_READONLY。这里我们用0x08做置换,那是PAGE_WRITECOPY,因此可以把”Change me !” 换成”cawan” ,再用ResumeThread让它继续执行。我们可以看到输出的界面是”cawan” ,而非”Change me !” 。如果我们不置换memory protection,或把它换成0x01(MEMORY_NOACCESS) ,”Change me !” 的置换就不能成功。除了把它换成0x08外,换成0x02(PAGE_READWRITE)也可以。

在release build,它的memory protection本来就是PAGE_WRITECOPY(0x08) ,不需要做置换就可以改了。同样的,用ollydebug,我们知道它的地址是0x00403020,把代码改成如下即可。

#include<stdio.h>
#include<windows.h>

int main()
{
  STARTUPINFO startupinfo;
  PROCESS_INFORMATION processinfo;
  char olddata[20];
  char newdata[]="cawan";
  //char filename[]="c:\\changeme_debug.exe";
  char filename[]="c:\\changeme_release.exe";
  unsigned long bytewrite;
  BOOL status;
  DWORD oldprotect;

  memset(&startupinfo,0,sizeof(STARTUPINFO));
  memset(&processinfo,0,sizeof(PROCESS_INFORMATION));
  startupinfo.cb=sizeof(STARTUPINFO);

  BOOL bRes=CreateProcess(filename,0,0,0,FALSE,CREATE_SUSPENDED,0,0,&startupinfo,&processinfo);
  if (bRes==0)
    return 0;

  status=VirtualProtectEx(processinfo.hProcess,(LPVOID)0x00403020,10,0x08,&oldprotect);
    printf("\nProtect Status: %x",status);
    printf("\nOld Protect: %x",oldprotect);
  
  status=ReadProcessMemory(processinfo.hProcess,(LPVOID)0x00403020,olddata,20,0);
    printf("\nRead Status: %x",status);

  status=WriteProcessMemory(processinfo.hProcess,(LPVOID)0x00403020,newdata,10,&bytewrite);
    printf("\nWrite Status: %x",status);  

  ResumeThread(processinfo.hThread);
  
  printf("\nOld Data: %s",olddata);

  printf("\n");

  return 0;
}

输出如下:

Protect Status: 1
Old Protect: 8
Read Status: 1
Write Status: 1
Old Data: Change me!

因此,作为小结,VirtualProtectEx可以很好被应用为检测与置换某个地址的memory protection,同时,也指出一些debug build与release build间的差别。


p/s:"Change me !"的地址可能会因base relocation而有所不同。记得用ollydebug先做检测。此外,changeme的文件我也随这帖上传,这是Shub Nigurrath作为测试用的。


参考:

[1] Shub Nigurrath, "Guide on how to play with processes memory, writing loaders, and Oraculumns"

[2] [url]http://msdn.microsoft.com/library/default.asp?url=/library/en-us/memory/base/memory_protection_constants.asp[/url]

[3] [url]http://msdn.microsoft.com/library/default.asp?url=/library/en-us/memory/base/virtualallocex.asp[/url]

页: [1]
© 1999-2008 EvilOctal Security Team