首页 / 资讯中心 / 文章详情

Android恶意样本分析入门:环境搭建、静态与动态分析实战

Android恶意样本分析入门:环境搭建、静态与动态分析实战 ★ FEATURED ARTICLE
Android恶意样本分析第一件要做的事不是急着脱壳也不是急着抓包而是先搞清楚自己手上是个什么东西。很多刚入门的同学拿到一个样本APK第一反应就是扔进在线扫描平台看报告这个习惯我不是说不好而是它容易让你产生依赖——报告是别人出的特征是别人提取的你只是看了一个结论自己什么都没学会。我自己做移动安全这些年最深的体会就是病毒分析本质上是一场信息博弈。样本在想办法隐藏自己你在想办法把它看穿。这个系列的文章我会按照实际分析的推进顺序来写从环境准备、静态分析、动态监控、脱壳对抗到行为判定一步步把一套完整的分析思路拆给你看。这一篇作为系列的第一篇先解决“从零开始怎么看一个安卓样本”的问题不涉及太深的反混淆和脱壳对抗重点把这套基础流程跑通。等这套基本功扎实了后面遇到加固、混淆、HOOK对抗的时候你才有底气说“我能分析”。1. 分析环境搭建没准备好战场别急着上枪1.1 为什么必须用独立的分析环境我一直跟身边的人强调分析恶意样本绝不能用主力机连插着SIM卡的测试机都不行。因为现在很多安卓恶意样本带有非常强的环境感知能力它们会检测你手机上是否安装了常用社交软件、是否有通话记录、是否插了SIM卡、甚至会不会收到特定的验证码。这些检测一旦被你手动过掉或者环境里不存在样本就会进入“休眠模式”什么都不做你的分析就会陷入“明明拿到了样本却看不到任何恶意行为”的尴尬局面。我见过最典型的一个案例某金融类木马样本在无SIM卡、无通讯录的模拟器上运行时非常安静所有的恶意代码全部不触发。后来我们把通话记录、通讯录、短信等数据全部模拟出来之后样本立刻开始活跃加密上传通讯录、拦截短信验证码、隐藏自身图标动作一个接一个。这个例子充分说明了“模拟真实用户环境”的重要性。独立分析环境要满足以下几个条件系统是干净的没有任何个人数据、常用APP、甚至不要登录任何账号网络是可控的最好能实时看到样本对外发出的每一个请求有完整的快照回滚能力样本搞坏了系统可以一键恢复工具的安装要克制不要装一堆大而全的监控软件——工具本身可能被样本反检测1.2 我推荐的模拟器配置方案安卓样本分析的主流载体还是模拟器因为快照、回滚、网络监控都方便。我自己常用的组合是这样的夜神模拟器安卓7作为主力动态分析环境安卓9或更高版本的系统镜像用于分析那些强制要求高版本系统的样本真机刷了原生系统的旧手机用于模拟器上跑不了或者行为异常的情况选择安卓7是有讲究的。早期的恶意样本绝大多数都兼容安卓7以下版本而且安卓7的ART运行时对Xposed框架的兼容性极好很多HOOK方案在安卓7上不需要考虑SELinux和Siginfo太多问题。另外许多加固方案的脱壳机对安卓7的支持也是最成熟的比如你在FART或者Youpk上看到的兼容条件绝大多数都写着“支持安卓7.0-9.0”。模拟器的配置有几个细节值得注意不要开Root权限的默认设置很多安全检测软件自己就是靠Root运行的你先开Root你的分析工具就已经暴露了CPU核心数给到4核以上内存给到4G以上样本很多时候要跑好几个小时资源不够会假死打开模拟器的“外部网络”访问权限如果只允许模拟器访问局部网有些样本的联网行为会异常1.3 基础分析工具清单这套工具是我每次拿到新样本都必须提前准备好的整理成清单给你参考工具作用使用场景JADXAPK静态反编译直接看Java层代码快速浏览样本逻辑jadx-guiJADX的可视化界面带反编译功能日常主要分析工具frida动态插桩框架任意Java层函数HOOK动态分析核心objection基于Frida的免Root动态分析快速绕过Root检测、SSL PinningXposed/LSPosedJava层及部分Native层HOOK框架高版本模拟器动态分析Wireshark网络流量抓取和分析抓样本通信数据Charles/FiddlerHTTPS解密代理分析样本与服务器的加密通信好压/7-Zip解包APK查看资源文件和原始文件强调一点工具不是越多越好而是越顺越好。你自己用得最顺手的工具组合效率永远是最高的。我见过很多人电脑上装了一堆工具结果每个工具都不会深度使用拿样本分析的时候反而不知道怎么下手。1.4 网络管控怎么做模拟器的网络管控最容易忽略但是最影响分析质量。我常用的方案是在宿主机上搭一个代理服务器模拟器的流量全部指向这个代理代理记录所有HTTP/HTTPS请求的域名、路径、参数HTTPS流量用Charles的中间人证书解密查看这里面有一个非常大的坑后面专门会讲很多恶意样本做了SSL Pinning校验你一挂代理抓HTTPS它会直接报错退出。所以网络分析必须准备两套方案一套是正常代理解密另一套是用Frida绕过SSL校验后再抓包。2. 静态分析三件套解包、看清单、搜特征2.1 把APK拆开看看里面有什么拿到样本后第一件事永远是解包。APK本质上是个ZIP包你可以直接用7-Zip打开。解包后的目录结构是这样assets/ 存放本地资源文件、加密的payload等 lib/ 存放SO库armeabi-v7a、arm64-v8a META-INF/ 签名信息和清单文件 res/ 各种资源文件 AndroidManifest.xml 核心配置文件 classes.dex 程序主代码Dalvik字节码看APK目录能获得的第一手信息是很多的assets目录里有没有可疑的加密文件——很多恶意样本会把真正的恶意代码藏在assets里的加密文件中运行时再解密释放lib目录下的SO库的名字和数量——如果大量SO库名带“protect”“secure”“shell”之类的字样那基本就是加了壳classes.dex的数量——正常APP一般一个dex就够如果解压出来是好几个dex要么功能确实很大要么就是把恶意代码拆分隐藏了我印象很深的一个样本解包后在assets目录下看到一个文件叫dd.dat大小有4MB多而这整个APK才6MB。正常APK的资源文件是不会有这种大体积的.dat文件的后来确认这个文件就是加密的恶意payload运行时解密释放到应用私有目录执行。2.2 读懂AndroidManifest.xmlAndroidManifest.xml是APK的“身份证”里面什么关键信息都有。拿JADX打开样本后第一件事是看manifest。主要关注这几个点包名包名是唯一的很多恶意样本会伪装成正常的包名来迷惑用户入口Activity通常第一个启动的界面权限列表样本申请了哪些权限是否有与其功能不符合的敏感权限Service、Receiver列表看样本注册了哪些后台服务Application的name有加固的话这个值会被替换成壳的Application看权限列表是识别恶意样本最快的途径之一。你想想一个计算器APP申请读取通讯录、发送短信、获取定位权限这正常吗明显不对。反过来如果这个计算器APP申请了“系统设置修改”权限那更不用想绝对有鬼。但也要注意高级样本越来越会“克制”权限申请它们会把敏感行为拆分成多次申请、或者运行时通过动态注册服务来避免在安装时暴露权限。所以看权限只是第一步不是判断依据。2.3 关键代码特征快速定位解包和看清单只是前期侦查真正要命的代码定位得靠搜索。我最常搜索的代码特征包括反射调用搜索Class.forName、getMethod、invoke恶意样本经常用反射做动态加载来隐藏真实行为动态加载搜索DexClassLoader、PathClassLoader样本把恶意代码藏在加密文件里运行时会动态加载系统命令执行搜索Runtime.getRuntime().exec、ProcessBuilder直接在Java层执行系统命令隐私数据获取搜索getDeviceId、getSubscriberId、getSimSerialNumber设备信息是黑产最想要的短信/通讯录操作搜索SmsManager、ContentResolver查询通讯录加密算法搜索AES、DES、RSA、Cipher样本和服务器通信前数据一般都会加密这些特征搜出来之后结合JADX的“交叉引用”功能谁调用了我、我调用了谁就能一步一步把整个调用链串起来。这个过程有点像剥洋葱一层一层剥开最终露出样本的“心脏”。有一个搜特征的技巧我记得特别牢不要只搜索一个词要多组合几个关键词。比如一个恶意行为需要三四个特征函数组合才能触发你只搜一个肯定不够反过来如果你搜到三个以上的敏感行为特征出现在同一段代码里那基本就能确定这是恶意逻辑。2.4 静态分析的局限静态分析不是万能的它的最大敌人是代码混淆和运行时动态行为。静态分析只能看到“代码长的什么样”看不到“代码运行时干了什么”。比如加密的payload在静态阶段是解密不了的因为密钥可能在SO库里、可能在服务器上、甚至可能在用户输入里——静态阶段根本无从知晓。另外很多恶意样本的代码被做了控制流平坦化、字符串加密静态分析看到的就是一堆乱糟糟的跳转和看不到明文的字符串这时候还得上动态分析。3. 动态分析实操让样本自己跑起来现原形3.1 动态分析的三大前置条件动态分析就是把样本放到隔离环境里让它真正运行起来然后观察它的行为。但跑之前有三个前置条件必须准备到位快照备份模拟器当前状态做一个快照样本跑挂了直接恢复网络代理已配置Charles/Wireshark已经挂好流量等着抓Hook工具已注入Frida server已经在模拟器里跑起来了有一次我犯了个低级错误样本还没开始跑Frida server没启动等样本起来了我才发现结果大部分通信流量已经错过了。所以这三样东西必须在样本安装之前就全部就绪。3.2 安装、启动、观察、记录四步法接下来是动态分析的常规流程安装样本注意看安装时的权限申请弹窗很多样本会诱导用户给权限启动样本启动后不要急着点先在系统进程里找到它确认进程存活观察行为看进程列表变化、看文件读写、看网络流量、看界面跳转记录每步操作包括点击了哪里、弹了什么窗、触发了什么行为动态分析最关键的一点是要像真实用户一样操作样本。你需要点击它的界面按钮模拟正常交互。有些样本的恶意行为要特定操作才会触发比如双击五次、长按三秒、输入特定代码等等。3.3 用Frida看Java层动态调用Frida是目前动态分析的主流方案它的能力是直接在运行时修改Java层方法逻辑打印所有关键函数的调用参数和返回值。以抓取getDeviceId为例Frida脚本可以这样写Java.perform(function() { var TelephonyManager Java.use(android.telephony.TelephonyManager); TelephonyManager.getDeviceId.implementation function() { var result this.getDeviceId(); console.log(getDeviceId called, result result); return result; }; });这个脚本运行后一旦样本调用了getDeviceId我们就能看到它拿走了什么设备信息。这种方式的优势是对样本完全透明样本感知不到自己被监视。我自己常用的是用objection直接做Frida插桩因为它自动化程度高你可以直接输入命令查看当前调用了哪些方法、实时拦截和修改返回值。像这样objection -g com.example.malware explore进入交互模式后输入android hooking list activities可以列出所有Activity输入android hooking watch class android.telephony.TelephonyManager就能监控TelephonyManager的所有方法调用。3.4 动态加载的代码怎么分析前面静态分析时提到的DexClassLoader在动态分析阶段就能暴露真面目了。当样本运行起来在JADX里看到DexClassLoader加载的dex路径上你会看到一个真实存在的文件这时候你就可以把那个文件拉出来再扔进JADX里反编译——这其实就是脱壳的雏形。加密payload也一样运行时它必须解密才能加载你只要在解密后、加载前的那一刻把文件抓出来整个加密就破了。这个时机抓得好不好直接决定了你的分析效率。4. 流量分析看样本和自己的服务器说了什么4.1 流量抓取的两个层次样本运行起来之后的网络行为是你判断它的用途、他的上线指令、它的远控地址最直接证据。流量分析分两个层次第一层抓包看HTTP/HTTPS明文。这是最直观的。样本跟服务器通信GET/POST请求、响应包内容一目了然。Charles上直接可以看到域名、路径、参数、返回值。第二层看TCP/UDP层的直接通信。有些样本不走HTTP直接裸TCP发数据——这通常是为了逃避HTTP层的检测规则。Wireshark能看到这些原始流量。4.2 HTTPS解密与SSL Pinning绕过现在绝大多数安卓恶意样本的通信都是HTTPS加密的直接抓包只能看到证书握手看不到内容。所以要用Charles的中间人证书来解密HTTPS流量。在模拟器上信任Charles的证书之后HTTP请求就能被解密查看。但真正麻烦的是SSL Pinning。样本把自己的服务器证书固定在了客户端代码里中间人证书不被信任SSL握手直接失败。绕过SSL Pinning的标准做法是用Frida Hook掉证书校验函数Java.perform(function() { var TrustManagerImpl Java.use(com.android.org.conscrypt.TrustManagerImpl); TrustManagerImpl.verifyChain.implementation function() { return []; // 直接返回空数组跳过证书校验 }; });跑上这个脚本后再开Charles抓包HTTPS流量的内容就能看到了。4.3 通信内容分析能从流量里发现的典型恶意特征包括上传本机信息POST请求的Body里带设备ID、手机号码、通讯录数据接收远程指令服务器响应一个JSON包含actionsendSms之类的命令字段下载恶意载荷样本从服务器下载一个APK或DEX然后动态加载执行心跳保活机制每30秒或者1分钟发一次心跳包保持和控制端的长连接我曾经分析过一个样本它的网络行为会周期性向服务器发送加密心跳包。抓包后发现心跳包的内容是一串经过AES加密的base64字符串用硬编码在样本里的密钥做解密后能直接看到里面包含手机的IMEI号、SIM卡运营商信息和当前电量——这些数据本身不敏感但组合起来就拼凑出这个手机号用户的完整画像了这就是黑产泄数前的情报收集行为。5. 恶意行为判定与分类5.1 常见恶意软件的判定标准把前面静态、动态、流量三个阶段的信息收集汇总之后就能判定样本是否属于恶意软件了。常见的分类维度如下隐私窃取类偷偷获取通讯录、短信、定位、设备信息并上传资费消耗类后台发短信、订购SP服务、下载应用远程控制类接收服务器指令执行操作包括静默安装、卸载应用勒索类加密用户文件弹窗索要赎金广告推送类强推广告、静默安装推广应用判定标准最好用一个简单粗暴的逻辑你愿不愿意让这个APP在你的主力手机上运行如果你犹豫了这个APP基本就有问题。5.2 行为特征、证据链完整记录分析完要写报告报告的核心是形成一条完整的证据链。恶意行为的证据链要满足“时间、地点、人物、事件”四要素时间样本在什么时间触发了恶意行为启动后多久点击后多久地点样本在什么路径下释放了什么文件assets/dd.dat被解压到/data/data目录对象样本操作了哪些数据获取的IMEI、通讯录条目数事件具体的恶意动作上传了内容、执行了命令写报告的时候这套证据链越完整你的分析结论就越可信。6. 反分析对抗样本不想让你看到的那些事6.1 Root检测、模拟器检测与绕过越高端的样本越会检查自己是不是运行在一个“安全环境”里。常见的手段有Root检测检查su文件是否存在、检查Root权限模拟器检测检查Build.FINGERPRINT里是否包含generic关键字调试检测检查Debug.isDebuggerConnected()返回值或者检测TracerPidHOOK框架检测检测Xposed相关包名是否存在这些检测一旦命中样本要么直接退出要么故意返回假数据坑的就是分析者。绕过思路也很清晰让样本认为它运行在一台真实手机上、而且这台真实手机没有Root、没有调试、没有HOOK。最暴力的办法是直接用Frida修改检测函数的返回值Java.perform(function() { var RootBeer Java.use(com.scottyab.rootbeer.RootBeer); RootBeer.isRooted.implementation function() { return false; }; });这种逐个Hook的方法在“代码阅读”阶段很有用但在“样本实际运行”阶段我觉得最靠谱的还是直接不触发检测条件——不要在模拟器里开Root标志、不要装Xposed全家桶、用Frida的时候用frida-server而不是Xposed。6.2 加固、混淆与动态脱壳现在市面上主流的安卓加固方案如360、腾讯乐固、爱加密等都有对应的脱壳方案。第一篇文章不展开讲脱壳但我先把我踩过的坑说出来脱壳机不是一键就能出的很多时候脱壳出来的dex内存是残缺的还需要配合修复工具做DEX修复这个过程很消磨耐心。遇到加固样本时我的建议是“能绕则绕”先看样本是不是有“未加固版本”的上线更新检测有时候老的版本没加固新版本加了你分析旧通知就行优先用Frida做运行时HOOK基里糊涂地绕过硬校验直接看运行时行为脱壳机出来之后需要修复修复里最核心的是重新计算DEX的checksum和结构对齐用现成的脚本是可以搞定的6.3 反调试与Anti-Frida技巧真正高端的样本会直接检测Frida的特征比如检查/data/local/tmp/frida-server路径是否存在、扫描进程列表里的frida进程、甚至检查特定端口27042是否被监听。针对这类样本我的建议是使用frida-server改名比如改成crash、systemd之类的合法名称用frida -H远程模式把frida-server放在一台单独的机器上与样本跑在同一个设备但进程列表里看不到frida用r0capture这类不依赖Frida的解法做脱壳7. 实战案例复盘一个模拟远控木马的分析过程7.1 样本基本信息下面用我之前分析过的一个模拟项目X的远控木马样本完整走一遍整个分析流程。这是一个伪装成某办公软件的APP包名叫com.system.update一眼看上去人畜无害。JADX打开manifest看到申请的权限里有读取联系人读取短信获取定位发送短信安装其他应用系统设置修改一个办公软件要发送短信和安装应用这个权限组合开了一个很不好的头。7.2 静态阶段发现的核心线索在JADX里搜索Runtime.getRuntime().exec找到了一个非常可疑的函数代码大概是这样的private void execShell(String cmd) { try { Process p Runtime.getRuntime().exec(cmd); // ... } catch (Exception e) { } }继续追踪这个函数的调用来源发现它被一个监听短信的BroadcastReceiver调用。也就是说这个样本在收到特定的短信指令后会执行系统命令。这已经是教科书级的远控木马行为了。7.3 动态阶段的关键证据样本启动后Charles里很快就看到它有一个POST请求到https://update.xx-xxxxx.com/api/v1/report请求的Body是一串加密过的JSON密文。Frida hook解密函数拿到明文内容后发现里面包含了设备的IMEI、手机号码、通讯录前10条记录的全部内容。这还不够继续观察运行行为发现样本在收到服务器返回的一条指令序列后会触发DexClassLoader动态加载一个下发的恶意dex。这个dex才是完整的勒索模块会扫描存储卡上的文件并加密。整个链条到这里就非常清晰了诱骗安装-窃取个人信息上传-接收远程指令-下载执行勒索模块。这已经是一个完整的多阶段攻击链。8. 常见问题与排查技巧实录8.1 问题速查表现象可能原因解决办法样本安装后打开闪退缺少依赖库或检测到模拟器环境用真机分析或修改模拟器特征Frida连接不上模拟器版本不匹配、端口被占检查frida-server版本与客户端一致换端口抓包抓不到HTTPS内容SSL Pinning未绕过用Frida hook证书校验函数样本运行后没有任何行为依赖特定环境SIM卡、通讯录在模拟器里模拟真实用户环境脱壳后的dex无法反编译DEX结构损坏用修复工具修复checksum和结构对齐网络流量一片空白网络代理配置错误检查模拟器代理设置与宿主机端口8.2 分析流程中的几个关键时间点我分享一下我分析样本时最常记录的“关键时间点”安装时包名是不是正常签名安装弹窗有没有诱导词首次启动时有没有申请敏感权限有没有先弹出隐私政策恶意样本经常伪造隐私政策走形式点击主要功能时点击按钮后流量里发生了什么事收到特定指令时比如来短信、接入USB、连上WiFi这类事件触发下样本是什么反应把每个关键时间点记录下来分析完成后你会得到一张完整的“行为时间轴”这就是报告的大纲。8.3 心态调整分析样本是在拼耐心安卓病毒分析不是一场闪电战而是一场持久战。我见过太多人拿一个棘手样本分析了一个小时就放弃了要么说“这个样本太高级了”要么说“工具不行”。实际上大多数时候是耐心不够、方法不对。我自己分析最久的一个样本前前后后花了两周时间。验证下来发现它就是简单的加固加反调试难点全在于“反调试”这一层。一旦绕过了反调试里面内容非常简单。所以遇到卡住的时候别急着换工具先回想一下是不是漏了某个检测、或者某个环境条件没满足。写在最后这一篇先把安卓病毒分析的基础流程理顺了搭建环境、静态解剖、动态监控、流量取证、行为判定、对抗思路再到一个完整案例的复盘。整个流程跑通一遍之后你基本就具备了独立分析一个普通恶意样本的能力。下一篇我会专门讲“脱壳实战”会把常见商业壳的脱壳方法、DEX修复原理和Frida在脱壳中的高级用法一一展开。这个领域最深的水就在脱壳和反混淆里但有了这一篇的地基你会走得稳很多。最后分享一个我个人的习惯每分析完一个样本把所有用到的命令、脚本、遇到的坑、突破的关键点整理成一份笔记。这个笔记既是积累也是武器下次再遇到同类型样本直接照着笔记推进速度能快一大截。
阅读完成 · 觉得有帮助?
咨询建站