mirror of
https://github.com/HackTricks-wiki/hacktricks.git
synced 2025-10-10 18:36:50 +00:00
208 lines
6.6 KiB
Markdown
208 lines
6.6 KiB
Markdown
# Frida Tutorial 2
|
||
|
||
{{#include ../../../banners/hacktricks-training.md}}
|
||
|
||
**这是文章的摘要**: [https://11x256.github.io/Frida-hooking-android-part-2/](https://11x256.github.io/Frida-hooking-android-part-2/) (第 2、3 和 4 部分)\
|
||
**APKs 和源代码**: [https://github.com/11x256/frida-android-examples](https://github.com/11x256/frida-android-examples)
|
||
|
||
第一部分非常简单。
|
||
|
||
**原始代码的某些部分无法正常工作,并在此进行了修改。**
|
||
|
||
## 第 2 部分
|
||
|
||
在这里,您可以看到如何 **hook 2 个同名但参数不同的函数** 的示例。\
|
||
此外,您将学习如何 **使用自己的参数调用函数**。\
|
||
最后,还有一个示例,展示如何 **找到类的实例并使其调用函数**。
|
||
```javascript
|
||
//s2.js
|
||
console.log("Script loaded successfully ");
|
||
Java.perform(function x() {
|
||
console.log("Inside java perform function");
|
||
var my_class = Java.use("com.example.a11x256.frida_test.my_activity");
|
||
//Hook "fun" with parameters (int, int)
|
||
my_class.fun.overload("int", "int").implementation = function (x, y) { //hooking the old function
|
||
console.log("original call: fun(" + x + ", " + y + ")");
|
||
var ret_value = this.fun(2, 5);
|
||
return ret_value;
|
||
};
|
||
//Hook "fun" with paramater(String)
|
||
var string_class = Java.use("java.lang.String");
|
||
my_class.fun.overload("java.lang.String").implementation = function (x) { //hooking the new function
|
||
console.log("*")
|
||
//Create a new String and call the function with your input.
|
||
var my_string = string_class.$new("My TeSt String#####");
|
||
console.log("Original arg: " + x);
|
||
var ret = this.fun(my_string);
|
||
console.log("Return value: " + ret);
|
||
console.log("*")
|
||
return ret;
|
||
};
|
||
//Find an instance of the class and call "secret" function.
|
||
Java.choose("com.example.a11x256.frida_test.my_activity", {
|
||
onMatch: function (instance) {
|
||
console.log(tring, and the it has"Found instance: " + instance);
|
||
console.log("Result of secret func: " + instance.secret());
|
||
},
|
||
onComplete: function () { }
|
||
});
|
||
});
|
||
```
|
||
您可以看到,要创建一个字符串,首先引用了类 _java.lang.String_,然后使用字符串作为内容创建了一个 _$new_ 对象。 这是创建类的新对象的正确方法。 但是,在这种情况下,您可以将任何字符串传递给 `this.fun()`,例如:`this.fun("hey there!")`
|
||
|
||
### Python
|
||
```python
|
||
//loader.py
|
||
import frida
|
||
import time
|
||
|
||
device = frida.get_usb_device()
|
||
pid = device.spawn(["com.example.a11x256.frida_test"])
|
||
device.resume(pid)
|
||
time.sleep(1) #Without it Java.perform silently fails
|
||
session = device.attach(pid)
|
||
script = session.create_script(open("s2.js").read())
|
||
script.load()
|
||
|
||
#prevent the python script from terminating
|
||
raw_input()
|
||
```
|
||
|
||
```
|
||
python loader.py
|
||
```
|
||
## Part 3
|
||
|
||
### Python
|
||
|
||
现在您将看到如何通过 Python 向被 Hook 的应用程序发送命令以调用函数:
|
||
```python
|
||
//loader.py
|
||
import time
|
||
import frida
|
||
|
||
def my_message_handler(message, payload):
|
||
print message
|
||
print payload
|
||
|
||
|
||
device = frida.get_usb_device()
|
||
pid = device.spawn(["com.example.a11x256.frida_test"])
|
||
device.resume(pid)
|
||
time.sleep(1) # Without it Java.perform silently fails
|
||
session = device.attach(pid)
|
||
with open("s3.js") as f:
|
||
script = session.create_script(f.read())
|
||
script.on("message", my_message_handler)
|
||
script.load()
|
||
|
||
command = ""
|
||
while 1 == 1:
|
||
command = raw_input("Enter command:\n1: Exit\n2: Call secret function\n3: Hook Secret\nchoice:")
|
||
if command == "1":
|
||
break
|
||
elif command == "2":
|
||
script.exports.callsecretfunction()
|
||
elif command == "3":
|
||
script.exports.hooksecretfunction()
|
||
```
|
||
命令 "**1**" 将 **退出**,命令 "**2**" 将查找并 **实例化类并调用私有函数** _**secret()**_,命令 "**3**" 将 **钩住** 函数 _**secret()**_ 以便 **返回** 一个 **不同的字符串**。
|
||
|
||
因此,如果你调用 "**2**",你将得到 **真实的秘密**,但如果你先调用 "**3**" 然后再调用 "**2**",你将得到 **假的秘密**。
|
||
|
||
### JS
|
||
```javascript
|
||
console.log("Script loaded successfully ")
|
||
var instances_array = []
|
||
function callSecretFun() {
|
||
Java.perform(function () {
|
||
if (instances_array.length == 0) {
|
||
// if array is empty
|
||
Java.choose("com.example.a11x256.frida_test.my_activity", {
|
||
onMatch: function (instance) {
|
||
console.log("Found instance: " + instance)
|
||
instances_array.push(instance)
|
||
console.log("Result of secret func: " + instance.secret())
|
||
},
|
||
onComplete: function () {},
|
||
})
|
||
} else {
|
||
//else if the array has some values
|
||
console.log("Result of secret func: " + instances_array[0].secret())
|
||
}
|
||
})
|
||
}
|
||
|
||
function hookSecret() {
|
||
Java.perform(function () {
|
||
var my_class = Java.use("com.example.a11x256.frida_test.my_activity")
|
||
var string_class = Java.use("java.lang.String")
|
||
my_class.secret.overload().implementation = function () {
|
||
var my_string = string_class.$new("TE ENGANNNNEEE")
|
||
return my_string
|
||
}
|
||
})
|
||
}
|
||
rpc.exports = {
|
||
callsecretfunction: callSecretFun,
|
||
hooksecretfunction: hookSecret,
|
||
}
|
||
```
|
||
## 第4部分
|
||
|
||
在这里,您将看到如何使用 JSON 对象使 **Python 和 JS 交互**。JS 使用 `send()` 函数将数据发送到 Python 客户端,而 Python 使用 `post()` 函数将数据发送到 JS 脚本。**JS 将阻止执行**,直到收到来自 Python 的响应。
|
||
|
||
### Python
|
||
```python
|
||
//loader.py
|
||
import time
|
||
import frida
|
||
|
||
def my_message_handler(message, payload):
|
||
print message
|
||
print payload
|
||
if message["type"] == "send":
|
||
print message["payload"]
|
||
data = message["payload"].split(":")[1].strip()
|
||
print 'message:', message
|
||
data = data.decode("base64")
|
||
user, pw = data.split(":")
|
||
data = ("admin" + ":" + pw).encode("base64")
|
||
print "encoded data:", data
|
||
script.post({"my_data": data}) # send JSON object
|
||
print "Modified data sent"
|
||
|
||
|
||
device = frida.get_usb_device()
|
||
pid = device.spawn(["com.example.a11x256.frida_test"])
|
||
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) # register the message handler
|
||
script.load()
|
||
raw_input()
|
||
```
|
||
### JS
|
||
```javascript
|
||
console.log("Script loaded successfully ")
|
||
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) // send data to python code
|
||
recv(function (received_json_object) {
|
||
string_to_recv = received_json_object.my_data
|
||
}).wait() //block execution till the message is received
|
||
console.log("Final string_to_recv: " + string_to_recv)
|
||
return this.setText(string_to_recv)
|
||
}
|
||
})
|
||
```
|
||
有一个第5部分,我不打算解释,因为没有新的内容。但如果你想阅读,可以在这里找到:[https://11x256.github.io/Frida-hooking-android-part-5/](https://11x256.github.io/Frida-hooking-android-part-5/)
|
||
|
||
{{#include ../../../banners/hacktricks-training.md}}
|