本文主要介绍使用一些工具对apk进行逆向获取部分源代码,并通过frida
对函数进行Hook并修改其值;使用Burpsuite
对app请求进行抓包并进行渗透测试,本文仅供交流学习。
1、逆向
先查看apk是否进行加壳,若加壳则需要使用脱壳工具进行脱壳,脱壳后拿到dex文件使用反编译工具对dex文件进行反编译获取源码进行分析。
1.1 壳分类
加壳技术 | 特点 | 脱壳难度 | 描述 |
---|---|---|---|
第一代:dex 整体加密型壳 | 采用 dex 整体加密,动态加载运行的机制 | 较容易被还原,通过自动化脱壳工具或脚本即可从内存中 dump 出 dex 文件 | 隐藏 dex 文件 |
第二代:dex 函数抽取型壳 | 粒度更细,将方法单独抽取出来,加密保存,解密执行 | 可以从根本上进行还原的,dump 出所有的运行时的方法体,填充到 dump 下来的 dex 中去的,这也是 fart 的核心原理 |
隐藏 dex 并下沉其中部分方法 |
第三代:vmp、dex2C 壳 | 独立虚拟机解释执行、语义等价语法迁移,强度最高 | dex2C 目前是没有办法还原的,只能跟踪进行分析; vmp虚拟机解释执行保护的是映射表,只要心思细、功夫深,是可以将映射表还原 | 虚拟机里跑虚拟机 |
1.2 脱壳工具
工具 | 描述 |
---|---|
BlackDex | github上开源项目,是一个运行在Android手机上的脱壳工具,支持5.0~12,无需依赖任何环境任何手机(无需root)都可以使用,包括模拟器。只需几秒,即可对已安装包括未安装的APK进行脱壳。 其只能脱第一代的壳,但也可拿到不少源代码进行分析。 |
Fart | 需刷入定制rom,不过其也提供了frida_frat供使用,均在其github中;详情可参见ART环境下基于主动调用的自动化脱壳方案。 |
frida-dexdump | 需依赖frida 框架,安装及命令均在 github中。 |
以上为比较常用的脱壳工具,还有很多其他工具如FDex2、FUPK3等就不再赘述了,需要的可以网上搜索使用教程。
1.3 反编译工具
工具 | 描述 |
---|---|
jadx | 本人常用的反编译工具,可直接使用jadx-gui打开apk、aar、jar、dex、aab、zip文件查看源代码 |
dex2jar | 把dex文件转换成jar的工具,有的时候jadx反编译失败可以尝试使用dex2jar来进行反编译,反编译后用jd-gui或者jadx查看源码。 |
以上为我常用的反编译工具,还有很多其他如CFR 、Procyon 等由于使用比较麻烦,只进行了了解未真正使用。
注:有的时候jadx加载脱壳后的dex文件时会发现缺少类(特别是各种Activity),并且jadx会提示错误jadx.plugins.input.dex.DexException: Bad checksum: 0xf0d8fef6, expected: 0xa2ffe277
,此时进入jadx文件加后使用jadx-gui -Pdex-input.verify-checksum=no
指令运行jadx后就会正常显示,相应的内存增量也会较大。
2、Hook与动态调试
Hook俗称钩子,本质是当调用某段代码时同时会执行Hook代码,这样可以读取输入输出,也可以修改输入输出,使用到的技术包含了反射、动态代理等,也分java层Hook与native层Hook等多种形式。Hook框架也分为root与非root两种,非root框架只能Hook本app内相关函数如epic
、sandhook
等便于开发,而需root框架则可以Hook系统调试其他app的框架,就是接下来要介绍的重点。
2.1 Hook调试框架
框架 | 描述 |
---|---|
frida | 一款基于 Python + JavaScript 的 Hook 与调试框架;易用的跨平 Hook 工具, Java 层到 Native 层的 Hook 无所不能,是一种动态的插桩工具,可以插入代码到原生 App 的内存空间中,动态的去监视和修改行为,原生平台包括 Win、Mac、Linux、Android、iOS 全平台,是目前主流的hook及动态注入框架。 |
xposed | 一款可以在不修改apk的情况下影响程序运行(修改系统)的框架服务,基于它可以制作出许多功能强大的模块,且在功能不冲突的情况下同时运作。由于使用起来颇为复杂,所以其使用率已经较少了。 |
2.2 Frida安装
Frida
分为客户端(即PC端)与服务端(即移动设备,也成为被控制端)。
hook流程大致是客户端通过编写的 Python代码(也可以通过指令直接注入js代码),用于连接服务端设备,提交要注入的 js代码到服务端,接受服务端发来的消息;服务端中需要用 js 代码注入到目标进程,操作内存数据,给客户端发送消息。
2.2.1 先安装Python
这里我使用的Python版本是3.11.0(由于我使用的frida版本比较新,所以无法使用Python2进行安装,若想使用Python2安装则需降低frida版本),可以去官网上下载。
2.2.2 安装Frida
当Python安装好并配置好环境变量后,可通过如下指令安装Frida
客户端:
pip install frida
//指定版本指令 pip install frida==x.x.x
pip install frida-tools
//指定版本指令 pip install frida-tools==x.x.x
安装好后可以通过frida --version
指令查看安装是否成功,这我安装的版本是16.0.2
服务端:
a、服务端去其官方github上下载与版本对应的server文件,不过server文件与系统架构也相互对应,若是跟我一样使用模拟器的,则可以下载16.0.2版本的x86架构sever,若是使用真机的则可以通过adb指令查询手机架构后寻找对应的进行下载即可。
注:若模拟器提示Failed to enumerate processes: unable to handle 64-bit processes due to build configuration
,需下载x86_64位版本。
b、下载完文件以后解压出里面的server文件,使用adb链接模拟器(手机),若是夜神模拟器,可以通过
adb connect 127.0.0.1:62001
进行连接(不同模拟器端口号不同),连接后使用adb push sever文件 data/local/tmp
命令把文件push到手机data/local/tmp
目录下
push搭配指定目录后,进入shell模式,提高server文件的权限
//进入shell模式
adb shell
//提高权限
chmod 777 xx-server
su -c xx-server &
//开启服务
./xx-server
通过
frida-ps -U
可了解服务是否运行成功
以上均成功,说明环境已配置完成,下一步可编写一些js注入脚本等进行实测。
ADB指令
//查看当前连接设备
adb devices
//多个设备时指定设备
adb -s 设备号 其他指令
// adb -s 设备端口 shell
//127.0.0.1:5555 蓝叠
//127.0.0.1:7555 MUMU模拟器
//127.0.0.1:62001 夜游神模拟器
//127.0.0.1:21503 逍遥模拟器
//查看Android处理器架构
adb shell getprop ro.product.cpu.abi
//安装APP
adb install xxx.apk
//安装APP,已经存在,覆盖安装
adb install -r xxx.apk
//强制安装apk,可安装一些未签名debug包
adb install -t xxx.apk
//卸载APP
adb uninstall 包名
//卸载APP,保留数据
adb uninstall -k 包名
//往手机传递文件
adb push 本地文件 手机路径
//从手机端获取文件
adb pull 手机文件 本地路径
//移动文件
mv 文件 路径
//修改文件权限
chmod 777 xxx
//查看日志
adb logcat
//清日志
adb logcat -c
//手机端安装的所有app包名
adb shell pm list packages
//查看当前包名和主Activity
adb shell dumpsys window | findstr mCurrentFocus
//启动APP
adb shell am start 包名/主Activity
//adb shell am start xxx.xxx.XXActivity
//关闭App
adb shell am force-stop 包名
//屏幕截图
adb shell screencap 手机路径/xxx.png
//录制视频
adb shell screenrecord 手机路径/xxx.mp4
//转发端口,使用python调试需要使用
adb forward tcp:27042 tcp:27042
adb forward tcp:27043 tcp:27043
Frida指令
//列举出来所有连接到电脑上的设备
frida-ls-devices
//连接到指定设备
frida-ps -D tcp
//列举出来设备上的所有进程
frida-ps -U
//列举出来设备上的所有应用程序
frida-ps -Ua
//列举出来设备上的所有已安装应用程序和对应的名字
frida-ps -Uai
//跟踪某个函数
frida-trace -U -f Name -i "函数名"
//跟踪某个方法
frida-trace -U -f Name -m "方法名"
//执行js脚本
frida -U -l js脚本 -f packagename --no-pause
2.2.3 js注入hook函数实战
a、先编写一个简单的Demo,一个MainActivity,在onCreate初始化时打印一个toast,内容是测试Hook,代码如下
安装到模拟器(手机)效果如下
b、现在要hook MainActivity的
onCreate
并修改toast
打印内容为"hook后,内容已被修改",hook_toast_test.js
注入代码如下
Java.perform(function () {
// hook类: MainActivity
var MainActivity = Java.use("cn.test.hook.MainActivity");
// hook方法: MainActivity.onCreate
MainActivity.onCreate.implementation = function (savedInstanceState) {
//控制台输出log日志,方便监控程序运行
console.log("执行onCreate");
// 程序不被终端,继续执行
this.onCreate(savedInstanceState);
};
// 获得Toast组件
var Toast = Java.use("android.widget.Toast");
var makeText = Toast.makeText;
var String = Java.use("java.lang.String");
// 函数重载, 设置参数类型
makeText.overload("android.content.Context", "java.lang.CharSequence", "int").implementation = function (
context,
content,
time
) {
//控制台输出log日志,方便监控程序运行
console.log("修改toast内容");
// 设置新内容
var content = "hook后,内容已被修改";
// 实例化字符串
var hookContent = String.$new(content);
// 程序不被终端,继续执行
return this.makeText(context, hookContent, time);
};
});
注:如果需要了解更多的Api可去官方Frida JavaScript Api文档中学习。
c、直接通过指令运行js脚本frida -U -f cn.test.hook --pause -l F:\workspace\vshook\hook_toast_test.js
来执行hook_toast_test.js
脚本,模拟器会启动包名为cn.test.hook
的应用程序,并执行hook与注入等
2.2.4 使用编辑器进行动态调试
我常用的编辑器是VS Code,安装扩展frida Workbench
后会显示一个R的标志,当启动frida-server后并使用adb转发端口,VS Code中就可以显示相应的设备可直接进行动态调试,这样就可以使用VS Code来编写python脚本加载js注入代码来完成更多的功能,调试起来也相对方便。
以上为一个hook注入操作的基本过程。
3、渗透测试
3.1、工具
常用Burpsuite,网上自取,安装教程可参见Burpsuite的超详细安装教程(图文版)。
3.1.1、抓数据
中间人攻击
步骤1:设置代理
点击Add后操作
步骤2:开启intercept
步骤3:模拟器手机设置代理
步骤4:抓取数据
3.1.2、https协议证书安装
由于有的app使用的https协议,抓包数据为密文数据,需要设置中间人证书,在步骤1中图示5导出证书cacert.der
,由于android无法使用der证书,需要使用openssl指令对证书进行导出,可以使用mac、linux系统进行操作或者windows安装openssl也可以。6.0及以下系统可直接安装证书,7.0及以上系统由于不再信任非系统证书,所以需要把证书安装到系统证书中,模拟器(手机)需要有root权限
//der转pem
sudu openssl x509 --inform cacert.der -in cacert.der -put burp.pem
//显示pem详细信息
sudu openssl x509 -in burp.pem --subject_hash_old
//把pen转成9a5ba575.0证书
sudo cp burp.pem 9a5ba575.0
得到9a5ba575.0证书后,
//设置remount
adb remount
//把证书push到系统证书中
adb push 9a5ba575.0 /system/etc/security/cacerts/
//重启手机
adb shell reboot
模拟器(手机)重启后在设置->安全->信任的凭据->系统中查看是否有PowerSwigger
,若存在说明证书安装成功,再抓取https协议请求后密文数据可显示为明文。
注:有的人在正确配置各项后打开app依然无法抓取请求,甚至burp中没有相应的请求,但是app中显示数据已请求完成,这种情况可能是app在代码中设置了网络请求绕过
proxy
,遇到这种情况有两种解决方式:1、使用Proxifier
开启一个代理通道,无需手机配置代理;2、反编译源码查看设置绕过proxy
的代码部分,对proxy
代码进行hook并绕过校验。
3.2、实际操作
待更新