吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 1568|回复: 13
上一主题 下一主题
收起左侧

[Android 原创] florida编译教程

[复制链接]
跳转到指定楼层
楼主
justWant404 发表于 2026-7-28 11:12 回帖奖励

在 macOS 上编译去特征版 frida-server(Florida + frida 17.16.4 实战)

本文基于 autorun.top 的 frida-hide 教程 思路,在 macOS 上用 frida 17.16.4 + Florida-17.16.4 跑通全流程。

现状

网上 frida 去特征编译教程不少,但大多数有两个问题:

  1. 版本旧:还在讲 16.x 甚至更早,新版 frida 源码已经动过,照抄的 patch 会失败
  2. 环境单一:默认 Linux,macOS 用户照做会撞 sed、lief 一堆问题,而且报错信息无法明确指示

本文记录的用 macOS arm64 + frida 17.16.4 + Florida-17.16.4 实际编译通过的流程,把每个报错和修法都写清楚。换到更新的版本,核心思路不变,按文末"升级检查清单"调整即可。

背景:Florida 是什么

Florida 是一个自动跟踪 frida 上游、打 patch、构建去特征版 frida-server 的项目。它的 release 只发 patch 文件(不是完整源码),你拿官方 frida 源码 + Florida 的 patch,自己打补丁编译。

环境准备

# macOS arm64,frida 官方仓库,checkout 到 17.16.4 tag
# 需要:git、python3、ninja(fride 自带在 deps/ 里)、meson(fride configure 会拉)
# 额外:lief(去特征脚本依赖)

第一步:拉源码

# 官方 frida(Florida 就跟踪这个,不是 fork)
git clone --recurse-submodules https://github.com/frida/frida
cd frida
git checkout 17.16.4
git submodule update --init --recursive   # 确保子模块对齐到这个 tag

# Florida release(只有 patch)
# 去 https://github.com/Ylarod/Florida/releases 下 17.16.4 的 source.zip,解压到隔壁
# 解压后结构:Florida-17.16.4/patches/frida-core/*.patch + patches/frida-gum/*.patch

关键:Florida 的 patch 是针对它发布那天官方 frida 默认分支 tip 写的(看它的 .github/workflows/build.yml 就是 git clone --recurse-submodules 不 pin commit)。所以你 checkout 到对应 tag 一般能对上,但 release 后上游再改过同一文件,patch 的精确行号就会漂移。

第二步:configure 编译环境

frida 主仓库根目录跑 configure(android-arm64):

./configure --host=android-arm64
# 或者你已有的 build/ 目录已经配好,跳过

这步会下载 frida 的 toolchain(deps/toolchain-macos-arm64/)、生成 build/build.ninja、build/frida-android-arm64.txt。首次比较慢。

第三步:打 patch(核心)

用 git apply --reject 批量应用。它能容错,能落地的落地,冲突的产生 .rej 文件,不会整体中止。

cd /path/to/frida/subprojects/frida-core

# 先清干净
git reset --hard HEAD && git clean -fd

