首页
论坛
课程
招聘
[原创]【脱壳一】某壳分析+修复
2018-5-2 17:50 10695

[原创]【脱壳一】某壳分析+修复

2018-5-2 17:50
10695

声明

仅限技术讨论,不得用于非法途径,后果自负。
分析中有什么错误欢迎大家指出

Java层分析

java层简单分析下流程,重点放在so文件分析
加固效果主要把类方法抽取(其实并没有抽取,还是在dex文件中,只是修改了accessFlags和codeoff)

通过查看AndroidManifest文件application被修改成壳入口的文件(此壳加固的原apk必须自己声明Application文件,否则会加固失败,加固网站也不会提示,只是在加固apk中有文本提示,感觉用户体验不是很好)

这里可以根据壳入口点自己跟着走一遍,我只说下大体流程吧

当执行完application就该执行AndroidManifest声明的activity,执行activity先执行里面的方法static方法,dofixc方法最终会执行到native的soInit和dofixs来修复方法

Native方法分析

通过java层分析,最终会加载libzuma.so
soinit方法分析,f5大法好
此壳f5一些函数损坏不是很严重,大部分都保留原样
方法大部分都是修复的,我只大体说下函数作用,其他具体自己看代码
int __fastcall Java_com_ali_mobisecenhance_Fix_soInit(int env, int a2, ali *zumaDataPath, int packageName, int context, int cookies, ali *dexnumbers)
{
  int packageName1; // r6
  JNIEnv *env1; // r7
  int v9; // r0
  int androidDevice; // r5
  int *androidDeviceAddr; // r3
  AndroidDevice **androidDeviceAddr1; // ST0C_4
  AndroidDevice *androidDevice1; // r5
  ali::AppInfo *appinfo; // r6
  int appinfoAddr; // r5
  ZumaInfo *zumaInfo; // r6
  ZumaInfo **zumaInfo1; // r5
  bool v18; // r2
  AndroidDevice **androidDeviceAddr2; // r6
  ZumaInfo **zumaInfo2; // r4
  int i; // r5
  int v22; // r3
  unsigned int *v23; // r1
  int v24; // r3
  int v25; // r3
  ZumaInfo *zumaInfo3; // r0
  int v27; // r0
  int v28; // r2
  int v29; // r2
  ArtMethodInfo *methodInfo1; // r4
  int *v32; // [sp+0h] [bp-100h]
  int v33; // [sp+8h] [bp-F8h]
  int v34; // [sp+Ch] [bp-F4h]
  ali *zumaDataPath1; // [sp+10h] [bp-F0h]
  char v36; // [sp+1Ch] [bp-E4h]
  char v37; // [sp+34h] [bp-CCh]
  char v38; // [sp+4Ch] [bp-B4h]
  char v39; // [sp+64h] [bp-9Ch]

  packageName1 = packageName;
  zumaDataPath1 = zumaDataPath;
  env1 = (JNIEnv *)env;
  v32 = &GLOBAL_OFFSET_TABLE_;
  enter("jni/demolish.cpp", "Java_com_ali_mobisecenhance_Fix_soInit", 584);
  v9 = ali::hookinit();
  if ( v9 )
    v9 = my_abort(
           "jni/demolish.cpp",
           "Java_com_ali_mobisecenhance_Fix_soInit",
           587,
           "hook init error! ",
           &GLOBAL_OFFSET_TABLE_);
  j_clock(v9);                                  // 测试函数执行时间
  ali::jstringToStdString(&v36, env1, packageName1);// [v38+4]=v38地址+16 [v38+5]存入packageName1开始[v38+4]存入packageName1结束
  std::string::string((int)&v38, (int)&v36);    // [v40+5]存入pName开始[v40+4]存入packageName1结束
  androidDevice = operator new(0x48u);
  ali::AndroidDevice::AndroidDevice(androidDevice, env1);
  androidDeviceAddr = (int *)*(v32 - 61);
  *androidDeviceAddr = androidDevice;
  androidDeviceAddr1 = (AndroidDevice **)androidDeviceAddr;
  std::priv::_String_base<char,std::allocator<char>>::_M_deallocate_block(&v38);
  androidDevice1 = *androidDeviceAddr1;
  std::string::string((int)&v38, (int)&v36);
  ali::AndroidDevice::get_art_so_address(androidDevice1, (int)&v38);// 获取art地址和classes.dex地址
  std::priv::_String_base<char,std::allocator<char>>::_M_deallocate_block(&v38);
  std::string::string((int)&v38, (int)&v36);
  appinfo = (ali::AppInfo *)operator new(0x64u);
  ali::AppInfo::AppInfo(appinfo, (_JNIEnv *)env1, (int)&v38);
  appinfoAddr = *(v32 - 62);
  *(_DWORD *)appinfoAddr = appinfo;
  std::priv::_String_base<char,std::allocator<char>>::_M_deallocate_block(&v38);
  *(_DWORD *)(*(_DWORD *)appinfoAddr + 96) = dexnumbers;
  ali::jstringToStdString(&v37, env1, (int)zumaDataPath1);
  std::string::string((int)&v38, (int)&v37);
  zumaInfo = (ZumaInfo *)operator new(0x34u);
  ali::ZumaInfo::ZumaInfo(zumaInfo, (const char **)&v38);// 读取zumadata信息
  zumaInfo1 = (ZumaInfo **)*(v32 - 63);
  *zumaInfo1 = zumaInfo;
  std::priv::_String_base<char,std::allocator<char>>::_M_deallocate_block(&v38);
  androidDeviceAddr2 = androidDeviceAddr1;
  zumaInfo2 = zumaInfo1;
  if ( cookies )                                // cookies
  {
    v34 = ((int (__fastcall *)(JNIEnv *, int, _DWORD))(*env1)->GetIntArrayElements)(env1, cookies, 0);
    v33 = ((int (__fastcall *)(JNIEnv *, int))(*env1)->GetArrayLength)(env1, cookies);
    j_memset(&v39, 0, 128);
    for ( i = 0; i < v33; ++i )
    {
      v18 = v34;
      v22 = *(_DWORD *)(v34 + 4 * i);
      v23 = *(unsigned int **)(v22 + 16);
      if ( !v23 )
      {
        v24 = *(_DWORD *)(v22 + 12);
        if ( !v24 )
          continue;
        v25 = *(_DWORD *)(v24 + 40);
        if ( !v25 )
          continue;
        v23 = *(unsigned int **)(v25 + 4);
        if ( !v23 )
          continue;
      }
      ali::ZumaInfo::set_dex_file_by_address(*zumaInfo2, v23, &v39);
    }
  }
  if ( (unsigned int)((*androidDeviceAddr2)->system_sdk_version - 21) <= 2 )
    ali::findDexByCookies(env1, (_JNIEnv *)((char *)&dword_0 + 1), v18);
  zumaInfo3 = *zumaInfo2;
  if ( (*androidDeviceAddr2)->systemModeBoolean )
  {
    if ( !ali::ZumaInfo::is_all_dex_address_found(zumaInfo3) )// 返回1
    {
      if ( (*androidDeviceAddr2)->system_sdk_version == 19 )
        ali::get_all_dex_header_address_dalvik(dexnumbers, 0, v29);
      else
        ali::get_dex_header_address_art((ali *)env1, 0);
    }
    methodInfo1 = (ArtMethodInfo *)operator new(0x24u);
    ali::ARTMethodInfo::ARTMethodInfo(methodInfo1, (_JNIEnv *)env1);
    *(_DWORD *)*(v32 - 60) = methodInfo1;
    showArtImportantInfo();
  }
  else
  {
    v27 = ali::ZumaInfo::is_all_dex_address_found(zumaInfo3);
    if ( !v27 )
      v27 = ali::get_all_dex_header_address_dalvik(dexnumbers, 0, v28);
  }
  j_clock(v27);
  quit("jni/demolish.cpp", "Java_com_ali_mobisecenhance_Fix_soInit", 677);
  std::priv::_String_base<char,std::allocator<char>>::_M_deallocate_block(&v37);
  return std::priv::_String_base<char,std::allocator<char>>::_M_deallocate_block(&v36);
}

