安全矩阵

 找回密码
 立即注册
搜索
查看: 2765|回复: 0

使用JEB、IDA Pro进行静态分析

[复制链接]

181

主题

182

帖子

721

积分

高级会员

Rank: 4

积分
721
发表于 2022-4-26 13:06:51 | 显示全部楼层 |阅读模式
本帖最后由 wangqiang 于 2022-4-26 13:08 编辑

使用JEB、IDA Pro进行静态分析
原创 tale Tide安全团队  

2022-04-24 17:03

转载自使用JEB、IDA Pro进行静态分析


前言

Android应用的逻辑代码是由Java进行开发,所以是第一层就是java代码,Java虚拟机JVM运行的是java文件编译过后的class文件,
Android虚拟机Dalvik并不是执行Java虚拟机JVM编译后生成的class文件,而是执行再重新整合打包后生成的dex文件编译之后的smali文件。

  1. APK:是编译完成后的Android应用程序安装包
  2. dex文件:是class文件的打包文件
  3. smali文件:是Dalvik字节码文件
  4. class文件:是JVM字节码文件
复制代码


Android工程编译完成会得到我们想要的APK安装包,APK文件其实是一个压缩包
​​​​​​​
  1. META-INF文件夹:
  2. 存放apk签名信息,用来保证apk包的完整性和系统的安全。
  3. res文件夹:
  4. 存放资源文件,包括icon,xml文件。
  5. AndroidManifest.xml文件:
  6. 应用程序配置文件,每个应用都必须定义和包含的,它描述了应用的名字、版本、权限、引用的库文件等信息。
  7. classes.dex文件:
  8. 可以直接在Dalvik虚拟机上加载运行的文件,由java文件经过IDE编译生成。
  9. resources.arsc文件
  10. 二进制资源文件,包括字符串等。
复制代码


我们在分析一个Apk的时候,一般来说通过静态分析才能够开始破解之门,但随着现在的APK程序加固的越来越高级,只依赖静态分析也是不够的,更需要静态分析和动态分析一定会结合在一起才能事半功倍。


使用JEB进行静态分析

JEB简介
JEB:一款强大的跨平台Android 静态分析工具,相比jd-gui、jadx、bytecode-viewer这类jar查看工具,JEB提供类似
IDA Pro的方法交叉引用与重命名功能,JEB的脚本化功能在自动分析与对抗代码混淆中很实用。

JEB的静态分析功能

打开jeb,将要分析的APK拖入并等待分析完成




下面以具体一个恶意APP为实例,运用动静态分析方法结合工具使用来分析该APP。
我们解压APK文件后,发现在r文件夹下存放了资源文件,dex为Dalvik虚拟机可执行文件,resources存放了一
些字符串,meta包含该APP签名信息,AndroidManifest文件中包含了APP的配置信息。





将要分析的APP文件拖入jeb之后,进入MainActivity,然后选择Decompile,通过代码分析发现该APP首先注册了Broadcast,
然后寻找该类Class.forName("com.shimeng.qq2693533893.MyServiceOne"),最后用startService来启动该类。主要逻辑在MyServiceOne类里。




点开MyServiceOne查看具体的逻辑



通过在模拟器运行该APP发现,连接模拟器的ADB断掉,而且重启模拟器会自动弹出APP的页面并且自动播放声音,该声音无法关掉,而且重启手机后也会自动播放声音。
所以该setprop persist.sys.usb.config none执行断掉自身USB的操作。





通过运行发现APP一直在调用MyServiceOne$100000007,通过静态分析找到100000007,发现该方法是调用getStreamMaxVolume系
统音量最大的api,所以该APP运行之后无法关闭音量。



回头来看我们输入的解锁码然后打印出来的内容,相当于输入了一个解锁码的参数,下图涉及到的调用方法即APP的执行流程。
  1. com.shimeng.qq2693533893 on (Android: 8.0.0) [net] # android hooking watch class com.shimeng.qq2693533893.MyServiceOne
复制代码

