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

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

一、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个四字节的通用寄存器:

在这里插入图片描述

在网络安全领域,PWN 技术涵盖多方面内容,在 Windows 平台上,其基础知识包含以下要点: ### 内存管理 Windows 采用虚拟内存管理机制,每个进程都有独立的虚拟地址空间。理解虚拟地址和物理地址的映射关系,以及内存分页、堆和栈的布局是基础。例如,栈通常用于存储函数调用信息和局部变量,而堆则用于动态内存分配。掌握 Windows 的内存保护机制,如数据执行保护(DEP)、地址空间布局随机化(ASLR)等,这些机制会增加 PWN 攻击的难度。例如,ASLR 会随机化程序加载的基地址,使得攻击者难以预测关键函数和变量的地址 [^1]。 ### 漏洞类型 常见的 Windows 平台漏洞包括缓冲区溢出、格式化字符串漏洞、整数溢出等。缓冲区溢出是指当程序向缓冲区写入的数据超过其容量时,会覆盖相邻的内存区域,可能导致程序崩溃或执行恶意代码。格式化字符串漏洞则是由于程序错误地处理格式化字符串参数,攻击者可以利用该漏洞读取或修改内存中的数据 [^1]。 ### 调试工具 熟练使用 Windows 平台的调试工具,如 WinDbg、OllyDbg 等。WinDbg 是微软官方的强大调试器,可用于分析系统级问题和调试恶意软件。OllyDbg 则更适合用于调试用户模式下的程序,它提供了直观的界面和丰富的调试功能,如反汇编、内存查看、断点设置等 [^1]。 ### 利用技术 ROP(Return Oriented Programming)是 Windows 平台上常用的利用技术之一。它通过在程序的现有代码中寻找一系列的指令片段(gadgets),并将这些片段拼接起来,形成一段新的代码逻辑,从而绕过内存保护机制。例如,攻击者可以利用 ROP 链调用系统函数,实现执行任意代码的目的 [^1]。 ### 示例代码 以下是一个简单的 Windows 平台 PWN 示例代码(仅作概念演示,实际环境可能需要更多调整): ```python from pwn import * # 假设这是一个本地程序 io = process("vulnerable_program.exe") # 找到缓冲区溢出的偏移量 # 这里省略了具体的查找过程 offset = 100 # 找到目标函数的地址 target_addr = 0x12345678 # 构造 payload payload = b'A' * offset + p32(target_addr) # 发送 payload io.sendline(payload) # 打开交互页面 io.interactive() ```
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

ShouCheng3

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

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

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

打赏作者

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

抵扣说明:

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

余额充值