主要3个方法

1.ali::AndroidDevice::AndroidDevice(androidDevice, env1);

主要判断sdk和dalvik还是art

AndroidDevice *__fastcall ali::AndroidDevice::AndroidDevice(int androidDevice, JNIEnv *env)
{
  AndroidDevice *androidDevice1; // r4
  JNIEnv *env1; // r7
  int v4; // r6
  int v5; // r0
  int v6; // r0
  _JNIEnv *v7; // r1
  _BOOL4 v8; // r0

  androidDevice1 = (AndroidDevice *)androidDevice;
  env1 = env;
  v4 = androidDevice + 4;
  *(_DWORD *)(androidDevice + 20) = androidDevice + 4;
  *(_DWORD *)(androidDevice + 24) = androidDevice + 4;
  std::priv::_String_base<char,std::allocator<char>>::_M_allocate_block(androidDevice + 4, 16);
  *(_BYTE *)androidDevice1->field_14 = 0;
  androidDevice1->systemModeAddr = 0;
  androidDevice1->field_30 = 0;
  androidDevice1->field_34 = 0;
  androidDevice1->dexAddr = 0;
  androidDevice1->field_3C = 0;
  androidDevice1->field_40 = 0;
  androidDevice1->env = (int)env1;
  std::string::operator=(v4, &unk_28EB8);
  androidDevice1->systemModeBoolean = 0;
  androidDevice1->system_sdk_version = ali::AndroidDevice::get_system_sdk_version((ali::AndroidDevice *)androidDevice1);// 魅族5.0.1->21
  v5 = ali::AndroidDevice::get_runtime_by_mmap((ali::AndroidDevice *)androidDevice1);// 获取系统模式dalvik返回1 art返回2
  v6 = ali::AndroidDevice::get_system_runtime((ali::AndroidDevice *)androidDevice1, v5);// 如果上边判断不出是dalvik还是art继续判断
  androidDevice1->systemMode = v6;
  androidDevice1->systemModeBoolean = (unsigned int)(v6 - 1) >= 1;// dalvik=false art=true
  if ( j_strstr(androidDevice1->systemModeContent, "libaoc.so") )
    androidDevice1->isYunOs = 1;
  else
    androidDevice1->isYunOs = ali::check_for_yun_os((JNIEnv *)androidDevice1->env, v7);// 有ro.yunos.version的话返回1
  v8 = ali::check_for_yun_os_TV((ali *)androidDevice1->env, v7);
  androidDevice1->isYunOsTv = v8;               // yun_os_tv返回1
  if ( v8 )
    androidDevice1->isYunOs = 1;
  return androidDevice1;
}
2.ali::AppInfo::AppInfo(appinfo, (_JNIEnv *)env1, (int)&v38);
主要是获取一些文件目录
AppInfo *__fastcall ali::AppInfo::AppInfo(ali::AppInfo *appinfo, _JNIEnv *env, int a3)
{
  AppInfo *appinfo1; // r4
  _JNIEnv *env1; // ST08_4
  char *v5; // r7
  const char **v6; // ST0C_4
  const char *v7; // r2

  appinfo1 = (AppInfo *)appinfo;
  env1 = env;
  v5 = (char *)appinfo + 0x18;
  v6 = (const char **)a3;
  std::string::string((int)appinfo);
  std::string::string((int)v5);
  std::string::string((int)&appinfo1->nativeLibraryDir);
  std::string::string((int)&appinfo1->sourceDir);
  std::string::operator=((std::string *)appinfo1, v6);
  std::string::operator=(v5, &unk_28EB8);
  std::string::operator=(&appinfo1->nativeLibraryDir, &unk_28EB8);
  std::string::operator=(&appinfo1->sourceDir, &unk_28EB8);
  appinfo1->field_60 = 0;
  ali::AppInfo::initAppInfo((ali::AppInfo *)appinfo1, env1, v7);
  return appinfo1;
}
3.ali::ZumaInfo::ZumaInfo(zumaInfo, (const char **)&v38);
读取zumadata信息到内存,然后把libzumadata信息读取出来,对应3个部分,头部,类信息,方法信息
ZumaInfo *__fastcall ali::ZumaInfo::ZumaInfo(ZumaInfo *zumaInfo, const char **a2)
{
  ZumaInfo *zumaInfo1; // r4
  const char **v3; // r3
  const char *v4; // r1
  const char *v5; // r2

  zumaInfo1 = zumaInfo;
  v3 = a2;
  zumaInfo->zumaDataPathEnd = (int)zumaInfo;
  zumaInfo->zumaDataPathStart = (int)zumaInfo;
  zumaInfo->zero = 0;
  if ( a2 != (const char **)zumaInfo )
  {
    v4 = a2[5];
    v5 = v3[4];
    if ( v5 != v4 )
      std::string::_M_append((std::string *)zumaInfo, v4, v5);// /data/data/com.kangkai.test/files/ali-s/libzumadata.so加到zumainfo中
  }
  zumaInfo1->zumaDataMemory = ali::ZumaInfo::mmap_datafile_to_memory(zumaInfo1);// /data/data/com.kangkai.test/files/ali-s/libzumadata.so加入到内存
  ali::ZumaInfo::gen_dex_info_list(zumaInfo1);
  ali::ZumaInfo::gen_clazz_info_list(zumaInfo1);
  ali::ZumaInfo::gen_method_info_list(zumaInfo1);
  return zumaInfo1;
}
ali::ZumaInfo::gen_dex_info_list(zumaInfo1)
读取信息到开辟的dexcount*0x2c的内存中
int __fastcall ali::ZumaInfo::gen_dex_info_list(ZumaInfo *zumaInfo)
{
  int dexCount; // r7
  ZumaInfo *zumaInfo1; // r4
  int v3; // r0
  int i; // r1
  int nextOffset1; // r0
  ZumaHeader *zumaHeader; // r3
  int v7; // r6
  int nextOffset; // r5
  int v9; // r6
  int v10; // r2
  int zumaDataMemory; // [sp+10h] [bp-20h]
  int dexCount1; // [sp+14h] [bp-1Ch]

  dexCount = zumaInfo->dexCount;
  zumaInfo1 = zumaInfo;
  v3 = j_malloc(0x2C * dexCount);
  zumaInfo1->zumaDataHeader = v3;
  if ( !v3 )
  {
    logoutRecord(
      "gen_dex_info_list",
      68,
      6,
      "RecordLog",
      "dex_count (%d),dex_info_list_size (%d)",
      dexCount,
      0x2C * dexCount);
    my_abort("jni/base/zuma-info.cpp", "gen_dex_info_list", 69, "malloc dex_info_list error");
  }
  j_memset(zumaInfo1->zumaDataHeader, 0, 0x2C * dexCount);
  i = 0;
  nextOffset1 = 0;
  zumaDataMemory = zumaInfo1->zumaDataMemory;
  dexCount1 = zumaInfo1->dexCount;
  while ( i != dexCount1 )                      // 把zumadata.so+4开始到0x18内容拷贝出来
  {
    zumaHeader = (ZumaHeader *)(zumaInfo1->zumaDataHeader + 0x2C * i);
    v7 = *(_DWORD *)(zumaDataMemory + nextOffset1 + 0x14);
    ++i;
    zumaHeader->field_0 = *(_DWORD *)(zumaDataMemory + nextOffset1 + 4);
    zumaHeader->field_4 = *(_DWORD *)(zumaDataMemory + nextOffset1 + 8);
    zumaHeader->field_8 = *(_DWORD *)(zumaDataMemory + nextOffset1 + 0xC);
    nextOffset = *(_DWORD *)(zumaDataMemory + nextOffset1 + 0x10);
    zumaHeader->classLength = v7;
    v9 = *(_DWORD *)(zumaDataMemory + nextOffset1 + 0x18);
    v10 = *(_DWORD *)(zumaDataMemory + nextOffset1 + 0x1C);
    zumaHeader->field_14 = nextOffset;
    zumaHeader->methodLength = v9;
    zumaHeader->field_20 = nextOffset1 + v10;
    zumaHeader->hex20 = 0x20;
    zumaHeader->dexAddr = 0;
    nextOffset1 += nextOffset;
  }
  return nextOffset1;
}
ali::ZumaInfo::gen_clazz_info_list(zumaInfo1)
把信息读取到开辟的内存中,然后会把内存中的数据排序
int __fastcall ali::ZumaInfo::gen_clazz_info_list(ZumaInfo *zumaInfo)
{
  int v1; // r3
  int dexCount; // r1
  ZumaInfo *zumaInfo1; // r4
  int i; // r5
  int v5; // r2
  int v6; // r0
  int v7; // r3
  int zumaData20; // r5
  int v9; // r6
  ZumaHeader *zumaHeader; // r3
  unsigned __int8 *v11; // r1
  int *v12; // r7
  int v13; // r0
  int zumaClass; // r3
  unsigned __int8 *v15; // r1
  int zumaClass1; // r7
  unsigned __int8 *v17; // r1
  unsigned __int8 *v18; // r1
  int v19; // r0
  int zumaClass2; // r3
  unsigned int v22; // [sp+4h] [bp-2Ch]
  int v23; // [sp+8h] [bp-28h]
  int v24; // [sp+Ch] [bp-24h]
  int v25; // [sp+10h] [bp-20h]

  v1 = 0;
  dexCount = zumaInfo->dexCount;
  zumaInfo1 = zumaInfo;
  for ( zumaInfo->zumaDataClassLength = 0;
        ;
        zumaInfo->zumaDataClassLength = i + *(_DWORD *)(zumaInfo->zumaDataHeader + v5 + 0xC) )
  {
    i = zumaInfo->zumaDataClassLength;          // 0x2cb
    if ( v1 == dexCount )
      break;
    v5 = 0x2C * v1++;
  }
  v6 = j_malloc(0x14 * i);                      // 0x37DC
  zumaInfo1->zumaClass = v6;
  j_memset(v6, 0, 0x14 * i);
  v7 = 0;
  v22 = 0;
  v25 = 0;
  while ( 1 )
  {
    v24 = v7;
    if ( v22 >= zumaInfo1->dexCount )
      break;
    zumaData20 = zumaInfo1->zumaDataMemory + v25 + *(_DWORD *)(zumaInfo1->zumaDataHeader + 0x2C * v22 + 0x18);// 读取zumadata从0x20位置开始
    v9 = 0x14 * v7;
    v23 = v7;
    while ( 1 )                                 // 把zumadata从0x20信息拷贝到classinfo
                                                // 0x10大小原样拷贝,从0x10开始拷贝zumadata20+0x10地址
    {
      zumaHeader = (ZumaHeader *)(zumaInfo1->zumaDataHeader + 0x2C * v22);
      v11 = (unsigned __int8 *)zumaHeader->classLength;// 0x2cb类信息大小
      if ( v23 - v24 >= (unsigned int)v11 )
        break;
      v12 = (int *)(zumaInfo1->zumaClass + v9);
      v13 = ali::readUint32((ali *)zumaData20, v11);
      zumaClass = zumaInfo1->zumaClass;
      *v12 = v13;
      *(_DWORD *)(zumaClass + v9 + 4) = ali::readUint32((ali *)(zumaData20 + 4), v15);
      zumaClass1 = zumaInfo1->zumaClass + v9;
      *(_DWORD *)(zumaClass1 + 8) = ali::readUint32((ali *)(zumaData20 + 8), v17);
      v19 = ali::readUint32((ali *)(zumaData20 + 0xC), v18);
      zumaClass2 = zumaInfo1->zumaClass + v9;
      *(_DWORD *)(zumaClass2 + 0xC) = v19;
      *(_DWORD *)(zumaClass2 + 0x10) = zumaData20 + 0x10;
      zumaData20 += 4 * (v19 + 4);
      ++v23;
      v9 += 0x14;
    }
    v25 += zumaHeader->field_14;
    ++v22;
    v7 = v23;
  }
  return ali::quicksort_Clazz_Info_Struct(zumaInfo1->zumaClass, 0, zumaInfo1->zumaDataClassLength - 1);
}
ali::ZumaInfo::gen_method_info_list(zumaInfo1)
看具体注释把
int __fastcall ali::ZumaInfo::gen_method_info_list(ZumaInfo *zumaInfo)
{
  int v1; // r3
  int v2; // r1
  ZumaInfo *zumaInfo1; // r5
  int v4; // r4
  int v5; // r2
  int v6; // r0
  int result; // r0
  ZumaHeader *zumaHeader; // r3
  int v9; // r4
  int zumaData90f0; // r4
  int v11; // r6
  ZumaHeader *zumaHeader1; // r3
  unsigned __int8 *v13; // r1
  int *v14; // r7
  int v15; // r0
  int methodInfo1; // r3
  unsigned __int8 *v17; // r1
  int methodInfo2; // r7
  unsigned __int8 *v19; // r1
  ali *v20; // r0
  int methodInfo3; // r7
  unsigned __int8 *v22; // r1
  unsigned int v23; // [sp+4h] [bp-2Ch]
  int v24; // [sp+8h] [bp-28h]
  int v25; // [sp+Ch] [bp-24h]
  int v26; // [sp+10h] [bp-20h]
  int v27; // [sp+14h] [bp-1Ch]

  v1 = 0;
  v2 = zumaInfo->dexCount;
  zumaInfo1 = zumaInfo;
  for ( zumaInfo->zumaDataMethodLength = 0;
        ;
        zumaInfo->zumaDataMethodLength = v4 + *(_DWORD *)(zumaInfo->zumaDataHeader + v5 + 0x10) )
  {
    v4 = zumaInfo->zumaDataMethodLength;        // 0x1906
    if ( v1 == v2 )
      break;
    v5 = 0x2C * v1++;
  }
  v6 = j_malloc(0x14 * v4);                     // 0x1f478
  zumaInfo1->methodInfo = v6;
  result = j_memset(v6, 0, 0x14 * v4);
  v23 = 0;
  v26 = 0;
  v24 = 0;
  while ( v23 < zumaInfo1->dexCount )
  {
    v25 = 0x2C * v23;
    zumaHeader = (ZumaHeader *)(zumaInfo1->zumaDataHeader + 0x2C * v23);
    v9 = 4 * zumaHeader->methodLength + 0x10 * zumaHeader->classLength;// 0x6418+0x2cb0=90c8
    if ( v9 & 0xF )                             // 0x8
      v9 = v9 + 0x10 - (v9 & 0xF);              // 0x90c8+0x10-0x8=0x90d0
    zumaData90f0 = zumaInfo1->zumaDataMemory + v26 + zumaHeader->hex20 + v9;// 0x90d0+0x20=0x90f0
    v27 = v24;
    v11 = 20 * v24;
    while ( 1 )                                 // method 0x0->*zudaData90f0 0x4->*zudaData90f0+0x4 0x8->*zudaData90f0+0x8
                                                // 0xc->*zudaData90f0+0xc+*zumaHeader+0x20
                                                // 0x10->*zumaHeader
    {
      zumaHeader1 = (ZumaHeader *)(zumaInfo1->zumaDataHeader + v25);
      v13 = (unsigned __int8 *)zumaHeader1->methodLength;
      if ( v24 - v27 >= (unsigned int)v13 )
        break;
      v14 = (int *)(zumaInfo1->methodInfo + v11);
      v15 = ali::readUint32((ali *)zumaData90f0, v13);
      methodInfo1 = zumaInfo1->methodInfo;
      *v14 = v15;
      *(_DWORD *)(methodInfo1 + v11 + 0x10) = *(_DWORD *)(zumaInfo1->zumaDataHeader + v25);
      *(_DWORD *)(methodInfo1 + v11 + 4) = ali::readUint32((ali *)(zumaData90f0 + 4), v17);
      methodInfo2 = zumaInfo1->methodInfo + v11;
      *(_DWORD *)(methodInfo2 + 8) = ali::readUint32((ali *)(zumaData90f0 + 8), v19);
      v20 = (ali *)(zumaData90f0 + 0xC);
      zumaData90f0 += 0x10;
      methodInfo3 = zumaInfo1->methodInfo + v11;
      v11 += 0x14;
      result = ali::readUint32(v20, v22) + *(_DWORD *)(zumaInfo1->zumaDataHeader + v25 + 0x20);
      *(_DWORD *)(methodInfo3 + 0xC) = result;
      ++v24;
    }
    v26 += zumaHeader1->field_14;
    ++v23;
  }
  return result;
}

