知识杂项
- int mprotect(const void *start, size_t len, int prot);
- mprotect()函数把自start开始的、长度为len的内存区的保护属性修改为prot指定的值。
- int fflush(FILE *stream)
- fflush():会强迫将缓冲区内的数据写回参数stream 指定的文件中. 如果参数stream 为NULL,fflush()会将所有打开的文件数据更新。
- DEP:可帮助防止数据页当作代码执行,从而有效分离数据与代码。通常情况下,不执行默认堆和堆栈中的代码。硬件实施 DEP 检测从这些位置运行的代码,并在发现执行情况时引发异常。软件实施 DEP 可帮助阻止恶意代码利用 Windows 中的异常处理机制进行破坏。
- prot可以取以下几个值,并且可以用“|”将几个属性合起来使用:
1)PROT_READ:表示内存段内的内容可写;
2)PROT_WRITE:表示内存段内的内容可读;
3)PROT_EXEC:表示内存段中的内容可执行;
4)PROT_NONE:表示内存段中的内容根本没法访问。 - ASLR(Address space layout randomization):是一种针对缓冲区溢出的安全保护技术,通过对堆、栈、共享库映射等线性区布局的随机化,通过增加攻击者预测目的地址的难度,防止攻击者直接定位攻击代码位置,达到阻止溢出攻击的目的。据研究表明ASLR可以有效的降低缓冲区溢出攻击的成功率,如今Linux、FreeBSD、Windows等主流操作系统都已采用了该技术。
PLT表与GOT表
stub code:大概就是占坑的代码,桩代码给出的实现是临时性的/待编辑的。它使得程序在结构上能够符合标准,又能够使程序员可以暂时不编辑这段代码。
ROP技术
- 如果某一页内存没有可写(W)属性,我们就无法向里面写入代码,如果没有可执行(X)属性,写入到内存页中的shellcode就无法执行。
- 那么我们怎么看某个ELF文件中是否有RWX内存页呢?首先我们可以在静态分析和调试中使用IDA的快捷键Ctrl + S。
- 可以使用pwntools自带的checksec命令检查程序是否带有RWX段,但由于程序可能在运行中调用mprotect(), mmap()等函数动态修改或分配具有RWX属性的内存页,以上方法均可能存在
误差。 - 既然攻击者们能想到在RWX段内存页中写入shellcode并执行,防御者们也能想到,因此,一种名为NX位(NoeXecute bit)的技术出现了。这是一种在CPU上实现的安全技术,这个位将内存页以数据和指令两种方式进行了分类。被标记为数据页的内存页(如栈和堆)上的数据无法被当成指令执行,即没有X属性。由于该保护方式的使用,之前直接向内存中写入shellcode执行的方式显然失去了作用。因此,我们就需要学习一种著名的绕过技术——ROP(Return-Oriented Programming, 返回导向编程)
顾名思义,ROP就是使用返回指令ret连接代码的一种技术(同理还可以使用jmp系列指令和call指令,有时候也会对应地成为JOP/COP)。一个程序中必然会存在函数,而有函数就会有ret指令。我们知道,ret指令的本质是pop eip,即把当前栈顶的内容作为内存地址进行跳转。而ROP就是利用栈溢出在栈上布置一系列内存地址,每个内存地址对应一个gadget,即以ret/jmp/call等指令结尾的一小段汇编指令,通过一个接一个的跳转执行某个功能。由于这些汇编指令本来就存在于指令区,肯定可以执行,而我们在栈上写入的只是内存地址,属于数据,所以这种方式可以有效绕过NX保护。
内容来源
Linux中mprotect()的用法
Linux程序的常用保护
Markdown基本语法
GOT表和PLT表知识详解
什么是桩代码
i春秋月刊第六期——Linux pwn零基础入门