发现主要的判断逻辑如下,如果与9DDEB743E935CE399F1DFAF080775366相等,则移除MyServiceOne.this.util.removeView(),进入sm2
​​​​​​​
  1. if(QQ2693533893.getSaltMD5(MyServiceOne.(v2.substring(0, 3))) + v2.substring(3, v2.length()).equals("9DDEB743E935CE399F1DFAF080775366" + v3_1)) {
  2. MyServiceOne.this.util.removeView();
  3. MyServiceOne.this.sm2();
复制代码






发现通过字符串搜索,最终利用静态分析定位到关键性逻辑。
针对一些小厂家较早期的APP,搜索字符串的方法确实能做到一步到位。
再比如下面这款看电视的APP,发现有强制升级我们尝试使用静态分析的方法来进行破解。




通过搜索字符串“立刻升级”定位代码位置
​​​​​​​
  1. public void update_show(Bundle arg4) {
  2.     if(arg4 != null && (arg4.containsKey("ver")) && (arg4.containsKey("info")) && (arg4.containsKey("path"))) {
  3.         new AlertDialog.Builder(this).setTitle("发现新版本 " + arg4.getString("ver") + " 是否升级").setMessage(arg4.getString("info")).setPositiveButton("立刻升级", new o(this, arg4)).show();
  4.     }
  5. }
复制代码


发现如果有一个条件不满足,就不会进行升级,然后我们找到info对应的smali,将判断结果的地方if-eqz改成if-nez即可让条件链失效,从而达到去强制升级的目的。





修改完之后打包签名,然后运行发现没有了强制升级




使用IDA Pro进行静态分析

IDA Pro简介IDA Pro:目前功能最强大的静态反编译分析工具,具备可交互、可编程、可扩展、多处理器支持等特点,软件逆向分析必备工具。
从6.1版本开始提供对 Android 的静态分析与动态调试的支持,包括 Dalvik 指令集的反汇编、原生库(ARM/Thumb 代码)的反汇编、原生库(ARM/Thumb 代码)的动态调试等。


IDA Pro的静态分析功能

在进行静态分析之前,我们需要先手动运行一下APP,了解下该程序的操作流程和进行更改的目的。寻找突破口是分析Android程序的关键。
一般的做法是按程序中的错误提示信息来找到关键代码,因为错误提示代码附近通常就是程序的核心验证代码,可以通过阅读这些代码来理解程序的流程。




通过运行该APP我们发现该程序需要进行注册码校验,只有通过校验成功的注册码才可进行下一步操作。还发现了两个按钮监听的事件,
因此从onclick可以作为破解该程序的出发点。
下一步我们解压APK取得 classes.dex,打开IDA Pro,将DEX拖入IDA Pro,选择默认选项,等待分析完成。
​​​​​​​
  1. IDA Pro支持以结构化形式显示数据结构。单击“IDA View-A”选项卡,来到反汇编代码界面,然后单击菜单项“Jump”->“jump to address”,或按“G”键,会弹出地址跳转对话框,输入0,跳转到DEX文件的开头。可看到IDA Pro已自动解释了结构体信息并加上了注释。
  2. DEX中所有方法的详细信息可在“Exports”选项卡中查看,方法的命名规则为“类名.方法名@方法声明”
复制代码


用IDA Pro定位关键代码的方法整体上与定位smali关键代码类似。方法主要有三种:

一、搜索特征字符串
按组合键“Ctrl+S”,打开段选择对话框,双击“STRINGS”,跳转到字符串段,然后单击菜单项“Search”->“text”,或按组合键“Alt+T”,打开文本搜索对话框,
在“String”旁输入要搜索的字符串,单击“OK”,等待片刻即可

二、搜索关键 API
按组合键“Ctrl+S”,打开段选择对话框,双击第一个“CODE”,跳转到数据起始段,然后单击菜单项“Search”->“text”,或按组合键“Alt+T”,
输入要搜索的 API 名称。若 API 被多次调用,可按组合键“Ctrl+T”搜索下一项

三、通过方法名判断方法的功能
此方法较笨拙,因为对混淆过的代码,定位其关键代码是较困难的。如,知道 Crackme程序的主Activity类为MainActivity,在“Exports”中输入“Main”,
会自动定位以“Main”开头的行(由此可粗略判断每个方法的作用)
通过分析APK文件后,以按钮点击事件为突破口查找关键代码,所以我们选择使用搜索特征字符串的方式来破解程序。

首先我们搜索字符串onclick




找到onclick对应的方法,判断逻辑分析发现有两个onClick()
第一个onClick()调用了MainActivity.access$000(),在反汇编界面双击MainActivity.access,可看到其调用了
MainActivity的 getAnnotations()。可看出,MainActivity$1.onClick()是“获取注解”按钮的事件响应代码




第二个onClick() ,来到其对应的反汇编代码,按“空格”键切换到 IDA Pro 的流程视图,代码的“分水岭”就是if-eqz p0, loc_116518,
如下图所示,在第一个方框下,左边的箭头表示条件不满足时程序执行的路线,右边的箭头表示条件满足时执行的路线。
可看出MainActivity$2.onClick() 是“检测注册码”按钮的事件响应代码





经过上面的分析,可知只要修改if-eqz指令为if-nez即可破解程序





将鼠标定位到指令“if-eqz v2, loc_2D0DCD ”所在行,然后点击IDA Pro主界面的“Hex View-A”选项卡,可看到这条指令所在的文件
偏移为0x2D0BE,相应的字节码为“38 02 0f 00 ”,将 if-eqz 的OpCode值38 改成if-nez的OpCode值39即可。





再比如一款抓包请求和响应全加密的APP,我们尝试使用静态分析的方法找到加密逻辑。


在登录处抓包发现,request包和response包都为加密传输:






我们使用字符串搜索的方法,在String窗口搜索loginbypassword(这个是登录时的信息),搜索后进入对应的类,接下来我们进入这个类看它用了哪些方法



找到这个字符串引用的代码位置


  1. 之后双击callWebAPI:data:method:ssl:completionHandler:
  2. 找到[WebService callWebAPI:data:method:ssl:completionHandler:]
  3. 然后F5一下
复制代码





浏览该类发现可以看到data等关键加密信息,接着我们尝试搜索data前面的setValue:forKey



​​​​​​​
  1. [_priv_NBSSafeMutableDictionary setValue:forKey:]查看该类发现无结果,返回上一步重新查看加密所在的类
  2. v87由v86 = -[WebService returnDictionaryWithDataPath:](v11, “returnDictionaryWithDataPath:”, v201)返回
复制代码

查看returnDictionaryWithDataPath:



​​​​​​​
  1. v8 = +[RSA encryptString:privateKey:](&OBJC_CLASS___RSA, “encryptString:privateKey:”, v4, v6);
  2. v4由convertToJsonData:返回(明文)v6由AppPrivate返回(密钥)
复制代码


查看密钥返回函数AppPrivate和encryptString:privateKey函数





找到了加密算法的逻辑后,我们可以编写脚本然后再使用frida进行hook



​​​​​​​
  1. if (ObjC.available){
  2.     try{
  3.         var className = "RSA";
  4.         var funcName = "+ encryptString:privateKey:";
  5.         var hook = eval('ObjC.classes.' + className + '["' + funcName + '"]');
  6.         console.log("[*] Class Name: " + className);
  7.         console.log("[*] Method Name: " + funcName);
  8.         Interceptor.attach(hook.implementation, {
  9.           onEnter: function(args) {
  10.             var param1 = new ObjC.Object(args[2]);
  11.             console.log("args[2] -> " + param1);

  12.             var param2 = new ObjC.Object(args[3]);
  13.             console.log("args[3] -> " + param2);
  14.           },
  15.           onLeave: function(retval) {
  16.             var retur = new ObjC.Object(retval);
  17.             console.log("retval -> " + retur);     
  18.           }
  19.         });
  20.     }
  21.     catch(err){
  22.         console.log("[!] Exception2: " + err.message);
  23.     }
  24. }
  25. else{
  26.     console.log("Objective-C Runtime is not available!");
  27. }
复制代码

可以发现通过字符串搜索的方式最终找到了加密算法。


总结

目前破解一个Apk的时,发现只使用静态分析的方式几乎毫无用途,随着加固技术的升级静态分析变得无从下手,所以动态分析是必须的,
动态分析在运行代码的情况下,通过跟踪分析相关的内存,如寄存器内容,函数执行结果,内存使用情况等等,分析函数功能,明确代码逻辑。
在某些场景下,静态分析作为辅助分析的一种手段,没有静态分析之后的结果,动态分析是无法开展的。因为动静结合的分析方式才会是高效的手段。​​​​​​​


  1. 参考资料
  2. https://www.cxyzjd.com/article/qq_44906504/89419090
  3. https://toutiao.io/posts/amtx3y/preview
  4. https://www.cnblogs.com/ichunqiu/p/9565028.html
  5. https://blog.csdn.net/zlmm741/article/details/104886648?spm=1001.2014.3001.5502
复制代码

END


回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|安全矩阵

GMT+8, 2024-11-30 10:52 , Processed in 0.023634 second(s), 18 queries .

Powered by Discuz! X4.0

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表