├── print_all_classes.py ├── hooking-native-code.py ├── WebViewActivity.java ├── debugger.py ├── device_id.py ├── root.py ├── hook_webview_frida_example.py ├── DebuggerCheck.java ├── multi-hooks-example.py ├── CheckFile.java ├── file.py ├── RootCheck.java ├── README.md └── objects-in-heap.js /print_all_classes.py: -------------------------------------------------------------------------------- 1 | import frida 2 | import sys 3 | 4 | package_name = "com.example.android" 5 | 6 | 7 | def get_messages_from_js(message, data): 8 | print (message) 9 | 10 | 11 | def instrument_debugger_checks(): 12 | hook_code = """setTimeout(function(){Java.enumerateLoadedClasses({onMatch: function(className) {send(className);},onComplete:function(){send("done");}});},0);""" 13 | return hook_code 14 | 15 | process = frida.get_device_manager().enumerate_devices()[-1].attach(package_name) 16 | script = process.create_script(instrument_debugger_checks()) 17 | script.on('message',get_messages_from_js) 18 | script.load() 19 | sys.stdin.read() 20 | -------------------------------------------------------------------------------- /hooking-native-code.py: -------------------------------------------------------------------------------- 1 | import frida 2 | import sys 3 | 4 | package_name = "com.jni.anto.kalip" 5 | 6 | 7 | def get_messages_from_js(message, data): 8 | print(message) 9 | print (message['payload']) 10 | 11 | 12 | def instrument_debugger_checks(): 13 | 14 | hook_code = """ 15 | Interceptor.attach (Module.findExportByName ( "libc.so", "read"), { 16 | onEnter: function (args) { 17 | send (Memory.readUtf8String (args [1])); 18 | }, 19 | onLeave: function (retval) { 20 | } 21 | });""" 22 | return hook_code 23 | 24 | 25 | process = frida.get_usb_device().attach(package_name) 26 | script = process.create_script(instrument_debugger_checks()) 27 | script.on('message',get_messages_from_js) 28 | script.load() 29 | sys.stdin.read() 30 | -------------------------------------------------------------------------------- /WebViewActivity.java: -------------------------------------------------------------------------------- 1 | package com.jni.anto.kalip; 2 | 3 | import android.os.Bundle; 4 | import android.support.v7.app.AppCompatActivity; 5 | import android.support.v7.widget.Toolbar; 6 | import android.webkit.WebView; 7 | 8 | 9 | public class WebViewActivity extends AppCompatActivity { 10 | 11 | 12 | 13 | @Override 14 | protected void onCreate(Bundle savedInstanceState) { 15 | super.onCreate(savedInstanceState); 16 | setContentView(R.layout.activity_main); 17 | Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); 18 | setSupportActionBar(toolbar); 19 | 20 | WebView w = (WebView) findViewById(R.id.webView); 21 | w.loadUrl("http://www.frida.re/"); 22 | w.getSettings().setJavaScriptEnabled(true); 23 | 24 | } 25 | } 26 | 27 | 28 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /debugger.py: -------------------------------------------------------------------------------- 1 | import frida 2 | import sys 3 | 4 | package_name = "com.jni.anto.kalip" 5 | 6 | 7 | def get_messages_from_js(message, data): 8 | print(message) 9 | print (message['payload']) 10 | 11 | 12 | def instrument_debugger_checks(): 13 | 14 | hook_code = """ 15 | setTimeout(function(){ 16 | Dalvik.perform(function () { 17 | 18 | var TM = Dalvik.use("android.os.Debug"); 19 | 20 | TM.isDebuggerConnected.implementation = function () { 21 | 22 | send("Called - isDebuggerConnected()"); 23 | 24 | return false; 25 | }; 26 | 27 | }); 28 | 29 | },0); 30 | """ 31 | 32 | return hook_code 33 | 34 | process = frida.get_device_manager().enumerate_devices()[-1].attach(package_name) 35 | script = process.create_script(instrument_debugger_checks()) 36 | script.on('message',get_messages_from_js) 37 | script.load() 38 | sys.stdin.read() 39 | 40 | -------------------------------------------------------------------------------- /device_id.py: -------------------------------------------------------------------------------- 1 | import frida 2 | import sys 3 | 4 | package_name = "com.abc.d" 5 | 6 | 7 | def get_messages_from_js(message, data): 8 | print(message) 9 | print (message['payload']) 10 | 11 | 12 | def instrument_load_url(): 13 | 14 | hook_code = """ 15 | setTimeout(function(){ 16 | Dalvik.perform(function () { 17 | 18 | var TM = Dalvik.use("android.telephony.TelephonyManager"); 19 | 20 | TM.getDeviceId.implementation = function () { 21 | 22 | send("Called - deviceID()"); 23 | 24 | return "pwn3d"; 25 | 26 | }; 27 | 28 | }); 29 | 30 | },0); 31 | """ 32 | 33 | return hook_code 34 | 35 | process = frida.get_device_manager().enumerate_devices()[-1].attach(package_name) 36 | script = process.create_script(instrument_load_url()) 37 | script.on('message',get_messages_from_js) 38 | script.load() 39 | sys.stdin.read() 40 | -------------------------------------------------------------------------------- /root.py: -------------------------------------------------------------------------------- 1 | import frida 2 | import sys 3 | 4 | package_name = "com.jni.anto.kalip" 5 | 6 | 7 | def get_messages_from_js(message, data): 8 | print(message) 9 | print (message['payload']) 10 | 11 | 12 | def instrument_root_checks(): 13 | 14 | hook_code = """ 15 | setTimeout(function(){ 16 | Dalvik.perform(function () { 17 | 18 | var TM = Dalvik.use("com.jni.anto.kalip.MainActivity"); 19 | 20 | TM.isPhoneRooted.implementation = function () { 21 | 22 | send("Called - isPhoneRooted()"); 23 | 24 | return false; 25 | 26 | }; 27 | 28 | }); 29 | 30 | },0); 31 | """ 32 | 33 | return hook_code 34 | 35 | process = frida.get_device_manager().enumerate_devices()[-1].attach(package_name) 36 | script = process.create_script(instrument_root_checks()) 37 | script.on('message',get_messages_from_js) 38 | script.load() 39 | sys.stdin.read() 40 | -------------------------------------------------------------------------------- /hook_webview_frida_example.py: -------------------------------------------------------------------------------- 1 | import frida 2 | import sys 3 | 4 | package_name = "com.jni.anto.kalip" 5 | 6 | 7 | def get_messages_from_js(message, data): 8 | print(message) 9 | print (message['payload']) 10 | 11 | 12 | def instrument_load_url(): 13 | 14 | hook_code = """ 15 | setTimeout(function(){ 16 | Dalvik.perform(function () { 17 | 18 | var WebView = Dalvik.use("android.webkit.WebView"); 19 | 20 | WebView.loadUrl.overload("java.lang.String").implementation = function (s) { 21 | 22 | send(s.toString()); 23 | 24 | this.loadUrl.overload("java.lang.String").call(this, s); 25 | 26 | }; 27 | 28 | }); 29 | 30 | },0); 31 | """ 32 | 33 | return hook_code 34 | 35 | process = frida.get_device_manager().enumerate_devices()[-1].attach(package_name) 36 | script = process.create_script(instrument_load_url()) 37 | script.on('message',get_messages_from_js) 38 | script.load() 39 | sys.stdin.read() 40 | 41 | -------------------------------------------------------------------------------- /DebuggerCheck.java: -------------------------------------------------------------------------------- 1 | package com.jni.anto.kalip; 2 | 3 | import android.os.Bundle; 4 | import android.support.v7.app.AppCompatActivity; 5 | import android.support.v7.widget.Toolbar; 6 | import android.view.View; 7 | import android.widget.Button; 8 | import android.widget.Toast; 9 | 10 | 11 | 12 | public class DebuggerCheck extends AppCompatActivity { 13 | 14 | 15 | 16 | @Override 17 | protected void onCreate(Bundle savedInstanceState) { 18 | super.onCreate(savedInstanceState); 19 | setContentView(R.layout.activity_main); 20 | Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); 21 | setSupportActionBar(toolbar); 22 | 23 | Button b = (Button)findViewById(R.id.button); 24 | b.setOnClickListener(new View.OnClickListener() { 25 | 26 | 27 | @Override 28 | public void onClick(View v) { 29 | if(android.os.Debug.isDebuggerConnected()){ 30 | Toast.makeText(getApplicationContext(),"App is Being Debugged",Toast.LENGTH_LONG).show(); 31 | } 32 | 33 | } 34 | }); 35 | 36 | 37 | 38 | } 39 | -------------------------------------------------------------------------------- /multi-hooks-example.py: -------------------------------------------------------------------------------- 1 | import frida 2 | import sys 3 | 4 | package_name = "com.jni.anto.kalip" 5 | 6 | 7 | def get_messages_from_js(message, data): 8 | print(message) 9 | print (message['payload']) 10 | 11 | 12 | def instrument_debugger_checks(): 13 | 14 | hook_code = """ 15 | setTimeout(function(){ 16 | Java.perform(function () { 17 | 18 | var TM = Java.use("android.os.Debug"); 19 | 20 | TM.isDebuggerConnected.implementation = function () { 21 | 22 | send("Called - isDebuggerConnected()"); 23 | 24 | return false; 25 | }; 26 | 27 | var TMS = Java.use("android.telephony.TelephonyManager"); 28 | TMS.getDeviceId.implementation = function () { 29 | send("Called - deviceID()"); 30 | return "pwn3d"; 31 | }; 32 | 33 | }); 34 | 35 | },0); 36 | """ 37 | 38 | return hook_code 39 | 40 | 41 | process = frida.get_usb_device().attach(package_name) 42 | script = process.create_script(instrument_debugger_checks()) 43 | script.on('message',get_messages_from_js) 44 | script.load() 45 | sys.stdin.read() 46 | -------------------------------------------------------------------------------- /CheckFile.java: -------------------------------------------------------------------------------- 1 | package com.jni.anto.kalip; 2 | 3 | import android.os.Bundle; 4 | import android.support.v7.app.AppCompatActivity; 5 | import android.support.v7.widget.Toolbar; 6 | import android.view.View; 7 | import android.widget.Button; 8 | import android.widget.Toast; 9 | 10 | import java.io.File; 11 | 12 | 13 | public class CheckFile extends AppCompatActivity { 14 | 15 | 16 | @Override 17 | protected void onCreate(Bundle savedInstanceState) { 18 | super.onCreate(savedInstanceState); 19 | setContentView(R.layout.activity_main); 20 | Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); 21 | setSupportActionBar(toolbar); 22 | 23 | Button b = (Button) findViewById(R.id.button); 24 | b.setOnClickListener(new View.OnClickListener() { 25 | 26 | 27 | @Override 28 | public void onClick(View v) { 29 | 30 | File file = new File("/sdcard/test"); 31 | if (file.exists()) { 32 | Toast.makeText(getApplicationContext(),"File Exist",Toast.LENGTH_LONG).show(); 33 | } else { 34 | Toast.makeText(getApplicationContext(),"File Doesnt Exist",Toast.LENGTH_LONG).show(); 35 | } 36 | } 37 | }); 38 | 39 | 40 | } 41 | 42 | } 43 | 44 | 45 | -------------------------------------------------------------------------------- /file.py: -------------------------------------------------------------------------------- 1 | import frida 2 | import sys 3 | from subprocess import Popen 4 | 5 | package_name = "com.jni.anto.kalip" 6 | 7 | 8 | def get_messages_from_js(message, data): 9 | print(message) 10 | 11 | 12 | 13 | 14 | 15 | 16 | def fake_file_checks(): 17 | hook_code = """ 18 | setTimeout(function(){ 19 | Dalvik.perform(function () { 20 | 21 | var TM = Dalvik.use("java.io.File"); 22 | 23 | TM.exists.implementation = function () { 24 | send("Called - canRead()"); 25 | console.log(this.path['value']); 26 | var file_path = this.path['value']; 27 | var root_locations = ['/bin/su','/xbin/su','Superuser.apk','busybox','/sdcard/test']; 28 | for (i = 0; i < root_locations.length; i++) { 29 | console.log(" Comparing " + root_locations[i] + " with "+file_path); 30 | 31 | if(root_locations[i] === file_path){ 32 | console.log('lalal'); 33 | return false; 34 | } 35 | } 36 | return true; 37 | }; 38 | 39 | }); 40 | 41 | },0); 42 | """ 43 | 44 | return hook_code 45 | Popen("adb forward tcp:27042 tcp:27042", shell=True).wait() 46 | process = frida.get_device_manager().enumerate_devices()[-1].attach(package_name) 47 | script = process.create_script(fake_file_checks()) 48 | script.on('message',get_messages_from_js) 49 | script.load() 50 | sys.stdin.read() 51 | 52 | -------------------------------------------------------------------------------- /RootCheck.java: -------------------------------------------------------------------------------- 1 | package com.jni.anto.kalip; 2 | 3 | import android.os.Bundle; 4 | import android.support.v7.app.AppCompatActivity; 5 | import android.support.v7.widget.Toolbar; 6 | import android.view.View; 7 | import android.widget.Button; 8 | import android.widget.Toast; 9 | 10 | import java.io.File; 11 | 12 | 13 | public class RootCheck extends AppCompatActivity { 14 | 15 | 16 | 17 | @Override 18 | protected void onCreate(Bundle savedInstanceState) { 19 | super.onCreate(savedInstanceState); 20 | setContentView(R.layout.activity_main); 21 | Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); 22 | setSupportActionBar(toolbar); 23 | 24 | Button b = (Button)findViewById(R.id.button); 25 | b.setOnClickListener(new View.OnClickListener() { 26 | 27 | 28 | @Override 29 | public void onClick(View v) { 30 | if(isPhoneRooted()){ 31 | Toast.makeText(getApplicationContext(),"Phone Rooted",Toast.LENGTH_LONG).show(); 32 | } 33 | 34 | } 35 | }); 36 | 37 | } 38 | 39 | 40 | 41 | 42 | public static boolean isPhoneRooted() { 43 | 44 | // get from build info 45 | String buildTags = android.os.Build.TAGS; 46 | if (buildTags != null && buildTags.contains("test-keys")) { 47 | return true; 48 | } 49 | 50 | // check if /system/app/Superuser.apk is present 51 | try { 52 | File file = new File("/system/app/Superuser.apk"); 53 | if (file.exists()) { 54 | return true; 55 | } 56 | } catch (Throwable e1) { 57 | // ignore 58 | } 59 | 60 | return false; 61 | } 62 | 63 | } 64 | 65 | 66 | 67 | 68 | 69 | 70 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # frida-android-hooks 2 | 3 | Lets you hook LoadURL Method Calls in Frida ( Android ) 4 | 5 | Welcome to Firda- Hooks ( Android ) 6 | 7 | You will find different different modules to hook various api calls in the android platform to conduct security analysis. Right now , we have the following modules : 8 | 9 | WebView loadUrl() : android.webkit.WebView calls to webview is logged . 10 | 11 | getDeviceId() : android.telephony.TelephonyManager detects if the above api is called and can return a fake device id if needed. 12 | 13 | isDebuggerConnected() : android.os.Debug checks if a debugger is connected (JDB) to the app instance , can log and re-implement the method to fake it to the application which is being instrumented. 14 | 15 | .exists() : java.io.File checks for the presence of files in disk , can log and even hide the presence of files from applications using this api. 16 | 17 | Root Bypass Re- Implementation : root.py example on how a method could be re-implemented overriding the root-checks of an android application . 18 | 19 | Setup : 20 | 21 | 1 . Load Firda -server into your android device . 22 | 23 | $ curl -O https://build.frida.re/frida/android/arm/bin/frida-server 24 | 25 | $ adb push frida-server /data/local/tmp/ 26 | 27 | $ adb shell "chmod 755 /data/local/tmp/frida-server" 28 | 29 | $ adb shell "/data/local/tmp/frida-server &" 30 | 31 | 2 . Install frida on your machine , easy_install frida 32 | 33 | 3 . Change the package_name variable in the script to match the application you are instrumenting . 34 | 35 | 4 . Run python hook_webview_frida_example.py 36 | 37 | 5 . Run any app which uses the instumented method / api. 38 | 39 | Have fun ! 40 | 41 | 42 | 43 | Authors and Contributors 44 | 45 | @antojoseph 46 | 47 | Support or Contact 48 | 49 | Having trouble with Scripts ? Check out our documentation or contact support or Log an Issue and we’ll help you sort it out. 50 | -------------------------------------------------------------------------------- /objects-in-heap.js: -------------------------------------------------------------------------------- 1 | // Script taken from : https://github.com/brompwnie/uitkyk 2 | 3 | 4 | var objectsToLookFor = ["java.net.Socket", "dalvik.system.DexClassLoader", "java.net.URLConnection", "java.net.URL", "java.security.cert.X509Certificate"]; 5 | for (var i in objectsToLookFor) { 6 | Java.perform(function () { 7 | Java.choose(objectsToLookFor[i], { 8 | "onMatch": function (instance) { 9 | if (objectsToLookFor[i] == "java.net.URL" && instance.getProtocol() != "file") { 10 | console.log("\n[+] Process has Instantiated instance of: " + objectsToLookFor[i]); 11 | console.log("[*] Process is communicating via " + instance.getProtocol()); 12 | console.log("[+] Communication Details: " + instance.toString()); 13 | } 14 | if (objectsToLookFor[i] == "dalvik.system.DexClassLoader") { 15 | console.log("\n[+] Process has Instantiated instance of: " + objectsToLookFor[i]); 16 | console.log("[*] Process is making use of DexClassLoader"); 17 | console.log("[+] Loader Details: " + instance.toString()); 18 | } 19 | if (objectsToLookFor[i] == "java.net.Socket") { 20 | console.log("\n[+] Process has Instantiated instance of: " + objectsToLookFor[i]); 21 | console.log("[*] Process is making use of a Socket Connection"); 22 | console.log("[+] Socket Details: " + instance.toString()); 23 | } 24 | if (objectsToLookFor[i] == "java.net.URLConnection") { 25 | console.log("\n[+] Process has Instantiated instance of: " + objectsToLookFor[i]); 26 | console.log("[*] Process is making use of a URL Connection"); 27 | console.log("[+] Details: " + instance.toString()); 28 | } 29 | if (objectsToLookFor[i] == "java.security.cert.X509Certificate") { 30 | console.log("\n[+] Process has Instantiated instance of: " + objectsToLookFor[i]); 31 | console.log("[*] Process is making use of a X509Certificate"); 32 | console.log("[+] X509Certificate Details: " + instance.toString()); 33 | } 34 | }, 35 | "onComplete": function () { 36 | } 37 | }); 38 | }); 39 | } 40 | --------------------------------------------------------------------------------