ROP学习
基本知识
Return Oriented Programming面向返回的编程。
通过找各种小片段gadget,去实现类似(最简单的)直接在栈上运行恶意代码的方法。
- 程序存在溢出
- 合适的gadget
rop种类
ret2shellcode
最简单的,当NX关着的时候(也就是可执行栈)。直接把返回地址跳到栈上缓冲区buf(用gets写入的恶意代码)
ret2text
差不多,当NX开着的时候,如果text段里居然刚好有你想要的功能,就把返回地址跳到那里。
ret2syscall
还是很巧妙的,通过栈溢出将栈上面排序好想要赋给寄存器的值,然后找到pop_eax_ret之类的gadget,就能完成对应的功能。
(ROPgadget,ropper)
ropper
ropper -f 程序 --search "pop|ret"
如下图,通过寻找各种gadget,配合ret实现栈操作:
ret2libc
- 找到libc中system的地址
- 找/bin/sh字符串地址
要注意的是32和64位系统差别:64位是把参数都放入rdi,rsi,rdx,rcx,r8,r9,然后第七个才会放入栈中。
如果直接有/bin/sh和system地址,就直接用
比如说32位放置的时候,要注意参数和system中间有4字节的返回地址。
system给plt地址也是可以的,gdb能看plt地址。
如果没有,就自己构建
- 通过任意一条libc函数第二次执行(第一次执行时got表无内容,第二次执行才能找到函数地址)(将payload返回地址设置为main函数即可循环)
- 然后通过该函数计算偏移量,因为动态库每次加载位置不一样,但是相对偏移是一样的。
- 用同样的方法,计算出/bin/sh的偏移量。
- 然后就回到了上面的第一种方法,通过设置栈顶顺序实现调用system并且给其传参。
还是很巧妙的,通过强行调用puts@plt获得libc的偏移位置,再减去libc.so.6的基址(so.2好像是老GNU使用的),然后就顺利成章的和前面一样构造。
ret2dl
即return to dl_runtime_resolve。
该函数简易原型为:_dl_runtime_resolve(*link_map,reloc_index)
本文来自博客园,作者:muyiGin,转载请注明原文链接:https://www.cnblogs.com/muyiGin/p/18357808