Skip to content

Instantly share code, notes, and snippets.

@oleavr
Last active March 13, 2026 10:50
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/zymbiote.c b/src/linux/helpers/zymbiote.c
index 29795135..e6a7d689 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/mman.h>
#include <sys/socket.h>
#include <sys/un.h>
@@ -33,6 +34,7 @@ struct _ZymbioteContext
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, ...);
};
ZymbioteContext zymbiote =
@@ -62,6 +64,7 @@ frida_zymbiote_replacement_setcontext (uid_t uid, bool is_system_server, const c
int res;
res = zymbiote.original_setcontext (uid, is_system_server, seinfo, name);
+ zymbiote.__android_log_print (ANDROID_LOG_INFO, "Frida", "setcontext called with name=\"%s\" (res=%d)", name, res);
if (res == -1)
return -1;
@@ -69,6 +72,7 @@ frida_zymbiote_replacement_setcontext (uid_t uid, bool is_system_server, const c
{
zymbiote.mprotect (zymbiote.payload_base, zymbiote.payload_size, PROT_READ | PROT_WRITE | PROT_EXEC);
zymbiote.package_name = zymbiote.strdup (name);
+ zymbiote.__android_log_print (ANDROID_LOG_INFO, "Frida", "setcontext hook stored package_name=\"%s\"", zymbiote.package_name);
}
return res;
@@ -85,9 +89,15 @@ frida_zymbiote_replacement_setargv0 (JNIEnv * env, jobject clazz, jstring name)
zymbiote.original_set_argv0 (env, clazz, name);
if (zymbiote.package_name != NULL)
+ {
name_utf8 = zymbiote.package_name;
+ zymbiote.__android_log_print (ANDROID_LOG_INFO, "Frida", "setargv0 hook using name=\"%s\" from selinux_android_setcontext()", name_utf8);
+ }
else
+ {
name_utf8 = (*env)->GetStringUTFChars (env, name, NULL);
+ zymbiote.__android_log_print (ANDROID_LOG_INFO, "Frida", "setargv0 hook using name=\"%s\" from argument list", name_utf8);
+ }
frida_wait_for_permission_to_resume (name_utf8, &revert_now);
diff --git a/src/linux/linux-host-session.vala b/src/linux/linux-host-session.vala
index 24432646..9e2664a9 100644
--- a/src/linux/linux-host-session.vala
+++ b/src/linux/linux-host-session.vala
@@ -1606,6 +1606,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> ();
@@ -1626,6 +1627,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;
@@ -1641,6 +1645,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)
@@ -1650,6 +1656,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);
@@ -1661,6 +1671,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;
@@ -1716,7 +1733,8 @@ namespace Frida {
uint64 replacement_setargv0;
uint64 replacement_setcontext;
Bytes payload = make_zymbiote_payload (server_name, payload_base, payload_original_protection, libc, libc_mapping,
- original_setargv0, original_setcontext, out replacement_setargv0, out replacement_setcontext);
+ liblog, liblog_mapping, original_setargv0, original_setcontext, out replacement_setargv0,
+ out replacement_setcontext);
var fd = open_process_memory (pid);
@@ -1776,8 +1794,9 @@ namespace Frida {
}
private static Bytes make_zymbiote_payload (string server_name, uint64 payload_base, int payload_original_protection,
- Gum.ElfModule libc, ProcMapsSnapshot.Mapping libc_mapping, uint64 original_setargv0,
- uint64 original_setcontext, out uint64 replacement_setargv0, out uint64 replacement_setcontext) {
+ Gum.ElfModule libc, 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)
@@ -1885,6 +1904,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