一篇文章带你领悟 Frida 的精髓(基于安卓8.1)

转载(一篇文章带你领悟Frida的精髓(基于安卓8.1)):https://www.freebuf.com/articles/system/190565.html

《Frida操作手册》:https://github.com/hookmaster/frida-all-in-one

Frida github 地址:https://github.com/dweinstein/awesome-frida

前言

受 《Xposed模块编写的那些事》:https://www.freebuf.com/articles/terminal/114910.html 影响,感觉有必要写一篇文章来回馈 freebuf 社区。现在最火爆的又是 frida,该框架从 Java 层 hook 到 Native 层 hook 无所不能,虽然持久化还是要依靠 Xposed hookzz 等开发框架,但是 frida 的动态和灵活对逆向以及自动化逆向的帮助非常巨大。

frida 是啥?

首先,frida 是啥,github目录 Awesome Frida( https://github.com/dweinstein/awesome-frida )这样介绍 frida 的:

Frida is Greasemonkey for native apps, or, put in more technical terms, it’s a dynamic code instrumentation toolkit. It lets you inject snippets of JavaScript into native apps that run on Windows, Mac, Linux, iOS and Android. Frida is an open source software.

frida 是平台原生 app 的 Greasemonkey,说的专业一点,就是一种动态插桩工具,可以插入一些代码到原生 app 的内存空间去,(动态地监视和修改其行为),这些原生平台可以是 Win、Mac、Linux、Android 或者 iOS。而且 frida 还是开源的。

Greasemonkey 可能大家不明白,它其实就是 firefox 的一套插件体系,使用它编写的脚本可以直接改变 firefox 对网页的编排方式,实现想要的任何功能。而且这套插件还是外挂的,非常灵活机动。

frida 也是一样的道理。

frida 为什么这么火?

动静态修改内存实现作弊一直是刚需,比如 金山游侠,本质上 frida 做的跟它是一件事情。原则上是可以用 frida 把金山游侠,包括 CheatEngine 等 "外挂" 做出来的。

当然,现在已经不是直接修改内存就可以高枕无忧的年代了。大家也不要这样做,做外挂可是违法行为。

在逆向的工作上也是一样的道理,使用 frida 可以 "看到" 平时看不到的东西。出于编译型语言的特性,机器码在 CPU 和内存上执行的过程中,其内部数据的交互和跳转,对用户来讲是看不见的。当然如果手上有源码,甚至哪怕有带调试符号的可执行文件包,也可以使用 gbd、lldb 等调试器连上去看。

那如果没有呢?如果是纯黑盒呢?又要对 app 进行逆向和动态调试、甚至自动化分析以及规模化收集信息的话,我们需要的是细粒度的流程控制和代码级的可定制体系,以及不断对调试进行动态纠正和可编程调试的框架,这就是 frida。

frida 使用的是 python、JavaScript 等 "胶水语言" 也是它火爆的一个原因,可以迅速将逆向过程自动化,以及整合到现有的架构和体系中去,为你们发布 "威胁情报"、"数据平台" 甚至 "AI风控" 等产品打好基础。

frida 实操环境

frida 分 客户端环境服务端环境

  • 客户端:编写 Python 代码,用于连接远程设备,提交要注入的代码到远程,接受服务端的发来的消息等。可以把 客户端 理解成控制端。
  • 服务端:需要用 Javascript 代码注入到目标进程,操作内存数据,给客户端发送消息等操作。可以把 服务端 理解成被控端。

假如我们要用 PC 来对 Android 设备上的某个进程进行操作,那么 PC 就是客户端,而 Android 设备就是服务端

准备 frida 服务端环境

服务端在 Android 平台测试。服务端环境准备步骤如下:

根据自己的平台下载 frida 服务端并解压:https://github.com/frida/frida/releases

执行以下命令将服务端推到手机的 /data/local/tmp 目录:

adb push frida-server /data/local/tmp/frida-server

执行以下命令修改 frida-server 文件权限:

adb shell chmod 777 /data/local/tmp/frida-server

注:Windows 系统执行命令可以在 CMD 中进行;Linux 和 MacOS 执行命令可以在终端中进行。adb 是 Android 一个调试工具,具体安装方法不是本文的重点。

准备 客户端环境

在 PC 上安装 Python 的运行环境,安装完成后执行下面的命令安装 frida:pip install frida

frida 命令帮助:

kali@kali:~$ frida -h
Usage: frida [options] targetOptions:--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-F, --attach-frontmostattach to frontmost application-n NAME, --attach-name=NAMEattach to NAME-p PID, --attach-pid=PIDattach to PID--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)--runtime=duk|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-l SCRIPT, --load=SCRIPTload SCRIPT-P PARAMETERS_JSON, --parameters=PARAMETERS_JSONparameters as JSON, same as Gadget-C CMODULE, --cmodule=CMODULEload CMODULE-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--no-pause            automatically start main thread after startup-o LOGFILE, --output=LOGFILEoutput to log file--exit-on-error       exit with code 1 after encountering any exception inthe SCRIPT
kali@kali:~$ 

