本文作者:杉木@涂鸦智能安全实验室
Frida
https://github.com/frida/frida
Frida是一个动态代码插入工具,可用于各种应用程序的调试和逆向工程。它提供了多种安装选项,包括Python和Node.js绑定,并提供了详细的命令行参数和选项。Frida还提供了一个服务器端,可以在目标执行环境(如手机)上安装和运行。此外,Frida还提供了多种工具,如frida-apk、frida-compile和frida-ps。Frida的Python库提供了丰富的功能,可以通过Python脚本调用。最后,文档通过一个CTF题目示例展示了如何使用Frida进行调试和逆向工程。
Install
pip install frida-tools # CLI tools
pip install frida # Python bindings
npm install frida # Node.js bindings
usage: frida [options] targetpositional arguments:args extra arguments and/or targetoptional arguments:-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--certificate CERTIFICATEspeak TLS with HOST, expecting CERTIFICATE--origin ORIGIN connect to remote server with “Origin” header set to ORIGIN--token TOKEN authenticate with HOST using TOKEN--keepalive-interval INTERVALset keepalive interval in seconds, or 0 to disable (defaults to -1 to auto-select based ontransport)--p2p establish a peer-to-peer connection with target--stun-server ADDRESSset STUN server ADDRESS to use with --p2p--relay address,username,password,turn-{udp,tcp,tls}add relay to use with --p2p-f TARGET, --file TARGETspawn FILE-F, --attach-frontmostattach to frontmost application-n NAME, --attach-name NAMEattach to NAME-N IDENTIFIER, --attach-identifier IDENTIFIERattach to IDENTIFIER-p PID, --attach-pid PIDattach to PID-W PATTERN, --await PATTERNawait spawn matching PATTERN--stdio {inherit,pipe}stdio behavior when spawning (defaults to “inherit”)--aux option set aux option when spawning, such as “uid=(int)42” (supported types are: string, bool, int)--realm {native,emulated}realm to attach in--runtime {qjs,v8} script runtime to use--debug enable the Node.js compatible script debugger--squelch-crash if enabled, will not dump crash report to console-O FILE, --options-file FILEtext file containing additional command line options--version show program's version number and exit-l SCRIPT, --load SCRIPTload SCRIPT-P PARAMETERS_JSON, --parameters PARAMETERS_JSONparameters as JSON, same as Gadget-C USER_CMODULE, --cmodule USER_CMODULEload CMODULE--toolchain {any,internal,external}CModule toolchain to use when compiling from source code-c CODESHARE_URI, --codeshare CODESHARE_URIload CODESHARE_URI-e CODE, --eval CODE evaluate CODE-q quiet mode (no prompt) and quit after -l and -e-t TIMEOUT, --timeout TIMEOUTseconds to wait before terminating in quiet mode--pause leave main thread paused after spawning program-o LOGFILE, --output LOGFILEoutput to log file--eternalize eternalize the script before exit--exit-on-error exit with code 1 after encountering any exception in the SCRIPT--kill-on-exit kill the spawned program when Frida exits--auto-perform wrap entered code with Java.perform--auto-reload Enable auto reload of provided scripts and c module (on by default, will be required in thefuture)--no-auto-reload Disable auto reload of provided scripts and c module
Frida详细安装教程
frida server
前面是一些frida的客户端和一些工具类,以及js的工具;接下来是在执行环境下的服务端安装;
https://github.com/frida/frida/releases
先看本地的frida客户端版本;
登录到执行环境下,也就是手机查看环境,下载对应的版本和环境的frida-server,并移动到手机上执行;
进行端口转发;
一开始传到下载目录下面,没有执行权限;
要传到/data/local/tmp目录,然后修改文件权限,再执行;
如果运行不了,关闭liunx的SELinux: echo 0 > /sys/fs/selinux/enforce
。
frida工具
frida-apk
usage: frida-apk [options] path.apkpositional arguments:apk apk fileoptional arguments:-h, --help show this help message and exit-O FILE, --options-file FILEtext file containing additional command line options--version show program's version number and exit-o OUTPUT, --output OUTPUToutput path
frida-compile
usage: frida-compile [options] <module>positional arguments:module TypeScript/JavaScript module to compileoptional arguments:-h, --help show this help message and exit-O FILE, --options-file FILEtext file containing additional command line options--version show program's version number and exit-o OUTPUT, --output OUTPUTwrite output to <file>-w, --watch watch for changes and recompile-S, --no-source-maps omit source-maps-c, --compress compress using terser-v, --verbose be verbose
frida-ps
usage: frida-ps [options]optional arguments:-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--certificate CERTIFICATEspeak TLS with HOST, expecting CERTIFICATE--origin ORIGIN connect to remote server with “Origin” header set to ORIGIN--token TOKEN authenticate with HOST using TOKEN--keepalive-interval INTERVALset keepalive interval in seconds, or 0 to disable (defaults to -1 to auto-select based on transport)--p2p establish a peer-to-peer connection with target--stun-server ADDRESSset STUN server ADDRESS to use with --p2p--relay address,username,password,turn-{udp,tcp,tls}add relay to use with --p2p-O FILE, --options-file FILEtext file containing additional command line options--version show program's version number and exit-a, --applications list only applications-i, --installed include all installed applications-j, --json output results as JSON
frida API
先看看python的frida库有哪些能力;
通过一道CTF题来认识一下frida
题目文件查看文章绑定的资源。
一道看雪的题目,打开APP执行一下看看;
有了关键字,反编译app后搜索一下,就在main中,可以清晰的看到入口处理逻辑;
主要处理逻辑在这个vvvv里面,只有vvvv通过验证,就会返回flag;进去vvvv里面看看;
有两个判断条件,一个是两个地方输入的长度总共要等于5;一个是要和bytes§一样;也就是说返回跟”6f452303f18605510aac694b0f5736beebf110bf“一样的内容就可以通过,这里为了学习如何使用frida,就先绕过验证;因为要拿flag的话,需要进行爆破,从题目提示得知,5位数字,然后经过eeee处理后等于bytes§就是对应的flag了;
先试着简单打印我们输入的内容;
function main(){//frida的main函数入口Java.perform(function() { //获取包名类方法Java.use("com.kanxue.pediy1.VVVVV").VVVV.implementation = function(x,y){//hook逻辑var result = this.VVVV(x,y);console.log("x,y,result:",x,y,result);return result;}})
}
setImmediate(main)
当然frida支持多种方式调用,上面是js脚本,可以直接用frida命令的方式调用;
也可以使用python的frida库调用js的方式来执行,如下;
import frida# 1. 用户输入目标进程名称
target_process = input("请输入目标进程名称:")# 2. 通过进程名称附加到目标进程
process = frida.get_usb_device().attach(target_process)# 3. 读取JavaScript文件内容
with open("exp.js", "r") as file:js_code = file.read()# 4. 创建一个Frida脚本
script = process.create_script(js_code)# 5. 定义回调函数,用于处理脚本的消息
def on_message(message, data):print("[*] Message:", message)# 6. 注册回调函数
script.on("message", on_message)# 7. 加载并运行脚本
script.load()# 8. 保持脚本运行,直到手动停止
input("[!] Press Enter to stop...")# 9. 分离脚本并关闭Frida会话
script.unload()
process.detach()
思路是通过篡改eeee函数执行结果,让eeee返回跟bytes§一样的内容即可让程序验证通过;
function main(){Java.perform(function() {Java.use("com.kanxue.pediy1.VVVVV").eeeee.implementation = function(x){var result = this.eeeee(x);console.log("x,result:",x,result);var v = result;v = Java.use("java.lang.String").$new("6f452303f18605510aac694b0f5736beebf110bf").getBytes();console.log(v);return v;}})
}
setImmediate(main)
上面只是绕过了程序验证,并非题目实际的flag,要获得真实flag还需要对5位数字进行爆破;
下面是爆破flag的脚本;
function firethehome(){Java.perform(function(){var VVVVV_Class = Java.use("com.kanxue.pediy1.VVVVV")console.log("VVVVV_Class:", VVVVV_Class)VVVVV_Class.eeeee.implementation=function(x){var result = this.eeeee(x);console.log("VVVVV.eeeee is hook! x ,result",x,JSON.stringify(result));return result;}var ByteString = Java.use("com.android.okhttp.okio.ByteString");console.log(ByteString);var pSign = Java.use("java.lang.String").$new("6f452303f18605510aac694b0f5736beebf110bf").getBytes();console.log( ByteString.of(pSign).hex());// 爆破5位for(var i = 9999;i<100000;i++){console.log("i="+i);var v = Java.use("java.lang.String").$new(String(i));var vSign = VVVVV_Class.eeeee(v);console.log("vSign:",ByteString.of(vSign).hex());if(ByteString.of(vSign).hex() == ByteString.of(pSign).hex()){console.log("i="+i);break;}}})
}
setImmediate(firethehome)
Frida及Brida学习记录 - 先知社区
JavaScript API
Frida Android hook
[原创]举杯邀Frida,对影成三题-Android安全-看雪-安全社区|安全招聘|kanxue.com
漏洞悬赏计划:涂鸦智能安全响应中心(https://src.tuya.com)欢迎白帽子来探索。