Hook Getting Started Demo

Preparation:
jadx_gui: decompile the apk, get the apk package name, and view the apk source code.

frida:hook framework: used to implant js scripts, modify the source program to intercept data, and obtain the desired data.

adb: The computer operates a real machine or an emulator.

NoxPlayer: Used for testing.

frida-server: It is used to implement communication. It can be understood as a server here. Send it to the mobile phone with adb to modify the permissions and run it. Note that it must be the same as the version of frida installed in the local python. The downloaded version is also different, and some cannot be used.

  • -pip install frida: The frida here is installed locally, which can be understood as a client
  • -pip install frida-tools: some tools

Demo:

import frida
import sys
import os


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

jscode = """
    function classExists(className) {
    var exists = false;
    try {
        var clz = Java.use(className);
        exists = true;
    } catch (err) {
    }
    return exists;
};

function checkLoadDex(className, dexfile) {
    if (!classExists(className)) {
        Java.openClassFile(dexfile).load();
    }
};

function toJSONString(obj) {
    try {
        checkLoadDex("com.alibaba.fastjson.JSON", "/data/local/tmp/fastjson.dex");
        var clz = Java.use("com.alibaba.fastjson.JSON");
        var toJSONStringMehtod = clz.toJSONString.overload("java.lang.Object");
        return toJSONStringMehtod.call(clz, obj);
    } catch (err) {
    }
    return "{}";
};

function fromJSONString(jsonStr, classObj) {
    try {
        checkLoadDex("com.alibaba.fastjson.JSON", "/data/local/tmp/fastjson.dex");
        var jsonObject = Java.use("com.alibaba.fastjson.JSONObject");
        var obj = jsonObject.parseObject(jsonStr, classObj.class);
        return obj;
    } catch (err) {
    }
    return null;

};

function newHashSet() {
    var HashSetClz = Java.use('java.util.HashSet');
    return HashSetClz.$new();
};

var Base64 = {
	_keyStr: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",
	encode: function(e) {
		var t = "";
		var n, r, i, s, o, u, a;
		var f = 0;
		e = Base64._utf8_encode(e);
		while (f < e.length) {
			n = e.charCodeAt(f++);
			r = e.charCodeAt(f++);
			i = e.charCodeAt(f++);
			s = n >> 2;
			o = (n & 3) << 4 | r >> 4;
			u = (r & 15) << 2 | i >> 6;
			a = i & 63;
			if (isNaN(r)) {
				u = a = 64;
			} else if (isNaN(i)) {
				a = 64;
			}
			t = t + this._keyStr.charAt(s) + this._keyStr.charAt(o) + this._keyStr.charAt(u) + this._keyStr.charAt(a);
		}
		return t;
	},
	decode: function(e) {
		var t = "";
		var n, r, i;
		var s, o, u, a;
		var f = 0;
		e = e.replace(/[^A-Za-z0-9+/=]/g, "");
		while (f < e.length) {
			s = this._keyStr.indexOf(e.charAt(f++));
			o = this._keyStr.indexOf(e.charAt(f++));
			u = this._keyStr.indexOf(e.charAt(f++));
			a = this._keyStr.indexOf(e.charAt(f++));
			n = s << 2 | o >> 4;
			r = (o & 15) << 4 | u >> 2;
			i = (u & 3) << 6 | a;
			t = t + String.fromCharCode(n);
			if (u != 64) {
				t = t + String.fromCharCode(r);
			}
			if (a != 64) {
				t = t + String.fromCharCode(i);
			}
		}
		t = Base64._utf8_decode(t);
		return t;
	},
	_utf8_encode: function(e) {
		e = e.replace(/rn/g, "n");
		var t = "";
		for (var n = 0; n < e.length; n++) {
			var r = e.charCodeAt(n);
			if (r < 128) {
				t += String.fromCharCode(r);
			} else if (r > 127 && r < 2048) {
				t += String.fromCharCode(r >> 6 | 192);
				t += String.fromCharCode(r & 63 | 128);
			} else {
				t += String.fromCharCode(r >> 12 | 224);
				t += String.fromCharCode(r >> 6 & 63 | 128);
				t += String.fromCharCode(r & 63 | 128);
			}
		}
		return t;
	},
	_utf8_decode: function(e) {
		var t = "";
		var n = 0;
		var r =  0;
        var c1;
        var c2 = 0;
		while (n < e.length) {
			r = e.charCodeAt(n);
			if (r < 128) {
				t += String.fromCharCode(r);
				n++;
			} else if (r > 191 && r < 224) {
				c2 = e.charCodeAt(n + 1);
				t += String.fromCharCode((r & 31) << 6 | c2 & 63);
				n += 2;
			} else {
				c2 = e.charCodeAt(n + 1);
				c1 = e.charCodeAt(n + 2);
				t += String.fromCharCode((r & 15) << 12 | (c2 & 63) << 6 | c1 & 63);
				n += 3;
			}
		}
		return t;
	}
};

rpc.exports = {
    hooker: function (param1) {
        Java.perform(function () {
            console.log(param1);
            /* 参数
			传参:
				long   int64
			重写:
				普通参数
					int          int
					long         long
					byte         [B
					boolean      boolean
					float		 float
				容器类
					String       java.lang.String
					HashMap      java.util.HashMap
					ArrayList    java.util.ArrayList
					HashSet		 java.util.HashSet
					LinkedList   java.util.LinkedList
					eg:
						var hashMap_clz = Java.use('java.util.HashMap');
            			var map_clz = Java.use('java.util.Map');
						var hashMap = hashMap_clz.$new();
                    	var map = Java.cast(hashMap, map_clz);
                 自定义类
                 	com.tencent.mm.protocal.protobuf.cqt
                 	com.tencent.mm.an.q
             */

			// hook代码实现数据截取、篡改
			//普通方法hook
			var main = Java.use("com.example.pt_fun.MainActivity");
			main.add.implementation = function (a, b) {
				console.log("Hook start ...");
				send(a);
				send(b);
				send("Success");
				return this.add("2", "2");
			};
			//构造方法hook
			var money = Java.use("com.example.pt_fun.Money");
			money.$init.implementation = function (a, b) {
				console.log("Hook start ...");
				send(a);
				send(b);
				send("Success");
				return this.$init(2000, "美元");
			};
			//重载方法hook
			var money = Java.use("com.example.pt_fun.Money");
			money.getInfo.overload("int").implementation = function (a) {
				console.log("Hook start ...");
				send(a);
				send("Success");
				//return this.getInfo(88888);
				return "重载方法hook成功"
			};
			//对象参数
			var main = Java.use("com.example.pt_fun.MainActivity");
			var money = Java.use("com.example.pt_fun.Money");
			main.mobj.implementation = function (obj) {
				console.log("Hook start ...");
				//send(obj);
				send(obj.getInfo());
				//获取属性值(一)
				send(obj.type.value);
				//修改属性
				obj.type.value = "英镑";
				var m = money.$new(1000, "台币");
				send(m.getInfo());
				return this.mobj(m);
			};
			//修改属性(映射)
			var main = Java.use("com.example.pt_fun.MainActivity");
			var money = Java.use("com.example.pt_fun.Money");
			var clazz = Java.use("java.lang.Class");
			main.mobj.implementation = function (obj) {
				var countid = Java.cast(obj.getClass(), clazz).getDeclaredField("count");
				countid.setAccessible(true);
				var value = countid.get(obj);
				console.log(value);
				countid.setInt(obj, 11111);
				return this.mobj(obj);
			};
			// 注册类,即实现接口
			var ab_clz = Java.use('com.example.pt_fun.interface');
			var cust_ab_clz = Java.registerClass({
				name: 'com.example.pt_fun.interface.lllx1',
				implements: [ab_clz],
				methods: {
					add(a, b) {
						return a+b;
					}
				}
			});
			cust_ab_clz.$new().add(1, 2);
			//枚举所有的类和方法
			Java.enumerateLoadedClasses({
				onMatch: function (name, handle) {
					if (name.indexOf("com.tencent.mm") != -1) {
						console.log("name: ", name);
						var clazz = Java.use(name);
						console.log("clazz: ", clazz);
						var methods = clazz.class.getDeclaredMethods();
						for (var i = 0; i < methods.length; i++) {
							console.log("methods: ", methods[i]);
						}
						Thread.sleep(0.1);
					}
				},
				onComplete: function () {
					console.log("okok");
				}
			});
        });
    }
};

"""


# 端口转发
os.system("adb forward tcp:27042 tcp:27042")
# 连接并获取运行的apk包名,即进程
process = frida.get_remote_device().attach('com.example.pt_fun')
# 植入脚本,拦截数据
script = process.create_script(jscode)
script.on('message', on_message)
script.load()
# 控制台打印信息
sys.stdin.read()

Test apk:
Click to download
and go to the home page to find the package named PT_fun.

Guess you like

Origin blog.csdn.net/xiaoxin_OK/article/details/118253754