首页
社区
课程
招聘
[原创]一个Android壳简单实现。
发表于: 2018-12-30 18:00 11413

[原创]一个Android壳简单实现。

2018-12-30 18:00
11413

又一年要过完了,没有什么提高,总结一下学习过程的中的笔记,顺便锻炼一下写文档的能力。

过时的技术,各位大佬请轻喷。

Dex加固

加壳程序工作流程:加密源程序APK文件,把加密后数据写入壳APK的Dex文件尾部并添加数据长度,修改Dex文件头部的checksum,signature,file_size字段,使用源程序AndroidMainfest.xml替换壳程序的AndroidMainfest.xml文件内容。

脱壳程序工作流程:读取Dex文件末尾数据以及长度信息,解密数据保存文件,动态加载源APK。

加壳程序:

DEX文件头部结构如下:


修复CheckSum,CheckSum使用alder32算法校验除去magic,checksum以外的部分。

修复Signature,Signature使用sha1计算除去 magic ,checksum 和 signature以外的部分。

修改添加加密数据后的Dex文件大小

修改Dex头部信息时需要先修改filesize,在计算signature,最后计算checksum的值否则会提示DEX文件无效。

到这里加壳程序就完成了很简单,只是做加密数据,合并内容,修改dex header字段,生成新dex文件。

脱壳程序:

首先需要创建一个MyApplication继承Application,实现attachBaseContext()和onCreate方法,因为程序启动后会先调用Application,之后在调用Activity。

在attachBaseContext()里解密数据释放源APK文件,使用反射加载APK然后替换ClassLoader,代码如下。

到这里为止已经实现了一个简单的壳了,但是一些APP会有Application类,这时还需要替换源程序的Application,代码如下。

至此实现了一个壳的雏形,测试一下效果。

加密源APK生成新dex文件


把新dex文件放入壳Apk中,重新签名,安装程序,启动程序,通过log可以看见执行了源APK中的代码。


再说一下实现过程中发现的一些问题,在java层进行解密及动态加载过程很容易被反编译,反编译后的伪代码与源码几乎没差,可以清楚的看出壳的运行逻辑,同时还会释放出源apk文件存放在本地。这时需要把关键代码移植到Native层,同时在内存中加载文件,这里就不多说了可以看代码,为了偷懒部分代码还是在java实现,完全可以把attachBaseContext和onCreate用native实现。

So加固

一)通过加密节的方式加密

解密程序流程:通过__attribute__((section(".mytext")))属性将要加密的函数定义在.mytext节中,实现解密函数,添加__attribute__((constructor))属性,将代码定义在.init_array段。

 解密函数的实现很简单,这里首先在getLibAddr函数中通过/proc/<pid>/maps文件获得加载的so文件路径和基址,通过ehdr->e_entry这个变量获取到被加密节的大小,ehdr->e_shoff获得加密节的地址偏移解密数据。

代码如下:

加密程序流程:解析elf结构,从文件头读取section偏移shoff,shnum和shstrtab,读取shstrtab中的字符串,从shoff读取section header,通过pShdr->sh_name读取节表名比较是否自定义节表名,通过pShdr->sh_offset pShdr->sh_size读取节表大小以及内容进行加密,修改section字段中的e_shoff为pShdr->sh_addr,修改e_entry为pShdr->sh_size,写入文件。

关于修改文件头的说明:作为动态链接库,e_entry入口地址是无意义的,因为程序被加载时,设定的跳转地址是动态连接器的地址,这个字段是可以被作为数据填充的。so装载时,与链接视图没有关系,即e_shoff、e_shentsize、e_shnum和e_shstrndx这些字段是可以任意修改。

代码如下:

加密后Add函数如下


二)加密SO中指定函数


[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)

收藏
免费 11
支持
分享
打赏 + 10.00雪花
打赏次数 2 雪花 + 10.00
 
赞赏  orz1ruo   +5.00 2018/12/31
赞赏  junkboy   +5.00 2018/12/30
最新回复 (14)
雪    币: 11716
活跃值: (133)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
感谢分享
2018-12-30 18:53
3
雪    币: 11321
活跃值: (3374)
能力值: (RANK:520 )
在线值:
发帖
回帖
粉丝
3
感谢分享
2018-12-31 09:01
2
雪    币: 10941
活跃值: (4577)
能力值: ( LV12,RANK:404 )
在线值:
发帖
回帖
粉丝
4
mark,感谢分享,很有帮助
2018-12-31 12:17
1
雪    币: 2694
活跃值: (3795)
能力值: ( LV9,RANK:140 )
在线值:
发帖
回帖
粉丝
5
谢谢分享
2019-1-1 10:27
1
雪    币: 1738
活跃值: (2337)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
感谢分享
2019-1-1 17:39
1
雪    币: 856
活跃值: (400)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
感谢分享
2019-1-1 22:01
1
雪    币: 3429
活跃值: (1566)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
感谢分享
2019-1-2 09:53
1
雪    币: 0
活跃值: (1629)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
9
感谢分享
2019-1-2 09:57
1
雪    币: 15003
活跃值: (6213)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
10
学习学习
2019-1-4 11:28
0
雪    币: 15
活跃值: (57)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
11
跟着楼主练练
2019-1-4 21:36
0
雪    币: 21
活跃值: (17)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
12
谢谢分享
2019-1-11 17:35
0
雪    币: 2731
活跃值: (1651)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
13
2019-1-12 19:18
0
雪    币: 159
活跃值: (695)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
14
感谢分享,如果多一些描述性和的思路性的原理性的话语,理解起来会更棒。
2019-11-12 15:05
0
雪    币: 2914
活跃值: (4996)
能力值: ( LV8,RANK:130 )
在线值:
发帖
回帖
粉丝
15
大佬知道这句代码Application app = (Application) RefInvoke.invokeMethod("android.app.LoadedApk", "makeApplication", loadedApkInfo, new Class[]{boolean.class, Instrumentation.class}, new Object[]{false, null});得到的app是null是怎么回事吗?然后在app.onCreate();这里执行到就闪退了
2020-3-2 16:58
0
游客
登录 | 注册 方可回帖
返回
//