如何将一个脚本注入到 Android 目标进程:frida -U -l myhook.js com.xxx.xxxx

参数解释:

  • -U    指定对 USB 设备操作
  • -l    指定加载一个 Javascript 脚本
  • 最后指定一个进程名,如果想指定进程 pid,用 -p 选项。

查看正在运行的进程可以用 frida-ps -U 命令,frida 运行过程中,执行 %resume 重新注入,执行 %reload 来重新加载脚本;执行 exit 结束脚本注入

用 kali linux 的原因是工具很全面,否则 python 和 node 的各种权限、环境和依赖实在是烦。

主机:

Host:Macbook Air CPU: i5 Memory:8GSystem:Kali Linux 2018.4 (Native,非虚拟机)

客户端:

client:Nexus 6 shamu CPU:Snapdragon 805 Mem:3GSystem:lineage-15.1-20181123-NIGHTLY-shamu,android 8.1

安装 "安卓sdk",然后添加环境变量 ,这样 adb 和 fastboot 命令就有了。下载 frida-server(下载地址: https://github.com/frida/frida/releases )并把对应的 frida-server 拷贝到安卓机器里去,使用 root用户跑起来,保持 adb 的连接不要断开。

$ ./adb root                               # might be required
$ ./adb push frida-server /data/local/tmp/
$ ./adb shell "chmod 755 /data/local/tmp/frida-server"
$ ./adb shell "/data/local/tmp/frida-server &"

最后在 kali linux 里安装好 frida 即可,一句话命令即可,保证不出错。(可能会需要先安装 pip,a安装命令:curl https://bootstrap.pypa.io/get-pip.py -o get-pip.py

pip install frida-tools

然后用 frida-ps -U 命令连上去,就可以看到正在运行的进程了。

基本能力 1:hook参数、修改结果

先自己写个 app

package com.roysue.demo02;import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;public class MainActivity extends AppCompatActivity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);while (true){try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}fun(50,30);}}void fun(int x , int y ){Log.d("Sum" , String.valueOf(x+y));}}

原理上很简单,就是间隔一秒在控制台输出一下 fun(50,30) 函数的结果,fun() 这个函数的作用是求和。那最终结果在控制台如下所示。

$ adb logcat |grep Sum
11-26 21:26:23.234  3245  3245 D Sum     : 80
11-26 21:26:24.234  3245  3245 D Sum     : 80
11-26 21:26:25.235  3245  3245 D Sum     : 80
11-26 21:26:26.235  3245  3245 D Sum     : 80
11-26 21:26:27.236  3245  3245 D Sum     : 80
11-26 21:26:28.237  3245  3245 D Sum     : 80
11-26 21:26:29.237  3245  3245 D Sum     : 80

图示:

现在我们来写一段js代码,并用 frida-server 将这段代码加载到 com.roysue.demo02 中去,执行其中的 hook 函数。

s1.js 代码:

console.log("Script loaded successfully ");
Java.perform(function x() {console.log("Inside java perform function");//定位类var my_class = Java.use("com.roysue.demo02.MainActivity");console.log("Java.Use.Successfully!");//定位类成功!//在这里更改类的方法的实现(implementation)my_class.fun.implementation = function(x,y){//打印替换前的参数console.log( "original call: fun("+ x + ", " + y + ")");//把参数替换成2和5,依旧调用原函数var ret_value = this.fun(2, 5);return ret_value;}
});

然后我们在 kali 主机上使用一段 python 脚本,将这段 js 脚本 "传递" 给安卓系统里正在运行的frida-server。

loader.py 代码:

import time
import frida# 连接安卓机上的frida-server
device = frida.get_usb_device()
# 启动`demo02`这个app
pid = device.spawn(["com.roysue.demo02"])
device.resume(pid)
time.sleep(1)
session = device.attach(pid)
# 加载s1.js脚本
with open("s1.js") as f:script = session.create_script(f.read())
script.load()# 脚本会持续运行等待输入
raw_input()

然后就是保证 frida-server 一直处于运行。在 kali 主机输入frida-ps -U 命令,如果安卓机上的进程出现了,则 frida-server 运行良好。

还需要保证 selinux 是关闭的状态,可以在 adb shell 里,su - 获得 root 权限之后,输入 setenforce 0 命令来获得,在 Settings→About Phone→SELinux status 里看到 Permissive,说明selinux 关闭成功。

然后在 kali 主机上输入 python loader.js,可以观察到安卓机上 com.roysue.demo02 这个 app 马上重启了。然后 $ adb logcat|grep Sum 里的内容也变了。

