运行Frida

  1. adb shell /data/local/tmp/frida-server-12.8.6

    看下端口号

  2. 这两个好像没啥用

    adb forward tcp:27042 tcp:27042

    adb forward tcp:27043 tcp:27043

  1. 检查frida是否连接成功

    frida-ps -U

Frida基础

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import frida, sys

//hook代码,采用javascript编写
jscode = """
//javascript代码,重点
"""
def on_message(message, data):
if message['type'] == 'send':
print("[*] {0}".format(message['payload']))
else:
print(message)


process = frida.get_usb_device().attach('应用完整包名')
script = process.create_script(jscode)
script.on('message', on_message)
script.load()
sys.stdin.read()

怎么样是不是很简单?在实例之前先了解一下各种类型数组的缩写

boolean [Z
byte [B
char [C
double [D
float [F
int [I
long [J
short [S

那String呢 使用java.lang.String

String数组就是[java.lang.String

数据类型使用

那么来看一个实例

Frida简单入门

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
"""
Java.perform(function () {
// 要hook的类名
var MainActivity = Java.use('com.example.xxx.MainActivity');
// hook按钮点击事件
MainActivity.onClick.implementation = function (v) {
// Show a message to know that the function got called
send('onClick');

// 执行原始方法代码
this.onClick(v);

//修改MainActivity中属性的值
this.m.value = 0;
this.n.value = 1;
this.cnt.value = 999;
//打印日志
console.log('Done:' + JSON.stringify(this.cnt));
};
});
"""

有点点一脸懵逼

那么来分析一下,第2行表示是一般(MainActivity)函数,然后hook的是onClick这个函数,也就是点击函数,第6行看到这里的onClick是传参的,第8行类似log,11行就是要执行源代码一次,然后修改一些属性值(通过这个函数),18行是控制台输出。

执行Frida的Python脚本

不过这是python2版本的,对于文件的io还不太不了解,先cp了以后说不定用得上

先编写好js脚本hooks.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
import frida, sys
import io
#python2.7

def on_message(message, data):
if message['type'] == 'send':
print("[*] {0}".format(message['payload']))
else:
print(message)

def run(pkg):
jscode = io.open('hooks.js','r',encoding= 'utf8').read()
device = frida.get_usb_device(timeout=5)
pid = device.spawn(pkg)
session = device.attach(pid)
script = session.create_script(jscode)
script.on('message', on_message)
script.load()
sys.stdin.read()

def main(argv):
if len(argv) != 2:
print("must input two arg")
print("For exanple: python demo.py packName")
else:
run(argv[1])

if __name__ == "__main__":
main(sys.argv)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
# -*- coding: utf-8 -*-
# python2.7
import sys
import subprocess
forward1 = "adb forward tcp:27042 tcp:27042"
forward2 = "adb forward tcp:27043 tcp:27043"

cmd = ["adb shell","su","cd /data/local/tmp","./frida-server-12.8.6"]

def Forward1():
s = subprocess.Popen(str(forward1+"\r\n"), stderr=subprocess.PIPE, stdin=subprocess.PIPE,stdout=subprocess.PIPE, shell=True)
stderrinfo, stdoutinfo = s.communicate()
return s.returncode

def Forward2():
s = subprocess.Popen(str(forward2+"\r\n"), stderr=subprocess.PIPE, stdin=subprocess.PIPE,stdout=subprocess.PIPE, shell=True)
stderrinfo, stdoutinfo = s.communicate()
return s.returncode

def Run():
s = subprocess.Popen(str(cmd[0]+"\r\n"), stderr=subprocess.PIPE, stdin=subprocess.PIPE,stdout=subprocess.PIPE, shell=True)

for i in range(1,len(cmd)):
s.stdin.write(str(cmd[i]+"\r\n"))
s.stdin.flush()

stderrinfo, stdoutinfo = s.communicate()
return s.returncode

if __name__ == "__main__":
Forward1()
print("adb forward tcp:27042 tcp:27042")
Forward2()
print("adb forward tcp:27043 tcp:27043")
print("Android server--->./frida-server64")
print("success-->frida-ps -R")
Run()

那么总的来说,利用Frida来进行hook是比较简单的。

Frida模板

构造函数

https://www.jianshu.com/p/dadacd02fefd

普通函数

用这个例子

注意对于有返回值的函数要带上return suitable_value

image-20200117211507087

一般函数

1
2
3
4
5
6
7
8
9
Java.perform(function()
{
var main = Java.use('ese.xposedtest.MainActivity');
main.Outclass.implementation = function() {
var ret = this.Outclass();
console.log('Done:' + JSON.stringify(ret));
return "Frida" + ret;
}
})

类内函数

1
2
3
4
5
6
7
8
9
10
11
Java.perform(function()
{
var main = Java.use('ese.xposedtest.MainActivity$inClasse');
main.formInclass.implementation = function(x, s)//这里加上实参,如果是数组要用其他形式
{
var arg1 = arguments[0];
var arg2 = arguments[1];
send("param1"+arg1+"param"+arg2);
return this.formInclass(1, "Frida");
}
})

Native函数

打开apk的得到的.so文件名字叫libnative-lib.so,函数名是Java_ese_xposedtest_MainActivity_stringFromJNI

1
2
3
4
5
6
7
8
9
10
11
12
13
14
setImmediate(function() {
console.log("[*] Native Starting script");
var nativePointer = Module.findExportByName("libnative-lib.so","Java_ese_xposedtest_MainActivity_stringFromJNI");
send("nativePointer--->"+nativePointer);
Interceptor.attach(nativePointer,{
onEnter:function(args){
console.log("ok");
send("Sart arg-->"+args[0]+" "+args[1]);
},
onLeave:function(retval){
send("return value:"+retval);
}
});
})

函数重载

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// If two methods of a class have the same name
// you need to use 'overload'

myClass.myMethod.overload().implementation = function(){
//无参函数
// do sth
}

myClass.myMethod.overload("[B", "[B").implementation = function(param1, param2) {
//两个字节数组的参数
// do sth
}

myClass.myMethod.overload("android.context.Context", "boolean").implementation = function(param1, param2){
//上下文和布尔值
// do sth
}

Bytes -> String

1
2
3
4
5
6
7
function bin2string(array){
var result = "";
for(var i = 0; i < array.length; ++i){
result+= (String.fromCharCode(array[i]));
}
return result;
}

https://www.52pojie.cn/forum.php?mod=viewthread&tid=931872

https://bbs.pediy.com/thread-227233.htm