native doFixS分析
通过二分法查询了之前排序的类信息的偏移位置
JNIEnv *__fastcall Java_com_ali_mobisecenhance_Fix_doFixS(JNIEnv *env, int a2, int *cls, ali *classHash)
{
  ali *classHash1; // r6
  JNIEnv *env1; // r7
  int v6; // r2
  int classIndex; // r5
  int v9; // r2
  int v10; // [sp+8h] [bp-28h]
  int *cls1; // [sp+Ch] [bp-24h]
  unsigned int v12; // [sp+10h] [bp-20h]

  classHash1 = classHash;
  v10 = a2;
  env1 = env;
  cls1 = cls;
  v12 = 0;
  classIndex = ali::getClazzInfoRefByClzHash(classHash, (int)&v12, cls);// 在dump的classinfo中查找类信息
  if ( classIndex == -1 )
    return (JNIEnv *)logout(
                       (const char *)&unk_28914,
                       699,
                       5,
                       "RecordLog",
                       "can not find clazz_hash %X",
                       classHash1,
                       v10,
                       cls1);
  if ( !ali::ZumaInfo::get_dex_file_adress(ali::g_zuma_infos, v12, v6, (int)&ali::g_zuma_infos) )
    ali::get_all_dex_header_address_dalvik(*(ali **)(ali::g_app_infos + 96), v12, v9);
  return fix_class(env1, v10, (int)cls1, classIndex);
}
fix_class方法
通过类偏移地址找到类信息,里面存储了需要修复的方法数量和方法偏移地址等
JNIEnv *__fastcall fix_class(JNIEnv *env, int a2, int cls, int classIndex)
{
  _jmethodID *cls1; // ST24_4
  JNIEnv *env1; // ST1C_4
  unsigned __int8 *v6; // ST20_4
  FixFunInfo *fixFunInfo; // r3
  int classHash1; // ST2C_4
  int v9; // ST30_4
  int fixNativeCount1; // ST38_4
  int methodOffset1; // ST3C_4
  int v12; // r5
  int dexAddr; // r0
  int v15; // [sp+40h] [bp-18h]

  cls1 = (_jmethodID *)cls;
  env1 = env;
  v6 = (unsigned __int8 *)a2;
  fixFunInfo = (FixFunInfo *)(ali::g_zuma_infos->zumaClass + 0x14 * classIndex);
  classHash1 = fixFunInfo->classHash;
  v9 = fixFunInfo->field_4;
  fixNativeCount1 = fixFunInfo->fixNativeCount; // 需要修复的native数量
  methodOffset1 = fixFunInfo->methodOffset;
  v12 = fixFunInfo->field_8;                    // 0
  dexAddr = ali::ZumaInfo::get_dex_file_adress(ali::g_zuma_infos, fixFunInfo->field_8, (int)&v15, (int)fixFunInfo);
  return ali::start_fix_this_class(env1, v6, cls1, dexAddr, classHash1, v9, v12, fixNativeCount1, methodOffset1);
}
start_fix_this_class方法
在dex中获取到类方法的地址,然后通过动态获取到类方法来修复
JNIEnv *__fastcall ali::start_fix_this_class(JNIEnv *result, unsigned __int8 *a2, _jmethodID *cls, int dexAddr, int a5, int a6, int a7, unsigned int nativeCount, int methodOffset)
{
  int dexAddr1; // r4
  unsigned int i; // r3
  int methodIdIndex; // r7
  unsigned __int16 *dexMethodId; // r3
  unsigned __int16 protoIdIndex; // r6
  char *methodName; // r7
  char *methodSign; // r6
  unsigned int v16; // [sp+14h] [bp-3Ch]
  int string_ids_addr; // [sp+18h] [bp-38h]
  int methodAddr; // [sp+1Ch] [bp-34h]
  int className; // [sp+20h] [bp-30h]
  int type_ids_addr; // [sp+24h] [bp-2Ch]
  int method_ids_addr; // [sp+28h] [bp-28h]
  char *env; // [sp+2Ch] [bp-24h]
  _jmethodID *cls1; // [sp+30h] [bp-20h]
  int proto_ids_addr; // [sp+34h] [bp-1Ch]

  dexAddr1 = dexAddr;
  env = (char *)result;
  string_ids_addr = dexAddr + *(_DWORD *)(dexAddr + 0x3C);
  cls1 = cls;
  type_ids_addr = dexAddr + *(_DWORD *)(dexAddr + 0x44);
  method_ids_addr = dexAddr1 + *(_DWORD *)(dexAddr1 + 0x5C);
  proto_ids_addr = dexAddr + *(_DWORD *)(dexAddr + 0x4C);
  for ( i = 0; ; i = v16 + 1 )
  {
    v16 = i;
    if ( i >= nativeCount )                     // 被native的方法数量
      break;
    methodAddr = 0x14 * ali::readUint32((ali *)(methodOffset + 4 * i), a2);// methodOffset=2e
                                                // 0000A230=0x081c*0x14  1C 08 00 00 1D 08 00 00  B9 D7 9C DA 00 00 00 00
    methodIdIndex = *(_DWORD *)(ali::g_zuma_infos->methodInfo + methodAddr + 4);// 0x4846
    dexMethodId = (unsigned __int16 *)(method_ids_addr + 8 * methodIdIndex);// dex中某个地址
    protoIdIndex = dexMethodId[1];
    className = ali::get_class_name(dexAddr1, string_ids_addr, type_ids_addr, *dexMethodId);// typeIdIndex
    methodName = (char *)ali::get_method_name(dexAddr1, string_ids_addr, method_ids_addr, methodIdIndex);
    methodSign = ali::get_method_sig(dexAddr1, string_ids_addr, type_ids_addr, proto_ids_addr, protoIdIndex);
    if ( ali::g_device_infos->systemModeBoolean )
      ali::fix_method_in_art(
        env,
        cls1,
        (_jmethodID *)className,
        methodName,
        methodSign,
        *(_jmethodID **)(ali::g_zuma_infos->methodInfo + methodAddr + 8),
        (_jmethodID *)dexAddr1);
    else
      ali::fix_method_in_dalvik(
        env,
        cls1,
        (_jmethodID *)className,
        methodName,
        methodSign,
        (_jmethodID *)(dexAddr1 + *(_DWORD *)(ali::g_zuma_infos->methodInfo + methodAddr + 8)),
        (_jmethodID *)dexAddr1);
    j_free(className);
    j_free(methodName);
    result = (JNIEnv *)j_free(methodSign);
  }
  return result;
}

