携程旅行APP libctripenc.so分析

携程旅行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

根据密码学常识,需要获得 IV 以及 KEY ,具体细节不表,直接上成品

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/super19911115/article/details/118255055