首页
论坛
课程
招聘
[原创]某Android DEX vmp加固逆向分析
2017-9-17 12:18 20504

[原创]某Android DEX vmp加固逆向分析

2017-9-17 12:18
20504

0x00 背景

最近无意中看到某家厂商的免费Android DEX 虚拟机壳,一时兴起,就上传了一个简单样本加固之后进行分析。本文只是对该DEX虚拟机的执行过程进行了简单分析,并没有提供对其进行修复的方案,原因当然是本人也不会咯。

0x01前期分析

测试原样本和加固样本经过jeb反编译,对比如下图所示

                                       未进行加固  


                                        进行加固之后反编译效果

可以看到加固之后部分函数已经成了native 了,抱着侥幸的心理,心想免费版本会不会是个假的vmp加固。重新重构还原DEX之后,发现效果还是如上图所示。看来vmp已经成了加固厂商的最低标准了。下面就开始分析了,lib目录下面有个名称为libx3g.so的文件。拖入IDA,效果如下图所示,发现并不能正常反编译,看来是做处理了。那就试着dump+修复这个so了。


0x02 so的dump及修复

1. 运行应用,IDA直接attach上去,找到libx3g.so在内存的起始地址和结束地址,    idc脚本dump下libx3g.so。
    

 2. 修复so。用010解析dump下来的so文件。 

    

   

首先将原apk的libx3g.so 文件的Dynamic Segment中的data部分拷贝到dump下来的so对应位置。 然后将第二个Loadable Segement 的p_offset 值等于p_vaddr,并且计算第二个Loadable Segement 的p_vaddr+p_memsz,最后将其结果赋给第一个Loadable Segement的p_filesz和p_memsz.最终的修复的so文件如下:


 此时IDA就可以正常打开so文件了。如下图所示,看来免费版本连动态注册都省了,很容易一眼看出被虚拟执行的onCreate函数。该函数只是简单混淆了下,导致一些函数的参数伪 C不是很清楚。但是总体来说,还是比较好分析的。下面根据未加固的原包与加固之后的指令进行对比,看下该虚拟机是如何执行的。


0x03  DEX虚拟机执行过程

  下面以onCreate函数为例。第一张图为未进行加固之后的反编译效果。第二张图为加固之后native层该函数的伪C代码。

   

   

  本来以为该vmp加固应该也会在so中一条一条的读加密替换之后的smali指令,然后逐句解释执行。   But 不是啊,它直接就翻译了。直接通过嵌套的if 把指令给翻执行            

  了。。。。。。。。。。。。   不知道还有没有其它哪家加固厂商也是这样做的。

  还是对比下几条指令,看下它的执行过程。 

  1.  方法调用指令:

invoke-super Activity->onCreate(Bundle)V, p0, p1
虚拟执行:
sub_2146(v4, &a2, &a3, (int)"android/app/Activity")
sub_1064(v4, v5, a2)
由于这里利用push pop指令做了点混淆。在调用sub_2146函数之前,将“(Landroid/os/Bundle;)V”字符串和“android/app/Activity”压人到栈中了,sub_2146函数会使用这两个值。

sub_2146的函数实现如下,对应此条指令的作用是通过JNI提供的FindClass函数先获取“android/app/Activity”类的jclass,然后调用GetMethodID函数获得jmethodid结构体。

sub_1064通过sub_2146返回的jmethodid,利用JNI提供的CallNonvirtualVoidMethodV函数对java层的“android/app/Activity”类 的onCreate方法进行调用。

 
这样就完成了  invoke-super Activity->onCreate(Bundle)V, p0, p1  这条smali指令的执行。

2. 赋值指令

对应smali指令: 
const                    v2, 0x7F080001
invoke-virtual MainActivity->findViewById(I)View, p0, v2
move-result-object      v2
check-cast              v2, TextView
iput-object             v2, p0, MainActivity->factor:TextView
对应java代码是:  
this.factor=this.findViewById(2131230721);
大致对应虚拟机执行代码:
sub_2146(v4, &v44, &v22, (int)"com/example/vmptest/MainActivity") )
v6 = sub_10E8(v4, v5, v22, 2131230721); 
sub_223C(v4, &v44, &v32, (int)"com/example/vmptest/MainActivity")
(*v4)->SetObjectField)(v4, v5, v32, v6);
其中   sub_2146是获取findViewById 方法。 sub_10E8 调用findViewById方法。sub_223c获取类成员变量factor,也就是通过jni提供的GetFieldID方法获取。最后调用SetObjectField方法对类成员factor赋值。

3. 循环语句
java代码:

对应虚拟机执行的指令:

0x04  总结

这个dex vmp的方案还是与其它厂商有区别的,它直接将原始的smali代码翻译成C层的代码了,没有抽取原始的smali代码。当然,由于这个没有做啥混淆,导致so的代码逻辑还是比较容易看明白的。


看雪招聘平台创建简历并且简历完整度达到90%及以上可获得500看雪币~

上传的附件:
收藏
点赞2
打赏
分享
打赏 + 1.00雪花
打赏次数 1 雪花 + 1.00
 