说明脚本执行成功了,代码也插到 com.roysue.demo02 这个包里去,并且成功执行了,s1.js 里的代码成功执行了,并且把交互结果传回了 kali 主机上。

基本能力 2:参数构造、方法重载、隐藏函数的处理

我们现在把 app 的代码稍微写复杂一点点:

package com.roysue.demo02;import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;public class MainActivity extends AppCompatActivity {private String total = "@@@###@@@";@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);while (true){try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}fun(50,30);Log.d("ROYSUE.string" , fun("LoWeRcAsE Me!!!!!!!!!"));}}void fun(int x , int y ){Log.d("ROYSUE.Sum" , String.valueOf(x+y));}String fun(String x){total +=x;return x.toLowerCase();}String secret(){return total;}
}

app 运行起来后在使用 logcat 打印出来的日志如下:

$ adb logcat |grep ROYSUE
11-26 22:22:35.689  3051  3051 D ROYSUE.Sum: 80
11-26 22:22:35.689  3051  3051 D ROYSUE.string: lowercase me!!!!!!!!!
11-26 22:22:36.695  3051  3051 D ROYSUE.Sum: 80
11-26 22:22:36.696  3051  3051 D ROYSUE.string: lowercase me!!!!!!!!!
11-26 22:22:37.696  3051  3051 D ROYSUE.Sum: 80
11-26 22:22:37.696  3051  3051 D ROYSUE.string: lowercase me!!!!!!!!!
11-26 22:22:38.697  3051  3051 D ROYSUE.Sum: 80
11-26 22:22:38.697  3051  3051 D ROYSUE.string: lowercase me!!!!!!!!!
11-26 22:22:39.697  3051  3051 D ROYSUE.Sum: 80
11-26 22:22:39.698  3051  3051 D ROYSUE.string: lowercase me!!!!!!!!!

图示:

可以看到 fun() 方法有了重载,在参数是两个 int 的情况下,返回两个 int 之和。在参数为 String 类型之下,则返回字符串的小写形式。另外,secret() 函数为隐藏方法,在 app 里没有被直接调用。
这时候如果我们直接使用上面的 js 脚本和 loader.js 来加载的话,肯定会崩溃。为了看到崩溃的信息,我们对 loader.js 做一些处理。

import time
import fridadef my_message_handler(message, payload):  # 定义错误处理print(message)print(payload)# 连接安卓机上的 frida-server
device = frida.get_usb_device()
# 启动`demo02`这个app
pid = device.spawn(["com.example.demo2"])
device.resume(pid)
time.sleep(1)
session = device.attach(pid)
# 加载s1.js脚本
with open("s1.js", encoding='utf-8') as f:script = session.create_script(f.read())script.on("message", my_message_handler)  # 调用错误处理
script.load()# 脚本会持续运行等待输入
input()

再运行$ python loader.py的话,就会看到如下的错误信息返回:

$ python loader.py
Script loaded successfully
Inside java perform function
Java.Use.Successfully!
{u'columnNumber': 1, u'description': u"Error: fun(): has more than one overload, use .overload(<signature>) to choose from:\n\t.overload('java.lang.String')\n\t.overload('int', 'int')", u'fileName': u'frida/node_modules/frida-java/lib/class-factory.js', u'lineNumber': 2233, u'type': u'error', u'stack': u"Error: fun(): has more than one overload, use .overload(<signature>) to choose from:\n\t.overload('java.lang.String')\n\t.overload('int', 'int')\n    at throwOverloadError (frida/node_modules/frida-java/lib/class-factory.js:2233)\n    at frida/node_modules/frida-java/lib/class-factory.js:1468\n    at x (/script1.js:14)\n    at frida/node_modules/frida-java/lib/vm.js:43\n    at M (frida/node_modules/frida-java/index.js:347)\n    at frida/node_modules/frida-java/index.js:299\n    at frida/node_modules/frida-java/lib/vm.js:43\n    at frida/node_modules/frida-java/index.js:279\n    at /script1.js:15"}
None

可以看出是一个 throwOverloadError,这时候就是因为我们没有处理重载,造成的重载处理错误。这个时候就需要我们来处理重载了,在 js 脚本中处理重载是这样写的:

my_class.fun.overload("int" , "int").implementation = function(x,y){//...
}
my_class.fun.overload("java.lang.String").implementation = function(x){//...
}

其中参数均为两个 int 的情况下,上一节已经讲过了。参数为 String类的时候,由于 String类 不是Java 基本数据类型( https://www.runoob.com/java/java-basic-datatypes.html ),而是 java.lang.String 类型,所以在替换参数的构造上,需要花点心思。

var string_class = Java.use("java.lang.String"); //获取String类型my_class.fun.overload("java.lang.String").implementation = function(x){console.log("*************************************");var my_string = string_class.$new("My TeSt String#####"); //new一个新字符串console.log("Original arg: " + x);var ret =  this.fun(my_string); // 用新的参数替换旧的参数,然后调用原函数获取结果console.log("Return value: "+ ret);console.log("*************************************");return ret;
};

