赞
踩
Frida是一款基于python + javascript 的hook框架,适用于android/ios/linux/win/osx等平台。Frida的动态代码执行功能,主要是在它的核心引擎Gum中用C语言来实现的。

pip install frida
pip install frida-tools
紧接着查看自己frida版本:
frida --version
然后查看自己的目标机架构版本,但有些可能不能显示出目标机架构版本,所以我直接到客户端:

模拟器版本: 7.0.1.0005-7.1.2700210226
系统版本: Windows10-64bit-8cpu
电脑型号: ASUSTeK COMPUTER INC.-TUF Gaming FX505DT_FX95DT
CPU: AMD Ryzen 7 3750H with Radeon Vega Mobile Gfx
总内存: 15809MB
可用内存: 8615MB
是否开启VT: 开启
渲染模式: OpenGL+
OpenGL版本: 4.6.0 NVIDIA 431.87
OpenGL渲染: GeForce GTX 1650/PCIe/SSE2
是否独显: 开启
显卡1: NVIDIA GeForce GTX 1650
显卡2: AMD Radeon™ RX Vega 10 Graphics
防火墙: 开启(推荐关闭)
安装路径: D:\夜神模拟器\Nox\bin
日志文件路径: C:\Users\ASUS\AppData\Local\Nox
模拟器磁盘大小: 总共 64G, 剩余 61G

64位程序执行不起来,所以的话frida-server下载32位
frida-serverfrida-server 是一个守护进程,通过TCP和Frida核心引擎通信,默认的监听端口是27042




adb devices

/data/local/tmp,然后修改属性为可执行adb push G:\buuctf\frida-server-14.2.2-android-x86\fs data/local/tmp/frida-server_test

使用push指令,这里注意点,如果是新安装的夜神模拟器,那么会遇到这个报错:
adb: error: failed to copy 'G:\buuctf\frida-server-14.2.14-android-x86_64\fs_Rui' to
'data\local\tmp\fs_Rui': couldn't create file: Read-only file system

文件系统仅仅可读。
/proc/mounts文件里面的目录的权限,确定是否缺少w权限,如果是的话,那么在proc目录下执行以下代码:mount -o remount,rw /
(一般到这里就可以试试push指令能不能用了,因为报错是文件系统的原因)
adb remount
adb root
linux下的目录(后者是linux目录)都是反斜杠,写正的没用。
adb push G:\buuctf\frida-server-14.2.14-android-x86_64\fs_Rui data\local\tmp\fs_Rui
adb push G:\buuctf\frida-server-14.2.2-android-x86\fs data/local/tmp/frida-server_test
adb shell //进入模拟器
exit//退出模拟器
//以下均为linux命令行
su
cd data/local/tmp
chmod 777 frida-server_test

./frida-server_test

frida-ps -U ,这行命令是列出手机上所有的进程信息,如果出现进程信息则说明环境搭配成功:frida-ps -U

但是我这里利用脱壳脚本,去连接frida-server,直接连接不上

求救
adb forward tcp:27042 tcp:27042
adb forward tcp:27043 tcp:27043
adb server version (31) doesn’t match this client (36),以至于每次一使用脚本连接,然后frida-server就会挂掉,然后就出现了上方的报错,只需要把sdk的adb复制一份放在夜神里面就行喽

D:\桌面\apktool.jar d D:\桌面\02.apk -o targetappFolder
D:\桌面\apktool.jar b -o repackaged.apk targetappFolder/
keytool -genkey -v -keystore custom.keystore -alias mykeyaliasname -keyalg RSA -keysize 2048 -validity 10000
jarsigner -sigalg SHA256withRSA -digestalg SHA1 -keystore custom.keystore -storepass 你的密码 repackaged.apk mykeyaliasname
这个custom.keystore也就是前面所生成的keystore,注意路径问题就行
jarsigner -verify repackaged.apk




