以下是菜鸟我对这几天做第五题的结题报告,水平有限敬请谅解,欢迎高手对我的补充。
过反调试后的伪代码:
len = strlen(inputfromjava);
v19 = sub_4A780018(&v38, 32, inputfromjava, len);
((void (__fastcall *)(int, char *))v12)("Bomb_Atlantis", &tempa);
((void (__fastcall *)(char *, char *))v13)(&tempa, &v38);
((void (__fastcall *)(char *, char *))v14)(&tempa, &tempb);
((void (__fastcall *)(char *, char *))v15)(&tempb, &tempc);
result = sub_4A76D650(&tempc, "0812a34d5f9eacdb062a23d35ffeacdb");
其中sub_4A780018函数是做base64解码
v12函数是将“Bomb_Atlantis”和另一个常量生成md5码
v13函数是进一步将值与上一步得到的md5值按字节异或
v14是一个复杂运算
v15是将字节码变成字符串字节码
sub_4A76D650将最终值与常量对比验证是否正确
以下分析仅对复杂运算v14:
j_j_j___aeabi_memset8(&BECF8198, 328608);
sub_4A77C9C0(&BECF8198, 328608);
sub_4A77D780(input, &v21, &BECF8198, 0);
sub_4A77D59C(&v21, &v16, &v17);
sub_4A77D3F4(&v21, &v18, &v19, 0);
sub_4A77D59C(&v21, &v20, &v17);
sub_4A77D780(&v21, output, &BECF8198, 1);
sub_4A77C9C0函数BECF8198内存初始化为常量值,这些值是固定的
sub_4A77D780(...,0)函数将input数组行列对换,随后用一个方法在BECF8198查表
sub_4A77D59C单向映射,映射关系和第几个字节有关
sub_4A77D780(...,1)函数是将v21数组行列对换,把最终结果放在output中。
以上这些函数都只是查表的过程。算法复杂度仅为256 * 16=4096。暴力搜索忽略不计。
最后来详细说一下sub_4A77D3F4这个函数:
sub_4A77D3F4(int input, int be90b3b8, int be92f3c8, 0)
{
sub_4A77D124()
i = 0;
do
{
v7 = (int)&v43;
j = 0;
do
{
v9 = v7;
k = 0;
do
{
v11 = be90b3b8 + (4 * input [k + 4 * j] | ((j << 12) + (i << 14) + (k << 10)));
v12 = 0;
v13 = v9;
do
{
*(_BYTE *)v13 = *(_BYTE *)(v11 - v12);
v13 += 16;
v4 = v12-- == -3;
}
while ( !v4 );
v9 += 4;
++k;
}
while ( k != 4 );
v7++;
++j;
}
while ( j != 3 );
sub_4A77D2EC(input, BE8FB128, i, be92f3c8);
sub_4A77D124()
i++;
}
while( i != 9 );
}
经过分析上面的循环是产生BE8FB128这个表:
input[0] -> BE8FB128[0],BE8FB128[10],BE8FB128[20],BE8FB128[30]
input[1] -> BE8FB128[4],BE8FB128[14],BE8FB128[24],BE8FB128[34]
input[2] -> BE8FB128[8],BE8FB128[18],BE8FB128[28],BE8FB128[38]
input[3] -> BE8FB128[c],BE8FB128[1c],BE8FB128[2c],BE8FB128[3c]
input[4] -> BE8FB128[1],BE8FB128[11],BE8FB128[21],BE8FB128[31]
input[5] -> BE8FB128[5],BE8FB128[15],BE8FB128[25],BE8FB128[35]
input[6] -> BE8FB128[9],BE8FB128[19],BE8FB128[29],BE8FB128[39]
input[7] -> BE8FB128[d],BE8FB128[1d],BE8FB128[2d],BE8FB128[3d]
input[8] -> BE8FB128[2],BE8FB128[12],BE8FB128[22],BE8FB128[32]
input[9] -> BE8FB128[6],BE8FB128[16],BE8FB128[26],BE8FB128[36]
input[a] -> BE8FB128[a],BE8FB128[1a],BE8FB128[2a],BE8FB128[3a]
input[b] -> BE8FB128[e],BE8FB128[1e],BE8FB128[2e],BE8FB128[3e]
input[c] -> BE8FB128[3],BE8FB128[13],BE8FB128[23],BE8FB128[33]
input[d] -> BE8FB128[7],BE8FB128[17],BE8FB128[27],BE8FB128[37]
input[e] -> BE8FB128[b],BE8FB128[1b],BE8FB128[2b],BE8FB128[3b]
input[f] -> BE8FB128[f],BE8FB128[1f],BE8FB128[2f],BE8FB128[3f]
sub_4A77D124()这个函数是循环左移的,前四个字节不动,第二四字节循环左移一位,第三四字节循环左移二位,第四四字节循环左移三位。
sub_4A77D2EC函数伪代码为:
sub_4A77D2EC(int input, int BE8FB128, int i, int be92f3c8)
{
v0 = 0x3000 * i + be92f3c8 + 0x200;
j = 0;
v2 = BE8FB128 + 2;
do
{
k = -2;
v1 = v0;
v3 = v2;
*(byte*)input = BE8FB12B[j * 4]
while ( k )
{
sub_4A77D250(input, *(byte*)v3, input[j], v1);
v1 -= 0x100;
--v3;
++k;
}
j++;
v0 += 0x300;
v2 += 4;
input++;
}
while(j != 16)
}
sub_4A77D250函数伪代码为:
sub_4A77D250(int input, char v3, int inputj, int v1)
{
int x,y;
sub_4A77D1CC(x,v3 >> 0x04, inputj >> 0x04, v1);
sub_4A77D1CC(y,v3 & 0xf, inputj & 0xf, v1 + 0x80);
*(byte*)input = x << 4 | y;
}
sub_4A77D1CC(int x,int v3, int v4, int v1)
{
byte y = v3 << 4 | v4;
if(y <= 0x7f)
x = v1[y] & 0xf;
else
x= v1[y & 0x7f] >> 4;
}
根据以上分析sub_4A77D3F4函数:
0 <-> 0,4,8,c
1 <-> 1,5,9,d
2 <-> 2,6,a,e
3 <-> 3,7,b,f
也就是说每一个字节跟四个字节有关。
从下到上逆向迭代,每一次需要暴力搜索2^32 * 4 = 2^34,总共9次。
暴力搜索sub_4A77D3F4为2^34 * 9 = 2^37。这样此函数存在暴力破解可能。
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课