int __fastcall ali::fix_dalvik_method_struct(ali *this, _JNIEnv *a2, int a3, unsigned int a4)
{
  int v4; // r5
  int v5; // r4
  unsigned __int8 *v6; // r1
  unsigned __int8 *v7; // r1
  int codeOff; // r3
  unsigned __int8 *v9; // r1
  unsigned int v10; // r1
  int result; // r0
  unsigned __int8 *v12; // r1
  unsigned int v13; // r1

  v4 = a3;
  v5 = (int)a2;
  ali::getRegistersSize((ali *)a3, (unsigned __int8 *)a2);
  ali::getOutsSize((ali *)v4, v6);
  codeOff = v4 + 0x10;
  if ( ali::g_device_infos->isYunOs )
  {
    *(_DWORD *)(v5 + 0x18) = codeOff;
    *(_WORD *)(v5 + 0x20) = ali::getRegistersSize((ali *)v4, v7);
    *(_WORD *)(v5 + 0x22) = ali::getOutsSize((ali *)v4, v9);
    result = ali::getAccessFlags((ali *)*(unsigned __int16 *)(v5 + 6), v10);
    *(_WORD *)(v5 + 6) = result;
  }
  else
  {
    *(_DWORD *)(v5 + 0x20) = codeOff;
    *(_WORD *)(v5 + 0xA) = ali::getRegistersSize((ali *)v4, v7);
    *(_WORD *)(v5 + 0xC) = ali::getOutsSize((ali *)v4, v12);
    result = ali::getAccessFlags(*(ali **)(v5 + 4), v13);
    *(_DWORD *)(v5 + 4) = result;
  }
  return result;
}

