您当前的位置:首页 >> 互联网 >  >> 正文
【mugen】猴子也能看懂的mugen凶恶原理(3)——StateDef溢出
来源: 哔哩哔哩      时间:2023-03-31 12:20:02

5.         StateDef溢出


【资料图】

通过搜索得知,其为[Statedef -3]中-3这部分的溢出,那么直接编写溢出代码,放在kfm.cns第一个Statedef之上。

od不会智能跳转到溢出报错处,x64dbg可以。

查看47ED05对应反编译代码,位于sub_47EBF0()——memset()

memset()也会溢出吗?理论上并不会,用od断点47ED05,查看汇编对应的含义,就明白发生了什么。

rep stos dword ptr es:[edi]

将edi开始的内存覆盖为eax(为0),4字节一次循环ecx次,这也正是memset()开辟内存核心汇编。而esi和edi都为41414141,很明显是因为前面47ECF2的汇编导致的。也就是说在47ED05之前,已经因为栈溢出覆盖掉了栈中一部分正常的地址,导致memset()报错。

那么具体是哪儿出现的栈溢出呢?稍微熟悉栈溢出的同学,往上翻一翻sub_47EBF0()的代码,就会发现正确答案。

非常熟悉的strcpy(),v33只有64个字节,a3是个int,也就是原本为[Statedef -3]的-3,如果我们填充64个A,就会导致溢出。

动态调试后发现这个动作是在47EC37完成的,再写一个[Statedef AAAA]进去,两次断点来对比一下到底能覆盖哪些东西。

可以看到覆盖了多个返回地址,实际测试下来其中有用的是D3FEE74,偏移量为Statedef+56,那么填充数据就是"Statedef "+"A"*55+"BBBB",注意Statedef后门带个空格。

修改一下后逐步单步后发现尝试跳转到BBBB。

栈溢出最简单的利用方式是栈内执行,这需要无NX保护和jmp esp,winmugen刚好满足条件。其自带的ALLEG40.DLL在0x1005FB9D地址写着call esp。

checksec.exe Winmugen.exe

!mona jmp -r esp -cpb "\x00"

那么利用python来替换字符串写入shellcode,当然惯例先用NOP尝试。

在1005FB9D下断点,但并没有达到理想中的效果进入栈中执行,动态调试后可以发现还是因为47ED05也就是memset报错。

经过简单测试,可以发现47ED05被破坏的栈在ret地址后5-8位。

根据47ED05上的汇编,本质上是清空一段内存地址,那么我们需要使用一个可写的地址替换掉AAAA,让其不再报错。学习%n和%f的时候我们用过两个不重要的地址0x4b4048和0x4B4000,但由于它实际上是0x00开头的有坏字符所以不行。同理整个winmugen.exe都不行,还好ALLEG40.DLL都是0x10开头的地址,那我们在data断上找一个空白的地址就行。我这里随便选的0x1009BDAD。

成功断到1005FB9D,栈布局也和我们溢出的一样。

那么在127EEE78断点,F8后成功在栈上执行NOP。

这样就能执行shellcode了吗?还不行,因为我们增加了一个1009BDAD的原因,栈上会把这个地址当作汇编来使用,同样会报错导致无法执行后续的shellcode。这个时候可以利用jmp short跳过这段不可控的地址。

可以看到刚好跳到NOP上,现在可以执行shellcode了吗?还是不行,因为溢出有长度限制,msfvenom最短也要220个字节,而我们只能在栈上控制164字节左右。

这里可以想办法缩短shellcode,但还是推荐另外一种不限shellcode长度的办法,参考Reboot人物。它的Reboot.st是这样的。

使用它之前可以修改shutdown的字节,以免真的导致系统重启,断点47EC1C(sub_47EBF0较前的地址)动态调试。前面有很多无意义的Statedef,快速F9到溢出,也就是Statedef 5900后面一个。

F8几下之后就会发现栈溢出,返回地址被覆盖为5D403246,和Reboot.st可以对应上。但剩下的并没有覆盖。

再F8到47EC4E就会发现5D变成了00,为什么呢?因为\x5D是],完成了对[Statedef的闭合。

继续F8,可以看到Need at least one state controller提示,这是对state的检测,代码如下。

可以看到离我们之前绕过的memset()非常近,而且这个代码中存在return。因为我们在溢出Statedef下面写了一个加气的state,所以走不进这个if中,所以才需要绕memset(),如果没有state,就可以提前return了。

代码走到retn,栈中可以看到,即将跳转到作者精心布置的一个地址403246

而这个地址的代码非常简单,add esp,0x10然后retn,也就是说再次跳转到栈+16的指针,也就是99E244A。

这个地址里存储了溢出Statedef空格后面所有的字节,所以一开始就用jmp short跳到下面的NOP。此时shellcode长度的限制就完全没有了。我们先修改kfm.cns.bak代码。

然后写好python脚本。

msfvenom -p windows/exec cmd="calc" exitfunc=thread -b "\x00\x1A\x3B" -f python

效果如下。

标签:

X 关闭

X 关闭