用python的llvmlite库实现了一个brainfuck的解释器。通过runtime.so的动态库中的ptrBoundChk做了内存边界检查,可读写的范围被限定在了[DATA+0x10, DATA+0X3010]的范围。所以解题的关键在于如何绕过边界检查。
先来看一下程序的几个关键函数:bfProgram用于将brainfuck语言转换成shortended_code的形式,就是一系列(state, imm)的二元组。codegen函数用于将上述的二元组转换成为llvm的IR,compile将IR转换成为x86的机器码。execute自然就是用于执行机器码。
这里的重点是在生成IR的过程中为了提高代码的执行效率引入了白名单机制,比赛过程中意识到了这里应该就是问题点,但是没有想到如何绕过边界检查,赛后看到别人的脚本才明白。在codegen函数里面有个递归处理的机制,如果处理的是单个代码块就直接根据二元组生成IR,如果涉及多个代码块就递归处理,这里把[]包裹的语句视作一个代码块。
在处理子代码块的递归调用时候是这样的:
headb = self.head.codegen(module)br1b = self.br1.codegen(module, (0, 0))br2b = self.br2.codegen(module, (0, 0))
生成移位操作和增减值操作的IR代码:
for op, imm in self.shortened_code:if op == 0:continueelif op == 1: # inc/dec ptrif imm != 0:ori = builder.ptrtoint(builder.load(dptr_ptr), i64)incr = llvmIR.Const
Codegate CTF 2020 PreliminaryChallenge : SimpleMachineDescription :(fixed-point challenge)Classic Check Flag Challenge MachineDOWNLOAD :http://ctf.codegate.org/099ef54feeff0c4e7c2e4c7dfd7deb6e/116ea16dbeabe08d1fe8891a27d0f16bpoint : 333 (80 team solved)
from pwn import *stage1 = [0xb0bd, 0xbabc, 0xbeb9, 0xbaac, 0xcfce, 0xcfce]stage2 = [0xf974, 0x2b9d, 0x4caf, 0xbee1, 0xfc0d, 0x6e48, 0xe03c, 0xd322, 0x1979, 0x36d6, 0x40e8, 0xcbf7]val = 0xdeadflag = ''for i in stage1:flag += p16((0x10000 - i))next = lambda x:x ^ ((x << 1) & 0xffff)for i in stage2:val = next(val)flag += p16((0x10000 - i) ^ val)# CODEGATE2020{ezpz_but_1t_1s_pr3t3xt}print flag
Codegate CTF 2020 PreliminaryChallenge : HalffeedDescription :nc 110.10.147.44 7777DOWNLOAD :http://ctf.codegate.org/099ef54feeff0c4e7c2e4c7dfd7deb6e/9a7f846af14e09f6b32cff3a648b80f5point : 670 (43 team solved)
mixFeed 算法 Nonce 误用攻击
伪造AAAAAAAAAAAAAAAA;cat flag;AAAAAA的密文和认证码:
'\x00' * 16、'A' * 16 + '\x00' * 16、'B' * 16 + '\x00' * 16,取密文最后16字节。t2 , _ = feed_plus(T1, ';cat flag;AAAAAA')"B" * 16 + xor(T1_[:8], t2[:8]) + t2[8:],取认证码。forge_ciphertext = xor('AAAAAAAAAAAAAAAA;cat flag;AAAAAA', T0 + T1)ENIGMA
找规律,一个字符对应一个字母,最后flag是
CODEGATE2020{HACKERS ARE NOT BORN ONLY IT IS MADE}