拿到题目先用jadx查看主函数.
我们可以发现验证输入的地方主要是在checkFlag的地方。然而在apk的源码中并没有发现相关代码。因此猜测在.so文件中。
可以看到这里的确加载了一个.so文件。然后我们通过jeb提取出.so文件,拖入ida进行分析。
在左边的窗口中发现了,验证的函数。直接f5查看伪代码。
可以看到最后是跟unk_497C进行比较,判断是否正确。但是前面经过了三个函数的处理。点进去分析。
发现了函数中,出现好多次256,猜测是某种加密算法。通过搜索引擎得知。该加密为rc4加密。
此函数为rc4加密中的初始化。我们跟进下一个函数看一下。
a2是我们输入的字符串,可以看到这里是将输入的字符进行一个rc4的加密。我们在跟进第三个函数看下。
这里是将我们输入的值进行rc4加密后,在进行一个异或,最终再跟unk_497C进行比较。那么此时就有了一个解题的思路,因为是逆向分析,所以流程图如下:
#include
#include
#include
#include
using namespace std;
unsigned int enc[] = {
0xA3,0x1A ,0xE3 ,0x69 ,0x2F ,0xBB ,0x1A ,0x84 ,0x65 ,0xC2 ,0xAD ,0xAD ,0x9E ,0x96 ,0x05 ,0x02 ,0x1F ,0x8E ,0x36 ,0x4F ,0xE1 ,0xEB
,0xAF ,0xF0 ,0xEA ,0xC4 ,0xA8 ,0x2D ,0x42 ,0xC7 ,0x6E ,0x3F ,0xB0 ,0xD3 ,0xCC ,0x78 ,0xF9 ,0x98 ,0x3F };
string key = "123456789";
unsigned char S[256];
unsigned char T[256];
void rc4_init()
{
for (int i = 0; i != 256; i++)
{
S[i] = i;
T[i] = key[i % 8];
}
int v9 = 0;
for (int i = 0; i != 256; i++)
{
int middle = S[i];
v9 = (middle + v9 + T[i]) % 256;
S[i] = S[v9];
S[v9] = middle;
}
}
void rc4_encrpto()
{
int count = 39;
int i = 0;
int v4 = 0;
int v3 = 0; int v5 = 0;
int index = 0;
while (count)
{
--count;
v4 = (v4 + 1) % 256;
v5 = S[v4];
v3 = (v3 + S[v4]) % 256;
S[v4] = S[v3];
S[v3] = v5;
enc[index++] ^= S[(v5 + S[v4]) % 256];
}
}
int main()
{
int i;
//a2为flag长度
int a2 = 39;
/*
for ( j = 0; j < a2; j += a4 )
{
for ( k = 0; (a4 & ~(a4 >> 31)) != k && j + k < a2; ++k )
result[k] ^= a3[k];
result += a4;
}
下面的与这个等价
*/
for (i = 0; i < a2; i++) {
enc[i] ^= key[i % 8];
}
/*
for ( i = 0; i < a2; i += 3 )
{
v5 = &result[i];
v6 = result[i + 2];
v7 = result[i + 1];
v8 = result[i] ^ v6;
result[i] = v8;
v5[2] = v6 ^ v7;
v5[1] = v7 ^ v8;
}
下面的与这个等价
*/
for (i = 0; i < a2; i += 3) {
enc[i + 1] = enc[i + 1] ^ enc[i];
enc[i + 2] = enc[i + 2] ^ enc[i + 1];
enc[i] = enc[i + 2] ^ enc[i];
}
char v7[256];
rc4_init();
rc4_encrpto();
for (i = 0; i < 39; i++) {
cout << char(enc[i]);
}
cout << endl;
return 0;
}