Ctrip travel APP libctripenc.so analysis
This article focuses on analyzing the decryption of response messages. The communication gateway and packetization and unpacking (ProcoltoHandle.java) are not within the scope of this article. Those who are interested can communicate privately.
JAVA layerctrip.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);
Open the lib/armeabi/libctripenc.so file with IDA and switch to Exports
Java_ctrip_foundation_util_EncodeUtil_cd 00006B80
Enter this function
Switch to flowchart
The steps can be seen from the flow chart as follows:
j_checkOk --> j_ctrip_dec
After entering j_checkOk, simply look at its logic through 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);
}
It is easy to know from the pseudo code that it is used to detect the identity of the caller. Therefore, our goal can be turned to j_ctrip_dec
Enter j_ctrip_dec
You can see it after F5, and then enter the ctrip_dec function, the content is as follows
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;
}
Through the above function, we can know that the decryption algorithm isAES/CBC/PKCS7Padding
According to cryptography common sense, it is necessary to obtain IV
and KEY
, the specific details are not shown, and the finished product will be directly uploaded.