PWN基础知识及基础栈溢出手法

本文详细介绍了栈溢出的概念、原理及其在x86和x64架构下的实现方法,包括return to libc技术、ROP(返回导向编程)以及GOT劫持。栈溢出涉及的主要寄存器、函数调用约定和危险函数也在文中进行了讲解,为理解安全漏洞和逆向工程提供了基础。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、pwntools常用函数

函数 用途
send(data) 发送数据(字符串形式发送)
sendline(data) 发送一行数据,默认在行尾加 \n(字符串形式发送)
recv(numb=1096,timeout=default) 接收指定字节数的数据
buf = p.recvuntil(“\n”, drop=True) 直到接收到\n为止,drop=True表示丢弃\n,buf为接收到的输出但不包括丢弃的\n
recvrepeat(timeout=default) 接收数据直到 EOF 或 timeout
recvall() 接收数据直到 EOF
recvline(keepends=True) 接收一行,可选择是否保留行尾的 \n
listen(端口) 开启一个本地的监听端口
remote(‘IP地址’, 端口) 与目标IP建立一个套接字管道与之远程交互(在线的)
interactive() 可同时读写管道,相当于回到 shell 模式进行交互,在取得 shell 之后调用
p8() p16() p32() p64() 把括号内数据打包成8位/16位/32位/64位的二进制数
u8() u16() u32() u64() 把括号内字符串解包成二进制数
process(‘文件路径’),p = process(argv=[‘./vuln’, payload]) 与本地文件建立一个交互通道,可传递参数
sendlineafter(“string”,payload) 接收到string后发送payload
close() 关闭交互的通道
ELF(‘文件路径’) 获取文件对象或者libc库对象
plt[‘函数名’] 获取函数在PLT表中的地址
got[‘函数名’] 获取函数在GOT表中的地址
symbols[‘函数名’]
或sym[‘函数名’]
获取函数plt地址,用在libc里面就是获取libc里的偏移地址
asm(“汇编指令”) 把汇编指令转换成对应的机器码,机器码是以字符串形式返回
bss(offset) 返回 .bss 段加上 offset 后的地址
asm(shellcraft.amd64.linux.sh(),arch=‘amd64’)(这里是指明x64环境,如果已经有context设置环境就直接写为asm(shellcraft.sh())) 生成shellcode,一般与asm进行联用,转为对应机器码
context(arch='amd64’或‘i386’,os=‘linux’,log_level=‘debug’) 设置环境
gdb.attach(p,‘b* main’) 调动gdb进行脚本调式

栈溢出

一、x86架构下的栈溢出

栈区:简单来说就是c语言中创建的局部变量(例如函数花括号里的变量)的存储位置。内存中的栈区指的是系统栈,由系统自动维护。

栈在程序加载进内存后就会出现

入栈:每个函数都有一个属于自己的栈帧空间,最先压入栈内的是函数的返回地址(用来返回到下一条指令),之后是函数的基地址、参数入栈。例如主调函数在调用函数a时,主调函数先存入自身栈帧的为返回地址、自身基地址、传入函数a的实参(如果有的话),然后替函数a创建一个新栈帧,在新栈帧中先压入函数a的返回地址(为了函数调用结束时,可以返回到下一条指令继续程序),再压入主调函数的基地址(函数调用结束时,返回到主调函数的基地址)以及函数a中的局部变量。此时是高地址往低地址生长(主调函数在的位置为高地址)

退栈:而函数调用结束,则与调用时相反,先从被调函数的局部变量开始直接弹出栈,栈顶指向存储着被调函数基地址(存储主调函数基地址),被调函数基地址被弹出后,释放出主调函数的基地址给ebp,然后将返回地址弹出交给eip去执行,之后便返回到下一条指令的地址(这里举例为主调函数直接调用一个函数,如果层层嵌套,则先会返回到上一个主调函数的栈帧),继续程序的运行,ebp指向此刻的主调函数的基地址

系统中当前正在运行的函数总是在栈顶

与函数状态相关的主要寄存器:esp,ebp,eip:

(1)esp:栈指针寄存器,存放一个指针,该指针永远指向系统栈正在运行的栈帧的栈顶(存储函数调用栈的栈顶地址),在压栈和退栈时发生变化

(2)ebp:基地址指针寄存器,该指针永远指向系统栈正在运行的栈帧的底部,在函数运行时不变,可以用来索引确定函数参数或局部变量的位置

(3)在esp和ebp之间的内存空间为当前栈帧

(4)eip:用来存储即将执行的程序指令的地址,cpu 依照 eip 的存储内容读取指令并执行,eip 随之指向相邻的下一条指令

因此,所谓的栈溢出漏洞,就是利用一些危险函数进行读取远超一个变量所需的数值,覆盖到相邻栈中的数值,从而修改相邻栈中的变量的值,往这些修改的值中注入我们所需要的跳转的例如shellcode,函数地址等,使程序崩坏或是让程序执行一些我们想要执行的程序,达到破坏的目的

x86下的CPU包含的8个四字节的通用寄存器:

在这里插入图片描述

寄存器使用约定:寄存器eax、edx和ecx为主调函数保存寄存器(caller-saved registers),当函数调用时,若主调函数希望保持这些寄存器的值,则必须在调用前显式地将其保存在栈中;被调函数可以覆盖这些寄存器,而不会破坏主调函数所需的数据。寄存器ebx、esi和edi为被调函数保存寄存器(callee-saved registers),即被调函数在覆盖这些寄存器的值时,必须先将寄存器原值压入栈中保存起来,并在函数返回前从栈中恢复其原值&#x

### PWN 栈溢出漏洞利用教程 #### 概述 栈溢出是一种常见的软件安全漏洞,通常发生在程序试图将过多的数据放入堆栈上的缓冲区时。当这种情况发生时,额外的数据会覆盖相邻内存区域的内容,可能导致程序行为异常甚至允许攻击者执行恶意代码。 #### 原理分析 在 C 或其他低级编程语言中,如果开发者使用了像 `read`、`gets` 这样的危险函数来处理用户输入而未做适当长度验证,则可能引发此类问题[^2]。具体来说: - **栈帧结构**:每当调用一个新的子程序(即函数),都会创建一个新层——称为“栈帧”。这包含了局部变量以及返回地址等重要信息。 - **溢出机制**:一旦超出分配给某个数组或其他类型的存储空间范围之外写入数据就会触发溢出事件。此时不仅会影响该对象本身还会影响到其后的元素直至最终篡改到当前活动线程的指令指针寄存器EIP/RIP (Extended Instruction Pointer/Register),进而改变应用程序正常逻辑走向。 #### 利用方法 为了成功实施基于栈溢出安全攻击并获取远程shell访问权限或者其他形式的有效载荷投放能力,可以采取如下策略之一或组合应用多个技术要点: ##### 1. 覆盖 Return Address 通过精心设计输入串使其恰好能够填充目标缓冲区直到触及ret addr位置处,并随后附加一条指向所需操作序列开头部分的新路径指示符完成转向控制转移过程[^4]。 ##### 2. ROP(Return-Oriented Programming) 考虑到现代操作系统普遍启用了诸如NX(non-executable stack)之类防御措施阻止直接注入可执机器码片段的做法变得不再可行;因此引入了一种间接方式—ROP链表构建法。此办法依赖于收集现有合法二进制映像内部已存在短小精悍的功能模块(gadgets),再按照一定顺序串联起来形成连贯完整的命令集达成预期目的[^3]。 ##### 3. 使用工具辅助开发 对于初学者而言掌握上述理论固然重要但也存在一定难度门槛,在实践中往往借助专门为此类场景定制化打造出来的框架库简化工作量提高效率。比如Python下的[pwntools](https://github.com/Gallopsled/pwntools/)就是一个非常流行的选择,它支持连接远端服务发送自定义payload并与之交互等功能特性[^5]。 ```python from pwn import * r = remote('example.com', port_number) # 构造Payload buffer_size = 0x80 padding = b'a' * buffer_size fake_rbp = b'b' * 8 return_address = p64(target_function_addr) payload = padding + fake_rbp + return_address # 发送Payload r.sendline(payload) # 开始交互模式等待响应 r.interactive() ``` #### 安全建议 为了避免成为潜在受害方,请务必遵循最佳实践编码指南以减少风险暴露面: - 尽量选用高级别的抽象层次编写业务逻辑; - 对所有外部接口传来的参数严格校验合法性边界; - 启用编译期优化选项如-fstack-protector-strong增强防护等级; - 及时更新补丁修复官方发布的各类已知缺陷报告。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ShouCheng3

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值