首页
论坛
课程
招聘
[原创]**加固分析
2022-2-15 02:53 29850

[原创]**加固分析

2022-2-15 02:53
29850

这篇帖子起因是前段时间想挂个协和的号,随便拿了个测试机下载好APP后打开卡在启动界面,以为是测试机root之类的东西被检测到后拒绝启动了。

于是准备看看怎么回事,发现这玩意儿使用了**加固,正准备分析分析,突然发现测试机WiFi没连上,连上网之后就正常了,于是就把它丢在一边没管了。

然后过年在家闲着没事,想起还有这么个东西,正好**加固以前没有遇到过,于是在垃圾桶里把它翻出来了。

分析完后,实在是忍不住想吐槽一下,,不知道是不是外包公司没给钱,这加固做得就跟期末大作业水平差不多,全程就像读源码一样,,和前一篇帖子分析的乐固差远了。。

分析

老规矩,先把apk用jadx反编译,从AndroidManifest.xml找到application的类com.***ivm.security.StubApplication,

发现这个类的attachBaseContext和onCreate方法都是native方法,然后有个静态代码块。

在SDK大于等于29(android9)的时候,先解除对隐藏api的反射限制。

然后init方法判断cpu架构,从apk的assets目录释放对应的so进行加载。

选择分析arm32的文件kadp_armeabi。


用ida加载kadp_armeabi,发现没有.init_array段,于是直接看JNI_OnLoad函数,代码很简单,只调用了init函数

init函数的代码也很简单,判断了下sdk版本和vm版本,然后注册了两个native方法

看下off_2C124的数据,注册了attachBaseContext和onCreate这两个方法


接着看native_attachBaseContext,首先调用了init_class


init_class函数中获取了一些字段和方法的id进行缓存


回到native_attachBaseContext,获取dalvik.system.DexFile的构造方法缓存起来,然后调用函数extractDexToMemMap_zlib从apk获取dex文件,接着调用函数cfile_init对dex进行解析

函数extractDexToMemMap_zlib通过zlib库遍历apk中的文件,获取classes.dex文件并mmap


函数cfile_init先判断文件类型,找到dex的基址,计算dex所属内存页,修改属性,用于后面解密直接修改

然后解析一些用于解密dex的字段


dex中用于解密的数据从dex的data数据之后开始,即起始位置的偏移为 dex_header.data_size+dex_header.data_off

结构如下:

magic字段内容如下,不匹配则解析失败

dex文件中的实际数据如下,

0x2e60处是magic

0x2e68处是dexCount,所以加密的dex文件数量为10个

0x2e6c处是dataOff,所以加密的dex数据起始位置为0x2e60+0x60=0x2ec0

0x2e70处是第一个***iDexItem,所以第一个加密的dex文件大小为0x8f84f8,起始位置为0x2ec0+0=0x2ec0



继续回到native_attachBaseContext,重新构造dexElements并替换,然后多线程执行函数thread_loadDex

函数thread_loadDex中主要调用mem_loadDex


函数mem_loadDex中首先调用函数cfile_load_file


函数cfile_load_file调用函数decrypt_buf进行dex解密


函数decrypt_buf的解密很简单,dex只有前9字节被加密了,算法是一个简单的异或

回到函数mem_loadDex中,调用write_mix_dex、openmemory_load_dex和load_dex_by_byteBuffer进行dex加载,

由于我的设备是sdk27,这几个函数中实际只有load_dex_by_byteBuffer这个函数有用。

然后通过make_dex_elements将DexFile添加到列表中


dex加载完成后,继续回到native_attachBaseContext,

首先通过reback_prot恢复内存页属性

然后通过old_application获取原始application的类名,原始application的类名作为metaData存放在AndroidManifest.xml,name为KWS_MAIN_APP

然后就是app相关的字段替换,就不分析了

脱壳代码

#include<fstream>
#include<string>


typedef unsigned char	u1;
typedef unsigned int	u4;

struct DexHeader {
	u1  magic[8];
	u4  checksum;
	u1  signature[20];
	u4  fileSize;
	u4  headerSize;
	u4  endianTag;
	u4  linkSize;
	u4  linkOff;
	u4  mapOff;
	u4  stringIdsSize;
	u4  stringIdsOff;
	u4  typeIdsSize;
	u4  typeIdsOff;
	u4  protoIdsSize;
	u4  protoIdsOff;
	u4  fieldIdsSize;
	u4  fieldIdsOff;
	u4  methodIdsSize;
	u4  methodIdsOff;
	u4  classDefsSize;
	u4  classDefsOff;
	u4  dataSize;
	u4  dataOff;
};


struct ***iDexItem {
	u4 dexSize;
	u4 dexOff;
};

struct ***iHeader {
	u1 magic[8];
	u4 dexCount;
	u4 dataOff;
	***iDexItem items[0];
};

