【APP 逆向百例】Frida 初体验,root 检测与加密字符串定位

article/2025/11/7 10:06:40

声明

本文章中所有内容仅供学习交流使用,不用于其他任何目的,不提供完整代码,抓包内容、敏感网址、数据接口等均已做脱敏处理,严禁用于商业用途和非法用途,否则由此产生的一切后果均与作者无关!

本文章未经许可禁止转载,禁止任何修改后二次传播,擅自使用本文讲解的技术而导致的任何意外,作者均不负责,若有侵权,请在公众号【K哥爬虫】联系作者立即删除!

逆向目标

  • 设备:Google Pixel4,Android 10,已 root
  • APP:UnCrackable-Level1.apk(可在公众号回复 APP 获取)
  • APP 检测了 root,如果手机 root 了,会强制退出 APP,过了 root 检测后,还需要输入一个字符串进行校验。

安装 ADB

adb(Android Debug Bridge)即安卓调试桥,安装后可以在电脑上与手机进行交互,Android Studio 等工具里面会自带 adb,有时候我们并不想下载这么大的工具,所以这里介绍一下 Android SDK Platform-Tools,它是 Android SDK 的一个组件,它包括与 Android 平台交互的工具,主要是 adb 和 fastboot,官方下载地址:https://developer.android.com/studio/releases/platform-tools ,下载完成后将该目录添加到环境变量,USB 连接手机,手机上设置允许 USB 调试,使用命令 adb version 可查看版本信息,adb devices 可以查看当前连接的设备,如下图所示:

01

安装 Frida

Frida 是一款基于 Python + JavaScript 的 Hook 与调试框架,首先电脑端使用命令 pip install frida-tools 安装 frida 模块(此命令默认会安装最新版的 frida 和 frida-tools,如),然后下载 frida-server,下载地址:https://github.com/frida/frida/releases

frida-server 要根据你电脑端安装的 frida 版本和手机的 CPU 架构来选择对应的,使用命令 frida --version 可以查看 frida 版本,使用命令 adb shell 进入手机,输入 getprop ro.product.cpu.abi 查看 CPU 架构,如下图所示,我这里 frida 是 15.2.2 版本,手机 CPU 为 arm64,所以我下载的是 frida-server-15.2.2-android-arm64.xz

某些 Android 低版本使用高版本 frida 可能有问题,遇到问题可尝试降低 frida 版本来解决。

02

03

将下载好的 frida-server 使用 adb push 命令传到手机的 /data/local/tmp/ 目录下,并给予 777 读、写、执行的权限,然后直接运行 frida-server,正常不会有任何输出,当然也可以使用 & 等方式让其在后台运行。

04

然后另开一个 cmd 使用命令 frida-ps -U 可查看手机进程,有输出则正常。

05

逆向分析

使用 adb install 命令安装 UnCrackable-Level1.apk,打开该 APP,会检测到 root,出现 Root detected! 的提示,如下图所示:

06

使用 JEB、JADX、GDA 等工具反编译 apk,直接搜索关键字 Root detected! 即可定位到检测的地方:

07

可以看到图中有三个检测方法 c.a()c.b()c.c(),其中一个返回为真,则弹出 Root detected!,然后前面还有一个 onClick 方法,如果点击 OK 按钮,则触发 System.exit(0);,即退出 APP,先点进三个检测方法看看:

a() 方法通过检测 Android 系统环境变量中是否有 su 文件来判断是否被 root;

b() 方法通过检测 Build.TAGS 中是否包含字符串 test-keys 来判断是否被 root;

c() 方法通过检测指定路径下是否包含指定的文件来判断是否被 root。

08

所以我们这里就有多种过掉检测的方法:

方法一:Hook 三个检测方法,让它们都返回 false,不再执行后续的 a 方法,就不会退出 APP 了:

