携程旅行APP libctripenc.so分析
本文着重分析响应报文的解密,通讯网关及封包、解包(ProcoltoHandle.java)不在本文范围内,有兴趣的可私下交流。
JAVA层 ctrip.foundation.util.EncodeUtil
static {
try {
System.loadLibrary("ctripenc");
} catch (Throwable th) {
if (!classVerify) {
th.printStackTrace();
System.loadLibrary("ctripenc");
}
}
}
public native byte[] cd(byte[] bArr, int i);
用IDA 打开lib/armeabi/libctripenc.so文件,切到 Exports
Java_ctrip_foundation_util_EncodeUtil_cd 00006B80
进入该函数
切换至流程图
从流程图中可看到其步骤如下:
j_checkOk --> j_ctrip_dec
进入 j_checkOk 后,通过F5 简单地看一下它的逻辑
int __fastcall checkOk(int a1)
{
int v1; // r4
int v2; // r5
int v3; // r0
int v4; // r6
int v5; // r0
int v6; // r8
int v7; // r6
int v8; // r0
int v9; // r1
v1 = a1;
++mCallCnt;
v2 = (*(int (__fastcall **)(int, const char *))(*(_DWORD *)a1 + 24))(a1, "ctrip/foundation/util/EncodeUtil");
v3 = (*(int (__fastcall **)(int))(*(_DWORD *)v1 + 912))(v1);
if ( !v2 )
return 0;
if ( v3 )
return 0;
v4 = (*(int (__fastcall **)(int, int, const char *, const char *))(*(_DWORD *)v1 + 452))(v1, v2, "a", "()I");
v5 = (*(int (__fastcall **)(int))(*(_DWORD *)v1 + 912))(v1);
if ( !v4 )
return 0;
if ( v5 )
return 0;
v6 = (*(int (__fastcall **)(int, int, int))(*(_DWORD *)v1 + 516))(v1, v2, v4);
v7 = (*(int (__fastcall **)(int, int, const char *, const char *))(*(_DWORD *)v1 + 452))(
v1,
v2,
"b",
"()Landroid/content/Context;");
v8 = (*(int (__fastcall **)(int))(*(_DWORD *)v1 + 912))(v1);
if ( !v7 || v8 )
return 0;
v9 = (*(int (__fastcall **)(int, int, int))(*(_DWORD *)v1 + 456))(v1, v2, v7);
return j_j_thirdApkCheck(v1, v9, v6 == 0);
}
通过伪代码很容易知道,是用来检测调用者身份的,因此,我们的目标可转向 j_ctrip_dec 上
进入 j_ctrip_dec
F5之后可以看到,接着进入 ctrip_dec 函数,内容如下
int __fastcall ctrip_dec(int a1, int a2, int a3, int a4)
{
int v4; // r10
int result; // r0
int v6; // r9
int v7; // r5
int v8; // r4
int v9; // r0
int v10; // r5
int v11; // [sp+0h] [bp-30h]
int v12; // [sp+4h] [bp-2Ch]
int v13; // [sp+8h] [bp-28h]
int v14; // [sp+Ch] [bp-24h]
int v15; // [sp+10h] [bp-20h]
v11 = a4;
v4 = a1;
if ( a2 << 28 )
{
perror("Error:Decrypt size should be xx*16");
result = _stack_chk_guard - v15;
if ( _stack_chk_guard == v15 )
result = -1;
}
else
{
v6 = a3;
v7 = a2;
v11 = 1359459520;
v12 = -1285381468;
v13 = -2126741968;
v14 = 1978844486;
v8 = j_c_malloc(a2, (int)&v15);
_aeabi_memcpy(v8, v4, v7);
v9 = j_ctrip_dec_internal(v8, v7, (int)&v11, 16);
v10 = j_pkcs7_unpadding(v8, v9, v6);
j_c_free(v8);
result = _stack_chk_guard - v15;
if ( _stack_chk_guard == v15 )
result = v10;
}
return result;
}
int __fastcall j_ctrip_dec_internal(int a1, int a2, int a3, int a4)
{
return ctrip_dec_internal(a1, a2, a3, a4);
}
int __fastcall ctrip_dec_internal(int a1, int a2, int a3, int a4)
{
int v4; // ST00_4
int v5; // r8
int v6; // r6
int v7; // r4
int v8; // r10
int v9; // r9
int v10; // r5
int v11; // r10
int v12; // r6
int result; // r0
int v14; // [sp+8h] [bp-28h]
int v15; // [sp+Ch] [bp-24h]
int v16; // [sp+10h] [bp-20h]
v4 = a4;
v5 = a1;
v6 = a4;
v7 = a3;
v8 = a2;
v9 = j_c_malloc(a4, a2);
_aeabi_memcpy(v9, v7, v6);
v15 = 0;
j_decrypt_two(v5, v8, v6, (int)&v15, v4);
v10 = v15;
v14 = 0;
j_encrypt_one(v15, v7, (int)&v14);
v11 = v8 - v6;
v12 = v14;
j_aes_cbc_enctypt(v5, v11, v14, 2);
c_free(v9);
c_free(v12);
c_free(v10);
result = _stack_chk_guard - v16;
if ( _stack_chk_guard == v16 )
result = v11;
return result;
}
int __fastcall standar_aes_cbc_enctypt(int a1, int a2, int a3, int a4, int a5, int a6)
{
int v6; // r5
signed int v7; // r4
signed int v8; // r10
int v9; // r11
int v10; // r6
int v11; // r8
int v12; // r9
int v13; // r4
int i; // r8
__int64 v15; // ST00_8
signed int v16; // r0
int result; // r0
int v18; // [sp+Ch] [bp-13Ch]
char v19; // [sp+10h] [bp-138h]
int v20; // [sp+128h] [bp-20h]
v18 = a4;
v6 = a1;
v7 = 0;
v8 = a2 + ((unsigned int)(a2 >> 31) >> 28);
v9 = a2 % 16;
v10 = 0;
if ( a2 % 16 > 0 )
v7 = 1;
v11 = a2 / 16;
if ( a6 == 1 )
{
j_aes_setkey_enc((int)&v19, a3, a5);
v10 = 1;
}
else if ( a6 == 2 )
{
j_aes_setkey_dec((int)&v19, a3, a5);
v10 = 0;
}
v12 = v7 + (v8 >> 4);
v13 = v11 + v7 - 1;
for ( i = 0; i < v12; ++i )
{
LODWORD(v15) = v6;
HIDWORD(v15) = v6;
j_aes_crypt_cbc((int)&v19, v10, 16, v18, v15);
v16 = 16;
if ( v13 == i )
v16 = v9;
v6 += v16;
}
result = _stack_chk_guard - v20;
if ( _stack_chk_guard == v20 )
result = 1;
return result;
}
通过以上函数,可得知解密算法是 AES/CBC/PKCS7Padding
扫描二维码关注公众号,回复:
17051250 查看本文章
根据密码学常识,需要获得 IV
以及 KEY
,具体细节不表,直接上成品