int main() {
	std::ifstream ifs("classes.dex", std::ifstream::binary);
	ifs.seekg(0, ifs.end);
	auto fileLen = static_cast<int>(ifs.tellg());
	auto rawDexBuf = new u1[fileLen];
	ifs.seekg(0, ifs.beg);
	ifs.read(reinterpret_cast<char *>(rawDexBuf), fileLen);
	ifs.close();

	auto dexHeader = reinterpret_cast<DexHeader*>(rawDexBuf);
	auto ***iHeader = reinterpret_cast<***iHeader*>(rawDexBuf + dexHeader->dataOff + dexHeader->dataSize);
	auto ***iDexItems = ***iHeader->items;
	auto dexCount = ***iHeader->dexCount;
	auto dexBasePtr = reinterpret_cast<u4>(***iHeader) + ***iHeader->dataOff;

	for (size_t dexIndex = 0; dexIndex < dexCount; dexIndex++)
	{
		auto  dexPtr = reinterpret_cast<u1*>(dexBasePtr + ***iDexItems[dexIndex].dexOff);
		for (size_t i = 0; i < 9; ++i)
		{
			dexPtr[i] ^= dexIndex + i + dexCount + 2;
		}
		std::ofstream ofs("classes_" + std::to_string(dexIndex) + ".dex", std::ofstream::binary);
		ofs.write(reinterpret_cast<char*>(dexPtr), ***iDexItems[dexIndex].dexSize);
		ofs.close();
	}

	return 0;
}


脱壳后




【看雪培训】《Adroid高级研修班》2022年夏季班招生中!

最后于 2022-2-17 20:10 被kanxue编辑 ,原因:
上传的附件:
收藏
点赞1
打赏
分享
最新回复 (19)
雪    币: 181
活跃值: 活跃值 (207)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
mb_yvvzfcdo 活跃值 2022-2-15 07:57
2
0
tql
雪    币: 2690
活跃值: 活跃值 (1849)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
caolinkai 活跃值 2022-2-15 09:04
3
0
支持
雪    币: 1931
活跃值: 活跃值 (629)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
灬哈密瓜 活跃值 2022-2-15 10:00
4
0
已读完源码
雪    币: 9
活跃值: 活跃值 (459)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
bullyxy 活跃值 2022-2-15 10:36
5
0
还有两so呢
雪    币: 9
活跃值: 活跃值 (459)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
bullyxy 活跃值 2022-2-15 10:40
6
0
他还有种加载是hook一些系统函数来加载
雪    币: 4711
活跃值: 活跃值 (2393)
能力值: ( LV8,RANK:135 )
在线值:
发帖
回帖
粉丝
卧勒个槽 活跃值 3 2022-2-15 11:15
7
0
bullyxy 还有两so呢
KwProtectSDK和kwsdataenc吗
雪    币:
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
mb_lasgffyh 活跃值 2022-2-16 17:20
8
0
雪    币: 3939
活跃值: 活跃值 (1281)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
D-t 活跃值 2022-2-16 17:28
9
0

根据楼主提供代码 编译了小工具 方便各位使用



最后于 2022-2-17 20:18 被kanxue编辑 ,原因:
上传的附件:
  • k.rar (33.94kb,80次下载)
雪    币: 970
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
mb_vjhvccto 活跃值 2022-2-16 19:11
10
0
我是搬运工
雪    币: 1765
活跃值: 活跃值 (3312)
能力值: ( LV10,RANK:160 )
在线值:
发帖
回帖
粉丝
爱吃菠菜 活跃值 2 2022-2-18 17:00
11
0
怎么变成了**
雪    币: 4711
活跃值: 活跃值 (2393)
能力值: ( LV8,RANK:135 )
在线值:
发帖
回帖
粉丝
卧勒个槽 活跃值 3 2022-2-18 17:02
12
0
爱吃菠菜 怎么变成了**[em_88]
和谐了,
雪    币: 2041
活跃值: 活跃值 (3311)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
lhxdiao 活跃值 2022-2-20 15:54
13
0
直接点,几维
雪    币: 4711
活跃值: 活跃值 (2393)
能力值: ( LV8,RANK:135 )
在线值:
发帖
回帖
粉丝
卧勒个槽 活跃值 3 2022-2-20 16:20
14
0
lhxdiao 直接点,几维
你看看最后编辑人,
雪    币: 84
活跃值: 活跃值 (246)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
K4NG 活跃值 2022-2-22 11:46
15
0
卧勒个槽 和谐了,[em_76]
和谐不彻底 图片中package暴漏了 
雪    币: 205
活跃值: 活跃值 (1266)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
杰克王 活跃值 2022-2-22 11:52
16
0
打工人,何必为难打工人?
雪    币: 970
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
mb_vjhvccto 活跃值 2022-2-23 08:50
17
0
感谢老板娘
雪    币: 9807
活跃值: 活跃值 (2092)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
tDasm 活跃值 2022-2-23 09:42
18
0
这个软件不是靠本身实力保护,而是靠看雪保护?
雪    币:
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
steve6 活跃值 2022-5-31 21:02
19
0
这个加壳后的apk能够提供一下吗?非常感谢。
雪    币: 970
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
mb_vjhvccto 活跃值 2022-6-18 17:01
20
0
数字对了恭喜恭喜
游客
登录 | 注册 方可回帖
返回