漏洞赏金提示 : 注册 Intigriti ,一个由黑客为黑客创建的高级 漏洞赏金平台 !今天就加入我们 https://go.intigriti.com/hacktricks ,开始赚取高达 $100,000 的赏金!
这是文章的摘要 : https://11x256.github.io/Frida-hooking-android-part-2/ (第 2、3 和 4 部分)
APKs 和源代码 : https://github.com/11x256/frida-android-examples
第一部分非常简单。
原始代码的某些部分无法正常工作,并在此处进行了修改。
第 2 部分
在这里你可以看到一个如何 hook 2 个同名但参数不同的函数 的示例。
此外,你将学习如何 使用自己的参数调用一个函数 。
最后,还有一个示例,展示如何 找到一个类的实例并使其调用一个函数 。
Copy //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
Copy // 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 ()
Part 3
Python
现在你将看到如何通过 Python 向被 Hook 的应用发送命令以调用函数:
Copy // 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
Copy 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
在这里你将看到如何使用 JSON 对象使 Python 和 JS 交互 。JS 使用 send()
函数将数据发送到 Python 客户端,而 Python 使用 post()
函数将数据发送到 JS 脚本。JS 将阻塞执行 ,直到收到来自 Python 的响应。
Python
Copy // 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
Copy 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);
}
});
There is a part 5 that I am not going to explain because there isn't anything new. But if you want to read it is here: https://11x256.github.io/Frida-hooking-android-part-5/
Bug bounty tip : 注册 Intigriti ,一个由黑客为黑客创建的高级漏洞赏金平台 !今天就加入我们,访问 https://go.intigriti.com/hacktricks ,开始赚取高达 $100,000 的赏金!