用机器学习检测Android恶意代码


0x00 前言


前段时间在乌云知识库上面看到一篇比较有意思的文章利用机器学习进行恶意代码分类。这篇文章对Kaggle上的一个恶意代码分类比赛中冠军队伍所采用的方法进行了介绍,展现了机器学习在安全领域的应用与潜力。但是这个比赛的主题是恶意代码的分类,没有进一步实现恶意代码的检测;其次比赛的代码只是针对Windows平台的PE格式,缺少对移动应用的研究。受此启发,尝试利用机器学习方法在Android平台对恶意代码进行检测,最终得到了一定的检测效果。

0x01 背景知识


安卓恶意代码检测方法

目前恶意软件检测方法主要有基于特征代码(signature-based)的检测方法和基于行为(behavior-based)的检测方法。基于特征代码的检测方法,通过检测文件是否拥有已知恶意软件的特征代码(如一段特殊代码或字符串)来判断其是否为恶意软件。它的优点是快速、准确率高、误报率低,但是无法检测未知的恶意代码。基于行为的检测方法,则依靠监视程序的行为与已知的恶意行为模式进行匹配,以此判断目标文件是否具备恶意特征。它的优点可以检测未知的恶意代码变种,缺点是误报率较高。

基于行为的分析方法又分为动态分析方法和静态分析方法。动态分析方法是指利用“沙盒或模拟器”来模拟运行程序,通过监控或者拦截的方式分析程序运行的行为,但是很消耗资源和时间。静态分析方法则是通过逆向手段抽取程序的特征,分析其中指令序列等。本文采用静态分析的方法进恶意行代码检测。

Weka与机器学习的分类算法

Weka(Waikato Environment for Knowledge Analysis),是一款免费的,非商业化基于JAVA环境下开源的机器学习(machine learning)以及数据挖掘(data minining)软件。Weka存储数据的格式是ARFF(Attribute-Relation File Format)文件,是一种ASCII文本文件。本文就是将特征数据生成ARFF格式的文件,利用Weka自带的分类算法进行数据训练与模型测试。

机器学习中分为有监督学习与无监督学习。有监督学习就是根据训练集,用学习算法学习出一个模型,然后可以用测试集对模型进行评估准确度和性能。分类算法属于有监督学习,需要先建立模型。常见的分类算法有:随机森林(Random Forest)支持向量机(SVM)等。

APK的基本格式

Wikipedia上面有APK(Android application package)的介绍。

APK文件格式是一种基于ZIP的格式,它与JAR文件的构造方式相似。它的互联网媒体类型是application/vnd.android.package-archive;

一个APK文件通常包含以下文件:

  • classes.dex: Dalvik字节码,可被Dalvik虚拟机执行。
  • AndroidManifest.xml: 一个的Android清单文件,用于描述该应用程序的名字、版本号、所需权限、注册的服务、链接的其他应用程序。该文件使用XML文件格式。
  • META-INF 文件夹: 下面有3个文件
    • MANIFEST.MF: 清单信息
    • CERT.RSA: 保存应用程序的证书和授权信息
    • CERT.SF: 保存SHA-1信息资源列表
  • res: APK所需要的资源文件夹
  • assets: 不需编译的原始资源文件目录
  • resources.arsc:编译后的二进制资源文件
  • lib:库文件目录

所有的文件中需要重点注意的是classes.dex,安卓的执行代码被编译后封装在这个文件中。

Dalvik虚拟机与反汇编

区别与JAVA虚拟机(JVM),安卓的虚拟机称为Dalvik虚拟机(DVM)。Java虚拟机运行的是Java字节码,Dalvik虚拟机运行的是Dalvik字节码。Java虚拟机基于栈架构,Dalvik虚拟机基于寄存器架构。

DVM拥有专属的DEX可执行文件格式和指令集代码。smalibaksmali则是针对DEX执行文件格式的汇编器和反汇编器,反汇编后DEX 文件会产生.smali 后缀的代码文件,smali代码拥有特定的格式与语法,smali语言是对Dalvik 虚拟机字节码的一种解释。

apktool工具是在smali工具的基础上进行封装和改进的,除了对DEX文件的汇编和反汇编功能外,还可以对APK 中已编译成二进制的资源文件进行反编译和重新编译。本文直接使用apktool工具来反汇编APK文件,而不是使用smali和baksmali工具。

java -jar apktool.jar d   D:\drebin\The_Drebin_Dataset\set\apk\DroidKungFu\xyz.apk

命令执行成功会在out 目录下产生如下所示的一级目录结构:

  • AndroidManifest.xml 配置文件
  • apktool.yml 反编译生成的文件,供apktool使用
  • assets/ 不需反编译的资源文件目录
  • lib/ 不需反编译的库文件目录
  • res/ 反编译后的资源文件目录
  • smali/ 反编译生成的smali 源码文件目录

其中,smali目录结构对应着原始的java源码src目录。

0x02 特征工程


Dalvik指令的分类与描述