这样我们对于重载函数的处理就算是 ok 了。我们到实验里来看下:

$ python loader.py
Script loaded successfully
Inside java perform function
original call: fun(50, 30)
*************************************
Original arg: LoWeRcAsE Me!!!!!!!!!
Return value: my test string#####
*************************************
original call: fun(50, 30)
*************************************
Original arg: LoWeRcAsE Me!!!!!!!!!
Return value: my test string#####
*************************************
original call: fun(50, 30)
*************************************
Original arg: LoWeRcAsE Me!!!!!!!!!
Return value: my test string#####
*************************************

然后 logcat 打出来的结果也变了。

$ adb logcat |grep ROYSUE
11-26 22:23:29.597  3244  3244 D ROYSUE.Sum: 7
11-26 22:23:29.673  3244  3244 D ROYSUE.string: my test string#####
11-26 22:23:30.689  3244  3244 D ROYSUE.Sum: 7
11-26 22:23:30.730  3244  3244 D ROYSUE.string: my test string#####
11-26 22:23:31.740  3244  3244 D ROYSUE.Sum: 7
11-26 22:23:31.789  3244  3244 D ROYSUE.string: my test string#####
11-26 22:23:32.797  3244  3244 D ROYSUE.Sum: 7
11-26 22:23:32.833  3244  3244 D ROYSUE.string: my test string#####

最后再说一下隐藏方法的调用,frida 对其的处理办法跟 Xposed 是非常像的,Xposed 使用的是XposedHelpers.findClass("com.example.inner_class_demo.demo", lpparam.classLoader); 方法,直接 findClass,

其实 frida 也非常类似,也是使用的直接到内存里去寻找的方法,也就是 Java.choose(className, callbacks) 函数,通过类名触发回掉函数。

