|
本帖最后由 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文件。
- APK:是编译完成后的Android应用程序安装包
- dex文件:是class文件的打包文件
- smali文件:是Dalvik字节码文件
- class文件:是JVM字节码文件
复制代码
Android工程编译完成会得到我们想要的APK安装包,APK文件其实是一个压缩包
- META-INF文件夹:
- 存放apk签名信息,用来保证apk包的完整性和系统的安全。
- res文件夹:
- 存放资源文件,包括icon,xml文件。
- AndroidManifest.xml文件:
- 应用程序配置文件,每个应用都必须定义和包含的,它描述了应用的名字、版本、权限、引用的库文件等信息。
- classes.dex文件:
- 可以直接在Dalvik虚拟机上加载运行的文件,由java文件经过IDE编译生成。
- resources.arsc文件
- 二进制资源文件,包括字符串等。
复制代码
我们在分析一个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的执行流程。
- com.shimeng.qq2693533893 on (Android: 8.0.0) [net] # android hooking watch class com.shimeng.qq2693533893.MyServiceOne
复制代码
发现主要的判断逻辑如下,如果与9DDEB743E935CE399F1DFAF080775366相等,则移除MyServiceOne.this.util.removeView(),进入sm2
- if(QQ2693533893.getSaltMD5(MyServiceOne.(v2.substring(0, 3))) + v2.substring(3, v2.length()).equals("9DDEB743E935CE399F1DFAF080775366" + v3_1)) {
- MyServiceOne.this.util.removeView();
- MyServiceOne.this.sm2();
复制代码
发现通过字符串搜索,最终利用静态分析定位到关键性逻辑。
针对一些小厂家较早期的APP,搜索字符串的方法确实能做到一步到位。
再比如下面这款看电视的APP,发现有强制升级我们尝试使用静态分析的方法来进行破解。
通过搜索字符串“立刻升级”定位代码位置
- public void update_show(Bundle arg4) {
- if(arg4 != null && (arg4.containsKey("ver")) && (arg4.containsKey("info")) && (arg4.containsKey("path"))) {
- new AlertDialog.Builder(this).setTitle("发现新版本 " + arg4.getString("ver") + " 是否升级").setMessage(arg4.getString("info")).setPositiveButton("立刻升级", new o(this, arg4)).show();
- }
- }
复制代码
发现如果有一个条件不满足,就不会进行升级,然后我们找到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,选择默认选项,等待分析完成。
- IDA Pro支持以结构化形式显示数据结构。单击“IDA View-A”选项卡,来到反汇编代码界面,然后单击菜单项“Jump”->“jump to address”,或按“G”键,会弹出地址跳转对话框,输入0,跳转到DEX文件的开头。可看到IDA Pro已自动解释了结构体信息并加上了注释。
- 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(这个是登录时的信息),搜索后进入对应的类,接下来我们进入这个类看它用了哪些方法
找到这个字符串引用的代码位置
- 之后双击callWebAPI:data:method:ssl:completionHandler:
- 找到[WebService callWebAPI:data:method:ssl:completionHandler:]
- 然后F5一下
复制代码
浏览该类发现可以看到data等关键加密信息,接着我们尝试搜索data前面的setValue:forKey
- [_priv_NBSSafeMutableDictionary setValue:forKey:]查看该类发现无结果,返回上一步重新查看加密所在的类
- v87由v86 = -[WebService returnDictionaryWithDataPath:](v11, “returnDictionaryWithDataPath:”, v201)返回
复制代码
查看returnDictionaryWithDataPath:
- v8 = +[RSA encryptString:privateKey:](&OBJC_CLASS___RSA, “encryptString:privateKey:”, v4, v6);
- v4由convertToJsonData:返回(明文)v6由AppPrivate返回(密钥)
复制代码
查看密钥返回函数AppPrivate和encryptString:privateKey函数
找到了加密算法的逻辑后,我们可以编写脚本然后再使用frida进行hook
- if (ObjC.available){
- try{
- var className = "RSA";
- var funcName = "+ encryptString:privateKey:";
- var hook = eval('ObjC.classes.' + className + '["' + funcName + '"]');
- console.log("[*] Class Name: " + className);
- console.log("[*] Method Name: " + funcName);
- Interceptor.attach(hook.implementation, {
- onEnter: function(args) {
- var param1 = new ObjC.Object(args[2]);
- console.log("args[2] -> " + param1);
- var param2 = new ObjC.Object(args[3]);
- console.log("args[3] -> " + param2);
- },
- onLeave: function(retval) {
- var retur = new ObjC.Object(retval);
- console.log("retval -> " + retur);
- }
- });
- }
- catch(err){
- console.log("[!] Exception2: " + err.message);
- }
- }
- else{
- console.log("Objective-C Runtime is not available!");
- }
复制代码
可以发现通过字符串搜索的方式最终找到了加密算法。
总结
目前破解一个Apk的时,发现只使用静态分析的方式几乎毫无用途,随着加固技术的升级静态分析变得无从下手,所以动态分析是必须的,
动态分析在运行代码的情况下,通过跟踪分析相关的内存,如寄存器内容,函数执行结果,内存使用情况等等,分析函数功能,明确代码逻辑。
在某些场景下,静态分析作为辅助分析的一种手段,没有静态分析之后的结果,动态分析是无法开展的。因为动静结合的分析方式才会是高效的手段。
- 参考资料
- https://www.cxyzjd.com/article/qq_44906504/89419090
- https://toutiao.io/posts/amtx3y/preview
- https://www.cnblogs.com/ichunqiu/p/9565028.html
- https://blog.csdn.net/zlmm741/article/details/104886648?spm=1001.2014.3001.5502
复制代码
END
|
|