赞赏  ExiaHan   +1.00 2017/09/20
最新回复 (31)
雪    币: 48
活跃值: 活跃值 (19)
能力值: ( LV2,RANK:15 )
在线值:
发帖
回帖
粉丝
bujianshi 活跃值 2017-9-17 13:21
2
0
顶象?666
雪    币: 4823
活跃值: 活跃值 (5066)
能力值: ( LV17,RANK:787 )
在线值:
发帖
回帖
粉丝
无名侠 活跃值 12 2017-9-17 15:39
3
0
学习了!!!!!
雪    币: 42
活跃值: 活跃值 (72)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
欧阳峰峰 活跃值 2017-9-17 16:04
4
0
顶象的,666
雪    币: 2830
活跃值: 活跃值 (714)
能力值: ( LV12,RANK:215 )
在线值:
发帖
回帖
粉丝
scxc 活跃值 3 2017-9-17 20:04
5
0
顶一下。楼主是之前写Xdex的作者。
雪    币: 46
活跃值: 活跃值 (41)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
TinyNiko 活跃值 1 2017-9-18 00:17
6
0
必须支持我大sherry
雪    币: 0
活跃值: 活跃值 (796)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
tangsilian 活跃值 2017-9-18 00:37
7
0
灵儿强啊。膜拜
雪    币: 53
活跃值: 活跃值 (66)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
rozfex 活跃值 2017-9-18 10:03
8
0
强啊    灵儿
雪    币: 1171
活跃值: 活跃值 (190)
能力值: ( LV13,RANK:360 )
在线值:
发帖
回帖
粉丝
Ericky 活跃值 6 2017-9-18 11:34
9
0
强大  过来顶一下大M 
雪    币: 3252
活跃值: 活跃值 (1021)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
Umiade 活跃值 2017-9-18 12:52
10
0
顶一手,感谢分享
雪    币: 456
活跃值: 活跃值 (199)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
ChengQing 活跃值 2017-9-18 13:57
11
0
Mark
雪    币: 72
活跃值: 活跃值 (39)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
黑炭BC 活跃值 2017-9-18 16:18
12
0
膜拜  大佬
雪    币: 202
活跃值: 活跃值 (10)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
RealityAbb 活跃值 2017-9-18 18:07
13
0
大佬牛逼。但是,这个所谓的VMP,其实是做的java到c的自动翻译?和我理解的VMP通过自定义指令集来执行的效果不一样啊~
雪    币: 95
活跃值: 活跃值 (307)
能力值: ( LV5,RANK:70 )
在线值:
发帖
回帖
粉丝
sherrydl 活跃值 1 2017-9-18 18:12
14
0
RealityAbb 大佬牛逼。但是,这个所谓的VMP,其实是做的java到c的自动翻译?和我理解的VMP通过自定义指令集来执行的效果不一样啊~
两种都有优劣吧。这种自动翻译能力还是挺佩服的啊
雪    币: 0
活跃值: 活跃值 (796)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
tangsilian 活跃值 2017-9-18 19:33
15
0
程序头:
  Type           Offset           VirtAddr         PhysAddr          FileSiz      MemSiz     Flg    Align
  LOAD           0x000000 0x00000000  0x00000000 0x02fdc    0x02fdc    R E    0x1000
  LOAD           0x003e70  0x00006e70   0x00006e70  0x00194   0x001b4    RW    0x1000

dump的so修复那一块  我没弄明白  

”然后将第二个Loadable Segement 的p_offset 值等于p_vaddr,并且计算第二个Loadable Segement 的p_vaddr+p_memsz,最后将其结果赋给第一个Loadable Segement的p_filesz和p_memsz.“

为什么第二个Loadable Segement(RW_)的p_offset是等于p_vaddr的??

还有第一个Loadable Segement(R_X)的p_filesz为什么是等于第二个的p_vaddr+p_memsz??

越南媳妇快来答疑解惑~
雪    币: 262
活跃值: 活跃值 (455)
能力值: ( LV3,RANK:35 )
在线值:
发帖
回帖
粉丝
lfyyy 活跃值 2017-9-19 11:55
16
0
雪    币: 763
活跃值: 活跃值 (2462)
能力值: ( LV8,RANK:120 )
在线值:
发帖
回帖
粉丝
葫芦娃 活跃值 1 2017-9-21 12:13
17
0
顶象之前好像是阿里出来的?
雪    币: 6817
活跃值: 活跃值 (153)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
聖blue 活跃值 2017-9-21 19:17
18
0
不错!!!!!!
雪    币: 402
活跃值: 活跃值 (23)
能力值: ( LV6,RANK:90 )
在线值:
发帖
回帖
粉丝
星星当空照 活跃值 2017-9-21 21:31
19
0
厉害了
雪    币: 134
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
Mattermon 活跃值 2017-9-22 15:07
20
0
终于确定之前看得一些so是vmp的了  [笑cry]
雪    币: 3503
活跃值: 活跃值 (610)
能力值: ( LV6,RANK:80 )
在线值:
发帖
回帖
粉丝
smartdon 活跃值 1 2017-10-8 16:08
21
0
厉害厉害
雪    币: 227
活跃值: 活跃值 (192)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
sky科 活跃值 2017-10-8 17:27
22
0
精彩  !!
雪    币: 80
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
zhengsidie 活跃值 2017-10-8 17:30
23
0
学习了
雪    币: 331
活跃值: 活跃值 (57)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
金箍棒 活跃值 2017-10-10 18:08
24
0
雪    币:
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
smallkay 活跃值 2017-10-14 15:53
25
0
游客
登录 | 注册 方可回帖
返回