1. 代码使用的JNI接口,端口开放是在so文件中,这里分析一下arm中的so文件
其接口:
IDA:Java_com_example_crack0_MainActivity_init
F5,找到加密函数xxx
v13 = _stack_chk_guard;
v0 = socket(2, 1, 0);
if ( v0 == -1 )
exit(1);
memset(&s, 0, 0x10u);
s = 2;
v6 = -28641;
v7 = inet_addr("127.0.0.1");
bind(v0, (const struct sockaddr *)&s, 0x10u);
listen(v0, 1);
while ( 1 )
{
memset(&v12, 0, 0x64u);
v1 = accept(v0, 0, 0);
v2 = v1;
if ( v1 < 0 )
goto LABEL_8;
v3 = read(v1, &v12, 0x64u);
if ( v3 >= 0
&& (v8 = 19088743,
v9 = -1985229329,
v10 = -19088744,
v11 = 1985229328,
n = v3,
xxx(&v12, &n, (int)&v8), 加密函数
write(v2, &v12, n) >= 0) )
{
close(v2);
sleep(3u);
}
else
{
v1 = v2;
LABEL_8:
close(v1);
}
}
}
分析上下文,调用xxx函数时,初始化了4个Int数,可能是作为key
函数的参数大概是xxx(缓冲区,大小,密钥)
{
_BYTE *v3; // r6@1
int v4; // r7@1
_BYTE *i; // r3@1
unsigned int v6; // r5@4
unsigned int v7; // r4@4
int v8; // r0@5
int result; // r0@5
v4 = a3;
for ( i = a1; (unsigned int)(i - a1) < *a2; ++i )
*i = ~*i; 循环取反
v6 = 0;
v7 = ((unsigned int)(*a2 + 7) >> 3) + 1;
*(_DWORD *)&a1[8 * v7 - 4] = a2;
*a2 = 8 * v7;
do
{
v8 = (int)&v3[8 * v6++];
result = xxxx(v8, v4); 根据key数组加密数据
}
while ( v6 < v7 );
return result;
}
函数xxx内部,先循环异或缓冲区,之后再通过密钥数组循环加密缓冲区,在函数ecode中
原名xxxx函数中
函数内部,就是进行循环异或,循环退出条件:0x-957401312
一次加密 8字节。
{
int v2; // r3@1
unsigned int v3; // r4@1
unsigned int v4; // r2@1
v3 = *(_DWORD *)result;
v4 = *(_DWORD *)(result + 4);
do
{
v2 -= 1640531527;
v3 += (v4 + v2) ^ (*(_DWORD *)a2 + 16 * v4) ^ (*(_DWORD *)(a2 + 4) + (v4 >> 5));
v4 += (v3 + v2) ^ (*(_DWORD *)(a2 + 8) + 16 * v3) ^ (*(_DWORD *)(a2 + 12) + (v3 >> 5));
}
while ( v2 != -957401312 );
*(_DWORD *)result = v3;
*(_DWORD *)(result + 4) = v4;
return result;
}
因为是异或,可以逆推。
// 分组解密函数 循环异或 |