首页 > android > android某加固脱壳-静态脱壳工具(二)
2015
11-17

android某加固脱壳-静态脱壳工具(二)

接着上一篇文章:首先首先将加固前的apk和加固后的apk做对比,对比结果如下图,

android某加固脱壳-静态脱壳工具(二) - 第1张  | 大白的小窝
看到结果看到增加了libshella-0.0.1.so、libshellx-0.0.1.so、mix.dex三个文件,同时修改了AndroidManifest.xml、classes.dex文件,

根据上一篇文章分析下dex文件头如何静态解密:

android某加固脱壳-静态脱壳工具(二) - 第2张  | 大白的小窝

memcpy(&s, (const void *)(v29 + 12328), 0x70u);

看下函数的原型:

从源src所指的内存地址的起始位置开始拷贝n个字节到目标dest所指的内存地址的起始位置中

void *memcpy(void *dest, const void *src, size_t n);

即:从(v29 + 12328)内存位置开始,复制0x70个字节到 s 所在的位置,

由于此加固是将原dex文件放到新dex文件的文件尾部:

android某加固脱壳-静态脱壳工具(二) - 第3张  | 大白的小窝

加密后的dex在加载到内存中转为odex:其中odex header 大小为0x28;

android某加固脱壳-静态脱壳工具(二) - 第4张  | 大白的小窝

静态分析看到:0x3028(12328)-0x28=0x3000;即在dex文件的0x3000偏移处为加密后的dex头文件。

知道加密后的dex文件头偏移后,接着看dex解密相关算法:

sub_C0BC(&v48, &s, 112, 32);

第二个参数为复制的dex加密的文件头。

signed int __fastcall sub_C0BC(int a1, int a2, unsigned int a3, int a4)
{
  int v4; // r7@1
  int v5; // r5@1
  int v6; // r6@4
  int v7; // r4@4
  int v8; // r3@6
  signed int result; // r0@8
  unsigned int v10; // [sp+4h] [bp-1Ch]@1

  v4 = a4;
  v5 = a1;
  v10 = a3 >> 3;
  if ( a2 && a1 && a4 && (v6 = (__PAIR__(a3 & 7, a3 & 7) - __PAIR__(a3, 1)) >> 32, v7 = a2, !v6) )//这里v7=a2;
  {
    while ( v6 != v10 )//循环计数
    {
      v8 = 8 * (v6 & 1);
      *(_DWORD *)v7 ^= *(_DWORD *)(v5 + v8);
      ++v6;
      *(_DWORD *)(v7 + 4) ^= *(_DWORD *)(v5 + v8 + 4);
      sub_BFFC(v5, v7, v7, v4);//每次对8个字节进行解密
      v7 += 8;//v7指针自增8
    }
    result = 1;
  }
  else
  {
    result = 0;
  }
  return result;
}

接着看 sub_BFFC(v5, v7, v7, v4);方法:

unsigned int __fastcall sub_BFFC(int a1, int a2, int a3, int a4)
{
  int v4; // r6@1
  unsigned int result; // r0@1
  int v6; // r5@1
  unsigned int v7; // r1@1
  int v8; // r4@1
  int v9; // [sp+4h] [bp-24h]@1
  int v10; // [sp+8h] [bp-20h]@1
  int v11; // [sp+Ch] [bp-1Ch]@1

  v9 = *(_DWORD *)a1;
  v4 = *(_DWORD *)(a1 + 12);
  v10 = *(_DWORD *)(a1 + 4);
  v11 = *(_DWORD *)(a1 + 8);
  result = *(_DWORD *)a2;//读取前四个
  v6 = 0;
  v7 = *(_DWORD *)(a2 + 4);//读取后四个加密数据
  v8 = -1640531527 * a4;
  while ( v6 != a4 )//进行一系列的运算解密
  {
    ++v6;
    v7 -= (v8 + result) ^ (16 * result + v11) ^ ((result >> 5) + v4);
    result -= (v7 + v8) ^ ((v7 >> 5) + v10) ^ (16 * v7 + v9);
    v8 += 1640531527;
  }
  *(_DWORD *)a3 = result;//存储前四个解密结果
  *(_DWORD *)(a3 + 4) = v7;//存储后四个解密结果。
  return result;
}

经过整理的算法:

#include <stdio.h>    
#include <stdlib.h>    
#include <string>    
#include <iostream>    
#define DWORD unsigned long     
void jiemi(char* cd);    
int step = 0;    
using namespace std;    
int main() {    
	//获取当前输入路径所在目录    
	printf_s("请输入classes.dex文件的路径:\n");    
	char path14[1000];    
	cin.getline(path14, 100);    
	string s(path14);    
	s = s.substr(0, s.rfind('\\')) + "\\afterclasses.dex";    
	char* path = (char*)s.c_str();    
	printf_s(path);    
	//two file point    
	FILE *fp;    
	FILE *out;    
	//数据模式读取文件    
	int a = fopen_s(&fp, path14, "rb");    
	// skip 0x3000    
	fseek(fp, 0x3000, 0);    
	char* ch = new char[0x70];    
	//read 0x70个 byte    
	fread(ch, 1, 0x70, fp);    
	//every time read 0x8 byte    
	int aa = 0x70 / 8;    
	while (aa)    
	{    
		jiemi(ch);    
		--aa;    
	}    
	//数据模式写文件    
	fopen_s(&out, path, "wb+");    
	fwrite(ch, 1, 0x70, out);    
	fclose(out);    
	FILE * aab;    
	fopen_s(&aab, path, "ab+");    
	char* cc = new char[1];    
	while (fread(cc, 1, 1, fp))    
	{    
		fwrite(cc, 1, 1, aab);    
	}    
	fclose(aab);    
	fclose(fp);    
	delete[]ch;    
	delete[]cc;    
	printf_s("获取dex文件完成!!!\n");    
	getchar();    
	return 0;    
}    
//解密函数    
void jiemi(char* cd) {    
	unsigned int result;    
	int v6;    
	unsigned int v7;    
	int v8;    
	printf_s("==============================\n");    
	result = *(DWORD *)(cd + step * 8);//读取的前四个数字;    
	printf_s("读取:%x\n", result);//打印读取工具    
	v6 = 0;    
	v7 = *(DWORD *)(cd + 4 + step * 8);//读取后四个数字    
	v8 = -1640531527 * 0x20;    
	while (v6 != 0x20)    
	{    
		++v6;    
		v7 -= (v8 + result) ^ (16 * result) ^ ((result >> 5));    
		result -= (v7 + v8) ^ ((v7 >> 5)) ^ (16 * v7);    
		v8 += 1640531527;    
	}    
	printf_s("输出(DWORD):%x\n", result);//前四个解密接结果    
	*(DWORD *)&cd[(step * 8)] = result;    
	printf_s("===%x===\n", *(DWORD *)&cd[step * 8]);    
	printf_s("输出(DWORD):%x\n", v7);//后四个解密结果    
	*(DWORD *)&cd[step * 8 + 4] = v7;    
	++step;    
}

c语言水平有限。只能写出这样了

结果如下:

android某加固脱壳-静态脱壳工具(二) - 第5张  | 大白的小窝

最后编辑:
作者:xiaowu
这个作者貌似有点懒,什么都没有留下。

留下一个回复

你的email不会被公开。