CTF逆向-[RoarCTF2019]polyre-WP_控制流扁平化去混淆idcpy去指令
来源:BUUCTF在线评测/
内容:无
附件:百度网盘 请输入提取码 提取码:nyty
答案:flag{6ff29390-6c20-4c56-ba70-a95758e3d1f8}
总体思路
使用deflat.py对程序扁平化处理。
使用ida的python idc工具对多余指令去除。
检查算法发现是crc64,按其流程逆运算
详细步骤
-
检查文件信息
-
打开程序发现控制流特别大,可能是进行了混淆
使用deflat.py(见附件),在ida中查看main方法的地址为0x400620'
python ./deflat.py 1 0x4006200
-
编写idc脚本,去除多余的永真分支
idc是一个ida中非常强大的工具集,可以通过使用
everything
或者utools
搜索idc.py,查看一下它实现了哪些可调用的方法。学习掌握它。
st = 0x400620 end = 0x401f54 def patch_nop(start, end): for i in range(start, end): idc.patch_byte(i, 0x90) # 修改指定地址处的指令 0x90是最简单的1字节nop def next_instr(addr): return addr + idc.get_item_size(addr) # ItemSize获取指令或数据长度,这个函数的作用就是去往下一条指令 addr = st while(addr < end): next = next_instr(addr) # idc.get_disasm(addr)得到addr的反汇编语句 if "ds:dword_603054" in idc.get_disasm(addr): while(True): addr = next next = next_instr(addr) if "jnz" in idc.get_disasm(addr): dest = idc.get_operand_value(addr, 0) # 得到操作数,就是指令后的数 idc.patch_byte(addr, 0xe9) idc.patch_byte(addr+5, 0x90) offset = dest - (addr + 5) idc.patch_dword(addr + 1, offset) print("patch bcf: 0x%x" % addr) addr = next break else: addr = next
-
检查加密算法为简单加密
在比对的g_key中按shift+e
复制值,得到解密脚本
import struct g_key = '966253436DF28FBC16EE300578000152EC085F93EAB5C04D50F453D8AF902B3481362CAABC0E258BE48AC6A2819F7555B326FA79764B00' g_key = bytearray.fromhex(g_key) single_len = 8 g_output = [g_key[x:x+single_len] for x in range(0, 6*single_len, single_len)] g_output = [struct.unpack('<Q', x)[0] for x in g_output] # 内层循环 def decode_k(v): is_negative = v & 1 # 判断当前值是否为负数 if is_negative: # 如果是负数,说明之前也是负数 v ^= 0xB0004B7679FA26B3 v >>= 1 # 右移一位表示除以2 if is_negative: # 防止负数除了以后变成正数 v |= 0x8000000000000000 return v # 外层循环 def decode_j(v): for k in range(64): v = decode_k(v) return v r = [decode_j(x) for x in g_output] flag = [struct.pack('<Q', x) for x in r] flag = [x.decode() for x in flag] print(''.join(flag)) // flag{6ff29390-6c20-4c56-ba70-a95758e3d1f8}
参考文档
-
struct.unpack用法
<Q
表示按小端取unsign long long -
在
unsign long long
中,因为总长度是8位且无符号,所以0x8000000000000000
是最小的负数,0x7fffffffffffffff
是最大的正数。
更多CTF逆向题通用性做法和常用工具下载参考该博文内容:CTF逆向Reverse题的玩法