VirtualAlloc这个函数我用的还是比较的多的,以前用的时候,只知道最后与一个参数是位我们要求分配的空间设置的属性(给我们开辟的物理页设置的属性),我这段代码是给用VirtualAlloc函数开辟了一个页,属性位可读可写,在往这段内存写入一段硬编码,这段硬编码调用一个MessageBox如下图所示 ,本来我认为只有VirtualAlloc有可读可写可执行的属性的时候才能执行,结果设置也的属性是可读可写的时候也能执行,不知如此char Name局部的开辟的空间在堆栈,它也能执行成功了,这就让我不禁怀疑我这个人的思想出了问题,以前理解的都是错的嘛?
结合我这两个天所学的,段的属性有可读可写可执行,页的属性有可读可写,10-10-12分页没有可执行,后来inter和AMD在2-9-9-12分页(PTT ,PDT的每项是8个字节,于是在最高位设置了一个XD位)用于页的可执行检查,XD=0可执行,XD=1不可可执行,于是对0x3D0000,和0x13ff64这两个线性地址进程拆分,查看他们的所在PTE的XD发现,当VirtualAlloc函数为可读可写的时候XD=1,为可读可写可执行的时候XD=0, 而name所在的物理页,XD=1,我看的教程那老师让我们试验验证XD是否可用,但是试验结构栈里面的也XD=1 R/W=1可读可写,
VirtualAlloc函数参数为PAGE_READWRITE XD=1标志着页应该是不可执行的可读可写没得问题
Name的地址是0x13FF64 局部变量空间在堆栈中开辟的,对应物理页的属性是可读可写可执行没得问题
VirtualAlloc函数参数为PAGE_EXECUTE_READWRITE XD=0标志着页应该是可执行的可读可写没得问题
VirtualAlloc第四个参数设置的是物理页的属性,让我有疑问的是没什么这段调用MessageBox的硬编码在这些情况下都能正确的执行成功,并返回呢,什么才是可执行,(由于实验颠覆了我的观念我验证了好几遍),用于求证才能在犯错的过程中学到更多的东西。
#include "stdafx.h"
#include <Windows.h>
typedef int (WINAPI MyMessageBox)( );
MyMessageBox Messbox;
int main(int argc, char argv[])
{
DWORD MessageAddr=0x77D507EA;
DWORD NextAddres=0;
DWORD address=0;
char Name[14]={0x6A,1,0x6A,0,0x6A,0,0x6A,0,0xe8,0,0,0,0,0xc3};
char addr=(char)VirtualAlloc(NULL,4096,MEM_COMMIT,PAGE_READWRITE);
if(addr==NULL){
MessageBox(NULL,"VirtualAlloc函数分配内存失败",0,0);
}
NextAddres=(int)addr+0xD;
address=MessageAddr-NextAddres;
((DWORD)&Name[9])=address;
memcpy(addr,Name,0xe);
Messbox=(MyMessageBox)(int)addr; //函数指针指向
Messbox(); //通过函数指针调用
NextAddres=(int)Name+0xD;
address=MessageAddr-NextAddres;
*((DWORD*)&Name[9])=address;
Messbox=(MyMessageBox)(int)Name;
Messbox();
printf("Hello World!\n");
getchar();
return 0;
}
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)