题目名为混淆和编码,有点恐怖(:з」∠)
打开main函数,发现仅对输入进行了fencode和encode两次处理后就与字符串比较,很简单明了
fencode的流程如下:
整体扫一下,是通过对code这个变量的比较和赋值来控制程序流程的,看起来有点像VM
不过再看一下程序流程图就清楚了:
这不就是控制流平坦化嘛
粗略扫了一遍,核心部分仅有以下两句
v10 += a1[4 * v12 + v9] * m[4 * v11 + v9];
a2[v6] = (char)v10 % 127;
显然是通过3个变量来控制两个数组相乘,然后累加的和模127作为一个输出
下标的变化方法可以人工跟随控制流走一遍,反正也不长
基本上就是
for(v12=0;v12<6;v12++)
for(v11=0;v11<4;v11++)
a2[i] = v10%127
v10 = 0
for(v9=0;v9<4;v9++)
v10 += xxx
敏锐的话一眼就能看出来是4x6的矩阵与4x4的矩阵相乘
m矩阵扒下来以后求逆矩阵即可
另一个encode函数也被控制流平坦化混淆了,但是从核心函数上一下就能看出来是b64的算法
注意到AlphaTable被改了,扒下来和源码结合解码
脚本如下:
import numpy
table = "FeVYKw6a0lDIOsnZQ5EAf2MvjS1GUiLWPTtH4JqRgu3dbC8hrcNo9/mxzpXBky7+"
s = "lUFBuT7hADvItXEGn7KgTEjqw8U5VQUq"
def decode(base64_str):
base64_bytes = ['{:0>6}'.format(str(bin(table.index(s))).replace('0b', '')) for s in base64_str]
resp = []#bytearray()
nums = len(base64_bytes) // 4
remain = len(base64_bytes) % 4
integral_part = base64_bytes[0:4 * nums]
while integral_part:
# 取4个6位base64字符,作为3个字节
tmp_unit = ''.join(integral_part[0:4])
tmp_unit = [int(tmp_unit[x: x + 8], 2) for x in [0, 8, 16]]
for i in tmp_unit:
resp.append(i)
integral_part = integral_part[4:]
if remain:
remain_part = ''.join(base64_bytes[nums * 4:])
tmp_unit = [int(remain_part[i * 8:(i + 1) * 8], 2) for i in range(remain - 1)]
for i in tmp_unit:
resp.append(i)
return resp
n = decode(s)
print(n)
m = [2, 2, 4, -5, 1, 1, 3, -3, -1, -2, -3, 4, -1, 0, -2, 2]
a = numpy.mat([n[4*i:4*i+4] for i in range(6)])
b = numpy.mat([m[4*i:4*i+4] for i in range(4)])
b = b.T.I
flag = (a*b).A
print(flag)
for i in range(24):
print(chr((int(flag[i//4][i%4]+0.5)%256)), end='')
这个混淆由于原程序较为简单因此没有起什么作用
大概搜索了一下,控制流平坦化除了动态调试中的脚本来打log以外就是符号执行来跑出程序流了
实际上它还是有些类似VMP的,因此可以通过log或者模拟器来进行一定程度上的求解
符号执行则是通过引擎来对控制code进行遍历找出所有路径,再结合块的恢复来还原代码
明天尝试一下上述两种方法反混淆