Smali是对DVM字节码的一种解释,虽然不是官方标准语言,但所有语句都遵循一套语法规范。Dalvik opcodes的详细说明可以参考这篇文章http://pallergabor.uw.hu/androidblog/dalvik_opcodes.html,里面详细列举了Dalvik Opcode 的含义及用法、例子。

由于Dalvik指令有两百多条,对此需要进行了分类与精简,去掉了无关的指令,只留下了M、R、G、I、T、P、V七大类核心的指令集合,并且只保留操作码字段,去掉了参数。M、R、G、I、T、P、V七大类指令集合分别代表了移动、返回、跳转、判断、取数据、存数据、调用方法七种类型的指令,对指令进行了一次分类与描述。具体见下图:

OpCode N-gram

n-gram是自然语言处理领域的概念,但是它也经常用来处理恶意代码的分析。OpCode N-gram就是对指令操作码字段提取N-gram特征,n可以取值为2,3,4等。对一个smali格式的汇编文件的OpCode N-gram如下图所示:

0x03 系统设计与实现


整个系统分两大部分:建立恶意代码检测模型、测试恶意代码检测模型。

建立恶意代码检测模型如下所示:

用C++写了几个程序,对模型建立过程中的数据进行处理:

  • Total.exe:用于将单个apk反汇编后生成的工程目录中所有的smali文件进行汇总到一个文件
  • Simplication.exe:用于提取指令,并进行分类与描述
  • NgramGen.exe:用于生成指定N的N-gram序列
  • Arff.exe 统计每种特征的个数、生成适用于Weka的ARFF格式文件

测试恶意代码检测模型如下所示:

用机器学习工具Weka进行模型测试,检测模型的准确度。得到准确度高的模型可以用来预测未知Android代码是否为恶意代码。

0x04 实验评估


实验数据来源

实验数据分为恶意代码样本与正常代码样本。正常代码样本从安卓市场下载;恶意代码样本数据来源于Drebin项目,该病毒库收集了2010年8月至2012年10月178种共5560份APK样本文件。178种恶意代码家族的数据量分布如下图所示:

实验结果

本文采用540个恶意样本与560个良性样本,2个分类,一共合计1100个样本。分类算法采用随机森林,150棵决策树,n取3,进行十折交叉验证。

准确率如下图所示,1045个样本得到正确分类,5个样本分类失败。对于malware,其中TPR(真阳性率)=0.981,FPR(假阳性率)=0.08,Precision(查准率) =0.922

ROC曲线效果如下,AUC=0.9923
ROC(Receiver Operating Characteristic)曲线和AUC常被用来评价一个二值分类器(binary classifier)的优劣,具体关于AUC相关知识请参见https://en.wikipedia.org/wiki/Area_under_the_curve_(pharmacokinetics)

0x05 总结与展望


  • 总的来说,实验结果表明对恶意代码检测有较高的准确率
  • 如果可以再结合其他的特征,应该还可以进一步提高准确率
  • 除了使用随机森林算法,也可以尝试其他的分类算法的效果,比如支持向量机等

0x06 参考资料


评论

B

BaD 2016-03-07 11:18:07

好文,细细拜读下。

路人甲 2016-03-10 11:03:11

好文!我可以看一下你的源码么,我想试试用其他分类方法····

路人甲 2016-03-10 11:58:31

您好,非常不错,谢谢分享。能否分享一下C++处理数据的那几个程序?

R

rebeyond 2016-03-11 13:35:26

建议楼主用一个独立测试集再验证一下,仅仅基于测试样本,很容易过拟合。

S

saar 2016-03-16 19:38:52

这个样本库,能够提供一下么?

R

runner 2016-03-16 22:30:54

@rebeyond 我会再验证一下

R

runner 2016-03-16 22:33:21

@saar 样本库很大。你可以看一下这个网址: https://github.com/ashishb/android-security-awesome ,在SAMPLE SOURCES下面还有几个样本库

S

saar 2016-03-17 09:04:58

@runner 找了一些,但是都需要翻墙,下载没啥速度。

路人甲 2016-03-20 01:51:09

刚准备毕设做这个的 就发现这个文章了 666 先码一下

路人甲 2016-04-21 10:23:18

楼组,我是湖大的软件学院的研究生,论文是做病毒检测。我下了这个样本集,但解压要密码,楼组能说下解压密码吗?非常感谢![email protected]/* <![CDATA[ */!function(t,e,r,n,c,a,p){try{t=document.currentScript||function(){for(t=document.getElementsByTagName('script'),e=t.length;e--;)if(t[e].getAttribute('data-cfhash'))return t[e]}();if(t&&(c=t.previousSibling)){p=t.parentNode;if(a=c.getAttribute('data-cfemail')){for(e='',r='0x'+a.substr(0,2)|0,n=2;a.length-n;n+=2)e+='%'+('0'+('0x'+a.substr(n,2)^r).toString(16)).slice(-2);p.replaceChild(document.createTextNode(decodeURIComponent(e)),c)}p.removeChild(t)}}catch(u){}}()/* ]]> */

R

runner 2016-04-23 16:15:07

@踏雪 infected

R

