├── AndroGum └── jni │ ├── Android.mk │ ├── Application.mk │ ├── frida-gumjs.h │ └── main.cpp └── README.md /AndroGum/jni/Android.mk: -------------------------------------------------------------------------------- 1 | LOCAL_PATH := $(call my-dir) 2 | 3 | include $(CLEAR_VARS) 4 | 5 | LOCAL_MODULE := libgumjs 6 | LOCAL_SRC_FILES := libfrida-gumjs.a 7 | include $(PREBUILT_STATIC_LIBRARY) 8 | include $(CLEAR_VARS) 9 | 10 | LOCAL_MODULE := androgum 11 | 12 | LOCAL_SRC_FILES := main.cpp 13 | 14 | LOCAL_STATIC_LIBRARIES := libgumjs 15 | LOCAL_CFLAGS := -w 16 | 17 | LOCAL_LDLIBS := -landroid -llog -lz 18 | include $(BUILD_SHARED_LIBRARY) -------------------------------------------------------------------------------- /AndroGum/jni/Application.mk: -------------------------------------------------------------------------------- 1 | APP_ABI := arm64-v8a 2 | APP_CXXFLAGS := -std=c++2a 3 | APP_CPPFLAGS := -frtti -fexceptions 4 | APP_STL := c++_static 5 | APP_PLATFORM := android-30 -------------------------------------------------------------------------------- /AndroGum/jni/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include 7 | 8 | #include 9 | #include 10 | 11 | #include "frida-gumjs.h" 12 | 13 | #define LOGI(...) __android_log_print(ANDROID_LOG_INFO, "VPID", __VA_ARGS__) 14 | 15 | static void on_message(const gchar *message, GBytes *data, gpointer user_data) { 16 | // LOGI("on_message: %p", message); 17 | // JsonParser *parser; 18 | // JsonObject *root; 19 | // const gchar *type; 20 | 21 | // parser = json_parser_new(); 22 | // json_parser_load_from_data(parser, message, -1, NULL); 23 | // root = json_node_get_object(json_parser_get_root(parser)); 24 | 25 | // type = json_object_get_string_member(root, "type"); 26 | // if(strcmp(type, "log") == 0) { 27 | // const gchar *log_message; 28 | 29 | // log_message = json_object_get_string_member(root, "payload"); 30 | // g_print("%s\n", log_message); 31 | // } 32 | // else { 33 | // g_print("on_message: %s\n", message); 34 | // } 35 | 36 | // g_object_unref(parser); 37 | } 38 | 39 | 40 | void *main_thread(void *) { 41 | std::string myScript = ""; 42 | FILE *f = fopen("/data/local/tmp/script.js", "r"); 43 | if (!f) { 44 | return 0; 45 | } 46 | 47 | char buf[1024]; 48 | while (fgets(buf, sizeof(buf), f)) { 49 | myScript += buf; 50 | } 51 | 52 | fclose(f); 53 | 54 | GumScriptBackend *backend; 55 | GError *error = NULL; 56 | GumScript *script; 57 | GMainContext *context; 58 | 59 | gum_init(); 60 | 61 | backend = gum_script_backend_obtain_qjs(); 62 | 63 | script = gum_script_backend_create_sync(backend, "script", myScript.c_str(), 0, 0, &error); 64 | g_assert(error == NULL); 65 | 66 | gum_script_set_message_handler(script, on_message, NULL, NULL); 67 | 68 | gum_script_load_sync(script, 0); 69 | 70 | LOGI("Script loaded!"); 71 | 72 | context = g_main_context_get_thread_default(); 73 | 74 | // Change this to while(true){} incase crash. 75 | while(g_main_context_pending(context)) 76 | g_main_context_iteration(context, FALSE); 77 | 78 | gum_script_unload_sync(script, 0); 79 | 80 | LOGI("Script unloaded!"); 81 | 82 | g_object_unref(script); 83 | } 84 | 85 | JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM*vm, void*reserved) { 86 | LOGI("Hello from JNI_OnLoad :)"); 87 | pthread_t t; 88 | pthread_create(&t, NULL, main_thread, NULL); 89 | return JNI_VERSION_1_6; 90 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Debugger Detection Bypass 2 | By default, frida's gadget will attach a debugger to the target process.\ 3 | To bypass or detect this behavior, we can use the following script to bypass the debugger detection and inject it before the app has the time to detect for a debugger. 4 | ```js 5 | Interceptor.attach(Module.findExportByName(null, "ptrace"), function (args) { 6 | console.log("ptrace called"); 7 | }); 8 | ``` 9 | 10 | # Default Port Bypass 11 | Frida Server default listening port is 27042. In some case, an app will check if the port 27042 is open.\ 12 | To bypass or detect this behavior, we can change the listen port to another port. 13 | ```sh 14 | frida-server -l 0.0.0.0:27043 15 | ``` 16 | 17 | # Port Scanning / Fingerprinting Bypass 18 | By default, Frida communicates with the client using WebSocket. In some case, an app will pretend to be a WebSocket and act like a client.\ 19 | To bypass or detect this behavior, we can set the ORIGIN to any string. 20 | ``` 21 | # On frida-server 22 | frida-server -l 0.0.0.0:27043 --origin=AKANE 23 | 24 | # On client 25 | frida-ps -H device_ip:27043 --origin=AKANE 26 | ``` 27 | 28 | Alternatively, we can set CERTIFICATE to make sure the frida communication is only performed in TLS. 29 | ``` 30 | # On frida-server 31 | frida-server -l 0.0.0.0:27043 --certificate=certificate.pem 32 | 33 | # On client 34 | frida-ps -H device_ip:27043 --certificate=certificate.pem 35 | ``` 36 | 37 | # Artifacts Detection Bypass 38 | When frida gadget is injected to a process, it will leave some Artifacts especially in the memory.\ 39 | To bypass or detect this behavior, we can use a customized frida-server such as: 40 | - https://github.com/hzzheyang/strongR-frida-android 41 | 42 | ## Notes 43 | It is recommended that you build the frida yourself so that any string artifacts are changed incase the developer already flagged the binaries in the repo release. 44 | 45 | # Gadget Detection Bypass 46 | There are lots of way to detect frida gadgets which might be overwhelming, one of them is Debugger Detection.\ 47 | But let's say found a way to inject a library to the target process, then you can use the frida's gumjs.\ 48 | It injects the script directly through the memory without needing a gadget.\ 49 | 50 | Compile [AndroGum](AndroGum) using NDK and use the library to inject a script. 51 | ## Notes 52 | Don't forget to download [libfrida-gumjs.a](https://github.com/frida/frida/releases) and put it in the same dir as Android.mk. 53 | --------------------------------------------------------------------------------