Skip to content

Instantly share code, notes, and snippets.

@oleavr
Last active February 13, 2026 13:51
Show Gist options
  • Select an option

  • Save oleavr/0788840e8f33bd1888a4450540cfbc58 to your computer and use it in GitHub Desktop.

Select an option

Save oleavr/0788840e8f33bd1888a4450540cfbc58 to your computer and use it in GitHub Desktop.
How to debug zymbiote.c

Steps

  1. Apply patch.
  2. Build the helper blob, e.g.: make -C src/linux/helpers FRIDA_HOST=android-x86_64
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