吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 265|回复: 1
上一主题 下一主题
收起左侧

[Android 原创] [AI-generated]某企业加固加载Frida流程

[复制链接]
跳转到指定楼层
楼主
Pueritia 发表于 2026-11-2 20:10 回帖奖励

某企业加固加载Frida流程

本教程流程由AI全程完成,教程由AI生成。
如有侵权,联系删除。


1. 环境

设备        ROOT真机
系统        Android 10
架构        arm64-v8a
加固        某企业加固(libjiagu_***_**.so / libjgdtc.so / assets/.jgapp)
工具链      frida 16.7.19
            adb

为什么必须真机:雷电 / MuMu 上跑的是 houdini(ARM→x86 翻译层),Process.arch 报 ia32,
native 层 hook 与 Frida 的 Java bridge 都会失配。改 so 字符串、改翻译库名、关 root、伪装 cpuinfo
全部无效——判定依据是"原生桥环境本身",绕不过去。


目标:把 Frida 装进目标进程

2.1 现象:attach 不上

frida -H 127.0.0.1:27099 -n com.***.app
→ Failed to attach: unable to access process with pid XXXX

而 ps 里进程活得好好的。查 /proc/<pid>/status:

TracerPid:  15086      ← 被别人 trace 着

Linux 规定一个进程同时只能有一个 tracer,所以 Frida 挂不上去。

2.2 守护进程的真实启动顺序(实测纠正)

最初的判断是"主进程与守护进程互相 ATTACH",方向对、机制错。
用 fork 钩子抓到真实顺序:

① 主进程 fork() 出守护进程
② 守护进程调用 ptrace(PTRACE_TRACEME)
   → 内核把「父进程」设为它的 tracer
   → 于是 守护.TracerPid = 主进程
③ 守护进程再调用 ptrace(PTRACE_ATTACH, 主进程)
   → 于是 主.TracerPid = 守护的某个线程

推论很关键:ATTACH 是守护进程发出的。所以只注入主进程去 hook ptrace,
永远看不到那次 ATTACH——这就是早期"伪造 EXITKILL 从没被调用"的真正原因。

时序上,这 4 次 fork 与 42 次 TRACEME 自检全部发生在 StubApp.attachBaseContext 阶段,
即 ***Application.onCreate 之前,调用方都在 libjiagu_***_**.so 的代码段。

2.3 五条失败路径(都实测过)

尝试 结果 原因
拦掉所有 fork 主进程 TracerPid=0、Java 可用,但 5–8 秒后 SIGSEGV 壳看门狗拿不到守护握手,判死自杀
只拦前 4 次 fork 第 5 次成功 → 守护建立 → 主进程被杀 fork 次数不固定
按调用栈只拦"壳发起"的 fork 仍放行了 1 个 → 被杀 栈回溯判断不准
放行 fork 但立刻 kill 子进程 主进程同时死 PTRACE_O_EXITKILL 绑死
把 TRACEME 返回值改成 0 2 秒内被杀 壳拿它与 TracerPid 交叉验证,改了就是自曝

结论:ptrace 的 TRACEME 一个字都不能碰,fork 也不能拦。
唯一可行的是——让守护进程正常存在,但让它挂不上主进程。

2.4 方案:把 ATTACH 伪造成"成功"

2.4.1 可行性判定

先读 libc.ptrace 入口的机器码,确认能不能做 inline patch:

