文章总结: 本文详细解读了Frida17.9.0版本的新功能,特别是其引入的eBPFspawngater机制。该版本旨在通过内核级技术增强隐蔽性,核心更新包括:1.使用eBPF在内核层面拦截execve系统调用来暂停进程,替代传统ptrace方案以隐藏TracerPid特征;2.实现了对被SIGSTOP信号暂停进程的注入;3.新增control-endpoint选项,允许通过localabstract等方式自定义连接端点以绕过端口检测。此外,文章还分析了新版本如何通过隐藏ptrace特征、Frida监听端口以及子进程创建监控的特征来对抗检测,并探讨了其代码实现细节。 综合评分: 85 文章分类: 逆向分析,二进制安全,恶意软件,渗透测试,红队
Frida官方下场做Frida隐藏功能,strongfrida快要死了?17.9.0引入的新功能全解读
原创
非虫 非虫
软件安全与逆向分析
2026年3月29日 10:23 湖北
Frida17.9.0引入的新功能解读
Frida这个版本的更新看上去是将eBPF的能力继续辐射到更多的Frida功能组件上。而且重点是官方将Frida隐藏作为重要的功能提上了日程。
这个版本的更新里面,Frida隐藏的部分有:
- 将ptrace特征彻底隐藏
- 隐藏Frida监听端口
- 隐藏子进程创建监控的特征
关于子进程创建监控的特征,我们这里再多说几句。国内X加密的企业版本在检测Frida时,使用了一个比较取巧的方法。重点在于监控进程的fork操作的:https://github.com/frida/frida-core/blob/main/lib/payload/fork-monitor.vala 。它会对fork与vfork进行监控。里面有一行代码:
interceptor.replace (vfork_impl, fork_impl);
意味着它会对这两个接口进行InlineHook,但它们的处理器使用同一个,这两者在进程空间的数据同步上有着一些差异,比如在父进程中的一个全局变量,子进程中它们的数据访问同步规则不同,这就可以用来检测fork与vfork是否被Hook,进而检测Frida。目前Frida官方并没有实现它的过检测,希望官方能够对其进行处理。这其实需要对interceptor.replace这类接口做eBPF的大手术,可能会有难度与兼容性的问题出现。
背景
Frida 17.9.0(2026年3月26日)紧跟17.8.0发布,带来了几项对安全研究者非常实用的新能力。三个核心更新值得重点关注:
-
Linux eBPF spawn gater
——在内核层面拦截
execve,实现比传统ptrace方案更隐蔽、更高效的进程捕获。 -
Group-stopped PIDs注入
——解决了eBPF spawn gater将进程SIGSTOP后无法注入的工程难题。
-
control-endpoint后端选项
——允许自定义frida-server连接端点,可通过
localabstract:等非标准端口绕过Frida端口检测。
从演进线看,17.8.0完成了eBPF syscall-tracer主线收编,17.9.0则将eBPF的应用范围扩展到spawn gating领域,并围绕它做了完整的工程闭环——从内核拦截到用户态注入再到端口隐藏,形成了一条完整的反检测链路。
分析范围与方法
分析窗口以17.9.0新增功能为主线(frida-core commit 4e5a60a5..c3864a15),同时覆盖17.8.x开发周期中的关键架构变更。涉及以下子项目:
| 子项目 | 17.9.0核心提交 | 聚焦方向 | | — | — | — | | frida-core | 7 | spawn gater、group-stopped注入、control-endpoint | | frida-gum | – | 无17.9.0专属提交 | | frida-python | 3 | override_option绑定、spawn gating示例 | | frida-tools | – | releng同步 |
本文聚焦以下代码:
- eBPF内核侧拦截:
src/linux/helpers/spawn-gater.bpf.c - 用户态spawn管理:
src/linux/spawn-gater.vala - 宿主会话集成:
src/linux/linux-host-session.vala - Group-stopped注入逻辑:
src/linux/frida-helper-backend.vala内InjectSession - 设备选项覆盖:
src/frida.vala内override_option() - Droidy/Fruity后端:
src/droidy/droidy-host-session.vala与src/fruity/fruity-host-session.vala
核心功能一:eBPF spawn gater
1 设计动机
Frida在macOS上早已通过DTrace实现spawn gating——当目标系统上有新进程exec时,先暂停该进程,通知Frida用户决定是否注入,再恢复执行。但Linux上一直缺少内核级的spawn gating实现,此前只在Android上通过Zygote子进程gating部分覆盖了这一需求。
17.9.0引入的eBPF spawn gater填补了这一空白。它的核心思路极为精炼:在execve系统调用入口处用eBPF程序发送SIGSTOP信号,把新进程冻住,同时通过ringbuf通知用户态。
这个方案的工程价值在于:eBPF程序运行在内核态,不需要ptrace附加目标进程,也不会在目标进程的/proc/pid/status中留下TracerPid痕迹,具有天然的反检测优势。
2 eBPF内核程序:spawn-gater.bpf.c
完整的eBPF程序只有55行,非常精炼。核心代码如下:
#include"frida-linux-syscalls.h"
#include<linux/bpf.h>
#include<bpf/bpf_helpers.h>
#include<bpf/bpf_tracing.h>
#define SIGSTOP 19
#define MAX_FILENAME 256
typedefstruct _ExecveEventExecveEvent;
struct _ExecveEvent
{
int pid;
char command[MAX_FILENAME];
};
struct
{
__uint (type, BPF_MAP_TYPE_RINGBUF);
__uint (max_entries, 1 << 22);
}
events SEC(".maps");
structtrace_event_raw_sys_enter
{
__u64 unused;
long id;
unsignedlong args[6];
};
SEC ("tracepoint/raw_syscalls/sys_enter")
int
on_execve_enter(struct trace_event_raw_sys_enter * ctx)
{
__s32 nr = (__s32) ctx->id;
if (nr != FRIDA_LINUX_SYSCALL_EXECVE)
return0;
ExecveEvent * e = bpf_ringbuf_reserve (&events, sizeof (ExecveEvent), 0);
if (e == NULL)
return0;
e->pid = bpf_get_current_pid_tgid () >> 32;
constchar * filename = (constchar *) ctx->args[0];
bpf_probe_read_user_str (e->command, sizeof (e->command), filename);
bpf_ringbuf_submit (e, 0);
bpf_send_signal (SIGSTOP);
return0;
}
char LICENSE[] SEC ("license") = "Dual BSD/GPL";
逐层分析关键设计决策:
挂载点选择:tracepoint/raw_syscalls/sys_enter
与17.8.0的syscall-tracer一脉相承,使用raw_syscalls/sys_enter而非tracepoint/syscalls/sys_enter_execve。原因是Android GKI 2.0内核默认关闭了FTRACE_SYSCALLS,而raw_syscalls是always-on的。通过在eBPF内部手动判断ctx->id == FRIDA_LINUX_SYSCALL_EXECVE来过滤,虽然多了一次比较,但换来了对所有Linux/Android内核的兼容性。
FRIDA_LINUX_SYSCALL_EXECVE定义在frida-linux-syscalls.h中,会根据目标架构自动选择正确的系统调用号(x86_64上为59,arm64上为221等),预编译产物覆盖了arm、arm64、x86、x86_64、mips、mips64共10个架构变体。
事件结构:ExecveEvent
struct _ExecveEvent {
int pid; // 进程TGID
char command[MAX_FILENAME]; // execve第一个参数:可执行文件路径
};
结构极简,只包含PID和命令路径。使用bpf_get_current_pid_tgid() >> 32获取TGID(即进程PID),通过bpf_probe_read_user_str从用户空间安全读取execve的第一个参数(文件名)。
核心机制:bpf_send_signal(SIGSTOP)
这是整个设计最精妙的一行。bpf_send_signal()是Linux 5.3引入的BPF helper,允许eBPF程序直接向当前任务发送信号。调用bpf_send_signal(SIGSTOP)会让正在执行execve的进程立即被内核暂停——进程进入group-stop状态。
这与ptrace的PTRACE_ATTACH完全不同:
-
ptrace会在目标进程的
/proc/pid/status中设置TracerPid字段,容易被反调试检测 -
SIGSTOP导致的group-stop是正常的进程状态,不涉及调试器附加
-
eBPF程序运行在内核上下文,对目标进程完全透明
ringbuf通信
使用BPF_MAP_TYPE_RINGBUF(大小4MB,即1 << 22)。先bpf_ringbuf_reserve预留空间、填充数据、再bpf_ringbuf_submit提交。比BPF_MAP_TYPE_PERF_EVENT_ARRAY更高效,不需要per-CPU buffer。
3 用户态管理:SpawnGater类
src/linux/spawn-gater.vala实现了完整的用户态管理逻辑,总计154行。
SpawnGater
├── start() // 加载eBPF程序,attach tracepoint,监听ringbuf
├── stop() // 卸载eBPF,恢复所有pending进程
├── enumerate_pending_spawn() // 返回当前被拦截的进程列表
├── try_resume() // 恢复指定进程
├── signal spawn_added // 通知上层有新进程被拦截
└── signal spawn_removed // 通知上层进程已恢复
启动流程
publicvoid start () throws Error {
var obj = BpfObject.open ("spawn-gater.elf",
Frida.Data.HelperBackend.get_spawn_gater_elf_blob ().data);
var events = obj.maps.get_by_name ("events");
obj.prepare ();
events_reader = new BpfRingbufReader (events);
obj.load ();
foreach (var program in obj.programs) {
var link = program.attach ();
links.add (link);
}
// 设置epoll监听ringbuf的fd
events_channel = new IOChannel.unix_new (events.fd);
var src = new IOSource (events_channel, IOCondition.IN);
var state = new EventsWatchState (this);
src.set_callback (state.on_ready);
src.attach (MainContext.get_thread_default ());
events_source = src;
}
这里复用了17.8.0引入的BpfObject和BpfRingbufReader基础设施。预编译的spawn-gater.elf以资源blob形式内嵌在frida-helper中,运行时通过libbpf加载。
BpfRingbufReader内部使用epoll监听ringbuf的文件描述符。当内核侧有新事件写入时,通过GLib的IOSource回调on_ready,进而调用process_pending_events()拉取事件。
事件处理
privatevoid handle_event (ExecveEvent * e) {
var info = HostSpawnInfo (e->pid, (string) e->command);
pending_spawn[e->pid] = info;
spawn_added (info);
}
每个事件被解析为HostSpawnInfo(包含pid和可执行文件路径),存入pending_spawn字典,并通过spawn_added信号通知上层。
恢复机制
publicbool try_resume (uint pid) {
HostSpawnInfo? spawn;
if (!pending_spawn.unset (pid, out spawn))
returnfalse;
spawn_removed (spawn);
perform_resume.begin (pid);
returntrue;
}
privateasyncvoid perform_resume (uint pid) {
try {
yield helper.resume (pid, null);
} catch (GLib.Error e) {
if (e is Error.INVALID_ARGUMENT)
Posix.kill ((Posix.pid_t) pid, Posix.Signal.CONT);
}
}
恢复时优先尝试通过helper.resume()(ptrace方式),如果失败则退回kill(pid, SIGCONT)直接发送继续信号。这个双路径设计保证了健壮性:如果进程已经被注入过(由InjectSession管理),走ptrace路径;否则走简单的SIGCONT。
4 宿主会话集成
linux-host-session.vala中的修改将spawn gater无缝集成到Frida的现有架构中:
publicoverrideasyncvoid enable_spawn_gating (...) {
// 先预加载helper(确保64位和32位helper都已就绪)
var helper_process = helper as LinuxHelperProcess;
if (helper_process != null)
yield helper_process.preload (cancellable);
var gater = ensure_spawn_gater ();
if (gater.state == STOPPED) {
// Android上允许eBPF启动失败(可能缺少CAP_BPF)
// 纯Linux上直接抛异常
#if ANDROID
try { gater.start (); } catch (Error e) { }
#else
gater.start ();
#endif
}
#if ANDROID
yield robo_launcher.enable_spawn_gating (cancellable);
#endif
}
关键设计点:
-
预加载helper
:
preload()方法确保frida-helper-64和frida-helper-32都已启动,避免后续注入时的延迟。 -
Android双轨制
:在Android上,eBPF spawn gater与传统的Zygote-based RoboLauncher并行工作。eBPF覆盖所有通过
execve启动的原生进程,RoboLauncher覆盖Java层fork出的App进程。两者产出的spawn事件统一汇聚到同一个spawn_added信号。 -
容错处理
:Android上eBPF启动失败不影响RoboLauncher工作,旧设备仍然可以通过Java层方案完成spawn gating。
enumerate_pending_spawn()也做了合并:
publicoverrideasync HostSpawnInfo[] enumerate_pending_spawn (...) {
var result = new HostSpawnInfo[0];
if (spawn_gater != null)
foreach (var spawn in spawn_gater.enumerate_pending_spawn ())
result += spawn;
#if ANDROID
foreach (var spawn in robo_launcher.enumerate_pending_spawn ())
result += spawn;
#endif
return result;
}
恢复时也是双路径尝试:
protectedoverrideasyncvoid perform_resume (uint pid, ...) {
if (spawn_gater != null && spawn_gater.try_resume (pid))
return;
#if ANDROID
if (robo_launcher.try_resume (pid))
return;
#endif
yield helper.resume (pid, cancellable);
}
核心功能二:Group-stopped PIDs注入
1 问题根源
eBPF spawn gater通过bpf_send_signal(SIGSTOP)将进程冻住。但这产生了一个新的工程问题:被SIGSTOP暂停的进程处于group-stop状态(/proc/pid/stat中标记为T),Frida原有的注入路径无法正确处理这种状态的进程。
原因是Frida的注入基于ptrace。标准流程是:
ptrace(SEIZE, pid) → ptrace(INTERRUPT, pid) → waitpid() → 注入 → ptrace(DETACH, pid)
但对于已经处于group-stop的进程,ptrace(INTERRUPT, pid)的行为不符合预期——进程已经停了,再发INTERRUPT会导致信号等待逻辑卡住或返回错误。
2 解决方案
commit 0bee9cba通过以下策略解决了这个问题:
第一步:检测group-stop状态
新增query_process_state()方法,通过读取/proc/<tid>/stat来判断进程状态:
privatestaticchar query_process_state (uint tid) {
try {
string stat;
FileUtils.get_contents ("/proc/%u/stat".printf (tid), out stat);
int paren_end = stat.last_index_of_char (')');
if (paren_end != -1 && paren_end + 2 < stat.length)
return stat[paren_end + 2];
} catch (FileError e) {
}
return'?';
}
/proc/pid/stat的格式是pid (comm) state ...,状态字符紧跟最后一个右括号后的空格。T表示stopped(包括group-stop和ptrace-stop),S表示sleeping,R表示running。代码使用last_index_of_char(')')定位最后一个),因为进程名(comm字段)本身可能包含括号和空格,从后向前搜索才能避免误解析。
第二步:差异化的ptrace附加流程
bool was_stopped = seize_supported && query_process_state (tid) == 'T';
// ...
if (seize_supported) {
if (was_stopped) {
was_group_stopped = true;
yield wait_for_next_stop (cancellable);
Posix.kill ((Posix.pid_t) pid, Posix.Signal.CONT);
} else {
ptrace (INTERRUPT, tid);
yield wait_for_signal (TRAP, cancellable);
}
}
对group-stopped进程的处理与正常进程完全不同:
- 跳过
ptrace(INTERRUPT)——进程已经停了,不需要再中断 - 直接
wait_for_next_stop()——等待ptrace报告当前的stop状态 - 发送
SIGCONT——将进程从group-stop切换到ptrace-stop,使后续的注入操作能正常进行
第三步:注入后保持暂停
var session = yield InjectSession.open (pid, cancellable);
RemoteAgent agent = yield session.inject (spec, cancellable);
if (session.was_group_stopped)
backend.suspended_by_inject[pid] = session;
else
session.close ();
如果目标进程原本就是group-stopped的(由eBPF spawn gater暂停),注入完成后不立即detach,而是保持InjectSession打开,把session存入suspended_by_inject字典。这样进程仍然处于暂停状态,等待用户显式resume()。
第四步:resume时清理
InjectSession inject_session;
if (backend.suspended_by_inject.unset (pid, out inject_session)) {
inject_session.close (); // ptrace detach,进程恢复执行
returnnull;
}
当用户调用resume(pid)时,从suspended_by_inject中取出session并close,触发ptrace detach,进程恢复执行。
3 完整链路
将eBPF spawn gater与group-stopped注入串联起来,完整的进程捕获-注入-恢复流程如下:
1. 目标进程调用 execve()
2. eBPF tracepoint 触发 on_execve_enter()
3. bpf_send_signal(SIGSTOP) → 进程进入 group-stop
4. bpf_ringbuf_submit() → 事件写入 ringbuf
5. SpawnGater.process_pending_events() 收到事件
6. spawn_added 信号通知用户
7. 用户决定注入 → attach(pid)
8. InjectSession.open() 检测到 'T' 状态
9. ptrace(SEIZE) → wait → SIGCONT → 注入代码
10. session 存入 suspended_by_inject(进程仍暂停)
11. 用户调用 resume(pid)
12. InjectSession.close() → ptrace(DETACH) → 进程恢复执行
整条链路的关键在于:eBPF拦截阶段完全不涉及ptrace,目标进程的TracerPid始终为0。只在注入阶段短暂使用ptrace(SEIZE)——此时TracerPid会被设置——但注入完成后立即ptrace(DETACH)将其清零。与传统的全程ptrace跟踪相比,TracerPid暴露窗口从”整个生命周期”缩短到”毫秒级注入窗口”。
核心功能三:control-endpoint后端选项
1 override_option()框架
17.9.0在Device类上新增了override_option()方法,建立了后端选项覆盖的通用框架:
publicvoid override_option (string name, Variant val) throws Error {
Value v;
switch (val.classify ()) {
case BOOLEAN:
v = Value (typeof (bool));
v.set_boolean (val.get_boolean ());
break;
case STRING:
v = Value (typeof (string));
v.set_string (val.get_string ());
break;
// ... 还支持 INT64, UINT64, DOUBLE
default:
throw new Error.INVALID_ARGUMENT ("Unsupported option type");
}
lock (host_session_options) {
if (host_session_options == null)
host_session_options = new HostSessionOptions ();
host_session_options.map[name] = v;
}
}
选项存储在HostSessionOptions中(一个Gee.HashMap<string, Value?>),创建host session时通过copy()方法线程安全地传递给后端Provider:
HostSessionOptions? opts;
lock (host_session_options)
opts = (host_session_options != null) ? host_session_options.copy () : null;
var session = yield provider.create (manager, opts, cancellable);
设计上,选项在建立host session时生效。如果session已存在,更新后的值在下次连接时才应用。
2 Droidy(Android)control-endpoint
Droidy后端接受任意ADB支持的endpoint格式:
string control_endpoint = ("tcp:%" + uint16.FORMAT_MODIFIER + "u")
.printf (DEFAULT_CONTROL_PORT); // 默认 "tcp:27042"
if (options != null) {
Value? control_endpoint_val = options.map["control-endpoint"];
if (control_endpoint_val != null) {
if (!control_endpoint_val.holds (typeof (string)))
throw new Error.INVALID_ARGUMENT (
"The control-endpoint option must be a string");
control_endpoint = control_endpoint_val.get_string ();
}
}
host_session = new DroidyHostSession (device_details, this, control_endpoint);
control_endpoint随后在连接frida-server时使用:
// 原来硬编码:
// var stream = yield channel_provider.open_channel ("tcp:27042", cancellable);
// 现在可配置:
var stream = yield channel_provider.open_channel (control_endpoint, cancellable);
open_channel()底层通过ADB的forward或reverse机制建立连接。ADB支持的endpoint格式包括:
| 格式 | 说明 | 示例 |
| — | — | — |
| tcp:<port> | TCP端口 | tcp:27042 |
| localabstract:<name> | Linux抽象Unix socket | localabstract:/my-frida-server |
| localreserved:<name> | 保留Unix socket | localreserved:frida |
| localfilesystem:<path> | 文件系统Unix socket | localfilesystem:/data/frida.sock |
3 Fruity(iOS)control-endpoint
Fruity后端仅支持TCP端口,从endpoint字符串中解析端口号:
uint16 control_port = DEFAULT_CONTROL_PORT; // 27042
if (options != null) {
Value? control_endpoint_val = options.map["control-endpoint"];
if (control_endpoint_val != null) {
unownedstring control_endpoint = control_endpoint_val.get_string ();
if (!control_endpoint.has_prefix ("tcp:"))
throw new Error.INVALID_ARGUMENT (
"The control-endpoint must be TCP-flavored");
control_port = (uint16) uint.parse (control_endpoint[4:]);
}
}
iOS由于走的是usbmuxd或RemoteXPC隧道,底层实现与ADB不同,只能转发TCP端口。
4 Python绑定
# frida/core.py
@cancellable
defoverride_option(self, name: str, value: Any) -> None:
"""Override a backend-specific option"""
self._impl.override_option(name, value)
C扩展层通过PyGObject_unmarshal_variant将Python对象转换为GVariant,再调用frida_device_override_option()。
对于命令行用户,frida和frida-trace等工具暂时还未直接暴露--control-endpoint参数,需要通过Python API使用。
其他重要更新
64位设备跳过32位helper(17.9.0)
commit be239982为纯64位Android设备(如Pixel 7+)跳过32位helper的启动尝试:
if (sizeof (void *) == 8 &&
_query_android_system_property ("ro.product.cpu.abilist32") == "")
throw new Error.NOT_SUPPORTED (
"Android system does not support 32-bit processes");
通过检查ro.product.cpu.abilist32系统属性是否为空来判断。在纯64位设备上避免无意义的32位helper spawn失败,减少启动耗时和日志噪音。
XCFramework devkit打包(17.9.0)
frida-gum新增了将devkit打包为XCFramework的工具支持(由sewerynplazuk贡献)。XCFramework是Apple推荐的多架构框架分发格式,支持在一个bundle中包含iOS真机(arm64)、iOS模拟器(arm64/x86_64)和macOS等多个平台的库。这对于在Xcode项目中集成Frida SDK的开发者来说减少了手动管理fat binary和lipo的工作。
以下更新来自17.8.x开发周期:
Android轻量级Zygote Hook(17.8.x)
commit 3e778a99重写了Android的spawn gating机制,从”注入内部agent到Zygote”改为轻量级方案:
- 通过
/proc/$pid/mem向Zygote进程的代码区写入微型payload(zymbiote,约740-920字节,按架构不同而变化) - Patch
android.os.Process.setArgV0Native()的ArtMethod,跳转到payload - payload作为代理,链式调用原始
setArgV0Native - 同时建立Unix socket连接回frida-core,报告新App的spawn
不再需要注入frida-java-bridge到Zygote,去掉了对system_server代码注入的依赖。
frida-helper.dex统一化(17.8.x)
commit 1b908e69将frida-helper.dex的使用从非root场景扩展到所有场景,统一了Android helper架构。唯一损失的功能是launch-timeout抑制。
Interceptor FORCE标志(17.8.x)
frida-gum新增GUM_ATTACH_FLAGS_FORCE标志(commit b665c979),允许对”太短”的函数强制inline hook:
typedefenum {
GUM_ATTACH_FLAGS_NONE = 0,
GUM_ATTACH_FLAGS_UNIGNORABLE = (1 << 0),
GUM_ATTACH_FLAGS_FORCE = (1 << 1), // 新增
} GumAttachFlags;
正常情况下,如果目标函数体太短(不够放跳转指令+保存上下文),Interceptor会拒绝attach。启用FORCE标志后,Interceptor会直接覆写函数末尾后面的字节。这在函数之间有对齐padding的情况下是安全的,frida-core的ELF RTLD notifier强制hook(commit 35c5d862)即使用了此标志。
RISC-V初步支持(17.8.x)
commit 747a9cd1在frida-core中添加了RISC-V架构的初步支持,为后续在RISC-V设备上运行Frida铺平道路。
Python绑定改进
- 新增spawn gating完整示例(
examples/spawn_gating.py),展示了enable_spawn_gating()→监听spawn-added→按条件注入→resume()的标准用法 - 修复child gating示例中过时的API调用(
getExportByName→getGlobalExportByName,Memory.readUtf8String(args[0])→args[0].readUtf8String()) - 类型标注改进:
@cancellable装饰器改进、flag字面量类型支持
frida-gum其他修复
| 提交 | 说明 |
| — | — |
| b75ee4a2 | 修复arm64 ucontext记录解析 |
| bd80b1a6 | 修复ELF32的GNU hash解析 |
| e9a92eb4 | 改进ELF文件偏移验证 |
| ed3388d7 | 验证HASH和GNU_HASH节的边界 |
| 414c40e9 | Android APK libs在enumerateRanges()中的处理 |
| 2f898792 | 处理__pthread_start符号后缀 |
提交归纳
frida-core 17.9.0核心提交
| 提交 | 分类 | 说明 |
| — | — | — |
| 465698a9 | 新功能 | eBPF spawn gater(NSEcho & oleavr) |
| 0bee9cba | 新功能 | Group-stopped PIDs注入支持 |
| be239982 | 优化 | 64位设备跳过32位helper |
| f9629316 | 基础设施 | HostSessionOptions.copy() |
| 3df05876 | 新功能 | Device.override_option()方法 |
| d2f2c400 | 新功能 | Droidy control-endpoint选项 |
| 1f77154b | 新功能 | Fruity control-endpoint选项 |
frida-core 17.8.x周期关键提交
| 提交 | 分类 | 说明 |
| — | — | — |
| 3e778a99 | 重构 | Android轻量级Zygote hooking(zymbiote) |
| 1b908e69 | 重构 | frida-helper.dex统一化 |
| 747a9cd1 | 新功能 | RISC-V初步支持 |
| 55c8bcb8 | 修复 | Fruity USB启动/关闭竞态 |
frida-gum(17.8.x周期)
| 提交 | 分类 | 说明 |
| — | — | — |
| b665c979 | 新功能 | Interceptor FORCE attach标志 |
| 35c5d862 | 增强 | ELF RTLD notifier强制hook |
| 2f898792 | 修复 | Android __pthread_start符号后缀处理 |
frida-python(17.9.0)
| 提交 | 分类 | 说明 |
| — | — | — |
| cc9a78e | 新功能 | Device.override_option()绑定 |
| 22ed1fa | 文档 | spawn gating示例 |
| 9b15bde | 修复 | child gating示例更新 |
总结
Frida 17.9.0的更新虽然只有7个核心提交,但形成了清晰的技术闭环:
-
eBPF spawn gater
在内核层面拦截进程创建,不留ptrace痕迹
-
Group-stopped注入
解决了eBPF拦截后的代码注入工程问题
-
control-endpoint
允许隐藏frida-server的网络指纹
三者串联使用,构成了一条完整的Frida反检测链路:eBPF无痕拦截 → 短窗口ptrace注入 → 非标准端口/socket通信。对于安全研究者来说,这意味着在对抗重防护App时多了一套可靠的工程选择。
从Frida的技术演进看,17.8.0和17.9.0连续两个版本都在深化eBPF的应用——从系统调用跟踪到进程捕获,eBPF正在成为Frida在Linux/Android平台上的核心基础设施之一。
同时也希望Frida作者在本体隐藏这一点上再接再厉!
免责声明:
本文所载程序、技术方法仅面向合法合规的安全研究与教学场景,旨在提升网络安全防护能力,具有明确的技术研究属性。
任何单位或个人未经授权,将本文内容用于攻击、破坏等非法用途的,由此引发的全部法律责任、民事赔偿及连带责任,均由行为人独立承担,本站不承担任何连带责任。
本站内容均为技术交流与知识分享目的发布,若存在版权侵权或其他异议,请通过邮件联系处理,具体联系方式可点击页面上方的联系我。
本文转载自:软件安全与逆向分析 非虫 非虫《Frida官方下场做Frida隐藏功能,strongfrida快要死了?17.9.0引入的新功能全解读》
版权声明
本站仅做备份收录,仅供研究与教学参考之用。
读者将信息用于其他用途的,全部法律及连带责任由读者自行承担,本站不承担任何责任。











评论