首页
社区
课程
招聘
[原创]检测Android虚拟机的方法和代码实现
发表于: 2018-4-4 22:17 35304

[原创]检测Android虚拟机的方法和代码实现

2018-4-4 22:17
35304

刚刚看了一些关于Detect Android Emulator的开源项目/文章/论文, 我看的这些其实都是13年14年提出的方法, 方法里大多是检测一些环境属性, 检查一些文件这样, 但实际上检测的思路并不局限于此. 有的是很直接了当去检测qemu, 而其它的方法则是旁敲侧击比如检测adb, 检测ptrace之类的. 思路也很灵活. 最后看到有提出通过利用QEMU这样的模拟CPU与物理CPU之间的实际差异(任务调度差异), 模拟传感器和物理传感器的差异, 缓存的差异等方法来检测. 相比检测环境属性, 检测效果会提升很多.

下面我就列出各个资料中所提出的一些方法/思路/代码供大家交流学习.

这些都是基于一些经验和特征来比对的属性, 这里的属性以及之后的一些文件呀属性啊之类的我就不再多作解释.

以下是对应的c++代码

这里我的描述可能并不准确, 因为并没有找到相关的资料. 我只能以自己的理解来解释一下:

SIGTRAP是调试器设置断点时发生的信号, 在nexus5或一加手机等大多数手机都可以触发. SIGBUS则是在一个总线错误, 指针也许访问了一个有效地址, 但总线会因为数据未对齐等原因无法使用, 在nexus4手机上可以触发. 而bkpt则是arm的断点指令, 这是曾经qemu被提出来的一个issue, qemu会因为SIGSEGV信号而崩溃, 作者想利用这个崩溃来检测qemu. 如果程序没有正常退出或被冻结, 那么就可以认定很可能是在模拟器里.

这个其实是用于检测当前操作到底是用户还是脚本在要求应用执行.

这个方法是用来检测调试, 判断是否有调试器连接.

这个方法是通过检查/proc/self/statusTracerPid项, 这个项在没有跟踪的时候默认为0, 当有程序在跟踪时会修改为对应的pid. 因此如果TracerPid不等于0, 那么就可以认为是在模拟器环境.

这个方法是通过读取/proc/net/tcp的信息来判断是否存在adb. 比如真机的的信息为0: 4604D20A:B512 A3D13AD8..., 而模拟器上的对应信息就是0: 00000000:0016 00000000:0000, 因为adb通常是反射到0.0.0.0这个ip上, 虽然端口有可能改变, 但确实是可行的.

这个比较单纯了. 就是通过检测包名, 检测Taint类来判断是否安装有TaintDroid这个污点分析工具. 另外也还可以检测TaintDroid的一些成员变量.

检测是否存在eth0网卡.

手机上配备了各式各样的传感器, 但它们实质上都是基于从环境收集的信息输出值, 因此想要模拟传感器是非常具有挑战性的. 这些传感器为识别手机和模拟器提供了新的机会.

比如在论文Rage Against the Virtual Machine: Hindering Dynamic Analysis of Android Malware中, 作者对Android模拟器的加速器进行测试, 作者发现Android模拟器上的传感器会在相同的时间间隔内(观测结果是0.8s, 标准偏差为0.003043)产生相同的值. 显然对于现实世界的传感器, 这是不可能的.

图片描述

于是我们可以先注册一个传感器监听器, 如果注册失败, 就可能是在模拟器中(排除实际设备不支持传感器的可能性). 如果注册成功, 那么检查onSensorChanged回调方法, 如果在连续调用这个方法的过程所观察到的传感器值或时间间隔相同, 那么就可以认定是在模拟器环境中.

出于性能优化的原因, QEMU在每次执行指令时都不会主动更新程序计数器(PC), 由于翻译指令在本地执行, 而增加PC需要额外的指令带来开销. 所以QEMU只在执行那些从线性执行过程里中断的指令(例如分支指令)时才会更新程序计数器. 这也就导致在执行一些基本块的期间如果发生了调度事件, 那么也没有办法恢复调度前的PC, 也是出于这个原因, QEMU仅在执行基本块后才发生调度事件, 绝不会执行的过程中发生.

图片描述

如上图, 因为调度可能在任意时间发生, 所以在非模拟器环境下, 会观察到大量的调度点. 而在模拟器环境中, 只能看到特定的调度点.

因为QEMU会跟踪代码页的改动, 于是存在一种新颖的方法来检测QEMU--使用自修改代码(Self-Modifying Code, SMC)引起模拟器和实际设备之间的执行流变化.
图片描述

ARM处理器包含有两个不同的缓冲Cache, 一个用于指令访问(I-Cache), 而另一个用于数据访问(D-Cache). 但如ARM这样的哈佛架构并不能保证I-Cache和D-Cache之间的一致性. 因此CPU有可能在新代码片已经写入主存后执行旧的代码片(也许是无效的).

这个问题可以通过强迫两个缓存一致得到解决, 这有两步:

在原生Android代码中, 可以使用cacheflush函数, 该函数通过系统调用完成上述操作.

