- Apply patch.
- Build the helper blob, e.g.:
make -C src/linux/helpers FRIDA_HOST=android-x86_64
Last active
February 13, 2026 13:51
-
-
Save oleavr/0788840e8f33bd1888a4450540cfbc58 to your computer and use it in GitHub Desktop.
How to debug zymbiote.c
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| diff --git a/src/linux/helpers/artifacts/native/arm64/zymbiote.elf b/src/linux/helpers/artifacts/native/arm64/zymbiote.elf | |
| index a5e0cf09..00f6e299 100644 | |
| Binary files a/src/linux/helpers/artifacts/native/arm64/zymbiote.elf and b/src/linux/helpers/artifacts/native/arm64/zymbiote.elf differ | |
| diff --git a/src/linux/helpers/zymbiote.c b/src/linux/helpers/zymbiote.c | |
| index c01138b9..497e67cc 100644 | |
| --- a/src/linux/helpers/zymbiote.c | |
| +++ b/src/linux/helpers/zymbiote.c | |
| @@ -2,6 +2,7 @@ | |
| #include <jni.h> | |
| #include <signal.h> | |
| #include <stdbool.h> | |
| +#include <android/log.h> | |
| #include <sys/socket.h> | |
| #include <sys/un.h> | |
| @@ -23,6 +24,7 @@ struct _FridaApi | |
| ssize_t (* recv) (int sockfd, void * buf, size_t len, int flags); | |
| int (* close) (int fd); | |
| int (* raise) (int sig); | |
| + int (* __android_log_print) (int prio, const char * tag, const char * fmt, ...); | |
| }; | |
| static volatile const FridaApi frida = | |
| @@ -57,8 +59,12 @@ frida_zymbiote_replacement_setargv0 (JNIEnv * env, jobject clazz, jstring name) | |
| name_utf8 = (*env)->GetStringUTFChars (env, name, NULL); | |
| + frida.__android_log_print (ANDROID_LOG_INFO, "Frida", "setargv0 called with name=\"%s\"", name_utf8); | |
| + | |
| frida_wait_for_permission_to_resume (name_utf8, &revert_now); | |
| + frida.__android_log_print (ANDROID_LOG_INFO, "Frida", "revert_now=%s", revert_now ? "true" : "false"); | |
| + | |
| (*env)->ReleaseStringUTFChars (env, name, name_utf8); | |
| if (revert_now) | |
| @@ -79,11 +85,14 @@ frida_zymbiote_replacement_setcontext (uid_t uid, bool is_system_server, const c | |
| bool revert_now; | |
| res = frida.original_setcontext (uid, is_system_server, seinfo, name); | |
| + frida.__android_log_print (ANDROID_LOG_INFO, "Frida", "setcontext called with name=\"%s\" (res=%d)", name, res); | |
| if (res == -1) | |
| return -1; | |
| frida_wait_for_permission_to_resume (name, &revert_now); | |
| + frida.__android_log_print (ANDROID_LOG_INFO, "Frida", "revert_now=%s", revert_now ? "true" : "false"); | |
| + | |
| if (revert_now) | |
| { | |
| __attribute__ ((musttail)) | |
| diff --git a/src/linux/linux-host-session.vala b/src/linux/linux-host-session.vala | |
| index 545e54b5..07d925cd 100644 | |
| --- a/src/linux/linux-host-session.vala | |
| +++ b/src/linux/linux-host-session.vala | |
| @@ -968,6 +968,7 @@ namespace Frida { | |
| unowned string? payload_path = null; | |
| uint64 payload_file_offset = 0; | |
| unowned string? libc_path = null; | |
| + unowned string? liblog_path = null; | |
| unowned string? libselinux_path = null; | |
| unowned string? runtime_path = null; | |
| Gee.List<ProcMapsSnapshot.Mapping> heap_candidates = new Gee.ArrayList<ProcMapsSnapshot.Mapping> (); | |
| @@ -985,6 +986,9 @@ namespace Frida { | |
| } else if (path.has_suffix ("/libc.so")) { | |
| if (libc_path == null) | |
| libc_path = path; | |
| + } else if (path.has_suffix ("/liblog.so")) { | |
| + if (liblog_path == null) | |
| + liblog_path = path; | |
| } else if (path.has_suffix ("/libselinux.so")) { | |
| if (libselinux_path == null) | |
| libselinux_path = path; | |
| @@ -1000,6 +1004,8 @@ namespace Frida { | |
| throw new Error.NOT_SUPPORTED ("Unable to pick a payload base"); | |
| if (libc_path == null) | |
| throw new Error.NOT_SUPPORTED ("Unable to detect libc.so path"); | |
| + if (liblog_path == null) | |
| + throw new Error.NOT_SUPPORTED ("Unable to detect liblog.so path"); | |
| if (runtime_path == null) | |
| throw new Error.NOT_SUPPORTED ("Unable to detect libandroid_runtime.so path"); | |
| if (heap_candidates.is_empty) | |
| @@ -1009,6 +1015,10 @@ namespace Frida { | |
| if (libc_mapping == null) | |
| throw new Error.NOT_SUPPORTED ("Unable to detect mapping for %s", libc_path); | |
| + var liblog_mapping = maps.find_module_by_path (liblog_path); | |
| + if (liblog_mapping == null) | |
| + throw new Error.NOT_SUPPORTED ("Unable to detect mapping for %s", liblog_path); | |
| + | |
| var runtime_mapping = maps.find_module_by_path (runtime_path); | |
| if (runtime_mapping == null) | |
| throw new Error.NOT_SUPPORTED ("Unable to detect mapping for %s", runtime_path); | |
| @@ -1020,6 +1030,13 @@ namespace Frida { | |
| throw new Error.NOT_SUPPORTED ("Unable to parse %s: %s", libc_path, e.message); | |
| } | |
| + Gum.ElfModule liblog; | |
| + try { | |
| + liblog = new Gum.ElfModule.from_file (liblog_path); | |
| + } catch (Gum.Error e) { | |
| + throw new Error.NOT_SUPPORTED ("Unable to parse %s: %s", liblog_path, e.message); | |
| + } | |
| + | |
| uint64 original_setcontext = 0; | |
| if (libselinux_path != null) { | |
| Gum.ElfModule? libselinux; | |
| @@ -1074,8 +1091,8 @@ namespace Frida { | |
| uint64 replacement_setargv0; | |
| uint64 replacement_setcontext; | |
| - Bytes payload = make_zymbiote_payload (server_name, payload_base, libc, libc_mapping, original_setargv0, | |
| - original_setcontext, out replacement_setargv0, out replacement_setcontext); | |
| + Bytes payload = make_zymbiote_payload (server_name, payload_base, libc, libc_mapping, liblog, liblog_mapping, | |
| + original_setargv0, original_setcontext, out replacement_setargv0, out replacement_setcontext); | |
| var fd = open_process_memory (pid); | |
| @@ -1135,8 +1152,9 @@ namespace Frida { | |
| } | |
| private static Bytes make_zymbiote_payload (string server_name, uint64 payload_base, Gum.ElfModule libc, | |
| - ProcMapsSnapshot.Mapping libc_mapping, uint64 original_setargv0, uint64 original_setcontext, | |
| - out uint64 replacement_setargv0, out uint64 replacement_setcontext) { | |
| + ProcMapsSnapshot.Mapping libc_mapping, Gum.ElfModule liblog, ProcMapsSnapshot.Mapping liblog_mapping, | |
| + uint64 original_setargv0, uint64 original_setcontext, out uint64 replacement_setargv0, | |
| + out uint64 replacement_setcontext) { | |
| var pointer_size = libc.pointer_size; | |
| var blob = (pointer_size == 8) | |
| @@ -1230,6 +1248,15 @@ namespace Frida { | |
| cursor += pointer_size; | |
| } | |
| + liblog.enumerate_exports (e => { | |
| + if (e.name == "__android_log_print") { | |
| + payload.write_pointer (cursor, liblog_mapping.start + e.address); | |
| + cursor += pointer_size; | |
| + return false; | |
| + } | |
| + return true; | |
| + }); | |
| + | |
| return payload.bytes; | |
| } | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment