这题一开始拿到人看麻了(不会),写篇wp记录新题型
这么一大大大串的函数图,是经过OLLVM 的控制流平坦化混肴.
控制流平坦化(Control Flow Flattening)的基本思想主要是通过一个主分发器来控制程序基本块的执行流程,例如下图是正常的执行流程:
经过控制流平坦化后的执行流程就如下图:
混淆代码块之间的逻辑,将其之前的逻辑混肴成switch嵌套循环,增加分析难度。
下面我们需要使用 angr符号执行去除控制流平坦化
环境ubuntu20.4 defalt.py脚本 (之前配好过angr环境)
在defalt.py上加上第12行
查看main函数地址
python deflat.py -f attachment --addr 0x400620
如此便为成功。
ida打开生成文件
逻辑清楚很多 ,分析代码。
这里的条件横为0,不执行
mian结束的地方
idapython脚本删除这些代码
st = 0x0000000000400620 #main开始
end = 0x0000000000402144 #main结束
def patch_nop(start,end):
for i in range(start,end):
ida_bytes.patch_byte(i, 0x90) #修改指定地址处的指令 0x90是最简单的1字节nop
def next_instr(addr):
return addr+idc.get_item_size(addr) #获取指令或数据长度,这个函数的作用就是去往下一条指令
addr = st
while(addr<end):
next = next_instr(addr)
if "ds:dword_603054" in GetDisasm(addr): #GetDisasm(addr)得到addr的反汇编语句
while(True):
addr = next
next = next_instr(addr)
if "jnz" in GetDisasm(addr):
dest = idc.get_operand_value(addr, 0) #得到操作数,就是指令后的数
ida_bytes.patch_byte(addr, 0xe9) #0xe9 jmp后面的四个字节是偏移
ida_bytes.patch_byte(addr+5, 0x90) #nop第五个字节
offset = dest - (addr + 5) #调整为正确的偏移地址 也就是相对偏移地址 - 当前指令后的地址
ida_bytes.patch_dword(addr + 1, offset) #把地址赋值给jmp后
print("patch bcf: 0x%x"%addr)
addr = next
break
else:
addr = next
算法分析:
输入一个48字节的数据。
第一部分:将空格换成0
第二部分:每次读取八个字节,如果大于0,则乘以2。如果小于0就乘以2再异或一个数。
CRC算法。
secret = [0xBC8FF26D43536296, 0x520100780530EE16, 0x4DC0B5EA935F08EC,
0x342B90AFD853F450, 0x8B250EBCAA2C3681, 0x55759F81A2C68AE4]
key = 0xB0004B7679FA26B3
flag = ""
# 产生CRC32查表法所用的表
for s in secret:
for i in range(64):
sign = s & 1 #数乘以二,必为偶数,再异或上奇数,得奇数 所以最后一位为1的数还原前为负。
if sign == 1:
s ^= key
s //= 2
# 防止负值除2,溢出为正值
if sign == 1:
s |= 0x8000000000000000 #让数回到负数
j = 0
while j < 8:
flag += chr(s&0xFF) #&0xff可以将高的24位置为0,低8位保持原样。
s >>= 8
j += 1
print(flag)
flag{6ff29390-6c20-4c56-ba70-a95758e3d1f8}
参考
https://blog.youkuaiyun.com/liuxiaohuai_/article/details/114369681
https://blog.youkuaiyun.com/weixin_50166464/article/details/121635877?spm=1001.2014.3001.5501