D:\桌面>D:\桌面\apktool.jar d targetapp.apk -o targetappFolder D:\桌面>D:\桌面\apktool.jar d targetapp.apk -o targetappFolder D:\桌面>D:\桌面\apktool.jar d D:\桌面\02.apk -o targetappFolder D:\桌面>apktool b -o repackaged.apk targetappFolder/ 'apktool' 不是内部或外部命令,也不是可运行的程序 或批处理文件。 D:\桌面>apktool b -o repackaged.apk targetappFolder/ 'apktool' 不是内部或外部命令,也不是可运行的程序 或批处理文件。 D:\桌面>D:\桌面\apktool.jar apktool b -o repackaged.apk targetappFolder/ D:\桌面>D:\桌面\apktool.jar b -o repackaged.apk targetappFolder/ D:\桌面>keytool -genkey -v -keystore custom.keystore -alias mykeyaliasname -keyalg RSA -keysize 2048 -validity 10000 输入密钥库口令: 再次输入新口令: 您的名字与姓氏是什么? [Unknown]: 张瑞彪 您的组织单位名称是什么? [Unknown]: 江科大 您的组织名称是什么? [Unknown]: 江科大 您所在的城市或区域名称是什么? [Unknown]: 江科大 您所在的省/市/自治区名称是什么? [Unknown]: 江科大 该单位的双字母国家/地区代码是什么? [Unknown]: 江科大 CN=张瑞彪, OU=江科大, O=江科大, L=江科大, ST=江科大, C=江科大是否正确? [否]: 是 正在为以下对象生成 2,048 位RSA密钥对和自签名证书 (SHA256withRSA) (有效期为 10,000 天): CN=张瑞彪, OU=江科大, O=江科大, L=江科大, ST=江科大, C=江科大 [正在存储custom.keystore] D:\桌面>jarsigner -sigalg SHA256withRSA -digestalg SHA1 -keystore custom.keystore -storepass 你的密码 repackaged.apk mykeyaliasname jarsigner 错误: java.lang.RuntimeException: 密钥库加载: keystore password was incorrect D:\桌面>jarsigner -sigalg SHA256withRSA -digestalg SHA1 -keystore custom.keystore -storepass 123456 repackaged.apk mykeyaliasname jarsigner 错误: java.lang.RuntimeException: 密钥库加载: D:\桌面\custom.keystore (系统找不到指定的文件。) D:\桌面>jarsigner -sigalg SHA256withRSA -digestalg SHA1 -keystore D:\桌面\custom.keystore -storepass 123456 repackaged.apk mykeyaliasname jar 已签名。 警告: 签名者证书为自签名证书。 为 -digestalg 选项指定的 SHA1 算法被视为存在安全风险。此算法将在未来的更新中被禁用。 D:\桌面>zipalign 4 repackaged.apk final.apk 'zipalign' 不是内部或外部命令,也不是可运行的程序 或批处理文件。 D:\桌面>jarsigner -verify repackaged.apk jar 已验证。 警告: 此 jar 包含其证书链无效的条目。原因: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target 此 jar 包含其签名者证书为自签名证书的条目。 SHA1 摘要算法被视为存在安全风险。此算法将在未来的更新中被禁用。 此 jar 包含的签名没有时间戳。如果没有时间戳, 则在其中任一签名者证书到期 (最早为 2048-08-30) 之后, 用户可能无法验证此 jar。 有关详细信息, 请使用 -verbose 和 -certs 选项重新运行。
frida-ps--version show program's version number and exit
-h, --help show this help message and exit
-D ID, --device=ID connect to device with the given ID
-U, --usb connect to USB device
-R, --remote connect to remote frida-server
-H HOST, --host=HOST connect to remote frida-server on HOST
-a, --applications list only applications
-i, --installed include all installed applications