sub  sp, sp, #0x30        ← 标准函数序言
str  x19, [sp, #0x10]
stp  x20, x21, [sp, #0x20]
stp  x29, x30, [sp, #0x30]

四条指令都不涉及 PC 相对寻址,覆盖 16 字节是安全的,不需要指令重定位。

2.4.2 stub 设计

核心约束:这个补丁必须在 fork 之前装好,好让守护进程继承。
而 fork 出的子进程没有 JS 线程,所以 stub 绝对不能回调 JS——
只能用纯 ARM64 机器码。

逻辑:

if (request == PTRACE_ATTACH      // 16
 || request == PTRACE_SEIZE       // 0x4206
 || request == PTRACE_SETOPTIONS) // 0x4204
      return 0;                   // 假装成功
else
      执行原序言 4 条 → 跳回 ptrace+16   // 其余请求原样透传

TRACEME(0) 故意不在列表里——它是壳的交叉验证锚点。

布局(72 字节):

+0   cmp  x0, #0x10
+4   beq  +64
+8   movz w4, #0x4206
+12  cmp  x0, x4
+16  beq  +64
+20  movz w4, #0x4204
+24  cmp  x0, x4
+28  beq  +64
+32  <原 prologue 4 条>
+48  ldr  x16, #8
+52  br   x16
+56  .quad ptrace+16
+64  mov  x0, #0
+68  ret

入口改写为 16 字节跳板:

ldr x16, #8
br  x16
.quad <stub>

2.4.3 安装三步

// ① 申请 RWX 页(关键:不能用 Memory.alloc)
var mmap = new NativeFunction(Module.findExportByName('libc.so', 'mmap'),
    'pointer', ['pointer','size_t','int','int','int','int64']);
var page = mmap(ptr(0), 4096, 7 /*RWX*/, 0x22 /*MAP_PRIVATE|MAP_ANON*/, -1, 0);

// ② 写 stub(此刻 ptrace 还没被改,可以直接调用自检)
...

// ③ 给入口打跳板
Memory.patchCode(pt, 16, function (code) {
    code.add(0).writeU32(0x58000050);   // ldr x16, #8
    code.add(4).writeU32(0xD61F0200);   // br x16
    code.add(8).writePointer(page);
});

2.4.4 自检与实机结果

stub 写好后先直接调用(此时 ptrace 还没打补丁),再打完补丁经入口调用,两次都要对:

SELFTEST  attach=0  detach=-1     ← 直接调 stub
LIVE      attach=0  detach=-1     ← 经 ptrace 入口

实机效果:

[  337ms] attached pid=7195
[  350ms] ptrace patched
[ 4327ms] procs=[(7195, 619), (7267, 7195)]  tracer=0
          JAVA_READY ver=10
          MainActivity → SplashActivity → MainTabActivity
[42533ms] t+30s  tracer=0  OK

守护进程 7267 正常存在,主进程 TracerPid=0,Java bridge 可用,30 秒以上稳定,可随时 attach/detach,无需重启。

2.5 三个隐蔽的坑

① Memory.patchCode 的 code 指针不会自动偏移。
两次 writeU32 都落在 offset 0,把入口前 8 字节写成了指针值。反汇编出来是 ldr s0; udf #0x76,
现象是"一调用就 SIGILL"。必须显式 code.add(0) / add(4) / add(8)。

② 用 Memory.alloc + patchCode 写 stub 会 SIGILL。
patchCode 用完会恢复该页原本的保护属性——堆页是 RW,恢复后就没有执行权限了。
必须 mmap 一块 RWX。

③ ARM64 指令缓存不保证一致。
裸写内存后 CPU 可能执行到旧指令。用 Memory.patchCode 写入(它负责 flush i-cache),
不要用 ptr.writeU32 直接怼。

2.6 标准加载流程

方式 A:冷启动 + 抢注(进程还没起来时)

adb shell "nohup /data/local/tmp/aaanew -P -l 127.0.0.1:27099 >/dev/null 2>&1 &"
adb forward tcp:27099 tcp:27099

python analysis/***946/frida_946_stable.py 300

内部顺序:am force-stop → am start → 轮询 pidof(约 +330ms 抢到)→ attach
→ 灌 frida_agent39_ptrace.js 打补丁 → 等 MainTabActivity 稳定 → 灌业务探针。

注意:aaanew 是重命名后的 frida-server。

方式 B:attach 已在运行的进程(推荐,不打断用户操作)

先看 TracerPid:

P=$(adb shell pidof com.******.app | tr -d '\r')
adb shell "grep TracerPid /proc/$P/status"
  • TracerPid: 0 → 直接 attach,无需补丁
  • TracerPid: 非0 → 说明守护已挂上,需要走方式 A 冷启动重来(或对当前进程补打补丁)
python analysis/***946/load_on_pid.py auto 你的脚本.js 60

免费评分

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

查看全部评分

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

沙发
yeyeyeaaa 发表于 2026-11-3 19:44
感谢大佬,有用,学习一手
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

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

GMT+8, 2026-11-4 04:02

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

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