PWN(二进制漏洞)
术语
exploit
用于攻击的脚本与方案
payload
攻击载荷,是目标进程被劫持控制流的数据
shellcode
调用攻击目标的shell代码
基础知识

可执行文件的分类
Windows:PE(Portable Executable)
可执行程序
.exe
动态链接库
.dll
静态链接库
.lib
Linux: ELF(Executable and Linkable Format)
可执行程序
.out
动态链接库
.so
静态链接库
.a
ELF文件头表(ELF header)
记录了ELF文件的组织结构
程序头表/段表(Program header table)
告诉系统如何创建进程
生成进程的可执行文件必须拥有此结构
重定位文件不一定需要
节头标(Section header table)
记录了ELF文件的节区信息
用于链接的目标文件必须拥有此结构
其他类型目标文件不一定需要
可执行文件
广义:文件中的数据是可执行代码的文件
.out .exe .sh .py
狭义:文件中的数据是机器码的文件
.out .exe .dll .so
段(segment)与节(section)
- 代码段(text segment):包含了代码与只读数据。其中的节有:
- .text 节:存放程序的机器代码。(例如存放main函数)
- .rodata 节(readonly data):存放只读数据,如字符串常量等。
- .hash 节、 .dynsym 节、 .dynstr 节、 .plt 节(解析动态函数的实际地址)、 .rel.got 节等。
- 数据段(data segment):包含了可读可写数据。常见的节包括:
- .data 节:用于声明了的全局变量。
- .dynamic 节、 .got 节(全局偏移表,Global Offset Table)、 .got.plt 节。
- .bss 节:用于存放还未声明的全局变量,在磁盘中并不占用空间,运行的时候可能会占用内存空间。

大端序与小端序
大端序列
低地址存放数据低位、高地址存放数据高位
我们所主要关注的格式
小端序列
低地址存放数据高位、高地址存放数据低位
AMD64寄存器结构
r开头是64位寄存器
e开头是32位寄存器
rax 8Bytes
eax 4Bytes
ax 2Bytes
ah 1Byte
al 1Byte
RIP
存放当前执行的指令的地址
RSP
存放当前栈帧的栈顶地址
RBP
存放当前栈帧的栈底地址
RAX
通用寄存器。存放函数返回值
64位 | 低32位 | 低16位 | 低8位 | 描述 |
---|---|---|---|---|
rax | eax | ax | al | 累加器 |
rbx | ebx | bx | bl | 基地址 |
rcx | ecx | cx | cl | 循环记数器 |
rdx | edx | dx | dl | 数据寄存器,通常扩展A寄存器 |
rsi | esi | si | sil | 字符串操作的源索引 |
rdi | edi | di | dil | 字符串操作的目的索引 |
rbp | ebp | bp | bpl | 栈指针 |
rsp | esp | sp | spl | 基地址指针(栈帧基地址) |
r8 | r8d | r8w | r8b | 新增通用寄存器 |
r9 | r9d | r9w | r9b | 新增通用寄存器 |
r10 | r10d | r10w | r10b | 新增通用寄存器 |
r11 | r11d | r11w | r11b | 新增通用寄存器 |
r12 | r12d | r12w | r12b | 新增通用寄存器 |
r13 | r13d | r13w | r13b | 新增通用寄存器 |
r14 | r14d | r14w | r14b | 新增通用寄存器 |
r15 | r15d | r15w | r15b | 新增通用寄存器 |
可执行文件结构