2. frida-trace 动态跟踪
--version show program's version number and exit -h, --help show this help message and exit -D ID, --device=ID connect to device with the given ID -U, --usb connect to USB device -R, --remote connect to remote frida-server -H HOST, --host=HOST connect to remote frida-server on HOST -f FILE, --file=FILE spawn FILE -n NAME, --attach-name=NAME attach to NAME -p PID, --attach-pid=PID attach to PID --debug enable the Node.js compatible script debugger --disable-jit disable JIT -I MODULE, --include-module=MODULE include MODULE -X MODULE, --exclude-module=MODULE exclude MODULE -i FUNCTION, --include=FUNCTION include FUNCTION -x FUNCTION, --exclude=FUNCTION exclude FUNCTION -a MODULE!OFFSET, --add=MODULE!OFFSET add MODULE!OFFSET -T, --include-imports include program's imports -t MODULE, --include-module-imports=MODULE include MODULE imports -m OBJC_METHOD, --include-objc-method=OBJC_METHOD include OBJC_METHOD
示例:
注意:使用frida-trace时,Android端一定要打开frida-server,否则就会出现这样
启动手机中的Chrome浏览器


frida-trace -i "open" -U com.android.chrome


可以看到终端中出现:open:Loaded handler at :”/用户名/__handlers__/libc.so/open.js”
frida-trace会生成一个javascript文件,然后Frida会将其注入到进程中,并跟踪特定的调用。生成的open.js脚本将钩住libc.so中的open函数并输出参数.
默认的open.js:
/* * Auto-generated by Frida. Please modify to match the signature of open. * This stub is currently auto-generated from manpages when available. * * For full API reference, see: https://frida.re/docs/javascript-api/ */ { /** * Called synchronously when about to call open. * * @this {object} - Object allowing you to store state for use in onLeave. * @param {function} log - Call this function with a string to be presented to the user. * @param {array} args - Function arguments represented as an array of NativePointer objects. * For example use args[0].readUtf8String() if the first argument is a pointer to a C string encoded as UTF-8. * It is also possible to modify arguments by assigning a NativePointer object to an element of this array. * @param {object} state - Object allowing you to keep state across function calls. * Only one JavaScript function will execute at a time, so do not worry about race-conditions. * However, do not use this to store function arguments across onEnter/onLeave, but instead * use "this" which is an object for keeping state local to an invocation. */ onEnter(log, args, state) { log('open()'); }, /** * Called synchronously when about to return from open. * * See onEnter for details. * * @this {object} - Object allowing you to access state stored in onEnter. * @param {function} log - Call this function with a string to be presented to the user. * @param {NativePointer} retval - Return value represented as a NativePointer object. * @param {object} state - Object allowing you to keep state across function calls. */ onLeave(log, retval, state) { } }


可以修改open.js进行操作,然后进行终端输出:
/* * Auto-generated by Frida. Please modify to match the signature of open. * This stub is currently auto-generated from manpages when available. * * For full API reference, see: http://www.frida.re/docs/javascript-api/ */ { /** * Called synchronously when about to call open. * * @this {object} - Object allowing you to store state for use in onLeave. * @param {function} log - Call this function with a string to be presented to the user. * @param {array} args - Function arguments represented as an array of NativePointer objects. * For example use Memory.readUtf8String(args[0]) if the first argument is a pointer to a C string encoded as UTF-8. * It is also possible to modify arguments by assigning a NativePointer object to an element of this array. * @param {object} state - Object allowing you to keep state across function calls. * Only one JavaScript function will execute at a time, so do not worry about race-conditions. * However, do not use this to store function arguments across onEnter/ onLeave, but instead * use "this" which is an object for keeping state local to an invocation. */ onEnter: function (log, args, state) { log("open(" + "path=\"" + Memory.readUtf8String(args[0]) + "\"" + ", oflag=" + args[1] + ")"); }, /** * Called synchronously when about to return from open. * * See onEnter for details. * * @this {object} - Object allowing you to access state stored in onEnter. * @param {function} log - Call this function with a string to be presented to the user. * @param {NativePointer} retval - Return value represented as a NativePointer object. * @param {object} state - Object allowing you to keep state across function calls. */ onLeave: function (log, retval, state) { } }

