首页
论坛
课程
招聘
[逆向分析] [原创]另类的dex代码保护方法
2021-4-27 14:45 4527

[逆向分析] [原创]另类的dex代码保护方法

2021-4-27 14:45
4527

这是之前在分析一款Android APP,具体功能是什么不重要,发现它采用了一种另类的代码保护方法,虽然原理不是很复杂,但中间反反复复折腾了好几天,在此把研究过程分享给大家。

1. 初次见面

运行这款APP,提示会申请设备管理器权限,自然想到程序代码中应该有类继承自AccessibilityService类,并重载了onAccessibilityEvent方法,反编译dex代码,发现是这样的:
图片描述
图1
第一感觉是java层代码native化了,换句话说,本来应该在java层实现的代码,放到了so库中通过c语言实现了(当时想可能是通过c反射调用java层API来实现)。把apk解压缩,找了一圈,竟然没有这样的so库!发现很多类代码初始化都会有这样的代码:
图片描述
图2
进一步跟踪发现程序调用,来到一个so库,这个so库负责恢复被保护的代码。具体调试和跟踪的过程不说了,直接公布答案。

2. 保护原理

这种代码保护简单概括成一句话,就是隐藏代码偏移。具体说呢,在dex文件里有一个字段记录着代码的偏移位置,代码保护把它修改为0,另有一个文件记录着真正的代码的偏移,在类的初始化过程中,调用native函数传入一个class和一个hash值(如图2),程序通过这两个参数在数据文件中搜索到正确的偏移,在运行时恢复。实际上,代码仍然保存在dex文件中。另外,被保护的方法属性被修改为native,方法属性也会在运行时修复。

3. 代码还原之路

还原代码看起来就不难了,把方法的native属性去掉(方法属性字段的某个bit位置零),把代码偏移重写到dex就ok了。

3.1. 直接修改dex文件

熟悉dex文件结构的朋友肯定知道LEB128数据格式,这种数据格式要求每个字节中的低7位表示数据,最高位为1表示后续还有数据,为0则表示没有数据了。dex文件的代码偏移就是LEB128数据格式(准确的说是ULEB128,无符号数据)。问题来了:代码偏移为0,字段占用1个字节,但实际的偏移通常要占用4字节。两个办法:一是中间插入3字节数据,二是不管其他的数据,直接覆盖后面3字节。由于dex文件数据结构的原因,插入3字节,使得诸多字段都要修改,工作量大不说,出现问题也不好定位。方法二是偷懒的办法,试过后发现几乎所有代码都不能反编译了。

3.2. 编译反编译工具dex2jar

dex反编译有很多工具,dex2jar是常用的一个,并且是开源的。思路是修改其源码:当反编译需要修正的类时,从dex文件中读取出来的代码偏移为0,这时在后面修改dex2jar代码,把保存dex代码偏移的变量赋值为正确的偏移值,这样就可以反编译出被保护的代码了。
根据dex2jar在SourceForge的介绍(https://sourceforge.net/p/dex2jar/wiki/BuildFromSource/),build方法有两种:通过Maven或Gradle编译工程。按照提示,Git clone工程代码,先按照Maven的方法编译。配好maven环境后,在工程的根目录下输入mvn clean package,编译出错了:
图片描述
图3
大致分析了一下,提示找不到的包和类,但其实都存在,目测是子过程之间的依赖配置不对。Google了一圈没有找到答案,翻了一遍GitHub工程主页的Issues,发现也没人反馈问题,难道是Mac环境的问题?以前编译android4.4源码的时候,Mac环境就是官方不支持的,于是换了Ubuntu。接下来,装Ubuntu 14.4虚拟机,配置maven环境,git clone源码,mvn clean package,问题依旧!鄙人对maven诸多配置项不甚熟悉,所以先暂时放弃。
尝试通过Gradle编译,根据官网提示,在工程根目录下键入gradle clean distZip,编译报错:
图片描述
图4
这是找不到外部资源报错的,工程尝试通过图4中的4个URL寻找外部资源失败。手动访问这4个URL确实都失效了,不过尝试访问https://repo1.maven.org/maven2/com/google/android/tools/dx/时,发现下面有个1.7的目录,尝试修改报错的dex-tools子工程下的配置文件:
图片描述
图5
上图红框处原来是“23”,改成“1.7“貌似有些离谱,不过最终真的编译成功了!

3.3. 修改dex2jar源码

找到子工程dex-reader,修改DexFileReader类acceptMethod方法。插入代码如下图所示:
图片描述
图6
如前所述,先得通过二进制编辑器去掉方法的native属性(属性字段是定长2字节,所以不必考虑数据覆盖的问题),否则dex2jar依然不会输出正确的结果。用修改后的dex2jar反编译,代码就出来了。如下图所示:
图片描述


第五届安全开发者峰会(SDC 2021)议题征集正式开启!

收藏
点赞2
打赏
分享
最新回复 (5)
雪    币: 8284
活跃值: 活跃值 (2269)
能力值: (RANK:200 )
在线值:
发帖
回帖
粉丝
LowRebSwrd 活跃值 4 2021-4-29 10:23
2
0
强! 
雪    币: 8
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
万里星河 活跃值 2021-4-29 12:01
3
0
厉害 可是像这样的 直接脱壳不是更方便
雪    币: 624
活跃值: 活跃值 (399)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
eastmaster 活跃值 2021-4-29 14:07
4
0
万里星河 厉害 可是像这样的 直接脱壳不是更方便
不是常规壳的逻辑
雪    币: 219
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
ba1yu2 活跃值 2021-4-30 18:02
5
0
请问可以提供一下样本吗
雪    币: 624
活跃值: 活跃值 (399)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
eastmaster 活跃值 2021-5-6 10:42
6
0
ba1yu2 请问可以提供一下样本吗
黑样本,不大方便发哈
游客
登录 | 注册 方可回帖
返回