图片描述
识别代码, 使用一个具有读写权限的内存, 其中包含两个不同函数f1和f2的代码, 这两个函数其实很简单, 只是单纯在一个全局字符串变量的末尾附加各自的函数名称, 这两个函数会在循环里交错执行, 这样就可以通过结果的字符串推断出函数调用序列.

如前所述, 我们调用cacheflush来同步缓存. 在实际设备和模拟器上运行代码得到的结果是相同的--每次执行都会产生一致的函数调用序列.

接下来我们移除调用cacheflush, 执行相同的操作. 那么在实际设备中, 我们每次运行都会观察到一个随机的函数调用序列, 这也如前所述的那样, 因为I-Cache可能包含一些旧指令, 每次调用的时候缓存都不同步所导致的.

而模拟器环境却不会发生这样的情况, 而且函数调用序列会跟之前没有移除cacheflush时完全相同, 也就是每次函数调用前缓存都是一致的. 这是因为QEMU会跟踪代码页上的修改, 并确保生成的代码始终与内存中的目标指令匹配, 因此QEMU会放弃之前版本的代码翻译并重新生成新代码.

看到这里会不会已经觉得检测方法够多了. 可是我还只是看了13年14年的资料. 有关近几年的资料还未涉及.

最后我就把这些检测方法整合在一张思维导图(见附件)里供大家一览, 欢迎大家和我交流带带我

 
 
 
 
 
 
 
 

[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

最后于 2019-2-2 14:19 被kanxue编辑 ,原因:
上传的附件:
收藏
免费 3
支持
分享
最新回复 (28)
雪    币: 916
活跃值: (3434)
能力值: ( LV8,RANK:120 )
在线值:
发帖
回帖
粉丝
2
66666,膜拜大佬
2018-4-4 23:43
1
雪    币: 23
活跃值: (37)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
膜拜,呕心沥血的总结小厂开发用不了这么详细的
2018-4-7 21:15
0
雪    币: 185
活跃值: (486)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
谢谢分享!
2018-4-8 09:16
0
雪    币: 1260
活跃值: (2168)
能力值: ( LV5,RANK:75 )
在线值:
发帖
回帖
粉丝
5
好文,赞
2018-4-8 09:50
0
雪    币: 389
活跃值: (565)
能力值: ( LV7,RANK:110 )
在线值:
发帖
回帖
粉丝
6
膜拜
2018-4-8 09:58
0
雪    币: 1601
活跃值: (5159)
能力值: ( LV6,RANK:80 )
在线值:
发帖
回帖
粉丝
7
2018-4-8 10:11
0
雪    币: 43
活跃值: (31)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
膜拜大佬  mark
2018-4-8 10:17
0
雪    币: 249
活跃值: (72)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
9
膜拜
2018-4-8 10:31
0
雪    币: 20
活跃值: (210)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
10
月莫
2018-4-8 10:50
0
雪    币: 220
活跃值: (19)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
11
好像没有一个绝对靠谱的手段,看数盟,同盾  都声称自己100%识别,不知道怎么做到的,文章中提到的各种手段貌似都有些缺陷,不知道题主  用的是哪种?
2018-4-8 11:04
0
雪    币: 1535
活跃值: (695)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
12
666啊,大佬们太勤快了,我得赶紧开干了,偷个懒的功夫,大佬又一篇好文出来了
2018-4-8 14:28
0
雪    币: 93
活跃值: (136)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
13
基于smc的检测,x86架构手机会误报吧?
2018-4-8 14:45
0
雪    币: 220
活跃值: (19)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
14
gugubupt 基于smc的检测,x86架构手机会误报吧?
非x86的也不完全正确
2018-4-8 19:37
0
雪    币: 20
活跃值: (105)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
15
马克  正好需要过模拟器检查
2018-4-8 21:38
0
雪    币: 233
活跃值: (25)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
16
谢谢总结和分析
2018-4-9 18:22
0
雪    币: 1
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
17
基于qemu?貌似现在模拟器都是通过vbox了,估计在一些细节上会有些差异吧,不过可以学习下
2018-4-9 18:47
0
雪    币: 6
活跃值: (1146)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
18
N多APP已经在copy  on  it  的路上了
2018-4-11 10:40
0
雪    币:
活跃值: (63)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
19
膜拜
2018-5-18 17:56
0
雪    币: 85
活跃值: (101)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
20
想请教下大佬,SMC检测,qemu任务调度,断点(bkpt)检测有没有绕过的一些手段?我琢磨了好久没想出办法来。。。
2018-5-28 22:31
0
雪    币: 102
活跃值: (2050)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
21
mark........
2018-6-16 17:10
0
雪    币: 210
活跃值: (50)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
22
mark
2018-6-21 16:15
0
雪    币: 2714
活跃值: (1611)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
24
整理的很详细,很不错的分享
2019-2-3 14:53
0
雪    币: 1
活跃值: (883)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
25
还好
最后于 2019-10-21 14:11 被zoukaiping编辑 ,原因:
2019-2-10 09:41
0
游客
登录 | 注册 方可回帖
返回
//