目录

前言 1.1

Stalker概览 1.2

Stalker介绍 1.3

用法 1.3.1

API接口 1.3.2

Stalker举例 1.4

___lldb_unnamed_symbol2575$$akd 1.4.1

libInFieldCollection.dylib的vsPHbdGf 1.4.2

libmetasec_ml.so的ms_bd_c_l_a 1.4.3

调试loginWithPhoneNbr函数 1.4.4

某小说App的Stalker用法 1.4.5

misc/frida-stalker-example.py 1.4.6

Stalker心得 1.5

Stalker.follow 1.5.1

Stalker的利用方式 1.5.1.1

events的属性含义 1.5.1.2

transform的逻辑 1.5.1.3

context的属性和含义 1.5.1.4

Instruction的属性 1.5.1.5

Stalker.follow()的内部实现原理 1.5.1.6

Stalker中函数地址和指令地址匹配不上 1.5.1.7

16字节之前的开始那段代码无法调试 1.5.1.8

实际内存地址和Stalker输出地址不匹配不一致 1.5.1.9

Stalker中去判断是否是函数的代码指令的逻辑 1.5.1.10

Stalker中优化hook到指令时的log显示 1.5.1.11

putCallout中传递有名的独立函数会导致崩溃 1.5.1.12

Stalker.exclude 1.5.2

用Stalker.exclude提高效率和减少干扰 1.5.2.1

Stalker工具类函数 1.6

stalkerHookUnnameNative 1.6.1

附录 1.7

参考资料 1.7.1

前言

Frida高级调试：Stalker

最新版本：1.1.0

更新时间：20250822

简介

介绍Frida高级调试中的Stalker的详细用法和技巧，包括各种举例和心得。先是概述Frida的Stalker，然后是介绍其基本用法和API接口；然后给出多个Stalker的详细实例举例，包括完整的代码和输出日志以及相关说明；然后整理出Stalker.follow的相关心得，包括如何利用Staker，events的属性含义，transform的基本逻辑，context有哪些属性，Stalker.follow()的内部实现机制原理，为何函数地址和指令地址不匹配等等；然后介绍用Stalker.exclude提高效率和减少干扰；然后贴出Stalker的工具类函数，尤其是stalkerHookUnnameNative等。最后给出附录和参考资料。

源码+浏览+下载

本书的各种源码、在线浏览地址、多种格式文件下载如下：

HonKit源码

crifan/frida_advanced_debug_stalker: Frida高级调试：Stalker

如何使用此HonKit源码去生成发布为电子书

详见：crifan/honkit_template: demo how to use crifan honkit template and demo

在线浏览

Frida高级调试：Stalker book.crifan.org

Frida高级调试：Stalker crifan.github.io

离线下载阅读

Frida高级调试：Stalker PDF

Frida高级调试：Stalker ePub

Frida高级调试：Stalker Mobi

版权和用途说明

此电子书教程的全部内容，如无特别说明，均为本人原创。其中部分内容参考自网络，均已备注了出处。如发现有侵权，请通过邮箱联系我 admin 艾特 crifan.com，我会尽快删除。谢谢合作。

各种技术类教程，仅作为学习和研究使用。请勿用于任何非法用途。如有非法用途，均与本人无关。

鸣谢

感谢我的老婆陈雪的包容理解和悉心照料，才使得我crifan有更多精力去专注技术专研和整理归纳出这些电子书和技术教程，特此鸣谢。

其他

作者的其他电子书

本人crifan还写了其他150+本电子书教程，感兴趣可移步至：

crifan/crifan_ebook_readme: Crifan的电子书的使用说明

关于作者

关于作者更多介绍，详见：

关于CrifanLi李茂 – 在路上

crifan.org，使用署名4.0国际(CC BY 4.0)协议发布 all right reserved，powered by Gitbook最后更新： 2025-08-22 22:01:28

Stalker概览

Stalker概览

Frida的Stalker

名称

别称：frida-stalker

笔者译为：Frida代码跟踪器

作用：汇编指令级别的hook

用途：追踪真实代码指令的执行过程

官网文档

Stalker介绍

Stalker的API接口

Stalker单词的含义

Stalk的英文原意：

n.（植物的）茎，秆；（动物的）肉柄，肉茎；柄；（车辆）（转向柱上控制指示仪、灯光等的）手柄；悄悄追踪；高视阔步

v. 偷偷接近，潜近；跟踪，盯梢；怒冲冲地走，趾高气扬地走；令人厌恶地穿过，威胁地通过；<文>（不好的气氛）笼罩，蔓延

Frida中的Stalker的含义

Stalk英文原意：跟踪

Stalker英文原意：跟踪者

有人（把Frida的Stalker）翻译成：潜行者

何时需要用到Frida的Stalker？

如下场景：

你想要搞懂该函数内部的执行的逻辑，想要查看哪个函数，甚至是哪个代码块codeblock，被执行了

还比如你想要搞懂，当传入不同参数时，函数内部代码执行的流程路径，是否有何不同

就可以去用：

Stalker.follow()

crifan.org，使用署名4.0国际(CC BY 4.0)协议发布 all right reserved，powered by Gitbook最后更新： 2025-06-04 11:30:51

Stalker介绍

Stalker介绍

此处详细介绍Frida的Stalker相关内容：

crifan.org，使用署名4.0国际(CC BY 4.0)协议发布 all right reserved，powered by Gitbook最后更新： 2025-06-03 23:04:07

用法

Stalker的用法

Stalker的用法的概述

核心逻辑

在frida命令上，和普通frida一样，都是调用js

frida -U -n akd -l ./fridaStalker_akdSymbol2575.js

frida -U -p 1234 -l yourFridaScript.js

frida -U -f com.apple.Preferences -l yourFridaScript.js

js内部逻辑

最初要初始化：计算出当前要hook的函数所属的模块和地址

在普通的Interceptor.attach的onEnter中，加上Stalker.follow

在transform中，计算是否是原始函数的代码

如果是，再去：实现特定的调试的目的

打印真实执行的指令的信息instruction.toString()

打印当时的变量的值context

等等

crifan.org，使用署名4.0国际(CC BY 4.0)协议发布 all right reserved，powered by Gitbook最后更新： 2025-06-04 10:44:43

API接口

Stalker的API接口

Stalker的API接口

接口形式

普通用户常直接调用：JS的API

Stalker - JavaScript API | Frida

内部接口：Gum接口

TypeScript type definitions

DefinitelyTyped/index.d.ts

接口内容

最核心接口

Stalker.follow([threadId, options])

常用接口

Stalker.exclude(range)

Stalker.parse(events[, options])

Stalker.unfollow([threadId])

其他

Stalker.flush()

Stalker.garbageCollect()

Stalker.invalidate(address)

Stalker.invalidate(threadId, address)

Stalker.addCallProbe(address, callback[, data])

Stalker.removeCallProbe

Stalker.trustThreshold

Stalker.queueCapacity

Stalker.queueDrainInterval

crifan.org，使用署名4.0国际(CC BY 4.0)协议发布 all right reserved，powered by Gitbook最后更新： 2025-06-04 12:07:05

Stalker举例

Stalker举例

下面去给出众多Frida的Stalker的真实使用案例以及调试结果以及相关说明。

crifan.org，使用署名4.0国际(CC BY 4.0)协议发布 all right reserved，powered by Gitbook最后更新： 2025-06-04 11:31:37

___lldb_unnamed_symbol2575$$akd

___lldb_unnamed_symbol2575$$akd

用Frida的Stalker调试arm64的akd函数___lldb_unnamed_symbol2575$$akd：

Frida命令

frida -U -n akd -l ./fridaStalker_akdSymbol2575.js

js文件fridaStalker_akdSymbol2575.js的内容

console.log("===== Frida Stalker hook for arm64 ___lldb_unnamed_symbol2575$$akd =====");
// arm64 akd: ___lldb_unnamed_symbol2575$$akd
// var funcRelativeStartAddr = 0x1000a0460;
var funcRelativeStartAddr = 0xa0460;
var functionSize = 0x24C8; // 9416 == 0x24C8
var funcRelativeEndAddr = funcRelativeStartAddr + functionSize;
console.log("funcRelativeStartAddr=" + funcRelativeStartAddr + ", functionSize=" + functionSize + ", funcRelativeEndAddr=" + funcRelativeEndAddr);
const moduleName = "akd";
const moduleBaseAddress = Module.findBaseAddress(moduleName);
console.log("moduleName=" + moduleName + ", moduleBaseAddress=" + moduleBaseAddress);
// console.log("moduleName=%s, moduleBaseAddress=%p", moduleName, moduleBaseAddress);
const funcRealStartAddr = moduleBaseAddress.add(funcRelativeStartAddr);
// var funcRealEndAddr = funcRealStartAddr + functionSize;
const funcRealEndAddr = funcRealStartAddr.add(functionSize);
console.log("funcRealStartAddr=" + funcRealStartAddr + ", funcRealEndAddr=" + funcRealEndAddr);
var curTid = null;
Interceptor.attach(funcRealStartAddr, {
    onEnter: function(args) {
        var arg0 = args[0]
        var arg1 = args[1]
        var arg2 = args[2]
        var arg3 = args[3]
        console.log("----- arg0=" + arg0 + ", arg1=" + arg1 + ", arg2=" + arg2 + ", arg3=" + arg3);
        var curTid = Process.getCurrentThreadId();
        console.log("curTid=", curTid);
        Stalker.follow(curTid, {
            events: {
                call: false, // CALL instructions: yes please
                ret: true, // RET instructions
                exec: false, // all instructions: not recommended as it's
                block: false, // block executed: coarse execution trace
                compile: false // block compiled: useful for coverage
            },
            // onReceive: Called with `events` containing a binary blob comprised of one or more GumEvent structs. See `gumevent.h` for details about the format. Use `Stalker.parse()` to examine the data.
            onReceive(events) {
                var parsedEvents = Stalker.parse(events)
                // var parsedEventsStr = JSON.stringify(parsedEventsStr)
                // console.log(">>> into onReceive: parsedEvents=" + parsedEvents + ", parsedEventsStr=" + parsedEventsStr);
                console.log(">>> into onReceive: parsedEvents=" + parsedEvents);
            },

            // transform: (iterator: StalkerArm64Iterator) => {
            transform: function (iterator) {
                // console.log("iterator=" + iterator);
                var instruction = iterator.next();
                const startAddress = instruction.address;
                // console.log("+++ into iterator: startAddress=" + startAddress);
                // const isAppCode = startAddress.compare(funcRealStartAddr) >= 0 && startAddress.compare(funcRealEndAddr) === -1;
                // const isAppCode = (startAddress.compare(funcRealStartAddr) >= 0) && (startAddress.compare(funcRealEndAddr) < 0);
                const gt_realStartAddr = startAddress.compare(funcRealStartAddr) >= 0
                const lt_realEndAddr = startAddress.compare(funcRealEndAddr) < 0
                var isAppCode = gt_realStartAddr && lt_realEndAddr
                console.log("+++ into iterator: startAddress=" + startAddress + ", isAppCode=" + isAppCode);

                // // for debug
                // isAppCode = true

                // console.log("isAppCode=" + isAppCode + ", gt_realStartAddr=" + gt_realStartAddr + ", lt_realEndAddr=" + lt_realEndAddr);
                do {
                    if (isAppCode) {
                        // is origal function code = which we focus on

                        // console.log("instruction: address=" + instruction.address
                        //     + ",next=" + instruction.next()
                        //     + ",size=" + instruction.size
                        //     + ",mnemonic=" + instruction.mnemonic
                        //     + ",opStr=" + instruction.opStr
                        //     + ",operands=" + JSON.stringify(instruction.operands)
                        //     + ",regsAccessed=" + JSON.stringify(instruction.regsAccessed)
                        //     + ",regsRead=" + JSON.stringify(instruction.regsRead)
                        //     + ",regsWritten=" + JSON.stringify(instruction.regsWritten)
                        //     + ",groups=" + JSON.stringify(instruction.groups)
                        //     + ",toString()=" + instruction.toString()
                        //     + ",toJSON()=" + instruction.toJSON()
                        // );

                        var curRealAddr = instruction.address;
                        // const isAppCode = curRealAddr.compare(funcRealStartAddr) >= 0 && curRealAddr.compare(funcRealEndAddr) === -1;
                        // console.log(curRealAddr + ": isAppCode=" + isAppCode);
                        var curOffsetHexPtr = curRealAddr.sub(funcRealStartAddr)
                        var curOffsetInt = curOffsetHexPtr.toInt32()

                        // var instructionStr = instruction.mnemonic + " " + instruction.opStr
                        var instructionStr = instruction.toString()
                        // console.log("\t" + curRealAddr + ": " + instructionStr);
                        // console.log("\t" + curRealAddr + " <+" + curOffsetHexPtr + ">: " + instructionStr);
                        console.log("\t" + curRealAddr + " <+" + curOffsetInt + ">: " + instructionStr);
                        if (curOffsetInt == 8516) {
                            console.log("curOffsetInt=" + curOffsetInt);
                            // iterator.putCallout(needDebug);
                            iterator.putCallout((context) => {
                                var contextStr = JSON.stringify(context)
                                console.log("contextStr=" + contextStr);
                                var x9Value1 = context.x9
                                var x9Value2 = context["x9"]
                                console.log("x9Value1=" + x9Value1 + ", x9Value2=" + x9Value2)
                            });
                        }
                    }
                    iterator.keep();
                } while ((instruction = iterator.next()) !== null);
            }
        });

        // function needDebug(context) {
        //     console.log("into needDebug");
        //     // console.log("into needDebug: context=" + context);
        //     // var contextStr = JSON.stringify(context, null, 2)
        //     // console.log("context=" + contextStr);
        //     // var x9Value1 = context.x9
        //     // var x9Value2 = context["x9"]
        //     // console.log("x9Value1=" + x9Value1 + ", x9Value2=" + x9Value2)
        // }
    },
    onLeave: function(retval) {
        console.log("retval=", new ObjC.Object(retval))
        if (curTid != null) {
            Stalker.unfollow(curTid);
            console.log("Stalker.unfollow curTid=", curTid)
        }
    }
});

调试期间

期间某次调试，以及优化代码逻辑时的调试效果：

...
instruction str=ldp x22, x21, [sp, #0xb0]
0x18134bb70: ldp x24, x23, [sp, #0xa0]
instruction str=ldp x24, x23, [sp, #0xa0]
0x18134bb70: ldp x26, x25, [sp, #0x90]
instruction str=ldp x26, x25, [sp, #0x90]
0x18134bb70: ldp x28, x27, [sp, #0x80]
instruction str=ldp x28, x27, [sp, #0x80]
0x18134bb70: add sp, sp, #0xe0
instruction str=add sp, sp, #0xe0
0x18134bb70: ret
instruction str=ret
iterator=[object Object]
0x1db012f38: instruction=ldr x1, [x22]
0x1db012f38: ldr x1, [x22]
instruction str=ldr x1, [x22]
0x1db012f38: ldr w2, [x21]
instruction str=ldr w2, [x21]
0x1db012f38: mov w0, #0x100
instruction str=mov w0, #0x100
0x1db012f38: b #0x1db012f7c
instruction str=b #0x1db012f7c
iterator=[object Object]
0x1db012f7c: instruction=mov w3, #0
0x1db012f7c: mov w3, #0
instruction str=mov w3, #0
0x1db012f7c: bl #0x1db0202cc
instruction str=bl #0x1db0202cc
iterator=[object Object]
0x1db0202cc: instruction=adrp x16, #0x1babe5000
0x1db0202cc: adrp x16, #0x1babe5000
instruction str=adrp x16, #0x1babe5000
0x1db0202cc: add x16, x16, #0x124
instruction str=add x16, x16, #0x124
0x1db0202cc: br x16
instruction str=br x16
iterator=[object Object]
0x1babe5124: instruction=mov x16, #0x170
0x1babe5124: mov x16, #0x170
instruction str=mov x16, #0x170
0x1babe5124: svc #0x80
instruction str=svc #0x80
0x1babe5124: b.lo #0x1babe5148
instruction str=b.lo #0x1babe5148
[iPhone::PID::8229 ]->

最终输出

最开始输出环境初始化信息：

===== Frida Stalker hook for arm64 ___lldb_unnamed_symbol2575$$akd =====
funcRelativeStartAddr=656480, functionSize=9416, funcRelativeEndAddr=665896
moduleName=akd, moduleBaseAddress=0x1040e4000
funcRealStartAddr=0x104184460, funcRealEndAddr=0x104186928
[iPhone::akd ]-> ----- arg0=0xfffffffffffffffe, arg1=0x16bf46838, arg2=0x16bf46838, arg3=0xfffffffffffffffe
curTid= 9739

（如果开启调试：

// for debug
isAppCode = true

则会输出）

（最初是）一些非原始函数代码：

+++ into iterator: startAddress=0x106d0bcd8, isAppCode=false
    0x106d0bcd8 <+45643896>: b #0x106d0bce8
+++ into iterator: startAddress=0x106d0bce8, isAppCode=false
    0x106d0bce8 <+45643912>: str wzr, [x19, #0x90]
    0x106d0bcec <+45643916>: ldr x0, [x19, #0xa0]
    0x106d0bcf0 <+45643920>: str xzr, [x19, #0xa0]
    0x106d0bcf4 <+45643924>: cbz x0, #0x106d0bcfc
+++ into iterator: startAddress=0x106d0bcf8, isAppCode=false
    0x106d0bcf8 <+45643928>: bl #0x106c0fef8
+++ into iterator: startAddress=0x106d0bcfc, isAppCode=false
    0x106d0bcfc <+45643932>: ldr x0, [x19, #0x98]
    0x106d0bd00 <+45643936>: str xzr, [x19, #0x98]
    0x106d0bd04 <+45643940>: cbz x0, #0x106d0bd14
+++ into iterator: startAddress=0x106d0bd08, isAppCode=false
    0x106d0bd08 <+45643944>: ldp x29, x30, [sp, #0x10]
    0x106d0bd0c <+45643948>: ldp x20, x19, [sp], #0x20
    0x106d0bd10 <+45643952>: b #0x106c0fef8
+++ into iterator: startAddress=0x106c0fef8, isAppCode=false
    0x106c0fef8 <+44612248>: stp x24, x23, [sp, #-0x40]!
    0x106c0fefc <+44612252>: stp x22, x21, [sp, #0x10]
    0x106c0ff00 <+44612256>: stp x20, x19, [sp, #0x20]
    0x106c0ff04 <+44612260>: stp x29, x30, [sp, #0x30]
    0x106c0ff08 <+44612264>: add x29, sp, #0x30
    0x106c0ff0c <+44612268>: mov x19, x0
    0x106c0ff10 <+44612272>: add x23, x0, #8
    0x106c0ff14 <+44612276>: add x20, x0, #0x10
    0x106c0ff18 <+44612280>: adrp x22, #0x107d28000
    0x106c0ff1c <+44612284>: adrp x21, #0x107d28000
    0x106c0ff20 <+44612288>: add x21, x21, #0x790
    0x106c0ff24 <+44612292>: ldar w24, [x23]
    0x106c0ff28 <+44612296>: cmp w24, #2
    0x106c0ff2c <+44612300>: b.lt #0x106c0ff50
+++ into iterator: startAddress=0x106c0ff30, isAppCode=false
    0x106c0ff30 <+44612304>: bl #0x106c12110
+++ into iterator: startAddress=0x106c0ff34, isAppCode=false
    0x106c0ff34 <+44612308>: sub w8, w24, #1
    0x106c0ff38 <+44612312>: ldaxr w9, [x23]
    0x106c0ff3c <+44612316>: cmp w9, w24
    0x106c0ff40 <+44612320>: b.ne #0x106c0ff7c
    0x106c0ff44 <+44612324>: stlxr w9, w8, [x23]
    0x106c0ff48 <+44612328>: cbnz w9, #0x106c0ff38
+++ into iterator: startAddress=0x106c0ff4c, isAppCode=false
    0x106c0ff4c <+44612332>: b #0x106c0ff84
+++ into iterator: startAddress=0x106c0ff84, isAppCode=false
    0x106c0ff84 <+44612388>: cmp w24, #2
    0x106c0ff88 <+44612392>: b.ne #0x106c10028
+++ into iterator: startAddress=0x106c0ff8c, isAppCode=false
    0x106c0ff8c <+44612396>: tbz w0, #0, #0x106c10028
+++ into iterator: startAddress=0x106c10028, isAppCode=false
    0x106c10028 <+44612552>: ldp x29, x30, [sp, #0x30]
    0x106c1002c <+44612556>: ldp x20, x19, [sp, #0x20]
    0x106c10030 <+44612560>: ldp x22, x21, [sp, #0x10]
    0x106c10034 <+44612564>: ldp x24, x23, [sp], #0x40
    0x106c10038 <+44612568>: ret
+++ into iterator: startAddress=0x106d0a104, isAppCode=false
    0x106d0a104 <+45636772>: ldur x8, [x29, #-0x48]
    0x106d0a108 <+45636776>: adrp x9, #0x107c28000
    0x106d0a10c <+45636780>: ldr x9, [x9, #0x28]
    0x106d0a110 <+45636784>: ldr x9, [x9]
    0x106d0a114 <+45636788>: cmp x9, x8
    0x106d0a118 <+45636792>: b.ne #0x106d0a138
+++ into iterator: startAddress=0x106d0a11c, isAppCode=false
    0x106d0a11c <+45636796>: ldp x29, x30, [sp, #0x100]
    0x106d0a120 <+45636800>: ldp x20, x19, [sp, #0xf0]
    0x106d0a124 <+45636804>: ldp x22, x21, [sp, #0xe0]
    0x106d0a128 <+45636808>: ldp x24, x23, [sp, #0xd0]
    0x106d0a12c <+45636812>: ldp x28, x27, [sp, #0xc0]
    0x106d0a130 <+45636816>: add sp, sp, #0x110
    0x106d0a134 <+45636820>: ret
+++ into iterator: startAddress=0x106cb825c, isAppCode=false
    0x106cb825c <+45301244>: add w22, w22, #1
    0x106cb8260 <+45301248>: b #0x106cb820c
+++ into iterator: startAddress=0x106cb820c, isAppCode=false
    0x106cb820c <+45301164>: ldr w8, [x25, #8]
    0x106cb8210 <+45301168>: cmp w22, w8
    0x106cb8214 <+45301172>: b.eq #0x106cb8264
+++ into iterator: startAddress=0x106cb8264, isAppCode=false
    0x106cb8264 <+45301252>: ldr w25, [x26, #0x10]
    0x106cb8268 <+45301256>: tbnz w19, #0, #0x106cb8274
+++ into iterator: startAddress=0x106cb8274, isAppCode=false
    0x106cb8274 <+45301268>: ldr x21, [sp, #8]
    0x106cb8278 <+45301272>: mov x0, x25
    0x106cb827c <+45301276>: bl #0x106cc899c
+++ into iterator: startAddress=0x106cb8280, isAppCode=false
    0x106cb8280 <+45301280>: adrp x8, #0x107d2a000
    0x106cb8284 <+45301284>: ldr x0, [x8, #0x780]
    0x106cb8288 <+45301288>: bl #0x106cb8b94
+++ into iterator: startAddress=0x106cb828c, isAppCode=false
    0x106cb828c <+45301292>: cbz w19, #0x106cb829c
+++ into iterator: startAddress=0x106cb8290, isAppCode=false
    0x106cb8290 <+45301296>: ldr x8, [x20, #0x70]
    0x106cb8294 <+45301300>: ldr x9, [sp, #0x10]
    0x106cb8298 <+45301304>: str x8, [x9]
    0x106cb829c <+45301308>: ldr x8, [x27]
    0x106cb82a0 <+45301312>: cbz x8, #0x106cb82dc
+++ into iterator: startAddress=0x106cb82dc, isAppCode=false
    0x106cb82dc <+45301372>: add x27, x20, #0x68
    0x106cb82e0 <+45301376>: ldr x8, [x27]
    0x106cb82e4 <+45301380>: str x8, [x21]
    0x106cb82e8 <+45301384>: tbnz w19, #0, #0x106cb82fc
+++ into iterator: startAddress=0x106cb82fc, isAppCode=false
    0x106cb82fc <+45301404>: ldp x29, x30, [sp, #0x90]
    0x106cb8300 <+45301408>: ldp x20, x19, [sp, #0x80]
    0x106cb8304 <+45301412>: ldp x22, x21, [sp, #0x70]
    0x106cb8308 <+45301416>: ldp x24, x23, [sp, #0x60]
    0x106cb830c <+45301420>: ldp x26, x25, [sp, #0x50]
    0x106cb8310 <+45301424>: ldp x28, x27, [sp, #0x40]
    0x106cb8314 <+45301428>: add sp, sp, #0xa0
    0x106cb8318 <+45301432>: ret
+++ into iterator: startAddress=0x1044fc0b0, isAppCode=false
    0x1044fc0b0 <+3636304>: add sp, sp, #0x10
    0x1044fc0b4 <+3636308>: ldp x1, x0, [sp], #0x10
    0x1044fc0b8 <+3636312>: msr nzcv, x1
    0x1044fc0bc <+3636316>: ldp x1, x2, [sp], #0x10
    0x1044fc0c0 <+3636320>: ldp x3, x4, [sp], #0x10
    0x1044fc0c4 <+3636324>: ldp x5, x6, [sp], #0x10
    0x1044fc0c8 <+3636328>: ldp x7, x8, [sp], #0x10
    0x1044fc0cc <+3636332>: ldp x9, x10, [sp], #0x10
    0x1044fc0d0 <+3636336>: ldp x11, x12, [sp], #0x10
    0x1044fc0d4 <+3636340>: ldp x13, x14, [sp], #0x10
    0x1044fc0d8 <+3636344>: ldp x15, x16, [sp], #0x10
    0x1044fc0dc <+3636348>: ldp x17, x18, [sp], #0x10
    0x1044fc0e0 <+3636352>: ldp x19, x20, [sp], #0x10
    0x1044fc0e4 <+3636356>: ldp x21, x22, [sp], #0x10
    0x1044fc0e8 <+3636360>: ldp x23, x24, [sp], #0x10
    0x1044fc0ec <+3636364>: ldp x25, x26, [sp], #0x10
    0x1044fc0f0 <+3636368>: ldp x27, x28, [sp], #0x10
    0x1044fc0f4 <+3636372>: ldp x29, x30, [sp], #0x10
    0x1044fc0f8 <+3636376>: ldp q0, q1, [sp], #0x20
    0x1044fc0fc <+3636380>: ldp q2, q3, [sp], #0x20
    0x1044fc100 <+3636384>: ldp q4, q5, [sp], #0x20
    0x1044fc104 <+3636388>: ldp q6, q7, [sp], #0x20
    0x1044fc108 <+3636392>: ldp q8, q9, [sp], #0x20
    0x1044fc10c <+3636396>: ldp q10, q11, [sp], #0x20
    0x1044fc110 <+3636400>: ldp q12, q13, [sp], #0x20
    0x1044fc114 <+3636404>: ldp q14, q15, [sp], #0x20
    0x1044fc118 <+3636408>: ldp q16, q17, [sp], #0x20
    0x1044fc11c <+3636412>: ldp q18, q19, [sp], #0x20
    0x1044fc120 <+3636416>: ldp q20, q21, [sp], #0x20
    0x1044fc124 <+3636420>: ldp q22, q23, [sp], #0x20
    0x1044fc128 <+3636424>: ldp q24, q25, [sp], #0x20
    0x1044fc12c <+3636428>: ldp q26, q27, [sp], #0x20
    0x1044fc130 <+3636432>: ldp q28, q29, [sp], #0x20
    0x1044fc134 <+3636436>: ldp q30, q31, [sp], #0x20
    0x1044fc138 <+3636440>: ldp x16, x17, [sp], #0x10
    0x1044fc13c <+3636444>: ret x16
+++ into iterator: startAddress=0x108040030, isAppCode=false
    0x108040030 <+65780688>: sub sp, sp, #0xf0
    0x108040034 <+65780692>: stp x28, x27, [sp, #0x90]
    0x108040038 <+65780696>: stp x26, x25, [sp, #0xa0]
    0x10804003c <+65780700>: stp x24, x23, [sp, #0xb0]
    0x108040040 <+65780704>: ldr x16, #0x108040048
    0x108040044 <+65780708>: br x16

之后才是：原始函数代码

+++ into iterator: startAddress=0x104184470, isAppCode=true
    0x104184470 <+16>: stp x22, x21, [sp, #0xc0]
    0x104184474 <+20>: stp x20, x19, [sp, #0xd0]
    0x104184478 <+24>: stp x29, x30, [sp, #0xe0]
    0x10418447c <+28>: add x29, sp, #0xe0
    0x104184480 <+32>: nop
    0x104184484 <+36>: ldr x8, #0x1041d87d8
    0x104184488 <+40>: ldr x8, [x8]
    0x10418448c <+44>: stur x8, [x29, #-0x58]
    0x104184490 <+48>: mov w26, #0x5a87
    0x104184494 <+52>: movk w26, #0x6c24, lsl #16
    0x104184498 <+56>: add x8, x0, #6
    0x10418449c <+60>: cmp x8, #5
    0x1041844a0 <+64>: ccmn x0, #8, #4, hs
    0x1041844a4 <+68>: mov w8, #1
    0x1041844a8 <+72>: csel w8, wzr, w8, eq
    0x1041844ac <+76>: mov w11, #0xa5a2
    0x1041844b0 <+80>: movk w11, #0x93db, lsl #16
    0x1041844b4 <+84>: cmp x1, #0
    0x1041844b8 <+88>: cset w9, eq
    0x1041844bc <+92>: orr w8, w9, w8
    0x1041844c0 <+96>: add w9, w26, w8
    0x1041844c4 <+100>: add w9, w9, w11
    0x1041844c8 <+104>: sub w9, w9, #0x21
    0x1041844cc <+108>: adr x25, #0x1041a6cb0
    0x1041844d0 <+112>: nop
    0x1041844d4 <+116>: ldrsw x9, [x25, w9, sxtw #2]
    0x1041844d8 <+120>: nop
    0x1041844dc <+124>: ldr x10, #0x1041dd158
    0x1041844e0 <+128>: add x9, x9, x10
    0x1041844e4 <+132>: mov w22, #-0xafc9
    0x1041844e8 <+136>: br x9
+++ into iterator: startAddress=0x1041844ec, isAppCode=true
    0x1041844ec <+140>: mov x23, x1
    0x1041844f0 <+144>: mov x28, x0
    0x1041844f4 <+148>: eor w8, w8, #1
    0x1041844f8 <+152>: sub w9, w11, #0x29
    0x1041844fc <+156>: madd w22, w8, w9, w26
    0x104184500 <+160>: mov x20, #0xa930
    0x104184504 <+164>: movk x20, #0xea59, lsl #16
    0x104184508 <+168>: movk x20, #0x9bdd, lsl #32
    0x10418450c <+172>: movk x20, #0xd570, lsl #48
    0x104184510 <+176>: add w8, w22, #0xb
    0x104184514 <+180>: adr x24, #0x1041ddfe0
    0x104184518 <+184>: nop
    0x10418451c <+188>: ldr x8, [x24, w8, sxtw #3]
    0x104184520 <+192>: sub x8, x8, #2
    0x104184524 <+196>: mov w0, #0x18
    0x104184528 <+200>: str x8, [sp, #0x60]
    0x10418452c <+204>: blr x8

其中触发了onReceive，对应输出的log是：

+++ into iterator: startAddress=0x194d31f44, isAppCode=false
+++ into iterator: startAddress=0x102e327ec, isAppCode=true
    0x102e327ec <+9100>: mov w8, #0x6beb
    0x102e327f0 <+9104>: movk w8, #0x3920, lsl #16
    0x102e327f4 <+9108>: add w24, w21, w23
    0x102e327f8 <+9112>: str xzr, [x20]
    0x102e327fc <+9116>: str w8, [x20, #8]
    0x102e32800 <+9120>: mov w8, #0xf28c
    0x102e32804 <+9124>: movk w8, #0x3820, lsl #16
    0x102e32808 <+9128>: str w8, [x20, #0xc]
    0x102e3280c <+9132>: mov x8, #0x77e8
    0x102e32810 <+9136>: movk x8, #0xcfa6, lsl #16
    0x102e32814 <+9140>: movk x8, #0xde0b, lsl #32
    0x102e32818 <+9144>: movk x8, #0x20cd, lsl #48
    0x102e3281c <+9148>: add x0, x19, x8
    0x102e32820 <+9152>: blr x27
+++ into iterator: startAddress=0x194d30564, isAppCode=false
>>> into onReceive: parsedEvents=ret,0x1084e0038,0x1085da104,0,ret,0x1085da134,0x10858825c,-1,ret,0x108588318,0x1036540b0,-2,ret,0x10365413c,0x10984000c,-3,ret,0x1ddc2abc0,0x194d2e05c,0,ret,0x194d2fbdc,0x194d2dc74,1,ret,0x194d311c4,0x194d2d830,1,ret,0x194d2d898,0x194d2e0a0,0,ret,0x1ddc2ac00,0x194d2e374,0,ret,0x194d2e3a8,0x194d31214,-1,ret,0x194d312e8,0x194d30478,-2,ret,0x194d304a4,0x102e30530,-3,ret,0x1ddc2abc0,0x194d2cd44,0,ret,0x194d31894,0x194d2f0a0,1,ret,0x194d31b3c,0x194d2f0c0,1,ret,0x194d2f1ac,0x194d2cd88,0,ret,0x1ddc2ac00,0x194d2d280,0,ret,0x194d2d2b4,0x194d3123c,-1,ret,0x194d312e8,0x194d30478,-2,ret,0x194d304a4,0x102e305ac,-3,ret,0x1bd80959c,0x102e244e0,-2,ret,0x1ddc36aec,0x183f794d8,0,ret,0x183f77ab0,0x183f7958c,0,ret,0x1bd808ca8,0x1bd809c04,1,ret,0x1bd809c40,0x183f795a0,0,ret,0x183f7970c,0x183f795e4,0,ret,0x183f7963c,0x183f7aa34,-1,ret,0x183f7aa98,0x102e24508,-2,ret,0x1bd808b70,0x1bd809194,-1,ret,0x1bd809240,0x102e24528,-2,ret,0x102e24630,0x102e315c4,-3,ret,0x1ddc2abc0,0x194d2e05c,0,ret,0x194d311c4,0x194d2d830,1,ret,0x194d2d898,0x194d2e0a0,0,ret,0x1ddc2ac00,0x194d2e374,0,ret,0x194d2e3a8,0x194d31214,-1,ret,0x194d312e8,0x194d30478,-2,ret,0x194d304a4,0x102e316b8,-3,ret,0x1ddc2abc0,0x194d2cd44,0,ret,0x194d31894,0x194d2efe4,1,ret,0x194d2f1ac,0x194d2cd88,0,ret,0x1ddc2ac00,0x194d2d280,0,ret,0x194d2d2b4,0x194d3123c,-1,ret,0x194d312e8,0x194d30478,-2,ret,0x194d304a4,0x102e31744,-3,ret,0x1bd808aa4,0x1bd809b78,-2,ret,0x1bd809bb0,0x102e32168,-3,ret,0x194d305c4,0x194d30a34,-1,ret,0x194d33380,0x194d30a50,-1,ret,0x194d30a1c,0x194d2c188,-2,ret,0x1ddc2abc0,0x194d31c80,-2,ret,0x194d2c06c,0x194d31dec,-2,ret,0x194d31894,0x194d31e00,-2,ret,0x194d31b3c,0x194d31eec,-2,ret,0x194d30e90,0x194d31f34,-2,ret,0x1ddc2ac00,0x102e327ec,-3
+++ into iterator: startAddress=0x194d30584, isAppCode=false
+++ into iterator: startAddress=0x194d30588, isAppCode=false

再往后，就是：非原始函数代码 和 原始函数代码 交替输出

而我们此处只关心 原始函数代码，去调试输出即可。

比如最后此刻所调试的+8516行的代码

+++ into iterator: startAddress=0x1041865a0, isAppCode=true
    0x1041865a0 <+8512>: mov w8, #0
    0x1041865a4 <+8516>: str x9, [x10]
curOffsetInt=8516
    0x1041865a8 <+8520>: b #0x104186740
contextStr={"pc":"0x1041865a4","sp":"0x16bf46740","nzcv":1610612736,"x0":"0x0","x1":"0x104ba0000","x2":"0xc","x3":"0x29","x4":"0x470b","x5":"0x0","x6":"0x0","x7":"0xec0","x8":"0x0","x9":"0x3050500","x10":"0x16bf46838","x11":"0x6c245a87","x12":"0x6c245a3d","x13":"0x1041864dc","x14":"0x45","x15":"0x0","x16":"0xd5709bdf0d7a48f0","x17":"0x123209fc0","x18":"0x0","x19":"0xdf3221f55389ecc8","x20":"0x1233064b0","x21":"0x93dba5a2","x22":"0x0","x23":"0x39207beb","x24":"0x6c245a87","x25":"0x1041a6cb0","x26":"0x6c245a87","x27":"0x194d2c100","x28":"0xfffffffffffffffe","fp":"0x16bf46820","lr":"0x104186168","q0":{},"q1":{},"q2":{},"q3":{},"q4":{},"q5":{},"q6":{},"q7":{},"q8":{},"q9":{},"q10":{},"q11":{},"q12":{},"q13":{},"q14":{},"q15":{},"q16":{},"q17":{},"q18":{},"q19":{},"q20":{},"q21":{},"q22":{},"q23":{},"q24":{},"q25":{},"q26":{},"q27":{},"q28":{},"q29":{},"q30":{},"q31":{},"d0":0.5585262685374610e-308,"d1":0.0000169759663317e-308,"d2":7.9499288951273454e-275,"d3":0,"d4":0,"d5":0,"d6":0,"d7":0,"d8":0,"d9":0,"d10":0,"d11":0,"d12":0,"d13":0,"d14":0,"d15":0,"d16":-1.0855813867524649e+251,"d17":0.000002084565455e-308,"d18":3.0554698911305689e-152,"d19":0.000001322084152e-308,"d20":3.7696966457559071e-175,"d21":1.0004894955531618e+128,"d22":9.5944260775693913e+225,"d23":-6.8154492514793903e-236,"d24":-2.1930923744387854e+50,"d25":-3.1153191556287330e+141,"d26":-1.0031492505499153e+302,"d27":-3.1584786060327890e-284,"d28":-1.7036104465458726e+239,"d29":-1.1538744009003510e-197,"d30":2.4944484440662111e-259,"d31":0,"s0":1.1035169354619356e-39,"s1":1.1210387714598533e-44,"s2":3.8204714345426298e-37,"s3":0,"s4":0,"s5":0,"s6":0,"s7":0,"s8":0,"s9":0,"s10":0,"s11":0,"s12":0,"s13":0,"s14":0,"s15":0,"s16":1.5548730664783592e-21,"s17":-1.3084408235578860e+36,"s18":-8.6088756618229034e-23,"s19":-5.408784745233076e-20,"s20":4.2151578028428229e+37,"s21":18362722504671230,"s22":3.372155249992253e+28,"s23":-7.6784630118876258e-30,"s24":-3715189.5,"s25":2.6426119211413095e+23,"s26":-3.5724724140742379e-23,"s27":-1.6239861190373424e-18,"s28":-205533200,"s29":-0.008124308660626411,"s30":-5.6424941355004989e-36,"s31":0}
x9Value1=0x3050500, x9Value2=0x3050500

输出了我们所希望的值：

x9=0x3050500

即可实现特定的调试目的。

crifan.org，使用署名4.0国际(CC BY 4.0)协议发布 all right reserved，powered by Gitbook最后更新： 2025-06-04 14:36:10

libInFieldCollection.dylib的vsPHbdGf

libInFieldCollection.dylib的vsPHbdGf

代码fridaStalker_vsPHbdGf.js

贴出之前的某个Frida的Stalker的完整调试代码：

/Users/crifan/dev/dev_root/iosReverse/iOSModifyActivation/subBin/libInFieldCollection_dylib/dynamicDebug/frida/frida_stalker/fridaStalker_vsPHbdGf.js

/**
 * Function: frida Stakler to hook libInFieldCollection.dylib funtion vsPHbdGf
 * Author: Crifan Li
 * Update: 20241217
 * Usage:
 *  cd /Users/crifan/dev/dev_root/iosReverse/iOSModifyActivation/subBin/libInFieldCollection_dylib/dynamicDebug/frida/frida_stalker
 *  frida -U -n mobileactivationd -l fridaStalker_vsPHbdGf.js
*/

// https://github.com/crifan/JsFridaUtil/blob/main/JsUtil.js
// pure JavaScript utils
class JsUtil {

  constructor() {
    console.log("JsUtil constructor")
  }

  static {
  }

  /*---------- Number(Int) ----------*/

  static intToHexStr(intValue, prefix="0x", isUpperCase=true){
    // var hexStr = prefix + intValue.toString(16)
    // var hexStr = prefix + String(intValue).padStart(2, "0")
    // var hexStr = prefix + intValue.toString(16).padStart(2, "0")
    var intHexStr = intValue.toString(16)
    // console.log("intHexStr=" + intHexStr)
    var padding0HexStr = intHexStr.padStart(2, "0")
    // console.log("padding0HexStr=" + padding0HexStr)
    if (isUpperCase) {
      padding0HexStr = padding0HexStr.toUpperCase()
      // console.log("padding0HexStr=" + padding0HexStr)
    }
    var fullHexStr = prefix + padding0HexStr
    // console.log("fullHexStr=" + fullHexStr)
    return fullHexStr
  }

  /*---------- Log ----------*/

  // Generate single line log string
  // input: logStr="Called: -[NSURLRequest initWithURL:]"
  // output: "=============================== Called: -[NSURLRequest initWithURL:] ==============================="
  static generateLineStr(logStr, isWithSpace=true, delimiterChar="=", lineWidth=80){
    // console.log("logStr=" + logStr, ", isWithSpace=" + isWithSpace + ", delimiterChar=" + delimiterChar + ", lineWidth=" + lineWidth)
    var lineStr = ""

    var realLogStr = ""
    if (isWithSpace) {
      realLogStr = " " + logStr + " "
    } else {
      realLogStr = logStr
    }

    var realLogStrLen = realLogStr.length
    if ((realLogStrLen % 2) > 0){
      realLogStr += " "
      realLogStrLen = realLogStr.length
    }

    var leftRightPaddingStr = ""
    var paddingLen = lineWidth - realLogStrLen
    if (paddingLen > 0) {
      var leftRightPaddingLen = paddingLen / 2
      leftRightPaddingStr = JsUtil.times(delimiterChar, leftRightPaddingLen)
    }

    lineStr = leftRightPaddingStr + realLogStr + leftRightPaddingStr

    // console.log("lineStr:\n" + lineStr)
    return lineStr
  }

  static logStr(curStr, isWithSpace=true, delimiterChar="=", lineWidth=80){
    // let delimiterStr = "--------------------"
    // console.log(delimiterStr + " " + curStr + " " + delimiterChar)
    var lineStr = JsUtil.generateLineStr(curStr, isWithSpace, delimiterChar, lineWidth)
    console.log(lineStr)
  }

  /*---------- Object: Dict/List/... ----------*/

  // convert Object(dict/list/...) to JSON string
  // function toJsonStr(curObj, singleLine=false, space=2){
  static toJsonStr(curObj, singleLine=false, space=2){
    // console.log("toJsonStr: singleLine=" + singleLine)
    // var jsonStr = JSON.stringify(curObj, null, 2)
    var jsonStr = JSON.stringify(curObj, null, space)
    if(singleLine) {
      // jsonStr = jsonStr.replace(/\\n/g, '')
      jsonStr = jsonStr.replace(/\n/g, '')
    }
    return jsonStr
    // return curObj.toString()
  }

  /*---------- List ----------*/

  // check whether is item inside the list
  // eg: curItem="abc", curList=["abc", "def"] => true
  static isItemInList(curItem, curList){
    // method1:
    return curList.includes(curItem)
    // // method2:
    // return curList.indexOf(curItem) > -1
  }

  static sortByKey(curList, keyName){
    if (null != curList){
      curList.sort(function(objA, objB) {
        var valueA = objA[keyName]
        var valueB = objB[keyName]
        var valudDiff = valueA - valueB
        // console.log("valueA=" + valueA + ", valueB=" + valueB + " -> valudDiff=" + valudDiff)
        return valudDiff
      })
    }
  }

  /*---------- String ----------*/

  /** Function that count occurrences of a substring in a string;
   * @param {String} string               The string
   * @param {String} subString            The sub string to search for
   * @param {Boolean} [allowOverlapping]  Optional. (Default:false)
   *
   * @author Vitim.us https://gist.github.com/victornpb/7736865
   * @see Unit Test https://jsfiddle.net/Victornpb/5axuh96u/
   * @see https://stackoverflow.com/a/7924240/938822
   */
  static occurrences(string, subString, allowOverlapping) {
    // console.log("string=" + string + ",subString=" + subString + ", allowOverlapping=" + allowOverlapping)
    string += "";
    subString += "";
    if (subString.length <= 0) return (string.length + 1);

    var n = 0,
      pos = 0,
      step = allowOverlapping ? 1 : subString.length;

    while (true) {
      pos = string.indexOf(subString, pos);
      // console.log("pos=" + pos)
      if (pos >= 0) {
        ++n;
        pos += step;
      } else break;
    }

    return n;
  }

  // String multiple
  // eg: str="=", num=5 => "====="
  static times(str, num){
    return new Array(num + 1).join(str)
  }

  // check string is empty or null
  static strIsEmpty(curStr){
    var isNull = null == curStr
    var isEmp = "" === curStr
    return isNull || isEmp
  }

  /*---------- Byte ----------*/

  // byte decimaal to byte hex
  // eg:
  //    8 => 8
  //    -60 => c4
  // function byteDecimalToByteHex(byteDecimal) {
  static byteDecimalToByteHex(byteDecimal) {
    // var digitCount = 6
    var digitCount = 2
    var minusDigitCount = 0 - digitCount
    // return (byteDecimal + Math.pow(16, 6)).toString(16).substr(-6)
    // var hexStr = (byteDecimal + Math.pow(16, 2)).toString(16).substr(-2)
    // return (byteDecimal + Math.pow(16, digitCount)).toString(16).substr(minusDigitCount)
    var hexStr = (byteDecimal + Math.pow(16, digitCount)).toString(16).substr(minusDigitCount)
    // console.log("typeof hexStr=" + (typeof hexStr))
    // console.log("hexStr=" + hexStr)
    var hexValue = parseInt(hexStr, 16)
    // console.log("typeof hexValue=" + (typeof hexValue))
    // console.log("hexValue=" + hexValue)
    return hexValue
  }

  /*---------- Object ----------*/

  // check is js string
  static isJsStr(curObj){
    // console.log("curObj=" + curObj)
    var curObjType = (typeof curObj)
    // console.log("curObjType=" + curObjType)
    var isStr = curObjType === "string"
    // console.log("isStr=" + isStr)
    return isStr
  }

  /*---------- Pointer ----------*/

  // check pointer is valid or not
  // example
  //         0x103e79560 => true
  //         0xc => false
  static isValidPointer(curPtr){
    let MinValidPointer = 0x10000
    var isValid = curPtr > MinValidPointer
    // console.log("curPtr=" + curPtr, " -> isValid=" + isValid)
    return isValid
  }

}

// https://github.com/crifan/JsFridaUtil/blob/main/frida/FridaUtil.js
// Frida Common Util
class FridaUtil {
  // for Stalker onEnter transform, is show opcode string or not
  static isShowOpcode = true

  constructor() {
    console.log("FridaUtil constructor")
    console.log("FridaUtil Process.platform=" + Process.platform)
  }

  static isiOS(){
    var platform = Process.platform
    // console.log("platform=" + platform)
    var isJavaAvailable = Java.available
    // console.log("isJavaAvailable=" + isJavaAvailable)
    var isDarwin = platform === "darwin"
    // console.log("isDarwin=" + isDarwin)
    var isiOSOS = (!isJavaAvailable) && isDarwin
    // console.log("isiOSOS=" + isiOSOS)
    return isiOSOS
  }

  static isAndroid(){
    var platform = Process.platform
    // console.log("platform=" + platform)
    var isJavaAvailable = Java.available
    // console.log("isJavaAvailable=" + isJavaAvailable)
    var isLinux = platform === "linux"
    // console.log("isLinux=" + isLinux)
    var isAndroidOS = isJavaAvailable && isLinux
    // console.log("isAndroidOS=" + isAndroidOS)
    return isAndroidOS
  }

  // Frida pointer to UTF-8 string
  static ptrToUtf8Str(curPtr){
    var curUtf8Str = curPtr.readUtf8String()
    // console.log("curUtf8Str=" + curUtf8Str)
    return curUtf8Str
  }

  // Frida pointer to C string
  static ptrToCStr(curPtr){
    // var curCStr = Memory.readCString(curPtr)
    var curCStr = curPtr.readCString()
    // var curCStr = curPtr.readUtf8String()
    // console.log("curCStr=" + curCStr)
    return curCStr
  }

  static genModuleInfoStr(foundModule){
    // console.log("Module: name=" + foundModule.name + ", base=" + foundModule.base + ", size=" + foundModule.size + ", path=" + foundModule.path)
    var endAddress = foundModule.base.add(foundModule.size)
    var sizeHexStr = JsUtil.intToHexStr(foundModule.size)
    // console.log("Module: name=" + foundModule.name + ", address=[" + foundModule.base + "-" + endAddress + "], size=" + sizeHexStr + "=" + foundModule.size + ", path=" + foundModule.path)
    var moduleInfoStr = "Module: address=[" + foundModule.base + "-" + endAddress + "], name=" + foundModule.name + ", size=" + sizeHexStr + "=" + foundModule.size + ", path=" + foundModule.path
    return moduleInfoStr
  }

  // print module basic info: name, base, size, path
  static printModuleBasicInfo(foundModule){
    var moduleInfoStr = FridaUtil.genModuleInfoStr(foundModule)
    console.log(moduleInfoStr)
  }

  // print module symbols
  static printModuleSymbols(foundModule){
    var curSymbolList = foundModule.enumerateSymbols()
    console.log("Symbol: length=" + curSymbolList.length + ", list=" + curSymbolList)
    for(var i = 0; i < curSymbolList.length; i++) {
      console.log("---------- Symbol [" + i + "]----------")
      var curSymbol = curSymbolList[i]
      var sectionStr = JSON.stringify(curSymbol.section)
      console.log("name=" + curSymbol.name + ", address=" + curSymbol.address + "isGlobal=" + curSymbol.isGlobal + ", type=" + curSymbol.type + ", section=" + sectionStr)
    }
  }

  // print module exports
  static printModuleExports(foundModule){
    var curExportList = foundModule.enumerateExports()
    console.log("Export: length=" + curExportList.length + ", list=" + curExportList)
    for(var i = 0; i < curExportList.length; i++) {
      console.log("---------- Export [" + i + "]----------")
      var curExport = curExportList[i]
      console.log("type=" + curExport.type + ", name=" + curExport.name + ", address=" + curExport.address)
    }
  }

  // print module info
  static printModuleInfo(moduleName){
    const foundModule = Module.load(moduleName)
    // const foundModule = Module.ensureInitialized()
    console.log("foundModule=" + foundModule)

    if (null == foundModule) {
      return
    }

    FridaUtil.printModuleBasicInfo(foundModule)

    FridaUtil.printModuleSymbols(foundModule)
    FridaUtil.printModuleExports(foundModule)
  }

  // print process basic info
  static printProcessBasicInfo(){
    console.log(
      "Process: id=" + Process.id
      + ", currentThreadId=" + Process.getCurrentThreadId()
      + ", currentDir=" + Process.getCurrentDir()
      + ", homeDir=" + Process.getHomeDir()
      + ", tmpDir=" + Process.getTmpDir()
      + ", arch=" + Process.arch
      + ", platform=" + Process.platform
      + ", pageSize=" + Process.pageSize
      + ", pointerSize=" + Process.pointerSize
      + ", codeSigningPolicy=" + Process.codeSigningPolicy
      + ", isDebuggerAttached=" + Process.isDebuggerAttached()
    )
  }

  // print all loaded modules basic info of current process
  //  Note: similar to `image list` in lldb
  static printAllLoadedModules(isSort=true){
    FridaUtil.printProcessBasicInfo()

    var moduleList = []

    Process.enumerateModules({
      onMatch: function(module){
        // console.log('Module name: ' + module.name + " - " + "Base Address: " + module.base.toString());
        // FridaUtil.printModuleBasicInfo(module)
        moduleList.push(module)
      },
      onComplete: function(){}
    })

    if (isSort) {
      // moduleList.sort(function(moduleA, moduleB) {
      //   // var isLarge = moduleA.base > moduleB.base
      //   // console.log("moduleA.base=" + moduleA.base + ", moduleB.base=" + moduleB.base + " -> isLarge=" + isLarge)
      //   var addrDiff = moduleA.base - moduleB.base
      //   console.log("moduleA.base=" + moduleA.base + ", moduleB.base=" + moduleB.base + " -> addrDiff=" + addrDiff)
      //   return addrDiff
      // })
      JsUtil.sortByKey(moduleList, "base")
    }

    for(var i = 0; i < moduleList.length; i++) {
      var curModule = moduleList[i]
      // var prefixStr = "\t"
      var prefixStr = "  "
      console.log(prefixStr + FridaUtil.genModuleInfoStr(curModule))
    }

  }

  static printModuleInfoAndStalkerExclude(moduleName){
    var foundModule = Process.getModuleByName(moduleName)
    console.log("moduleName=" + moduleName + " -> foundModule=" + foundModule)
    if (null != foundModule) {
      Stalker.exclude(foundModule)
      // console.log("Stalker.exclude for module:")
      // FridaUtil.printModuleBasicInfo(foundModule)
      console.log("Stalker.exclude for: " + FridaUtil.genModuleInfoStr(foundModule))
    }
  }

  // print function call and stack, output content type is: address
  static printFunctionCallStack_addr(curContext, prefix=""){
    var backtracerType = Backtracer.ACCURATE
    // var backtracerType = Backtracer.FUZZY
    if (!JsUtil.strIsEmpty(prefix)){
      prefix = prefix + " "
    }
    // const linePrefix = "\n"
    // const linePrefix = "\n\t"
    const linePrefix = "\n  "
    // const linePrefix = "\n "
    // const linePrefix = "\n"
    console.log(prefix + 'Stack:' + linePrefix +
      Thread.backtrace(curContext, backtracerType)
      .map(DebugSymbol.fromAddress).join(linePrefix) + '\n');
  }

  static dumpMemory(toDumpPtr, byteLen=128){
    var buf = toDumpPtr.readByteArray(byteLen)
    var dumpHexStr = hexdump(
      buf,
      {
        offset: 0,
        length: byteLen,
        header: true,
        ansi: true
      }
    )
    console.log("dumpHexStr=\n" + dumpHexStr)
  }

  // convert ByteArray to Opcode string
  static byteArrayToOpcodeStr(byteArr){
    var byteStrList = []
    for(var i = 0; i < byteArr.length; i++) {
      var curByte = byteArr[i]
      // console.log("curByte=" + curByte)
      var curByteStr = JsUtil.intToHexStr(curByte, "", true)
      // console.log("curByteStr=" + curByteStr)
      byteStrList.push(curByteStr)
    }
    // console.log("byteStrList=" + byteStrList)
    var opcodeStr = byteStrList.join(" ")
    // console.log("byteArr=" + byteArr + " -> opcodeStr=" + opcodeStr)
    return opcodeStr
  }

  // read byte array from address
  // Note: curAddress is NativePointer
  static readAddressByteArray(curAddress, byteSize){
    // console.log("curAddress=" + curAddress + ", byteSize=" + byteSize)
    // var instructionByteArrBuffer = curAddress.readByteArray(byteSize)
    var curByteArray = []
    for(var i = 0; i < byteSize; i++){
      var curAddr = curAddress.add(i)
      // console.log("curAddr=" + curAddr)
      var byteU8 = curAddr.readU8()
      // console.log("byteU8=" + byteU8)
      curByteArray.push(byteU8)
    }
    // console.log("curByteArray=" + curByteArray)
    return curByteArray
  }

  static genInstructionOpcodeStr(instruction){
    var instructionByteArr = FridaUtil.readAddressByteArray(instruction.address, instruction.size)
    // console.log("instructionByteArr=" + instructionByteArr)

    // var instructionOpcodeStr = hexdump(
    //   instructionByteArr,
    //   {
    //     offset: 0,
    //     length: curInstructionSize,
    //     header: false,
    //     ansi: false
    //   }
    // )
    var instructionOpcodeStr = FridaUtil.byteArrayToOpcodeStr(instructionByteArr)
    // console.log("instructionOpcodeStr=" + instructionOpcodeStr)
    return instructionOpcodeStr
  }

  static printInstructionInfo(instruction){
    // Instruction: address=0x252c0edf8,toString()=br x10,next=0x4,size=4,mnemonic=br,opStr=x10,operands=[{"type":"reg","value":"x10","access":"r"}],regsAccessed={"read":["x10"],"written":[]},regsRead=[],regsWritten=[],groups=["jump"],toJSON()={"address":"0x252c0edf8","next":"0x4","size":4,"mnemonic":"br","opStr":"x10","operands":[{"type":"reg","value":"x10","access":"r"}],"regsAccessed":{"read":["x10"],"written":[]},"regsRead":[],"regsWritten":[],"groups":["jump"]}
    console.log("Instruction: address=" + instruction.address
      + ",toString()=" + instruction.toString()
      + ",toJSON()=" + JSON.stringify(instruction.toJSON())
      // + ",next=" + instruction.next
      // + ",size=" + instruction.size
      // + ",mnemonic=" + instruction.mnemonic
      // + ",opStr=" + instruction.opStr
      // + ",operands=" + JSON.stringify(instruction.operands)
      // + ",regsAccessed=" + JSON.stringify(instruction.regsAccessed)
      // + ",regsRead=" + JSON.stringify(instruction.regsRead)
      // + ",regsWritten=" + JSON.stringify(instruction.regsWritten)
      // + ",groups=" + JSON.stringify(instruction.groups)
    )
  }

  // Frida Stalker hoo unknown name native function
  static stalkerHookUnnameNative(moduleBaseAddress, funcRelativeStartAddr, functionSize, argNum, hookFuncMap){
    console.log("Frida Stalker hook: module: baseAddress=" + moduleBaseAddress + ", isShowOpcode=" + FridaUtil.isShowOpcode)

    var functionSizeHexStr = JsUtil.intToHexStr(functionSize)
    var funcRelativeStartAddrHexStr = JsUtil.intToHexStr(funcRelativeStartAddr)
    var funcRelativeEndAddr = funcRelativeStartAddr + functionSize
    var funcRelativeEndAddrHexStr = JsUtil.intToHexStr(funcRelativeEndAddr)
    console.log("function: relativeStartAddr=" + funcRelativeStartAddrHexStr + ", size=" + functionSize + "=" + functionSizeHexStr + ", relativeEndAddr=" + funcRelativeEndAddrHexStr)

    const funcRealStartAddr = moduleBaseAddress.add(funcRelativeStartAddr)
    // var funcRealEndAddr = funcRealStartAddr + functionSize
    const funcRealEndAddr = funcRealStartAddr.add(functionSize)
    console.log("funcRealStartAddr=" + funcRealStartAddr + ", funcRealEndAddr=" + funcRealEndAddr)
    var curTid = null
    console.log("curTid=" + curTid)
    Interceptor.attach(funcRealStartAddr, {
      onEnter: function(args) {
        JsUtil.logStr("Trigged addr: relative [" + funcRelativeStartAddrHexStr + "] = real [" + funcRealStartAddr + "]")

        for(var i = 0; i < argNum; i++) {
          var curArg = args[i]
          console.log("arg[" + i  + "]=" + curArg)
        }

        var curTid = Process.getCurrentThreadId()
        console.log("curTid=" + curTid)
        Stalker.follow(curTid, {
            events: {
              call: false, // CALL instructions: yes please
              ret: true, // RET instructions
              exec: false, // all instructions: not recommended as it's
              block: false, // block executed: coarse execution trace
              compile: false // block compiled: useful for coverage
            },
            // onReceive: Called with `events` containing a binary blob comprised of one or more GumEvent structs. See `gumevent.h` for details about the format. Use `Stalker.parse()` to examine the data.
            onReceive(events) {
              var parsedEvents = Stalker.parse(events)
              // var parsedEventsStr = JSON.stringify(parsedEventsStr)
              // console.log(">>> into onReceive: parsedEvents=" + parsedEvents + ", parsedEventsStr=" + parsedEventsStr);
              console.log(">>> into onReceive: parsedEvents=" + parsedEvents);
            },

            // transform: (iterator: StalkerArm64Iterator) => {
            transform: function (iterator) {
              // https://www.radare.org/doc/frida/interfaces/StalkerArmIterator.html

              // console.log("iterator=" + iterator)
              var instruction = iterator.next()
              const startAddress = instruction.address
              // console.log("+++ into iterator: startAddress=" + startAddress)
              // const isAppCode = startAddress.compare(funcRealStartAddr) >= 0 && startAddress.compare(funcRealEndAddr) === -1
              // const isAppCode = (startAddress.compare(funcRealStartAddr) >= 0) && (startAddress.compare(funcRealEndAddr) < 0)
              const gt_realStartAddr = startAddress.compare(funcRealStartAddr) >= 0
              const lt_realEndAddr = startAddress.compare(funcRealEndAddr) < 0
              var isAppCode = gt_realStartAddr && lt_realEndAddr
              console.log("+++ into iterator: startAddress=" + startAddress + ", isAppCode=" + isAppCode)

              // // for debug
              // isAppCode = true

              // console.log("isAppCode=" + isAppCode + ", gt_realStartAddr=" + gt_realStartAddr + ", lt_realEndAddr=" + lt_realEndAddr)
              do {
                if (isAppCode) {
                  // is origal function code = which we focus on
                  // FridaUtil.printInstructionInfo(instruction)

                  var curRealAddr = instruction.address
                  // console.log("curRealAddr=" + curRealAddr)
                  // const isAppCode = curRealAddr.compare(funcRealStartAddr) >= 0 && curRealAddr.compare(funcRealEndAddr) === -1
                  // console.log(curRealAddr + ": isAppCode=" + isAppCode)
                  var curOffsetHexPtr = curRealAddr.sub(funcRealStartAddr)
                  var curOffsetInt = curOffsetHexPtr.toInt32()
                  console.log("current: realAddr=" + curRealAddr + " -> offset: hex=" + curOffsetHexPtr + "=" + curOffsetInt)

                  // var instructionStr = instruction.mnemonic + " " + instruction.opStr
                  var instructionStr = instruction.toString()
                  // console.log("\t" + curRealAddr + ": " + instructionStr);
                  // console.log("\t" + curRealAddr + " <+" + curOffsetHexPtr + ">: " + instructionStr)
                  // console.log("\t" + curRealAddr + " <+" + curOffsetInt + ">: " + instructionStr)

                  var opcodeStr = ""
                  if (FridaUtil.isShowOpcode) {
                    opcodeStr = " " + FridaUtil.genInstructionOpcodeStr(instruction)
                  }
                  var instructionFullLogStr = "\t" + curRealAddr + " <+" + curOffsetInt + ">" + opcodeStr + ": " + instructionStr
                  console.log(instructionFullLogStr)
                  // 0x252c0edf8 <+356>: br x10
                  // 0x252c0edf8 <+356> 40 01 1F D6: br x10

                  if (curOffsetInt in hookFuncMap){
                    console.log("offset: " + curOffsetHexPtr + "=" + curOffsetInt)
                    // let curHookFunc = hookFuncMap.get(curOffsetInt)
                    var curHookFunc = hookFuncMap[curOffsetInt]
                    // console.log("curOffsetInt=" + curOffsetInt + " -> curHookFunc=" + curHookFunc)

                    // putCallout -> https://www.radare.org/doc/frida/interfaces/StalkerArmIterator.html#putCallout
                    // StalkerScriptCallout -> https://www.radare.org/doc/frida/types/StalkerScriptCallout.html
                    // CpuContext -> https://www.radare.org/doc/frida/types/CpuContext.html
                    // Arm64CpuContext -> https://www.radare.org/doc/frida/interfaces/Arm64CpuContext.html

                    // work: normal
                    iterator.putCallout(curHookFunc)

                    // var extraDataDict = {
                    //   "curOffsetInt": curOffsetInt
                    // }
                    // Not work: abnormal
                    // iterator.putCallout((context) => {
                    // // iterator.putCallout((context, extraDataDict) => {
                    //   // console.log("match offset: " + curOffsetHexPtr + ", curRealAddr=" + curRealAddr)
                    //   // curHookFunc(context, curOffsetInt, moduleBaseAddress)
                    //   // context.curOffsetInt = curOffsetInt
                    //   // context.curOffsetHexPtr = curOffsetHexPtr
                    //   // context.moduleBaseAddress = moduleBaseAddress
                    //   // context[curOffsetInt] = curOffsetInt
                    //   // context[curOffsetHexPtr] = curOffsetHexPtr
                    //   // context[moduleBaseAddress] = moduleBaseAddress
                    //   // curHookFunc(context, extraDataDict)
                    //   curHookFunc(context)
                    // })
                  }

                }
                iterator.keep()
              } while ((instruction = iterator.next()) !== null)
            }
        });

        // function needDebug(context) {
        //     console.log("into needDebug")
        //     // console.log("into needDebug: context=" + context)
        //     // var contextStr = JSON.stringify(context, null, 2)
        //     // console.log("context=" + contextStr)
        //     // var x9Value1 = context.x9
        //     // var x9Value2 = context["x9"]
        //     // console.log("x9Value1=" + x9Value1 + ", x9Value2=" + x9Value2)
        // }
      },
      onLeave: function(retval) {
        console.log("addr: relative [" + funcRelativeStartAddrHexStr + "] real [" + funcRealStartAddr + "] -> retval=" + retval)
        if (curTid != null) {
          Stalker.unfollow(curTid)
          console.log("Stalker.unfollow curTid=", curTid)
        }
      }
    })
  }

}

/*******************************************************************************
 * Other Util
*******************************************************************************/

// function logMain(mainStr){
//   const mainDelimiter = "========================================"
//   console.log(mainDelimiter + " " + mainStr + " " + mainDelimiter)
// }

// function logSub(subStr){
//   const subDelimiter = "------------------------------"
//   console.log(subDelimiter + " " + subStr + " " + subDelimiter)
// }

/*******************************************************************************
 * Main Hook
*******************************************************************************/

function stalkerHookNative_vsPHbdGf(){
  // console.log("into stalkerHookNative_vsPHbdGf:")
  // logSub("into stalkerHookNative_vsPHbdGf")
  JsUtil.logStr("into stalkerHookNative_vsPHbdGf", true, "-")

  var libraryName = "libInFieldCollection.dylib"

  // for debug
  // libraryName = "mobileactivationd"

  const moduleBaseAddress = Module.findBaseAddress(libraryName)
  console.log("libraryName=" + libraryName + " -> moduleBaseAddress=" + moduleBaseAddress)
  if (null == moduleBaseAddress) {
    console.error("Failed to find library " + libraryName)
    return
  }

  var funcName = "vsPHbdGf"

  // for debug
  // -[MACollectionInterface copyIngestData:]    __text    00000001000067B4    00000D84    00000270        R    .    .    .    .    .    B    T    .
  // funcName = "-[MACollectionInterface copyIngestData:]"
  // funcName = "DERDecodeItem"
  // funcName = "mach_msg"

  var origFuncPtr = Module.findExportByName(libraryName, funcName)
  console.log("origFuncPtr=" + origFuncPtr)

  if (null == origFuncPtr) {
    console.error("Failed to find function " + funcName + "in lib " + libraryName)
    return
  }

  var funcRelativeStartAddr = origFuncPtr - moduleBaseAddress
  console.log("funcRelativeStartAddr=" + funcRelativeStartAddr + "=" + JsUtil.intToHexStr(funcRelativeStartAddr))

  // for debug
  /*
    [iPhone::mobileactivationd ]-> ============ Trigged addr: relative [0x13c94] = real [0x1c280ec94]  ============
    ...
    +++ into iterator: startAddress=0x1c2813d78, isAppCode=true
    current: realAddr=0x1c2813d78 -> offset: hex=0x50e4=20708
        0x1c2813d78 <+20708>: str x0, [sp, #0xc8]
    current: realAddr=0x1c2813d7c -> offset: hex=0x50e8=20712
        0x1c2813d7c <+20712>: bl #0x1c2842d88
  */
  // // use later address as start address, try to avoid only hook part code == not hook all code
  // funcRelativeStartAddr = funcRelativeStartAddr + 0x50e4

  var functionSize = 0x61FC
  // for debug: make larger, tyr to support hook more code
  // var functionSize = 0x10000

  // CollectPCRT == void __fastcall vsPHbdGf(__int64 a1, __int64 a2)
  var argNum = 2
  console.log("functionSize=" + functionSize + "=" + JsUtil.intToHexStr(functionSize) + ", argNum=" + argNum)

  // try exclude not-concern functions inside common libs

  // // var moduleName_libObjc = "/usr/lib/libobjc.A.dylib"
  // var moduleName_libObjc = "libobjc.A.dylib"
  // // FridaUtil.printModuleInfo(moduleName_libObjc)
  // var module_libObjc = Process.getModuleByName(moduleName_libObjc)
  // console.log("module_libObjc=" + module_libObjc)
  // if (null != module_libObjc) {
  //   FridaUtil.printModuleBasicInfo(module_libObjc)

  //   Stalker.exclude(module_libObjc)
  // }

  // // var moduleName_system =
  // var moduleName_system = "libSystem.B.dylib"
  // // FridaUtil.printModuleInfo(moduleName_system)
  // var module_system = Process.getModuleByName(moduleName_system)
  // console.log("module_system=" + module_system)
  // if (null != module_system) {
  //   FridaUtil.printModuleBasicInfo(module_system)

  //   Stalker.exclude(module_system)
  // }

  // var moduleName_MobileGestalt = "libMobileGestalt.dylib"
  // var module_MobileGestalt = Process.getModuleByName(moduleName_MobileGestalt)
  // console.log("module_MobileGestalt=" + module_MobileGestalt)
  // if (null != module_MobileGestalt) {
  //   FridaUtil.printModuleBasicInfo(module_MobileGestalt)
  // }

  // var moduleName_IOKit = "IOKit"
  // var module_IOKit = Process.getModuleByName(moduleName_IOKit)
  // console.log("module_IOKit=" + module_IOKit)
  // if (null != module_IOKit) {
  //   FridaUtil.printModuleBasicInfo(module_IOKit)
  // }

  // var moduleName_Foundation = "Foundation"
  // var module_Foundation = Process.getModuleByName(moduleName_Foundation)
  // console.log("module_Foundation=" + module_Foundation)
  // if (null != module_Foundation) {
  //   FridaUtil.printModuleBasicInfo(module_Foundation)
  // }

  // var moduleName_CoreFoundation = "CoreFoundation"
  // var module_CoreFoundation = Process.getModuleByName(moduleName_CoreFoundation)
  // console.log("module_CoreFoundation=" + module_CoreFoundation)
  // if (null != module_CoreFoundation) {
  //   FridaUtil.printModuleBasicInfo(module_CoreFoundation)
  // }

  // FridaUtil.printModuleInfoAndStalkerExclude("libobjc.A.dylib") // /usr/lib/libobjc.A.dylib
  // FridaUtil.printModuleInfoAndStalkerExclude("libSystem.B.dylib") // /usr/lib/libSystem.B.dylib
  // FridaUtil.printModuleInfoAndStalkerExclude("libsystem_malloc.dylib") // /usr/lib/system/libsystem_malloc.dylib

  FridaUtil.printAllLoadedModules()

  var toExcludeModuleList = [
    "libobjc.A.dylib", // /usr/lib/libobjc.A.dylib
    "libSystem.B.dylib", // /usr/lib/libSystem.B.dylib
    "libsystem_malloc.dylib", // /usr/lib/system/libsystem_malloc.dylib
    "libsystem_m.dylib", // /usr/lib/system/libsystem_m.dylib
    "libsystem_networkextension.dylib", // /usr/lib/system/libsystem_networkextension.dylib
    "libsystem_notify.dylib", // /usr/lib/system/libsystem_notify.dylib
    "libsystem_sandbox.dylib", // /usr/lib/system/libsystem_sandbox.dylib
    "libsystem_kernel.dylib", // /usr/lib/system/libsystem_kernel.dylib
    "libsystem_platform.dylib", // /usr/lib/system/libsystem_platform.dylib
    "libsystem_pthread.dylib", // /usr/lib/system/libsystem_pthread.dylib
    "libsystem_symptoms.dylib", // /usr/lib/system/libsystem_symptoms.dylib
    "libsystem_trace.dylib", // /usr/lib/system/libsystem_trace.dylib
    "libunwind.dylib", // /usr/lib/system/libunwind.dylib
    "libxpc.dylib", // /usr/lib/system/libxpc.dylib

    // Module: address=[0x19a60a000-0x19a60f000], name=libcache.dylib, size=0x5000=20480, path=/usr/lib/system/libcache.dylib
    "libcache.dylib",
    // Module: address=[0x19a60f000-0x19a61b000], name=libcommonCrypto.dylib, size=0xc000=49152, path=/usr/lib/system/libcommonCrypto.dylib
    "libcommonCrypto.dylib",
    // Module: address=[0x19a61b000-0x19a620000], name=libcompiler_rt.dylib, size=0x5000=20480, path=/usr/lib/system/libcompiler_rt.dylib
    "libcompiler_rt.dylib",
    // Module: address=[0x19a620000-0x19a629000], name=libcopyfile.dylib, size=0x9000=36864, path=/usr/lib/system/libcopyfile.dylib
    "libcopyfile.dylib",
    // Module: address=[0x19a629000-0x19a68d000], name=libcorecrypto.dylib, size=0x64000=409600, path=/usr/lib/system/libcorecrypto.dylib
    "libcorecrypto.dylib",
    // Module: address=[0x19a68d000-0x19a6fd000], name=libdispatch.dylib, size=0x70000=458752, path=/usr/lib/system/libdispatch.dylib
    "libdispatch.dylib",
    // Module: address=[0x19a6fd000-0x19a727000], name=libdyld.dylib, size=0x2a000=172032, path=/usr/lib/system/libdyld.dylib
    "libdyld.dylib",

    // Module: address=[0x22ab49000-0x22abcb000], name=libsystem_c.dylib, size=0x82000=532480, path=/usr/lib/system/libsystem_c.dylib
    "libsystem_c.dylib",
    // Module: address=[0x22af96000-0x22b2f5000], name=CoreFoundation, size=0x35f000=3534848, path=/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation
    "CoreFoundation",
    // Module: address=[0x101720000-0x10172c000], name=MAMock.dylib, size=0xc000=49152, path=/Library/MobileSubstrate/DynamicLibraries/MAMock.dylib
    "MAMock.dylib",

    // // Module: address=[0x22b61f000-0x22b654000], name=libMobileGestalt.dylib, size=0x35000=217088, path=/usr/lib/libMobileGestalt.dylib
    // "libMobileGestalt.dylib",
  ]
  for(var i = 0; i < toExcludeModuleList.length; i++) {
    // console.log("---------- Module [" + i + "]----------")
    var curModule = toExcludeModuleList[i]

    FridaUtil.printModuleInfoAndStalkerExclude(curModule)
  }

  let hookFuncMap = {
    0x164: // +356
      function (context) {
        var contextStr = JSON.stringify(context)
        console.log("[0x164] contextStr=" + contextStr)
        var x10 = context.x10
        console.log("[0x164] x10=" + x10)
      },
    0x1DC: // +476
      function (context) {
        var contextStr = JSON.stringify(context)
        console.log("[0x1DC] contextStr=" + contextStr)
        var x10 = context.x10
        console.log("[0x1DC] x10=" + x10)
      },
  }

  FridaUtil.isShowOpcode = false
  FridaUtil.stalkerHookUnnameNative(moduleBaseAddress, funcRelativeStartAddr, functionSize, argNum, hookFuncMap)
}

function hookNative(){
  // console.log("into hookNative:")
  // logMain("into hookNative")
  JsUtil.logStr("into hookNative")
  stalkerHookNative_vsPHbdGf()
}

hookNative()

输出日志

部分调试输出日志：

➜  frida_stalker frida -U -n mobileactivationd -l fridaStalker_vsPHbdGf.js
     ____
    / _  |   Frida 16.5.9 - A world-class dynamic instrumentation toolkit
   | (_| |
    > _  |   Commands:
   /_/ |_|       help      -> Displays the help system
   . . . .       object?   -> Display information about 'object'
   . . . .       exit/quit -> Exit
   . . . .
   . . . .   More info at https://frida.re/docs/home/
   . . . .
   . . . .   Connected to iPhone (id=9bad8d3c9530bd2fc62072c30ee3accf3cdc45d6)
Attaching...
=============================== into hookNative  ===============================
----------------------- into stalkerHookNative_vsPHbdGf  -----------------------
libraryName=libInFieldCollection.dylib -> moduleBaseAddress=null
Failed to find library libInFieldCollection.dylib
[iPhone::mobileactivationd ]-> %reload
=============================== into hookNative  ===============================
----------------------- into stalkerHookNative_vsPHbdGf  -----------------------
libraryName=libInFieldCollection.dylib -> moduleBaseAddress=null
Failed to find library libInFieldCollection.dylib
[iPhone::mobileactivationd ]-> %reload
=============================== into hookNative  ===============================
----------------------- into stalkerHookNative_vsPHbdGf  -----------------------
libraryName=libInFieldCollection.dylib -> moduleBaseAddress=null
Failed to find library libInFieldCollection.dylib
[iPhone::mobileactivationd ]-> %reload
=============================== into hookNative  ===============================
----------------------- into stalkerHookNative_vsPHbdGf  -----------------------
libraryName=libInFieldCollection.dylib -> moduleBaseAddress=null
Failed to find library libInFieldCollection.dylib
[iPhone::mobileactivationd ]-> %reload
=============================== into hookNative  ===============================
----------------------- into stalkerHookNative_vsPHbdGf  -----------------------
libraryName=libInFieldCollection.dylib -> moduleBaseAddress=0x252bfb000
origFuncPtr=0x252c0ec94
funcRelativeStartAddr=81044
functionSize=25084=0x61fc, argNum=2
Process: id=9871, currentThreadId=11303, currentDir=/, homeDir=/var/mobile, tmpDir=/var/tmp, arch=arm64, platform=darwin, pageSize=16384, pointerSize=8, codeSigningPolicy=optional, isDebuggerAttached=false
  Module: address=[0x100620000-0x10082c000], name=mobileactivationd, size=0x20c000=2146304, path=/usr/libexec/mobileactivationd
  Module: address=[0x100884000-0x100888000], name=MobileSubstrate.dylib, size=0x4000=16384, path=/Library/MobileSubstrate/MobileSubstrate.dylib
  Module: address=[0x1008cc000-0x1008d0000], name=SubstrateInserter.dylib, size=0x4000=16384, path=/usr/lib/substrate/SubstrateInserter.dylib
  Module: address=[0x100a00000-0x100a18000], name=SubstrateLoader.dylib, size=0x18000=98304, path=/usr/lib/substrate/SubstrateLoader.dylib
  Module: address=[0x100a44000-0x100a9c000], name=dyld, size=0x58000=360448, path=/usr/lib/dyld
  Module: address=[0x100b44000-0x100b50000], name=MAMock.dylib, size=0xc000=49152, path=/Library/MobileSubstrate/DynamicLibraries/MAMock.dylib
  Module: address=[0x100d00000-0x100e14000], name=libsubstrate.dylib, size=0x114000=1130496, path=/usr/lib/libsubstrate.dylib
  Module: address=[0x22a217000-0x22a219000], name=libSystem.B.dylib, size=0x2000=8192, path=/usr/lib/libSystem.B.dylib
  Module: address=[0x22a219000-0x22a26f000], name=libc++.1.dylib, size=0x56000=352256, path=/usr/lib/libc++.1.dylib
  Module: address=[0x22a26f000-0x22a282000], name=libc++abi.dylib, size=0x13000=77824, path=/usr/lib/libc++abi.dylib
  Module: address=[0x22a282000-0x22aa0a000], name=libobjc.A.dylib, size=0x788000=7897088, path=/usr/lib/libobjc.A.dylib
  Module: address=[0x22aa0a000-0x22aa0f000], name=libcache.dylib, size=0x5000=20480, path=/usr/lib/system/libcache.dylib
  Module: address=[0x22aa0f000-0x22aa1b000], name=libcommonCrypto.dylib, size=0xc000=49152, path=/usr/lib/system/libcommonCrypto.dylib
  Module: address=[0x22aa1b000-0x22aa20000], name=libcompiler_rt.dylib, size=0x5000=20480, path=/usr/lib/system/libcompiler_rt.dylib
...
  Module: address=[0x22cbc2000-0x22cbc3000], name=vecLib, size=0x1000=4096, path=/System/Library/Frameworks/Accelerate.framework/Frameworks/vecLib.framework/vecLib
...
  Module: address=[0x252bfb000-0x252c51000], name=libInFieldCollection.dylib, size=0x56000=352256, path=/usr/lib/libInFieldCollection.dylib
  Module: address=[0x252c62000-0x252c70000], name=libMobileGestaltExtensions.dylib, size=0xe000=57344, path=/usr/lib/libMobileGestaltExtensions.dylib
...
  Module: address=[0x256365000-0x2563fa000], name=SampleAnalysis, size=0x95000=610304, path=/System/Library/PrivateFrameworks/SampleAnalysis.framework/SampleAnalysis
---------- Module [0]----------
moduleName=libobjc.A.dylib -> foundModule=[object Object]
Stalker.exclude for: Module: address=[0x22a282000-0x22aa0a000], name=libobjc.A.dylib, size=0x788000=7897088, path=/usr/lib/libobjc.A.dylib
---------- Module [1]----------
moduleName=libSystem.B.dylib -> foundModule=[object Object]
Stalker.exclude for: Module: address=[0x22a217000-0x22a219000], name=libSystem.B.dylib, size=0x2000=8192, path=/usr/lib/libSystem.B.dylib
---------- Module [2]----------
moduleName=libsystem_malloc.dylib -> foundModule=[object Object]
Stalker.exclude for: Module: address=[0x22ac81000-0x22aca4000], name=libsystem_malloc.dylib, size=0x23000=143360, path=/usr/lib/system/libsystem_malloc.dylib
---------- Module [3]----------
moduleName=libsystem_m.dylib -> foundModule=[object Object]
Stalker.exclude for: Module: address=[0x22ac53000-0x22ac81000], name=libsystem_m.dylib, size=0x2e000=188416, path=/usr/lib/system/libsystem_m.dylib
---------- Module [4]----------
moduleName=libsystem_networkextension.dylib -> foundModule=[object Object]
Stalker.exclude for: Module: address=[0x22aca4000-0x22acb0000], name=libsystem_networkextension.dylib, size=0xc000=49152, path=/usr/lib/system/libsystem_networkextension.dylib
---------- Module [5]----------
moduleName=libsystem_notify.dylib -> foundModule=[object Object]
Stalker.exclude for: Module: address=[0x22acb0000-0x22acb7000], name=libsystem_notify.dylib, size=0x7000=28672, path=/usr/lib/system/libsystem_notify.dylib
---------- Module [6]----------
moduleName=libsystem_sandbox.dylib -> foundModule=[object Object]
Stalker.exclude for: Module: address=[0x22acd3000-0x22acd6000], name=libsystem_sandbox.dylib, size=0x3000=12288, path=/usr/lib/system/libsystem_sandbox.dylib
---------- Module [7]----------
moduleName=libsystem_kernel.dylib -> foundModule=[object Object]
Stalker.exclude for: Module: address=[0x22ac28000-0x22ac53000], name=libsystem_kernel.dylib, size=0x2b000=176128, path=/usr/lib/system/libsystem_kernel.dylib
---------- Module [8]----------
moduleName=libsystem_platform.dylib -> foundModule=[object Object]
Stalker.exclude for: Module: address=[0x22acb7000-0x22acc2000], name=libsystem_platform.dylib, size=0xb000=45056, path=/usr/lib/system/libsystem_platform.dylib
---------- Module [9]----------
moduleName=libsystem_pthread.dylib -> foundModule=[object Object]
Stalker.exclude for: Module: address=[0x22acc2000-0x22acd3000], name=libsystem_pthread.dylib, size=0x11000=69632, path=/usr/lib/system/libsystem_pthread.dylib
---------- Module [10]----------
moduleName=libsystem_symptoms.dylib -> foundModule=[object Object]
Stalker.exclude for: Module: address=[0x22acd6000-0x22acde000], name=libsystem_symptoms.dylib, size=0x8000=32768, path=/usr/lib/system/libsystem_symptoms.dylib
---------- Module [11]----------
moduleName=libsystem_trace.dylib -> foundModule=[object Object]
Stalker.exclude for: Module: address=[0x22acde000-0x22acf4000], name=libsystem_trace.dylib, size=0x16000=90112, path=/usr/lib/system/libsystem_trace.dylib
---------- Module [12]----------
moduleName=libunwind.dylib -> foundModule=[object Object]
Stalker.exclude for: Module: address=[0x22acf4000-0x22acfa000], name=libunwind.dylib, size=0x6000=24576, path=/usr/lib/system/libunwind.dylib
---------- Module [13]----------
moduleName=libxpc.dylib -> foundModule=[object Object]
Stalker.exclude for: Module: address=[0x22acfa000-0x22ad28000], name=libxpc.dylib, size=0x2e000=188416, path=/usr/lib/system/libxpc.dylib
---------- Module [14]----------
moduleName=libcache.dylib -> foundModule=[object Object]
Stalker.exclude for: Module: address=[0x22aa0a000-0x22aa0f000], name=libcache.dylib, size=0x5000=20480, path=/usr/lib/system/libcache.dylib
---------- Module [15]----------
moduleName=libcommonCrypto.dylib -> foundModule=[object Object]
Stalker.exclude for: Module: address=[0x22aa0f000-0x22aa1b000], name=libcommonCrypto.dylib, size=0xc000=49152, path=/usr/lib/system/libcommonCrypto.dylib
---------- Module [16]----------
moduleName=libcompiler_rt.dylib -> foundModule=[object Object]
Stalker.exclude for: Module: address=[0x22aa1b000-0x22aa20000], name=libcompiler_rt.dylib, size=0x5000=20480, path=/usr/lib/system/libcompiler_rt.dylib
---------- Module [17]----------
moduleName=libcopyfile.dylib -> foundModule=[object Object]
Stalker.exclude for: Module: address=[0x22aa20000-0x22aa29000], name=libcopyfile.dylib, size=0x9000=36864, path=/usr/lib/system/libcopyfile.dylib
---------- Module [18]----------
moduleName=libcorecrypto.dylib -> foundModule=[object Object]
Stalker.exclude for: Module: address=[0x22aa29000-0x22aa8d000], name=libcorecrypto.dylib, size=0x64000=409600, path=/usr/lib/system/libcorecrypto.dylib
---------- Module [19]----------
moduleName=libdispatch.dylib -> foundModule=[object Object]
Stalker.exclude for: Module: address=[0x22aa8d000-0x22aafd000], name=libdispatch.dylib, size=0x70000=458752, path=/usr/lib/system/libdispatch.dylib
---------- Module [20]----------
moduleName=libdyld.dylib -> foundModule=[object Object]
Stalker.exclude for: Module: address=[0x22aafd000-0x22ab27000], name=libdyld.dylib, size=0x2a000=172032, path=/usr/lib/system/libdyld.dylib
---------- Module [21]----------
moduleName=libsystem_c.dylib -> foundModule=[object Object]
Stalker.exclude for: Module: address=[0x22ab49000-0x22abcb000], name=libsystem_c.dylib, size=0x82000=532480, path=/usr/lib/system/libsystem_c.dylib
---------- Module [22]----------
moduleName=CoreFoundation -> foundModule=[object Object]
Stalker.exclude for: Module: address=[0x22af96000-0x22b2f5000], name=CoreFoundation, size=0x35f000=3534848, path=/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation
---------- Module [23]----------
moduleName=MAMock.dylib -> foundModule=[object Object]
Stalker.exclude for: Module: address=[0x100b44000-0x100b50000], name=MAMock.dylib, size=0xc000=49152, path=/Library/MobileSubstrate/DynamicLibraries/MAMock.dylib
Frida Stalker hook: module: baseAddress=0x252bfb000
function: relativeStartAddr=0x13c94, size=25084=0x61fc, relativeEndAddr=0x19e90
funcRealStartAddr=0x252c0ec94, funcRealEndAddr=0x252c14e90
curTid=null
[iPhone::mobileactivationd ]-> ============ Trigged addr: relative [0x13c94] = real [0x252c0ec94]  ============
arg[0]=0x16f866988
arg[1]=0x16f866984
curTid=21011
+++ into iterator: startAddress=0x10f3c1768, isAppCode=false
+++ into iterator: startAddress=0x10f3c1778, isAppCode=false
...
+++ into iterator: startAddress=0x11074c030, isAppCode=false
+++ into iterator: startAddress=0x252c0eca4, isAppCode=true
Instruction: address=0x252c0eca4,toString()=stp x20, x19, [sp, #0x40],next=0x4,size=4,mnemonic=stp,opStr=x20, x19, [sp, #0x40],operands=[{"type":"reg","value":"x20","access":"r"},{"type":"reg","value":"x19","access":"r"},{"type":"mem","value":{"base":"sp","disp":64},"access":"rw"}],regsAccessed={"read":["x20","x19","sp"],"written":[]},regsRead=[],regsWritten=[],groups=[],toJSON()={"address":"0x252c0eca4","next":"0x4","size":4,"mnemonic":"stp","opStr":"x20, x19, [sp, #0x40]","operands":[{"type":"reg","value":"x20","access":"r"},{"type":"reg","value":"x19","access":"r"},{"type":"mem","value":{"base":"sp","disp":64},"access":"rw"}],"regsAccessed":{"read":["x20","x19","sp"],"written":[]},"regsRead":[],"regsWritten":[],"groups":[]}
current: realAddr=0x252c0eca4 -> offset: hex=0x10=16
    0x252c0eca4 <+16>: stp x20, x19, [sp, #0x40]
Instruction: address=0x252c0eca8,toString()=stp x29, x30, [sp, #0x50],next=0x4,size=4,mnemonic=stp,opStr=x29, x30, [sp, #0x50],operands=[{"type":"reg","value":"fp","access":"r"},{"type":"reg","value":"lr","access":"r"},{"type":"mem","value":{"base":"sp","disp":80},"access":"rw"}],regsAccessed={"read":["fp","lr","sp"],"written":[]},regsRead=[],regsWritten=[],groups=[],toJSON()={"address":"0x252c0eca8","next":"0x4","size":4,"mnemonic":"stp","opStr":"x29, x30, [sp, #0x50]","operands":[{"type":"reg","value":"fp","access":"r"},{"type":"reg","value":"lr","access":"r"},{"type":"mem","value":{"base":"sp","disp":80},"access":"rw"}],"regsAccessed":{"read":["fp","lr","sp"],"written":[]},"regsRead":[],"regsWritten":[],"groups":[]}
current: realAddr=0x252c0eca8 -> offset: hex=0x14=20
    0x252c0eca8 <+20>: stp x29, x30, [sp, #0x50]
Instruction: address=0x252c0ecac,toString()=add x29, sp, #0x50,next=0x4,size=4,mnemonic=add,opStr=x29, sp, #0x50,operands=[{"type":"reg","value":"fp","access":"w"},{"type":"reg","value":"sp","access":"r"},{"type":"imm","value":"80","access":"r"}],regsAccessed={"read":["sp"],"written":["fp"]},regsRead=[],regsWritten=[],groups=[],toJSON()={"address":"0x252c0ecac","next":"0x4","size":4,"mnemonic":"add","opStr":"x29, sp, #0x50","operands":[{"type":"reg","value":"fp","access":"w"},{"type":"reg","value":"sp","access":"r"},{"type":"imm","value":"80","access":"r"}],"regsAccessed":{"read":["sp"],"written":["fp"]},"regsRead":[],"regsWritten":[],"groups":[]}
current: realAddr=0x252c0ecac -> offset: hex=0x18=24
    0x252c0ecac <+24>: add x29, sp, #0x50
Instruction: address=0x252c0ecb0,toString()=sub sp, sp, #1, lsl #12,next=0x4,size=4,mnemonic=sub,opStr=sp, sp, #1, lsl #12,operands=[{"type":"reg","value":"sp","access":"w"},{"type":"reg","value":"sp","access":"r"},{"type":"imm","value":"1","shift":{"type":"lsl","value":12},"access":"r"}],regsAccessed={"read":["sp"],"written":["sp"]},regsRead=[],regsWritten=[],groups=[],toJSON()={"address":"0x252c0ecb0","next":"0x4","size":4,"mnemonic":"sub","opStr":"sp, sp, #1, lsl #12","operands":[{"type":"reg","value":"sp","access":"w"},{"type":"reg","value":"sp","access":"r"},{"type":"imm","value":"1","shift":{"type":"lsl","value":12},"access":"r"}],"regsAccessed":{"read":["sp"],"written":["sp"]},"regsRead":[],"regsWritten":[],"groups":[]}
current: realAddr=0x252c0ecb0 -> offset: hex=0x1c=28
    0x252c0ecb0 <+28>: sub sp, sp, #1, lsl #12
Instruction: address=0x252c0ecb4,toString()=sub sp, sp, #0xf00,next=0x4,size=4,mnemonic=sub,opStr=sp, sp, #0xf00,operands=[{"type":"reg","value":"sp","access":"w"},{"type":"reg","value":"sp","access":"r"},{"type":"imm","value":"3840","access":"r"}],regsAccessed={"read":["sp"],"written":["sp"]},regsRead=[],regsWritten=[],groups=[],toJSON()={"address":"0x252c0ecb4","next":"0x4","size":4,"mnemonic":"sub","opStr":"sp, sp, #0xf00","operands":[{"type":"reg","value":"sp","access":"w"},{"type":"reg","value":"sp","access":"r"},{"type":"imm","value":"3840","access":"r"}],"regsAccessed":{"read":["sp"],"written":["sp"]},"regsRead":[],"regsWritten":[],"groups":[]}
current: realAddr=0x252c0ecb4 -> offset: hex=0x20=32
    0x252c0ecb4 <+32>: sub sp, sp, #0xf00
Instruction: address=0x252c0ecb8,toString()=str x1, [sp, #0x88],next=0x4,size=4,mnemonic=str,opStr=x1, [sp, #0x88],operands=[{"type":"reg","value":"x1","access":"r"},{"type":"mem","value":{"base":"sp","disp":136},"access":"rw"}],regsAccessed={"read":["x1","sp"],"written":[]},regsRead=[],regsWritten=[],groups=[],toJSON()={"address":"0x252c0ecb8","next":"0x4","size":4,"mnemonic":"str","opStr":"x1, [sp, #0x88]","operands":[{"type":"reg","value":"x1","access":"r"},{"type":"mem","value":{"base":"sp","disp":136},"access":"rw"}],"regsAccessed":{"read":["x1","sp"],"written":[]},"regsRead":[],"regsWritten":[],"groups":[]}
current: realAddr=0x252c0ecb8 -> offset: hex=0x24=36
    0x252c0ecb8 <+36>: str x1, [sp, #0x88]
Instruction: address=0x252c0ecbc,toString()=str x0, [sp, #0xa8],next=0x4,size=4,mnemonic=str,opStr=x0, [sp, #0xa8],operands=[{"type":"reg","value":"x0","access":"r"},{"type":"mem","value":{"base":"sp","disp":168},"access":"rw"}],regsAccessed={"read":["x0","sp"],"written":[]},regsRead=[],regsWritten=[],groups=[],toJSON()={"address":"0x252c0ecbc","next":"0x4","size":4,"mnemonic":"str","opStr":"x0, [sp, #0xa8]","operands":[{"type":"reg","value":"x0","access":"r"},{"type":"mem","value":{"base":"sp","disp":168},"access":"rw"}],"regsAccessed":{"read":["x0","sp"],"written":[]},"regsRead":[],"regsWritten":[],"groups":[]}
current: realAddr=0x252c0ecbc -> offset: hex=0x28=40
    0x252c0ecbc <+40>: str x0, [sp, #0xa8]
Instruction: address=0x252c0ecc0,toString()=add x28, sp, #0x428,next=0x4,size=4,mnemonic=add,opStr=x28, sp, #0x428,operands=[{"type":"reg","value":"x28","access":"w"},{"type":"reg","value":"sp","access":"r"},{"type":"imm","value":"1064","access":"r"}],regsAccessed={"read":["sp"],"written":["x28"]},regsRead=[],regsWritten=[],groups=[],toJSON()={"address":"0x252c0ecc0","next":"0x4","size":4,"mnemonic":"add","opStr":"x28, sp, #0x428","operands":[{"type":"reg","value":"x28","access":"w"},{"type":"reg","value":"sp","access":"r"},{"type":"imm","value":"1064","access":"r"}],"regsAccessed":{"read":["sp"],"written":["x28"]},"regsRead":[],"regsWritten":[],"groups":[]}
current: realAddr=0x252c0ecc0 -> offset: hex=0x2c=44
    0x252c0ecc0 <+44>: add x28, sp, #0x428
Instruction: address=0x252c0ecc4,toString()=add x23, sp, #0x315,next=0x4,size=4,mnemonic=add,opStr=x23, sp, #0x315,operands=[{"type":"reg","value":"x23","access":"w"},{"type":"reg","value":"sp","access":"r"},{"type":"imm","value":"789","access":"r"}],regsAccessed={"read":["sp"],"written":["x23"]},regsRead=[],regsWritten=[],groups=[],toJSON()={"address":"0x252c0ecc4","next":"0x4","size":4,"mnemonic":"add","opStr":"x23, sp, #0x315","operands":[{"type":"reg","value":"x23","access":"w"},{"type":"reg","value":"sp","access":"r"},{"type":"imm","value":"789","access":"r"}],"regsAccessed":{"read":["sp"],"written":["x23"]},"regsRead":[],"regsWritten":[],"groups":[]}
current: realAddr=0x252c0ecc4 -> offset: hex=0x30=48
    0x252c0ecc4 <+48>: add x23, sp, #0x315
Instruction: address=0x252c0ecc8,toString()=add x26, sp, #0x158,next=0x4,size=4,mnemonic=add,opStr=x26, sp, #0x158,operands=[{"type":"reg","value":"x26","access":"w"},{"type":"reg","value":"sp","access":"r"},{"type":"imm","value":"344","access":"r"}],regsAccessed={"read":["sp"],"written":["x26"]},regsRead=[],regsWritten=[],groups=[],toJSON()={"address":"0x252c0ecc8","next":"0x4","size":4,"mnemonic":"add","opStr":"x26, sp, #0x158","operands":[{"type":"reg","value":"x26","access":"w"},{"type":"reg","value":"sp","access":"r"},{"type":"imm","value":"344","access":"r"}],"regsAccessed":{"read":["sp"],"written":["x26"]},"regsRead":[],"regsWritten":[],"groups":[]}
current: realAddr=0x252c0ecc8 -> offset: hex=0x34=52

...

    0x252c0edf0 <+348>: add x10, x8, x10
Instruction: address=0x252c0edf4,toString()=add w8, w9, #1,next=0x4,size=4,mnemonic=add,opStr=w8, w9, #1,operands=[{"type":"reg","value":"w8","access":"w"},{"type":"reg","value":"w9","access":"r"},{"type":"imm","value":"1","access":"r"}],regsAccessed={"read":["w9"],"written":["w8"]},regsRead=[],regsWritten=[],groups=[],toJSON()={"address":"0x252c0edf4","next":"0x4","size":4,"mnemonic":"add","opStr":"w8, w9, #1","operands":[{"type":"reg","value":"w8","access":"w"},{"type":"reg","value":"w9","access":"r"},{"type":"imm","value":"1","access":"r"}],"regsAccessed":{"read":["w9"],"written":["w8"]},"regsRead":[],"regsWritten":[],"groups":[]}
current: realAddr=0x252c0edf4 -> offset: hex=0x160=352
    0x252c0edf4 <+352>: add w8, w9, #1
Instruction: address=0x252c0edf8,toString()=br x10,next=0x4,size=4,mnemonic=br,opStr=x10,operands=[{"type":"reg","value":"x10","access":"r"}],regsAccessed={"read":["x10"],"written":[]},regsRead=[],regsWritten=[],groups=["jump"],toJSON()={"address":"0x252c0edf8","next":"0x4","size":4,"mnemonic":"br","opStr":"x10","operands":[{"type":"reg","value":"x10","access":"r"}],"regsAccessed":{"read":["x10"],"written":[]},"regsRead":[],"regsWritten":[],"groups":["jump"]}
current: realAddr=0x252c0edf8 -> offset: hex=0x164=356
    0x252c0edf8 <+356>: br x10
offset: 0x164=356
[0x164] contextStr={"pc":"0x252c0edf8","sp":"0x16f864a10","nzcv":536870912,"x0":"0x58eef7c8","x1":"0x16f866984","x2":"0x16f8669c8","x3":"0x1","x4":"0x100c71750","x5":"0x8","x6":"0x64","x7":"0x0","x8":"0x7","x9":"0x6","x10":"0x252c0ee00","x11":"0x6","x12":"0x2668d857","x13":"0x0","x14":"0x10082738d","x15":"0x2648f095a","x16":"0x252c4ea00","x17":"0xa711087f","x18":"0x0","x19":"0x16f8669c8","x20":"0x100827377","x21":"0x100834018","x22":"0x0","x23":"0x16f864d25","x24":"0x399258cb","x25":"0x0","x26":"0x16f864b68","x27":"0x176dc56e","x28":"0x16f864e38","fp":"0x16f866960","lr":"0x11074c00c","q0":{},"q1":{},"q2":{},"q3":{},"q4":{},"q5":{},"q6":{},"q7":{},"q8":{},"q9":{},"q10":{},"q11":{},"q12":{},"q13":{},"q14":{},"q15":{},"q16":{},"q17":{},"q18":{},"q19":{},"q20":{},"q21":{},"q22":{},"q23":{},"q24":{},"q25":{},"q26":{},"q27":{},"q28":{},"q29":{},"q30":{},"q31":{},"d0":6.0132879286022618e-154,"d1":1.9999992847442624,"d2":7.9499288951273454e-275,"d3":0,"d4":0,"d5":0,"d6":0,"d7":0,"d8":0,"d9":0,"d10":0,"d11":0,"d12":0,"d13":0,"d14":0,"d15":0,"d16":-1.0855813867524649e+251,"d17":0.000002084565455e-308,"d18":3.0554698911305689e-152,"d19":0.000001322084152e-308,"d20":3.7696966457559071e-175,"d21":1.0004894955531618e+128,"d22":9.5944260775693913e+225,"d23":-6.8154492514793903e-236,"d24":-2.1930923744387854e+50,"d25":0,"d26":0,"d27":0,"d28":0,"d29":0,"d30":0,"d31":0,"s0":1.3563115067909484e-19,"s1":1.9999998807907104,"s2":3.8204714345426298e-37,"s3":0,"s4":0,"s5":0,"s6":0,"s7":0,"s8":0,"s9":0,"s10":0,"s11":0,"s12":0,"s13":0,"s14":0,"s15":0,"s16":1.5548730664783592e-21,"s17":-1.3084408235578860e+36,"s18":-8.6088756618229034e-23,"s19":-5.408784745233076e-20,"s20":4.2151578028428229e+37,"s21":18362722504671230,"s22":3.372155249992253e+28,"s23":-7.6784630118876258e-30,"s24":-3715189.5,"s25":0,"s26":0,"s27":0,"s28":0,"s29":0,"s30":0,"s31":0}
[0x164] x10=0x252c0ee00
+++ into iterator: startAddress=0x252c0ee00, isAppCode=true
Instruction: address=0x252c0ee00,toString()=mov w25, #0xddc9,next=0x4,size=4,mnemonic=mov,opStr=w25, #0xddc9,operands=[{"type":"reg","value":"w25","access":"w"},{"type":"imm","value":"56777","access":""}],regsAccessed={"read":[],"written":["w25"]},regsRead=[],regsWritten=[],groups=[],toJSON()={"address":"0x252c0ee00","next":"0x4","size":4,"mnemonic":"mov","opStr":"w25, #0xddc9","operands":[{"type":"reg","value":"w25","access":"w"},{"type":"imm","value":"56777","access":""}],"regsAccessed":{"read":[],"written":["w25"]},"regsRead":[],"regsWritten":[],"groups":[]}
current: realAddr=0x252c0ee00 -> offset: hex=0x16c=364
    0x252c0ee00 <+364>: mov w25, #0xddc9
Instruction: address=0x252c0ee04,toString()=movk w25, #0x6c8d, lsl #16,next=0x4,size=4,mnemonic=movk,opStr=w25, #0x6c8d, lsl #16,operands=[{"type":"reg","value":"w25","access":"rw"},{"type":"imm","value":"27789","shift":{"type":"lsl","value":16},"access":"r"}],regsAccessed={"read":["w25"],"written":["w25"]},regsRead=[],regsWritten=[],groups=[],toJSON()={"address":"0x252c0ee04","next":"0x4","size":4,"mnemonic":"movk","opStr":"w25, #0x6c8d, lsl #16","operands":[{"type":"reg","value":"w25","access":"rw"},{"type":"imm","value":"27789","shift":{"type":"lsl","value":16},"access":"r"}],"regsAccessed":{"read":["w25"],"written":["w25"]},"regsRead":[],"regsWritten":[],"groups":[]}
current: realAddr=0x252c0ee04 -> offset: hex=0x170=368

...

    0x252c13cd8 <+20548>: add x8, x8, x9
Instruction: address=0x252c13cdc,toString()=br x8,next=0x4,size=4,mnemonic=br,opStr=x8,operands=[{"type":"reg","value":"x8","access":"r"}],regsAccessed={"read":["x8"],"written":[]},regsRead=[],regsWritten=[],groups=["jump"],toJSON()={"address":"0x252c13cdc","next":"0x4","size":4,"mnemonic":"br","opStr":"x8","operands":[{"type":"reg","value":"x8","access":"r"}],"regsAccessed":{"read":["x8"],"written":[]},"regsRead":[],"regsWritten":[],"groups":["jump"]}
current: realAddr=0x252c13cdc -> offset: hex=0x5048=20552
    0x252c13cdc <+20552>: br x8
+++ into iterator: startAddress=0x252c13ce4, isAppCode=true
Instruction: address=0x252c13ce4,toString()=mov w22, #0xf6e,next=0x4,size=4,mnemonic=mov,opStr=w22, #0xf6e,operands=[{"type":"reg","value":"w22","access":"w"},{"type":"imm","value":"3950","access":""}],regsAccessed={"read":[],"written":["w22"]},regsRead=[],regsWritten=[],groups=[],toJSON()={"address":"0x252c13ce4","next":"0x4","size":4,"mnemonic":"mov","opStr":"w22, #0xf6e","operands":[{"type":"reg","value":"w22","access":"w"},{"type":"imm","value":"3950","access":""}],"regsAccessed":{"read":[],"written":["w22"]},"regsRead":[],"regsWritten":[],"groups":[]}
current: realAddr=0x252c13ce4 -> offset: hex=0x5050=20560
    0x252c13ce4 <+20560>: mov w22, #0xf6e
Instruction: address=0x252c13ce8,toString()=movk w22, #0x327e, lsl #16,next=0x4,size=4,mnemonic=movk,opStr=w22, #0x327e, lsl #16,operands=[{"type":"reg","value":"w22","access":"rw"},{"type":"imm","value":"12926","shift":{"type":"lsl","value":16},"access":"r"}],regsAccessed={"read":["w22"],"written":["w22"]},regsRead=[],regsWritten=[],groups=[],toJSON()={"address":"0x252c13ce8","next":"0x4","size":4,"mnemonic":"movk","opStr":"w22, #0x327e, lsl #16","operands":[{"type":"reg","value":"w22","access":"rw"},{"type":"imm","value":"12926","shift":{"type":"lsl","value":16},"access":"r"}],"regsAccessed":{"read":["w22"],"written":["w22"]},"regsRead":[],"regsWritten":[],"groups":[]}
current: realAddr=0x252c13ce8 -> offset: hex=0x5054=20564

...

    0x252c13d70 <+20700>: sub w25, w8, #0x2a
Instruction: address=0x252c13d74,toString()=bl #0x252c42e9c,next=0x4,size=4,mnemonic=bl,opStr=#0x252c42e9c,operands=[{"type":"imm","value":"9978523292","access":"r"}],regsAccessed={"read":[],"written":["lr"]},regsRead=[],regsWritten=["lr"],groups=["call","jump","branch_relative"],toJSON()={"address":"0x252c13d74","next":"0x4","size":4,"mnemonic":"bl","opStr":"#0x252c42e9c","operands":[{"type":"imm","value":"9978523292","access":"r"}],"regsAccessed":{"read":[],"written":["lr"]},"regsRead":[],"regsWritten":["lr"],"groups":["call","jump","branch_relative"]}
current: realAddr=0x252c13d74 -> offset: hex=0x50e0=20704
    0x252c13d74 <+20704>: bl #0x252c42e9c
+++ into iterator: startAddress=0x252c42e9c, isAppCode=false
+++ into iterator: startAddress=0x22ac914c0, isAppCode=false
+++ into iterator: startAddress=0x22ac914dc, isAppCode=false
+++ into iterator: startAddress=0x22ac914f0, isAppCode=false
+++ into iterator: startAddress=0x252c13d78, isAppCode=true
Instruction: address=0x252c13d78,toString()=str x0, [sp, #0xc8],next=0x4,size=4,mnemonic=str,opStr=x0, [sp, #0xc8],operands=[{"type":"reg","value":"x0","access":"r"},{"type":"mem","value":{"base":"sp","disp":200},"access":"rw"}],regsAccessed={"read":["x0","sp"],"written":[]},regsRead=[],regsWritten=[],groups=[],toJSON()={"address":"0x252c13d78","next":"0x4","size":4,"mnemonic":"str","opStr":"x0, [sp, #0xc8]","operands":[{"type":"reg","value":"x0","access":"r"},{"type":"mem","value":{"base":"sp","disp":200},"access":"rw"}],"regsAccessed":{"read":["x0","sp"],"written":[]},"regsRead":[],"regsWritten":[],"groups":[]}
current: realAddr=0x252c13d78 -> offset: hex=0x50e4=20708
    0x252c13d78 <+20708>: str x0, [sp, #0xc8]
Instruction: address=0x252c13d7c,toString()=bl #0x252c42d88,next=0x4,size=4,mnemonic=bl,opStr=#0x252c42d88,operands=[{"type":"imm","value":"9978523016","access":"r"}],regsAccessed={"read":[],"written":["lr"]},regsRead=[],regsWritten=["lr"],groups=["call","jump","branch_relative"],toJSON()={"address":"0x252c13d7c","next":"0x4","size":4,"mnemonic":"bl","opStr":"#0x252c42d88","operands":[{"type":"imm","value":"9978523016","access":"r"}],"regsAccessed":{"read":[],"written":["lr"]},"regsRead":[],"regsWritten":["lr"],"groups":["call","jump","branch_relative"]}
current: realAddr=0x252c13d7c -> offset: hex=0x50e8=20712
    0x252c13d7c <+20712>: bl #0x252c42d88
+++ into iterator: startAddress=0x252c42d88, isAppCode=false
+++ into iterator: startAddress=0x22ab7145c, isAppCode=false
+++ into iterator: startAddress=0x22ab71478, isAppCode=false
+++ into iterator: startAddress=0x22ab7147c, isAppCode=false
+++ into iterator: startAddress=0x22ab71490, isAppCode=false
+++ into iterator: startAddress=0x22ab714a0, isAppCode=false
+++ into iterator: startAddress=0x22ab714cc, isAppCode=false
+++ into iterator: startAddress=0x22ab714d0, isAppCode=false
+++ into iterator: startAddress=0x22ab714f8, isAppCode=false
+++ into iterator: startAddress=0x22ab7151c, isAppCode=false
+++ into iterator: startAddress=0x252c13d80, isAppCode=true
Instruction: address=0x252c13d80,toString()=mov w5, #0x87f,next=0x4,size=4,mnemonic=mov,opStr=w5, #0x87f,operands=[{"type":"reg","value":"w5","access":"w"},{"type":"imm","value":"2175","access":""}],regsAccessed={"read":[],"written":["w5"]},regsRead=[],regsWritten=[],groups=[],toJSON()={"address":"0x252c13d80","next":"0x4","size":4,"mnemonic":"mov","opStr":"w5, #0x87f","operands":[{"type":"reg","value":"w5","access":"w"},{"type":"imm","value":"2175","access":""}],"regsAccessed":{"read":[],"written":["w5"]},"regsRead":[],"regsWritten":[],"groups":[]}
current: realAddr=0x252c13d80 -> offset: hex=0x50ec=20716
    0x252c13d80 <+20716>: mov w5, #0x87f
Instruction: address=0x252c13d84,toString()=movk w5, #0xa711, lsl #16,next=0x4,size=4,mnemonic=movk,opStr=w5, #0xa711, lsl #16,operands=[{"type":"reg","value":"w5","access":"rw"},{"type":"imm","value":"42769","shift":{"type":"lsl","value":16},"access":"r"}],regsAccessed={"read":["w5"],"written":["w5"]},regsRead=[],regsWritten=[],groups=[],toJSON()={"address":"0x252c13d84","next":"0x4","size":4,"mnemonic":"movk","opStr":"w5, #0xa711, lsl #16","operands":[{"type":"reg","value":"w5","access":"rw"},{"type":"imm","value":"42769","shift":{"type":"lsl","value":16},"access":"r"}],"regsAccessed":{"read":["w5"],"written":["w5"]},"regsRead":[],"regsWritten":[],"groups":[]}
current: realAddr=0x252c13d84 -> offset: hex=0x50f0=20720

...

crifan.org，使用署名4.0国际(CC BY 4.0)协议发布 all right reserved，powered by Gitbook最后更新： 2025-06-04 14:33:47

libmetasec_ml.so的ms_bd_c_l_a

libmetasec_ml.so的ms_bd_c_l_a

此处示例代码特点是：

已整理出Frida的Stalker的hook的通用的工具类函数

FridaUtil.js

stalkerHookUnnameNative

支持通过hookFuncMap传入，要hook的，多个对应的代码的点=位置

以及调用到的其他相关工具类函数：

JsUtil.js

isValidPointer

logStr

intToHexStr

isItemInList

FridaUtil.js

printFunctionCallStack_addr

dumpMemory

ptrToCStr

ptrToUtf8Str

FridaAndroidUtil.js

hookAfterLibLoaded

getJavaClassName

getJclassName

stalkerHookNative_ms_bd_c_l_a及相关代码

贴出此处示例的核心hook代码：

function hookNative_ms_bd_c_l_a(moduleBaseAddress){
  /*
    ==================== Trigged RegisterNatives [0x738cd109f8] ====================
    jniEnv=0x74504ec130
    clazz=0x85 -> jclassName=ms.bd.c.l
    methodsPtr=0x72d02cce60
    nMethods=0x1 -> methodNum=1
    ---------------------------------- method [0] ----------------------------------
    name: pos=0x72d02cce60 -> ptr=0x73a04e22d0 -> str=a
    signature: pos=0x72d02cce68 -> ptr=0x73d04fcb90 -> str=(IIJLjava/lang/String;Ljava/lang/Object;)Ljava/lang/Object;
    fnPtr: pos=0x72d02cce70 -> ptr=0x727a656100 -> offset=0x104100
    Module: name=libmetasec_ml.so, base=0x727a552000, size=undefined, path=/data/app/~~cJq-AFnKyZwZZqpRJY9hWA==/com.ss.android.ugc.aweme-1LCghzY2HKvNbI0WF3vccQ==/lib/arm64/libmetasec_ml.so

    sources/ms/bd/c/l.java
      public class l {
        public static native Object a(int i, int i2, long j, String str, Object obj);
  */
  var funcRelativeStartAddr = 0x104100
  console.log("funcRelativeStartAddr=" + funcRelativeStartAddr)

  const funcRealStartAddr = moduleBaseAddress.add(funcRelativeStartAddr)
  console.log("funcRealStartAddr=" + funcRealStartAddr)

  // var funcName = "ms.bd.c.l.a"
  var funcName = "ms_bd_c_l_a"
  Interceptor.attach(funcRealStartAddr, {
    onEnter: function(args) {
      JsUtil.logStr("Trigged " + funcName + " [" + funcRealStartAddr + "]")
      // FridaUtil.printFunctionCallStack_addr(this.context, funcName)

      var arg0 = args[0]
      var arg1 = args[1]
      var arg2 = args[2]
      var arg3 = args[3]
      var arg4 = args[4]
      var arg5 = args[5]
      var arg6 = args[6]

      var x0 = this.context.x0
      var x1 = this.context.x1
      var x2 = this.context.x2
      var x3 = this.context.x3
      var x4 = this.context.x4
      var x5 = this.context.x5
      var x6 = this.context.x6
      var sp = this.context.sp

      var realArg_i = arg3 // W3
      var realArg_i2 = arg2 // W2
      var realArg_j = arg4 // X4
      var realArg_str = arg5 // X5
      var realArg_obj = arg6 // X6

      var realArg_i_type = typeof realArg_i
      var realArg_i_int = parseInt(realArg_i)
      console.log("realArg_i_type=" + realArg_i_type + ", realArg_i_int=" + realArg_i_int)

      let RI_REPORT_I_LIST = [
        196609, // 0x30001
        196610, // 0x30002
        196611, // 0x30003
      ]

      // if (JsUtil.isItemInList(realArg_i_int, RI_REPORT_I_LIST)){
        console.log("arg0=" + arg0 + ", arg1=" + arg1 + ", arg2=" + arg2 + ", arg3=" + arg3 + ", arg4=" + arg4 + ", arg5=" + arg5 + ", arg6=" + arg6)

        console.log("realArg_i=" + realArg_i + ", realArg_i2=" + realArg_i2 + ", realArg_j=" + realArg_j + ", realArg_str=" + realArg_str + ", realArg_obj=" + realArg_obj)

        console.log("x0=" + x0 + ", x1=" + x1 + ", x2=" + x2 + ", x3=" + x3 + ", x4=" + x4 + ", x5=" + x5 + ", x6=" + x6 + ", sp=" + sp)

        // // var newBrX1Ptr_1 = ptr(sp - 0x58)
        // var newBrX1Ptr = sp.sub(0x58)
        // // console.log("newBrX1Ptr_1=" + newBrX1Ptr_1 + ", newBrX1Ptr=" + newBrX1Ptr)
        // console.log("newBrX1Ptr=" + newBrX1Ptr)
        // var newBrX1_nativePointer = newBrX1Ptr.readPointer()
        // // console.log("newBrX1_nativePointer=" + newBrX1_nativePointer)
        // var newBrX1_U64 = newBrX1Ptr.readU64()
        // // console.log("newBrX1_U64=" + newBrX1_U64)
        // console.log("newBrX1: nativePointer=" + newBrX1_nativePointer + ", U64=" + newBrX1_U64)

        // var toDumpPtr = newBrX1Ptr
        // // var toDumpPtr = newBrX1Ptr - 0x10
        // // var toDumpPtr = ptr(newBrX1Ptr - 0x10)
        // console.log("toDumpPtr=" + toDumpPtr)
        // var byteLen = 64
        // var byteLen = 128
        // FridaUtil.dumpMemory(toDumpPtr, byteLen)

        if (JsUtil.isValidPointer(realArg_str)){
          var cStr = FridaUtil.ptrToCStr(realArg_str)
          console.log("cStr=" + cStr)
          // var utf8Str = FridaUtil.ptrToUtf8Str(realArg_str)
          // console.log("utf8Str=" + utf8Str)
          // console.log("cStr=" + cStr + ", utf8Str=" + utf8Str)
        }

        if (JsUtil.isValidPointer(realArg_obj)){
          var javaClassName = FridaAndroidUtil.getJavaClassName(realArg_obj)
          console.log("javaClassName=" + javaClassName)
          // var jclassName = FridaAndroidUtil.getJclassName(realArg_obj)
          // console.log("jclassName=" + jclassName)
          // console.log("jclassName=" + jclassName + ", javaClassName=" + javaClassName)
        }
      // }

    },
    onLeave: function(retVal){
      console.log(funcName + " [0x104100]: retVal=" + retVal)
    }
  })
}

function stalkerHookNative_sub_10413C(moduleBaseAddress){
  var funcRelativeStartAddr = 0x10413C
  var functionSize = 0x14 // 0x104150 - 0x10413C = 0x14
  var argNum = 0
  let hookFuncMap = {
    0x08:
      function (context) {
        var contextStr = JSON.stringify(context)
        console.log("[0x08] contextStr=" + contextStr)
        var sp = context.sp
        console.log("sp=" + sp)
      },
    0x0C:
      function (context) {
        var contextStr = JSON.stringify(context)
        console.log("[0x0C] contextStr=" + contextStr)
        var x0 = context.x0
        console.log("x0=" + x0)
      },
  }

  FridaUtil.stalkerHookUnnameNative(moduleBaseAddress, funcRelativeStartAddr, functionSize, argNum, hookFuncMap)
}

function stalkerHookNative_loc_104190(moduleBaseAddress){
  var funcRelativeStartAddr = 0x104190
  var functionSize = 0x40 // @@@ Tracing basic block at 0x114190, block size = 0x40
  var argNum = 0
  let hookFuncMap = {
    0x18:
      function (context) {
        var contextStr = JSON.stringify(context)
        console.log("[0x18] contextStr=" + contextStr)
        var x23 = context.x23
        console.log("[0x18] x23=" + x23)
      },
    0x1C:
      function (context) {
        var contextStr = JSON.stringify(context)
        console.log("[0x1C] contextStr=" + contextStr)
        var x23 = context.x23
        console.log("[0x1C] x23=" + x23)
      },
    0x20:
      function (context) {
        var contextStr = JSON.stringify(context)
        console.log("[0x20] contextStr=" + contextStr)
        var x8 = context.x8
        console.log("[0x20] x8=" + x8)
      },
  }

  FridaUtil.stalkerHookUnnameNative(moduleBaseAddress, funcRelativeStartAddr, functionSize, argNum, hookFuncMap)
}

function stalkerHookNative_ms_bd_c_l_a(moduleBaseAddress){
  var funcRelativeStartAddr = 0x104100
  var functionSize = 0x38 // 0x104138 - 0x104100 = 0x38
  // var functionSize = 0x50 // including sub_10413C: 0x104150 - 0x104100 = 0x50
  var argNum = 5
  // let hookFuncMap = new Map()
  // hookFuncMap.set(
  //   0x30,
  //   function (context) {
  //     var contextStr = JSON.stringify(context)
  //     console.log("contextStr=" + contextStr)
  //     var x0 = context.x0
  //     var x0ToOffset = x0.sub(moduleBaseAddress)
  //     console.log("x0=" + x0 + "-> offset=" + x0ToOffset)
  //     var x1 = context.x1
  //     console.log("x1=" + x1)
  //     var x1ToOffset = x1.sub(moduleBaseAddress)
  //     console.log("x1=" + x1 + "-> offset=" + x1ToOffset)
  //   }
  // )
  let hookFuncMap = {
    // 0x2C:
    //   // function (context, curOffsetInt, moduleBaseAddr) {
    //   // function (context, extraDataDict) {
    //   function (context) {
    //     // var curOffsetInt = context.curOffsetInt
    //     // var curOffsetHexPtr = context.curOffsetHexPtr
    //     // var moduleBaseAddr = context.moduleBaseAddress
    //     // var curOffsetInt = context[curOffsetInt]
    //     // var curOffsetHexPtr = context[curOffsetHexPtr]
    //     // var moduleBaseAddr = context[moduleBaseAddress]
    //     // console.log("in 0x2C: curOffsetInt=" + curOffsetInt + "=" + curOffsetHexPtr)

    //     // var contextStr = JSON.stringify(context)
    //     // console.log("[0x2C] contextStr=" + contextStr)
    //   },
    0x30:
      function (context) {
      // function (context, extraDataDict) {
      // function (context, curOffsetInt, moduleBaseAddr) {
        // console.log("extraDataDict=" + extraDataDict)
        // var curOffsetInt = context.curOffsetInt
        // var curOffsetHexPtr = context.curOffsetHexPtr
        // var moduleBaseAddr = context.moduleBaseAddress
        // var curOffsetInt = context[curOffsetInt]
        // var curOffsetHexPtr = context[curOffsetHexPtr]
        // var moduleBaseAddr = context[moduleBaseAddress]
        // console.log("called 0x30: curOffsetInt=" + curOffsetInt + ", moduleBaseAddr=" + moduleBaseAddr)
        // // var curOffsetHexPtr = JsUtil.intToHexStr(curOffsetInt)
        // console.log("----- current offset: [" + curOffsetHexPtr + "] -----")

        // var contextStr = JSON.stringify(context)
        // console.log("[0x30] contextStr=" + contextStr)
        var x0 = context.x0
        var x0ToOffset = x0.sub(moduleBaseAddress)
        console.log("[0x30] x0=" + x0 + "-> offset=" + x0ToOffset)
      },
    0x38:
      // function (context, extraDataDict) {
      // function (context, curOffsetInt, moduleBaseAddress) {
      function (context) {
        // var curOffsetInt = context.curOffsetInt
        // var curOffsetHexPtr = context.curOffsetHexPtr
        // var moduleBaseAddr = context.moduleBaseAddress
        // var curOffsetInt = context[curOffsetInt]
        // var curOffsetHexPtr = context[curOffsetHexPtr]
        // var moduleBaseAddr = context[moduleBaseAddress]
        // console.log("in 0x38: curOffsetInt=" + curOffsetInt)
        // var curOffsetHexPtr = JsUtil.intToHexStr(curOffsetInt)
        // console.log("----- current offset: [" + curOffsetHexPtr + "] -----")

        // var contextStr = JSON.stringify(context)
        // console.log("[0x38] contextStr=" + contextStr)
        var x1 = context.x1
        var x1ToOffset = x1.sub(moduleBaseAddress)
        console.log("[0x38] x1=" + x1 + "-> offset=" + x1ToOffset)
      }
  }

  FridaUtil.stalkerHookUnnameNative(moduleBaseAddress, funcRelativeStartAddr, functionSize, argNum, hookFuncMap)

  // console.log("===== Frida Stalker hook for libmetasec_ml.so ms.bd.c.l a function =====");
  // /*
  //   ==================== Trigged RegisterNatives [0x738cd109f8] ====================
  //   jniEnv=0x74504ec130
  //   clazz=0x85 -> jclassName=ms.bd.c.l
  //   methodsPtr=0x72d02cce60
  //   nMethods=0x1 -> methodNum=1
  //   ---------------------------------- method [0] ----------------------------------
  //   name: pos=0x72d02cce60 -> ptr=0x73a04e22d0 -> str=a
  //   signature: pos=0x72d02cce68 -> ptr=0x73d04fcb90 -> str=(IIJLjava/lang/String;Ljava/lang/Object;)Ljava/lang/Object;
  //   fnPtr: pos=0x72d02cce70 -> ptr=0x727a656100 -> offset=0x104100
  //   Module: name=libmetasec_ml.so, base=0x727a552000, size=undefined, path=/data/app/~~cJq-AFnKyZwZZqpRJY9hWA==/com.ss.android.ugc.aweme-1LCghzY2HKvNbI0WF3vccQ==/lib/arm64/libmetasec_ml.so

  //   sources/ms/bd/c/l.java
  //     public class l {
  //       public static native Object a(int i, int i2, long j, String str, Object obj);
  // */

  // var funcRelativeStartAddr = 0x104100
  // // console.log("funcRelativeStartAddr=" + funcRelativeStartAddr)
  // var funcRelativeStartAddrHexStr = JsUtil.intToHexStr(funcRelativeStartAddr)
  // // var functionSize = 0x38 // 0x104138 - 0x104100 = 0x38
  // var functionSize = 0x50 // including sub_10413C: 0x104150 - 0x104100 = 0x50
  // var functionSizeHexStr = JsUtil.intToHexStr(functionSize)
  // var funcRelativeEndAddr = funcRelativeStartAddr + functionSize
  // var funcRelativeEndAddrHexStr = JsUtil.intToHexStr(funcRelativeEndAddr)
  // console.log("function: relativeStartAddr=" + funcRelativeStartAddrHexStr + ", size=" + functionSize + "=" + functionSizeHexStr + ", relativeEndAddr=" + funcRelativeEndAddrHexStr)
  // // const moduleName = "libmetasec_ml.so"
  // // const moduleBaseAddress = Module.findBaseAddress(moduleName)
  // // console.log("moduleName=" + moduleName + ", moduleBaseAddress=" + moduleBaseAddress)
  // console.log("moduleBaseAddress=" + moduleBaseAddress)
  // const funcRealStartAddr = moduleBaseAddress.add(funcRelativeStartAddr)
  // // var funcRealEndAddr = funcRealStartAddr + functionSize
  // const funcRealEndAddr = funcRealStartAddr.add(functionSize)
  // console.log("funcRealStartAddr=" + funcRealStartAddr + ", funcRealEndAddr=" + funcRealEndAddr)
  // var curTid = null
  // console.log("curTid=" + curTid)
  // Interceptor.attach(funcRealStartAddr, {
  //     onEnter: function(args) {
  //         var arg0 = args[0]
  //         var arg1 = args[1]
  //         var arg2 = args[2]
  //         var arg3 = args[3]
  //         var arg4 = args[4]
  //         console.log("----- arg0=" + arg0 + ", arg1=" + arg1 + ", arg2=" + arg2 + ", arg3=" + arg3 + ", arg4=" + arg4)

  //         var curTid = Process.getCurrentThreadId()
  //         console.log("curTid=", curTid)
  //         Stalker.follow(curTid, {
  //             events: {
  //                 call: false, // CALL instructions: yes please
  //                 ret: true, // RET instructions
  //                 exec: false, // all instructions: not recommended as it's
  //                 block: false, // block executed: coarse execution trace
  //                 compile: false // block compiled: useful for coverage
  //             },
  //             // onReceive: Called with `events` containing a binary blob comprised of one or more GumEvent structs. See `gumevent.h` for details about the format. Use `Stalker.parse()` to examine the data.
  //             onReceive(events) {
  //                 var parsedEvents = Stalker.parse(events)
  //                 // var parsedEventsStr = JSON.stringify(parsedEventsStr)
  //                 // console.log(">>> into onReceive: parsedEvents=" + parsedEvents + ", parsedEventsStr=" + parsedEventsStr);
  //                 console.log(">>> into onReceive: parsedEvents=" + parsedEvents);
  //             },

  //             // transform: (iterator: StalkerArm64Iterator) => {
  //             transform: function (iterator) {
  //                 // console.log("iterator=" + iterator)
  //                 var instruction = iterator.next()
  //                 const startAddress = instruction.address
  //                 // console.log("+++ into iterator: startAddress=" + startAddress)
  //                 // const isAppCode = startAddress.compare(funcRealStartAddr) >= 0 && startAddress.compare(funcRealEndAddr) === -1
  //                 // const isAppCode = (startAddress.compare(funcRealStartAddr) >= 0) && (startAddress.compare(funcRealEndAddr) < 0)
  //                 const gt_realStartAddr = startAddress.compare(funcRealStartAddr) >= 0
  //                 const lt_realEndAddr = startAddress.compare(funcRealEndAddr) < 0
  //                 var isAppCode = gt_realStartAddr && lt_realEndAddr
  //                 console.log("+++ into iterator: startAddress=" + startAddress + ", isAppCode=" + isAppCode)

  //                 // // for debug
  //                 // isAppCode = true

  //                 // console.log("isAppCode=" + isAppCode + ", gt_realStartAddr=" + gt_realStartAddr + ", lt_realEndAddr=" + lt_realEndAddr)
  //                 do {
  //                     if (isAppCode) {
  //                         // is origal function code = which we focus on

  //                         // console.log("instruction: address=" + instruction.address
  //                         //     + ",next=" + instruction.next()
  //                         //     + ",size=" + instruction.size
  //                         //     + ",mnemonic=" + instruction.mnemonic
  //                         //     + ",opStr=" + instruction.opStr
  //                         //     + ",operands=" + JSON.stringify(instruction.operands)
  //                         //     + ",regsAccessed=" + JSON.stringify(instruction.regsAccessed)
  //                         //     + ",regsRead=" + JSON.stringify(instruction.regsRead)
  //                         //     + ",regsWritten=" + JSON.stringify(instruction.regsWritten)
  //                         //     + ",groups=" + JSON.stringify(instruction.groups)
  //                         //     + ",toString()=" + instruction.toString()
  //                         //     + ",toJSON()=" + instruction.toJSON()
  //                         // );

  //                         var curRealAddr = instruction.address
  //                         // console.log("curRealAddr=" + curRealAddr)
  //                         // const isAppCode = curRealAddr.compare(funcRealStartAddr) >= 0 && curRealAddr.compare(funcRealEndAddr) === -1
  //                         // console.log(curRealAddr + ": isAppCode=" + isAppCode)
  //                         var curOffsetHexPtr = curRealAddr.sub(funcRealStartAddr)
  //                         var curOffsetInt = curOffsetHexPtr.toInt32()
  //                         console.log("current: realAddr=" + curRealAddr + "-> offset: hex=" + curOffsetHexPtr + "=" + curOffsetInt)

  //                         // var instructionStr = instruction.mnemonic + " " + instruction.opStr
  //                         var instructionStr = instruction.toString()
  //                         // console.log("\t" + curRealAddr + ": " + instructionStr);
  //                         // console.log("\t" + curRealAddr + " <+" + curOffsetHexPtr + ">: " + instructionStr)
  //                         console.log("\t" + curRealAddr + " <+" + curOffsetInt + ">: " + instructionStr)
  //                         if (curOffsetInt == 0x30) {
  //                           console.log("offset: " + curOffsetHexPtr)
  //                           // iterator.putCallout(needDebug);
  //                           iterator.putCallout((context) => {
  //                               var contextStr = JSON.stringify(context)
  //                               console.log("contextStr=" + contextStr)
  //                               var x0 = context.x0
  //                               var x0ToOffset = x0.sub(moduleBaseAddress)
  //                               console.log("x0=" + x0 + "-> offset=" + x0ToOffset)
  //                               var x1 = context.x1
  //                               console.log("x1=" + x1)
  //                               var x1ToOffset = x1.sub(moduleBaseAddress)
  //                               console.log("x1=" + x1 + "-> offset=" + x1ToOffset)
  //                           })
  //                         } else if  (curOffsetInt == 0x38) {
  //                           console.log("offset: " + curOffsetHexPtr)
  //                           // iterator.putCallout(needDebug)
  //                           iterator.putCallout((context) => {
  //                               var contextStr = JSON.stringify(context)
  //                               console.log("contextStr=" + contextStr)
  //                               var x1 = context.x1
  //                               console.log("x1=" + x1)
  //                               var x1ToOffset = x1.sub(moduleBaseAddress)
  //                               console.log("x1ToOffset=" + x1ToOffset)
  //                           })
  //                         }
  //                     }
  //                     iterator.keep();
  //                 } while ((instruction = iterator.next()) !== null)
  //             }
  //         });

  //         // function needDebug(context) {
  //         //     console.log("into needDebug")
  //         //     // console.log("into needDebug: context=" + context)
  //         //     // var contextStr = JSON.stringify(context, null, 2)
  //         //     // console.log("context=" + contextStr)
  //         //     // var x9Value1 = context.x9
  //         //     // var x9Value2 = context["x9"]
  //         //     // console.log("x9Value1=" + x9Value1 + ", x9Value2=" + x9Value2)
  //         // }
  //     },
  //     onLeave: function(retval) {
  //         console.log("retval=" + retval)
  //         if (curTid != null) {
  //             Stalker.unfollow(curTid);
  //             console.log("Stalker.unfollow curTid=", curTid)
  //         }
  //     }
  // })
}

function afterLibLoaded_libmetasec_ml(libraryName) {
  const moduleBaseAddress = Module.findBaseAddress(libraryName)
  console.log("libraryName=" + libraryName + " -> moduleBaseAddress=" + moduleBaseAddress)

  // hookNative_ms_bd_c_l_a(moduleBaseAddress)
  // stalkerHookNative_ms_bd_c_l_a(moduleBaseAddress)
  // stalkerHookNative_sub_10413C(moduleBaseAddress)
  stalkerHookNative_loc_104190(moduleBaseAddress)
}

function hookNative_libmetasec_ml(){
  FridaAndroidUtil.hookAfterLibLoaded("libmetasec_ml.so", afterLibLoaded_libmetasec_ml)
}

function hookDouyin_Native(){
  hookNative_libmetasec_ml()
}

function hookDouyin() {
  // hookDouyin_Java()
  hookDouyin_Native()
}

function hookAndroid() {
  if(!Java.available){
    console.error("Java is not available")
    return
  }

  console.log("Java is available")
  console.log("Java.androidVersion=" + Java.androidVersion)

  Java.perform(function () {
    hookInit()

    hookDouyin()

    console.log("-------------------- Begin Hook --------------------")
  })

}

setImmediate(hookAndroid)

调试日志

某次的调试输出的日志：

➜  frida frida -U -f com.ss.android.ugc.aweme -l hook_douyin.js
     ____
    / _  |   Frida 16.4.8 - A world-class dynamic instrumentation toolkit
   | (_| |
    > _  |   Commands:
   /_/ |_|       help      -> Displays the help system
   . . . .       object?   -> Display information about 'object'
   . . . .       exit/quit -> Exit
   . . . .
   . . . .   More info at https://frida.re/docs/home/
   . . . .
   . . . .   Connected to M2101K9C (id=9C181A8D3C3F3B)
Spawning `com.ss.android.ugc.aweme`...
FridaAndroidUtil.cacheDictEnvClazz=[object Object]
FridaAndroidUtil.curThrowableCls=<class: java.lang.Throwable>
FridaAndroidUtil.JavaArray=<class: java.lang.reflect.Array>
FridaAndroidUtil.JavaArrays=<class: java.util.Arrays>
FridaAndroidUtil.JavaArrayList=<class: java.util.ArrayList>
FridaAndroidUtil.JavaByteArr=<class: [B>
FridaAndroidUtil.JavaObjArr=<class: [Ljava.lang.Object;>
JNIEnvIdx.CallObjectMethod=34
Java is available
Java.androidVersion=13
Spawned `com.ss.android.ugc.aweme`. Resuming main thread!
[M2101K9C::com.ss.android.ugc.aweme ]-> libName=libmetasec_ml.so
libraryName=libmetasec_ml.so, callback_afterLibLoaded=function afterLibLoaded_libmetasec_ml(libraryName) {
  const moduleBaseAddress = Module.findBaseAddress(libraryName)
  console.log("libraryName=" + libraryName + " -> moduleBaseAddress=" + moduleBaseAddress)

  // hook_JNI_OnLoad(libraryName)

  // FridaAndroidUtil.printModuleInfo("libmetasec_ml.so")

  // hookNative__JNIEnv_CallStaticObjectMethod(moduleBaseAddress)
  // hookNative__JNIEnv_NewObject(moduleBaseAddress)
  // hookNative_getJNIEnv(moduleBaseAddress)
  // hookNative__JNIEnv_CallObjectMethod(moduleBaseAddress)

  // hookNative_getSecDeviceToken(moduleBaseAddress)
  // hookNative_doHttpReqSignByUrl(moduleBaseAddress)

  // hookNative_ms_bd_c_l_a(moduleBaseAddress)
  // stalkerHookNative_ms_bd_c_l_a(moduleBaseAddress)
  // stalkerHookNative_sub_10413C(moduleBaseAddress)
  stalkerHookNative_loc_104190(moduleBaseAddress)
}
android_dlopen_ext=0x7a9cb230b8
-------------------- Begin Hook --------------------
+++ Loaded lib libmetasec_ml.so
libraryName=libmetasec_ml.so -> moduleBaseAddress=0x7708060000
Frida Stalker hook: module: baseAddress=0x7708060000
function: relativeStartAddr=0x104190, size=64=0x40, relativeEndAddr=0x1041d0
funcRealStartAddr=0x7708164190, funcRealEndAddr=0x77081641d0
curTid=null
=========== Trigged addr: relative [0x104190] = real [0x7708164190]  ===========
curTid=20389
+++ into iterator: startAddress=0x77d7300360, isAppCode=false
+++ into iterator: startAddress=0x77d7300370, isAppCode=false
+++ into iterator: startAddress=0x77d7300380, isAppCode=false
...
+++ into iterator: startAddress=0x77d72c484c, isAppCode=false
+++ into iterator: startAddress=0x7a9cdab0b4, isAppCode=false
+++ into iterator: startAddress=0x7a9cd03530, isAppCode=false
+++ into iterator: startAddress=0x77081641a0, isAppCode=true
current: realAddr=0x77081641a0 -> offset: hex=0x10=16
    0x77081641a0 <+16>: stp x29, x30, [sp, #0x40]
current: realAddr=0x77081641a4 -> offset: hex=0x14=20
    0x77081641a4 <+20>: add x29, sp, #0x40
current: realAddr=0x77081641a8 -> offset: hex=0x18=24
    0x77081641a8 <+24>: mrs x23, tpidr_el0
offset: 0x18=24
current: realAddr=0x77081641ac -> offset: hex=0x1c=28
    0x77081641ac <+28>: ldr x8, [x23, #0x28]
offset: 0x1c=28
current: realAddr=0x77081641b0 -> offset: hex=0x20=32
    0x77081641b0 <+32>: mov x19, x4
offset: 0x20=32
current: realAddr=0x77081641b4 -> offset: hex=0x24=36
    0x77081641b4 <+36>: mov x20, x3
current: realAddr=0x77081641b8 -> offset: hex=0x28=40
    0x77081641b8 <+40>: mov x21, x2
current: realAddr=0x77081641bc -> offset: hex=0x2c=44
    0x77081641bc <+44>: mov w22, w1
current: realAddr=0x77081641c0 -> offset: hex=0x30=48
    0x77081641c0 <+48>: str x8, [sp, #8]
current: realAddr=0x77081641c4 -> offset: hex=0x34=52
    0x77081641c4 <+52>: str w0, [sp, #4]
current: realAddr=0x77081641c8 -> offset: hex=0x38=56
    0x77081641c8 <+56>: adr x9, #0x77081641c8
current: realAddr=0x77081641cc -> offset: hex=0x3c=60
    0x77081641cc <+60>: b #0x77081641d4
[0x18] contextStr={"pc":"0x77081641a8","sp":"0x773cc9abf0","nzcv":2684354560,"x0":"0x1000001","x1":"0x0","x2":"0x0","x3":"0x773cc9ad08","x4":"0x773cc9ad0c","x5":"0x773cc9ad08","x6":"0x773cc9ad0c","x7":"0x0","x8":"0x8d4e175111831754","x9":"0x8d4e175111831754","x10":"0x30","x11":"0x7","x12":"0x7c33","x13":"0xffffffffffffffff","x14":"0x775dc83dcc","x15":"0xf339","x16":"0x77081641a0","x17":"0x775e01f23c","x18":"0x773c532000","x19":"0x7960801bb0","x20":"0x0","x21":"0x0","x22":"0x78b07cadd0","x23":"0x1","x24":"0x1","x25":"0x3c","x26":"0x6e","x27":"0x52","x28":"0x135c5d40","fp":"0x773cc9ac30","lr":"0x7a9cd0350c","q0":{},"q1":{},"q2":{},"q3":{},"q4":{},"q5":{},"q6":{},"q7":{},"q8":{},"q9":{},"q10":{},"q11":{},"q12":{},"q13":{},"q14":{},"q15":{},"q16":{},"q17":{},"q18":{},"q19":{},"q20":{},"q21":{},"q22":{},"q23":{},"q24":{},"q25":{},"q26":{},"q27":{},"q28":{},"q29":{},"q30":{},"q31":{},"d0":5.330481526237208e+228,"d1":1.6766152451136167e+243,"d2":0,"d3":-8.348743279794574e-210,"d4":0,"d5":4.003911019303815,"d6":0,"d7":3.1152901395860827e-307,"d8":1.69759663317e-313,"d9":0,"d10":0,"d11":0,"d12":0,"d13":0,"d14":0,"d15":0,"d16":-16.04693223164578,"d17":32.00198376226035,"d18":5.30498948e-315,"d19":1.95354366e-314,"d20":-1.3467897878976211e+116,"d21":-4.197101104091689e-187,"d22":2.3236709860767083e+130,"d23":1.8121650802628091e+267,"d24":1.9535436624e-314,"d25":1.953543663e-314,"d26":1.9535436634e-314,"d27":1.953543664e-314,"d28":1.9535436644e-314,"d29":1.953543665e-314,"d30":1.9535436653e-314,"d31":8.900981273429906e-307,"s0":284916448105594880000,"s1":1.6926149821424084e+22,"s2":0,"s3":-1.8800355907811577e+23,"s4":0,"s5":2.250244379043579,"s6":0,"s7":7.255137319835417e-39,"s8":1.1210387714598537e-44,"s9":0,"s10":0,"s11":0,"s12":0,"s13":0,"s14":0,"s15":0,"s16":-2.7507331371307373,"s17":2.369642786801667e-38,"s18":2.000000238418579,"s19":-4.1950209245322364e+26,"s20":56.58197021484375,"s21":9.273393360036293e+31,"s22":-4.102617163036699e-37,"s23":-1.6180783810626933e+28,"s24":-4.195022769206644e+26,"s25":-4.195023138141525e+26,"s26":-4.195023507076407e+26,"s27":-4.195023876011288e+26,"s28":-4.1950242449461696e+26,"s29":-4.195024613881051e+26,"s30":-4.1950249828159326e+26,"s31":9.183685541750161e-39}
[0x18] x23=0x1
[0x1C] contextStr={"pc":"0x77081641ac","sp":"0x773cc9abf0","nzcv":2684354560,"x0":"0x1000001","x1":"0x0","x2":"0x0","x3":"0x773cc9ad08","x4":"0x773cc9ad0c","x5":"0x773cc9ad08","x6":"0x773cc9ad0c","x7":"0x0","x8":"0x8d4e175111831754","x9":"0x8d4e175111831754","x10":"0x30","x11":"0x7","x12":"0x7c33","x13":"0xffffffffffffffff","x14":"0x775dc83dcc","x15":"0xf339","x16":"0x77081641a0","x17":"0x775e01f23c","x18":"0x773c532000","x19":"0x7960801bb0","x20":"0x0","x21":"0x0","x22":"0x78b07cadd0","x23":"0x773cc9c000","x24":"0x1","x25":"0x3c","x26":"0x6e","x27":"0x52","x28":"0x135c5d40","fp":"0x773cc9ac30","lr":"0x7a9cd0350c","q0":{},"q1":{},"q2":{},"q3":{},"q4":{},"q5":{},"q6":{},"q7":{},"q8":{},"q9":{},"q10":{},"q11":{},"q12":{},"q13":{},"q14":{},"q15":{},"q16":{},"q17":{},"q18":{},"q19":{},"q20":{},"q21":{},"q22":{},"q23":{},"q24":{},"q25":{},"q26":{},"q27":{},"q28":{},"q29":{},"q30":{},"q31":{},"d0":5.330481526237208e+228,"d1":1.6766152451136167e+243,"d2":0,"d3":-8.348743279794574e-210,"d4":0,"d5":4.003911019303815,"d6":0,"d7":3.1152901395860827e-307,"d8":1.69759663317e-313,"d9":0,"d10":0,"d11":0,"d12":0,"d13":0,"d14":0,"d15":0,"d16":-16.04693223164578,"d17":32.00198376226035,"d18":5.30498948e-315,"d19":1.95354366e-314,"d20":-1.3467897878976211e+116,"d21":-4.197101104091689e-187,"d22":2.3236709860767083e+130,"d23":1.8121650802628091e+267,"d24":1.9535436624e-314,"d25":1.953543663e-314,"d26":1.9535436634e-314,"d27":1.953543664e-314,"d28":1.9535436644e-314,"d29":1.953543665e-314,"d30":1.9535436653e-314,"d31":8.900981273429906e-307,"s0":284916448105594880000,"s1":1.6926149821424084e+22,"s2":0,"s3":-1.8800355907811577e+23,"s4":0,"s5":2.250244379043579,"s6":0,"s7":7.255137319835417e-39,"s8":1.1210387714598537e-44,"s9":0,"s10":0,"s11":0,"s12":0,"s13":0,"s14":0,"s15":0,"s16":-2.7507331371307373,"s17":2.369642786801667e-38,"s18":2.000000238418579,"s19":-4.1950209245322364e+26,"s20":56.58197021484375,"s21":9.273393360036293e+31,"s22":-4.102617163036699e-37,"s23":-1.6180783810626933e+28,"s24":-4.195022769206644e+26,"s25":-4.195023138141525e+26,"s26":-4.195023507076407e+26,"s27":-4.195023876011288e+26,"s28":-4.1950242449461696e+26,"s29":-4.195024613881051e+26,"s30":-4.1950249828159326e+26,"s31":9.183685541750161e-39}
[0x1C] x23=0x773cc9c000
[0x20] contextStr={"pc":"0x77081641b0","sp":"0x773cc9abf0","nzcv":2684354560,"x0":"0x1000001","x1":"0x0","x2":"0x0","x3":"0x773cc9ad08","x4":"0x773cc9ad0c","x5":"0x773cc9ad08","x6":"0x773cc9ad0c","x7":"0x0","x8":"0x8d4e175111831754","x9":"0x8d4e175111831754","x10":"0x30","x11":"0x7","x12":"0x7c33","x13":"0xffffffffffffffff","x14":"0x775dc83dcc","x15":"0xf339","x16":"0x77081641a0","x17":"0x775e01f23c","x18":"0x773c532000","x19":"0x7960801bb0","x20":"0x0","x21":"0x0","x22":"0x78b07cadd0","x23":"0x773cc9c000","x24":"0x1","x25":"0x3c","x26":"0x6e","x27":"0x52","x28":"0x135c5d40","fp":"0x773cc9ac30","lr":"0x7a9cd0350c","q0":{},"q1":{},"q2":{},"q3":{},"q4":{},"q5":{},"q6":{},"q7":{},"q8":{},"q9":{},"q10":{},"q11":{},"q12":{},"q13":{},"q14":{},"q15":{},"q16":{},"q17":{},"q18":{},"q19":{},"q20":{},"q21":{},"q22":{},"q23":{},"q24":{},"q25":{},"q26":{},"q27":{},"q28":{},"q29":{},"q30":{},"q31":{},"d0":5.330481526237208e+228,"d1":1.6766152451136167e+243,"d2":0,"d3":-8.348743279794574e-210,"d4":0,"d5":4.003911019303815,"d6":0,"d7":3.1152901395860827e-307,"d8":1.69759663317e-313,"d9":0,"d10":0,"d11":0,"d12":0,"d13":0,"d14":0,"d15":0,"d16":-16.04693223164578,"d17":32.00198376226035,"d18":5.30498948e-315,"d19":1.95354366e-314,"d20":-1.3467897878976211e+116,"d21":-4.197101104091689e-187,"d22":2.3236709860767083e+130,"d23":1.8121650802628091e+267,"d24":1.9535436624e-314,"d25":1.953543663e-314,"d26":1.9535436634e-314,"d27":1.953543664e-314,"d28":1.9535436644e-314,"d29":1.953543665e-314,"d30":1.9535436653e-314,"d31":8.900981273429906e-307,"s0":284916448105594880000,"s1":1.6926149821424084e+22,"s2":0,"s3":-1.8800355907811577e+23,"s4":0,"s5":2.250244379043579,"s6":0,"s7":7.255137319835417e-39,"s8":1.1210387714598537e-44,"s9":0,"s10":0,"s11":0,"s12":0,"s13":0,"s14":0,"s15":0,"s16":-2.7507331371307373,"s17":2.369642786801667e-38,"s18":2.000000238418579,"s19":-4.1950209245322364e+26,"s20":56.58197021484375,"s21":9.273393360036293e+31,"s22":-4.102617163036699e-37,"s23":-1.6180783810626933e+28,"s24":-4.195022769206644e+26,"s25":-4.195023138141525e+26,"s26":-4.195023507076407e+26,"s27":-4.195023876011288e+26,"s28":-4.1950242449461696e+26,"s29":-4.195024613881051e+26,"s30":-4.1950249828159326e+26,"s31":9.183685541750161e-39}
[0x20] x8=0x8d4e175111831754
+++ into iterator: startAddress=0x77081641d4, isAppCode=false
...
+++ into iterator: startAddress=0x7708164b10, isAppCode=false
>>> into onReceive: parsedEvents=ret,0x77d73f17ec,0x77d72fe844,0,ret,0x77d72ffd0c,0x77d72c478c,-1,ret,0x77d72c486c,0x7a9cdab0b4,-2,ret,0x7a9cdab140,0x7a9cd0350c,-3,ret,0x770816421c,0x77081641fc,-3,ret,0x7708164280,0x7708164264,-3,ret,0x7708164280,0x770816429c,-3,ret,0x770816755c,0x770816857c,-1,ret,0x77080a29cc,0x7708168584,-1,ret,0x770816755c,0x770816857c,-1,ret,0x77080a29cc,0x7708168584,-1,ret,0x770816755c,0x770816857c,-1,ret,0x77080a29cc,0x7708168584,-1,ret,0x770816755c,0x770816857c,-1,ret,0x77080a29cc,0x7708168584,-1,ret,0x77081685b8,0x770816798c,-2,ret,0x7708167dcc,0x770816799c,-2,ret,0x7708168654,0x77081679b0,-2,ret,0x77081685e4,0x77081679d4,-2,ret,0x77080a29cc,0x77081679e0,-2,ret,0x77081685e4,0x77081679f4,-2,ret,0x7708167a18,0x77081643f8,-3,ret,0x7a9084eee4,0x7708164a4c,-1,ret,0x7a9084dfc0,0x7708164a54,-1,ret,0x7a90855d34,0x7a907d89a8,4,ret,0x7a907d89b4,0x7a907da374,3,ret,0x7a90855ff4,0x7a907d8a3c,4,ret,0x7a907e4f5c,0x7a907da45c,3,ret,0x7a907da514,0x7a907dab70,2,ret,0x7a907dab84,0x7a907d5134,1,ret,0x7a907d514c,0x77081ca484,0,ret,0x77081ca4a0,0x7708164a6c,-1,ret,0x77ee47dc04,0x77ee64bc90,2,ret,0x7a90855d34,0x7a907d89a8,8,ret,0x7a907d89b4,0x7a907da330,7,ret,0x7a90855ff4,0x7a907d8a3c,8,ret,0x7a907d8a4c,0x7a907da45c,7,ret,0x7a907da514,0x7a907dab70,6,ret,0x7a907dab84,0x7a907d5134,5,ret,0x7a907d514c,0x7a80a5abc8,4,ret,0x7a80a5abe4,0x77ee64c050,3,ret,0x77ee64c108,0x77ee64bcdc,2,ret,0x77ee47dcb4,0x77ee64bd34,2,ret,0x77ee653610,0x77ee64be34,2,ret,0x7a90855df4,0x7a907dec6c,4,ret,0x7a90855d34,0x7a907d89a8,5,ret,0x7a907d89b4,0x7a907decb0,4,ret,0x7a90855ff4,0x7a907d8a3c,4,ret,0x7a907e4f5c,0x7a907da9c4,3,ret,0x7a907da9d4,0x77ee64be88,2,ret,0x77ee64beb8,0x77080acbd0,1,ret,0x77080acbf0,0x7708164b10,0
+++ into iterator: startAddress=0x7708164b98, isAppCode=false
...
+++ into iterator: startAddress=0x7a9084e288, isAppCode=false
[M2101K9C::com.ss.android.ugc.aweme ]->
+++ into iterator: startAddress=0x7a9084e2fc, isAppCode=false
[M2101K9C::com.ss.android.ugc.aweme ]-> +++ into iterator: startAddress=0x7a9084e308, isAppCode=false
+++ into iterator: startAddress=0x7a9084e4a0, isAppCode=false
...
+++ into iterator: startAddress=0x77ee69c190, isAppCode=false
>>> into onReceive: parsedEvents=ret,0x7708164bb8,0x7708164a74,-1,ret,0x7a9084e020,0x7708164a80,-1,ret,0x7708164ad4,0x77080ac5a0,-2,ret,0x7a9084dfd8,0x7708164be0,-1,ret,0x77ee47dc04,0x77ee64bc90,1,ret,0x7a90855d34,0x7a907d89a8,7,ret,0x7a907d89b4,0x7a907da330,6,ret,0x7a90855ff4,0x7a907d8a3c,7,ret,0x7a907e4f5c,0x7a907da45c,6,ret,0x7a907da514,0x7a907dab70,5,ret,0x7a907dab84,0x7a907d5134,4,ret,0x7a907d514c,0x7a80a5abc8,3,ret,0x7a80a5abe4,0x77ee64c050,2,ret,0x77ee64c108,0x77ee64bcdc,1,ret,0x77ee47dcb4,0x77ee64bd34,1,ret,0x77ee653610,0x77ee64be34,1,ret,0x7a90855df4,0x7a907dec6c,3,ret,0x7a90855d34,0x7a907d89a8,4,ret,0x7a907d89b4,0x7a907decb0,3,ret,0x7a90855ff4,0x7a907d8a3c,3,ret,0x7a907d8a4c,0x7a907da9c4,2,ret,0x7a907da9d4,0x77ee64be88,1,ret,0x77ee64beb8,0x77080acbd0,0,ret,0x77080acbf0,0x7708164bec,-1,ret,0x7708164bf8,0x77080ac5a8,-2,ret,0x770809fd08,0x77080ac5b0,-2,ret,0x77080ac5f4,0x77080ac5d4,-2,ret,0x770809fd08,0x77080ac628,-2,ret,0x7708164948,0x7708164928,-1,ret,0x77081649b0,0x7708164994,-1,ret,0x77081649b0,0x77081649cc,-1,ret,0x7708164a10,0x77080ac63c,-2,ret,0x770816369c,0x77080ac65c,-2,ret,0x7a90855cb4,0x7a9084e598,3,ret,0x7a9084e534,0x7a9084e318,2,ret,0x7a9084e284,0x7708160d8c,1,ret,0x7708160db4,0x77080a0c98,0,ret,0x7a90855d34,0x7a907d89a8,5,ret,0x7a907d89b4,0x7a907da330,4,ret,0x7a90855ff4,0x7a907d8a3c,5,ret,0x7a907d8a4c,0x7a907da45c,4,ret,0x7a907da514,0x7a907dab70,3,ret,0x7a907dab84,0x7a907d5134,2,ret,0x7a907d514c,0x77081ca484,1,ret,0x77081ca4a0,0x77080a0ca4,0,ret,0x7a90855ed4,0x7a9084e854,1,ret,0x7a9084e888,0x77080a0cb8,0,ret,0x77080a0cd8,0x7708165ba8,-1,ret,0x7a90855d34,0x7a907d89a8,4,ret,0x7a907d89b4,0x7a907da330,3,ret,0x7a90855ff4,0x7a907d8a3c,4,ret,0x7a907d8a4c,0x7a907da45c,3,ret,0x7a907da514,0x7a907dab70,2,ret,0x7a907dab84,0x7a907d5134,1,ret,0x7a907d514c,0x77081ca484,0,ret,0x77081ca4a0,0x7708165bbc,-1,ret,0x770809fd08,0x770815fb6c,0,ret,0x770815fbb0,0x770815fb90,0,ret,0x770809fd08,0x770815fbe4,0,ret,0x7708164948,0x7708164928,1,ret,0x77081649b0,0x7708164994,1,ret,0x77081649b0,0x77081649cc,1,ret,0x7708164a10,0x770815fbf8,0,ret,0x770815fde4,0x7708165bd8,-1,ret,0x7a907e2310,0x77ee69b978,0,ret,0x77ee47dc04,0x77ee69bcdc,0,ret,0x77ee6b7d1c,0x77ee6b6618,1,ret,0x77ee6b6adc,0x77ee69bf40,0,ret,0x77ee5c880c,0x77ee4c3f70,1,ret,0x77ee4c3fa8,0x77ee69bf50,0
+++ into iterator: startAddress=0x77ee853518, isAppCode=false
...
+++ into iterator: startAddress=0x77ee858198, isAppCode=false
>>> into onReceive: parsedEvents=ret,0x77ee47dc04,0x77ee47df90,2,ret,0x77ee47e1b4,0x77ee85355c,1,ret,0x7a90855df4,0x7a907dec6c,3,ret,0x7a90855d34,0x7a907d89a8,4,ret,0x7a907d89b4,0x7a907decb0,3,ret,0x7a90855ff4,0x7a907d8a3c,3,ret,0x7a907d8a4c,0x7a907da9c4,2,ret,0x7a907da9d4,0x77ee853590,1,ret,0x77ee47dc74,0x77ee47edb0,2,ret,0x7a907e4f5c,0x77ee47ee90,2,ret,0x77ee47ed44,0x77ee8535b0,1,ret,0x7a907fa42c,0x7a88f5e248,4,ret,0x7a88f5e270,0x77f0731598,3,ret,0x77f07315a8,0x7aa249f254,2,ret,0x7aa249f25c,0x77ee8535bc,1,ret,0x775995f484,0x77ee8535d4,1,ret,0x7a907fa42c,0x7a88f5e248,4,ret,0x7a88f5e270,0x77f07315c4,3,ret,0x77f07315d0,0x7aa249f2d0,2,ret,0x7aa249f2d4,0x77ee8535d8,1,ret,0x77ee8535f8,0x77ee69c198,0,ret,0x77ee47dc04,0x77ee47df90,2,ret,0x77ee47e1b4,0x77ee85355c,1,ret,0x7a90855df4,0x7a907dec6c,3,ret,0x7a90855d34,0x7a907d89a8,4,ret,0x7a907d89b4,0x7a907decb0,3,ret,0x7a90855ff4,0x7a907d8a3c,3,ret,0x7a907d8a4c,0x7a907da9c4,2,ret,0x7a907da9d4,0x77ee853590,1,ret,0x77ee47dc74,0x77ee47edb0,2,ret,0x77ee47ed44,0x77ee8535b0,1,ret,0x7a907fa42c,0x7a88f5e248,4,ret,0x7a88f5e270,0x77f0731598,3,ret,0x77f07315a8,0x7aa249f254,2,ret,0x7aa249f25c,0x77ee8535bc,1,ret,0x775995f484,0x77ee8535d4,1,ret,0x7a907fa42c,0x7a88f5e248,4,ret,0x7a88f5e270,0x77f07315c4,3,ret,0x77f07315d0,0x7aa249f2d0,2,ret,0x7aa249f2d4,0x77ee8535d8,1,ret,0x77ee8535f8,0x77ee69c198,0,ret,0x77ee47dc04,0x77ee47df90,2,ret,0x77ee47e1b4,0x77ee85355c,1,ret,0x7a90855df4,0x7a907dec6c,3,ret,0x7a90855d34,0x7a907d89a8,4,ret,0x7a907d89b4,0x7a907decb0,3,ret,0x7a90855ff4,0x7a907d8a3c,3,ret,0x7a907d8a4c,0x7a907da9c4,2,ret,0x7a907da9d4,0x77ee853590,1,ret,0x77ee47dc74,0x77ee47edb0,2,ret,0x77ee47ed44,0x77ee8535b0,1,ret,0x7a907fa42c,0x7a88f5e248,4,ret,0x7a88f5e270,0x77f0731598,3,ret,0x77f07315a8,0x7aa249f254,2,ret,0x7aa249f25c,0x77ee8535bc,1,ret,0x775995f484,0x77ee8535d4,1,ret,0x7a907fa42c,0x7a88f5e248,4,ret,0x7a88f5e270,0x77f07315c4,3,ret,0x77f07315d0,0x7aa249f2d0,2,ret,0x7aa249f2d4,0x77ee8535d8,1,ret,0x77ee8535f8,0x77ee69c198,0,ret,0x77ee47dc04,0x77ee47df90,2,ret,0x77ee47e1b4,0x77ee85355c,1,ret,0x7a90855df4,0x7a907dec6c,3,ret,0x7a90855d34,0x7a907d89a8,4,ret,0x7a907d89b4,0x7a907decb0,3,ret,0x7a90855ff4,0x7a907d8a3c,3,ret,0x7a907d8a4c,0x7a907da9c4,2,ret,0x7a907da9d4,0x77ee853590,1,ret,0x77ee47dc74,0x77ee47edb0,2,ret,0x77ee47ed44,0x77ee8535b0,1,ret,0x7a907fa42c,0x7a88f5e248,4,ret,0x7a88f5e270,0x77f0731598,3,ret,0x77f07315a8,0x7aa249f254,2,ret,0x7aa249f25c,0x77ee8535bc,1,ret,0x775995f484,0x77ee8535d4,1,ret,0x7a907fa42c,0x7a88f5e248,4,ret,0x7a88f5e270,0x77f07315c4,3,ret,0x77f07315d0,0x7aa249f2d0,2,ret,0x7aa249f2d4,0x77ee8535d8,1,ret,0x77ee8535f8,0x77ee69c198,0,ret,0x77ee47dc04,0x77ee47df90,2,ret,0x77ee47e1b4,0x77ee85355c,1,ret,0x7a90855df4,0x7a907dec6c,3,ret,0x7a90855d34,0x7a907d89a8,4,ret,0x7a907d89b4,0x7a907decb0,3,ret,0x7a90855ff4,0x7a907d8a3c,3,ret,0x7a907d8a4c,0x7a907da9c4,2,ret,0x7a907da9d4,0x77ee853590,1,ret,0x77ee47dc74,0x77ee47edb0,2,ret,0x77ee47ed44,0x77ee8535b0,1,ret,0x7a907fa42c,0x7a88f5e248,4,ret,0x7a88f5e270,0x77f0731598,3,ret,0x77f07315a8,0x7aa249f254,2,ret,0x7aa249f25c,0x77ee8535bc,1,ret,0x775995f484,0x77ee8535d4,1,ret,0x7a907fa42c,0x7a88f5e248,4,ret,0x7a88f5e270,0x77f07315c4,3,ret,0x77f07315d0,0x7aa249f2d0,2,ret,0x7aa249f2d4,0x77ee8535d8,1,ret,0x77ee8535f8,0x77ee69c198,0,ret,0x77ee47dc04,0x77ee47df90,2,ret,0x77ee47e1b4,0x77ee85355c,1,ret,0x7a90855df4,0x7a907dec6c,3,ret,0x7a90855d34,0x7a907d89a8,4,ret,0x7a907d89b4,0x7a907decb0,3,ret,0x7a90855ff4,0x7a907d8a3c,3,ret,0x7a907d8a4c,0x7a907da9c4,2,ret,0x7a907da9d4,0x77ee853590,1,ret,0x77ee47dc74,0x77ee47edb0,2,ret,0x77ee47ed44,0x77ee8535b0,1,ret,0x7a907fa42c,0x7a88f5e248,4,ret,0x7a88f5e270,0x77f0731598,3,ret,0x77f07315a8,0x7aa249f254,2,ret,0x7aa249f25c,0x77ee8535bc,1,ret,0x775995f484,0x77ee8535d4,1,ret,0x7a907fa42c,0x7a88f5e248,4,ret,0x7a88f5e270,0x77f07315c4,3,ret,0x77f07315d0,0x7aa249f2d0,2,ret,0x7aa249f2d4,0x77ee8535d8,1,ret,0x77ee8535f8,0x77ee69c198,0,ret,0x77ee47dc04,0x77ee47df90,2,ret,0x77ee47e1b4,0x77ee85355c,1,ret,0x7a90855df4,0x7a907dec6c,3,ret,0x7a90855d34,0x7a907d89a8,4,ret,0x7a907d89b4,0x7a907decb0,3,ret,0x7a90855ff4,0x7a907d8a3c,3,ret,0x7a907d8a4c,0x7a907da9c4,2,ret,0x7a907da9d4,0x77ee853590,1,ret,0x77ee47dc74,0x77ee47edb0,2,ret,0x7a907e4f5c,0x77ee47ee90,2,ret,0x77ee47ed44,0x77ee8535b0,1,ret,0x7a907fa42c,0x7a88f5e248,4,ret,0x7a88f5e270,0x77f0731598,3,ret,0x77f07315a8,0x7aa249f254,2,ret,0x7aa249f25c,0x77ee8535bc,1,ret,0x775995f484,0x77ee8535d4,1,ret,0x7a907fa42c,0x7a88f5e248,4,ret,0x7a88f5e270,0x77f07315c4,3,ret,0x77f07315d0,0x7aa249f2d0,2,ret,0x7aa249f2d4,0x77ee8535d8,1,ret,0x77ee8535f8,0x77ee69c198,0,ret,0x77ee47dc04,0x77ee47df90,2,ret,0x77ee47e1b4,0x77ee85355c,1,ret,0x7a90855df4,0x7a907dec6c,3,ret,0x7a90855d34,0x7a907d89a8,4,ret,0x7a907d89b4,0x7a907decb0,3,ret,0x7a90855ff4,0x7a907d8a3c,3,ret,0x7a907d8a4c,0x7a907da9c4,2,ret,0x7a907da9d4,0x77ee853590,1,ret,0x77ee47dc74,0x77ee47edb0,2,ret,0x77ee47ed44,0x77ee8535b0,1,ret,0x7a907fa42c,0x7a88f5e248,4,ret,0x7a88f5e270,0x77f0731598,3,ret,0x77f07315a8,0x7aa249f254,2,ret,0x7aa249f25c,0x77ee8535bc,1,ret,0x775995f484,0x77ee8535d4,1,ret,0x7a907fa42c,0x7a88f5e248,4,ret,0x7a88f5e270,0x77f07315c4,3,ret,0x77f07315d0,0x7aa249f2d0,2,ret,0x7aa249f2d4,0x77ee8535d8,1,ret,0x77ee8535f8,0x77ee69c198,0,ret,0x77ee47dc04,0x77ee47df90,2,ret,0x77ee47e1b4,0x77ee85355c,1,ret,0x7a90855df4,0x7a907dec6c,3,ret,0x7a90855d34,0x7a907d89a8,4,ret,0x7a907d89b4,0x7a907decb0,3,ret,0x7a90855ff4,0x7a907d8a3c,3,ret,0x7a907d8a4c,0x7a907da9c4,2,ret,0x7a907da9d4,0x77ee853590,1,ret,0x77ee47dc74,0x77ee47edb0,2,ret,0x77ee47ed44,0x77ee8535b0,1,ret,0x7a907fa42c,0x7a88f5e248,4,ret,0x7a88f5e270,0x77f0731598,3,ret,0x77f07315a8,0x7aa249f254,2,ret,0x7aa249f25c,0x77ee8535bc,1,ret,0x77ee41d1b4,0x77ee4c4bb0,2,ret,0x77ee4c5114,0x77ee8535d4,1,ret,0x7a907fa42c,0x7a88f5e248,4,ret,0x7a88f5e270,0x77f07315c4,3,ret,0x77f07315d0,0x7aa249f2d0,2,ret,0x7aa249f2d4,0x77ee8535d8,1,ret,0x77ee8535f8,0x77ee69c198,0,ret,0x77ee47dc04,0x77ee47df90,2,ret,0x77ee47e1b4,0x77ee85355c,1,ret,0x7a90855df4,0x7a907dec6c,3,ret,0x7a90855d34,0x7a907d89a8,4,ret,0x7a907d89b4,0x7a907decb0,3,ret,0x7a90855d34,0x7a907d89a8,6,ret,0x7a907d89b4,0x7a907dc50c,5,ret,0x7a907dc518,0x7a907dcee4,4,ret,0x7a90855ff4,0x7a907d8a3c,5,ret,0x7a907d8a4c,0x7a907dcf00,4,ret,0x7a90855d34,0x7a907d89a8,5,ret,0x7a907d89b4,0x7a907dcf30,4,ret,0x7a907dcfe8,0x7a907ded74,3,ret,0x7a90855ff4,0x7a907d8a3c,3,ret,0x7a907d8a4c,0x7a907da9c4,2,ret,0x7a907da9d4,0x77ee853590,1,ret,0x77ee47dc74,0x77ee47edb0,2,ret,0x7a907e4f5c,0x77ee47ee90,2,ret,0x77ee47ed44,0x77ee8535b0,1,ret,0x7a907fa42c,0x7a88f5e248,4,ret,0x7a88f5e270,0x77f0731598,3,ret,0x77f07315a8,0x7aa249f254,2,ret,0x7aa249f25c,0x77ee8535bc,1,ret,0x775995f484,0x77ee8535d4,1,ret,0x7a907fa42c,0x7a88f5e248,4,ret,0x7a88f5e270,0x77f07315c4,3,ret,0x77f07315d0,0x7aa249f2d0,2,ret,0x7aa249f2d4,0x77ee8535d8,1,ret,0x77ee8535f8,0x77ee69c198,0,ret,0x7a907fa42c,0x7a88f5e248,6,ret,0x7a88f5e270,0x77f0731568,5,ret,0x77f0731580,0x7aa249f1d4,4,ret,0x7aa249f1dc,0x77ee47e214,3,ret,0x77ee47e28c,0x77ee47dfc0,2,ret,0x77ee47e35c,0x77ee47dfcc,2,ret,0x7a907fa42c,0x7a88f5e248,5,ret,0x7a88f5e270,0x77f07315c4,4,ret,0x77f07315d0,0x7aa249f2d0,3,ret,0x7aa249f2d4,0x77ee47e130,2,ret,0x77ee47dc04,0x77ee47df90,2,ret,0x77ee47e1b4,0x77ee85355c,1,ret,0x7a90855df4,0x7a907dec6c,3,ret,0x7a90855d34,0x7a907d89a8,4,ret,0x7a907d89b4,0x7a907decb0,3,ret,0x7a90855ff4,0x7a907d8a3c,3,ret,0x7a907d8a4c,0x7a907da9c4,2,ret,0x7a907da9d4,0x77ee853590,1,ret,0x77ee47dc74,0x77ee47edb0,2,ret,0x77ee47ed44,0x77ee8535b0,1,ret,0x7a907fa42c,0x7a88f5e248,4,ret,0x7a88f5e270,0x77f0731598,3,ret,0x77f07315a8,0x7aa249f254,2,ret,0x7aa249f25c,0x77ee8535bc,1,ret,0x775995f484,0x77ee8535d4,1,ret,0x7a907fa42c,0x7a88f5e248,4,ret,0x7a88f5e270,0x77f07315c4,3,ret,0x77f07315d0,0x7aa249f2d0,2,ret,0x7aa249f2d4,0x77ee8535d8,1,ret,0x77ee8535f8,0x77ee69c198,0,ret,0x77ee47dc04,0x77ee47df90,2,ret,0x77ee47e1b4,0x77ee85355c,1,ret,0x7a90855df4,0x7a907dec6c,3,ret,0x7a90855d34,0x7a907d89a8,4,ret,0x7a907d89b4,0x7a907decb0,3,ret,0x7aa3c2c440,0x7a907e4120,5,ret,0x7a907e412c,0x7a907d8a98,4,ret,0x7a907d8ab0,0x7a907ded64,3,ret,0x7a90855d34,0x7a907d89a8,6,ret,0x7a907d89b4,0x7a907dc50c,5,ret,0x7a907dc518,0x7a907dcee4,4,ret,0x7a90855ff4,0x7a907d8a3c,5,ret,0x7a907d8a4c,0x7a907dcf00,4,ret,0x7a90855d34,0x7a907d89a8,5,ret,0x7a907d89b4,0x7a907dcf30,4,ret,0x7a907dcfe8,0x7a907ded74,3,ret,0x7a90855ff4,0x7a907d8a3c,3,ret,0x7a907d8a4c,0x7a907da9c4,2,ret,0x7a907da9d4,0x77ee853590,1,ret,0x77ee47dc74,0x77ee47edb0,2,ret,0x7a907e4f5c,0x77ee47ee90,2,ret,0x77ee47ed44,0x77ee8535b0,1,ret,0x7a907fa42c,0x7a88f5e248,4,ret,0x7a88f5e270,0x77f0731598,3,ret,0x77f07315a8,0x7aa249f254,2,ret,0x7aa249f25c,0x77ee8535bc,1,ret,0x775995f484,0x77ee8535d4,1,ret,0x7a907fa42c,0x7a88f5e248,4,ret,0x7a88f5e270,0x77f07315c4,3,ret,0x77f07315d0,0x7aa249f2d0,2,ret,0x7aa249f2d4,0x77ee8535d8,1,ret,0x77ee8535f8,0x77ee69c198,0,ret,0x77ee47dc04,0x77ee47df90,2,ret,0x77ee47e1b4,0x77ee85355c,1,ret,0x7a90855df4,0x7a907dec6c,3,ret,0x7a90855d34,0x7a907d89a8,4,ret,0x7a907d89b4,0x7a907decb0,3,ret,0x7a90855ff4,0x7a907d8a3c,3,ret,0x7a907d8a4c,0x7a907da9c4,2,ret,0x7a907da9d4,0x77ee853590,1,ret,0x77ee47dc74,0x77ee47edb0,2,ret,0x7a907e4f5c,0x77ee47ee90,2,ret,0x77ee47ed44,0x77ee8535b0,1,ret,0x7a907fa42c,0x7a88f5e248,4,ret,0x7a88f5e270,0x77f0731598,3,ret,0x77f07315a8,0x7aa249f254,2,ret,0x7aa249f25c,0x77ee8535bc,1,ret,0x77ee41d1b4,0x77ee4c4bb0,2,ret,0x77ee4c5114,0x77ee8535d4,1,ret,0x7a907fa42c,0x7a88f5e248,4,ret,0x7a88f5e270,0x77f07315c4,3,ret,0x77f07315d0,0x7aa249f2d0,2,ret,0x7aa249f2d4,0x77ee8535d8,1,ret,0x77ee8535f8,0x77ee69c198,0,ret,0x77ee47dc04,0x77ee47df90,2,ret,0x77ee47e1b4,0x77ee85355c,1,ret,0x7a90855df4,0x7a907dec6c,3,ret,0x7a90855d34,0x7a907d89a8,4,ret,0x7a907d89b4,0x7a907decb0,3,ret,0x7a90855ff4,0x7a907d8a3c,3,ret,0x7a907d8a4c,0x7a907da9c4,2,ret,0x7a907da9d4,0x77ee853590,1,ret,0x77ee47dc74,0x77ee47edb0,2,ret,0x7a907e4f5c,0x77ee47ee90,2,ret,0x77ee47ed44,0x77ee8535b0,1,ret,0x7a907fa42c,0x7a88f5e248,4,ret,0x7a88f5e270,0x77f0731598,3,ret,0x77f07315a8,0x7aa249f254,2,ret,0x7aa249f25c,0x77ee8535bc,1,ret,0x77ee41d1b4,0x77ee4c4bb0,2,ret,0x77ee4c5114,0x77ee8535d4,1,ret,0x7a907fa42c,0x7a88f5e248,4,ret,0x7a88f5e270,0x77f07315c4,3,ret,0x77f07315d0,0x7aa249f2d0,2,ret,0x7aa249f2d4,0x77ee8535d8,1,ret,0x77ee8535f8,0x77ee69c198,0,ret,0x7a907fa42c,0x7a88f5e248,6,ret,0x7a88f5e270,0x77f0731568,5,ret,0x77f0731580,0x7aa249f1d4,4,ret,0x7aa249f1dc,0x77ee47e214,3,ret,0x77ee47e28c,0x77ee47dfc0,2,ret,0x77ee47e35c,0x77ee47dfcc,2,ret,0x7a907fa42c,0x7a88f5e248,5,ret,0x7a88f5e270,0x77f07315c4,4,ret,0x77f07315d0,0x7aa249f2d0,3,ret,0x7aa249f2d4,0x77ee47e130,2,ret,0x77ee47dc04,0x77ee47df90,2,ret,0x77ee47e1b4,0x77ee85355c,1,ret,0x7a90855df4,0x7a907dec6c,3,ret,0x7a90855d34,0x7a907d89a8,4,ret,0x7a907d89b4,0x7a907decb0,3,ret,0x7a90855ff4,0x7a907d8a3c,3,ret,0x7a907d8a4c,0x7a907da9c4,2,ret,0x7a907da9d4,0x77ee853590,1,ret,0x77ee47dc74,0x77ee47edb0,2,ret,0x7a907e4f5c,0x77ee47ee90,2,ret,0x77ee47ed44,0x77ee8535b0,1,ret,0x7a907fa42c,0x7a88f5e248,4,ret,0x7a88f5e270,0x77f0731598,3,ret,0x77f07315a8,0x7aa249f254,2,ret,0x7aa249f25c,0x77ee8535bc,1,ret,0x775995f484,0x77ee8535d4,1,ret,0x7a907fa42c,0x7a88f5e248,4,ret,0x7a88f5e270,0x77f07315c4,3,ret,0x77f07315d0,0x7aa249f2d0,2,ret,0x7aa249f2d4,0x77ee8535d8,1,ret,0x77ee8535f8,0x77ee69c198,0,ret,0x77ee47dc04,0x77ee47df90,2,ret,0x77ee47e1b4,0x77ee85355c,1,ret,0x7a90855df4,0x7a907dec6c,3,ret,0x7a90855d34,0x7a907d89a8,4,ret,0x7a907d89b4,0x7a907decb0,3,ret,0x7a90855ff4,0x7a907d8a3c,3,ret,0x7a907d8a4c,0x7a907da9c4,2,ret,0x7a907da9d4,0x77ee853590,1,ret,0x77ee47dc74,0x77ee47edb0,2,ret,0x7a907e4f5c,0x77ee47ee90,2,ret,0x77ee47ed44,0x77ee8535b0,1,ret,0x7a907fa42c,0x7a88f5e248,4,ret,0x7a88f5e270,0x77f0731598,3,ret,0x77f07315a8,0x7aa249f254,2,ret,0x7aa249f25c,0x77ee8535bc,1,ret,0x77ee41d1b4,0x77ee4c4bb0,2,ret,0x77ee4c5114,0x77ee8535d4,1,ret,0x7a907fa42c,0x7a88f5e248,4,ret,0x7a88f5e270,0x77f07315c4,3,ret,0x77f07315d0,0x7aa249f2d0,2,ret,0x7aa249f2d4,0x77ee8535d8,1,ret,0x77ee8535f8,0x77ee69c198,0,ret,0x77ee47dc04,0x77ee47df90,2,ret,0x77ee47e1b4,0x77ee85355c,1,ret,0x7a90855df4,0x7a907dec6c,3,ret,0x7a90855d34,0x7a907d89a8,4,ret,0x7a907d89b4,0x7a907decb0,3,ret,0x7a90855ff4,0x7a907d8a3c,3,ret,0x7a907d8a4c,0x7a907da9c4,2,ret,0x7a907da9d4,0x77ee853590,1,ret,0x77ee47dc74,0x77ee47edb0,2,ret,0x7a907e4f5c,0x77ee47ee90,2,ret,0x77ee47ed44,0x77ee8535b0,1,ret,0x7a907fa42c,0x7a88f5e248,4,ret,0x7a88f5e270,0x77f0731598,3,ret,0x77f07315a8,0x7aa249f254,2,ret,0x7aa249f25c,0x77ee8535bc,1,ret,0x77ee41d1b4,0x77ee4c4bb0,2,ret,0x77ee4c5114,0x77ee8535d4,1,ret,0x7a907fa42c,0x7a88f5e248,4,ret,0x7a88f5e270,0x77f07315c4,3,ret,0x77f07315d0,0x7aa249f2d0,2,ret,0x7aa249f2d4,0x77ee8535d8,1,ret,0x77ee8535f8,0x77ee69c198,0,ret,0x77ee47dc04,0x77ee47df90,2,ret,0x77ee47e1b4,0x77ee85355c,1,ret,0x7a90855df4,0x7a907dec6c,3,ret,0x7a90855d34,0x7a907d89a8,4,ret,0x7a907d89b4,0x7a907decb0,3,ret,0x7a90855ff4,0x7a907d8a3c,3,ret,0x7a907d8a4c,0x7a907da9c4,2,ret,0x7a907da9d4,0x77ee853590,1,ret,0x77ee47dc74,0x77ee47edb0,2,ret,0x7a907e4f5c,0x77ee47ee90,2,ret,0x77ee47ed44,0x77ee8535b0,1,ret,0x7a907fa42c,0x7a88f5e248,4,ret,0x7a88f5e270,0x77f0731598,3,ret,0x77f07315a8,0x7aa249f254,2,ret,0x7aa249f25c,0x77ee8535bc,1,ret,0x77ee41d1b4,0x77ee4c4bb0,2,ret,0x77ee4c5114,0x77ee8535d4,1,ret,0x7a907fa42c,0x7a88f5e248,4,ret,0x7a88f5e270,0x77f07315c4,3,ret,0x77f07315d0,0x7aa249f2d0,2,ret,0x7aa249f2d4,0x77ee8535d8,1,ret,0x77ee8535f8,0x77ee69c198,0,ret,0x7a907fa42c,0x7a88f5e248,6,ret,0x7a88f5e270,0x77f0731568,5,ret,0x77f0731580,0x7aa249f1d4,4,ret,0x7aa249f1dc,0x77ee47e214,3,ret,0x77ee47e28c,0x77ee47dfc0,2,ret,0x77ee47e35c,0x77ee47dfcc,2,ret,0x7a907fa42c,0x7a88f5e248,5,ret,0x7a88f5e270,0x77f07315c4,4,ret,0x77f07315d0,0x7aa249f2d0,3,ret,0x7aa249f2d4,0x77ee47e130,2,ret,0x77ee47dc04,0x77ee47df90,2,ret,0x77ee47e1b4,0x77ee85355c,1,ret,0x7a90855df4,0x7a907dec6c,3,ret,0x7a90855d34,0x7a907d89a8,4,ret,0x7a907d89b4,0x7a907decb0,3,ret,0x7a90855ff4,0x7a907d8a3c,3,ret,0x7a907d8a4c,0x7a907da9c4,2,ret,0x7a907da9d4,0x77ee853590,1,ret,0x77ee47dc74,0x77ee47edb0,2,ret,0x7a907e4f5c,0x77ee47ee90,2,ret,0x77ee47ed44,0x77ee8535b0,1,ret,0x7a907fa42c,0x7a88f5e248,4,ret,0x7a88f5e270,0x77f0731598,3,ret,0x77f07315a8,0x7aa249f254,2,ret,0x7aa249f25c,0x77ee8535bc,1,ret,0x77ee41d1b4,0x77ee4c4bb0,2,ret,0x77ee4c5114,0x77ee8535d4,1,ret,0x7a907fa42c,0x7a88f5e248,4,ret,0x7a88f5e270,0x77f07315c4,3,ret,0x77f07315d0,0x7aa249f2d0,2,ret,0x7aa249f2d4,0x77ee8535d8,1,ret,0x77ee8535f8,0x77ee69c198,0,ret,0x77ee47dc04,0x77ee47df90,2,ret,0x77ee47e1b4,0x77ee85355c,1,ret,0x7a90855df4,0x7a907dec6c,3,ret,0x7a90855d34,0x7a907d89a8,4,ret,0x7a907d89b4,0x7a907decb0,3,ret,0x7a90855ff4,0x7a907d8a3c,3,ret,0x7a907d8a4c,0x7a907da9c4,2,ret,0x7a907da9d4,0x77ee853590,1,ret,0x77ee47dc74,0x77ee47edb0,2,ret,0x7a907e4f5c,0x77ee47ee90,2,ret,0x77ee47ed44,0x77ee8535b0,1,ret,0x7a907fa42c,0x7a88f5e248,4,ret,0x7a88f5e270,0x77f0731598,3,ret,0x77f07315a8,0x7aa249f254,2,ret,0x7aa249f25c,0x77ee8535bc,1,ret,0x775995f484,0x77ee8535d4,1,ret,0x7a907fa42c,0x7a88f5e248,4,ret,0x7a88f5e270,0x77f07315c4,3,ret,0x77f07315d0,0x7aa249f2d0,2,ret,0x7aa249f2d4,0x77ee8535d8,1,ret,0x77ee8535f8,0x77ee69c198,0,ret,0x77ee47dc04,0x77ee47df90,2,ret,0x77ee47e1b4,0x77ee85355c,1,ret,0x7a90855df4,0x7a907dec6c,3,ret,0x7a90855d34,0x7a907d89a8,4,ret,0x7a907d89b4,0x7a907decb0,3,ret,0x7a90855ff4,0x7a907d8a3c,3,ret,0x7a907d8a4c,0x7a907da9c4,2,ret,0x7a907da9d4,0x77ee853590,1,ret,0x77ee47dc74,0x77ee47edb0,2,ret,0x7a907e4f5c,0x77ee47ee90,2,ret,0x77ee47ed44,0x77ee8535b0,1,ret,0x7a907fa42c,0x7a88f5e248,4,ret,0x7a88f5e270,0x77f0731598,3,ret,0x77f07315a8,0x7aa249f254,2,ret,0x7aa249f25c,0x77ee8535bc,1,ret,0x775995f484,0x77ee8535d4,1,ret,0x7a907fa42c,0x7a88f5e248,4,ret,0x7a88f5e270,0x77f07315c4,3,ret,0x77f07315d0,0x7aa249f2d0,2,ret,0x7aa249f2d4,0x77ee8535d8,1,ret,0x77ee8535f8,0x77ee69c198,0,ret,0x7a907fa42c,0x7a88f5e248,6,ret,0x7a88f5e270,0x77f0731568,5,ret,0x77f0731580,0x7aa249f1d4,4,ret,0x7aa249f1dc,0x77ee47e214,3,ret,0x77ee47e28c,0x77ee47dfc0,2,ret,0x77ee47e35c,0x77ee47dfcc,2,ret,0x77ee47dc44,0x77ee47dfdc,2,ret,0x7a907e88a0,0x7a90838c08,3,ret,0x7a90838c1c,0x77ee47e040,2,ret,0x7a907e88a0,0x77ee47e048,2,ret,0x77ee47dc44,0x77ee47e12c,2,ret,0x7a907fa42c,0x7a88f5e248,5,ret,0x7a88f5e270,0x77f07315c4,4,ret,0x77f07315d0,0x7aa249f2d0,3,ret,0x7aa249f2d4,0x77ee47e130,2,ret,0x77ee47dc04,0x77ee47df90,2,ret,0x77ee47e1b4,0x77ee85355c,1,ret,0x7a90855df4,0x7a907dec6c,3,ret,0x7a90855d34,0x7a907d89a8,4,ret,0x7a907d89b4,0x7a907decb0,3,ret,0x7a90855ff4,0x7a907d8a3c,3,ret,0x7a907d8a4c,0x7a907da9c4,2,ret,0x7a907da9d4,0x77ee853590,1,ret,0x77ee47dc74,0x77ee47edb0,2,ret,0x7a907e4f5c,0x77ee47ee90,2,ret,0x77ee47ed44,0x77ee8535b0,1,ret,0x7a907fa42c,0x7a88f5e248,4,ret,0x7a88f5e270,0x77f0731598,3,ret,0x77f07315a8,0x7aa249f254,2,ret,0x7aa249f25c,0x77ee8535bc,1,ret,0x77ee41d1b4,0x77ee4c4bb0,2,ret,0x77ee4c5114,0x77ee8535d4,1,ret,0x7a907fa42c,0x7a88f5e248,4,ret,0x7a88f5e270,0x77f07315c4,3,ret,0x77f07315d0,0x7aa249f2d0,2,ret,0x7aa249f2d4,0x77ee8535d8,1,ret,0x77ee8535f8,0x77ee69c198,0,ret,0x77ee47dc04,0x77ee47df90,2,ret,0x77ee47e1b4,0x77ee85355c,1,ret,0x7a90855df4,0x7a907dec6c,3,ret,0x7a90855d34,0x7a907d89a8,4,ret,0x7a907d89b4,0x7a907decb0,3,ret,0x7a90855ff4,0x7a907d8a3c,3,ret,0x7a907d8a4c,0x7a907da9c4,2,ret,0x7a907da9d4,0x77ee853590,1,ret,0x77ee47dc74,0x77ee47edb0,2,ret,0x77ee47ed44,0x77ee8535b0,1,ret,0x7a907fa42c,0x7a88f5e248,4,ret,0x7a88f5e270,0x77f0731598,3,ret,0x77f07315a8,0x7aa249f254,2,ret,0x7aa249f25c,0x77ee8535bc,1,ret,0x775995f484,0x77ee8535d4,1,ret,0x7a907fa42c,0x7a88f5e248,4,ret,0x7a88f5e270,0x77f07315c4,3,ret,0x77f07315d0,0x7aa249f2d0,2,ret,0x7aa249f2d4,0x77ee8535d8,1,ret,0x77ee8535f8,0x77ee69c198,0,ret,0x77ee47dc04,0x77ee47df90,2,ret,0x77ee47e1b4,0x77ee85355c,1,ret,0x7a90855df4,0x7a907dec6c,3,ret,0x7a90855d34,0x7a907d89a8,4,ret,0x7a907d89b4,0x7a907decb0,3,ret,0x7a90855ff4,0x7a907d8a3c,3,ret,0x7a907d8a4c,0x7a907da9c4,2,ret,0x7a907da9d4,0x77ee853590,1,ret,0x77ee47dc74,0x77ee47edb0,2,ret,0x77ee47ed44,0x77ee8535b0,1,ret,0x7a907fa42c,0x7a88f5e248,4,ret,0x7a88f5e270,0x77f0731598,3,ret,0x77f07315a8,0x7aa249f254,2,ret,0x7aa249f25c,0x77ee8535bc,1,ret,0x77ee41d1b4,0x77ee4c4bb0,2,ret,0x77ee4c5114,0x77ee8535d4,1,ret,0x7a907fa42c,0x7a88f5e248,4,ret,0x7a88f5e270,0x77f07315c4,3,ret,0x77f07315d0,0x7aa249f2d0,2,ret,0x7aa249f2d4,0x77ee8535d8,1,ret,0x77ee8535f8,0x77ee69c198,0,ret,0x77ee47dc04,0x77ee47df90,2,ret,0x77ee47e1b4,0x77ee85355c,1,ret,0x7a90855df4,0x7a907dec6c,3,ret,0x7a90855d34,0x7a907d89a8,4,ret,0x7a907d89b4,0x7a907decb0,3,ret,0x7a90855ff4,0x7a907d8a3c,3,ret,0x7a907d8a4c,0x7a907da9c4,2,ret,0x7a907da9d4,0x77ee853590,1,ret,0x77ee47dc74,0x77ee47edb0,2,ret,0x77ee47ed44,0x77ee8535b0,1,ret,0x7a907fa42c,0x7a88f5e248,4,ret,0x7a88f5e270,0x77f0731598,3,ret,0x77f07315a8,0x7aa249f254,2,ret,0x7aa249f25c,0x77ee8535bc,1,ret,0x775995f484,0x77ee8535d4,1,ret,0x7a907fa42c,0x7a88f5e248,4,ret,0x7a88f5e270,0x77f07315c4,3,ret,0x77f07315d0,0x7aa249f2d0,2,ret,0x7aa249f2d4,0x77ee8535d8,1,ret,0x77ee8535f8,0x77ee69c198,0,ret,0x77ee47dc04,0x77ee47df90,2,ret,0x77ee47e1b4,0x77ee85355c,1,ret,0x7a90855df4,0x7a907dec6c,3,ret,0x7a90855d34,0x7a907d89a8,4,ret,0x7a907d89b4,0x7a907decb0,3,ret,0x7a90855ff4,0x7a907d8a3c,3,ret,0x7a907d8a4c,0x7a907da9c4,2,ret,0x7a907da9d4,0x77ee853590,1,ret,0x77ee47dc74,0x77ee47edb0,2,ret,0x77ee47ed44,0x77ee8535b0,1,ret,0x7a907fa42c,0x7a88f5e248,4,ret,0x7a88f5e270,0x77f0731598,3,ret,0x77f07315a8,0x7aa249f254,2,ret,0x7aa249f25c,0x77ee8535bc,1,ret,0x77ee41d1b4,0x77ee4c4bb0,2,ret,0x77ee4c5114,0x77ee8535d4,1,ret,0x7a907fa42c,0x7a88f5e248,4,ret,0x7a88f5e270,0x77f07315c4,3,ret,0x77f07315d0,0x7aa249f2d0,2,ret,0x7aa249f2d4,0x77ee8535d8,1,ret,0x77ee8535f8,0x77ee69c198,0,ret,0x77ee47dc04,0x77ee47df90,2,ret,0x77ee47e1b4,0x77ee85355c,1,ret,0x7a90855df4,0x7a907dec6c,3,ret,0x7a90855d34,0x7a907d89a8,4,ret,0x7a907d89b4,0x7a907decb0,3,ret,0x7a90855ff4,0x7a907d8a3c,3,ret,0x7a907d8a4c,0x7a907da9c4,2,ret,0x7a907da9d4,0x77ee853590,1,ret,0x77ee47dc74,0x77ee47edb0,2,ret,0x77ee47ed44,0x77ee8535b0,1,ret,0x7a907fa42c,0x7a88f5e248,4,ret,0x7a88f5e270,0x77f0731598,3,ret,0x77f07315a8,0x7aa249f254,2,ret,0x7aa249f25c,0x77ee8535bc,1,ret,0x77ee41d1b4,0x77ee4c4bb0,2,ret,0x77ee4c5114,0x77ee8535d4,1,ret,0x7a907fa42c,0x7a88f5e248,4,ret,0x7a88f5e270,0x77f07315c4,3,ret,0x77f07315d0,0x7aa249f2d0,2,ret,0x7aa249f2d4,0x77ee8535d8,1,ret,0x77ee8535f8,0x77ee69c198,0,ret,0x77ee47dc04,0x77ee47df90,2,ret,0x77ee47e1b4,0x77ee85355c,1,ret,0x7a90855df4,0x7a907dec6c,3,ret,0x7a90855d34,0x7a907d89a8,4,ret,0x7a907d89b4,0x7a907decb0,3,ret,0x7a90855ff4,0x7a907d8a3c,3,ret,0x7a907d8a4c,0x7a907da9c4,2,ret,0x7a907da9d4,0x77ee853590,1,ret,0x77ee47dc74,0x77ee47edb0,2,ret,0x77ee47ed44,0x77ee8535b0,1,ret,0x7a907fa42c,0x7a88f5e248,4,ret,0x7a88f5e270,0x77f0731598,3,ret,0x77f07315a8,0x7aa249f254,2,ret,0x7aa249f25c,0x77ee8535bc,1,ret,0x77ee41d1b4,0x77ee4c4bb0,2,ret,0x77ee4c5114,0x77ee8535d4,1,ret,0x7a907fa42c,0x7a88f5e248,4,ret,0x7a88f5e270,0x77f07315c4,3,ret,0x77f07315d0,0x7aa249f2d0,2,ret,0x7aa249f2d4,0x77ee8535d8,1,ret,0x77ee8535f8,0x77ee69c198,0,ret,0x77ee47dc04,0x77ee47df90,2,ret,0x77ee47e1b4,0x77ee85355c,1,ret,0x7a90855df4,0x7a907dec6c,3,ret,0x7a90855d34,0x7a907d89a8,4,ret,0x7a907d89b4,0x7a907decb0,3,ret,0x7a90855ff4,0x7a907d8a3c,3,ret,0x7a907d8a4c,0x7a907da9c4,2,ret,0x7a907da9d4,0x77ee853590,1,ret,0x77ee47dc74,0x77ee47edb0,2,ret,0x7a907e4f5c,0x77ee47ee90,2,ret,0x77ee47ed44,0x77ee8535b0,1,ret,0x7a907fa42c,0x7a88f5e248,4,ret,0x7a88f5e270,0x77f0731598,3,ret,0x77f07315a8,0x7aa249f254,2,ret,0x7aa249f25c,0x77ee8535bc,1,ret,0x775995f484,0x77ee8535d4,1,ret,0x7a907fa42c,0x7a88f5e248,4,ret,0x7a88f5e270,0x77f07315c4,3,ret,0x77f07315d0,0x7aa249f2d0,2,ret,0x7aa249f2d4,0x77ee8535d8,1,ret,0x77ee8535f8,0x77ee69c198,0,ret,0x77ee47dc04,0x77ee47df90,2,ret,0x77ee47e1b4,0x77ee85355c,1,ret,0x7a90855df4,0x7a907dec6c,3,ret,0x7a90855d34,0x7a907d89a8,4,ret,0x7a907d89b4,0x7a907decb0,3,ret,0x7a90855ff4,0x7a907d8a3c,3,ret,0x7a907d8a4c,0x7a907da9c4,2,ret,0x7a907da9d4,0x77ee853590,1,ret,0x77ee47dc74,0x77ee47edb0,2,ret,0x7a907e4f5c,0x77ee47ee90,2,ret,0x77ee47ed44,0x77ee8535b0,1,ret,0x7a907fa42c,0x7a88f5e248,4,ret,0x7a88f5e270,0x77f0731598,3,ret,0x77f07315a8,0x7aa249f254,2,ret,0x7aa249f25c,0x77ee8535bc,1,ret,0x77ee41d1b4,0x77ee4c4bb0,2,ret,0x77ee4c5114,0x77ee8535d4,1,ret,0x7a907fa42c,0x7a88f5e248,4,ret,0x7a88f5e270,0x77f07315c4,3,ret,0x77f07315d0,0x7aa249f2d0,2,ret,0x7aa249f2d4,0x77ee8535d8,1,ret,0x77ee8535f8,0x77ee69c198,0,ret,0x77ee47dc04,0x77ee47df90,2,ret,0x77ee47e1b4,0x77ee85355c,1,ret,0x7a90855df4,0x7a907dec6c,3,ret,0x7a90855d34,0x7a907d89a8,4,ret,0x7a907d89b4,0x7a907decb0,3,ret,0x7a90855ff4,0x7a907d8a3c,3,ret,0x7a907d8a4c,0x7a907da9c4,2,ret,0x7a907da9d4,0x77ee853590,1,ret,0x77ee47dc74,0x77ee47edb0,2,ret,0x7a907e4f5c,0x77ee47ee90,2,ret,0x77ee47ed44,0x77ee8535b0,1,ret,0x7a907fa42c,0x7a88f5e248,4,ret,0x7a88f5e270,0x77f0731598,3,ret,0x77f07315a8,0x7aa249f254,2,ret,0x7aa249f25c,0x77ee8535bc,1,ret,0x775995f484,0x77ee8535d4,1,ret,0x7a907fa42c,0x7a88f5e248,4,ret,0x7a88f5e270,0x77f07315c4,3,ret,0x77f07315d0,0x7aa249f2d0,2,ret,0x7aa249f2d4,0x77ee8535d8,1,ret,0x77ee8535f8,0x77ee69c198,0,ret,0x77ee47dc04,0x77ee47df90,2,ret,0x77ee47e1b4,0x77ee85355c,1,ret,0x7a90855df4,0x7a907dec6c,3,ret,0x7a90855d34,0x7a907d89a8,4,ret,0x7a907d89b4,0x7a907decb0,3,ret,0x7a90855ff4,0x7a907d8a3c,3,ret,0x7a907d8a4c,0x7a907da9c4,2,ret,0x7a907da9d4,0x77ee853590,1,ret,0x77ee47dc74,0x77ee47edb0,2,ret,0x7a907e4f5c,0x77ee47ee90,2,ret,0x77ee47ed44,0x77ee8535b0,1,ret,0x7a907fa42c,0x7a88f5e248,4,ret,0x7a88f5e270,0x77f0731598,3,ret,0x77f07315a8,0x7aa249f254,2,ret,0x7aa249f25c,0x77ee8535bc,1,ret,0x775995f484,0x77ee8535d4,1,ret,0x7a907fa42c,0x7a88f5e248,4,ret,0x7a88f5e270,0x77f07315c4,3,ret,0x77f07315d0,0x7aa249f2d0,2,ret,0x7aa249f2d4,0x77ee8535d8,1,ret,0x77ee8535f8,0x77ee69c198,0,ret,0x77ee47dc04,0x77ee47df90,2,ret,0x77ee47e1b4,0x77ee85355c,1,ret,0x7a90855df4,0x7a907dec6c,3,ret,0x7a90855d34,0x7a907d89a8,4,ret,0x7a907d89b4,0x7a907decb0,3,ret,0x7a90855ff4,0x7a907d8a3c,3,ret,0x7a907d8a4c,0x7a907da9c4,2,ret,0x7a907da9d4,0x77ee853590,1,ret,0x77ee47dc74,0x77ee47edb0,2,ret,0x7a907e4f5c,0x77ee47ee90,2,ret,0x77ee47ed44,0x77ee8535b0,1,ret,0x7a907fa42c,0x7a88f5e248,4,ret,0x7a88f5e270,0x77f0731598,3,ret,0x77f07315a8,0x7aa249f254,2,ret,0x7aa249f25c,0x77ee8535bc,1,ret,0x775995f484,0x77ee8535d4,1,ret,0x7a907fa42c,0x7a88f5e248,4,ret,0x7a88f5e270,0x77f07315c4,3,ret,0x77f07315d0,0x7aa249f2d0,2,ret,0x7aa249f2d4,0x77ee8535d8,1,ret,0x77ee8535f8,0x77ee69c198,0,ret,0x77ee47dc04,0x77ee47df90,2,ret,0x77ee47e1b4,0x77ee85355c,1,ret,0x7a90855df4,0x7a907dec6c,3,ret,0x7a90855d34,0x7a907d89a8,4,ret,0x7a907d89b4,0x7a907decb0,3,ret,0x7a90855ff4,0x7a907d8a3c,3,ret,0x7a907d8a4c,0x7a907da9c4,2,ret,0x7a907da9d4,0x77ee853590,1,ret,0x77ee47dc74,0x77ee47edb0,2,ret,0x7a907e4f5c,0x77ee47ee90,2,ret,0x77ee47ed44,0x77ee8535b0,1,ret,0x7a907fa42c,0x7a88f5e248,4,ret,0x7a88f5e270,0x77f0731598,3,ret,0x77f07315a8,0x7aa249f254,2,ret,0x7aa249f25c,0x77ee8535bc,1,ret,0x77ee41d1b4,0x77ee4c4bb0,2,ret,0x77ee4c5114,0x77ee8535d4,1,ret,0x7a907fa42c,0x7a88f5e248,4,ret,0x7a88f5e270,0x77f07315c4,3,ret,0x77f07315d0,0x7aa249f2d0,2,ret,0x7aa249f2d4,0x77ee8535d8,1,ret,0x77ee8535f8,0x77ee69c198,0,ret,0x77ee47dc04,0x77ee47df90,2,ret,0x77ee47e1b4,0x77ee85355c,1,ret,0x7a90855df4,0x7a907dec6c,3,ret,0x7a90855d34,0x7a907d89a8,4,ret,0x7a907d89b4,0x7a907decb0,3,ret,0x7a90855ff4,0x7a907d8a3c,3,ret,0x7a907d8a4c,0x7a907da9c4,2,ret,0x7a907da9d4,0x77ee853590,1,ret,0x77ee47dc74,0x77ee47edb0,2,ret,0x77ee47ed44,0x77ee8535b0,1,ret,0x7a907fa42c,0x7a88f5e248,4,ret,0x7a88f5e270,0x77f0731598,3,ret,0x77f07315a8,0x7aa249f254,2,ret,0x7aa249f25c,0x77ee8535bc,1,ret,0x775995f484,0x77ee8535d4,1,ret,0x7a907fa42c,0x7a88f5e248,4,ret,0x7a88f5e270,0x77f07315c4,3,ret,0x77f07315d0,0x7aa249f2d0,2,ret,0x7aa249f2d4,0x77ee8535d8,1,ret,0x77ee8535f8,0x77ee69c198,0,ret,0x77ee47dc04,0x77ee47df90,2,ret,0x77ee47e1b4,0x77ee85355c,1,ret,0x7a90855df4,0x7a907dec6c,3,ret,0x7a90855d34,0x7a907d89a8,4,ret,0x7a907d89b4,0x7a907decb0,3,ret,0x7a90855ff4,0x7a907d8a3c,3,ret,0x7a907d8a4c,0x7a907da9c4,2,ret,0x7a907da9d4,0x77ee853590,1,ret,0x77ee47dc74,0x77ee47edb0,2,ret,0x77ee47ed44,0x77ee8535b0,1,ret,0x7a907fa42c,0x7a88f5e248,4,ret,0x7a88f5e270,0x77f0731598,3,ret,0x77f07315a8,0x7aa249f254,2,ret,0x7aa249f25c,0x77ee8535bc,1,ret,0x77ee41d1b4,0x77ee4c4bb0,2,ret,0x77ee4c5114,0x77ee8535d4,1,ret,0x7a907fa42c,0x7a88f5e248,4,ret,0x7a88f5e270,0x77f07315c4,3,ret,0x77f07315d0,0x7aa249f2d0,2,ret,0x7aa249f2d4,0x77ee8535d8,1,ret,0x77ee8535f8,0x77ee69c198,0,ret,0x77ee47dc04,0x77ee47df90,2,ret,0x77ee47e1b4,0x77ee85355c,1,ret,0x7a90855df4,0x7a907dec6c,3,ret,0x7a90855d34,0x7a907d89a8,4,ret,0x7a907d89b4,0x7a907decb0,3,ret,0x7a90855ff4,0x7a907d8a3c,3,ret,0x7a907d8a4c,0x7a907da9c4,2,ret,0x7a907da9d4,0x77ee853590,1,ret,0x77ee47dc74,0x77ee47edb0,2,ret,0x77ee47ed44,0x77ee8535b0,1,ret,0x7a907fa42c,0x7a88f5e248,4,ret,0x7a88f5e270,0x77f0731598,3,ret,0x77f07315a8,0x7aa249f254,2,ret,0x7aa249f25c,0x77ee8535bc,1,ret,0x775995f484,0x77ee8535d4,1,ret,0x7a907fa42c,0x7a88f5e248,4,ret,0x7a88f5e270,0x77f07315c4,3,ret,0x77f07315d0,0x7aa249f2d0,2,ret,0x7aa249f2d4,0x77ee8535d8,1,ret,0x77ee8535f8,0x77ee69c198,0,ret,0x77ee47dc04,0x77ee47df90,2,ret,0x77ee47e1b4,0x77ee85355c,1,ret,0x7a90855df4,0x7a907dec6c,3,ret,0x7a90855d34,0x7a907d89a8,4,ret,0x7a907d89b4,0x7a907decb0,3,ret,0x7a90855ff4,0x7a907d8a3c,3,ret,0x7a907d8a4c,0x7a907da9c4,2,ret,0x7a907da9d4,0x77ee853590,1,ret,0x77ee47dc74,0x77ee47edb0,2,ret,0x77ee47ed44,0x77ee8535b0,1,ret,0x7a907fa42c,0x7a88f5e248,4,ret,0x7a88f5e270,0x77f0731598,3,ret,0x77f07315a8,0x7aa249f254,2,ret,0x7aa249f25c,0x77ee8535bc,1,ret,0x77ee41d1b4,0x77ee4c4bb0,2,ret,0x77ee4c5114,0x77ee8535d4,1,ret,0x7a907fa42c,0x7a88f5e248,4,ret,0x7a88f5e270,0x77f07315c4,3,ret,0x77f07315d0,0x7aa249f2d0,2,ret,0x7aa249f2d4,0x77ee8535d8,1,ret,0x77ee8535f8,0x77ee69c198,0,ret,0x77ee47dc04,0x77ee47df90,2,ret,0x77ee47e1b4,0x77ee85355c,1,ret,0x7a90855df4,0x7a907dec6c,3,ret,0x7a90855d34,0x7a907d89a8,4,ret,0x7a907d89b4,0x7a907decb0,3,ret,0x7a90855ff4,0x7a907d8a3c,3,ret,0x7a907d8a4c,0x7a907da9c4,2,ret,0x7a907da9d4,0x77ee853590,1,ret,0x77ee47dc74,0x77ee47edb0,2,ret,0x77ee47ed44,0x77ee8535b0,1,ret,0x7a907fa42c,0x7a88f5e248,4,ret,0x7a88f5e270,0x77f0731598,3,ret,0x77f07315a8,0x7aa249f254,2,ret,0x7aa249f25c,0x77ee8535bc,1,ret,0x775995f484,0x77ee8535d4,1,ret,0x7a907fa42c,0x7a88f5e248,4,ret,0x7a88f5e270,0x77f07315c4,3,ret,0x77f07315d0,0x7aa249f2d0,2,ret,0x7aa249f2d4,0x77ee8535d8,1,ret,0x77ee8535f8,0x77ee69c198,0,ret,0x77ee47dc04,0x77ee47df90,2,ret,0x77ee47e1b4,0x77ee85355c,1,ret,0x7a90855df4,0x7a907dec6c,3,ret,0x7a90855d34,0x7a907d89a8,4,ret,0x7a907d89b4,0x7a907decb0,3,ret,0x7a90855ff4,0x7a907d8a3c,3,ret,0x7a907d8a4c,0x7a907da9c4,2,ret,0x7a907da9d4,0x77ee853590,1,ret,0x77ee47dc74,0x77ee47edb0,2,ret,0x77ee47ed44,0x77ee8535b0,1,ret,0x7a907fa42c,0x7a88f5e248,4,ret,0x7a88f5e270,0x77f0731598,3,ret,0x77f07315a8,0x7aa249f254,2,ret,0x7aa249f25c,0x77ee8535bc,1,ret,0x775995f484,0x77ee8535d4,1,ret,0x7a907fa42c,0x7a88f5e248,4,ret,0x7a88f5e270,0x77f07315c4,3,ret,0x77f07315d0,0x7aa249f2d0,2,ret,0x7aa249f2d4,0x77ee8535d8,1,ret,0x77ee8535f8,0x77ee69c198,0,ret,0x77ee47dc04,0x77ee47df90,2,ret,0x77ee47e1b4,0x77ee85355c,1,ret,0x7a90855df4,0x7a907dec6c,3,ret,0x7a90855d34,0x7a907d89a8,4,ret,0x7a907d89b4,0x7a907decb0,3,ret,0x7a90855ff4,0x7a907d8a3c,3,ret,0x7a907d8a4c,0x7a907da9c4,2,ret,0x7a907da9d4,0x77ee853590,1,ret,0x77ee47dc74,0x77ee47edb0,2,ret,0x77ee47ed44,0x77ee8535b0,1,ret,0x7a907fa42c,0x7a88f5e248,4,ret,0x7a88f5e270,0x77f0731598,3,ret,0x77f07315a8,0x7aa249f254,2,ret,0x7aa249f25c,0x77ee8535bc,1,ret,0x775995f484,0x77ee8535d4,1,ret,0x7a907fa42c,0x7a88f5e248,4,ret,0x7a88f5e270,0x77f07315c4,3,ret,0x77f07315d0,0x7aa249f2d0,2,ret,0x7aa249f2d4,0x77ee8535d8,1,ret,0x77ee8535f8,0x77ee69c198,0,ret,0x77ee47dc04,0x77ee47df90,2,ret,0x77ee47e1b4,0x77ee85355c,1,ret,0x7a90855df4,0x7a907dec6c,3,ret,0x7a90855d34,0x7a907d89a8,4,ret,0x7a907d89b4,0x7a907decb0,3,ret,0x7a90855ff4,0x7a907d8a3c,3,ret,0x7a907d8a4c,0x7a907da9c4,2,ret,0x7a907da9d4,0x77ee853590,1,ret,0x77ee47dc74,0x77ee47edb0,2,ret,0x77ee47ed44,0x77ee8535b0,1,ret,0x7a907fa42c,0x7a88f5e248,4,ret,0x7a88f5e270,0x77f0731598,3,ret,0x77f07315a8,0x7aa249f254,2,ret,0x7aa249f25c,0x77ee8535bc,1,ret,0x77ee41d1b4,0x77ee4c4bb0,2,ret,0x77ee4c5114,0x77ee8535d4,1,ret,0x7a907fa42c,0x7a88f5e248,4,ret,0x7a88f5e270,0x77f07315c4,3,ret,0x77f07315d0,0x7aa249f2d0,2,ret,0x7aa249f2d4,0x77ee8535d8,1,ret,0x77ee8535f8,0x77ee69c198,0,ret,0x77ee47dc04,0x77ee47df90,2,ret,0x77ee47e1b4,0x77ee85355c,1,ret,0x7a90855df4,0x7a907dec6c,3,ret,0x7a90855d34,0x7a907d89a8,4,ret,0x7a907d89b4,0x7a907decb0,3,ret,0x7a90855ff4,0x7a907d8a3c,3,ret,0x7a907d8a4c,0x7a907da9c4,2,ret,0x7a907da9d4,0x77ee853590,1,ret,0x77ee47dc74,0x77ee47edb0,2,ret,0x77ee47ed44,0x77ee8535b0,1,ret,0x7a907fa42c,0x7a88f5e248,4,ret,0x7a88f5e270,0x77f0731598,3,ret,0x77f07315a8,0x7aa249f254,2,ret,0x7aa249f25c,0x77ee8535bc,1,ret,0x775995f484,0x77ee8535d4,1,ret,0x7a907fa42c,0x7a88f5e248,4,ret,0x7a88f5e270,0x77f07315c4,3,ret,0x77f07315d0,0x7aa249f2d0,2,ret,0x7aa249f2d4,0x77ee8535d8,1,ret,0x77ee8535f8,0x77ee69c198,0,ret,0x77ee47dc04,0x77ee47df90,2,ret,0x77ee47e1b4,0x77ee85355c,1,ret,0x7a90855df4,0x7a907dec6c,3,ret,0x7a90855d34,0x7a907d89a8,4,ret,0x7a907d89b4,0x7a907decb0,3,ret,0x7a90855ff4,0x7a907d8a3c,3,ret,0x7a907d8a4c,0x7a907da9c4,2,ret,0x7a907da9d4,0x77ee853590,1,ret,0x77ee47dc74,0x77ee47edb0,2,ret,0x77ee47ed44,0x77ee8535b0,1,ret,0x7a907fa42c,0x7a88f5e248,4,ret,0x7a88f5e270,0x77f0731598,3,ret,0x77f07315a8,0x7aa249f254,2,ret,0x7aa249f25c,0x77ee8535bc,1,ret,0x77ee41d1b4,0x77ee4c4bb0,2,ret,0x77ee4c5114,0x77ee8535d4,1,ret,0x7a907fa42c,0x7a88f5e248,4,ret,0x7a88f5e270,0x77f07315c4,3,ret,0x77f07315d0,0x7aa249f2d0,2,ret,0x7aa249f2d4,0x77ee8535d8,1,ret,0x77ee8535f8,0x77ee69c198,0,ret,0x77ee47dc04,0x77ee47df90,2,ret,0x77ee47e1b4,0x77ee85355c,1,ret,0x7a90855df4,0x7a907dec6c,3,ret,0x7a90855d34,0x7a907d89a8,4,ret,0x7a907d89b4,0x7a907decb0,3,ret,0x7a90855ff4,0x7a907d8a3c,3,ret,0x7a907d8a4c,0x7a907da9c4,2,ret,0x7a907da9d4,0x77ee853590,1,ret,0x77ee47dc74,0x77ee47edb0,2,ret,0x77ee47ed44,0x77ee8535b0,1,ret,0x7a907fa42c,0x7a88f5e248,4,ret,0x7a88f5e270,0x77f0731598,3,ret,0x77f07315a8,0x7aa249f254,2,ret,0x7aa249f25c,0x77ee8535bc,1,ret,0x77ee41d1b4,0x77ee4c4bb0,2,ret,0x77ee4c5114,0x77ee8535d4,1,ret,0x7a907fa42c,0x7a88f5e248,4,ret,0x7a88f5e270,0x77f07315c4,3,ret,0x77f07315d0,0x7aa249f2d0,2,ret,0x7aa249f2d4,0x77ee8535d8,1,ret,0x77ee8535f8,0x77ee69c198,0,ret,0x77ee47dc04,0x77ee47df90,2,ret,0x77ee47e1b4,0x77ee85355c,1,ret,0x7a90855df4,0x7a907dec6c,3,ret,0x7a90855d34,0x7a907d89a8,4,ret,0x7a907d89b4,0x7a907decb0,3,ret,0x7a90855ff4,0x7a907d8a3c,3,ret,0x7a907d8a4c,0x7a907da9c4,2,ret,0x7a907da9d4,0x77ee853590,1,ret,0x77ee47dc74,0x77ee47edb0,2,ret,0x77ee47ed44,0x77ee8535b0,1,ret,0x7a907fa42c,0x7a88f5e248,4,ret,0x7a88f5e270,0x77f0731598,3,ret,0x77f07315a8,0x7aa249f254,2,ret,0x7aa249f25c,0x77ee8535bc,1,ret,0x77ee41d1b4,0x77ee4c4bb0,2,ret,0x77ee4c5114,0x77ee8535d4,1,ret,0x7a907fa42c,0x7a88f5e248,4,ret,0x7a88f5e270,0x77f07315c4,3,ret,0x77f07315d0,0x7aa249f2d0,2,ret,0x7aa249f2d4,0x77ee8535d8,1,ret,0x77ee8535f8,0x77ee69c198,0,ret,0x7a907fa42c,0x7a88f5e248,6,ret,0x7a88f5e270,0x77f0731568,5,ret,0x77f0731580,0x7aa249f1d4,4,ret,0x7aa249f1dc,0x77ee47e214,3,ret,0x77ee47e28c,0x77ee47dfc0,2,ret,0x77ee47e35c,0x77ee47dfcc,2,ret,0x77ee47dc44,0x77ee47dfdc,2,ret,0x7a907e4f5c,0x77ee47e040,2,ret,0x77ee47dc44,0x77ee47e12c,2,ret,0x7a907fa42c,0x7a88f5e248,5,ret,0x7a88f5e270,0x77f07315c4,4,ret,0x77f07315d0,0x7aa249f2d0,3,ret,0x7aa249f2d4,0x77ee47e130,2,ret,0x7a907fa42c,0x7a88f5e248,6,ret,0x7a88f5e270,0x77f0731568,5,ret,0x77f0731580,0x7aa249f1d4,4,ret,0x7aa249f1dc,0x77ee47e214,3,ret,0x77ee47e28c,0x77ee47dfc0,2,ret,0x77ee47e35c,0x77ee47dfcc,2,ret,0x7a907fa42c,0x7a88f5e248,5,ret,0x7a88f5e270,0x77f07315c4,4,ret,0x77f07315d0,0x7aa249f2d0,3,ret,0x7aa249f2d4,0x77ee47e130,2,ret,0x77ee47dc04,0x77ee47df90,2,ret,0x77ee47e1b4,0x77ee85355c,1,ret,0x7a90855df4,0x7a907dec6c,3,ret,0x7a90855d34,0x7a907d89a8,4,ret,0x7a907d89b4,0x7a907decb0,3,ret,0x7a90855ff4,0x7a907d8a3c,3,ret,0x7a907d8a4c,0x7a907da9c4,2,ret,0x7a907da9d4,0x77ee853590,1,ret,0x77ee47dc74,0x77ee47edb0,2,ret,0x77ee47dc74,0x77ee47edb0,2,ret,0x7a907e4f5c,0x77ee47ee90,2,ret,0x77ee47ed44,0x77ee8535b0,1,ret,0x7a907fa42c,0x7a88f5e248,4,ret,0x7a88f5e270,0x77f0731598,3,ret,0x77f07315a8,0x7aa249f254,2,ret,0x7aa249f25c,0x77ee8535bc,1,ret,0x77ee41d1b4,0x77ee4c4bb0,2,ret,0x77ee4c5114,0x77ee8535d4,1,ret,0x7a907fa42c,0x7a88f5e248,4,ret,0x7a88f5e270,0x77f07315c4,3,ret,0x77f07315d0,0x7aa249f2d0,2,ret,0x7aa249f2d4,0x77ee8535d8,1,ret,0x77ee8535f8,0x77ee69c198,0,ret,0x77ee47dc04,0x77ee47df90,2,ret,0x77ee47e1b4,0x77ee85355c,1,ret,0x7a90855df4,0x7a907dec6c,3,ret,0x7a90855d34,0x7a907d89a8,4,ret,0x7a907d89b4,0x7a907decb0,3,ret,0x7a90855ff4,0x7a907d8a3c,3,ret,0x7a907d8a4c,0x7a907da9c4,2,ret,0x7a907da9d4,0x77ee853590,1,ret,0x77ee47dc74,0x77ee47edb0,2,ret,0x77ee47ed44,0x77ee8535b0,1,ret,0x7a907fa42c,0x7a88f5e248,4,ret,0x7a88f5e270,0x77f0731598,3,ret,0x77f07315a8,0x7aa249f254,2,ret,0x7aa249f25c,0x77ee8535bc,1,ret,0x77ee41d1b4,0x77ee4c4bb0,2,ret,0x77ee4c5114,0x77ee8535d4,1,ret,0x7a907fa42c,0x7a88f5e248,4,ret,0x7a88f5e270,0x77f07315c4,3,ret,0x77f07315d0,0x7aa249f2d0,2,ret,0x7aa249f2d4,0x77ee8535d8,1,ret,0x77ee8535f8,0x77ee69c198,0,ret,0x77ee47dc04,0x77ee47df90,2,ret,0x77ee47e1b4,0x77ee85355c,1,ret,0x7a90855df4,0x7a907dec6c,3,ret,0x7a90855d34,0x7a907d89a8,4,ret,0x7a907d89b4,0x7a907decb0,3,ret,0x7a90855ff4,0x7a907d8a3c,3,ret,0x7a907d8a4c,0x7a907da9c4,2,ret,0x7a907da9d4,0x77ee853590,1,ret,0x77ee47dc74,0x77ee47edb0,2,ret,0x77ee47ed44,0x77ee8535b0,1,ret,0x7a907fa42c,0x7a88f5e248,4,ret,0x7a88f5e270,0x77f0731598,3,ret,0x77f07315a8,0x7aa249f254,2,ret,0x7aa249f25c,0x77ee8535bc,1,ret,0x77ee41d1b4,0x77ee4c4bb0,2,ret,0x77ee4c5114,0x77ee8535d4,1,ret,0x7a907fa42c,0x7a88f5e248,4,ret,0x7a88f5e270,0x77f07315c4,3,ret,0x77f07315d0,0x7aa249f2d0,2,ret,0x7aa249f2d4,0x77ee8535d8,1,ret,0x77ee8535f8,0x77ee69c198,0,ret,0x77ee47dc04,0x77ee47df90,2,ret,0x77ee47e1b4,0x77ee85355c,1,ret,0x7a90855df4,0x7a907dec6c,3,ret,0x7a90855d34,0x7a907d89a8,4,ret,0x7a907d89b4,0x7a907decb0,3,ret,0x7a907e46e8,0x7a907ddccc,4,ret,0x7a90855d34,0x7a907d89a8,6,ret,0x7a907d89b4,0x7a907dc50c,5,ret,0x7a907dc518,0x7a907ddd5c,4,ret,0x7a907ddebc,0x7a907dddb8,4,ret,0x7a90855ff4,0x7a907d8a3c,4,ret,0x7a907d8a4c,0x7a907dedb0,3,ret,0x7a90855ff4,0x7a907d8a3c,3,ret,0x7a907e4f5c,0x7a907da9c4,2,ret,0x7a907da9d4,0x77ee853590,1,ret,0x77ee47dc74,0x77ee47edb0,2,ret,0x7a907e4f5c,0x77ee47ee90,2,ret,0x77ee47ed44,0x77ee8535b0,1,ret,0x7a907fa42c,0x7a88f5e248,4,ret,0x7a88f5e270,0x77f0731598,3,ret,0x77f07315a8,0x7aa249f254,2,ret,0x7aa249f25c,0x77ee8535bc,1,ret,0x77ee41d1b4,0x77ee4c4bb0,2,ret,0x77ee4c5114,0x77ee8535d4,1,ret,0x7a907fa42c,0x7a88f5e248,4,ret,0x7a88f5e270,0x77f07315c4,3,ret,0x77f07315d0,0x7aa249f2d0,2,ret,0x7aa249f2d4,0x77ee8535d8,1,ret,0x77ee8535f8,0x77ee69c198,0,ret,0x77ee47dc04,0x77ee47df90,2,ret,0x77ee47e1b4,0x77ee85355c,1,ret,0x7a90855df4,0x7a907dec6c,3,ret,0x7a90855d34,0x7a907d89a8,4,ret,0x7a907d89b4,0x7a907decb0,3,ret,0x7a90855ff4,0x7a907d8a3c,3,ret,0x7a907d8a4c,0x7a907da9c4,2,ret,0x7a907da9d4,0x77ee853590,1,ret,0x77ee47dc74,0x77ee47edb0,2,ret,0x7a907e4f5c,0x77ee47ee90,2,ret,0x77ee47ed44,0x77ee8535b0,1,ret,0x7a907fa42c,0x7a88f5e248,4,ret,0x7a88f5e270,0x77f0731598,3,ret,0x77f07315a8,0x7aa249f254,2,ret,0x7aa249f25c,0x77ee8535bc,1,ret,0x77ee41d1b4,0x77ee4c4bb0,2,ret,0x77ee4c5114,0x77ee8535d4,1,ret,0x7a907fa42c,0x7a88f5e248,4,ret,0x7a88f5e270,0x77f07315c4,3,ret,0x77f07315d0,0x7aa249f2d0,2,ret,0x7aa249f2d4,0x77ee8535d8,1,ret,0x77ee8535f8,0x77ee69c198,0,ret,0x77ee47dc04,0x77ee47df90,2,ret,0x77ee47e1b4,0x77ee85355c,1,ret,0x7a90855df4,0x7a907dec6c,3,ret,0x7a90855d34,0x7a907d89a8,4,ret,0x7a907d89b4,0x7a907decb0,3,ret,0x7a90855ff4,0x7a907d8a3c,3,ret,0x7a907d8a4c,0x7a907da9c4,2,ret,0x7a907da9d4,0x77ee853590,1,ret,0x77ee47dc74,0x77ee47edb0,2,ret,0x7a907e4f5c,0x77ee47ee90,2,ret,0x77ee47ed44,0x77ee8535b0,1,ret,0x7a907fa42c,0x7a88f5e248,4,ret,0x7a88f5e270,0x77f0731598,3,ret,0x77f07315a8,0x7aa249f254,2,ret,0x7aa249f25c,0x77ee8535bc,1,ret,0x77ee41d1b4,0x77ee4c4bb0,2,ret,0x77ee4c5114,0x77ee8535d4,1,ret,0x7a907fa42c,0x7a88f5e248,4,ret,0x7a88f5e270,0x77f07315c4,3,ret,0x77f07315d0,0x7aa249f2d0,2,ret,0x7aa249f2d4,0x77ee8535d8,1,ret,0x77ee8535f8,0x77ee69c198,0,ret,0x77ee47dc04,0x77ee47df90,2,ret,0x77ee47e1b4,0x77ee85355c,1,ret,0x7a90855df4,0x7a907dec6c,3,ret,0x7a90855d34,0x7a907d89a8,4,ret,0x7a907d89b4,0x7a907decb0,3,ret,0x7a90855ff4,0x7a907d8a3c,3,ret,0x7a907d8a4c,0x7a907da9c4,2,ret,0x7a907da9d4,0x77ee853590,1,ret,0x77ee47dc74,0x77ee47edb0,2,ret,0x7a907e4f5c,0x77ee47ee90,2,ret,0x77ee47ed44,0x77ee8535b0,1,ret,0x7a907fa42c,0x7a88f5e248,4,ret,0x7a88f5e270,0x77f0731598,3,ret,0x77f07315a8,0x7aa249f254,2,ret,0x7aa249f25c,0x77ee8535bc,1,ret,0x77ee41d1b4,0x77ee4c4bb0,2,ret,0x77ee4c5114,0x77ee8535d4,1,ret,0x7a907fa42c,0x7a88f5e248,4,ret,0x7a88f5e270,0x77f07315c4,3,ret,0x77f07315d0,0x7aa249f2d0,2,ret,0x7aa249f2d4,0x77ee8535d8,1,ret,0x77ee8535f8,0x77ee69c198,0,ret,0x7a907fa42c,0x7a88f5e248,6,ret,0x7a88f5e270,0x77f0731568,5,ret,0x77f0731580,0x7aa249f1d4,4,ret,0x7aa249f1dc,0x77ee47e214,3,ret,0x77ee47e28c,0x77ee47dfc0,2,ret,0x77ee47e35c,0x77ee47dfcc,2,ret,0x7a907fa42c,0x7a88f5e248,5,ret,0x7a88f5e270,0x77f07315c4,4,ret,0x77f07315d0,0x7aa249f2d0,3,ret,0x7aa249f2d4,0x77ee47e130,2,ret,0x77ee47dc04,0x77ee47df90,2,ret,0x77ee47e1b4,0x77ee85355c,1,ret,0x7a90855df4,0x7a907dec6c,3,ret,0x7a90855d34,0x7a907d89a8,4,ret,0x7a907d89b4,0x7a907decb0,3,ret,0x7a90855ff4,0x7a907d8a3c,3,ret,0x7a907d8a4c,0x7a907da9c4,2,ret,0x7a907da9d4,0x77ee853590,1,ret,0x77ee47dc74,0x77ee47edb0,2,ret,0x7a907e4f5c,0x77ee47ee90,2,ret,0x77ee47ed44,0x77ee8535b0,1,ret,0x7a907fa42c,0x7a88f5e248,4,ret,0x7a88f5e270,0x77f0731598,3,ret,0x77f07315a8,0x7aa249f254,2,ret,0x7aa249f25c,0x77ee8535bc,1,ret,0x77ee41d1b4,0x77ee4c4bb0,2,ret,0x77ee4c5114,0x77ee8535d4,1,ret,0x7a907fa42c,0x7a88f5e248,4,ret,0x7a88f5e270,0x77f07315c4,3,ret,0x77f07315d0,0x7aa249f2d0,2,ret,0x7aa249f2d4,0x77ee8535d8,1,ret,0x77ee8535f8,0x77ee69c198,0,ret,0x77ee47dc04,0x77ee47df90,2,ret,0x77ee47e1b4,0x77ee85355c,1,ret,0x7a90855df4,0x7a907dec6c,3,ret,0x7a90855d34,0x7a907d89a8,4,ret,0x7a907d89b4,0x7a907decb0,3,ret,0x7a90855ff4,0x7a907d8a3c,3,ret,0x7a907d8a4c,0x7a907da9c4,2,ret,0x7a907da9d4,0x77ee853590,1,ret,0x77ee47dc74,0x77ee47edb0,2,ret,0x7a907e4f5c,0x77ee47ee90,2,ret,0x77ee47ed44,0x77ee8535b0,1,ret,0x7a907fa42c,0x7a88f5e248,4,ret,0x7a88f5e270,0x77f0731598,3,ret,0x77f07315a8,0x7aa249f254,2,ret,0x7aa249f25c,0x77ee8535bc,1,ret,0x775995f484,0x77ee8535d4,1,ret,0x7a907fa42c,0x7a88f5e248,4,ret,0x7a88f5e270,0x77f07315c4,3,ret,0x77f07315d0,0x7aa249f2d0,2,ret,0x7aa249f2d4,0x77ee8535d8,1,ret,0x77ee8535f8,0x77ee69c198,0,ret,0x77ee47dc04,0x77ee47df90,2,ret,0x77ee47e1b4,0x77ee85355c,1,ret,0x7a90855df4,0x7a907dec6c,3,ret,0x7a90855d34,0x7a907d89a8,4,ret,0x7a907d89b4,0x7a907decb0,3,ret,0x7aa3c2c440,0x7a907e4120,5,ret,0x7a907e412c,0x7a907d8a98,4,ret,0x7a907d8ab0,0x7a907ded64,3,ret,0x7a90855d34,0x7a907d89a8,6,ret,0x7a907d89b4,0x7a907dc50c,5,ret,0x7a907dc518,0x7a907dcee4,4,ret,0x7a90855ff4,0x7a907d8a3c,5,ret,0x7a907d8a4c,0x7a907dcf00,4,ret,0x7a90855d34,0x7a907d89a8,5,ret,0x7a907d89b4,0x7a907dcf30,4,ret,0x7a907dcfe8,0x7a907ded74,3,ret,0x7a90855ff4,0x7a907d8a3c,3,ret,0x7a907d8a4c,0x7a907da9c4,2,ret,0x7a907da9d4,0x77ee853590,1,ret,0x77ee47dc74,0x77ee47edb0,2,ret,0x7a907e4f5c,0x77ee47ee90,2,ret,0x77ee47ed44,0x77ee8535b0,1,ret,0x7a907fa42c,0x7a88f5e248,4,ret,0x7a88f5e270,0x77f0731598,3,ret,0x77f07315a8,0x7aa249f254,2,ret,0x7aa249f25c,0x77ee8535bc,1,ret,0x77ee41d1b4,0x77ee4c4bb0,2,ret,0x77ee4c5114,0x77ee8535d4,1,ret,0x7a907fa42c,0x7a88f5e248,4,ret,0x7a88f5e270,0x77f07315c4,3,ret,0x77f07315d0,0x7aa249f2d0,2,ret,0x7aa249f2d4,0x77ee8535d8,1,ret,0x77ee8535f8,0x77ee69c198,0,ret,0x77ee47dc04,0x77ee47df90,2,ret,0x77ee47e1b4,0x77ee85355c,1,ret,0x7a90855df4,0x7a907dec6c,3,ret,0x7a90855d34,0x7a907d89a8,4,ret,0x7a907d89b4,0x7a907decb0,3,ret,0x7a90855ff4,0x7a907d8a3c,3,ret,0x7a907d8a4c,0x7a907da9c4,2,ret,0x7a907da9d4,0x77ee853590,1,ret,0x77ee47dc74,0x77ee47edb0,2,ret,0x7a907e4f5c,0x77ee47ee90,2,ret,0x77ee47ed44,0x77ee8535b0,1,ret,0x7a907fa42c,0x7a88f5e248,4,ret,0x7a88f5e270,0x77f0731598,3,ret,0x77f07315a8,0x7aa249f254,2,ret,0x7aa249f25c,0x77ee8535bc,1,ret,0x77ee41d1b4,0x77ee4c4bb0,2,ret,0x77ee4c5114,0x77ee8535d4,1,ret,0x7a907fa42c,0x7a88f5e248,4,ret,0x7a88f5e270,0x77f07315c4,3,ret,0x77f07315d0,0x7aa249f2d0,2,ret,0x7aa249f2d4,0x77ee8535d8,1,ret,0x77ee8535f8,0x77ee69c198,0,ret,0x77ee47dc04,0x77ee47df90,2,ret,0x77ee47e1b4,0x77ee85355c,1,ret,0x7a90855df4,0x7a907dec6c,3,ret,0x7a90855d34,0x7a907d89a8,4,ret,0x7a907d89b4,0x7a907decb0,3,ret,0x7a90855ff4,0x7a907d8a3c,3,ret,0x7a907d8a4c,0x7a907da9c4,2,ret,0x7a907da9d4,0x77ee853590,1,ret,0x77ee47dc74,0x77ee47edb0,2,ret,0x7a907e4f5c,0x77ee47ee90,2,ret,0x77ee47ed44,0x77ee8535b0,1,ret,0x7a907fa42c,0x7a88f5e248,4,ret,0x7a88f5e270,0x77f0731598,3,ret,0x77f07315a8,0x7aa249f254,2,ret,0x7aa249f25c,0x77ee8535bc,1,ret,0x77ee41d1b4,0x77ee4c4bb0,2,ret,0x77ee4c5114,0x77ee8535d4,1,ret,0x7a907fa42c,0x7a88f5e248,4,ret,0x7a88f5e270,0x77f07315c4,3,ret,0x77f07315d0,0x7aa249f2d0,2,ret,0x7aa249f2d4,0x77ee8535d8,1,ret,0x77ee8535f8,0x77ee69c198,0,ret,0x77ee47dc04,0x77ee47df90,2,ret,0x77ee47e1b4,0x77ee85355c,1,ret,0x7a90855df4,0x7a907dec6c,3,ret,0x7a90855d34,0x7a907d89a8,4,ret,0x7a907d89b4,0x7a907decb0,3,ret,0x7a90855ff4,0x7a907d8a3c,3,ret,0x7a907d8a4c,0x7a907da9c4,2,ret,0x7a907da9d4,0x77ee853590,1,ret,0x77ee47dc74,0x77ee47edb0,2,ret,0x7a907e4f5c,0x77ee47ee90,2,ret,0x77ee47ed44,0x77ee8535b0,1,ret,0x7a907fa42c,0x7a88f5e248,4,ret,0x7a88f5e270,0x77f0731598,3,ret,0x77f07315a8,0x7aa249f254,2,ret,0x7aa249f25c,0x77ee8535bc,1,ret,0x77ee41d1b4,0x77ee4c4bb0,2,ret,0x77ee4c5114,0x77ee8535d4,1,ret,0x7a907fa42c,0x7a88f5e248,4,ret,0x7a88f5e270,0x77f07315c4,3,ret,0x77f07315d0,0x7aa249f2d0,2,ret,0x7aa249f2d4,0x77ee8535d8,1,ret,0x77ee8535f8,0x77ee69c198,0,ret,0x77ee47dc04,0x77ee47df90,2,ret,0x77ee47e1b4,0x77ee85355c,1,ret,0x7a90855df4,0x7a907dec6c,3,ret,0x7a90855d34,0x7a907d89a8,4,ret,0x7a907d89b4,0x7a907decb0,3,ret,0x7a90855ff4,0x7a907d8a3c,3,ret,0x7a907d8a4c,0x7a907da9c4,2,ret,0x7a907da9d4,0x77ee853590,1,ret,0x77ee47dc74,0x77ee47edb0,2,ret,0x7a907e4f5c,0x77ee47ee90,2,ret,0x77ee47ed44,0x77ee8535b0,1,ret,0x7a907fa42c,0x7a88f5e248,4,ret,0x7a88f5e270,0x77f0731598,3,ret,0x77f07315a8,0x7aa249f254,2,ret,0x7aa249f25c,0x77ee8535bc,1,ret,0x775995f484,0x77ee8535d4,1,ret,0x7a907fa42c,0x7a88f5e248,4,ret,0x7a88f5e270,0x77f07315c4,3,ret,0x77f07315d0,0x7aa249f2d0,2,ret,0x7aa249f2d4,0x77ee8535d8,1,ret,0x77ee8535f8,0x77ee69c198,0,ret,0x77ee47dc04,0x77ee47df90,2,ret,0x77ee47e1b4,0x77ee85355c,1,ret,0x7a90855df4,0x7a907dec6c,3,ret,0x7a90855d34,0x7a907d89a8,4,ret,0x7a907d89b4,0x7a907decb0,3,ret,0x7a90855ff4,0x7a907d8a3c,3,ret,0x7a907d8a4c,0x7a907da9c4,2,ret,0x7a907da9d4,0x77ee853590,1,ret,0x77ee47dc74,0x77ee47edb0,2,ret,0x7a907e4f5c,0x77ee47ee90,2,ret,0x77ee47ed44,0x77ee8535b0,1,ret,0x7a907fa42c,0x7a88f5e248,4,ret,0x7a88f5e270,0x77f0731598,3,ret,0x77f07315a8,0x7aa249f254,2,ret,0x7aa249f25c,0x77ee8535bc,1,ret,0x77ee41d1b4,0x77ee4c4bb0,2,ret,0x77ee4c5114,0x77ee8535d4,1,ret,0x7a907fa42c,0x7a88f5e248,4,ret,0x7a88f5e270,0x77f07315c4,3,ret,0x77f07315d0,0x7aa249f2d0,2,ret,0x7aa249f2d4,0x77ee8535d8,1,ret,0x77ee8535f8,0x77ee69c198,0,ret,0x77ee47dc04,0x77ee47df90,2,ret,0x77ee47e1b4,0x77ee85355c,1,ret,0x7a90855df4,0x7a907dec6c,3,ret,0x7a90855d34,0x7a907d89a8,4,ret,0x7a907d89b4,0x7a907decb0,3,ret,0x7a90855ff4,0x7a907d8a3c,3,ret,0x7a907d8a4c,0x7a907da9c4,2,ret,0x7a907da9d4,0x77ee853590,1,ret,0x77ee47dc74,0x77ee47edb0,2,ret,0x7a907e4f5c,0x77ee47ee90,2,ret,0x77ee47ed44,0x77ee8535b0,1,ret,0x7a907fa42c,0x7a88f5e248,4,ret,0x7a88f5e270,0x77f0731598,3,ret,0x77f07315a8,0x7aa249f254,2,ret,0x7aa249f25c,0x77ee8535bc,1,ret,0x77ee41d1b4,0x77ee4c4bb0,2,ret,0x77ee4c5114,0x77ee8535d4,1,ret,0x7a907fa42c,0x7a88f5e248,4,ret,0x7a88f5e270,0x77f07315c4,3,ret,0x77f07315d0,0x7aa249f2d0,2,ret,0x7aa249f2d4,0x77ee8535d8,1,ret,0x77ee8535f8,0x77ee69c198,0,ret,0x77ee47dc04,0x77ee47df90,2,ret,0x77ee47e1b4,0x77ee85355c,1,ret,0x7a90855df4,0x7a907dec6c,3,ret,0x7a90855d34,0x7a907d89a8,4,ret,0x7a907d89b4,0x7a907decb0,3,ret,0x7a90855ff4,0x7a907d8a3c,3,ret,0x7a907d8a4c,0x7a907da9c4,2,ret,0x7a907da9d4,0x77ee853590,1,ret,0x77ee47dc74,0x77ee47edb0,2,ret,0x7a907e4f5c,0x77ee47ee90,2,ret,0x77ee47ed44,0x77ee8535b0,1,ret,0x7a907fa42c,0x7a88f5e248,4,ret,0x7a88f5e270,0x77f0731598,3,ret,0x77f07315a8,0x7aa249f254,2,ret,0x7aa249f25c,0x77ee8535bc,1,ret,0x77ee41d1b4,0x77ee4c4bb0,2,ret,0x77ee4c5114,0x77ee8535d4,1,ret,0x7a907fa42c,0x7a88f5e248,4,ret,0x7a88f5e270,0x77f07315c4,3,ret,0x77f07315d0,0x7aa249f2d0,2,ret,0x7aa249f2d4,0x77ee8535d8,1,ret,0x77ee8535f8,0x77ee69c198,0,ret,0x77ee47dc04,0x77ee47df90,2,ret,0x77ee47e1b4,0x77ee85355c,1,ret,0x7a90855df4,0x7a907dec6c,3,ret,0x7a90855d34,0x7a907d89a8,4,ret,0x7a907d89b4,0x7a907decb0,3,ret,0x7aa3c2c440,0x7a907e4120,5,ret,0x7a907e412c,0x7a907d8a98,4,ret,0x7a907d8ab0,0x7a907ded64,3,ret,0x7a90855d34,0x7a907d89a8,6,ret,0x7a907d89b4,0x7a907dc50c,5,ret,0x7a907dc518,0x7a907dcee4,4,ret,0x7a90855ff4,0x7a907d8a3c,5,ret,0x7a907d8a4c,0x7a907dcf00,4,ret,0x7a90855d34,0x7a907d89a8,5,ret,0x7a907d89b4,0x7a907dcf30,4,ret,0x7a907dcfe8,0x7a907ded74,3,ret,0x7a90855ff4,0x7a907d8a3c,3,ret,0x7a907d8a4c,0x7a907da9c4,2,ret,0x7a907da9d4,0x77ee853590,1,ret,0x77ee47dc74,0x77ee47edb0,2,ret,0x7a907e4f5c,0x77ee47ee90,2,ret,0x77ee47ed44,0x77ee8535b0,1,ret,0x7a907fa42c,0x7a88f5e248,4,ret,0x7a88f5e270,0x77f0731598,3,ret,0x77f07315a8,0x7aa249f254,2,ret,0x7aa249f25c,0x77ee8535bc,1,ret,0x775995f484,0x77ee8535d4,1,ret,0x7a907fa42c,0x7a88f5e248,4,ret,0x7a88f5e270,0x77f07315c4,3,ret,0x77f07315d0,0x7aa249f2d0,2,ret,0x7aa249f2d4,0x77ee8535d8,1,ret,0x77ee8535f8,0x77ee69c198,0,ret,0x77ee47dc04,0x77ee47df90,2,ret,0x77ee47e1b4,0x77ee85355c,1,ret,0x7a90855df4,0x7a907dec6c,3,ret,0x7a90855d34,0x7a907d89a8,4,ret,0x7a907d89b4,0x7a907decb0,3,ret,0x7a90855ff4,0x7a907d8a3c,3,ret,0x7a907d8a4c,0x7a907da9c4,2,ret,0x7a907da9d4,0x77ee853590,1,ret,0x77ee47dc74,0x77ee47edb0,2,ret,0x7a907e4f5c,0x77ee47ee90,2,ret,0x77ee47ed44,0x77ee8535b0,1,ret,0x7a907fa42c,0x7a88f5e248,4,ret,0x7a88f5e270,0x77f0731598,3,ret,0x77f07315a8,0x7aa249f254,2,ret,0x7aa249f25c,0x77ee8535bc,1,ret,0x77ee41d1b4,0x77ee4c4bb0,2,ret,0x77ee4c5114,0x77ee8535d4,1,ret,0x7a907fa42c,0x7a88f5e248,4,ret,0x7a88f5e270,0x77f07315c4,3,ret,0x77f07315d0,0x7aa249f2d0,2,ret,0x7aa249f2d4,0x77ee8535d8,1,ret,0x77ee8535f8,0x77ee69c198,0,ret,0x77ee47dc04,0x77ee47df90,2,ret,0x77ee47e1b4,0x77ee85355c,1,ret,0x7a90855df4,0x7a907dec6c,3,ret,0x7a90855d34,0x7a907d89a8,4,ret,0x7a907d89b4,0x7a907decb0,3,ret,0x7a90855ff4,0x7a907d8a3c,3,ret,0x7a907d8a4c,0x7a907da9c4,2,ret,0x7a907da9d4,0x77ee853590,1,ret,0x77ee47dc74,0x77ee47edb0,2,ret,0x7a907e4f5c,0x77ee47ee90,2,ret,0x77ee47ed44,0x77ee8535b0,1,ret,0x7a907fa42c,0x7a88f5e248,4,ret,0x7a88f5e270,0x77f0731598,3,ret,0x77f07315a8,0x7aa249f254,2,ret,0x7aa249f25c,0x77ee8535bc,1,ret,0x77ee41d1b4,0x77ee4c4bb0,2,ret,0x77ee4c5114,0x77ee8535d4,1,ret,0x7a907fa42c,0x7a88f5e248,4,ret,0x7a88f5e270,0x77f07315c4,3,ret,0x77f07315d0,0x7aa249f2d0,2,ret,0x7aa249f2d4,0x77ee8535d8,1,ret,0x77ee8535f8,0x77ee69c198,0,ret,0x77ee47dc04,0x77ee47df90,2,ret,0x77ee47e1b4,0x77ee85355c,1,ret,0x7a90855df4,0x7a907dec6c,3,ret,0x7a90855d34,0x7a907d89a8,4,ret,0x7a907d89b4,0x7a907decb0,3,ret,0x7a90855ff4,0x7a907d8a3c,3,ret,0x7a907d8a4c,0x7a907da9c4,2,ret,0x7a907da9d4,0x77ee853590,1,ret,0x77ee47dc74,0x77ee47edb0,2,ret,0x7a907e4f5c,0x77ee47ee90,2,ret,0x77ee47ed44,0x77ee8535b0,1,ret,0x7a907fa42c,0x7a88f5e248,4,ret,0x7a88f5e270,0x77f0731598,3,ret,0x77f07315a8,0x7aa249f254,2,ret,0x7aa249f25c,0x77ee8535bc,1,ret,0x77ee41d1b4,0x77ee4c4bb0,2,ret,0x77ee4c5114,0x77ee8535d4,1,ret,0x7a907fa42c,0x7a88f5e248,4,ret,0x7a88f5e270,0x77f07315c4,3,ret,0x77f07315d0,0x7aa249f2d0,2,ret,0x7aa249f2d4,0x77ee8535d8,1,ret,0x77ee8535f8,0x77ee69c198,0,ret,0x77ee47dc04,0x77ee47df90,2,ret,0x77ee47e1b4,0x77ee85355c,1,ret,0x7a90855df4,0x7a907dec6c,3,ret,0x7a90855d34,0x7a907d89a8,4,ret,0x7a907d89b4,0x7a907decb0,3,ret,0x7a90855ff4,0x7a907d8a3c,3,ret,0x7a907d8a4c,0x7a907da9c4,2,ret,0x7a907da9d4,0x77ee853590,1,ret,0x77ee47dc74,0x77ee47edb0,2,ret,0x7a907e4f5c,0x77ee47ee90,2,ret,0x77ee47ed44,0x77ee8535b0,1,ret,0x7a907fa42c,0x7a88f5e248,4,ret,0x7a88f5e270,0x77f0731598,3,ret,0x77f07315a8,0x7aa249f254,2,ret,0x7aa249f25c,0x77ee8535bc,1,ret,0x77ee41d1b4,0x77ee4c4bb0,2,ret,0x77ee4c5114,0x77ee8535d4,1,ret,0x7a907fa42c,0x7a88f5e248,4,ret,0x7a88f5e270,0x77f07315c4,3,ret,0x77f07315d0,0x7aa249f2d0,2,ret,0x7aa249f2d4,0x77ee8535d8,1,ret,0x77ee8535f8,0x77ee69c198,0,ret,0x77ee47dc04,0x77ee47df90,2,ret,0x77ee47e1b4,0x77ee85355c,1,ret,0x7a90855df4,0x7a907dec6c,3,ret,0x7a90855d34,0x7a907d89a8,4,ret,0x7a907d89b4,0x7a907decb0,3,ret,0x7a90855ff4,0x7a907d8a3c,3,ret,0x7a907d8a4c,0x7a907da9c4,2,ret,0x7a907da9d4,0x77ee853590,1,ret,0x77ee47dc74,0x77ee47edb0,2,ret,0x7a907e4f5c,0x77ee47ee90,2,ret,0x77ee47ed44,0x77ee8535b0,1,ret,0x7a907fa42c,0x7a88f5e248,4,ret,0x7a88f5e270,0x77f0731598,3,ret,0x77f07315a8,0x7aa249f254,2,ret,0x7aa249f25c,0x77ee8535bc,1,ret,0x77ee41d1b4,0x77ee4c4bb0,2,ret,0x77ee4c5114,0x77ee8535d4,1,ret,0x7a907fa42c,0x7a88f5e248,4,ret,0x7a88f5e270,0x77f07315c4,3,ret,0x77f07315d0,0x7aa249f2d0,2,ret,0x7aa249f2d4,0x77ee8535d8,1,ret,0x77ee8535f8,0x77ee69c198,0,ret,0x77ee47dc04,0x77ee47df90,2,ret,0x77ee47e1b4,0x77ee85355c,1,ret,0x7a90855df4,0x7a907dec6c,3,ret,0x7a90855d34,0x7a907d89a8,4,ret,0x7a907d89b4,0x7a907decb0,3,ret,0x7a90855ff4,0x7a907d8a3c,3,ret,0x7a907d8a4c,0x7a907da9c4,2,ret,0x7a907da9d4,0x77ee853590,1,ret,0x77ee47dc74,0x77ee47edb0,2,ret,0x7a907e4f5c,0x77ee47ee90,2,ret,0x77ee47ed44,0x77ee8535b0,1,ret,0x7a907fa42c,0x7a88f5e248,4,ret,0x7a88f5e270,0x77f0731598,3,ret,0x77f07315a8,0x7aa249f254,2,ret,0x7aa249f25c,0x77ee8535bc,1,ret,0x77ee41d1b4,0x77ee4c4bb0,2,ret,0x77ee4c5114,0x77ee8535d4,1,ret,0x7a907fa42c,0x7a88f5e248,4,ret,0x7a88f5e270,0x77f07315c4,3,ret,0x77f07315d0,0x7aa249f2d0,2,ret,0x7aa249f2d4,0x77ee8535d8,1,ret,0x77ee8535f8,0x77ee69c198,0,ret,0x77ee47dc04,0x77ee47df90,2,ret,0x77ee47e1b4,0x77ee85355c,1,ret,0x7a90855df4,0x7a907dec6c,3,ret,0x7a90855d34,0x7a907d89a8,4,ret,0x7a907d89b4,0x7a907decb0,3,ret,0x7a90855ff4,0x7a907d8a3c,3,ret,0x7a907d8a4c,0x7a907da9c4,2,ret,0x7a907da9d4,0x77ee853590,1,ret,0x77ee47dc74,0x77ee47edb0,2,ret,0x7a907e4f5c,0x77ee47ee90,2,ret,0x77ee47ed44,0x77ee8535b0,1,ret,0x7a907fa42c,0x7a88f5e248,4,ret,0x7a88f5e270,0x77f0731598,3,ret,0x77f07315a8,0x7aa249f254,2,ret,0x7aa249f25c,0x77ee8535bc,1,ret,0x77ee41d1b4,0x77ee4c4bb0,2,ret,0x77ee4c5114,0x77ee8535d4,1,ret,0x7a907fa42c,0x7a88f5e248,4,ret,0x7a88f5e270,0x77f07315c4,3,ret,0x77f07315d0,0x7aa249f2d0,2,ret,0x7aa249f2d4,0x77ee8535d8,1,ret,0x77ee8535f8,0x77ee69c198,0,ret,0x7a907fa42c,0x7a88f5e248,6,ret,0x7a88f5e270,0x77f0731568,5,ret,0x77f0731580,0x7aa249f1d4,4,ret,0x7aa249f1dc,0x77ee47e214,3,ret,0x77ee47e28c,0x77ee47dfc0,2,ret,0x77ee47e35c,0x77ee47dfcc,2,ret,0x7a907fa42c,0x7a88f5e248,5,ret,0x7a88f5e270,0x77f07315c4,4,ret,0x77f07315d0,0x7aa249f2d0,3,ret,0x7aa249f2d4,0x77ee47e130,2,ret,0x77ee47dc04,0x77ee47df90,2,ret,0x77ee47e1b4,0x77ee85355c,1,ret,0x7a90855df4,0x7a907dec6c,3,ret,0x7a90855d34,0x7a907d89a8,4,ret,0x7a907d89b4,0x7a907decb0,3,ret,0x7a907e46e8,0x7a907ddccc,4,ret,0x7a90855d34,0x7a907d89a8,6,ret,0x7a907d89b4,0x7a907dc50c,5,ret,0x7a907dc518,0x7a907ddd5c,4,ret,0x7a907ddebc,0x7a907dddb8,4,ret,0x7a90855ff4,0x7a907d8a3c,4,ret,0x7a907d8a4c,0x7a907dedb0,3,ret,0x7a90855ff4,0x7a907d8a3c,3,ret,0x7a907d8a4c,0x7a907da9c4,2,ret,0x7a907da9d4,0x77ee853590,1,ret,0x77ee47dc74,0x77ee47edb0,2,ret,0x7a907e4f5c,0x77ee47ee90,2,ret,0x77ee47ed44,0x77ee8535b0,1,ret,0x7a907fa42c,0x7a88f5e248,4,ret,0x7a88f5e270,0x77f0731598,3,ret,0x77f07315a8,0x7aa249f254,2,ret,0x7aa249f25c,0x77ee8535bc,1,ret,0x775995f484,0x77ee8535d4,1,ret,0x7a907fa42c,0x7a88f5e248,4,ret,0x7a88f5e270,0x77f07315c4,3,ret,0x77f07315d0,0x7aa249f2d0,2,ret,0x7aa249f2d4,0x77ee8535d8,1,ret,0x77ee8535f8,0x77ee69c198,0,ret,0x77ee47dc04,0x77ee47df90,2,ret,0x77ee47e1b4,0x77ee85355c,1,ret,0x7a90855df4,0x7a907dec6c,3,ret,0x7a90855d34,0x7a907d89a8,4,ret,0x7a907d89b4,0x7a907decb0,3,ret,0x7a90855ff4,0x7a907d8a3c,3,ret,0x7a907d8a4c,0x7a907da9c4,2,ret,0x7a907da9d4,0x77ee853590,1,ret,0x77ee47dc74,0x77ee47edb0,2,ret,0x7a907e4f5c,0x77ee47ee90,2,ret,0x77ee47ed44,0x77ee8535b0,1,ret,0x7a907fa42c,0x7a88f5e248,4,ret,0x7a88f5e270,0x77f0731598,3,ret,0x77f07315a8,0x7aa249f254,2,ret,0x7aa249f25c,0x77ee8535bc,1,ret,0x775995f484,0x77ee8535d4,1,ret,0x7a907fa42c,0x7a88f5e248,4,ret,0x7a88f5e270,0x77f07315c4,3,ret,0x77f07315d0,0x7aa249f2d0,2,ret,0x7aa249f2d4,0x77ee8535d8,1,ret,0x77ee8535f8,0x77ee69c198,0,ret,0x77ee47dc04,0x77ee47df90,2,ret,0x77ee47e1b4,0x77ee85355c,1,ret,0x7a90855df4,0x7a907dec6c,3,ret,0x7a90855d34,0x7a907d89a8,4,ret,0x7a907d89b4,0x7a907decb0,3,ret,0x7a90855ff4,0x7a907d8a3c,3,ret,0x7a907d8a4c,0x7a907da9c4,2,ret,0x7a907da9d4,0x77ee853590,1,ret,0x77ee47dc74,0x77ee47edb0,2,ret,0x7a907e4f5c,0x77ee47ee90,2,ret,0x77ee47ed44,0x77ee8535b0,1,ret,0x7a907fa42c,0x7a88f5e248,4,ret,0x7a88f5e270,0x77f0731598,3,ret,0x77f07315a8,0x7aa249f254,2,ret,0x7aa249f25c,0x77ee8535bc,1,ret,0x775995f484,0x77ee8535d4,1,ret,0x7a907fa42c,0x7a88f5e248,4,ret,0x7a88f5e270,0x77f07315c4,3,ret,0x77f07315d0,0x7aa249f2d0,2,ret,0x7aa249f2d4,0x77ee8535d8,1,ret,0x77ee8535f8,0x77ee69c198,0,ret,0x77ee47dc04,0x77ee47df90,2,ret,0x77ee47e1b4,0x77ee85355c,1,ret,0x7a90855df4,0x7a907dec6c,3,ret,0x7a90855d34,0x7a907d89a8,4,ret,0x7a907d89b4,0x7a907decb0,3,ret,0x7a90855ff4,0x7a907d8a3c,3,ret,0x7a907d8a4c,0x7a907da9c4,2,ret,0x7a907da9d4,0x77ee853590,1,ret,0x77ee47dc74,0x77ee47edb0,2,ret,0x7a907e4f5c,0x77ee47ee90,2,ret,0x77ee47ed44,0x77ee8535b0,1,ret,0x7a907fa42c,0x7a88f5e248,4,ret,0x7a88f5e270,0x77f0731598,3,ret,0x77f07315a8,0x7aa249f254,2,ret,0x7aa249f25c,0x77ee8535bc,1,ret,0x77ee41d1b4,0x77ee4c4bb0,2,ret,0x77ee4c5114,0x77ee8535d4,1,ret,0x7a907fa42c,0x7a88f5e248,4,ret,0x7a88f5e270,0x77f07315c4,3,ret,0x77f07315d0,0x7aa249f2d0,2,ret,0x7aa249f2d4,0x77ee8535d8,1,ret,0x77ee8535f8,0x77ee69c198,0,ret,0x77ee47dc04,0x77ee47df90,2,ret,0x77ee47e1b4,0x77ee85355c,1,ret,0x77ee743674,0x77ee8535a4,1,ret,0x77ee47dc74,0x77ee47edb0,2,ret,0x7a907e4f5c,0x77ee47ee90,2,ret,0x77ee47ed44,0x77ee8535b0,1,ret,0x7a907fa42c,0x7a88f5e248,4,ret,0x7a88f5e270,0x77f0731598,3,ret,0x77f07315a8,0x7aa249f254,2,ret,0x7aa249f25c,0x77ee8535bc,1,ret,0x775995f484,0x77ee8535d4,1,ret,0x7a907fa42c,0x7a88f5e248,4,ret,0x7a88f5e270,0x77f07315c4,3,ret,0x77f07315d0,0x7aa249f2d0,2,ret,0x7aa249f2d4,0x77ee8535d8,1,ret,0x77ee8535f8,0x77ee69c198,0,ret,0x77ee47dc74,0x77ee69c184,0,ret,0x77ee47dc04,0x77ee47df90,2,ret,0x77ee47e1b4,0x77ee85355c,1,ret,0x77ee743674,0x77ee8535a4,1,ret,0x77ee47dc74,0x77ee47edb0,2,ret,0x7a907e4f5c,0x77ee47ee90,2,ret,0x77ee47ed44,0x77ee8535b0,1,ret,0x7a907fa42c,0x7a88f5e248,4,ret,0x7a88f5e270,0x77f0731598,3,ret,0x77f07315a8,0x7aa249f254,2,ret,0x7aa249f25c,0x77ee8535bc,1,ret,0x775995f484,0x77ee8535d4,1,ret,0x7a907fa42c,0x7a88f5e248,4,ret,0x7a88f5e270,0x77f07315c4,3,ret,0x77f07315d0,0x7aa249f2d0,2,ret,0x7aa249f2d4,0x77ee8535d8,1,ret,0x77ee8535f8,0x77ee69c198,0,ret,0x77ee47dc74,0x77ee69c184,0,ret,0x77ee69c6c0,0x7708165bf8,-1,ret,0x7a90855d34,0x7a907d89a8,4,ret,0x7a907d89b4,0x7a907da330,3,ret,0x7a90855ff4,0x7a907d8a3c,4,ret,0x7a907d8a4c,0x7a907da45c,3,ret,0x7a907da514,0x7a907dab70,2,ret,0x7a907dab84,0x7a907d5134,1,ret,0x7a907d514c,0x77081ca484,0,ret,0x77081ca4a0,0x7708165c14,-1,ret,0x770809fd08,0x770815fe1c,0,ret,0x770815fe60,0x770815fe40,0,ret,0x770809fd08,0x770815fe94,0,ret,0x7708164948,0x7708164928,1,ret,0x77081649b0,0x7708164994,1,ret,0x77081649b0,0x77081649cc,1,ret,0x7708164a10,0x770815ff0c,0,ret,0x770815ff84,0x7708165c30,-1,ret,0x7a90855d34,0x7a907d89a8,4,ret,0x7a907d89b4,0x7a907da374,3,ret,0x7a90855ff4,0x7a907d8a3c,4,ret,0x7a907d8a4c,0x7a907da45c,3,ret,0x7a907da514,0x7a907dab70,2,ret,0x7a907dab84,0x7a907d5134,1,ret,0x7a907d514c,0x77081ca484,0,ret,0x77081ca4a0,0x7708165c5c,-1,ret,0x770809fd08,0x770815ffbc,0,ret,0x7708160000,0x770815ffe0,0,ret,0x770809fd08,0x7708160034,0,ret,0x7708164948,0x7708164928,1,ret,0x77081649b0,0x7708164994,1,ret,0x77081649b0,0x77081649cc,1,ret,0x7708164a10,0x7708160048,0,ret,0x7708160120,0x7708160100,0,ret,0x7708160274,0x7708165c8c,-1,ret,0x7708180fb4,0x77081653e8,1,ret,0x77ee47dc04,0x77ee47df90,3,ret,0x7a907ee238,0x7aa264e240,4,ret,0x7aa264e244,0x77ee47e178,3,ret,0x77ee47e1b4,0x77ee660d54,2,ret,0x77ee47dc44,0x77ee480b4c,3,ret,0x77ee47dc74,0x77ee47edb0,4,ret,0x7a907e4f5c,0x77ee47ee90,4,ret,0x77ee47ed44,0x77ee480b68,3,ret,0x7a907e88a0,0x7a90838c08,4,ret,0x7a90838c1c,0x77ee480b88,3,ret,0x7a907e88a0,0x77ee480b90,3,ret,0x77ee47dc04,0x77ee47df90,4,ret,0x7a907ee238,0x7aa264e240,5,ret,0x7aa264e244,0x77ee47e178,4,ret,0x77ee47e1b4,0x77ee480bd8,3,ret,0x77ee47dc44,0x77ee480c08,3,ret,0x77ee480c3c,0x77ee660d6c,2,ret,0x77ee47dc74,0x77ee47edb0,3,ret,0x7a907e4f5c,0x77ee47ee90,3,ret,0x77ee47ed44,0x77ee660d84,2,ret,0x77ee47dc04,0x77ee47df90,3,ret,0x7a907ee238,0x7aa264e240,4,ret,0x7aa264e244,0x77ee47e178,3,ret,0x77ee47e1b4,0x77ee660d54,2,ret,0x77ee47dc44,0x77ee480b4c,3,ret,0x77ee47dc74,0x77ee47edb0,4,ret,0x7a907e4f5c,0x77ee47ee90,4,ret,0x77ee47ed44,0x77ee480b68,3,ret,0x7a907e4f5c,0x77ee480b88,3,ret,0x77ee47dc04,0x77ee47df90,4,ret,0x7a907ee238,0x7aa264e240,5,ret,0x7aa264e244,0x77ee47e178,4,ret,0x77ee47e1b4,0x77ee480bd8,3,ret,0x77ee47dc44,0x77ee480c08,3,ret,0x77ee480c3c,0x77ee660d6c,2,ret,0x77ee47dc74,0x77ee47edb0,3,ret,0x7a907e4f5c,0x77ee47ee90,3,ret,0x77ee47ed44,0x77ee660d84,2,ret,0x77ee47dc04,0x77ee660c44,2,ret,0x77ee5c99dc,0x77ee6b638c,3,ret,0x77ee6b645c,0x77ee660e0c,2,ret,0x77ee47dc04,0x77ee47df90,4,ret,0x77ee47e1b4,0x77ee85355c,3,ret,0x7a90855df4,0x7a907dec6c,5,ret,0x7a90855d34,0x7a907d89a8,6,ret,0x7a907d89b4,0x7a907decb0,5,ret,0x7a90855ff4,0x7a907d8a3c,5,ret,0x7a907d8a4c,0x7a907da9c4,4,ret,0x7a907da9d4,0x77ee853590,3,ret,0x77ee47dc74,0x77ee47edb0,4,ret,0x77ee47ed44,0x77ee8535b0,3,ret,0x7a907fa42c,0x7a88f5e248,6,ret,0x7a88f5e270,0x77f0731598,5,ret,0x77f07315a8,0x7aa249f254,4,ret,0x7aa249f25c,0x77ee8535bc,3,ret,0x775995f484,0x77ee8535d4,3,ret,0x7a907fa42c,0x7a88f5e248,6,ret,0x7a88f5e270,0x77f07315c4,5,ret,0x77f07315d0,0x7aa249f2d0,4,ret,0x7aa249f2d4,0x77ee8535d8,3,ret,0x77ee8535f8,0x77ee661068,2,ret,0x77ee47dc04,0x77ee47df90,4,ret,0x77ee47e1b4,0x77ee85355c,3,ret,0x7a90855df4,0x7a907dec6c,5,ret,0x7a90855d34,0x7a907d89a8,6,ret,0x7a907d89b4,0x7a907decb0,5,ret,0x7a90855ff4,0x7a907d8a3c,5,ret,0x7a907d8a4c,0x7a907da9c4,4,ret,0x7a907da9d4,0x77ee853590,3,ret,0x77ee47dc74,0x77ee47edb0,4,ret,0x77ee47ed44,0x77ee8535b0,3,ret,0x7a907fa42c,0x7a88f5e248,6,ret,0x7a88f5e270,0x77f0731598,5,ret,0x77f07315a8,0x7aa249f254,4,ret,0x7aa249f25c,0x77ee8535bc,3,ret,0x775995f484,0x77ee8535d4,3,ret,0x7a907fa42c,0x7a88f5e248,6,ret,0x7a88f5e270,0x77f07315c4,5,ret,0x77f07315d0,0x7aa249f2d0,4,ret,0x7aa249f2d4,0x77ee8535d8,3,ret,0x77ee8535f8,0x77ee661068,2,ret,0x77ee47dc04,0x77ee47df90,4,ret,0x77ee47e1b4,0x77ee85355c,3,ret,0x77ee743674,0x77ee8535a4,3,ret,0x77ee47dc74,0x77ee47edb0,4,ret,0x77ee47ed44,0x77ee8535b0,3,ret,0x7a907fa42c,0x7a88f5e248,6,ret,0x7a88f5e270,0x77f0731598,5,ret,0x77f07315a8,0x7aa249f254,4,ret,0x7aa249f25c,0x77ee8535bc,3,ret,0x775995f484,0x77ee8535d4,3,ret,0x7a907fa42c,0x7a88f5e248,6,ret,0x7a88f5e270,0x77f07315c4,5,ret,0x77f07315d0,0x7aa249f2d0,4,ret,0x7aa249f2d4,0x77ee8535d8,3,ret,0x77ee8535f8,0x77ee661068,2,ret,0x77ee47dc74,0x77ee661054,2,ret,0x77ee6610b8,0x7708165400,1,ret,0x77ee6b5f00,0x7708165414,1,ret,0x77ee47dc04,0x77ee662a50,2
+++ into iterator: startAddress=0x77ee662c0c, isAppCode=false
...
+++ into iterator: startAddress=0x77ee64e7ec, isAppCode=false

Thank you for using Frida!

crifan.org，使用署名4.0国际(CC BY 4.0)协议发布 all right reserved，powered by Gitbook最后更新： 2025-06-04 11:27:37

调试loginWithPhoneNbr函数

调试loginWithPhoneNbr函数

参考：

【iOS逆向】某营业厅算法分析_小陈_InfoQ写作社区

的ts=TypeScript代码的Frida的Stalker调试loginWithPhoneNbr函数的例子：

var addr = 0x0000000029FD08 // loginWithPhoneNbr函数的起始地址
var mainModule = Process.enumerateModules()[0];
console.log(JSON.stringify(mainModule));
var mainName: string = mainModule.name;
var baseAddr = Module.findBaseAddress(mainName)!;
Interceptor.attach(baseAddr.add(addr), {
    onEnter: function(args) {
        console.log(addr.toString(16), "= loginWithPhoneNbr onEnter =");
        var tid = Process.getCurrentThreadId();
        Stalker.follow(tid, {
            events: {
                call: true, // CALL instructions: yes please
                ret: false, // RET instructions
                exec: false, // all instructions: not recommended as it's
                block: false, // block executed: coarse execution trace
                compile: false // block compiled: useful for coverage
            },
            transform: (iterator: StalkerArm64Iterator) => {
                let instruction = iterator.next();
                const startAddress = instruction!.address;
                var isAppCode = startAddress.compare(baseAddr.add(addr)) >= 0 && startAddress.compare(baseAddr.add(addr).add(10000)) === -1;
                do {
                    if (isAppCode) {
                        if (instruction!.mnemonic === "bl") {
                            iterator.putCallout((ctx) => {
                                var arm64Context = ctx as Arm64CpuContext;
                                console.log("bl x0 = " + new ObjC.Object(arm64Context.x0))
                                console.log("bl x1 = " + arm64Context.x1.readCString())
                            });
                        }
                    }
                    iterator.keep();
                } while ((instruction = iterator.next()) !== null);
             }
        })
    }, onLeave: function(retval) {
        console.log("retval:", new ObjC.Object(retval))
        console.log(addr.toString(16), "= loginWithPhoneNbr onLeave =");
    }
});

crifan.org，使用署名4.0国际(CC BY 4.0)协议发布 all right reserved，powered by Gitbook最后更新： 2025-06-04 09:29:55

某小说App的Stalker用法

某小说App的Stalker用法

参考：

Frida Stalker 是什么？ - 奋飞安全

的Stalker示例代码：

function trace_entry(baseAddr, tatgetAddr) {
  Interceptor.attach(tatgetAddr, {
    onEnter: function (args) {
      console.log("enter tatgetAddr====================================================================");

      this.pid = Process.getCurrentThreadId();
      Stalker.follow(this.pid, {
        events: {
          // 暂时不需要这些 events
          call: false,
          ret: false,
          exec: false,

          block: false,
          compile: false
        },
        onReceive: function (events) {
        },

        transform: function (iterator) {
          var instruction = iterator.next();
          const startAddress = instruction.address;
          // 从ida里面 找到 Java_com_baidu_searchbox_NativeBds_dae1 函数的 代码 在 0xE84 和 0x126C 之间
          var isModule = startAddress.compare(baseAddr.add(0xE84)) >= 0 && startAddress.compare(baseAddr.add(0x126C)) < 0;
          do {
            if (isModule) {
              console.log(instruction.address.sub(baseAddr) + "\t:\t" + instruction);

            if(instruction.address.sub(baseAddr) == 0xfb8){
              iterator.putCallout((context) => {
                var string = Memory.readCString(context["x21"]);
                console.log("####  key = " + string)
              })
            }
            }
            iterator.keep();
          } while ((instruction = iterator.next()) !== null);
        },

        onCallSummary: function (summary) {

        }
      });
    }, onLeave: function (retval) {
      Stalker.unfollow(this.pid);
      console.log("retval:" + retval);
      console.log("leave tatgetAddr====================================================================");
    }
  });
}

部分输出日志：

0xfb4        :        add x21, x21, x0, lsr #1
0xfb8        :        mov x0, x21
0xfbc        :        ldr x22, [x8, #0x580]
0xfc0        :        bl #0x7a751c55f0
####  key = D0CD8B760CE07BC3
0xfc4        :        mov x1, x0
0xfc8        :        mov x0, x20
0xfcc        :        blr x22
0xfd0        :        ldr x8, [x20]

crifan.org，使用署名4.0国际(CC BY 4.0)协议发布 all right reserved，powered by Gitbook最后更新： 2025-06-04 11:40:54

misc/frida-stalker-example.py

misc/frida-stalker-example.py

别处：

misc/frida-stalker-example.py at master · poxyran/misc · GitHub

的某个Python代码内包含Frida的Stalker的js的例子：

import sys
import frida

def on_message(message, data):
    print "[%s] -> %s" % (message, data)

def main(target_process):
    session = frida.attach(target_process)
    script = session.create_script("""
function StalkerExeample()
{
    var threadIds = [];

    Process.enumerateThreads({
        onMatch: function (thread)
        {
            threadIds.push(thread.id);
            console.log("Thread ID: " + thread.id.toString());
        },

        onComplete: function ()
        {
            threadIds.forEach(function (threadId)
                {
                    Stalker.follow(threadId,
                    {
                        events: {call: true},

                    onReceive: function (events)
                    {
                        console.log("onReceive called.");
                    },
                    onCallSummary: function (summary)
                    {
                        console.log("onCallSummary called.");
                    }
                });
            });
        }
    });
}

StalkerExeample();
""")
    script.on('message', on_message)
    script.load()
    raw_input('[!] Press <Enter> at any time to detach from instrumented program.\n\n')
    session.detach()

if __name__ == '__main__':
    if len(sys.argv) < 2:
        print 'Usage: %s <process name or PID>' % __file__
        sys.exit(1)

    try:
        target_process = int(sys.argv[1])
    except ValueError:
        target_process = sys.argv[1]

    main(target_process)

crifan.org，使用署名4.0国际(CC BY 4.0)协议发布 all right reserved，powered by Gitbook最后更新： 2025-06-04 09:28:23

Stalker心得

Stalker心得

crifan.org，使用署名4.0国际(CC BY 4.0)协议发布 all right reserved，powered by Gitbook最后更新： 2025-06-03 22:51:05

Stalker.follow

Stalker.follow

此处介绍Frida的Stalker中，相对最核心的Stalker.follow的相关心得。

crifan.org，使用署名4.0国际(CC BY 4.0)协议发布 all right reserved，powered by Gitbook最后更新： 2025-06-04 12:09:32

Stalker的利用方式

Stalker的利用方式

Frida的Stalker的利用方式，目前算明白了，至少有2种：

（1）给特定位置加上额外的代码

（2）针对特定位置，去调试输出打印相关值

查看寄存器的值

（读取）查看内存的值

等等

举例说明：

（1）给特定位置加上额外的代码

官网的例子：

JavaScript API | Frida • A world-class dynamic instrumentation toolkit

  //
  // Advanced users: This is how you can plug in your own
  //                 StalkerTransformer, where the provided
  //                 function is called synchronously
  //                 whenever Stalker wants to recompile
  //                 a basic block of the code that's about
  //                 to be executed by the stalked thread.
  //
  //transform(iterator) {
  //  let instruction = iterator.next();
  //
  //  const startAddress = instruction.address;
  //  const isAppCode = startAddress.compare(appStart) >= 0 &&
  //      startAddress.compare(appEnd) === -1;
  //
  //  do {
  //    if (isAppCode && instruction.mnemonic === 'ret') {
  //      iterator.putCmpRegI32('eax', 60);
  //      iterator.putJccShortLabel('jb', 'nope', 'no-hint');
  //
  //      iterator.putCmpRegI32('eax', 90);
  //      iterator.putJccShortLabel('ja', 'nope', 'no-hint');
  //
  //      iterator.putCallout(onMatch);
  //
  //      iterator.putLabel('nope');
  //    }
  //
  //    iterator.keep();
  //  } while ((instruction = iterator.next()) !== null);
  //},
  //
  // The default implementation is just:
  //
  //   while (iterator.next() !== null)
  //     iterator.keep();
  //
  // The example above shows how you can insert your own code
  // just before every `ret` instruction across any code
  // executed by the stalked thread inside the app's own
  // memory range. It inserts code that checks if the `eax`
  // register contains a value between 60 and 90, and inserts
  // a synchronous callout back into JavaScript whenever that
  // is the case. The callback receives a single argument
  // that gives it access to the CPU registers, and it is
  // also able to modify them.
  //
  // function onMatch (context) {
  //   console.log('Match! pc=' + context.pc +
  //       ' rax=' + context.rax.toInt32());
  // }
  //
  // Note that not calling keep() will result in the
  // instruction getting dropped, which makes it possible
  // for your transform to fully replace certain instructions
  // when this is desirable.
  //

意思是：

此处希望实现的特定效果

当发现是ret指令，即在ret真正运行，函数返回值，再去：

插入对应的代码：

  //      iterator.putCmpRegI32('eax', 60);
  //      iterator.putJccShortLabel('jb', 'nope', 'no-hint');
  //
  //      iterator.putCmpRegI32('eax', 90);
  //      iterator.putJccShortLabel('ja', 'nope', 'no-hint’);
  //      iterator.putLabel('nope');

实现特定的逻辑：

检查eax寄存器是否包含 60 到 90 之间的值

-》如果你有类似需求，也可以去实现：

当满足条件（比如某个特定的指令，具体到某行代码），去插入特定代码，实现你的特定的逻辑

（2）针对特定位置，去调试输出打印相关值

比如我前面的：

___lldb_unnamed_symbol2575$$akd

-》核心代码是：

var funcRelativeStartAddr = 0xa0460;
var functionSize = 0x24C8; // 9416 == 0x24C8
var funcRelativeEndAddr = funcRelativeStartAddr + functionSize;
console.log("funcRelativeStartAddr=" + funcRelativeStartAddr + ", functionSize=" + functionSize + ", funcRelativeEndAddr=" + funcRelativeEndAddr);
const moduleName = "akd";
const moduleBaseAddress = Module.findBaseAddress(moduleName);
console.log("moduleName=" + moduleName + ", moduleBaseAddress=" + moduleBaseAddress);
// console.log("moduleName=%s, moduleBaseAddress=%p", moduleName, moduleBaseAddress);
const funcRealStartAddr = moduleBaseAddress.add(funcRelativeStartAddr);
// var funcRealEndAddr = funcRealStartAddr + functionSize;
const funcRealEndAddr = funcRealStartAddr.add(functionSize);
console.log("funcRealStartAddr=" + funcRealStartAddr + ", funcRealEndAddr=" + funcRealEndAddr);

Interceptor.attach(funcRealStartAddr, {
    onEnter: function(args) {
        var arg0 = args[0]
        var arg1 = args[1]
        var arg2 = args[2]
        var arg3 = args[3]
        console.log("----- arg0=" + arg0 + ", arg1=" + arg1 + ", arg2=" + arg2 + ", arg3=" + arg3);
        var curTid = Process.getCurrentThreadId();
        console.log("curTid=", curTid);
        Stalker.follow(curTid, {
            events: {
                call: true, // CALL instructions: yes please
                ret: false, // RET instructions
                exec: false, // all instructions: not recommended as it's
                block: false, // block executed: coarse execution trace
                compile: false // block compiled: useful for coverage
            },
            // transform: (iterator: StalkerArm64Iterator) => {
            transform: function (iterator) {
                var instruction = iterator.next();
                const startAddress = instruction.address;
                const gt_realStartAddr = startAddress.compare(funcRealStartAddr) >= 0
                const lt_realEndAddr = startAddress.compare(funcRealEndAddr) < 0
                var isAppCode = gt_realStartAddr && lt_realEndAddr
                console.log("+++ into iterator: startAddress=" + startAddress + ", isAppCode=" + isAppCode);
                do {
                    if (isAppCode) {
                        // is origal function code = which we focus on

                        var curRealAddr = instruction.address;
                        // const isAppCode = curRealAddr.compare(funcRealStartAddr) >= 0 && curRealAddr.compare(funcRealEndAddr) === -1;
                        // console.log(curRealAddr + ": isAppCode=" + isAppCode);
                        var curOffsetHexPtr = curRealAddr.sub(funcRealStartAddr)
                        var curOffsetInt = curOffsetHexPtr.toInt32()

                        // var instructionStr = instruction.mnemonic + " " + instruction.opStr
                        var instructionStr = instruction.toString()
                        console.log("\t" + curRealAddr + " <+" + curOffsetInt + ">: " + instructionStr);
                        if (curOffsetInt == 8516) {
                            console.log("curOffsetInt=" + curOffsetInt);
                            iterator.putCallout((context) => {
                                var contextStr = JSON.stringify(context)
                                console.log("contextStr=" + contextStr);
                                var x9Value1 = context.x9
                                var x9Value2 = context["x9"]
                                console.log("x9Value1=" + x9Value1 + ", x9Value2=" + x9Value2)
                            });
                        }
                    }
                    iterator.keep();
                } while ((instruction = iterator.next()) !== null);
            }
        });

其中就是：

当判断到是 +8516 行代码时，去查看x9的值（是否是我们希望的，最后所要返回的值）

所以就去判断：

是否是改行代码

if (curOffsetInt == 8516) {

如果是，则去：

通过putCallout，传入匿名函数，其中去调试

去打印x9寄存器的值

crifan.org，使用署名4.0国际(CC BY 4.0)协议发布 all right reserved，powered by Gitbook最后更新： 2025-06-04 10:26:18

events的属性含义

Stalker.follow中的events的属性含义

对于：

Interceptor.attach(funcRealStartAddr, {
    onEnter: function(args) {
...
        Stalker.follow(curTid, {
            events: {
              call: false, // CALL instructions: yes please
              ret: true, // RET instructions
              exec: false, // all instructions: not recommended as it's
              block: false, // block executed: coarse execution trace
              compile: false // block compiled: useful for coverage
            },
            // onReceive: Called with `events` containing a binary blob comprised of one or more GumEvent structs. See `gumevent.h` for details about the format. Use `Stalker.parse()` to examine the data.
            onReceive(events) {
              var parsedEvents = Stalker.parse(events)
              // var parsedEventsStr = JSON.stringify(parsedEventsStr)
              // console.log(">>> into onReceive: parsedEvents=" + parsedEvents + ", parsedEventsStr=" + parsedEventsStr);
              console.log(">>> into onReceive: parsedEvents=" + parsedEvents);
            },

            // transform: (iterator: StalkerArm64Iterator) => {
            transform: function (iterator) {
...

中：

Stalker.follow中的events的属性含义

概述

Stalker.follow中的events中某个属性是true，含义是：当出现对应指令，则触发对应event事件

详解

属性

对应的属性的含义是

call：call指令

Intel=X86的：call指令

ARM的：BL类的指令

普通的=arm64的：BL、BLR等

arm64e的，带PAC的：BLRAA、BLRAAZ、BLRAB、BLRABZ等

ret：ret指令

exec：所有指令

block：（单个）block的（所有）指令

compile：特殊，（单个）block被编译时，仅用于测试代码覆盖率？

除去特殊的compile参数，其他几个参数，按照范围大小去划分，更容易理解：

exec：所有代码的级别

block：单个代码块的级别

某些特殊指令的级别

call：单独的call指令

ret：单独的ret指令

event事件

会触发onReceive(events)函数

其中可以events是二进制（的blob），需要去用Stalker.parse()解析后才能看懂

->events和onReceive的作用

暂时不完全懂，只是知道，可以设置参数，决定call、ret等指令的触发时去打印，其他用途暂时不清楚

crifan.org，使用署名4.0国际(CC BY 4.0)协议发布 all right reserved，powered by Gitbook最后更新： 2025-06-04 14:41:53

transform的逻辑

Frida的Stalker中transform的逻辑

除了官网文档介绍了内部具体实现机制和过程之外：

对于，想要搞懂如何利用transform去调试代码来说：

需要明白的逻辑是：

此处代码：

Interceptor.attach(funcRealStartAddr, {
    onEnter: function(args) {
...
        var curTid = Process.getCurrentThreadId();
        console.log("curTid=", curTid);
        Stalker.follow(curTid, {
            events: {
                call: true, // CALL instructions: yes please
                ret: false, // RET instructions
                exec: false, // all instructions: not recommended as it's
                block: false, // block executed: coarse execution trace
                compile: false // block compiled: useful for coverage
            },
            // transform: (iterator: StalkerArm64Iterator) => {
            transform: function (iterator) {
                ...

触发到的transform的iterator来说：

每次触发=每个iterator：都（对应着）单个block=（basic）代码块

此处代码块有2种

非原始函数代码 == isAppCode=false

对应着应该是Stalker内部实现原理说的，copy拷贝出的代码

其中会额外加上很多逻辑，用于实现Stalker的功能和逻辑

估计就是这里说的这些内容

[原创] sktrace：基于 Frida Stalker 的 trace 工具-Android安全-看雪-安全社区|安全招聘|kanxue.com

每当执行到一个基本块，Stalker都会做以下几件事：

对于方法调用，保存lr等必要信息

重定位位置相关指令，例如：ADR Xd, label

建立此块的索引，如果此块在达到可信阈值后，内容未曾变化，下次将不再重新编译（为了加快速度）

根据 transform 函数，编译生成一个新的基本块 GumExecBlock ，保存到 GumSlab 。void transform(GumStalkerIterator iterator, GumStalkerOutput output, gpointer user_data) 可以控制读取，改动，写入指令。

transform 过程中还可通过 void gum_stalker_iterator_put_callout (GumStalkerIterator self,GumStalkerCallout callout, gpointer data, GDestroyNotify data_destroy) 来设置一个当此位置被执行到时的callout。通过此void callout(GumCpuContext cpu_context, gpointer user_data)获取cpu信息。

执行一个基本快GumExecBlock，开始下一个基本快

所以无需操作具体内部过程，直接忽略即可

原始函数代码 == isAppCode=true

是实际运行的代码，才是我们所要关注的代码

才会真正的去处理：比如判断是否是对应的（某个偏移量的）代码，然后去打印查看调试寄存器的值等等

此处去通过计算是否是 原始函数代码isAppCode 决定是否处理

具体详见示例代码：

___lldb_unnamed_symbol2575$$akd

crifan.org，使用署名4.0国际(CC BY 4.0)协议发布 all right reserved，powered by Gitbook最后更新： 2025-06-04 12:12:06

context的属性和含义

iterator.putCallout中的context的属性和含义

对于

transform: function (iterator) {
...
  iterator.putCallout((context) => {
...

中的context，其定义是：

Stalker | Frida • A world-class dynamic instrumentation toolkit

typedef GumArm64CpuContext GumCpuContext;

struct _GumArm64CpuContext
{
  guint64 pc;
  guint64 sp;

  guint64 x[29];
  guint64 fp;
  guint64 lr;
  guint8 q[128];
};

某次调试时打印出的值是：

contextStr={"pc":"0x1041865a4","sp":"0x16bf46740","nzcv":1610612736,"x0":"0x0","x1":"0x104ba0000","x2":"0xc","x3":"0x29","x4":"0x470b","x5":"0x0","x6":"0x0","x7":"0xec0","x8":"0x0","x9":"0x3050500","x10":"0x16bf46838","x11":"0x6c245a87","x12":"0x6c245a3d","x13":"0x1041864dc","x14":"0x45","x15":"0x0","x16":"0xd5709bdf0d7a48f0","x17":"0x123209fc0","x18":"0x0","x19":"0xdf3221f55389ecc8","x20":"0x1233064b0","x21":"0x93dba5a2","x22":"0x0","x23":"0x39207beb","x24":"0x6c245a87","x25":"0x1041a6cb0","x26":"0x6c245a87","x27":"0x194d2c100","x28":"0xfffffffffffffffe","fp":"0x16bf46820","lr":"0x104186168","q0":{},"q1":{},"q2":{},"q3":{},"q4":{},"q5":{},"q6":{},"q7":{},"q8":{},"q9":{},"q10":{},"q11":{},"q12":{},"q13":{},"q14":{},"q15":{},"q16":{},"q17":{},"q18":{},"q19":{},"q20":{},"q21":{},"q22":{},"q23":{},"q24":{},"q25":{},"q26":{},"q27":{},"q28":{},"q29":{},"q30":{},"q31":{},"d0":0.5585262685374610e-308,"d1":0.0000169759663317e-308,"d2":7.9499288951273454e-275,"d3":0,"d4":0,"d5":0,"d6":0,"d7":0,"d8":0,"d9":0,"d10":0,"d11":0,"d12":0,"d13":0,"d14":0,"d15":0,"d16":-1.0855813867524649e+251,"d17":0.000002084565455e-308,"d18":3.0554698911305689e-152,"d19":0.000001322084152e-308,"d20":3.7696966457559071e-175,"d21":1.0004894955531618e+128,"d22":9.5944260775693913e+225,"d23":-6.8154492514793903e-236,"d24":-2.1930923744387854e+50,"d25":-3.1153191556287330e+141,"d26":-1.0031492505499153e+302,"d27":-3.1584786060327890e-284,"d28":-1.7036104465458726e+239,"d29":-1.1538744009003510e-197,"d30":2.4944484440662111e-259,"d31":0,"s0":1.1035169354619356e-39,"s1":1.1210387714598533e-44,"s2":3.8204714345426298e-37,"s3":0,"s4":0,"s5":0,"s6":0,"s7":0,"s8":0,"s9":0,"s10":0,"s11":0,"s12":0,"s13":0,"s14":0,"s15":0,"s16":1.5548730664783592e-21,"s17":-1.3084408235578860e+36,"s18":-8.6088756618229034e-23,"s19":-5.408784745233076e-20,"s20":4.2151578028428229e+37,"s21":18362722504671230,"s22":3.372155249992253e+28,"s23":-7.6784630118876258e-30,"s24":-3715189.5,"s25":2.6426119211413095e+23,"s26":-3.5724724140742379e-23,"s27":-1.6239861190373424e-18,"s28":-205533200,"s29":-0.008124308660626411,"s30":-5.6424941355004989e-36,"s31":0}

格式化后：

{
    "pc": "0x1041865a4",
    "sp": "0x16bf46740",
    "nzcv": 1610612736,
    "x0": "0x0",
    "x1": "0x104ba0000",
    "x2": "0xc",
    "x3": "0x29",
    "x4": "0x470b",
    "x5": "0x0",
    "x6": "0x0",
    "x7": "0xec0",
    "x8": "0x0",
    "x9": "0x3050500",
    "x10": "0x16bf46838",
    "x11": "0x6c245a87",
    "x12": "0x6c245a3d",
    "x13": "0x1041864dc",
    "x14": "0x45",
    "x15": "0x0",
    "x16": "0xd5709bdf0d7a48f0",
    "x17": "0x123209fc0",
    "x18": "0x0",
    "x19": "0xdf3221f55389ecc8",
    "x20": "0x1233064b0",
    "x21": "0x93dba5a2",
    "x22": "0x0",
    "x23": "0x39207beb",
    "x24": "0x6c245a87",
    "x25": "0x1041a6cb0",
    "x26": "0x6c245a87",
    "x27": "0x194d2c100",
    "x28": "0xfffffffffffffffe",
    "fp": "0x16bf46820",
    "lr": "0x104186168",
    "q0": {},
    "q1": {},
    "q2": {},
    "q3": {},
    "q4": {},
    "q5": {},
    "q6": {},
    "q7": {},
    "q8": {},
    "q9": {},
    "q10": {},
    "q11": {},
    "q12": {},
    "q13": {},
    "q14": {},
    "q15": {},
    "q16": {},
    "q17": {},
    "q18": {},
    "q19": {},
    "q20": {},
    "q21": {},
    "q22": {},
    "q23": {},
    "q24": {},
    "q25": {},
    "q26": {},
    "q27": {},
    "q28": {},
    "q29": {},
    "q30": {},
    "q31": {},
    "d0": 0.5585262685374610e-308,
    "d1": 0.0000169759663317e-308,
    "d2": 7.9499288951273454e-275,
    "d3": 0,
    "d4": 0,
    "d5": 0,
    "d6": 0,
    "d7": 0,
    "d8": 0,
    "d9": 0,
    "d10": 0,
    "d11": 0,
    "d12": 0,
    "d13": 0,
    "d14": 0,
    "d15": 0,
    "d16": -1.0855813867524649e+251,
    "d17": 0.000002084565455e-308,
    "d18": 3.0554698911305689e-152,
    "d19": 0.000001322084152e-308,
    "d20": 3.7696966457559071e-175,
    "d21": 1.0004894955531618e+128,
    "d22": 9.5944260775693913e+225,
    "d23": -6.8154492514793903e-236,
    "d24": -2.1930923744387854e+50,
    "d25": -3.1153191556287330e+141,
    "d26": -1.0031492505499153e+302,
    "d27": -3.1584786060327890e-284,
    "d28": -1.7036104465458726e+239,
    "d29": -1.1538744009003510e-197,
    "d30": 2.4944484440662111e-259,
    "d31": 0,
    "s0": 1.1035169354619356e-39,
    "s1": 1.1210387714598533e-44,
    "s2": 3.8204714345426298e-37,
    "s3": 0,
    "s4": 0,
    "s5": 0,
    "s6": 0,
    "s7": 0,
    "s8": 0,
    "s9": 0,
    "s10": 0,
    "s11": 0,
    "s12": 0,
    "s13": 0,
    "s14": 0,
    "s15": 0,
    "s16": 1.5548730664783592e-21,
    "s17": -1.3084408235578860e+36,
    "s18": -8.6088756618229034e-23,
    "s19": -5.408784745233076e-20,
    "s20": 4.2151578028428229e+37,
    "s21": 18362722504671230,
    "s22": 3.372155249992253e+28,
    "s23": -7.6784630118876258e-30,
    "s24": -3715189.5,
    "s25": 2.6426119211413095e+23,
    "s26": -3.5724724140742379e-23,
    "s27": -1.6239861190373424e-18,
    "s28": -205533200,
    "s29": -0.008124308660626411,
    "s30": -5.6424941355004989e-36,
    "s31": 0
}

-》其中可以看到：各个寄存器的值

-》实现了调试的目的：查看寄存器等方面的值

crifan.org，使用署名4.0国际(CC BY 4.0)协议发布 all right reserved，powered by Gitbook最后更新： 2025-06-04 12:13:04

Instruction的属性

Stalker.follow中的transform中的Instruction的属性

此处介绍Stalker.follow中transform中的指令=instruction的属性的详情：

Instruction有哪些属性

参考

Frida官网

Frida的Instruction

相关资料

Capstone

Java接口

capstone/Capstone.java at next · capstone-engine/capstone · GitHub

Python接口

capstone/init.py at next · capstone-engine/capstone · GitHub

总结出：

Instruction的属性

address

next

size

mnemonic

opStr

operands

regsRead

regsWritten

groups

toString()

regsAccessed

toJSON()

注：但是没有（其实希望也有的）bytes=opcode属性。

如何打印Instruction的属性

打印对应的属性值的代码：

console.log("instruction: address=" + instruction.address
    + ",next=" + instruction.next()
    + ",size=" + instruction.size
    + ",mnemonic=" + instruction.mnemonic
    + ",opStr=" + instruction.opStr
    + ",operands=" + JSON.stringify(instruction.operands)
    + ",regsAccessed=" + JSON.stringify(instruction.regsAccessed)
    + ",regsRead=" + JSON.stringify(instruction.regsRead)
    + ",regsWritten=" + JSON.stringify(instruction.regsWritten)
    + ",groups=" + JSON.stringify(instruction.groups)
    + ",toString()=" + instruction.toString()
    + ",toJSON()=" + instruction.toJSON()
);

输出效果：

（注：当时没加regsAccessed和toJSON()）

instruction: address=0x10f4ecef4,next=0x4,size=4,mnemonic=ldr,opStr=x0, #0x10f4ecf78,operands=[{"type":"reg","value":"x0","access":"w"},{"type":"imm","value":"4551790456","access":"r"}],regsRead=[],regsWritten=[],groups=[],toString()=ldr x0, #0x10f4ecf78
[0x10f4ecef4] ldr x0, #0x10f4ecf78

instruction: address=0x10f4ecef8,next=0x4,size=4,mnemonic=bl,opStr=#0x1091a500c,operands=[{"type":"imm","value":"4447686668","access":"r"}],regsRead=[],regsWritten=["lr"],groups=["call","jump","branch_relative"],toString()=bl #0x1091a500c
[0x10f4ecef8] bl #0x1091a500c

FridaUtil的printInstructionInfo

以及后续新版中，加上：regsAccessed、toJSON()后，经过整理，已提取到工具类函数中：

https://github.com/crifan/JsFridaUtil/blob/main/frida/FridaUtil.js

中的：

  static printInstructionInfo(instruction){
    // Instruction: address=0x252c0edf8,toString()=br x10,next=0x4,size=4,mnemonic=br,opStr=x10,operands=[{"type":"reg","value":"x10","access":"r"}],regsAccessed={"read":["x10"],"written":[]},regsRead=[],regsWritten=[],groups=["jump"],toJSON()={"address":"0x252c0edf8","next":"0x4","size":4,"mnemonic":"br","opStr":"x10","operands":[{"type":"reg","value":"x10","access":"r"}],"regsAccessed":{"read":["x10"],"written":[]},"regsRead":[],"regsWritten":[],"groups":["jump"]}
    console.log("Instruction: address=" + instruction.address
      + ",toString()=" + instruction.toString()
      + ",toJSON()=" + JSON.stringify(instruction.toJSON())
      // + ",next=" + instruction.next
      // + ",size=" + instruction.size
      // + ",mnemonic=" + instruction.mnemonic
      // + ",opStr=" + instruction.opStr
      // + ",operands=" + JSON.stringify(instruction.operands)
      // + ",regsAccessed=" + JSON.stringify(instruction.regsAccessed)
      // + ",regsRead=" + JSON.stringify(instruction.regsRead)
      // + ",regsWritten=" + JSON.stringify(instruction.regsWritten)
      // + ",groups=" + JSON.stringify(instruction.groups)
    )
  }

以及之前的某次输出的效果是：

Instruction: address=0x252c0eca4,toString()=stp x20, x19, [sp, #0x40],next=0x4,size=4,mnemonic=stp,opStr=x20, x19, [sp, #0x40],operands=[{"type":"reg","value":"x20","access":"r"},{"type":"reg","value":"x19","access":"r"},{"type":"mem","value":{"base":"sp","disp":64},"access":"rw"}],regsAccessed={"read":["x20","x19","sp"],"written":[]},regsRead=[],regsWritten=[],groups=[],toJSON()={"address":"0x252c0eca4","next":"0x4","size":4,"mnemonic":"stp","opStr":"x20, x19, [sp, #0x40]","operands":[{"type":"reg","value":"x20","access":"r"},{"type":"reg","value":"x19","access":"r"},{"type":"mem","value":{"base":"sp","disp":64},"access":"rw"}],"regsAccessed":{"read":["x20","x19","sp"],"written":[]},"regsRead":[],"regsWritten":[],"groups":[]}

供参考。

Instruction的属性的来源

而这些属性的来源：

主要是Capstone

Java接口

capstone/Capstone.java at next · capstone-engine/capstone · GitHub

Python接口

capstone/__init__.py at next · capstone-engine/capstone · GitHub

其次是Frida内部

frida/frida-gum

https://github.com/frida/frida-gum/blob/main/bindings/gumjs/gumquickinstruction.c

下面摘录其相关的核心代码：

capstone/Capstone.java

capstone/Capstone.java

  protected static class _cs_insn extends Structure {
    // instruction ID.
    public int id;
    // instruction address.
    public long address;
    // instruction size.
    public short size;
    // machine bytes of instruction.
    public byte[] bytes;
    // instruction mnemonic. NOTE: irrelevant for diet engine.
    public byte[] mnemonic;
    // instruction operands. NOTE: irrelevant for diet engine.
    public byte[] op_str;
    // detail information of instruction.
    public _cs_detail.ByReference cs_detail;

...

  public static class CsInsn {
    private Pointer csh;
    private CS cs;
    private _cs_insn raw;
    private int arch;

    // instruction ID.
    public int id;
    // instruction address.
    public long address;
    // instruction size.
    public short size;
    // Machine bytes of this instruction, with number of bytes indicated by size above
    public byte[] bytes;
    // instruction mnemonic. NOTE: irrelevant for diet engine.
    public String mnemonic;
    // instruction operands. NOTE: irrelevant for diet engine.
    public String opStr;
    // list of all implicit registers being read.
    public short[] regsRead;
    // list of all implicit registers being written.
    public short[] regsWrite;
    // list of semantic groups this instruction belongs to.
    public byte[] groups;
    public OpInfo operands;

capstone/__init__.py

capstone/__init__.py

中相关核心代码：

class _cs_insn(ctypes.Structure):
    _fields_ = (
        ('id', ctypes.c_uint),
        ('alias_id', ctypes.c_uint64),
        ('address', ctypes.c_uint64),
        ('size', ctypes.c_uint16),
        ('bytes', ctypes.c_ubyte * 24),
        ('mnemonic', ctypes.c_char * 32),
        ('op_str', ctypes.c_char * 160),
        ('is_alias', ctypes.c_bool),
        ('usesAliasDetails', ctypes.c_bool),
        ('illegal', ctypes.c_bool),
        ('detail', ctypes.POINTER(_cs_detail)),
    )

...

# Python-style class to disasm code
class CsInsn(object):
    def __init__(self, cs, all_info):
        self._raw = copy_ctypes(all_info)
        self._cs = cs
        if self._cs._detail and not self.is_invalid_insn():
            # save detail
            self._raw.detail = ctypes.pointer(all_info.detail._type_())
            ctypes.memmove(ctypes.byref(self._raw.detail[0]), ctypes.byref(all_info.detail[0]),
                           ctypes.sizeof(type(all_info.detail[0])))

    def __repr__(self):
        return '<CsInsn 0x%x [%s]: %s %s>' % (self.address, self.bytes.hex(), self.mnemonic, self.op_str)

    # return if the instruction is invalid
    def is_invalid_insn(self):
        arch = self._cs.arch
        if arch == CS_ARCH_EVM:
            return self.id == evm.EVM_INS_INVALID
        else:
            return self.id == 0

    # return instruction's ID.
    @property
    def id(self):
        return self._raw.id

    # return instruction's address.
    @property
    def address(self):
        return self._raw.address

    # return instruction's size.
    @property
    def size(self):
        return self._raw.size

    # return instruction's is_alias flag
    @property
    def is_alias(self):
        return self._raw.is_alias

    # return instruction's illegal flag
    # Set if instruction can be decoded but is invalid
    # due to context or illegal operands.
    @property
    def illegal(self):
        return self._raw.illegal

    # return instruction's alias_id
    @property
    def alias_id(self):
        return self._raw.alias_id

    # return instruction's flag if it uses alias details
    @property
    def uses_alias_details(self):
        return self._raw.usesAliasDetails

    # return instruction's machine bytes (which should have @size bytes).
    @property
    def bytes(self):
        return bytearray(self._raw.bytes)[:self._raw.size]

    # return instruction's mnemonic.
    @property
    def mnemonic(self):
        if self._cs._diet:
            # Diet engine cannot provide @mnemonic.
            raise CsError(CS_ERR_DIET)

        return self._raw.mnemonic.decode('ascii')

    # return instruction's operands (in string).
    @property
    def op_str(self):
        if self._cs._diet:
            # Diet engine cannot provide @op_str.
            raise CsError(CS_ERR_DIET)

        return self._raw.op_str.decode('ascii')

    # return list of all implicit registers being read.
    @property
    def regs_read(self):
        if self.is_invalid_insn():
            raise CsError(CS_ERR_SKIPDATA)

        if self._cs._diet:
            # Diet engine cannot provide @regs_read.
            raise CsError(CS_ERR_DIET)

        if self._cs._detail:
            return self._raw.detail.contents.regs_read[:self._raw.detail.contents.regs_read_count]

        raise CsError(CS_ERR_DETAIL)

    # return list of all implicit registers being modified
    @property
    def regs_write(self):
        if self.is_invalid_insn():
            raise CsError(CS_ERR_SKIPDATA)

        if self._cs._diet:
            # Diet engine cannot provide @regs_write
            raise CsError(CS_ERR_DIET)

        if self._cs._detail:
            return self._raw.detail.contents.regs_write[:self._raw.detail.contents.regs_write_count]

        raise CsError(CS_ERR_DETAIL)

    # return list of semantic groups this instruction belongs to.
    @property
    def groups(self):
        if self.is_invalid_insn():
            raise CsError(CS_ERR_SKIPDATA)

        if self._cs._diet:
            # Diet engine cannot provide @groups
            raise CsError(CS_ERR_DIET)

        if self._cs._detail:
            return self._raw.detail.contents.groups[:self._raw.detail.contents.groups_count]

        raise CsError(CS_ERR_DETAIL)

    # return whether instruction has writeback operands.
    @property
    def writeback(self):
        if self.is_invalid_insn():
            raise CsError(CS_ERR_SKIPDATA)

        if self._cs._diet:
            # Diet engine cannot provide @writeback.
            raise CsError(CS_ERR_DIET)

        if self._cs._detail:
            return self._raw.detail.contents.writeback

        raise CsError(CS_ERR_DETAIL)

frida-gum/bindings/gumjs/gumquickinstruction.c

frida-gum/bindings/gumjs/gumquickinstruction.c at main · frida/frida-gum

的相关核心代码：

static const JSCFunctionListEntry gumjs_instruction_entries[] =
{
  JS_CGETSET_DEF ("address", gumjs_instruction_get_address, NULL),
  JS_CGETSET_DEF ("next", gumjs_instruction_get_next, NULL),
  JS_CGETSET_DEF ("size", gumjs_instruction_get_size, NULL),
  JS_CGETSET_DEF ("mnemonic", gumjs_instruction_get_mnemonic, NULL),
  JS_CGETSET_DEF ("opStr", gumjs_instruction_get_op_str, NULL),
  JS_CGETSET_DEF ("operands", gumjs_instruction_get_operands, NULL),
  JS_CGETSET_DEF ("regsAccessed", gumjs_instruction_get_regs_accessed, NULL),
  JS_CGETSET_DEF ("regsRead", gumjs_instruction_get_regs_read, NULL),
  JS_CGETSET_DEF ("regsWritten", gumjs_instruction_get_regs_written, NULL),
  JS_CGETSET_DEF ("groups", gumjs_instruction_get_groups, NULL),
  JS_CFUNC_DEF ("toString", 0, gumjs_instruction_to_string),
  JS_CFUNC_DEF ("toJSON", 0, gumjs_instruction_to_json),
};

crifan.org，使用署名4.0国际(CC BY 4.0)协议发布 all right reserved，powered by Gitbook最后更新： 2025-08-22 21:43:42

Stalker.follow()的内部实现原理

Stalker.follow()内部实现原理

当用户调用Stalker.follow()时，内部调用：

要么是：gum_stalker_follow_me() ：去跟踪当前的线程thread

函数原型

GUM_API void gum_stalker_follow_me (GumStalker * self, GumStalkerTransformer * transformer, GumEventSink * sink);

底层JS引擎：是QuickJS或V8

要么是：gum_stalker_follow(thread_id)：去跟踪当前process进程中的其他某个线程thread

gum_stalker_follow_me的内部原理

#ifdef __APPLE__

.globl _gum_stalker_follow_me

_gum_stalker_follow_me:
#else
.globl gum_stalker_follow_me

.type gum_stalker_follow_me, %function

gum_stalker_follow_me:
#endif
stp x29, x30, [sp, -16]!

mov x29, sp

mov x3, x30

#ifdef __APPLE__

bl __gum_stalker_do_follow_me

#else
bl _gum_stalker_do_follow_me

#endif
ldp x29, x30, [sp], 16

br x0

-》

内部原理

LR=Link Register=X30=链接寄存器

AArch64架构中，根据LR去决定从哪里开始跟踪

当遇到BR，BLR等跳转指令时，会去设置LR

LR被设置为，当前函数返回后，继续运行的地址

由于只有一个LR，如果被调用函数调用了其他函数，此时LR的值就会被保存起来，比如保存到Stack栈上，后续当RET指令执行之前，会重新把LR从Stack栈中加载到寄存器中，最终返回到调用者

FP=Frame Pointer=X29=帧指针

FP始终指向Stack top栈的顶部，表示当前函数被调用时的栈的位置

所以就可以通过固定的偏移量去访问到，所有通过Stack栈传入的参数和基于栈的局部变量

且每个函数都有自己的FP，所以需要调用新函数时，保存之前的FP，返回之前函数时，恢复FP。

在刚进入新函数后，备份FP后，就可以去设置：mov x29, sp，把SP给X29=FP了。

保持了原先传入x0-x2的3个参数，额外加上x3=x30=LR，所以再去调用函数，就对应上参数了：

gpointer_gum_stalker_do_follow_me (GumStalker * self, GumStalkerTransformer * transformer, GumEventSink * sink, gpointer ret_addr)

gum_stalker_follow的内部原理

和gum_stalker_follow_me()类似，但有额外参数：thread_id

void
gum_stalker_follow (GumStalker * self,
                    GumThreadId thread_id,
                    GumStalkerTransformer * transformer,
                    GumEventSink * sink)
{
  if (thread_id == gum_process_get_current_thread_id ())
  {
    gum_stalker_follow_me (self, transformer, sink);
  }
  else
  {
    GumInfectContext ctx;

    ctx.stalker = self;
    ctx.transformer = transformer;
    ctx.sink = sink;

    gum_process_modify_thread (thread_id, gum_stalker_infect, &ctx);
  }
}

其中：gum_process_modify_thread()，不属于Stalker，但属于Gum

回调callback会去修改：GumCpuContext

GumCpuContext

GumCpuContext的定义：

typedef GumArm64CpuContext GumCpuContext;

struct _GumArm64CpuContext
{
  guint64 pc;
  guint64 sp;

  guint64 x[29];
  guint64 fp;
  guint64 lr;
  guint8 q[128];
};

相关：

static void
gum_stalker_infect (GumThreadId thread_id,
                    GumCpuContext * cpu_context,
                    gpointer user_data)

gum_process_modify_thread() 内部实现

Linux/Android：ptrace

GDB也用的这个：挂载到进程上，读写寄存器

Stalker每次只处理一个代码块block

内部机制：

新申请一块内存，写入给原始代码中加了调试代码后的代码

加的指令，用于生成事件、提供其他Stalker所支持的功能。

以及根据情况去relocate重定位指令代码。

比如对于下面代码，要重定位：

ADR Address of label at a PC-relative offset.

ADR Xd, label

Xd Is the 64-bit name of the general-purpose destination register, in the range 0 to 31.

label Is the program label whose address is to be calculated. It is an offset from the address of this instruction, in the range ±1MB.

底层通过Gum的Relocator

frida-gum/gumarm64relocator.c at main · frida/frida-gum · GitHub

现在，回想一下我们说过潜行者一次工作一个块。那么我们如何检测下一个块呢？我们还记得每个块也以分支指令结尾，如果我们修改这个分支以分支回 Stalker 引擎，但确保我们存储分支打算结束的目的地，我们可以检测下一个块并在那里重定向执行。这个相同的简单过程可以一个接一个地继续。

Stalker=潜行者

现在，这个过程可能有点慢，因此我们可以应用一些优化。首先，如果我们多次执行相同的代码块（例如循环，或者可能只是一个多次调用的函数），我们不必重新检测它。我们可以重新执行相同的检测代码。出于这个原因，我们保留了一个哈希表，其中包含我们之前遇到的所有块以及我们放置块的检测副本的位置。

其次，当遇到呼叫指令时，在发出检测的呼叫后，我们随后会发出一个着陆板，我们可以返回该着陆板而无需重新进入 Stalker。Stalker使用记录真实返回地址（real_address）和此着陆垫（code_address）的GumExecFrame结构构建了一个侧堆栈。当一个函数返回时，我们发出代码，该代码将根据real_address检查侧堆栈中的返回地址，如果匹配，它可以简单地返回到code_address，而无需重新进入运行时。这个着陆板最初将包含进入 Stalker 引擎以检测下一个块的代码，但稍后可以将其反向修补以直接分支到该块。这意味着可以处理整个返回序列，而无需输入和离开 Stalker。

如果返回地址与存储的GumExecFrame real_address不匹配，或者我们在侧堆栈中的空间不足，我们只需从头开始重新构建一个新的。我们需要在应用程序代码执行时保留 LR 的值，以便应用程序不能使用它来检测 Stalker 的存在（反调试），或者如果它将其用于除简单返回之外的任何其他目的（例如，在代码部分中引用内联数据）。此外，我们希望 Stalker 能够随时取消关注，所以我们不想不得不返回我们的堆栈来更正我们在此过程中修改的 LR 值。

最后，虽然我们总是用对 Stalker 的调用来替换分支以检测下一个块，但根据 Stalker.trustThreshold 的配置，我们可能会对此类检测代码进行反向修补，以将调用替换为下一个检测块的直接分支。确定性分支（例如，目的地是固定的，分支不是有条件的）很简单，我们可以将分支替换为下一个块。但是我们也可以处理条件分支，如果我们检测两个代码块（一个是分支，一个是不是）。然后，我们可以将原始条件分支替换为一个条件分支，该条件分支将控制流定向到获取分支时遇到的块的检测版本，然后是另一个检测块的无条件分支。我们还可以部分处理目标不是静态的分支。假设我们的分支是这样的：

BR X0

这种指令在调用函数指针或类方法时很常见。虽然 X0 的值可以更改，但通常它实际上总是相同的。在这种情况下，我们可以将最终的分支指令替换为代码，该代码将 X0 的值与我们的已知函数进行比较，如果它将分支与代码的检测副本的地址匹配。然后，如果不匹配，则可以将无条件分支返回到 Stalker 引擎。因此，如果函数指针 say 的值发生了变化，那么代码仍然有效，无论我们最终到达哪里，我们都将重新输入 Stalker 和乐器。但是，如果如我们预期的那样它保持不变，那么我们可以完全绕过 Stalker 引擎并直接进入仪器化功能。

crifan.org，使用署名4.0国际(CC BY 4.0)协议发布 all right reserved，powered by Gitbook最后更新： 2025-06-04 12:13:41

Stalker中函数地址和指令地址匹配不上

Stalker中函数地址和指令地址匹配不上

对于之前Stalker代码

___lldb_unnamed_symbol2575$$akd

的某次调试输出日志是：

===== dynamicDebug/frida/scripts/fridaStalker_akdSymbol2575.js =====
funcRelativeStartAddr=656480, functionSize=9416, funcRelativeEndAddr=665896
moduleName=akd, moduleBaseAddress=0x10054c000
funcRealStartAddr=0x1005ec460, funcRealEndAddr=0x1005ec4609416
[iPhone::PID::13098 ]-> ----- arg0=0xfffffffffffffffe, arg1=0x16fe26838, arg2=0x16fe26838, arg3=0xfffffffffffffffe

curTid= 26635

+++ into iterator=
[0x1071dbcd8] b #0x1071dbce8
+++ into iterator=
[0x1071dbce8] str wzr, [x19, #0x90]
[0x1071dbcec] ldr x0, [x19, #0xa0]
[0x1071dbcf0] str xzr, [x19, #0xa0]
[0x1071dbcf4] cbz x0, #0x1071dbcfc
+++ into iterator=
[0x1071dbcf8] bl #0x1070dfef8
+++ into iterator=
[0x1071dbcfc] ldr x0, [x19, #0x98]
[0x1071dbd00] str xzr, [x19, #0x98]
[0x1071dbd04] cbz x0, #0x1071dbd14
...

-》看到2个函数地址不匹配：

函数实际内存起始地址：0x1005ec460

0x1005exxxx 之类的地址

Stalker中运行期间的函数地址：0x1071dbcd8

0x1071dxxxx 之类的地址

后来明白原因了：

Stalker内部的hook指令的原理就是：

把当前代码拷贝一份，加上hook代码及其他逻辑

而此处的：拷贝一份，到别处，别的一段内存地址空间，此处就是指的是：

0x1071dbcd8

0x1071dxxxx 之类的地址

所以，原始函数代码和被Stalker去hook的代码，两个地址是不同的，是可以理解的，没有出错，是正常的。

crifan.org，使用署名4.0国际(CC BY 4.0)协议发布 all right reserved，powered by Gitbook最后更新： 2025-06-04 12:13:54

16字节之前的开始那段代码无法调试

16字节之前的开始那段代码无法调试

Frida的Stalker，触发的时候，往往第一行代码，确切的说是前面一小段代码，是无法打印出来的

而能开始打印的时候，往往是代码向后偏移大概0x10=16字节之后，才能打印出来

举例

想要去hook函数：

libInFieldCollection.dylib的vsPHbdGf

IDA中，起始地址是：

__text:00000001A8A26C94             ; CollectPCRT
__text:00000001A8A26C94             ; Attributes: bp-based frame
__text:00000001A8A26C94
__text:00000001A8A26C94             ; void __fastcall vsPHbdGf(__int64, __int64)
__text:00000001A8A26C94                             EXPORT _vsPHbdGf
...
__text:00000001A8A26C94 FC 6F BA A9                 STP             X28, X27, [SP,#-0x10+var_50]!
__text:00000001A8A26C98 FA 67 01 A9                 STP             X26, X25, [SP,#0x50+var_40]
__text:00000001A8A26C9C F8 5F 02 A9                 STP             X24, X23, [SP,#0x50+var_30]
__text:00000001A8A26CA0 F6 57 03 A9                 STP             X22, X21, [SP,#0x50+var_20]
__text:00000001A8A26CA4 F4 4F 04 A9                 STP             X20, X19, [SP,#0x50+var_10]
__text:00000001A8A26CA8 FD 7B 05 A9                 STP             X29, X30, [SP,#0x50+var_s0]
__text:00000001A8A26CAC FD 43 01 91                 ADD             X29, SP, #0x50
__text:00000001A8A26CB0 FF 07 40 D1                 SUB             SP, SP, #1,LSL#12

libInFieldCollection.dylib的vsPHbdGf

中的输出是：

into hookNative:
into stalkerHookNative_vsPHbdGf:
libraryName=libInFieldCollection.dylib -> moduleBaseAddress=0x1c27fb000
origFuncPtr=0x1c280ec94
funcRelativeStartAddr=81044
functionSize=25084=0x61fc, argNum=2
Frida Stalker hook: module: baseAddress=0x1c27fb000
function: relativeStartAddr=0x13c94, size=25084=0x61fc, relativeEndAddr=0x19e90
funcRealStartAddr=0x1c280ec94, funcRealEndAddr=0x1c2814e90
curTid=null
[iPhone::mobileactivationd ]-> ============ Trigged addr: relative [0x13c94] = real [0x1c280ec94]  ============
arg[0]=0x16fa8a988
arg[1]=0x16fa8a984
curTid=21019
+++ into iterator: startAddress=0x10f3c1768, isAppCode=false
+++ into iterator: startAddress=0x10f3c1778, isAppCode=false
...
+++ into iterator: startAddress=0x1108cc030, isAppCode=false
+++ into iterator: startAddress=0x1c280eca4, isAppCode=true
current: realAddr=0x1c280eca4 -> offset: hex=0x10=16
    0x1c280eca4 <+16>: stp x20, x19, [sp, #0x40]
current: realAddr=0x1c280eca8 -> offset: hex=0x14=20
    0x1c280eca8 <+20>: stp x29, x30, [sp, #0x50]
current: realAddr=0x1c280ecac -> offset: hex=0x18=24
    0x1c280ecac <+24>: add x29, sp, #0x50
...

此时：

函数的第一行代码=函数起始地址是：0x1c280ec94

真正开始打印log日志的地址是：0x1c280eca4

已经是起始地址的偏移量：0x10=16了

原因

猜测是和Frida的Stalker的内部实现机制有关系：

好像大概意思是，从原始代码code拷贝到新的地方，再去hook和打印

使得好像无法实现最初代码的hook？？

影响和结果

无法实现，去函数最开始的几行（4行）代码去hook（比如打印输出参数时的寄存器值等等）

即：

此处开始打印hook的代码，已经是：

__text:00000001A8A26C94 FC 6F BA A9                 STP             X28, X27, [SP,#-0x10+var_50]!
__text:00000001A8A26C98 FA 67 01 A9                 STP             X26, X25, [SP,#0x50+var_40]
__text:00000001A8A26C9C F8 5F 02 A9                 STP             X24, X23, [SP,#0x50+var_30]
__text:00000001A8A26CA0 F6 57 03 A9                 STP             X22, X21, [SP,#0x50+var_20]
__text:00000001A8A26CA4 F4 4F 04 A9                 STP             X20, X19, [SP,#0x50+var_10]

中的：

__text:00000001A8A26CA4 F4 4F 04 A9                 STP             X20, X19, [SP,#0x50+var_10]

对应着输出的：

偏移量是：0x10=16的0x1c280eca4

+++ into iterator: startAddress=0x1c280eca4, isAppCode=true
current: realAddr=0x1c280eca4 -> offset: hex=0x10=16
    0x1c280eca4 <+16>: stp x20, x19, [sp, #0x40]

而要去hook前面（16字节=0x10=占用4个指令的大小）4行代码：

__text:00000001A8A26C94 FC 6F BA A9                 STP             X28, X27, [SP,#-0x10+var_50]!
__text:00000001A8A26C98 FA 67 01 A9                 STP             X26, X25, [SP,#0x50+var_40]
__text:00000001A8A26C9C F8 5F 02 A9                 STP             X24, X23, [SP,#0x50+var_30]
__text:00000001A8A26CA0 F6 57 03 A9                 STP             X22, X21, [SP,#0x50+var_20]

目前看来，就无法实现了

如何解决

暂时无解。

除非以后对Stalker机制有深入了解，看看是否有机会解决此，感觉算是Stalker的bug了。

crifan.org，使用署名4.0国际(CC BY 4.0)协议发布 all right reserved，powered by Gitbook最后更新： 2025-06-04 14:37:55

实际内存地址和Stalker输出地址不匹配不一致

实际内存地址和Stalker输出地址不匹配不一致

某次Stalker调试的log是：

===== dynamicDebug/frida/scripts/fridaStalker_akdSymbol2575.js =====
funcRelativeStartAddr=656480, functionSize=9416, funcRelativeEndAddr=665896
moduleName=akd, moduleBaseAddress=0x10054c000
funcRealStartAddr=0x1005ec460, funcRealEndAddr=0x1005ec4609416
[iPhone::PID::13098 ]-> ----- arg0=0xfffffffffffffffe, arg1=0x16fe26838, arg2=0x16fe26838, arg3=0xfffffffffffffffe

curTid= 26635

+++ into iterator=
[0x1071dbcd8] b #0x1071dbce8
+++ into iterator=
[0x1071dbce8] str wzr, [x19, #0x90]
[0x1071dbcec] ldr x0, [x19, #0xa0]
[0x1071dbcf0] str xzr, [x19, #0xa0]
[0x1071dbcf4] cbz x0, #0x1071dbcfc
+++ into iterator=
[0x1071dbcf8] bl #0x1070dfef8
+++ into iterator=
[0x1071dbcfc] ldr x0, [x19, #0x98]
[0x1071dbd00] str xzr, [x19, #0x98]
[0x1071dbd04] cbz x0, #0x1071dbd14
...

其中指令地址看起来不匹配=不一致：

指令地址：0x1071dbcd8

函数二进制内偏移量：0xa0460

此处akd模块基地址：0x10054c000

所以函数的实际真实起始地址：0x1005ec460

后来才明白是：

Frida的Stalker中，看到2个函数地址不匹配：

函数实际内存起始地址：0x1005ec460

0x1005exxxx 之类的地址

Stalker中运行期间的函数地址：0x1071dbcd8

0x1071dxxxx 之类的地址

的原因：

Stalker内部的hook指令的原理就是：把当前代码拷贝一份，加上hook代码及其他逻辑

而此处的：拷贝一份，到别处，别的一段内存地址空间，此处就是指的是：

0x1071dbcd8

0x1071dxxxx 之类的地址

所以，原始函数代码和被Stalker去hook的代码，两个地址是不同的，是可以理解的。

crifan.org，使用署名4.0国际(CC BY 4.0)协议发布 all right reserved，powered by Gitbook最后更新： 2025-08-22 21:45:24

Stalker中去判断是否是函数的代码指令的逻辑

Stalker中去判断是否是函数的代码指令的逻辑

需求：Frida的Stalker调试期间，想要知道当前所执行的代码，是否属于：真正的要hook的函数的真实代码

解决办法

经过调试用如下代码：

console.log("===== Frida Stalker hook for arm64 ___lldb_unnamed_symbol2575$$akd =====");
// arm64 akd: ___lldb_unnamed_symbol2575$$akd
// var funcRelativeStartAddr = 0x1000a0460;
var funcRelativeStartAddr = 0xa0460;
var functionSize = 0x24C8; // 9416 == 0x24C8
var funcRelativeEndAddr = funcRelativeStartAddr + functionSize;
console.log("funcRelativeStartAddr=" + funcRelativeStartAddr + ", functionSize=" + functionSize + ", funcRelativeEndAddr=" + funcRelativeEndAddr);
const moduleName = "akd";
const moduleBaseAddress = Module.findBaseAddress(moduleName);
console.log("moduleName=" + moduleName + ", moduleBaseAddress=" + moduleBaseAddress);
// console.log("moduleName=%s, moduleBaseAddress=%p", moduleName, moduleBaseAddress);
const funcRealStartAddr = moduleBaseAddress.add(funcRelativeStartAddr);
// var funcRealEndAddr = funcRealStartAddr + functionSize;
const funcRealEndAddr = funcRealStartAddr.add(functionSize);
console.log("funcRealStartAddr=" + funcRealStartAddr + ", funcRealEndAddr=" + funcRealEndAddr);
var curTid = null;
Interceptor.attach(funcRealStartAddr, {
    onEnter: function(args) {
        var arg0 = args[0]
        var arg1 = args[1]
        var arg2 = args[2]
        var arg3 = args[3]
        console.log("----- arg0=" + arg0 + ", arg1=" + arg1 + ", arg2=" + arg2 + ", arg3=" + arg3);
        var curTid = Process.getCurrentThreadId();
        console.log("curTid=", curTid);
        Stalker.follow(curTid, {
            events: {
                call: true, // CALL instructions: yes please
                ret: false, // RET instructions
                exec: false, // all instructions: not recommended as it's
                block: false, // block executed: coarse execution trace
                compile: false // block compiled: useful for coverage
            },
            // transform: (iterator: StalkerArm64Iterator) => {
            transform: function (iterator) {
                var instruction = iterator.next();
                const startAddress = instruction.address;
                console.log("+++ into iterator: startAddress=" + startAddress);
                // const isAppCode = startAddress.compare(funcRealStartAddr) >= 0 && startAddress.compare(funcRealEndAddr) === -1;
                // const isAppCode = (startAddress.compare(funcRealStartAddr) >= 0) && (startAddress.compare(funcRealEndAddr) < 0);
                const gt_realStartAddr = startAddress.compare(funcRealStartAddr) >= 0
                const lt_realEndAddr = startAddress.compare(funcRealEndAddr) < 0
                const isAppCode = gt_realStartAddr && lt_realEndAddr
                console.log("isAppCode=" + isAppCode + ", gt_realStartAddr=" + gt_realStartAddr + ", lt_realEndAddr=" + lt_realEndAddr);
                do {
                    if (isAppCode) {
                        var curRealAddr = instruction.address;
                        var curOffset = curRealAddr.sub(funcRealStartAddr)
                        var curOffsetInt = curOffset.toInt32()
                        var instructionStr = instruction.toString()
                        console.log("\t" + curRealAddr + " <+" + curOffsetInt + ">: " + instructionStr);
                    }
                    iterator.keep();
                } while ((instruction = iterator.next()) !== null);
             }
        })
    },
    onLeave: function(retval) {
        console.log("retval:", new ObjC.Object(retval))
        if (curTid != null) {
            Stalker.unfollow(curTid);
            console.log("Stalker.unfollow curTid=", curTid)
        }
    }
});

可以输出：

===== Frida Stalker hook for arm64 ___lldb_unnamed_symbol2575$$akd =====
funcRelativeStartAddr=656480, functionSize=9416, funcRelativeEndAddr=665896
moduleName=akd, moduleBaseAddress=0x10237c000
funcRealStartAddr=0x10241c460, funcRealEndAddr=0x10241e928
[iPhone::akd ]-> ----- arg0=0xfffffffffffffffe, arg1=0x16dcae838, arg2=0x16dcae838, arg3=0xfffffffffffffffe
curTid= 15635
+++ into iterator: startAddress=0x1089dbcd8
isAppCode=false, gt_realStartAddr=true, lt_realEndAddr=false
+++ into iterator: startAddress=0x1089dbce8
...
isAppCode=true, gt_realStartAddr=true, lt_realEndAddr=true, arg3=0xfffffffffffffffe
    0x10241c470 <+16>: stp x22, x21, [sp, #0xc0]
    0x10241c474 <+20>: stp x20, x19, [sp, #0xd0]
    0x10241c478 <+24>: stp x29, x30, [sp, #0xe0]
    0x10241c47c <+28>: add x29, sp, #0xe0
...

算是实现了，通过计算，最后用isAppCode这个变量去判断是否是当前代码

上述代码的所属的完整的示例代码，详见：

___lldb_unnamed_symbol2575$$akd

crifan.org，使用署名4.0国际(CC BY 4.0)协议发布 all right reserved，powered by Gitbook最后更新： 2025-08-22 21:47:50

Stalker中优化hook到指令时的log显示

Stalker中优化hook到指令时的log显示格式

需求：Frida的Stalker中，希望输出的log日志 -》 尽量模拟之前Xcode的汇编代码的形式

核心代码：

  var curRealAddr = instruction.address;
  var curOffsetHexPtr = curRealAddr.sub(funcRealStartAddr)
  var curOffsetInt = curOffsetHexPtr.toInt32()
  var instructionStr = instruction.toString()
  console.log("\t" + curRealAddr + " <+" + curOffsetInt + ">: " + instructionStr);

输出效果

+++ into iterator: startAddress=0x104b48470
  0x104b48470 <+16>: stp x22, x21, [sp, #0xc0]
  0x104b48474 <+20>: stp x20, x19, [sp, #0xd0]
  0x104b48478 <+24>: stp x29, x30, [sp, #0xe0]
  0x104b4847c <+28>: add x29, sp, #0xe0
  0x104b48480 <+32>: nop
  0x104b48484 <+36>: ldr x8, #0x104b9c7d8

注：完整代码和输出，详见：

___lldb_unnamed_symbol2575$$akd

crifan.org，使用署名4.0国际(CC BY 4.0)协议发布 all right reserved，powered by Gitbook最后更新： 2025-08-22 21:50:52

putCallout中传递有名的独立函数会导致崩溃

putCallout中传递有名的独立函数会导致崩溃

问题概述

给putCallout传递函数：

传递有名的独立的函数：会导致崩溃

传递匿名的函数：就可以正常运行

详解

Frida的Stalker的transform中去写putCallout代码

注

完整代码详见：

___lldb_unnamed_symbol2575$$akd

如果把putCallout写成是传入一个独立的js函数：

transform: function (iterator) {
...
    if (curOffsetInt == 8516) {
        iterator.putCallout(needDebug);
    }
}

...
      function needDebug (context) {
          console.log("into needDebug: context=" + context);
          ...
      }

->就会导致此处出现崩溃：

。。。
Process terminated

Thank you for using Frida!
Fatal Python error: _enter_buffered_busy: could not acquire lock for <_io.BufferedReader name='<stdin>'> at interpreter shutdown, possibly due to daemon threads
Python runtime state: finalizing (tstate=0x000000010308e0c8)

Current thread 0x00000001f4ab4140 (most recent call first):
  <no Python frame>

而如果改为：js匿名名函数

transform: function (iterator) {
...
    if (curOffsetInt == 8516) {
        // iterator.putCallout(needDebug);
        iterator.putCallout((context) => {
            console.log("into needDebug: context=" + context);
        });
    }
}

就不会崩溃

很是诡异。暂时不清楚具体原因。

心得：Frida中对于js的支持，还是不够完善

容易遇到一些诡异的bug

crifan.org，使用署名4.0国际(CC BY 4.0)协议发布 all right reserved，powered by Gitbook最后更新： 2025-08-22 21:57:18

Stalker.exclude

Stalker.exclude

此处介绍Stalker.exclude的使用心得。

crifan.org，使用署名4.0国际(CC BY 4.0)协议发布 all right reserved，powered by Gitbook最后更新： 2025-06-04 12:15:20

用Stalker.exclude提高效率和减少干扰

用Stalker.exclude提高效率和减少干扰

现象

libInFieldCollection.dylib的vsPHbdGf

中的Frida的Stalker的核心部分代码：

function stalkerHookNative_vsPHbdGf(){
  console.log("into stalkerHookNative_vsPHbdGf:")

  var libraryName = "libInFieldCollection.dylib"
  const moduleBaseAddress = Module.findBaseAddress(libraryName)
  console.log("libraryName=" + libraryName + " -> moduleBaseAddress=" + moduleBaseAddress)
  if (null == moduleBaseAddress) {
    console.error("Failed to find library " + libraryName)
    return
  }

  var origFuncPtr = Module.findExportByName(libraryName, "vsPHbdGf")
  console.log("origFuncPtr=" + origFuncPtr)

  var funcRelativeStartAddr = origFuncPtr - moduleBaseAddress
  console.log("funcRelativeStartAddr=" + funcRelativeStartAddr)

  var functionSize = 0x61FC

  // CollectPCRT == void __fastcall vsPHbdGf(__int64 a1, __int64 a2)
  var argNum = 2
  console.log("functionSize=" + functionSize + "=" + JsUtil.intToHexStr(functionSize) + ", argNum=" + argNum)

    Stalker.exclude(module_system)
  }

  let hookFuncMap = {
    0x164: // +356
      function (context) {
        var contextStr = JSON.stringify(context)
        console.log("[0x164] contextStr=" + contextStr)
        var x10 = context.x10
        console.log("[0x164] x10=" + x10)
      },
    0x1DC: // +476
      function (context) {
        var contextStr = JSON.stringify(context)
        console.log("[0x1DC] contextStr=" + contextStr)
        var x10 = context.x10
        console.log("[0x1DC] x10=" + x10)
      },
  }

  FridaUtil.stalkerHookUnnameNative(moduleBaseAddress, funcRelativeStartAddr, functionSize, argNum, hookFuncMap)
}

function hookNative(){
  console.log("into hookNative:")
  stalkerHookNative_vsPHbdGf()
}

hookNative()

和对应的：

FridaUtil的stalkerHookUnnameNative

  // Frida Stalker hoo unknown name native function
  static stalkerHookUnnameNative(moduleBaseAddress, funcRelativeStartAddr, functionSize, argNum, hookFuncMap){
    console.log("Frida Stalker hook: module: baseAddress=" + moduleBaseAddress)

    var functionSizeHexStr = JsUtil.intToHexStr(functionSize)
    var funcRelativeStartAddrHexStr = JsUtil.intToHexStr(funcRelativeStartAddr)
    var funcRelativeEndAddr = funcRelativeStartAddr + functionSize
    var funcRelativeEndAddrHexStr = JsUtil.intToHexStr(funcRelativeEndAddr)
    console.log("function: relativeStartAddr=" + funcRelativeStartAddrHexStr + ", size=" + functionSize + "=" + functionSizeHexStr + ", relativeEndAddr=" + funcRelativeEndAddrHexStr)

    const funcRealStartAddr = moduleBaseAddress.add(funcRelativeStartAddr)
    // var funcRealEndAddr = funcRealStartAddr + functionSize
    const funcRealEndAddr = funcRealStartAddr.add(functionSize)
    console.log("funcRealStartAddr=" + funcRealStartAddr + ", funcRealEndAddr=" + funcRealEndAddr)
    var curTid = null
    console.log("curTid=" + curTid)
    Interceptor.attach(funcRealStartAddr, {
      onEnter: function(args) {
        JsUtil.logStr("Trigged addr: relative [" + funcRelativeStartAddrHexStr + "] = real [" + funcRealStartAddr + "]")

        for(var i = 0; i < argNum; i++) {
          var curArg = args[i]
          console.log("arg[" + i  + "]=" + curArg)
        }

        var curTid = Process.getCurrentThreadId()
        console.log("curTid=" + curTid)
        Stalker.follow(curTid, {
            events: {
              call: false, // CALL instructions: yes please
              ret: true, // RET instructions
              exec: false, // all instructions: not recommended as it's
              block: false, // block executed: coarse execution trace
              compile: false // block compiled: useful for coverage
            },
            // onReceive: Called with `events` containing a binary blob comprised of one or more GumEvent structs. See `gumevent.h` for details about the format. Use `Stalker.parse()` to examine the data.
            onReceive(events) {
              var parsedEvents = Stalker.parse(events)
              // var parsedEventsStr = JSON.stringify(parsedEventsStr)
              // console.log(">>> into onReceive: parsedEvents=" + parsedEvents + ", parsedEventsStr=" + parsedEventsStr);
              console.log(">>> into onReceive: parsedEvents=" + parsedEvents);
            },

            // transform: (iterator: StalkerArm64Iterator) => {
            transform: function (iterator) {
              // https://www.radare.org/doc/frida/interfaces/StalkerArmIterator.html

              // console.log("iterator=" + iterator)
              var instruction = iterator.next()
              const startAddress = instruction.address
              // console.log("+++ into iterator: startAddress=" + startAddress)
              // const isAppCode = startAddress.compare(funcRealStartAddr) >= 0 && startAddress.compare(funcRealEndAddr) === -1
              // const isAppCode = (startAddress.compare(funcRealStartAddr) >= 0) && (startAddress.compare(funcRealEndAddr) < 0)
              const gt_realStartAddr = startAddress.compare(funcRealStartAddr) >= 0
              const lt_realEndAddr = startAddress.compare(funcRealEndAddr) < 0
              var isAppCode = gt_realStartAddr && lt_realEndAddr
              console.log("+++ into iterator: startAddress=" + startAddress + ", isAppCode=" + isAppCode)

              // // for debug
              // isAppCode = true

              // console.log("isAppCode=" + isAppCode + ", gt_realStartAddr=" + gt_realStartAddr + ", lt_realEndAddr=" + lt_realEndAddr)
              do {
                if (isAppCode) {
                  // is origal function code = which we focus on

                  // console.log("instruction: address=" + instruction.address
                  //     + ",next=" + instruction.next()
                  //     + ",size=" + instruction.size
                  //     + ",mnemonic=" + instruction.mnemonic
                  //     + ",opStr=" + instruction.opStr
                  //     + ",operands=" + JSON.stringify(instruction.operands)
                  //     + ",regsAccessed=" + JSON.stringify(instruction.regsAccessed)
                  //     + ",regsRead=" + JSON.stringify(instruction.regsRead)
                  //     + ",regsWritten=" + JSON.stringify(instruction.regsWritten)
                  //     + ",groups=" + JSON.stringify(instruction.groups)
                  //     + ",toString()=" + instruction.toString()
                  //     + ",toJSON()=" + instruction.toJSON()
                  // );

                  var curRealAddr = instruction.address
                  // console.log("curRealAddr=" + curRealAddr)
                  // const isAppCode = curRealAddr.compare(funcRealStartAddr) >= 0 && curRealAddr.compare(funcRealEndAddr) === -1
                  // console.log(curRealAddr + ": isAppCode=" + isAppCode)
                  var curOffsetHexPtr = curRealAddr.sub(funcRealStartAddr)
                  var curOffsetInt = curOffsetHexPtr.toInt32()
                  console.log("current: realAddr=" + curRealAddr + " -> offset: hex=" + curOffsetHexPtr + "=" + curOffsetInt)

                  // var instructionStr = instruction.mnemonic + " " + instruction.opStr
                  var instructionStr = instruction.toString()
                  // console.log("\t" + curRealAddr + ": " + instructionStr);
                  // console.log("\t" + curRealAddr + " <+" + curOffsetHexPtr + ">: " + instructionStr)
                  console.log("\t" + curRealAddr + " <+" + curOffsetInt + ">: " + instructionStr)

                  if (curOffsetInt in hookFuncMap){
                    console.log("offset: " + curOffsetHexPtr + "=" + curOffsetInt)
                    // let curHookFunc = hookFuncMap.get(curOffsetInt)
                    var curHookFunc = hookFuncMap[curOffsetInt]
                    // console.log("curOffsetInt=" + curOffsetInt + " -> curHookFunc=" + curHookFunc)

                    // putCallout -> https://www.radare.org/doc/frida/interfaces/StalkerArmIterator.html#putCallout
                    // StalkerScriptCallout -> https://www.radare.org/doc/frida/types/StalkerScriptCallout.html
                    // CpuContext -> https://www.radare.org/doc/frida/types/CpuContext.html
                    // Arm64CpuContext -> https://www.radare.org/doc/frida/interfaces/Arm64CpuContext.html

                    // work: normal
                    iterator.putCallout(curHookFunc)

                    // var extraDataDict = {
                    //   "curOffsetInt": curOffsetInt
                    // }
                    // Not work: abnormal
                    // iterator.putCallout((context) => {
                    // // iterator.putCallout((context, extraDataDict) => {
                    //   // console.log("match offset: " + curOffsetHexPtr + ", curRealAddr=" + curRealAddr)
                    //   // curHookFunc(context, curOffsetInt, moduleBaseAddress)
                    //   // context.curOffsetInt = curOffsetInt
                    //   // context.curOffsetHexPtr = curOffsetHexPtr
                    //   // context.moduleBaseAddress = moduleBaseAddress
                    //   // context[curOffsetInt] = curOffsetInt
                    //   // context[curOffsetHexPtr] = curOffsetHexPtr
                    //   // context[moduleBaseAddress] = moduleBaseAddress
                    //   // curHookFunc(context, extraDataDict)
                    //   curHookFunc(context)
                    // })
                  }

                }
                iterator.keep()
              } while ((instruction = iterator.next()) !== null)
            }
        });

        // function needDebug(context) {
        //     console.log("into needDebug")
        //     // console.log("into needDebug: context=" + context)
        //     // var contextStr = JSON.stringify(context, null, 2)
        //     // console.log("context=" + contextStr)
        //     // var x9Value1 = context.x9
        //     // var x9Value2 = context["x9"]
        //     // console.log("x9Value1=" + x9Value1 + ", x9Value2=" + x9Value2)
        // }
      },
      onLeave: function(retval) {
        console.log("addr: relative [" + funcRelativeStartAddrHexStr + "] real [" + funcRealStartAddr + "] -> retval=" + retval)
        if (curTid != null) {
          Stalker.unfollow(curTid)
          console.log("Stalker.unfollow curTid=", curTid)
        }
      }
    })
  }

注：其最新代码详见：FridaUtil.js

但是hook不到，该函数vsPHbdGf的全部代码

具体现象就是： vsPHbdGf函数代码很多，但是Stalker输出的代码执行逻辑，最后，最多，只到：

frida/frida_stalker/logs/fridaStalker_vsPHbdGf_20241208_BR2nd.log

[iPhone::mobileactivationd ]-> %reload
into hookNative:
into stalkerHookNative_vsPHbdGf:
libraryName=libInFieldCollection.dylib -> moduleBaseAddress=0x1c27fb000
origFuncPtr=0x1c280ec94
funcRelativeStartAddr=81044
functionSize=25084=0x61fc, argNum=2
Frida Stalker hook: module: baseAddress=0x1c27fb000
function: relativeStartAddr=0x13c94, size=25084=0x61fc, relativeEndAddr=0x19e90
funcRealStartAddr=0x1c280ec94, funcRealEndAddr=0x1c2814e90
curTid=null
[iPhone::mobileactivationd ]-> ============ Trigged addr: relative [0x13c94] = real [0x1c280ec94]  ============
arg[0]=0x16fa8a988
arg[1]=0x16fa8a984
curTid=21019
+++ into iterator: startAddress=0x10f3c1768, isAppCode=false
+++ into iterator: startAddress=0x10f3c1778, isAppCode=false
...
+++ into iterator: startAddress=0x1c280eca4, isAppCode=true
current: realAddr=0x1c280eca4 -> offset: hex=0x10=16
    0x1c280eca4 <+16>: stp x20, x19, [sp, #0x40]
...
current: realAddr=0x1c2813d74 -> offset: hex=0x50e0=20704
    0x1c2813d74 <+20704>: bl #0x1c2842e9c
+++ into iterator: startAddress=0x1c2842e9c, isAppCode=false
+++ into iterator: startAddress=0x19a8914c0, isAppCode=false
...
+++ into iterator: startAddress=0x19a8914f0, isAppCode=false
+++ into iterator: startAddress=0x1c2813d78, isAppCode=true
current: realAddr=0x1c2813d78 -> offset: hex=0x50e4=20708
    0x1c2813d78 <+20708>: str x0, [sp, #0xc8]
current: realAddr=0x1c2813d7c -> offset: hex=0x50e8=20712
    0x1c2813d7c <+20712>: bl #0x1c2842d88
+++ into iterator: startAddress=0x1c2842d88, isAppCode=false
+++ into iterator: startAddress=0x19a77145c, isAppCode=false
+++ into iterator: startAddress=0x19a8bfd74, isAppCode=false
...

对应着IDA中的D7C结尾的位置：

后续的，之后的代码，就看不到运行了。

原因

基本上确定就是：

由于（Stalker）去hook的内容太多，导致出现异常，即没有hook到后续代码的运行

解决办法

用Stalker.exclude排除掉其他的、无需关心的代码

具体步骤

先找到，要排除掉的代码的范围

核心思路是：从你的函数中，真实额外调用了第三方（尤其是系统库中的函数），去寻找要排除掉的范围

举例

此处iOS的程序，且调试期间的确看到了后续代码会调用到malloc、arc4random等函数

其中，好像是，这些函数就是属于 ObjC或System相关的库中？

且此处的函数vsPHbdGf所属的库libInFieldCollection.dylib，所依赖的外部库，即import的库

libInFieldCollection_dylib/staticAnalysis/exportedStrResInfo/libInFieldCollection_rabin2_l_libraries.coffee

/System/Library/Frameworks/IOKit.framework/Versions/A/IOKit

/System/Library/Frameworks/Foundation.framework/Foundation

/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation

/usr/lib/libMobileGestalt.dylib

/usr/lib/libobjc.A.dylib

/usr/lib/libSystem.B.dylib

其中就有

iOS的常见的底层通用的库

/usr/lib/libobjc.A.dylib

/usr/lib/libSystem.B.dylib

所以，基本上可以确定就是：

此处后续要排除的范围，就是：libobjc.A.dylib、libSystem.B.dylib等系统基础的底层的库

再去用Stalker.exclude排除掉（整个库）

然后再去代码中加上：

  // try exclude not-concern functions inside common libs

  // var moduleName_libObjc = "/usr/lib/libobjc.A.dylib"
  var moduleName_libObjc = "libobjc.A.dylib"
  // FridaUtil.printModuleInfo(moduleName_libObjc)
  var module_libObjc = Process.getModuleByName(moduleName_libObjc)
  console.log("module_libObjc=" + module_libObjc)
  if (null != module_libObjc) {
    FridaUtil.printModuleBasicInfo(module_libObjc)

    Stalker.exclude(module_libObjc)
  }

  // var moduleName_system = "/usr/lib/libSystem.B.dylib"
  var moduleName_system = "libSystem.B.dylib"
  // FridaUtil.printModuleInfo(moduleName_system)
  var module_system = Process.getModuleByName(moduleName_system)
  console.log("module_system=" + module_system)
  if (null != module_system) {
    FridaUtil.printModuleBasicInfo(module_system)

    Stalker.exclude(module_system)
  }

最新代码是：

function stalkerHookNative_vsPHbdGf(){
  console.log("into stalkerHookNative_vsPHbdGf:")

  var libraryName = "libInFieldCollection.dylib"
  const moduleBaseAddress = Module.findBaseAddress(libraryName)
  console.log("libraryName=" + libraryName + " -> moduleBaseAddress=" + moduleBaseAddress)
  if (null == moduleBaseAddress) {
    console.error("Failed to find library " + libraryName)
    return
  }

  var origFuncPtr = Module.findExportByName(libraryName, "vsPHbdGf")
  console.log("origFuncPtr=" + origFuncPtr)

  var funcRelativeStartAddr = origFuncPtr - moduleBaseAddress
  console.log("funcRelativeStartAddr=" + funcRelativeStartAddr)
  // for debug
  /*
    [iPhone::mobileactivationd ]-> ============ Trigged addr: relative [0x13c94] = real [0x1c280ec94]  ============
    ...
    +++ into iterator: startAddress=0x1c2813d78, isAppCode=true
    current: realAddr=0x1c2813d78 -> offset: hex=0x50e4=20708
        0x1c2813d78 <+20708>: str x0, [sp, #0xc8]
    current: realAddr=0x1c2813d7c -> offset: hex=0x50e8=20712
        0x1c2813d7c <+20712>: bl #0x1c2842d88
  */
  // // use later address as start address, try to avoid only hook part code == not hook all code
  // funcRelativeStartAddr = funcRelativeStartAddr + 0x50e4

  var functionSize = 0x61FC
  // for debug: make larger, tyr to support hook more code
  // var functionSize = 0x10000

  // CollectPCRT == void __fastcall vsPHbdGf(__int64 a1, __int64 a2)
  var argNum = 2
  console.log("functionSize=" + functionSize + "=" + JsUtil.intToHexStr(functionSize) + ", argNum=" + argNum)

  // try exclude not-concern functions inside common libs

  // var moduleName_libObjc = "/usr/lib/libobjc.A.dylib"
  var moduleName_libObjc = "libobjc.A.dylib"
  // FridaUtil.printModuleInfo(moduleName_libObjc)
  var module_libObjc = Process.getModuleByName(moduleName_libObjc)
  console.log("module_libObjc=" + module_libObjc)
  if (null != module_libObjc) {
    FridaUtil.printModuleBasicInfo(module_libObjc)

    Stalker.exclude(module_libObjc)
  }

  // var moduleName_system = "/usr/lib/libSystem.B.dylib"
  var moduleName_system = "libSystem.B.dylib"
  // FridaUtil.printModuleInfo(moduleName_system)
  var module_system = Process.getModuleByName(moduleName_system)
  console.log("module_system=" + module_system)
  if (null != module_system) {
    FridaUtil.printModuleBasicInfo(module_system)

    Stalker.exclude(module_system)
  }

  let hookFuncMap = {
    0x164: // +356
      function (context) {
        var contextStr = JSON.stringify(context)
        console.log("[0x164] contextStr=" + contextStr)
        var x10 = context.x10
        console.log("[0x164] x10=" + x10)
      },
    0x1DC: // +476
      function (context) {
        var contextStr = JSON.stringify(context)
        console.log("[0x1DC] contextStr=" + contextStr)
        var x10 = context.x10
        console.log("[0x1DC] x10=" + x10)
      },
  }

  FridaUtil.stalkerHookUnnameNative(moduleBaseAddress, funcRelativeStartAddr, functionSize, argNum, hookFuncMap)
}

function hookNative(){
  console.log("into hookNative:")
  stalkerHookNative_vsPHbdGf()
}

hookNative()

最开始的输出中，关于库的输出是：

module_libObjc=[object Object]
Module: name=libobjc.A.dylib, base=0x199e82000, size7897088, path=/usr/lib/libobjc.A.dylib
module_system=[object Object]
Module: name=libSystem.B.dylib, base=0x199e17000, size8192, path=/usr/lib/libSystem.B.dylib
Frida Stalker hook: module: baseAddress=0x1c27fb000

最终结果是：

即可顺利hook出后续代码

（d7c结尾的）+20712的后续代码

从（d80结尾的）+20716开始的后续的代码

的执行了：

frida/frida_stalker/logs/fridaStalker_vsPHbdGf_20241209_exclude.log.log

...
+++ into iterator: startAddress=0x19a77151c, isAppCode=false
+++ into iterator: startAddress=0x1c2813d80, isAppCode=true
current: realAddr=0x1c2813d80 -> offset: hex=0x50ec=20716
    0x1c2813d80 <+20716>: mov w5, #0x87f
current: realAddr=0x1c2813d84 -> offset: hex=0x50f0=20720
    0x1c2813d84 <+20720>: movk w5, #0xa711, lsl #16
current: realAddr=0x1c2813d88 -> offset: hex=0x50f4=20724
    0x1c2813d88 <+20724>: mov x8, #0

心得

刚开始以为是Frida的Stalker的bug呢，导致函数的后续代码没触发

后来也看到了，官网有提到：

Stalker | Frida • A world-class dynamic instrumentation toolkit

Excluded Ranges

Stalker also has the API Stalker.exclude(range) that’s passed a base and limit used to prevent Stalker from instrumenting code within these regions. Consider, for example, your thread calls malloc() inside libc. You most likely don’t care about the inner workings of the heap and this is not only going to slow down performance, but also generate a whole lot of extraneous events you don’t care about. One thing to consider, however, is that as soon as a call is made to an excluded range, stalking of that thread is stopped until it returns. That means, if that thread were to call a function which is not inside a restricted range, a callback perhaps, then this would not be captured by Stalker. Just as this can be used to stop the stalking of a whole library, it can be used to stop stalking a given function (and its callees) too. This can be particularly useful if your target application is statically linked. Here, was cannot simply ignore all calls to libc, but we can find the symbol for malloc() using Module.enumerateSymbols() and ignore that single function.

以及找到了对应的API接口描述

JavaScript API | Frida • A world-class dynamic instrumentation toolkit

Stalker

Stalker.exclude(range): marks the specified memory range as excluded, which is an object with base and size properties – like the properties in an object returned by e.g. Process.getModuleByName().

This means Stalker will not follow execution when encountering a call to an instruction in such a range. You will thus be able to observe/modify the arguments going in, and the return value coming back, but won’t see the instructions that happened between.

Useful to improve performance and reduce noise.

其中最后一行明显是：

可以用来：提高性能和降低噪音。

-》但是差点，仍旧怀疑是Stalker的bug，而没去尝试Stalker.exclude，差点错过了这个Stalker.exclude

-》实践证明：Stalker.exclude是可以解决此问题的

最后的心得，就是：

以后遇到这类，觉得有一点希望的思路，只要时间允许，还是尽量也去试试

且同时也是增加技术能力的，此处即新学习了个Stalker.exclude的用法

crifan.org，使用署名4.0国际(CC BY 4.0)协议发布 all right reserved，powered by Gitbook最后更新： 2025-06-04 14:37:15

Stalker工具类函数

Stalker工具类函数

此处整理，Frida的Stalker期间，整理出的，工具类函数。

crifan.org，使用署名4.0国际(CC BY 4.0)协议发布 all right reserved，powered by Gitbook最后更新： 2025-06-04 11:06:49

stalkerHookUnnameNative

stalkerHookUnnameNative

函数：stalkerHookUnnameNative

作用：实现Frida的Stalker去hook某个位置的代码的通用逻辑

（调用）举例

libmetasec_ml.so的ms_bd_c_l_a

FridaUtil.stalkerHookUnnameNative(moduleBaseAddress, funcRelativeStartAddr, functionSize, argNum, hookFuncMap)

最新代码

详见：FridaUtil.js

stalkerHookUnnameNative的代码

  // Frida Stalker hoo unknown name native function
  static stalkerHookUnnameNative(moduleBaseAddress, funcRelativeStartAddr, functionSize, argNum, hookFuncMap){
    console.log("Frida Stalker hook: module: baseAddress=" + moduleBaseAddress + ", isShowOpcode=" + FridaUtil.isShowOpcode)

    var functionSizeHexStr = JsUtil.intToHexStr(functionSize)
    var funcRelativeStartAddrHexStr = JsUtil.intToHexStr(funcRelativeStartAddr)
    var funcRelativeEndAddr = funcRelativeStartAddr + functionSize
    var funcRelativeEndAddrHexStr = JsUtil.intToHexStr(funcRelativeEndAddr)
    console.log("function: relativeStartAddr=" + funcRelativeStartAddrHexStr + ", size=" + functionSize + "=" + functionSizeHexStr + ", relativeEndAddr=" + funcRelativeEndAddrHexStr)

    const funcRealStartAddr = moduleBaseAddress.add(funcRelativeStartAddr)
    // var funcRealEndAddr = funcRealStartAddr + functionSize
    const funcRealEndAddr = funcRealStartAddr.add(functionSize)
    console.log("funcRealStartAddr=" + funcRealStartAddr + ", funcRealEndAddr=" + funcRealEndAddr)
    var curTid = null
    console.log("curTid=" + curTid)
    Interceptor.attach(funcRealStartAddr, {
      onEnter: function(args) {
        JsUtil.logStr("Trigged addr: relative [" + funcRelativeStartAddrHexStr + "] = real [" + funcRealStartAddr + "]")

        for(var i = 0; i < argNum; i++) {
          var curArg = args[i]
          console.log("arg[" + i  + "]=" + curArg)
        }

        var curTid = Process.getCurrentThreadId()
        console.log("curTid=" + curTid)
        Stalker.follow(curTid, {
            events: {
              call: false, // CALL instructions: yes please
              ret: true, // RET instructions
              exec: false, // all instructions: not recommended as it's
              block: false, // block executed: coarse execution trace
              compile: false // block compiled: useful for coverage
            },
            // onReceive: Called with `events` containing a binary blob comprised of one or more GumEvent structs. See `gumevent.h` for details about the format. Use `Stalker.parse()` to examine the data.
            onReceive(events) {
              var parsedEvents = Stalker.parse(events)
              // var parsedEventsStr = JSON.stringify(parsedEventsStr)
              // console.log(">>> into onReceive: parsedEvents=" + parsedEvents + ", parsedEventsStr=" + parsedEventsStr);
              console.log(">>> into onReceive: parsedEvents=" + parsedEvents);
            },

            // transform: (iterator: StalkerArm64Iterator) => {
            transform: function (iterator) {
              // https://www.radare.org/doc/frida/interfaces/StalkerArmIterator.html

              // console.log("iterator=" + iterator)
              var instruction = iterator.next()
              const startAddress = instruction.address
              // console.log("+++ into iterator: startAddress=" + startAddress)
              // const isAppCode = startAddress.compare(funcRealStartAddr) >= 0 && startAddress.compare(funcRealEndAddr) === -1
              // const isAppCode = (startAddress.compare(funcRealStartAddr) >= 0) && (startAddress.compare(funcRealEndAddr) < 0)
              const gt_realStartAddr = startAddress.compare(funcRealStartAddr) >= 0
              const lt_realEndAddr = startAddress.compare(funcRealEndAddr) < 0
              var isAppCode = gt_realStartAddr && lt_realEndAddr
              console.log("+++ into iterator: startAddress=" + startAddress + ", isAppCode=" + isAppCode)

              // // for debug
              // isAppCode = true

              // console.log("isAppCode=" + isAppCode + ", gt_realStartAddr=" + gt_realStartAddr + ", lt_realEndAddr=" + lt_realEndAddr)
              do {
                if (isAppCode) {
                  // is origal function code = which we focus on
                  // FridaUtil.printInstructionInfo(instruction)

                  var curRealAddr = instruction.address
                  // console.log("curRealAddr=" + curRealAddr)
                  // const isAppCode = curRealAddr.compare(funcRealStartAddr) >= 0 && curRealAddr.compare(funcRealEndAddr) === -1
                  // console.log(curRealAddr + ": isAppCode=" + isAppCode)
                  var curOffsetHexPtr = curRealAddr.sub(funcRealStartAddr)
                  var curOffsetInt = curOffsetHexPtr.toInt32()
                  console.log("current: realAddr=" + curRealAddr + " -> offset: hex=" + curOffsetHexPtr + "=" + curOffsetInt)

                  // var instructionStr = instruction.mnemonic + " " + instruction.opStr
                  var instructionStr = instruction.toString()
                  // console.log("\t" + curRealAddr + ": " + instructionStr);
                  // console.log("\t" + curRealAddr + " <+" + curOffsetHexPtr + ">: " + instructionStr)
                  // console.log("\t" + curRealAddr + " <+" + curOffsetInt + ">: " + instructionStr)

                  var opcodeStr = ""
                  if (FridaUtil.isShowOpcode) {
                    opcodeStr = " " + FridaUtil.genInstructionOpcodeStr(instruction)
                  }
                  var instructionFullLogStr = "\t" + curRealAddr + " <+" + curOffsetInt + ">" + opcodeStr + ": " + instructionStr
                  console.log(instructionFullLogStr)
                  // 0x252c0edf8 <+356>: br x10
                  // 0x252c0edf8 <+356> 40 01 1F D6: br x10

                  if (curOffsetInt in hookFuncMap){
                    console.log("offset: " + curOffsetHexPtr + "=" + curOffsetInt)
                    // let curHookFunc = hookFuncMap.get(curOffsetInt)
                    var curHookFunc = hookFuncMap[curOffsetInt]
                    // console.log("curOffsetInt=" + curOffsetInt + " -> curHookFunc=" + curHookFunc)

                    // putCallout -> https://www.radare.org/doc/frida/interfaces/StalkerArmIterator.html#putCallout
                    // StalkerScriptCallout -> https://www.radare.org/doc/frida/types/StalkerScriptCallout.html
                    // CpuContext -> https://www.radare.org/doc/frida/types/CpuContext.html
                    // Arm64CpuContext -> https://www.radare.org/doc/frida/interfaces/Arm64CpuContext.html

                    // work: normal
                    iterator.putCallout(curHookFunc)

                    // var extraDataDict = {
                    //   "curOffsetInt": curOffsetInt
                    // }
                    // Not work: abnormal
                    // iterator.putCallout((context) => {
                    // // iterator.putCallout((context, extraDataDict) => {
                    //   // console.log("match offset: " + curOffsetHexPtr + ", curRealAddr=" + curRealAddr)
                    //   // curHookFunc(context, curOffsetInt, moduleBaseAddress)
                    //   // context.curOffsetInt = curOffsetInt
                    //   // context.curOffsetHexPtr = curOffsetHexPtr
                    //   // context.moduleBaseAddress = moduleBaseAddress
                    //   // context[curOffsetInt] = curOffsetInt
                    //   // context[curOffsetHexPtr] = curOffsetHexPtr
                    //   // context[moduleBaseAddress] = moduleBaseAddress
                    //   // curHookFunc(context, extraDataDict)
                    //   curHookFunc(context)
                    // })
                  }

                }
                iterator.keep()
              } while ((instruction = iterator.next()) !== null)
            }
        });

        // function needDebug(context) {
        //     console.log("into needDebug")
        //     // console.log("into needDebug: context=" + context)
        //     // var contextStr = JSON.stringify(context, null, 2)
        //     // console.log("context=" + contextStr)
        //     // var x9Value1 = context.x9
        //     // var x9Value2 = context["x9"]
        //     // console.log("x9Value1=" + x9Value1 + ", x9Value2=" + x9Value2)
        // }
      },
      onLeave: function(retval) {
        console.log("addr: relative [" + funcRelativeStartAddrHexStr + "] real [" + funcRealStartAddr + "] -> retval=" + retval)
        if (curTid != null) {
          Stalker.unfollow(curTid)
          console.log("Stalker.unfollow curTid=", curTid)
        }
      }
    })
  }

crifan.org，使用署名4.0国际(CC BY 4.0)协议发布 all right reserved，powered by Gitbook最后更新： 2025-06-04 11:10:34

附录

附录

下面列出相关参考资料。

crifan.org，使用署名4.0国际(CC BY 4.0)协议发布 all right reserved，powered by Gitbook最后更新： 2022-03-17 20:39:28

参考资料

参考资料

【基本解决】Frida的Stalker.follow中events的含义和用法

【已解决】Frida中Stalker如何在Stalker.follow中写代码追踪指令代码运行

【已解决】Mac中如何使用frida的Stalker的js脚本

【未解决】Frida的stalker trace

【基本解决】Frida的Stalker.follow中events的含义和用法

【已解决】Frida去hook函数报错：Error unable to intercept function at please file a bug

【无法解决】Frida的Stalker中transform中的instruction是否可以获取到bytes即opcode

【已解决】优化Frida的Stalker的代码追踪逻辑

【已解决】Frida的Stalker中函数地址和指令地址匹配不上

【已解决】搞懂Frida的Stalker.follow的transform的调试指令运行的逻辑

【已解决】Frida的Stalker.follow中transform中的指令instruction

【记录】分析Frida的Stalker对于___lldb_unnamed_symbol2575代码追踪的输出结果

【记录】学习Frida官网文档Stalker搞懂基本用法和逻辑

【已解决】Frida的Stalker中去判断是否是函数的代码指令的逻辑

【整理】Frida的Stalker的利用方式

【未解决】尝试Frida的stalker能否修复抖音AwemeCore中函数名常量字符串

【整理】Frida的Stalker经验心得：用Stalker.exclude提高效率和减少干扰

【已解决】iOS逆向：如何写Frida的Stalker代码去监控函数___lldb_unnamed_symbol2575$$akd的指令运行

【已解决】给Frida的Stalker中输出log日志到文件

【已解决】Frida的Stalker中优化hook到指令时的log日志输出

【已解决】Frida的Stalker中调试报错：Fatal Python error _enter_buffered_busy: could not acquire lock

Stalker介绍

Stalker

Stalker - JavaScript API | Frida

DefinitelyTyped/index.d.ts

[原创] sktrace：基于 Frida Stalker 的 trace 工具-Android安全-看雪-安全社区|安全招聘|kanxue.com

Stalker的API

【iOS逆向】某营业厅算法分析_小陈_InfoQ写作社区

misc/frida-stalker-example.py at master · poxyran/misc · GitHub

Frida Stalker 是什么？-腾讯云开发者社区-腾讯云

某小说App返回数据 解密分析 - 奋飞安全

Frida Stalker 是什么？ - 奋飞安全

Crashed when hooking too many functions · Issue #244 · frida/frida

Frida 4.4.0 Stalker.follow() Crashes process. Win8.1 x86_64, JS Bindings · Issue #63 · frida/frida

crifan.org，使用署名4.0国际(CC BY 4.0)协议发布 all right reserved，powered by Gitbook最后更新： 2025-08-22 21:31:28