结合asm可以可以得到最终的pyaload
from pwn import *context(os='linux',arch='amd64')shellcode = asm(shellcraft.sh())或者from pwn import *shellcode = asm(shellcraft.amd64.linux.sh())
elf = ELF('ropasaurusrex')rop = ROP(elf)rop.read(0, elf.bss(0x80))rop.dump()# ['0x0000:0x80482fc (read)',#'0x0004:0xdeadbeef',#'0x0008:0x0',#'0x000c:0x80496a8']str(rop)# '\xfc\x82\x04\x08\xef\xbe\xad\xde\x00\x00\x00\x00\xa8\x96\x04\x08'
rop.read(0, elf.bss(0x80))
实际相当于rop.call('read', (0,elf.bss(0x80)))
。通过多次添加函数调用,最后使用str将整个rop chain dump出来就可以了 。call(resolvable, arguments=())
: 添加一个调用 , resolvable可以是一个符号,也可以是一个int型地址 , 注意后面的参数必须是元组否则会报错,即使只有一个参数也要写成元组的形式(在后面加上一个逗号)
chain()
: 返回当前的字节序列,即payload
dump()
: 直观地展示出当前的rop chain
raw()
: 在rop chain
中加上一个整数或字符串
search(move=0, regs=None, order=’size’)
: 按特定条件搜索gadget
unresolve(value)
: 给出一个地址 , 反解析出符号
- GOT(Global Offset Table)全局偏移表 。存储导入变量的地址
- PLT(Procedure Linkage Table)程序链接表 。它有两个功能,要么在
.got.plt
节中拿到地址,并跳转 。要么当.got.plt
没有所需地址的时,触发「链接器」去找到所需地址,与常见导入的函数有关 , 如 read 等函数 。 - .got.plt,这个是 GOT 专门为 PLT 专门准备的节 。说白了,.got.plt 中的值是 GOT 的一部分 。它包含上述 PLT 表所需地址(已经找到的和需要去触发的),存储导入函数的地址
- .plt.got,与动态链接有关系 。
puts
这样的函数都是定义在glibc
动态库里的,只有当程序运行起来时才可以确定地址,而运行时重定位是无法修改.text
段的地址的,只能将puts
重定位到data
段,那么got
表怎么知道puts()
函数的真实地址呢,链接器会额外生成一小段代码,如下所示.text...// 调用printf的call指令call printf_stub...printf_stub:mov rax, [printf函数的储存地址] // 获取printf重定位之后的地址jmp rax // 跳过去执行printf函数.data...printf函数的储存地址,这里储存printf函数重定位后的地址
总体来说,动态链接每个函数需要两个东西:- 用来存放外部函数地址的数据段
- 用来获取数据段记录的外部函数地址的代码
文章插图
可执行文件里面保存的是 PLT 表的地址,对应 PLT 地址指向的是 GOT 的地址,GOT 表指向的就是 glibc 中的地址,那我们可以发现,在这里面想要通过 plt 表获取函数的地址,首先要保证 got 表已经获取了正确的地址,但是在一开始就进行所有函数的重定位是比较麻烦的 , 为此,linux 引入了延迟绑定机制
延迟绑定只有动态库函数在被调用时 , 才会地址解析和重定位工作,为此可以使用类似这样的代码来实现
//一开始没有重定位的时候将 printf@got 填成 lookup_printf 的地址void printf@plt(){address_good:jmp *printf@gotlookup_printf:调用重定位函数查找 printf 地址 , 并写到 printf@got goto address_good;//再返回去执行address_good}
说明一下这段代码工作流程,一开始,printf@got 是 lookup_printf 函数的地址 , 这个函数用来寻找 printf() 的地址,然后写入 printf@got,lookup_printf 执行完成后会返回到 address_good , 这样再 jmp 的话就可以直接跳到printf 来执行了也就是说这样的机制的话如果不知道 printf 的地址,就去找一下,知道的话就直接去 jmp 执行 printf 了
下面是一段
plt
表的示例Disassembly of section .plt:080482d0 <common@plt>: 80482d0: ff 35 04 a0 04 08pushl0x804a004 80482d6: ff 25 08 a0 04 08jmp*0x804a008跳转到_dl_runtime_resolve这个函数中查找运行时地址它是got表的第三项,所以可以看到该地址为08而puts对应的got表的地址为0c 80482dc: 00 00add%al,(%eax) ...080482e0 <puts@plt>: 80482e0: ff 25 0c a0 04 08jmp*0x804a00c从got表的第四项开始 80482e6: 68 00 00 00 00push$0x0这个 push进去的实际上就是在 got 表中的索引 80482eb: e9 e0 ff ff ffjmp80482d0 <_init+0x28>又跳到最上面的 公共 plt080482f0 <__libc_start_main@plt>: 80482f0: ff 25 10 a0 04 08jmp*0x804a010 80482f6: 68 08 00 00 00push$0x8每一个got表项对应的 push 的参数之间的间隔为8 80482fb: e9 d0 ff ff ffjmp80482d0 <_init+0x28>
推荐阅读
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 四十一 增删查改分页 Java开发学习----MyBatisPlus标准数据层开发
- 中 学习ASP.NET Core Blazor编程系列十——路由
- CC1,3,6回顾
- 图学习【参考资料2】-知识补充与node2vec代码注解
- 二十四 设计模式学习:Spring 中使用到的设计模式
- Java安全之CC3
- TensorFlow深度学习!构建神经网络预测股票价格!?
- JUC学习笔记——共享模型之管程
- Seata Server 1.5.2 源码学习
- 2022极端高温!机器学习如何预测森林火灾?? 万物AI