Java.perform(function(){console.log("[*] Hook begin")var vantagePoint = Java.use("sg.vantagepoint.a.c")vantagePoint.a.implementation = function(){console.log("[*] Hook vantagepoint.a.c.a")this.a();return false;}vantagePoint.b.implementation = function(){console.log("[*] Hook vantagepoint.a.c.b")this.b();return false;}vantagePoint.c.implementation = function(){console.log("[*] Hook vantagepoint.a.c.c")this.c();return false;}}
)

方法二:Hook a() 方法,置空,什么都不做,不弹出对话框,也不退出 APP:

Java.perform(function(){console.log("[*] Hook begin")var mainActivity = Java.use("sg.vantagepoint.uncrackable1.MainActivity");mainActivity.a.implementation = function(){console.log("[*] Hook mainActivity.a")}}
)

方法三:Hook onClick() 方法,点击 OK 后不让其退出 APP,注意这里是内部类的 Hook 写法:

Java.perform(function(){console.log("[*] Hook begin")var mainActivity$1 = Java.use("sg.vantagepoint.uncrackable1.MainActivity$1");mainActivity$1.onClick.implementation = function(){console.log("[*] Hook mainActivity$1.onClick")}}
)

方法四:Hook System.exit() 方法,点击 OK 后不让其退出 APP:

Java.perform(function(){console.log("[*] Hook begin")var javaSystem = Java.use("java.lang.System");javaSystem.exit.implementation = function(){console.log("[*] Hook system.exit")}}
)

root 检测过掉之后,APP 还要输入一个字符串,输入错误会提示 That's not it. Try again.,如下图所示:

09

分析 Java 代码,有一个 if-else 判断,obj 为输入的字符串,a.a(obj) 判断为真,就表示输入正确。

10

跟到 a.a() 方法,可以看到 bArr 是内置的字符串,通过 equals() 方法比较输入的 str 是否和 bArr 相等:

11

bArr 的值,主要经过 sg.vantagepoint.a.a.a() 方法处理后得到,继续跟进去可以发现是 AES 加密算法:

12

这里就可以直接 Hook sg.vantagepoint.a.a.a(),直接拿到加密后的值,也就是我们要的正确字符串,由于这里返回的是 ASCII 码,所以我们还需要在 JavaScript 代码中使用 String.fromCharCode() 将其转换成正常字符,Hook 代码如下:

Java.perform(function(){var cryptoAES = Java.use("sg.vantagepoint.a.a");cryptoAES.a.implementation = function(bArr, bArr2){console.log("[*] Hook cryptoAES")var secret = "";var decryptValue = this.a(bArr, bArr2);console.log("[*] DecryptValue:", decryptValue)for (var i=0; i < decryptValue.length; i++){secret += String.fromCharCode(decryptValue[i]);}console.log("[*] Secret:", secret)return decryptValue;}}
)

运行 Hook 脚本有两种方式,一是结合 Python 使用,二是直接通过 frida 命令使用脚本,注入 Hook 代码也有个时机问题,有时候需要在 APP 启动就开始 Hook,有时候可以等 APP 启动加载完毕了再 Hook,本例中,过 root 检测的时候,如果采用第一、二种方法,即 Hook 三个检测方法或者 a 方法,那就需要在 APP 启动的时候就 Hook,如果采用第三、四种方法,即 Hook onClick() 或者 System.exit() 方法,那么等 APP 启动了再 Hook 也可以。

结合 Python 使用

首先来看一下结合 Python 怎么使用,JavaScript 代码如下(frida-hook.js):

