Frida Tutorial 2

Tip

AWS ํ•ดํ‚น ๋ฐฐ์šฐ๊ธฐ ๋ฐ ์—ฐ์Šตํ•˜๊ธฐ:HackTricks Training AWS Red Team Expert (ARTE)
GCP ํ•ดํ‚น ๋ฐฐ์šฐ๊ธฐ ๋ฐ ์—ฐ์Šตํ•˜๊ธฐ: HackTricks Training GCP Red Team Expert (GRTE) Azure ํ•ดํ‚น ๋ฐฐ์šฐ๊ธฐ ๋ฐ ์—ฐ์Šตํ•˜๊ธฐ: HackTricks Training Azure Red Team Expert (AzRTE)

HackTricks ์ง€์›ํ•˜๊ธฐ

์ด๊ฒƒ์€ ๊ฒŒ์‹œ๋ฌผ์˜ ์š”์•ฝ์ž…๋‹ˆ๋‹ค: https://11x256.github.io/Frida-hooking-android-part-2/ (ํŒŒํŠธ 2, 3 & 4)
APKs ๋ฐ ์†Œ์Šค ์ฝ”๋“œ: https://github.com/11x256/frida-android-examples

ํŒŒํŠธ 1์€ ๋งค์šฐ ์‰ฝ์Šต๋‹ˆ๋‹ค.

์›๋ณธ ์ฝ”๋“œ์˜ ์ผ๋ถ€๋Š” ์ž‘๋™ํ•˜์ง€ ์•Š์œผ๋ฉฐ ์—ฌ๊ธฐ์—์„œ ์ˆ˜์ •๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

Part 2

์—ฌ๊ธฐ์—์„œ ๊ฐ™์€ ์ด๋ฆ„์„ ๊ฐ€์ง„ 2๊ฐœ์˜ ํ•จ์ˆ˜๋ฅผ ํ›„ํ‚นํ•˜๋Š” ๋ฐฉ๋ฒ•์˜ ์˜ˆ๋ฅผ ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
๋˜ํ•œ, ์ž์‹ ์˜ ๋งค๊ฐœ๋ณ€์ˆ˜๋กœ ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ๋ฐฐ์šธ ๊ฒƒ์ž…๋‹ˆ๋‹ค.
๋งˆ์ง€๋ง‰์œผ๋กœ, ํด๋ž˜์Šค์˜ ์ธ์Šคํ„ด์Šค๋ฅผ ์ฐพ์•„ ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•˜๋Š” ๋ฐฉ๋ฒ•์˜ ์˜ˆ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.

//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

//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์„ ์‚ฌ์šฉํ•˜์—ฌ ํ›„ํ‚น๋œ ์•ฑ์— ๋ช…๋ น์„ ๋ณด๋‚ด๊ณ  ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค:

//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

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,
}

Part 4

์—ฌ๊ธฐ์—์„œ๋Š” Python๊ณผ JS๊ฐ€ JSON ๊ฐ์ฒด๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ƒํ˜ธ์ž‘์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ๋ณด์—ฌ์ค๋‹ˆ๋‹ค. JS๋Š” send() ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋ฐ์ดํ„ฐ๋ฅผ Python ํด๋ผ์ด์–ธํŠธ์— ์ „์†กํ•˜๊ณ , Python์€ post() ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋ฐ์ดํ„ฐ๋ฅผ JS ์Šคํฌ๋ฆฝํŠธ์— ์ „์†กํ•ฉ๋‹ˆ๋‹ค. JS๋Š” 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

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/

Tip

AWS ํ•ดํ‚น ๋ฐฐ์šฐ๊ธฐ ๋ฐ ์—ฐ์Šตํ•˜๊ธฐ:HackTricks Training AWS Red Team Expert (ARTE)
GCP ํ•ดํ‚น ๋ฐฐ์šฐ๊ธฐ ๋ฐ ์—ฐ์Šตํ•˜๊ธฐ: HackTricks Training GCP Red Team Expert (GRTE) Azure ํ•ดํ‚น ๋ฐฐ์šฐ๊ธฐ ๋ฐ ์—ฐ์Šตํ•˜๊ธฐ: HackTricks Training Azure Red Team Expert (AzRTE)

HackTricks ์ง€์›ํ•˜๊ธฐ