Ctrip travel APP libctripenc.so analysis

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
Insert image description here

Java_ctrip_foundation_util_EncodeUtil_cd	00006B80	

Enter this function

Insert image description here
Switch to flowchart

Insert image description here
Insert image description here
Insert image description here
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

Insert image description here
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 IVand KEY, the specific details are not shown, and the finished product will be directly uploaded.

Insert image description here

Guess you like

Origin blog.csdn.net/super19911115/article/details/118255055