基础汇编
__cdecl函数调用约定
push ebp;mov ebp;sub esp,28h
28h 表示开辟40个字节空间
esp 栈顶,目前函数的栈顶
ebp 栈基址,目前函数的栈的基地址
push 指令为压栈指令
push ebp 表示将ebp的值压入栈中
mov ebp,esp 表示将esp的值拷贝到ebp,即ebp=esp
sub esp,28h 开辟40字节的空间
逆向过程中会遇到的函数
c语言
read 是一个系统调用,用于从文件描述符(fd)中读取数据到缓冲区(buf)
read(fd, buf, nbytes);
fd:文件描述符,是一个非负整数,用于标识打开的文件。它通常通过 open 系统调用获得。
buf:指向缓冲区的指针,用于存储从文件描述符读取的数据。
nbytes:要读取的最大字节数。
system($0)等于system(/bin/sh) $0的ascii为0x24 0x30
python
flat 函数是 pwntools 提供的一个非常实用的工具,用于将多个值打包成一个字节字符串(byte string),这在构造攻击载荷(payload)时非常有用
remote('域名或ip',端口号)指定服务器
变量名.sendlineafter('需要等待的字符串',发送的数据)等待出现指定字符串再发送数据
elf.sym['函数名']读取函数的地址
工具环境
pwntools
gdb & pwndbg
IDA
其他工具
pwntools
下载地址:https://github.com/Gallopsled/pwntools
python安装:pip install pwntools(python -m pip install pwntools)
linux安装:apt-get install python3-pwntools
pwntools基本用法
from pwn import *#导入pwntools所有函数
context(arch='i386',os='linux')#指定目标系统环境
#(可写为context.arch="i386", context.os = "linux")
r = remote('exploitme.example.com', 31337)#第一个参数表示目标ip或域名,第二个参数表示端口号
#以下代码用于发送
r.send(asm(shellcraft.sh()))
#以下代码表示,将控制器给用户
r.interactive()
#send和sendline的区别
'''
send('a')发送a
sendline('a')发送a\n
'''
#一下代码用于接收
recv(n)
recvuntil(par1)
'''
recv(n)表示这个进程接收n字节的数据,recvuntil(par1)表示接收到par1就停止。两个函数的返回值都为接收到的数据
'''
常用的代码有:
context.arch="amd64" 表示预设目标环境的架构为AMD64
context.log_level="debug",表示预设log的级别是debug,一般用于调试。debub级别表示打印与进程交互的信息,默认是不打印的。
context.endian="little",表示预设目标环境是小端序(大部分机器都采用小端序)。如果将payload的形式改为大端序,可以写为context.endian="big".
recvline()表示读取一行数据
pwndbg
pwndbg下载地址:https://github.com/pwndbg/pwndbg
pwndbg常用命令
命令 | 解释 | 示例 |
---|---|---|
r,c | run:从头开始运行 continue:继续运行 |
|
b<函数名> b*<地址> d |
设置断点到函数名 设置断点到某个特定地址 删除断点 |
b main b* 0x401000 d 1 |
i | Info:查看各类信息 | info b(查看断点信息) info proc mapping(查看内存分配) |
si,ni,finish | si:相当于其他调速器中的”Step Into(单步跟踪进入)“ ni:相当于其他调速器中的”Step Over“(单步跟踪) si/ni:针对的是汇编指令,而s/n针对的是源代码 finish:跳出当前函数,相当于Step Out |
|
x/<n/u/f> | 查看内存地址的值 n表示长度,u表示字节数 f表示输出格式,其中x为十六进制,s为字符串,i为指令,b表示单字节,h表示双字节,w表示四字节,g表示八字节 |
x/20wx 0x7fffffffe81d(20表示20个单元,x表示hex编码,w表示word类型,该语句表示从地址0x7ffffffffe81d以hex编码查看20个word类型数据) |
set | 设置寄存器和内存值 | set $eax = 0x004000000 set *0x8048a51=0x0 |
IDA
IDA快捷键
c code,将光标地址处的内容解析成代码
p public,在函数开始处使用p,从当前地址声明一个函数
d data,将光标地址处的代码解析成数据
u undefine,与p成对使用,取消函数的定义
x 查看光标地址的交叉引用
f5 查看汇编语言对应的c伪代码
其他工具
keypatch下载地址:https://github.com/keystone-engine/keypatch
one_gadget下载地址:https://github.com/david942j/one_gadget(linux下载:gem install one-gadget)
ROPgadget下载地址:https://github.com/JonathanSalwan/ROPgadget
栈溢出入门
栈的概念
1.栈满足先进后出原则
2.栈是向下生长的
3.压入数据是从右到左的
- THE END -
最后修改:2025年1月26日
非特殊说明,本博所有文章均为博主原创。
如若转载,请注明出处:https://guofun.top/ctf/pwn/10/
共有 0 条评论