OhNativeEnc
本题考查对 Android 原生加密函数的逆向分析。
和 Week1 的安卓一样寻找加密。

但是加密函数是 native 的,说明加密函数在 so 文件里。

.apk 后缀改成 .zip 打开,把 lib\arm64-v8a\libohnativeenc.so 解压出来,用 IDA 打开。
找到 Java_work_pangbai_ohnativeenc_FirstFragment_checkFlag 函数。
cpp
bool __fastcall Java_work_pangbai_ohnativeenc_FirstFragment_checkFlag(__int64 a1, __int64 a2, __int64 a3)
{
const char *src; // x19
unsigned int v4; // w8
unsigned int v5; // w10
unsigned int v6; // w9
unsigned int v7; // w11
unsigned int dest__1; // w12
unsigned int v9; // w13
unsigned int v10; // w14
unsigned int v11; // w15
int v12; // w16
unsigned int n0x1BF52; // w17
int v14; // w1
int v15; // w2
int v16; // w4
bool v17; // cf
int v18; // w5
int v19; // w1
int v20; // w1
unsigned __int64 n31; // x10
unsigned __int64 n0x1E; // x9
int v23; // w11
int v24; // w12
__int128 dest_; // [xsp+0h] [xbp-30h] BYREF
__int128 v27; // [xsp+10h] [xbp-20h]
__int64 v28; // [xsp+28h] [xbp-8h]
v28 = *(_QWORD *)(_ReadStatusReg(ARM64_SYSREG(3, 3, 13, 0, 2)) + 40);
src = (const char *)(*(__int64 (__fastcall **)(__int64, __int64, _QWORD))(*(_QWORD *)a1 + 1352LL))(a1, a3, 0LL);
__android_log_print(4, "native", "input:%s", src);
dest_ = 0u;
v27 = 0u;
strncpy((char *)&dest_, src, 0x20uLL);
v4 = v27;
v5 = DWORD1(v27);
v7 = DWORD2(v27);
v6 = HIDWORD(v27);
dest__1 = dest_;
v9 = DWORD1(dest_);
v11 = DWORD2(dest_);
v10 = HIDWORD(dest_);
v12 = -12;
n0x1BF52 = 0x1BF52;
do
{
v14 = (n0x1BF52 >> 2) & 3;
v15 = *(_DWORD *)&aThisisaxxteake[4 * v14];
v16 = *(_DWORD *)&aThisisaxxteake[4 * (v14 ^ 1)];
v17 = __CFADD__(v12++, 1);
dest__1 += (((4 * v9) ^ (v6 >> 5)) + ((v9 >> 3) ^ (16 * v6))) ^ ((v15 ^ v6) + (v9 ^ n0x1BF52));
v18 = *(_DWORD *)&aThisisaxxteake[4 * (v14 ^ 2)];
v9 += (((4 * v11) ^ (dest__1 >> 5)) + ((v11 >> 3) ^ (16 * dest__1))) ^ ((v16 ^ dest__1) + (v11 ^ n0x1BF52));
v19 = *(_DWORD *)&aThisisaxxteake[4 * (v14 ^ 3)];
v11 += (((4 * v10) ^ (v9 >> 5)) + ((v10 >> 3) ^ (16 * v9))) ^ ((v18 ^ v9) + (v10 ^ n0x1BF52));
v10 += (((4 * v4) ^ (v11 >> 5)) + ((v4 >> 3) ^ (16 * v11))) ^ ((v19 ^ v11) + (v4 ^ n0x1BF52));
v4 += (((4 * v5) ^ (v10 >> 5)) + ((v5 >> 3) ^ (16 * v10))) ^ ((v15 ^ v10) + (v5 ^ n0x1BF52));
v5 += (((4 * v7) ^ (v4 >> 5)) + ((v7 >> 3) ^ (16 * v4))) ^ ((v16 ^ v4) + (v7 ^ n0x1BF52));
v7 += (((4 * v6) ^ (v5 >> 5)) + ((v6 >> 3) ^ (16 * v5))) ^ ((v18 ^ v5) + (v6 ^ n0x1BF52));
v20 = (((4 * dest__1) ^ (v7 >> 5)) + ((dest__1 >> 3) ^ (16 * v7))) ^ ((v19 ^ v7) + (dest__1 ^ n0x1BF52));
n0x1BF52 += 114514;
v6 += v20;
}
while ( !v17 );
*(_QWORD *)&dest_ = __PAIR64__(v9, dest__1);
*((_QWORD *)&dest_ + 1) = __PAIR64__(v10, v11);
*(_QWORD *)&v27 = __PAIR64__(v5, v4);
*((_QWORD *)&v27 + 1) = __PAIR64__(v6, v7);
if ( (unsigned __int8)mm[0] != (unsigned __int8)dest__1 )
return 0LL;
n31 = 0LL;
do
{
n0x1E = n31;
if ( n31 == 31 )
break;
v23 = *((unsigned __int8 *)&dest_ + n31 + 1);
v24 = (unsigned __int8)mm[++n31];
}
while ( v23 == v24 );
return n0x1E > 0x1E;
}可以分析一下操作,mm 是密文,其实就是一个 flag 块加上 另一个 flag 的加密块 的循环,看 key 的内容也可以知道这是 xxtea 加密。
可以网上找个 xxtea 算法,把 delta 改为题目相同的值就行了。
c
#include <stdint.h>
#define DELTA 114514
#define MX (((z >> 5 ^ y << 2) + (y >> 3 ^ z << 4)) ^ ((sum ^ y) + (key[(p & 3) ^ e] ^ z)))
// 容易魔改
void btea(uint32_t *v, int n, uint32_t const key[4])
{
// v 为数据,n 为数据长度 (负时为解密),key 为密钥
uint32_t y, z, sum;
unsigned p, rounds, e;
if (n > 1)
/* Coding Part */
{
rounds = 6 + 52 / n;
sum = 0;
z = v[n - 1];
do
{
sum += DELTA;
e = (sum >> 2) & 3;
for (p = 0; p < n - 1; p++)
{
y = v[p + 1];
z = v[p] += MX;
}
y = v[0];
z = v[n - 1] += MX;
} while (--rounds);
}
else if (n < -1)
/* Decoding Part */
{
n = -n;
rounds = 6 + 52 / n;
sum = rounds * DELTA;
y = v[0];
do
{
e = (sum >> 2) & 3;
for (p = n - 1; p > 0; p--)
{
z = v[p - 1];
y = v[p] -= MX;
}
z = v[n - 1];
y = v[0] -= MX;
sum -= DELTA;
} while (--rounds);
}
}
int main(int argc, char **argv)
{
unsigned char key[16] = "ThisIsAXXteaKey";
unsigned char mm[] = {0xb6, 0x53, 0x6e, 0x4d, 0x77, 0x5d, 0x08, 0xd2, 0xfb, 0x2c, 0x63, 0x1e, 0xbb, 0x7b, 0x01, 0x9b, 0xf5, 0x04, 0x6a, 0xf4, 0x0e, 0x84, 0x27, 0x47, 0x64, 0xa1, 0xe4, 0xd9, 0xef, 0x12, 0x44, 0x37};
btea((uint32_t *)mm, -8, (uint32_t *)key);
puts(mm);
return 0;
}