/* ==================================
# @Time    : 2022-08-29
# @Author  : 微信公众号:K哥爬虫
# @FileName: frida-hook.js
# @Software: PyCharm
# ================================== */Java.perform(function(){console.log("[*] Hook begin")// 方法一:Hook 三个检测方法,让它们都返回 false,不再执行后续的 a 方法,就不会退出 APP 了// var vantagePoint = Java.use("sg.vantagepoint.a.c")// vantagePoint.a.implementation = function(){//     console.log("[*] Hook vantagepoint.a.c.a")//     this.a();//     return false;// }// vantagePoint.b.implementation = function(){//     console.log("[*] Hook vantagepoint.a.c.b")//     this.b();//     return false;// }// vantagePoint.c.implementation = function(){//     console.log("[*] Hook vantagepoint.a.c.c")//     this.c();//     return false;// }// 方法二:Hook a() 方法,置空,什么都不做,不弹出对话框,也不退出 APP// var mainActivity = Java.use("sg.vantagepoint.uncrackable1.MainActivity");// mainActivity.a.implementation = function(){//    console.log("[*] Hook mainActivity.a")// }// 方法三:Hook onClick() 方法,点击 OK 后不让其退出 APP// var mainActivity$1 = Java.use("sg.vantagepoint.uncrackable1.MainActivity$1");// mainActivity$1.onClick.implementation = function(){//     console.log("[*] Hook mainActivity$1.onClick")// }// 方法四:Hook System.exit 方法,点击 OK 后不让其退出 APPvar javaSystem = Java.use("java.lang.System");javaSystem.exit.implementation = function(){console.log("[*] Hook system.exit")}var cryptoAES = Java.use("sg.vantagepoint.a.a");cryptoAES.a.implementation = function(bArr, bArr2){console.log("[*] Hook cryptoAES")var secret = "";var decryptValue = this.a(bArr, bArr2);console.log("[*] DecryptValue:", decryptValue)for (var i=0; i < decryptValue.length; i++){secret += String.fromCharCode(decryptValue[i]);}console.log("[*] Secret:", secret)return decryptValue;}}
)

Python 代码如下(frida-hook.py):

# ==================================
# --*-- coding: utf-8 --*--
# @Time    : 2022-08-29
# @Author  : 微信公众号:K哥爬虫
# @FileName: frida-hook.py
# @Software: PyCharm
# ==================================import sys
import fridadef on_message(message, data):if message['type'] == 'send':print("[*] {0}".format(message['payload']))else:print(message)with open("./frida-hook.js", "r", encoding="utf-8") as fp:hook_string = fp.read()# 方式一:attach 模式,已经启动的 APP
process = frida.get_usb_device(-1).attach("Uncrackable1")
script = process.create_script(hook_string)
script.on("message", on_message)
script.load()
sys.stdin.read()# 方式二,spawn 模式,重启 APP
# device = frida.get_usb_device(-1)
# pid = device.spawn(["owasp.mstg.uncrackable1"])
# process = device.attach(pid)
# script = process.create_script(hook_string)
# script.on("message", on_message)
# script.load()
# device.resume(pid)
# sys.stdin.read()

Python 代码中,attach 模式 Hook 已经存在的进程,spawn 模式会重启 APP,启动一个新的进程并挂起,在启动的同时注入 frida 代码,适用于在进程启动前的一些 Hook,attach 模式传入的是 APP 名称,spawn 模式传入的是 APP 包名,查看 APP 名称和包名的方法有很多,这里介绍两个 frida 命令,frida-ps -Uai:列出安装的程序,frida-ps -Ua:列出正在运行中的程序,如下图所示,本例中 Uncrackable1 就是 APP 名称,owasp.mstg.uncrackable1 就是包名:

13

运行 Python 代码,注意手机端也要启动 frida-server,过掉 root 检测后,先随便输入字符串,点击 VERIFY 就会 Hook 到正确的字符串为 I want to believe,再次输入正确的字符串,即可验证成功。

14

frida 命令

不使用 Python,也可以直接使用 frida 命令来实现,和前面 Python 一样也有两种模式,同样的一个是 APP 名一个是包名:

frida -U Uncrackable1 -l .\frida-hook.js:attach 模式,APP 启动后注入 frida 代码;

frida -U -f owasp.mstg.uncrackable1 -l .\frida-hook.js --no-pause:spawn 模式,重启 APP,启动的同时注入 frida 代码。

15

至此,我们完美绕过了 root 检测,并成功找到了正确的字符串。


http://chatgpt.dhexx.cn/article/jUUvWR9y.shtml

相关文章

巴斯勒相机acA1300-60gm

Basler acA1300-60gm GigE 相机配有 e2v EV76C560 CMOS 感光芯片&#xff0c;每秒 60 帧图像&#xff0c;130 万像素分辨率。

如何选择合适的工业相机

如何选择合适的工业相机 目录 如何选择合适的工业相机简洁具体**多相机检测****工业相机的白平衡知识**工业相机的参数工业数字相机常见问题解决方案参考文献 简洁 工业相机有许多项参数&#xff0c;选择合适的工业相机既要考虑工业相机的参数&#xff0c;也要考虑到项目的精度…

巴斯勒BASLER GIGE相机程序调试报错后需要拔网线

巴斯勒BASLER GIGE相机程序调试报错后需要拔网线的个人解决方案 根据SDK的用户手册提示&#xff0c;在相机连接后&#xff0c;直接执行以下程序。 camera.Parameters[PLTransportLayer.HeartbeatTimeout].TrySetValue(1000,IntegerValueCorrection.Nearest); // 1000 ms time…

机器视觉_工业相机及相关配件选型

文章目录 工业相机一、 概述二、 相机参数1. 传感器芯片1.1. CCD&CMOS1.2. CCD1.3. CMOS1.4. 靶面1.5. 传感器芯片选型 2. 黑白or彩色3. 帧数⭐4. 接口类型4.1. POE供电 三、相关硬件⭐1. 镜头1.1. 焦距⭐1.2. 视野⭐1.3. 物距1.4. 景深⭐1.5. 调焦1.6. 镜头的一些理论小知…

Ubuntu环境下配置巴斯勒相机及相机测试

Ubuntu环境下配置巴斯勒相机及相机测试 Ubuntu配置巴斯勒相机及相机测试软硬件要求Ubuntu虚拟系统安装安装c编译器安装Sublime Text 3及配置C运行环境配置巴斯勒相机SDK及代码测试 Ubuntu配置巴斯勒相机及相机测试 软硬件要求 软件 我们对Markdown编辑器进行了一些功能拓展与…

Python之OpenCV 005 工业相机Basler之图像采集

工业机器视觉系统2D应用用到Basler&#xff08;德国&#xff09;&#xff0c;Baumer&#xff08;瑞士&#xff09;&#xff0c;ImageSource&#xff08;台湾&#xff09;&#xff0c;大恒和海康等等牌子工业相机。 Basler&#xff08;巴斯勒&#xff09;是比较常用的&#xff…

机器视觉 · 工业相机

文章目录 工业相机 面阵相机工业相机 线阵相机工业相机 光场相机工业相机 棱镜相机工业相机 多光谱/高光谱工业相机 偏振相机工业相机 传感器 CCD工业相机 传感器 ICCD工业相机 传感器 EMCCD工业相机 传感器 CMOS工业相机 传感器 sCMOS工业相机 传感器 红外探…

BASLER巴斯勒线扫相机使用流程

(Q有答疑)康耐视智能相机Insight-OCR读取案例 1、相机连接—线缆连接 将相机电源线、网线与相机连接,网线另一端连接电脑 无编码器触发时,只需连接网线、电源线即可 2、修改电脑IP 3、修改相机IP 4、相机连接—软件连接 连接相机有两种方式: 1、双击该相机型号进行连接;…

basler工业相机使用经验小记

1&#xff0c;windows10的系统&#xff0c;要用&#xff15;以上的&#xff53;&#xff44;&#xff4b;不然打不开相机。 &#xff12;&#xff0c;如果用&#xff4f;&#xff50;&#xff45;&#xff4e;&#xff43;&#xff56;或&#xff56;&#xff53;程序打开忘记…

国内工业相机十大排名

国内智能相机十大排名&#xff0c;我们今天先不从视觉检测解决方案的角度出发&#xff0c;而是从ccd视觉检测产品的角度来评选出机器视觉龙头企业。众所周知&#xff0c;整个视觉系统我们所用到的软硬件产品有&#xff1a;光源、镜头、工业相机、视觉软件等&#xff0c;那么在这…

工业相机厂家十大排名

我们今天先不从视觉检测解决方案的角度出发&#xff0c;而是从ccd视觉检测产品的角度来评选出机器视觉龙头企业。众所周知&#xff0c;整个视觉系统我们所用到的软硬件产品有&#xff1a;光源、镜头、工业相机、视觉软件等&#xff0c;那么在这些领域哪些公司做的比较好呢&…

机器视觉-工业相机篇

机器视觉-工业相机篇 工业相机又俗称摄像机&#xff0c;相比于传统的民用相机&#xff08;摄像机&#xff09;而言&#xff0c;它具有高的图像稳定性、高传输能力和高抗干扰能力等优点。目前市面上工业相机大多是基于 CCD &#xff08; Charge Coupled Device &#xff09;或 …

丝贝视像的工业相机系列介绍

目前&#xff0c;丝贝视像的主要工业相机型号如下表所示&#xff0c; 型号分辨率最大帧率可采用备注SVV034-USB2752X48060单色全局快门 SVM001-USB21280x102415单色有少量彩色型号SVM001-USB31280x102430单色有少量彩色型号SVP001-USB32560x192015彩色可定购单色 对大多数普…

巴斯勒相机SDK全代码

本文已参与「新人创作礼」活动&#xff0c;一起开启掘金创作之路。 js using Basler.Pylon; using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.T…

机器视觉 工业相机

一、工业相机的结构 工业相机一般由镜头接口、滤光片、图像传感器、驱动电路、数字图像处理模块、转换电路、相机的供电/控制信号接口、图像数据传输组成接口。 二、工业相机的分类 1、按照相机芯片分类 按照芯片工艺分类CCDCMOS曝光方式一般为全局曝光卷帘/全局曝光灵敏…

linux-巴斯勒相机 GigE通信配置步骤

环境&#xff1a;ubuntu18.04 交换机&#xff1a;8端口千兆-带PoE供电功能的交换机 问题&#xff1a;1、始终显示没有设备(no device found)&#xff0c;可能是因为使用了扩展坞&#xff0c;也可能本身就存在这个问题&#xff1b; 2、显示端口冲突。 问题1解决方案&#xff…

Qt调用工业相机之巴斯勒相机

作者&#xff1a;billy 版权声明&#xff1a;著作权归作者所有&#xff0c;商业转载请联系作者获得授权&#xff0c;非商业转载请注明出处 开发环境 操作系统&#xff1a;Windows 10 1903 18362.778 相机型号&#xff1a;BASLER acA 1300-60gm 相机软件&#xff1a;pylon_Run…

W25QXX使用教程

W25QXX是华邦公司生产的一块FLASH储存芯片 那W25Q256为例&#xff1a;驱动方式&#xff1a;单路双路四路SPI、QSPI&#xff1b; 擦写周期&#xff1a;10W次 支持电压&#xff1a;2.7~3.6V 频率&#xff1a;单路最大104Mhz、双路208Mhz、四路416Mhz 容量&#xff1a;容量为32M字…

flash spi w25q128 w25q64 w25q32 w25q16 verilog fpga程序代码

flash spi w25q128 w25q64 w25q32 w25q16 verilog fpga程序代码 fpga w25q128/64/32/16 verilog代码 资料包清单&#xff1a; 1.w25qxx_code_uart_top&#xff1a;altera工程代码&#xff0c;可移植ise&#xff0c;后续会出&#xff0c;需要的话提前加好友 2.功能说明书 注1&a…

STM32读写W25Q

文章目录 硬件外观引脚说明代码摘要代码获取 硬件外观 引脚说明 关于如何接线&#xff1f; 1&#xff0c;CS 2&#xff0c;MISO 3&#xff0c;3.3V 4&#xff0c;GND 5&#xff0c;MOSI 6&#xff0c;SCK 7&#xff0c;3.3V 8&#xff0c;3.3V 关于如何查询芯片引脚&#xff…