ApkPecker自动化DEX-VMP脱壳功能全新上线


by 腾讯科恩实验室

腾讯安全科恩实验室自研的面向攻击面的Android应用自动化检测系统ApkPecker,正式上线自动化APK脱壳能力!线上ApkPecker系统提供高成功率的自动化脱壳服务,扩大漏洞扫描的覆盖面。限时扫码加入ApkPecker技术交流群,体验更高效的Android应用检测服务。

背景

为避免Android应用程序被轻易逆向暴露程序逻辑,Android平台APP加固技术也不断发展。加固服务能一定程度提高Android应用程序被逆向的难度,但仍无法避免和防止应用程序自身的安全问题和漏洞。除此之外,恶意程序还能利用加固服务隐藏恶意行为逻辑。因此,通过研究Android应用程序通用自动脱壳方法,能客观评估加固的有效性,还能及时发现应用本身存在的安全问题,并为恶意应用程序的发现扫清障碍。
经过多年的发展和对抗,Android平台APP加固技术已经相当成熟,防护粒度从DEX整体加密开始,细化到方法级别和指令级别,不断增加逆向分析的难度和工作量来保护客户端代码。相应的,针对这些加固技术,也出现了很多通用的脱壳方法和工具。这些工具通过内存dump在运行时获取壳释放的APP原始代码,来实现DEX层通用脱壳。然而厂商也发展出了定制化的加固方法来对抗通用脱壳,DEX虚拟化(DEX-VMP)便是其中之一。DEX虚拟化加固使得常见的基于内存dump的通用脱壳工具不再适用,增加了自动化分析的难度。为帮助厂商进一步提升应用安全检测覆盖面,ApkPecker推出自动化DEX-VMP脱壳服务。

DEX-VMP实现原理

DEX-VMP是一种基于虚拟机的DEX加固方案。DEX-VMP在加固阶段将App受保护的方法native化,抽取原始字节码并转换成自定义格式的字节码;在运行阶段,DEX-VMP使用自定义的Dalvik解释器来解释执行转换后的自定义字节码。表1展示了DEX-VMP加固前后的代码对比。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// DEX-VMP 加固前App代码
class Foo{
void onCreate(){
super.onCreate();
}
}

// DEX-VMP加固后App代码
class Foo {
void onCreate(){
vm.v(0);
}
}

//厂商解释器入口函数
class Vm {
void native v(int methodId);
}

图1展示了正常Dalvik代码和DEX-VMP保护的代码在执行时的区别。正常Dalvik代码由Android ART运行时执行,而被DEX-VMP Native化的方法在运行时通过JNI进入厂商解释器入口。厂商解释器可以进行各种定制化修改,例如使用自定义的Opcode映射表和指令格式,增加还原难度。DEX-VMP在厂商解释器中解释执行自定义的字节码,不释放原始Dalvik字节码,从而能够对抗通用脱壳技术。

DEX-VMP自动化脱壳难点

  1. 如何找到所有的自定义字节码?
    通用脱壳可以通过主动调用App的所有方法,在壳释放出Dalvik代码后,在ART内部获得所有方法的字节码。然而DEX-VMP使用了自定义的解释器,很难使用通用的方法获得其字节码。
  2. 如何将自定义字节码翻译成标准Dalvik
    厂商自定义的解释器对字节码进行了加密和转换。例如,解释器在执行前解密字节码,字节码中的opcode、常量索引等在加固时也被转换成内部对应的opcode和索引。同时,厂商的加固服务会周期性更换这些转换关系,增加还原的难度。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
while (1) {
uint8_t* pc = vm_ctx->pc;
uint8_t opcode_xor_key = vm_ctx->xor_key;
uint8_t opcode = opcode_decrypt(*pc ^ opcode_xor_key);
switch (opcode & 0xFF) {
case 0x00: // add-int vAA,vBB,vCC
uint32_t AA = read_uint8(pc+1) ^ 0x12;//decrypt operand
uint32_t BB = read_uint8(pc+2) ^ 0x34;
uint32_t CC = read_uint8(pc+3) ^ 0x56;

int32_t vBB = vm_ctx->registers[BB];
int32_t vCC = vm_ctx->registers[CC];
vm_ctx->registers[AA] = (uint32_t)(vBB + vCC);
pc += 4; break;
case 0x01: // const-string vAA,string@BBBB
uint32_t AA = read_uint8(pc+1) ^ 0xab
//decrypt string index
uint32_t BBBB = read_uint32(pc+2) ^ 0xcdef;
jstring jstr = create_string_from_internal_index(BBBB);
vm_ctx->registers[AA] = (uint32_t)jstr;
pc+=4;
break;
... // other handlers
}

表2展示了一个自定义Dalvik解释器的伪代码片段。pc指向待执行的指令,xor_key用来在执行前解密指令的opcode,registers数组代表寄存器。该例子中opcode 0x00对应的语义是add-int,0x01对应const-string,与Dalvik标准中opcode编号不同,并且使用了自定义的字符串索引,而不是DEX常量池中的字符串索引。
为了将自定义的字节码转换成符合Dalvik标准的字节码,需要从解释器中提取字节码的解密逻辑和自定义的常量池数据,同时也要需要识别opcode handler的语义。Dalvik 标准中有两百多条Opcode,人工从厂商解释器的二进制代码中识别这些handler对应的语义十分繁琐。

ApkPecker的自动化DEX-VMP脱壳服务

腾讯安全科恩实验室研发的ApkPecker,是一款全自动的Android应用漏洞扫描工具,能够输出高质量漏洞扫描报告,提供高品质漏洞信息以及漏洞触发完整路径,精准定位漏洞并提供修复建议,帮助移动安全人员解决现有痛点,提升应用安全性。 在现有漏洞扫描的基础上,ApkPecker提供了自动化APK脱壳服务,针对市面主流加固厂商,以高成功率自动化脱壳,为移动安全分析人员解决了障碍,扩大漏洞扫描的覆盖面。

DEX-VMP自动化脱壳方案

ApkPecker支持恢复常见的DEX加密和指令抽取等类型的加固,同时,针对厂商的DEX虚拟化保护(DEX-VMP), ApkPecker也进行了针对性脱壳和恢复。
ApkPecker在确定厂商字节码格式的基础上,通过AI学习厂商解释器二进制中opcode handler的运行时行为,从而自动化恢复出厂商解释器的opcode语义,还原出原始Dalvik字节码,并重写DEX文件。ApkPekcer的脱壳方案解决了opcode handler识别的难点,自动化还原被DEX-VMP保护的代码,提高了脱壳的完整度和自动化程度。图2展示了ApkPecker对指令抽取和DEX-VMP的脱壳效果。

脱壳覆盖面与成功率

整体来看,ApkPecker的脱壳能力可以通过以下几个关键指标体现:
● 支持的加固方法 :DEX加密,指令抽取,DEX虚拟化
● 大规模测试下的脱壳成功率 >= 85%
ApkPecker脱壳功能适配主流的DEX加密、指令抽取和DEX虚拟化等加固方法。我们在主流App市场的测试发现,超过60%的的加固App受到不同程度的DEX-VMP保护,而ApkPecker对加固App的脱壳成功率高于85%。

交流和体验

限时扫描二维码进入ApkPecker技术交流群,获取更多脱壳以及应用自动化检测技术资料,更有不定期福利放送。
浏览器中体验面向攻击面的Android应用自动化检测系统ApkPecker:ApkPecker在线地址

介绍视频