基本ROP-ret2syscall
原理ret2syscall就是调用系统函数以达到getshell的目的在计算机中,系统调用是一种编程方式,计算机程序从该程序中向执行其的操作系统内核请求服务,这可能包括与硬件相关的服务(例如,访问硬盘驱动器),创建和执行新进程以及诸如进程调度之类的集成内核服务进行通信。系统调用提供了进程与操作系统之间的基本接口因此,我们要做的是:让程序调用execve(“/bin/sh”, NULL, NULl)函数即可拿到shell 攻击步骤调用此函数的具体步骤如下(32位): eax应该为0xb ebx应该指向/bin/sh的地址,其实执行sh的地址也可以 ecx应该为0 edx应该为0 执行int 0x80触发中断即可执行execve()获取shell系统在运行的时候会使用以上4个寄存器,所以上面的内容我们也可以写为int 0x80(eax, ebx, ecx, edx)。只要我们把对应获取shell的系统调用参数放到对应寄存器中,那么我们再执行int 0x80就可以执行对应的系统调用 而我们如何控制这些寄存器的值?在学习汇编函数时,最常用的就是...
基本ROP-ret2shellcode
原理ret2shellcode,即控制程序执行shellcode代码。shellcode指的是完成某个功能的汇编代码,常见的功能主要是获取目标系统的shell。一般来说,shellcode需要我们自己填充。这其实是另外一种典型的利用方法,即此时我们需要自己去填充一些可执行的代码 利用前提 程序存在溢出,并且还要能够控制返回地址 程序运行时,shellcode所在区域要拥有执行权限(NX保护关闭、bss段可执行) 操作系统还需要关闭ASLR(地址空间布局随机化)保护 攻击步骤 先使用cyclic测试出溢出点,构造初步的payload 确定程序中的溢出位,看是否可在bss段传入数据 使用GDB的vmmap查看进程的完整内存布局(一般用户提交的变量在bss段中) 先发送为shellcode的数据写入到bss段 将程序溢出到上一步用户提交变量的地址 示例 [!info] .bss段不可执行在现在较高版本的Ubuntu上,.bss段权限已经被设定为不可执行。所以shellcode在.bss段上的已经无法成功攻击了但是mprotect()函数可以动态修改.bss段属性,使得.bss段恢复...
基本ROP-ret2text
原理ret2text即控制程序执行程序本身已有的的代码(.text)。其实,这种攻击方法是一种笼统的描述。我们控制执行程序已有的代码的时候也可以控制程序执行好几段不相邻的程序已有的代码(也就是gadgets),这就是我们所要说的ROP。这时我们就需要知道对应返回代码的位置,当然程序可能开启了某些保护,我们需要想办法绕过这些保护 [!note]顾名思义,ret2text(return to text),也就是说我们的利用点在原文件中寻找相对应的危险代码即可(例如进程存在危险函数system(“/bin/sh”)或execv(“/bin/sh”)的片段,我们可以直接劫持返回地址到危险函数上,从而getshell),控制程序执行程序本身已有的代码(.text) 利用前提开启了NX,栈上无法直接写入shellcode当NX保护开启,就表示题目给了你system(“/bin.sh”),如果关闭,表示你需要自己构造shellcode 示例 [!info] 栈帧布局对齐GCC编译32位程序时,默认保持栈帧边界按照16字节对齐,所以有时在实际...
缓冲区溢出之栈溢出
栈溢出缓冲区溢出:简单来说,缓冲区溢出就是超长的数据向小缓冲区复制,导致数据超出了小缓冲区,致使缓冲区其他的数据遭到破坏而栈溢出是缓冲区溢出的一种,也是最常见的。只不过栈溢出发生在栈,堆溢出发生在堆 12345678910111213141516171819202122232425262728293031323334#include <stdio.h>#include <string.h>#define PASSWORD "12345"int test(char *password){ int ret_num; char buffer[8]; ret_num = strcmp(password, PASSWORD); strcpy(buffer, password); return ret_num;}int main(){ int flag = 0; char password[88]; while (1) { printf(&q...
pwntools语法
框架1from pwn import * #导入pwntools模块 1context(arch = 'i386', os = 'linux') #设置目标机的信息 123456r = remote('exploitme.example.com', 31337)'''用来建立一个远程连接,url或ip作为地址,然后指明端口这里也可以仅仅是用本地文件,调式时更方便'''r = process("./pwn") #pwn即为文件名,这使得改变远程和本地十分方便 1234567891011asm(shellcraft.sh())'''asm()函数接收一个字符串作为参数,得到汇编码的机器代码例如:>>> asm('mov eax, 0')'\xb8\x00\x00\x00\x00'shellcraft模块是shellcode的模块,包含一些生成shellc...
Linux动态链接中的PLT表和GOT表
引言文件在编译链接时,是不知道glibc动态库内printf的函数地址的,而只是写了一个“占位符”在汇编中,glibc动态库内printf的函数地址只有装载进内存时才能够知道 但是进程运行起来后,glibc动态库装载了,printf函数地址也确定了,那call指令是怎么重定位地址的呢? 一种简单的方法就是将指令中的“占位符”修改成printf函数的真实地址即可。但是随之又出现两个问题: 现代操作系统不允许修改代码段,只能修改数据段 如果函数是在一个动态库(.so)中,修改了代码段,那么它就无法做到系统内所有进程共享同一个动态库所以prinf函数的地址只能回写到数据段,而不是代码段,这样的回写其实叫做运行时重定位,与之相应的还有链接时重定位 编译与链接每个编译单元(通常是一个.cpp文件)都会经历编译和链接两个阶段 编译阶段是将.c源代码编译成汇编指令的中间文件,即.o中间文件。由于编译阶段无法知道printf函数的地址,所以call指令后会预先放一个占位符,然后用重定位项来描述:这个地址在链接时需要修正,它的修正值是根据printf函数地址(更确切应该说是符号,链接器眼中只有...
Linux ELF文件保护机制
Linux ELF文件的保护机制主要有四种:Canary、NX、PIE、RELRO 一、CanaryLinux Canary是一种用于检测缓冲区溢出漏洞的安全机制,它在函数返回值之前添加的一串随机数(不超过机器字长)(也叫做cookie),末位为/x00(提供了覆盖最后一字节输出泄露Canary的可能)。如果出现缓冲区溢出攻击,覆盖内容覆盖到Canary处,就会改变原本该处的数值。当程序执行到此处时,会检查Canary值是否跟开始的值一样,如果不一样,程序会崩溃,从而达到保护返回地址的目的。Canary的确切位置会因为系统不同和编译器而异,但通常存储在栈帧的底部,位于局部变量和函数的返回地址之间,以防止缓冲区溢出攻击。 二、NXNX即No-eXecute(不可执行)的意思,NX(DEP)的基本原理是将数据所在内存页标识为不可执行,当程序溢出成功转入shellcode时,程序会尝试在数据页面上执行指令,此时CPU就会抛出异常,而不是去执行恶意指令。 [!info]这里的“标识”,指的是内存页表项中的一个比特位。在x86架构中叫NX位;而ARM架构中叫XN 正常在栈溢出时通过跳转...
bss段、data段、text段、堆(heap)和栈(stack)
bss段 bss段(bss segment)通常是指用来存放程序中未初始化的全局变量的一块内存区域 bss是英文Block Started by Symbol的简称 bss段属于静态内存分配 [!info] 静态内存分配与动态内存分配内存的静态分配和动态分配的区别主要是两个: 时间不同。静态分配发生在程序编译和连接的时候。动态分配则发生在程序调入和执行的时候。 空间不同。堆都是动态分配的,没有静态分配的堆。栈有2种分配方式:静态分配和动态分配。静态分配是编译器完成的,比如局部变量的分配。动态分配由函数malloc进行分配。不过栈的动态分配和堆不同,他的动态分配是由编译器进行释放,无需我们手工实现。(堆需要手动释放内存) 对于一个进程的内存空间而言,可以在逻辑上分成3个部份:代码区,静态数据区和动态数据区。动态数据区一般就是“堆栈”。“栈(stack)”和“堆(heap)”是两种不同的动态数据区,栈是一种线性结构,堆是一种链式结构。进程的每个线程都有私有的“栈”,所以每个线程虽然代码一样,但本地变量的数据都是互不干扰。一个堆栈可以通过“基地址”和“栈顶”地址来描述。全局变量...
C函数调用过程原理及函数栈帧分析
在x86的计算机系统中,内存空间中的栈主要用于保存函数的参数,返回值,返回地址,本地变量等。一切的函数调用都要将不同的数据、地址压入或者弹出栈。因此,为了更好地理解函数的调用,我们需要先来看看栈是怎么工作的。 栈是什么?简单来说,栈是一种后进先出的数据结构。这种形式的数据结构正好满足我们调用函数的方式:父函数调用子函数,父函数在前,子函数在后;返回时,子函数先返回,父函数后返回。栈支持两种基本操作,push和pop。push将数据压入栈中,pop将栈中的数据弹出并存储到指定寄存器或者内存中。 两个重要的注意点: 栈的生长方向是从高地址到低地址的 pop操作后,栈中的数据并没有被清空,只是该数据我们无法直接访问 栈帧是什么栈帧,本质就是一种栈,只是这种栈专门用于保存函数调用过程中的各种信息(参数,返回地址,本地变量等)。栈帧有栈顶和栈底之分,其中栈顶的地址最低,栈底的地址最高,SP(栈指针)就是一直指向栈顶的。在x86-32bit中,我们用ebp指向栈底、用 esp指向栈顶。下面是一个栈帧的示意图: 一般来说,我们将ebp到esp之间区域作为栈帧。并不是整个栈空间...
滴水-PE
1. PE文件结构1.1 可执行文件可执行文件指的是可以由操作系统进行加载执行的文件 可执行文件结构: Windows平台:PE(Portable Executable)文件结构 Linux平台:ELF(Executable and Linking Format)文件结构 PE文件结构使用场景: 病毒与反病毒 外挂与反外挂 加壳与脱壳(保护与破解) 无源码修改功能、软件汉化等 1.2 如何识别PE文件 PE文件的特征(PE指纹)分别打开.exe、.dll、.sys等文件,观察特征前2个字节 不能仅仅通过文件的后缀名来认定PE文件 1.3 PE文件的整体结构 2. PE文件的两种状态2.1 主要结构体 DOS部分: IMAGE_DOS_HEADER结构:DOS MZ文件头,64 Byte DOS Stub:DOS块(IMAGE_DOS_HEADER结构的最后一个成员指向了PE头开始的位置,由此可以判断DOS块的大小) PE文件头: “PE”,0,0:PE文件头标志,4 Byte IMAGE_FILE_HEADER结构:PE文件表头,标准PE头,20 Byte IMA...