示例:
从Python注入chrome.js脚本
注意:从命令行加载脚本然后生成一个命令的进程时,Frida容易崩溃。所以先生成进程,再让Frida注入脚本
#!/usr/bin/python import frida # js jscode= """ console.log("[*] Starting script"); Java.perform(function() { var Activity = Java.use("android.app.Activity"); Activity.onResume.implementation = function () { console.log("[*] onResume() got called!"); this.onResume(); }; }); """ # startup frida and attach to com.android.chrome process on a usb device process = frida.get_remote_device().attach("com.android.chrome") # create a script for frida of jsccode script = process.create_script(jscode) # and load the script script.load()
注意点:
adb forward tcp:27042 tcp:27042
adb forward tcp:27043 tcp:27043
否则如下报错

frida.get_usb_device().attach(),改用frida.get_remote_device().attach(),否则如下报错:
学习Frida的magic,并通过Frida覆盖一个函数。此外,我们还将介绍如何从外部脚本加载代码,而不是将代码键入cli,因为这种方式更方便。首先,将下面的代码保存到一个脚本文件中,例如chrome.js:
1.
Java.perform(function () {
var Activity = Java.use("android.app.Activity");
Activity.onResume.implementation = function () {
console.log("[*] onResume() got called!");
this.onResume();
};
});
上面的代码将会覆盖android.app.Activity类的onResume函数。它会调用Java.use来接收这个类的包装对象,并访问其onResume函数的implementation属性,以提供一个新的实现。在新的函数体中,它将通过this.onResume()调用原始的onResume实现,所以应用程序依然可以继续正常运行。
通过命令行注入:
frida -U -l chrome.js com.android.chrome
一旦触发了onResume——例如切换到另一个应用程序并返回到模拟器中的Chrome——您将收到下列输出:[*] onResume() got called!


如上图所示。
但是我使用python绑定进行注入,直接没用。。。搞不懂为什么
#!/usr/bin/python import frida # put your javascript-code here jscode= """ console.log("[*] Starting script"); Java.perform(function() { var Activity = Java.use("android.app.Activity"); Activity.onResume.implementation = function () { console.log("[*] onResume() got called!"); this.onResume(); }; }); """ # startup frida and attach to com.android.chrome process on a usb device process = frida.get_usb_device().attach("com.android.chrome") # create a script for frida of jsccode script = process.create_script(jscode) # and load the script script.load()


这里呢,是我误会了这行命令行的作用:
frida -U -f com.android.xxxxx —no-pause
它的作用也就是:—no-pause不会中断应用程序,并将生成的进程的任务留给FRIDA,这会打开一个shell,在里边使用Javascript API向Frida写命令,至于用
frida -U -l chrome.js com.android.chrome
它仅仅只是注入js脚本,然后进行阻塞,回传log
python绑定和它并没有任何关系。python绑定的log回传是在Python脚本里面的。
使用命令的时候,建议使用如下这个:
frida -U -f com.android.chrome --no-pause
如果不加--no-pause的话,那么需要手动启动主线程函数

输入%resume来进行线程的启动
这里的话请教了夜影学长,然后他说Python脚本注入的话,显示log是在python里面显示的

显示的东西是由frida里执行的js发给py的,所以的话,py要自己负责阻塞,需要input阻塞,在最后加上sys.stdin.read(),最后也就变成这样:
#!/usr/bin/python import frida import sys # put your javascript-code here jscode= """ console.log("[*] Starting script"); Java.perform(function() { var Activity = Java.use("android.app.Activity"); Activity.onResume.implementation = function () { console.log("[*] onResume() got called!"); this.onResume(); }; }); """ # startup frida and attach to com.android.chrome process on a usb device process = frida.get_usb_device().attach("com.android.chrome") # create a script for frida of jsccode script = process.create_script(jscode) # and load the script script.load() sys.stdin.read()

Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。