文章作者:cawan
信息来源:邪恶八进制信息安全团队(
www.eviloctal.com)
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]
http://msdn.microsoft.com/librar ... ction_constants.asp
[3]
http://msdn.microsoft.com/librar ... /virtualallocex.asp