至此壳的流程基本走完了
分析完可知
header



修复

因为通过上面分析,我们能找到native方法对应的codeoff,所以可以动态写脚本来修复
但是会有一个问题,codeoff可能会超出原来大小,这样dex整个偏移都要变,修复太麻烦,不现实
参考文章https://bbs.pediy.com/thread-220717.htm
通过修改baksmali源码来修复codeoff
说一下修复思路,源码我就不放出来了
1.通过上面源码分析,还原出gen_dex_info_list、gen_clazz_info_list、gen_method_info_list的代码
2.通过还原出的类,主动去加载所有需要修复的类
3.还原出修复类方法代码start_fix_this_class,由此可以得到codeoff
4.因为codeoff在dex文件中,所以直接在电脑64位系统加载到内存会有问题,我直接把类、方法、签名、codeoff保存到文件中
5.baksmali中去加载保存的文件信息,存到集合中
6.当baksmali反编译时候修复accessflag和codeoff

我分析的样本是之前的,修复脚本最新免费版一样适用


[2022夏季班]《安卓高级研修班(网课)》月薪三万班招生中~

最后于 2018-5-7 16:26 被Roselia编辑 ,原因:
上传的附件:
收藏
点赞2
打赏
分享
最新回复 (14)
雪    币: 38
活跃值: 活跃值 (10)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
KCG 活跃值 2018-5-2 20:21
2
0
ali吧
雪    币: 445
活跃值: 活跃值 (130)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
Roselia 活跃值 1 2018-5-2 21:24
3
0
嗯嗯,玩过的应该一眼就能看出来
雪    币: 6817
活跃值: 活跃值 (153)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
聖blue 活跃值 2018-5-2 23:11
4
0
雪    币: 143
活跃值: 活跃值 (260)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
人在塔在 活跃值 2018-5-3 09:19
5
0
mark  ali  谢谢分享
雪    币: 62
活跃值: 活跃值 (27)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
toToC 活跃值 2018-5-3 10:03
6
0
哈哈,阿里壳
雪    币: 80
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
zhengsidie 活跃值 2018-5-3 10:16
7
0
mark,分析到位。
雪    币: 20
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
一xOO 活跃值 2018-5-3 12:20
8
0
mark厉害
雪    币: 319
活跃值: 活跃值 (189)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
Lucaks 活跃值 1 2018-5-17 12:56
9
0
写了一个自动修复的,对于你个这个样本可以了。还需要真实的样本测试
雪    币: 203
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
曾庆XOZQY 活跃值 2018-5-17 22:02
10
0
真厉害,学习了
雪    币: 165
活跃值: 活跃值 (45)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
LOphTg 活跃值 2018-5-20 15:05
11
0
学习
雪    币: 654
活跃值: 活跃值 (25)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
miyuecao 活跃值 2018-12-12 15:34
13
0
厉害厉害,学习了
雪    币: 53
活跃值: 活跃值 (684)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
cydian 活跃值 2019-8-23 12:51
14
0
mark
游客
登录 | 注册 方可回帖
返回