runner 2016-04-25 13:41:38

正常APK样本可以从安卓应用商店爬,这里提供一个我写的爬虫:
https://github.com/runner-china/APK_Downloader

路人甲 2016-04-28 20:36:06

你好 楼主 ~~
仁慈大量又可爱的楼主能把你写的程序给我这个小白借鉴一下么~~深深的感激~
[email protected]/* <![CDATA[ */!function(t,e,r,n,c,a,p){try{t=document.currentScript||function(){for(t=document.getElementsByTagName('script'),e=t.length;e--;)if(t[e].getAttribute('data-cfhash'))return t[e]}();if(t&&(c=t.previousSibling)){p=t.parentNode;if(a=c.getAttribute('data-cfemail')){for(e='',r='0x'+a.substr(0,2)|0,n=2;a.length-n;n+=2)e+='%'+('0'+('0x'+a.substr(n,2)^r).toString(16)).slice(-2);p.replaceChild(document.createTextNode(decodeURIComponent(e)),c)}p.removeChild(t)}}catch(u){}}()/* ]]> */

路人甲 2016-04-28 20:38:11

楼主 ~~愿意付出代价 求楼主大神让小白参考下大神的思路~~求程序~~

路人甲 2016-04-29 09:56:43

@runner
楼主 我在你的github上follow了你~~能否留个联系方式~

路人甲 2016-04-30 15:49:12

@踏雪 问下 你知道在哪个网站上下样本 的账号密码么?谢谢~~

路人甲 2016-04-30 16:00:03

@runner 楼主你好 我在Drebin的网站上下载样本集 需要账号密码 能提供下么?谢谢~~

路人甲 2016-04-30 16:01:38

@踏雪 我加你qq了~非常期待你的帮助

M

meta 2016-05-08 17:39:19

楼主您好,我是做android恶意代码检测的,那个android的opcode是如何提取的,我看了pe的那个python代码对应到android的classes.dex是不一样的,希望能看看您提取opcode的代码,[email protected]/* <![CDATA[ */!function(t,e,r,n,c,a,p){try{t=document.currentScript||function(){for(t=document.getElementsByTagName('script'),e=t.length;e--;)if(t[e].getAttribute('data-cfhash'))return t[e]}();if(t&&(c=t.previousSibling)){p=t.parentNode;if(a=c.getAttribute('data-cfemail')){for(e='',r='0x'+a.substr(0,2)|0,n=2;a.length-n;n+=2)e+='%'+('0'+('0x'+a.substr(n,2)^r).toString(16)).slice(-2);p.replaceChild(document.createTextNode(decodeURIComponent(e)),c)}p.removeChild(t)}}catch(u){}}()/* ]]> */com. 谢谢

T

tian 2016-05-16 10:37:16

我看了下smali文件,发现提取opcode有困难,希望能看一下你是如何从SMALI文件中提取Davik Opcode序列的,
希望能发个源代码。非常感谢,邮箱 [email protected]/* <![CDATA[ */!function(t,e,r,n,c,a,p){try{t=document.currentScript||function(){for(t=document.getElementsByTagName('script'),e=t.length;e--;)if(t[e].getAttribute('data-cfhash'))return t[e]}();if(t&&(c=t.previousSibling)){p=t.parentNode;if(a=c.getAttribute('data-cfemail')){for(e='',r='0x'+a.substr(0,2)|0,n=2;a.length-n;n+=2)e+='%'+('0'+('0x'+a.substr(n,2)^r).toString(16)).slice(-2);p.replaceChild(document.createTextNode(decodeURIComponent(e)),c)}p.removeChild(t)}}catch(u){}}()/* ]]> */

路人甲 2016-05-18 14:15:49

@runner 楼主好,问一下N=3,又有7种类指令集合,那么特征一共有7^3这么多吗?

路人甲 2016-05-18 15:59:20

你好,能分享提取了哪些特征吗?谢谢

路人甲 2016-05-18 16:05:38

Drebin项目介绍及下载的用户名密码有吗?谢谢了

路人甲 2016-05-24 11:04:43

@runner 非常感谢

路人甲 2016-06-02 14:03:47

求提取OpCode的方法,谢谢

路人甲 2016-06-02 14:04:22

@runner求提取OpCode的方法,谢谢

路人甲 2016-06-19 15:58:45

51616516

随机分类

CTF 文章:62 篇
网络协议 文章:18 篇
SQL注入 文章:39 篇
安全管理 文章:7 篇
事件分析 文章:223 篇

扫码关注公众号

WeChat Offical Account QRCode

最新评论

Article_kelp

因为这里的静态目录访功能应该理解为绑定在static路径下的内置路由,你需要用s

N

Nas

师傅您好!_static_url_path那 flag在当前目录下 通过原型链污

Z

zhangy

你好,为什么我也是用windows2016和win10,但是流量是smb3,加密

0

0x0dee

标题写错了,是ASX to MP3 3.1.3.7 - '.m3u' Local

K

k0uaz

foniw师傅提到的setfge当在类的字段名成是age时不会自动调用。因为获取

目录