Ctrip旅行APP libctripenc.so分析

Ctrip旅行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 ファイルを開き、[エクスポート] に切り替えます。
ここに画像の説明を挿入します

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 を入力してください

ここに画像の説明を挿入します
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

暗号の常識によれば、IVとを取得する必要がありますKEYが、具体的な詳細は示されておらず、完成品が直接アップロードされます。

ここに画像の説明を挿入します

おすすめ

転載: blog.csdn.net/super19911115/article/details/118255055