Java.choose("com.roysue.demo02.MainActivity" , {onMatch : function(instance){ //该类有多少个实例,该回调就会被触发多少次console.log("Found instance: "+instance);console.log("Result of secret func: " + instance.secret());},onComplete:function(){}
});

最终运行效果如下:

$ python loader.py
Script loaded successfully
Inside java perform function
Found instance: com.roysue.demo02.MainActivity@92d5deb
Result of secret func: @@@###@@@
original call: fun(50, 30)
*************************************
Original arg: LoWeRcAsE Me!!!!!!!!!
Return value: my test string#####
*************************************
original call: fun(50, 30)
*************************************
Original arg: LoWeRcAsE Me!!!!!!!!!
Return value: my test string#####
*************************************
original call: fun(50, 30)

这样隐藏方法也被调用起来了。

示例代码:

import sys
import frida"""java 层 Hook"""'''
https://blog.csdn.net/weixin_33862188/article/details/93088768
Hook 普通方法
'''
js_code = '''
Java.perform(function(){var utils = Java.use('com.example.fridaapp.Utils');utils.getCalc.implementation = function(a, b){console.log("Hook Start ...");send(arguments[0]);send(arguments[1]);var ret_val = this.getCalc(arguments[0], arguments[1]);    send(ret_val.toString());return 12345;}    
});
''''''
https://blog.csdn.net/weixin_33690963/article/details/93088770
hook 构造函数 和 普通函数 是有区别的,构造函数要用 $init 这种形式,
并且要 return this.$init(arg1,arg2) 调用原始的函数实现
'''
js_code = '''
Java.perform(function() { var money = Java.use('com.example.fridaapp.Money');money.$init.implementation = function (a, b) {console.log("Hook Start...");send(arguments[0]);send(b);send("Success!");return this.$init(10000, "美元");}
});
''''''
http://www.mamicode.com/info-detail-2684127.html
hook重载函数的几种写法:https://blog.csdn.net/universsky2015/article/details/77965614
hook 重载方法
'''
js_code_test = '''
Java.perform(function () {var utils = Java.use('com.example.fridaapp.Utils');utils.test.overload("int").implementation = function (a) {console.log("Hook Start...");send(arguments[0]);send("有参数!");return "有参数";}utils.test.overload().implementation = function (a) {console.log("Hook Start...");send(arguments[0]);send("没有参数!");return "没有参数";}
});
''''''
http://www.mamicode.com/info-detail-2684162.html
Hook 对象参数函数
'''
js_code = '''
Java.perform(function () {var utils = Java.use('com.xiaojianbang.app.Utils');var money = Java.use('com.xiaojianbang.app.Money');utils.test.overload('com.xiaojianbang.app.Money').implementation = function (obj) {send("Hook Start...");send(obj.getInfo());var mon = money.$new(2000,‘港币‘);send(mon.getInfo());return this.test(mon);}
});
'''js_code = """
Java.perform(function () {// Function to hook is defined herevar MainActivity = Java.use('com.example.seccon2015.rock_paper_scissors.MainActivity');// Whenever button is clickedMainActivity.onClick.implementation = function (v) {// Show a message to know that the function got calledsend('onClick');// Call the original onClick handlerthis.onClick(v);// Set our values after running the original onClick handlerthis.m.value = 0;this.n.value = 1;this.cnt.value = 999;// Log to the console that it's done, and we should have the flag!//console.log('Done:' + JSON.stringify(this.cnt));}}
);
"""def js_callback_func(msg, data):if msg['type'] == 'send':print(f'[*] {msg["payload"]}')else:print(msg)if __name__ == '__main__':# get_remote_device 获取远程设备 (get_usb_device)  attach 附加进程process = frida.get_remote_device().attach('com.example.fridaapp')script = process.create_script(js_code_test)script.on('message', js_callback_func)  # 绑定一个事件script.load()sys.stdin.read()pass

中级能力:远程调用( RPC

上面我们在安卓机器上使用 js 脚本调用了隐藏函数 secret(),它在 app 内虽然没有被任何地方调用,但是仍然被我们的脚本 "找到" 并且 "调用" 了起来

这一小节我们要实现的是,不仅要在跑在安卓机上的 js 脚本里调用这个函数,还要可以在 kali 主机上的 py 脚本里,直接调用这个函数。

也就是使用 frida 提供的 RPC 功能( Remote Procedure Call )。

安卓 app 不需要有任何修改,这次我们要修改的是 js 脚本和 py 脚本。

s3.js 代码:

console.log("Script loaded successfully ");function callSecretFun() { //定义导出函数Java.perform(function () { //找到隐藏函数并且调用Java.choose("com.roysue.demo02.MainActivity", {onMatch: function (instance) {console.log("Found instance: " + instance);console.log("Result of secret func: " + instance.secret());},onComplete: function () { }});});
}
rpc.exports = {// 把callSecretFun函数导出为callsecretfunction符号,// 导出名不可以有大写字母或者下划线callsecretfunction: callSecretFun 
};

然后我们可以在 kali 主机的 py 脚本里直接调用该函数:

loader3.py 代码:

import time
import fridadef my_message_handler(message, payload):print(message)print(payload)device = frida.get_usb_device()
pid = device.spawn(["com.example.demo2"])
device.resume(pid)
time.sleep(1)
session = device.attach(pid)
with open("s3.js", encoding='utf-8') as f:script = session.create_script(f.read())
script.on("message", my_message_handler)
script.load()command = ""
while 1 == 1:command = input("Enter command:\n\t1: Exit\n\t2: Call secret function\nchoice:")if command == "1":breakelif command == "2":  # 在这里调用script.exports.callsecretfunction()

然后在 kali 主机上我们就可以看到以下的输出:

$ python loader3.py
Script loaded successfully
Enter command:
1: Exit
2: Call secret function
choice:2
Found instance: com.roysue.demo02.MainActivity@2eacd80
Result of secret func: @@@###@@@LoWeRcAsE Me!!!!!!!!!LoWeRcAsE Me!!!!!!!!!LoWeRcAsE Me!!!!!!!!!LoWeRcAsE Me!!!!!!!!!
Enter command:
1: Exit
2: Call secret function
choice:2
Found instance: com.roysue.demo02.MainActivity@2eacd80
Result of secret func: @@@###@@@LoWeRcAsE Me!!!!!!!!!LoWeRcAsE Me!!!!!!!!!LoWeRcAsE Me!!!!!!!!!LoWeRcAsE Me!!!!!!!!!LoWeRcAsE Me!!!!!!!!!LoWeRcAsE Me!!!!!!!!!LoWeRcAsE Me!!!!!!!!!
Enter command:
1: Exit
2: Call secret function
choice:2
Found instance: com.roysue.demo02.MainActivity@2eacd80
Result of secret func: @@@###@@@LoWeRcAsE Me!!!!!!!!!LoWeRcAsE Me!!!!!!!!!LoWeRcAsE Me!!!!!!!!!LoWeRcAsE Me!!!!!!!!!LoWeRcAsE Me!!!!!!!!!LoWeRcAsE Me!!!!!!!!!LoWeRcAsE Me!!!!!!!!!LoWeRcAsE Me!!!!!!!!!LoWeRcAsE Me!!!!!!!!!
Enter command:
1: Exit
2: Call secret function
choice:1

这样我们就实现了在 kali 主机上直接调用安卓 app 内部的函数的能力。

frida rpc 与常规 hook 的区别:

  • rpc 能主动调用要 Hook 的代码
  • 常规 Hook 是被动,Hook 的函数/方法要被动等待触发,不能主动调用要 Hook 的代码

rpc 写法:

rpc.exports = {var sig = "";get_hello: function (str) {Java.perfrom(function () {var some = Java.use('XXXXX')sig = some.get_sig()})}return sig;
};

常规 hook 写法:

Java.perfrom(function(){var some = Java.use('XXXXX')some.get_sig.implemtation = function(){//do some thing}}
)

示例:

# -*- coding: utf-8 -*-
# @Author  : 佛祖保佑, 永无 bug
# @Date    : 
# @File    : rpc.py
# @Software: PyCharm
# @description : XXXimport fridarpc_js_code = '''
/// 方式 1 //
function getas111(arg_str) {send('hello');Java.perform(function () {// 拿到 context 上下文var current_application = Java.use('android.app.ActivityThread').currentApplication();var context = current_application.getApplicationContext();var AuthUtils = Java.use('com.coolapk.market.util.AuthUtils');var sig = AuthUtils.getAS(context, arg_str);send(sig);});
}
rpc.exports = {callgetas111:getas111
};
/// 方式 2 //
// rpc.exports = {
//     callgetas222:function (arg_str) {
//         send('hello');
//         Java.perform(function () {
//             // 拿到 context 上下文
//             var current_application = Java.use('android.app.ActivityThread').currentApplication();
//             var context = current_application.getApplicationContext();
// 
//             var AuthUtils = Java.use('com.coolapk.market.util.AuthUtils');
//             var sig = AuthUtils.getAS(context, arg_str);
//             send(sig);
//         });
//     }
// };
/
'''def js_callback_func(msg, data):# js中执行send函数后要回调的函数if 'send' == msg['type']:print(f'[*] {msg["payload"]}')elif 'error' == msg['type']:print(msg['stack'])else:print(msg)process = frida.get_remote_device().attach('com.coolapk.market')
script = process.create_script(rpc_js_code)
script.on('message', js_callback_func)
script.load()# ######### 导出名不可以有大写字母,或者下划线 #########
script.exports.callgetas111('hdfashfkdsh')
script.exports.callgetas222('hdfashfkdsh')

运行结果:

高级能力:互联互通、动态修改

最后我们要实现的功能是,我们不仅仅可以在 kali 主机上调用安卓 app 里的函数。我们还可以把数据从安卓 app 里传递到 kali 主机上,在主机上进行修改,再传递回安卓 app 里面去。

我们编写这样一个 app,其中最核心的地方在于判断用户是否为 admin,如果是,则直接返回错误,禁止登陆。如果不是,则把用户和密码上传到服务器上进行验证。

package com.roysue.demo04;import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Base64;
import android.view.View;
import android.widget.EditText;
import android.widget.TextView;public class MainActivity extends AppCompatActivity {EditText username_et;EditText password_et;TextView message_tv;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);password_et = (EditText) this.findViewById(R.id.editText2);username_et = (EditText) this.findViewById(R.id.editText);message_tv = ((TextView) findViewById(R.id.textView));this.findViewById(R.id.button).setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {if (username_et.getText().toString().compareTo("admin") == 0) {message_tv.setText("You cannot login as admin");return;}//hook targetmessage_tv.setText("Sending to the server :" + Base64.encodeToString((username_et.getText().toString() + ":" + password_et.getText().toString()).getBytes(), Base64.DEFAULT));}});}
}

最终跑起来之后,效果就是这样。

我们的目标就是在 kali 主机上 "得到" 输入框输入的内容,并且修改其输入的内容,并且 "传输" 给安卓机器,使其通过验证。也就是说,我们哪怕输入admin 的账户和密码,也可以绕过本地校验,进行登陆的操作。

所以最终安卓端的 js 代码的逻辑就是,截取输入,传输给 kali 主机,暂停执行,得到 kali 主机传回的数据之后,继续执行。形成代码如下:

Java.perform(function () {var tv_class = Java.use("android.widget.TextView");tv_class.setText.overload("java.lang.CharSequence").implementation = function (x) {var string_to_send = x.toString();var string_to_recv;send(string_to_send); // 将数据发送给kali主机的python代码recv(function (received_json_object) {string_to_recv = received_json_object.my_dataconsole.log("string_to_recv: " + string_to_recv);}).wait(); //收到数据之后,再执行下去return this.setText(string_to_recv);}
});

kali 主机端的流程就是,将接受到的 JSON 数据解析,提取出其中的密码部分,然后将用户名替换成 admin,这样就实现了将 admin 和 pw 发送给 "服务器" 的结果。

import time
import fridadef my_message_handler(message, payload):print messageprint payloadif message["type"] == "send":print message["payload"]data = message["payload"].split(":")[1].strip()print 'message:', messagedata = data.decode("base64")user, pw = data.split(":")data = ("admin" + ":" + pw).encode("base64")print "encoded data:", datascript.post({"my_data": data})  # 将JSON对象发送回去print "Modified data sent"device = frida.get_usb_device()
pid = device.spawn(["com.roysue.demo04"])
device.resume(pid)
time.sleep(1)
session = device.attach(pid)
with open("s4.js") as f:script = session.create_script(f.read())
script.on("message", my_message_handler)  # 注册消息处理函数
script.load()
raw_input()

我们只要输入任意用户名(非admin)+密码,非admin的用户名可以绕过compareTo校验,然后frida会帮助我们将用户名改成admin,最终就是 admin:pw 的组合发送到服务器。

$ python loader4.py
Script loaded successfully
{u'type': u'send', u'payload': u'Sending to the server :YWFhYTpiYmJi\n'}
None
Sending to the server :YWFhYTpiYmJimessage: {u'type': u'send', u'payload': u'Sending to the server :YWFhYTpiYmJi\n'}
data: aaaa:bbbb
pw: bbbb
encoded data: YWRtaW46YmJiYg==Modified data sent
string_to_recv: YWRtaW46YmJiYg==

动态修改输入内容就这样实现了。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/495330.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

神经元之间是如何形成“社交网络”的

来源&#xff1a;中科院神经科学研究院摘要&#xff1a;我们的大脑中存在着亿万个神经元&#xff0c;在神经科学领域有一个非常重要的问题&#xff0c;就是一个神经元是如何在这亿万个神经元中选择与某一些神经元形成突触联系的。演讲者&#xff1a;中国科学院神经科学研究所徐…

毕马威:2018全球科技创新报告(附PDF下载)

来源&#xff1a;走向智能论坛摘要&#xff1a;日前&#xff0c;毕马威发布《2018全球科技创新报告》&#xff0c;报告显示&#xff0c;我们如今正处在一个科技创新爆发的时代&#xff0c;人工智能、机器人和物联网必将会影响全球的商业&#xff0c;那些不主动去抓住未来趋势的…

GWT(Google Web Tookit) Eclipse Plugin的zip下载地址(同时提供GWT Designer下载地址)

按照Eclipse Help->Install new software->....(这里是官方安装文档&#xff1a;http://code.google.com/intl/zh-CN/eclipse/docs/install-eclipse-3.6.html) 的方法安装失败&#xff0c;界面始终显示Pedding状态&#xff0c;很长时间都没反映&#xff0c;无奈之下&…

《卫报》长文解读机器的崛起:人类越来越无法掌控它们

来源&#xff1a;网易智能摘要&#xff1a;技术正开始以智能和不可预知的方式运作&#xff0c;连它的创造者都无法捉摸。正当机器越来越多地改变全球事件时&#xff0c;我们该如何重新控制它们呢&#xff1f;《卫报》网站今日撰文详述了机器的崛起。技术正开始以智能和不可预知…

Android 逆向分析大全

转载&#xff1a;Android 逆向分析大全&#xff1a;https://www.jianshu.com/p/a12d04fc748f 1. 概述 1.1 分析步骤 通用逆向分析步骤 1. 了解该模块正向编程相关方法2. 使用apktool解密apk&#xff0c;得到资源、jni模块等文件3. 从apk提取出dex文件&#xff0c;使用dex2jar转…

美国智库报告:自动驾驶对社会、经济与劳动力的影响

来源&#xff1a;资本实验室在过去几年中&#xff0c;从政府到企业&#xff0c;自动驾驶的开发和应用已经成为新的投入重点。自动驾驶汽车在道路安全、生产率、燃料消耗和自然环保等方面的预期进步也充分吸引了公众的想象力和注意力。SAFE&#xff08;Securing America’s Futu…

一篇文章带你搞懂 DEX 文件的结构

From&#xff1a;https://blog.csdn.net/sinat_18268881/article/details/55832757 Dex文件格式详解&#xff1a;https://www.jianshu.com/p/f7f0a712ddfe dex文件解析(第三篇)&#xff1a;https://blog.csdn.net/tabactivity/article/details/78950379 深入理解DEX文件格式…

Google AI 研发医疗新模型,预测死亡率比医院高出10%

&#xfeff;&#xfeff;编译 | 姗姗出品 | 人工智能头条&#xff08;公众号ID&#xff1a;AI_Thinker&#xff09;摘要&#xff1a;Google 开发了一种新型算法——读取了这名女性的175,639个数据点——并对死亡风险进行了评估&#xff0c;结果为 19.9%。几天后这位女士去世了…

互联网如何“升级”制造业?《“人工智能+制造”产业发展研究报告》发布

来源&#xff1a;腾讯研究院摘要&#xff1a;过去两年&#xff0c;消费升级、智慧零售、智慧城市等概念成了大众讨论的热点。过去两年&#xff0c;消费升级、智慧零售、智慧城市等概念成了大众讨论的热点。除了这些概念是新经济的增长点之外&#xff0c;另一个原因是当这些概念…

Inspeckage,安卓动态分析工具

From&#xff1a;安卓分析工具 Inspeckage 介绍&#xff1a;http://xdxd.love/2016/08/09/安卓分析辅助工具Inspeckage介绍/ PJ 微信数据库 并查询数据上传服务器&#xff1a;http://blog.csdn.net/qq_35834055 https://github.com/1998lixin/WeChat-database/tree/dev 安卓…

【图文解析】带你看清全球机器人四大家族现状,四家企业瓜分中国57%、全球50%的市场份额...

来源&#xff1a;前瞻经济学研究院摘要&#xff1a;工业机器人是智能制造业最具代表性的装备。工业机器人是智能制造业最具代表性的装备。工业机器人集精密化、柔性化、智能化、软件应用开发等先进制造技术于一体&#xff0c;通过对过程实施检测、控制、优化、调度、管理和决策…

从微软一站式代码库中学到的--跨域之间的session共享

据说下面的这段代码这件可以实现不同域之间的session共享&#xff1a; namespace CSASPNETShareSessionBetweenSubDomainsModule{ /// <summary> /// A HttpModule used for sharing the session between Applications in /// sub domains. /// </summar…

专家解读下一代互联网创新模式,核心技术是根本

来源&#xff1a;经济参考报摘要&#xff1a;下一代互联网全面建成还有哪些现实困境&#xff1f;如何解决发展中面临的现实困境&#xff0c;让下一代互联网真正落地生根&#xff1f;如何促进下一代互联网与社会治理同步推进&#xff1f;专访了IPv6推动者、中国工程院院士吴建平…

一文读懂类加载机制 --- ClassLoader

From&#xff1a;https://www.cnblogs.com/sunnick/p/9609326.html 【JVM笔记】classloader加载class文件的原理和机制&#xff1a;https://www.jianshu.com/p/52c38cf2e3d4 JVM 架构整体架构 在进入 classloader 分析之前&#xff0c;先了解一下 jvm 整体架构&#xff1a; JV…

数学家到底在研究什么?牛人解说数学体系

来源&#xff1a;环球物理摘要&#xff1a;这个题目在当今Computer Vision中百花齐放的世界中并没有任何特别的地方。事实上&#xff0c;使用各种Graphical Model把各种东西联合在一起framework&#xff0c;在近年的论文中并不少见。一、为什么要深入数学的世界作为计算机的学生…

Frida hook 加固的 Android 应用

Android 加固应用Hook方式 --- Frida&#xff1a;https://github.com/xiaokanghub/Android 转载&#xff1a;使用 frida 来 hook 加固的 Android 应用的 java 层&#xff1a;https://bbs.pediy.com/thread-246767.htm 使用 Frida 给 apk 脱壳并穿透加固 Hook 函数&#xff1a…

176页报告辟谣自动化时代的就业危机(附下载)

来源&#xff1a;智东西摘要&#xff1a;世行从新兴技术的社会影响出发&#xff0c;盘点劳动力市场的再培训、再就业需求&#xff0c;以及资本、政府的社会职责。近十年&#xff0c;以人工智能为代表的技术爆炸正在重塑新一轮社会经济格局。这些创新极大地改变了就业市场形势&a…

CSS3技巧 —— 渐变

CSS渐变在Webkit率先得到实现&#xff0c;现在Firefox 3.6也支持了&#xff0c;来看下各个浏览器如何实现CSS渐变效果。 Webkit 下面这行代码可用于Chrome, Safari等&#xff0c;它能实现线性渐变&#xff0c;从top(#ccc)渐变到bottom(#000)。 background: -webkit-gradient(li…

Frida hook 插件化 apk ( classloader )

From&#xff1a;使用 frida hook 插件化 apk&#xff1a;https://bbs.pediy.com/thread-258772.htm 最近拿到一个XX视频apk样本&#xff0c;里面有视频、直播和小说&#xff0c;没有VIP只能试看30秒&#xff0c;刚好最近学习frida&#xff0c;用来练习下&#xff0c;分析过程中…

MIT开发出新界面系统 操作员可用思维控制机器人

来源&#xff1a;VentureBeat、网易科技摘要&#xff1a;麻省理工学院(MIT)下属计算机科学与人工智能实验室(CSAIL)的研究人员开发了一种新界面&#xff0c;它可以读取人类操作人员的脑电波&#xff0c;让他们通过思维命令机器执行任务。据VentureBeat报道&#xff0c;用思维控…