ROP学习

基本知识

Return Oriented Programming面向返回的编程。
通过找各种小片段gadget,去实现类似(最简单的)直接在栈上运行恶意代码的方法。

  1. 程序存在溢出
  2. 合适的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

  1. 找到libc中system的地址
  2. 找/bin/sh字符串地址

要注意的是32和64位系统差别:64位是把参数都放入rdi,rsi,rdx,rcx,r8,r9,然后第七个才会放入栈中。

如果直接有/bin/sh和system地址,就直接用

比如说32位放置的时候,要注意参数和system中间有4字节的返回地址。

system给plt地址也是可以的,gdb能看plt地址。

如果没有,就自己构建

  1. 通过任意一条libc函数第二次执行(第一次执行时got表无内容,第二次执行才能找到函数地址)(将payload返回地址设置为main函数即可循环)
  2. 然后通过该函数计算偏移量,因为动态库每次加载位置不一样,但是相对偏移是一样的
  3. 用同样的方法,计算出/bin/sh的偏移量。
  4. 然后就回到了上面的第一种方法,通过设置栈顶顺序实现调用system并且给其传参。

还是很巧妙的,通过强行调用puts@plt获得libc的偏移位置,再减去libc.so.6的基址(so.2好像是老GNU使用的),然后就顺利成章的和前面一样构造。

ret2dl

return to dl_runtime_resolve
该函数简易原型为:_dl_runtime_resolve(*link_map,reloc_index)

posted @ 2024-08-13 22:13  muyiGin  阅读(16)  评论(0编辑  收藏  举报