# 批量 apply 10 个 patch
for p in $(ls /path/to/Florida-17.16.4/patches/frida-core/*.patch | sort); do
  git apply --reject --whitespace=fix "$p"
done

判断 patch 链是否自洽,看 patch 里的 new file mode 标记,不要靠单测:

grep -E "new file mode" Florida-17.16.4/patches/frida-core/*.patch
# 会看到 0003 里有: new file mode 100644 (src/anti-anti-frida.py)

跑完 git apply --reject 后,预期产生 2 个 .rej:

  • lib/base/rpc.vala.rej —— 来自 0001,需手解(坑 3)
  • src/windows/windows-host-session.vala.rej —— 来自 0003,直接忽略(坑 4)

0001 patch 改 rpc.vala 3 处:插入 getRpcStr() 方法 + 2 处调用 + 1 处比较。其中第 3 个 hunk 能 apply 成功(把 type != "frida:rpc" 改成 type != getRpcStr(false)),但前 2 个 reject——结果就是第 128 行引用了 getRpcStr 但方法没定义,编译必报错。

失败原因是上游在 17.16.4 release 后又改过 rpc.vala,把 Object (peer: peer) 从第 11 行挪到了第 22 行,行号漂移导致 hunk 对不上。但搜索目标字符串是稳定的,用 python 行级编辑补上:

cd /path/to/frida/subprojects/frida-core
python3 - <<'EOF'
import io
path = "lib/base/rpc.vala"
with io.open(path, "r", encoding="utf-8", newline="") as f: src = f.read()

# 在构造器后插入 getRpcStr 方法
anchor = "\t\t\tObject (peer: peer);\n\t\t}\n"
assert src.count(anchor) == 1, "anchor 没找到,frida-core 改过这块了,看 0001 patch 重新定位"
method = ("\t\t\tpublic string getRpcStr(bool quote){\n"
          "\t\t\t\tstring result = (string) GLib.Base64.decode((string) GLib.Base64.decode(\"Wm5KcFpHRTZjbkJq\"));\n"
          "\t\t\t\tif(quote){\n\t\t\t\t\treturn \"\\\"\" + result + \"\\\"\";\n"
          "\t\t\t\t}else{\n\t\t\t\t\treturn result;\n\t\t\t\t}\n\t\t\t\t}\n")
src = src.replace(anchor, anchor + "\n" + method, 1)

# 替换两处调用
src = src.replace('\t\t\t\t.add_string_value ("frida:rpc")\n',
                  '\t\t\t\t.add_string_value (getRpcStr(false))\n', 1)
src = src.replace('\t\t\tif (json.index_of ("\\"frida:rpc\\"") == -1)\n',
                  '\t\t\tif (json.index_of (getRpcStr(true)) == -1)\n', 1)
with io.open(path, "w", encoding="utf-8", newline="") as f: f.write(src)
print("rpc.vala patched")
EOF

# 验证:4 处 getRpcStr(1 定义 + 3 调用),无 frida:rpc 残留
grep -c getRpcStr lib/base/rpc.vala   # 4
grep '"frida:rpc"' lib/base/rpc.vala  # 应无输出

为什么不用 Edit 工具/手敲:vala 文件是 tab 缩进,Edit 的字符串匹配容易因 tab 数量不对失败。python 行级编辑 + 锚点字符串最稳。别写死行号,升级后行号会变,但搜索字符串稳定。

坑 4:windows-host-session.vala reject —— 直接忽略

0003 把 9 个文件的 frida_agent_main 改 main,其中 Windows 那个因行号漂移 reject。但你只编 android-arm64,根本不编译 Windows 目标。验证:

ls build/subprojects/frida-core/ | grep -i windows  # 无输出 = 不编 Windows

直接删掉这个 .rej 即可,其它 8 个文件(darwin/freebsd/linux/qnx host-session + agent-container + 2 个 test)都已 cleanly apply。

坑 5:embed-agent.py 里路径写错(原教程提过但没说清)

0010 patch 在 src/embed-agent.py 里写死路径调用去特征脚本:

custom_script=str(output_dir)+"/../../../../frida/subprojects/frida-core/src/anti-anti-frida.py"

从 output_dir(build/subprojects/frida-core/src)往上 4 级到 frida 仓库根,再 frida/subprojects/... 多了一级 frida。编译时会报 can't open file ... anti-anti-frida.py(原教程就警告这个,但没说怎么算对)。

正确做法:去掉多余的 frida/,用 python 重新算相对路径:

python3 - <<'EOF'
import io, os
from pathlib import Path
path = "src/embed-agent.py"
with io.open(path, "r", encoding="utf-8", newline="") as f: src = f.read()

# output_dir 的实际值从 build.ninja 里 embed-agent.py 那行 COMMAND 取
# 一般是 <frida>/build/subprojects/frida-core/src
output_dir = Path("/path/to/frida/build/subprojects/frida-core/src")
real_file = Path("/path/to/frida/subprojects/frida-core/src/anti-anti-frida.py")
rel = os.path.relpath(real_file, output_dir)  # 算出 ../../../../subprojects/frida-core/src/anti-anti-frida.py

lines = src.split("\n")
for i, l in enumerate(lines):
    if l.startswith('            custom_script=str(output_dir)+"/'):
        lines[i] = f'            custom_script=str(output_dir)+"/{rel}"'
        break
with io.open(path, "w", encoding="utf-8", newline="") as f: f.write("\n".join(lines))
print(f"path fixed -> {rel}")
EOF

坑 6:anti-anti-frida.py 的 sed -b 在 macOS 失效

脚本用 os.system(f"sed -b -i s/gum-js-loop/{random_name}/g {input_file}") 改 3 个线程名(gum-js-loop/gmain/gdbus)。macOS 的 BSD sed 不认 -b(GNU sed 选项),3 处全报 sed: illegal option -- b,线程名没被替换——但脚本照样打印

  • Patch gum-js-loop to xxx,这个假象让你以为成功了,实际产物里线程名原封不动。

    正确做法:把 3 处 sed 改成 Python 原生字节替换,跨平台可靠:

    python3 - <<'EOF'
    import io
    path = "src/anti-anti-frida.py"
    with io.open(path, "r", encoding="utf-8", newline="") as f: src = f.read()
    
    # 加辅助函数
    anchor = "import sys\nimport random\nimport os\n"
    assert src.count(anchor) == 1
    helper = anchor + "\n\ndef _patch_bytes(path, old: bytes, new: bytes):\n    with open(path, \"rb\") as f:\n        data = f.read()\n    data = data.replace(old, new)\n    with open(path, \"wb\") as f:\n        f.write(data)\n"
    src = src.replace(anchor, helper, 1)
    
    # 替换 3 处 sed
    for name in ["gum-js-loop", "gmain", "gdbus"]:
        old = f'    os.system(f"sed -b -i s/{name}/{{random_name}}/g {{input_file}}")\n'
        new = f'    _patch_bytes(input_file, b"{name}", random_name.encode())\n'
        assert src.count(old) == 1, f"{name} 那行没找到,脚本改过了?"
        src = src.replace(old, new, 1)
    
    with io.open(path, "w", encoding="utf-8", newline="") as f: f.write(src)
    print("sed -> python done")
    EOF

    坑 7:frida-gum 的 ggbond 是已知特征

    frida-gum 的 patch 把进程名改成 "ggbond"——这串本身已是公开已知特征(原教程作者特意提醒过)。apply 后再改成随机串:

    cd /path/to/frida/subprojects/frida-gum
    git apply --reject /path/to/Florida-17.16.4/patches/frida-gum/0001-Florida-pool-frida.patch
    
    # 生成随机串改掉 ggbond
    NEWNAME=$(LC_ALL=C tr -dc 'a-zA-Z' < /dev/urandom | head -c 7)
    python3 - "$NEWNAME" <<'EOF'
    import sys, io
    path = "gum/gum.c"
    with io.open(path, "r", encoding="utf-8", newline="") as f: src = f.read()
    old = '  g_set_prgname ("ggbond");\n'
    new = f'  g_set_prgname ("{sys.argv[1]}");\n'
    assert src.count(old) == 1
    with io.open(path, "w", encoding="utf-8", newline="") as f: f.write(src.replace(old, new, 1))
    print(f"ggbond -> {sys.argv[1]}")
    EOF

    注意这个进程名是编译时固定的,不是运行时随机。每次编译换一个新的。

    清理 .rej,准备编译

    cd /path/to/frida/subprojects/frida-core
    find . -name "*.rej" -delete   # rpc.vala.rej 已手解,windows 的可忽略

    第四步:装 lief(去特征脚本依赖)

    这是 macOS 上最容易漏的一步。anti-anti-frida.py 用 lief 解析 ELF 改符号,但编译用的 python 没装的话,脚本 4 次报 No module named 'lief',去特征等于没做,产物带着原始 frida 符号——而且编译不会因此失败(脚本失败不影响 ninja 继续链接),你不查根本发现不了。

    先确认编译用的是哪个 python(从 build.ninja 看),再给那个 python 装:

    # 找编译用的 python
    PYBUILD=$(grep -o "/[^ ]*/python3" /path/to/frida/build/build.ninja | head -1)
    echo "编译用 python: $PYBUILD"
    
    # 装 lief
    $PYBUILD -m pip install lief
    
    # 验证
    $PYBUILD -c "import lief; print(lief.__version__)"

    别装到系统默认 python 上——ninja 调的是 build.ninja 里写死的那个 python,装错地方等于没装。

    第五步:编译

    cd /path/to/frida
    make    # 首次约 5-15 分钟,编 vala/C/Go

    坑 8(重编译场景):ninja 不会自动重跑去特征

    如果你之前已经编译过(产物已存在),改了 patch 重来时,光跑 make ninja 会说 "no work to do"——它不知道 anti-anti-frida.py 改过,也不会重跑 embed-agent 处理已有的 agent so。要强制重生成:

    cd /path/to/frida/build
    # 清掉 embed-agent 的产物,强制重跑
    ninja -t clean subprojects/frida-core/src/frida-data-agent-blob.S
    ninja subprojects/frida-core/src/frida-data-agent-blob.S
    # 重新链接
    ninja subprojects/frida-core/server/frida-server subprojects/frida-core/inject/frida-inject

    跑这步时控制台应该看到去特征脚本的彩色输出:

  • Patch frida-agent: .../frida-agent-64.so
  • Patch `frida` to `XuKbq`
  • Patching section name=.rodata offset=0x... orig:FridaScriptEngine new:enignEtpircSadirF
  • Patch `gum-js-loop` to `ZdsHJXzQnlC`
  • Patch `gmain` to `eAmEY`
  • Patch `gdbus` to `lOkch`
  • Patch Finish
  • 看到 4 个 anti-anti-frida finished 才算成功(64/32 是有效 ELF 会处理;arm64/arm 在只编 64 位 host 时是空文件,会打印 Not elf, exit,正常)。

    第六步:对 frida-server 本体也跑一遍去特征

    ninja 的 embed-agent 只处理 agent so(嵌进 blob 的那个)。但最终的 frida-server 本体链接了 glib,自带 gmain/gdbus 等线程名,这部分没被处理。要做到彻底,手动对 frida-server 再跑一次:

    cd /path/to/frida
    $PYBUILD subprojects/frida-core/src/anti-anti-frida.py build/subprojects/frida-core/server/frida-server

    这步不在 ninja 构建图里,每次重新编译后都要手动跑一次,否则 frida-server 会被覆盖回带特征版本。

    第七步:验证产物

    SRV=build/subprojects/frida-core/server/frida-server
    
    # 文件类型:ELF ARM aarch64, stripped
    file "$SRV"
    
    # 无 frida 导出符号
    nm -D "$SRV" | grep -i frida          # 应无输出
    
    # 无三个线程名
    strings "$SRV" | grep -x "gum-js-loop\|gmain\|gdbus"   # 应无输出
    
    # 无关键特征串(被反转了)
    strings "$SRV" | grep -E "FridaScriptEngine|GumScript|frida_agent_main"  # 应无输出

    全部无输出 = 去特征生效。

    产物怎么用

    # push 到手机
    adb push build/subprojects/frida-core/server/frida-server /data/local/tmp/frida-server
    adb shell "chmod 755 /data/local/tmp/frida-server"
    adb shell "su -c '/data/local/tmp/frida-server &'"
    
    # 电脑端连(用同名改名后的 frida 工具,或直接 frida -U)
    frida -U -n com.target.app -s hook.js

    frida-inject 是一次性注入工具(不常驻),适合自动化场景:

    adb push build/subprojects/frida-core/inject/frida-inject /data/local/tmp/
    adb shell "/data/local/tmp/frida-inject -n com.target.app -s hook.js"

    踩坑总结表

    # 坑 现象 根因 修法
    1 目录错 git am 报 not a git repo 教程写的 build/subprojects/ 是产物目录 用 subprojects/(git 子模块)
    2 git am 不容错 行号漂移就整体失败 git am/--3way 对 base sha1 缺失零容忍 用 git apply --reject
    — 假象 以为 anti-anti-frida.py 缺失 --check 单测制造 看 new file mode 标记
    3 rpc.vala reject 编译报 getRpcStr 未定义 0001 前 2 个 hunk 行号漂移 python 行级编辑补 3 处
    4 windows reject 0003 1 个 hunk 失败 行号漂移 跳过(不编 Windows)
    5 路径错 编译报找不到 anti-anti-frida.py 0010 多写一级 frida/ 重新算相对路径
    6 sed -b 失效 线程名没换(但脚本假装成功) macOS BSD sed 不认 -b 改 Python 字节替换
    7 ggbond 是特征 进程名是已知串 patch 写死 改随机串
    8 lief 没装 去特征脚本全失败但编译照过 编译 python 没装 lief pip install lief 到编译 python
    — 重编译不跑去特征 ninja "no work to do" 构建图不含去特征 ninja -t clean 强制重生成

    升级到新版本时的检查清单

    1. frida 版本对齐:主仓库 checkout 到新 tag,git submodule status 确认子模块对齐
    2. Florida 版本对齐:下对应版本 release,确认 patch 数量/名称没变
    3. 坑 3 复发风险高:rpc.vala 是高频改动文件,重新看 0001 patch 的 hunk,确认搜索字符串(Object (peer: peer)、.add_string_value ("frida:rpc") 等)还在,不在就重新定位
    4. 坑 5 复发:目录结构变了重新算 output_dir → anti-anti-frida.py 的相对路径
    5. 坑 8 复发:确认编译用 python 没换,重装 lief
    6. 新 patch:Florida 可能加新 patch,重新跑 git apply --reject 看 reject 情况
    7. lief API 兼容:如果 anti-anti-frida.py 跑报 AttributeError,检查 lief 版本 API 是否又改了(0.x → 1.0 改过一次)

    参考链接


    本文基于 frida 17.16.4 + Florida-17.16.4 在 macOS arm64 实测通过。

  • 免费评分

    参与人数 1吾爱币 +1 收起 理由
    HackXK + 1 用心讨论,共获提升!

    查看全部评分

    发帖前要善用【论坛搜索】功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

    来自 #
     楼主| justWant404 发表于 2026-8-1 14:13 |楼主
    server我传到github上了,不想编译的直接下载哈
    https://github.com/SimpsonGet/florida-server-builds

    免费评分

    参与人数 1吾爱币 +1 热心值 +1 收起 理由
    huluwa123 + 1 + 1 热心回复!

    查看全部评分

    沙发
    suixin1230 发表于 2026-7-28 18:34
    3#
    ShriyGo 发表于 2026-7-28 22:27
    好东西。我之前用hluda,能过一部分检测。不过这种编译的应该还是过不了libmsaoaidsec.so
    4#
    huluwa123 发表于 2026-7-29 10:25
    没有mac 有别的办法吗 大佬
    5#
    盛世美颜贾队长 发表于 2026-7-29 10:29
    佛罗里达都给我干出来了
    6#
     楼主| justWant404 发表于 2026-7-29 12:26 |楼主
    huluwa123 发表于 2026-7-29 10:25
    没有mac 有别的办法吗 大佬

    本质是一样的,你把这个过程给 ai 他应该就能顺利编译了
    7#
    Hoison 发表于 2026-7-29 14:06
    下载论坛附件
    8#
    u133asdnihaoa 发表于 2026-7-29 15:02
    很实用,学习了
    9#
    huluwa123 发表于 2026-7-29 19:17
    justWant404 发表于 2026-7-29 12:26
    本质是一样的,你把这个过程给 ai 他应该就能顺利编译了

    谢谢大佬指点
    10#
    johnfung 发表于 2026-7-29 19:26
    不错不错,非常感谢大佬的指导
    您需要登录后才可以回帖 登录 | 注册[Register]

    本版积分规则

    返回列表

    RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - 52pojie.cn ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

    GMT+8, 2026-10-13 02:25

    Powered by Discuz!

    Copyright © 2001-2020, Tencent Cloud.

    快速回复 返回顶部 返回列表