首页
社区
课程
招聘
62
[原创]基于VM的全新Trace框架发布!功能强大,一分钟1.5g,提高你的逆向体验~
发表于: 2025-2-9 12:30 11997

[原创]基于VM的全新Trace框架发布!功能强大,一分钟1.5g,提高你的逆向体验~

2025-2-9 12:30
11997

因为现有的作品均有大大小小的问题,想自己开发一个自己用着比较舒服的框架,提供分析效率。

因为想收集大家出现的反馈,继续发展壮大,我会持续维护一阵子,来提升自己的开发实力。

答案是不开源,会给出so文件,以及详细的使用方法,以及入门的例子,但是不开源不代表不维护

文章结尾会放上微信技术交流群,来讨论trace相关问题,以及逆向相关问题

这一篇算是对我git上的注入模块的部分的一个填坑,也是某搜题软件的第二篇的填坑,我最终目的是开发出无痕注入 、hook 、trace 、debug。

image

欢迎大家贴数据对比速度,当然后期有更多的优化空间,目前先不考虑改善(够用了)

已经手动trace过某团、某音、某Q,均无崩溃完成trace完成

但是在我测试中也有无法trace无法使用的情况,比如某宝,但是根据trace

进行了针对性patch后也可以继续运行完成

所以我希望大家发掘更多样本进行开发修复

CleanShot_2025_02_09_at_11_23_21

文本例子(可以结尾下载trace文件,自己搜索查看)

CleanShot_2025_02_09_at_11_39_48

CleanShot_2025_02_09_at_11_41_09

CleanShot_2025_02_09_at_11_40_53

CleanShot_2025_02_09_at_11_40_33

CleanShot_2025_02_09_at_11_40_08

并且支持通过得到的Jmethod id 反查是哪个类型

*为正在读取的内存内容

CleanShot_2025_02_09_at_11_48_58

以及一些方便算法还原的打印

这个目前不全,后面会加上所有调用参数等的打印

CleanShot_2025_02_09_at_11_41_57

有人会问有啥用

CleanShot_2025_02_09_at_11_42_38

append一些函数就能逮到了

后面会和上面的功能一起维护好,打印所有入参,相当于给所有函数都inlinehook了一遍

CleanShot_2025_02_09_at_12_11_17

此次的案例以我上一篇trace的案例作为教学,所有相关文件都会放在git仓库里

运行后得到0x9deeed68

继续运行

ptr(0x9deeed68).add(16).readPointer();

得到

由于读写内存的权限问题,需要刷入指定面具模块

可以在github仓库中找到

推动git上的so到/data/local/tmp/test.so

关闭setlinux

‍刷入面具模块(在仓库里)

在过掉msao后(见上一篇帖子开头)

attach输入

之后主动调用拿到结果:

去手机里拉到/data/user/0/com.fenbi.android.leo/log.txt

trace文件

基于qbdi框架的魔改和拓展,so没有任何加固混淆
欢迎反编译交流学习,会逐渐补充原理部分

防止读取到无效内存的地址,缓存maps相关的内存区段,防止进行非法读写

在跳转指令执行的时候(拦截B,BL的指令)

首先先dladdr找到调用的模块的落地文件,使用elf解析工具,把所有符号+偏移地址都缓存到自己的内存里,

如果匹配就可以替换

JNI打印就是在此基础上进行优化的打印

方案1 速度很慢

方案2 自己实现了一些搜索的策略 贪婪搜索策略 不再是窗口策略

方案3 管道

方案4 错误捕获

还有4种方案

其实就是遇到SVC指令的时候 读取他的X8拿到系统调用号,拿到调用名称并且打印

后面如果想打印更多返回值 就可以像// 对 openat 系统调用进行专门处理 这里一样增加更多case

但是目前只有openat被处理了,后面更新也会更新这里

仓库地址:

https://github.com/jiqiu2022/vm-trace-release

欢迎使用,求个star~ 有问题可以提issue,有问题我会补充到文档里

交流群:(纯技术交流,无广告,欢迎大佬们来交朋友)

加好友拉你进群 现在超过200没法二维码加了

预告:

接下来闲下来会完善hook相关的事情,以及做一些Linux内核模块开发的分享(隐藏调试信息,改机等)

Call addr: 0x7f3d15b9a0 [libc.so!memmove]
[libc.so!memmove](0xb400007d5ace2da0, 0xb400007db18f7c14, 32)
Call addr: 0x7f3d1582c0 [libc.so!memcmp]
memcmp(0xb400007d5a9dc760, 0xb400007d5ace2da0, 32)
Call addr: 0x7f3d15b9a0 [libc.so!memmove]
[libc.so!memmove](0xb400007d5ace2da0, 0xb400007db18f7c14, 32)
Call addr: 0x7f3d1582c0 [libc.so!memcmp]
memcmp(0xb400007d5a9dc760, 0xb400007d5ace2da0, 32)
memory read at 0x7d1e843ba8, instruction address = 0x7df45647cc, data size = 8, data value = 2a00000000000000
memory read at 0x7d1e843ba8, instruction address = 0x7df45647cc, data size = 8, data value = 2a00000000000000
function getHandle(object) {
    var handle = null;
    try {
        handle = object.$handle;
    } catch (e) {
    }
    if (handle == null) {
        try {
            handle = object.$h;
        } catch (e) {
        }
  
    }
    if (handle == null) {
        try {
            handle = object.handle;
        } catch (e) {
        }
  
    }
    return handle;
}
  
Java.perform(function () {
    let ReadableNativeMap = Java.use("com.fenbi.android.leo.utils.e");
    console.log(getHandle(ReadableNativeMap["zcvsd1wr2t"]))
  
});
function getHandle(object) {
    var handle = null;
    try {
        handle = object.$handle;
    } catch (e) {
    }
    if (handle == null) {
        try {
            handle = object.$h;
        } catch (e) {
        }
  
    }
    if (handle == null) {
        try {
            handle = object.handle;
        } catch (e) {
        }
  
    }
    return handle;
}
  
Java.perform(function () {
    let ReadableNativeMap = Java.use("com.fenbi.android.leo.utils.e");
    console.log(getHandle(ReadableNativeMap["zcvsd1wr2t"]))
  
});
DebugSymbol.fromAddress(ptr(0x7de5c78bf4))
 
{
    "address": "0x7de5c78bf4",
    "column": 0,
    "fileName": "",
    "lineNumber": 0,
    "moduleName": "libRequestEncoder.so",
    "name": "0x61bf4"
}
DebugSymbol.fromAddress(ptr(0x7de5c78bf4))
 
{
    "address": "0x7de5c78bf4",
    "column": 0,
    "fileName": "",
    "lineNumber": 0,
    "moduleName": "libRequestEncoder.so",
    "name": "0x61bf4"
}
adb shell
su
setenforce  0
adb shell
su
setenforce  0
function prepareArgs(args) {
    if (args === undefined || !Array.isArray(args)) {
        args = [];
    }
    var argNum = args.length;
    var argSize = Process.pointerSize * argNum;
    var argsPtr = Memory.alloc(argSize);
 
    for (var i = 0; i < argNum; i++) {
        var arg = args[i];
        var argPtr;
        if (!arg){
            arg=0
        }
        if (arg instanceof NativePointer) {
            // 如果是 NativePointer,直接使用
            argPtr = arg;
        } else if (typeof arg === 'number') {
            // 如果是数字,直接转换为指针
            argPtr = ptr(arg);
        } else if (typeof arg === 'string') {
            // 如果是字符串,分配内存并获取指针
            argPtr = Memory.allocUtf8String(arg);
        } else if (typeof arg === 'object' && arg.hasOwnProperty('handle')) {
            // 如果是带有 handle 属性的对象(如 JNIEnv)
            argPtr = arg.handle;
        } else if (typeof arg === 'object' && arg instanceof ArrayBuffer) {
            // 如果是二进制数据,分配内存并写入数据
            var dataPtr = Memory.alloc(arg.byteLength);
            Memory.writeByteArray(dataPtr, arg);
            argPtr = dataPtr;
        } else {
            console.error('Unsupported argument type at index ' + i + ':', typeof arg);
            throw new TypeError('Unsupported argument type at index ' + i + ': ' + typeof arg);
        }
 
        // 将参数指针写入参数数组
        Memory.writePointer(argsPtr.add(i * Process.pointerSize), argPtr);
    }
 
    return {
        argsPtr: argsPtr,
        argNum: argNum
    };
}
 
var  dlopenPtr = Module.findExportByName(null, 'dlopen');
var  dlopen = new NativeFunction(dlopenPtr, 'pointer', ['pointer', 'int']);
var soPath = "/data/local/tmp/test.so"; // 示例路径
var  soPathPtr = Memory.allocUtf8String(soPath);
var handle = dlopen(soPathPtr, 2);
 
var traceaddr = Module.findExportByName("test.so", 'start_trace');
var trace = new NativeFunction(traceaddr, 'pointer', ['pointer', 'pointer', 'uint32','pointer','uint32']);
var aimbase =Module.findBaseAddress("libRequestEncoder.so");
var targetFuncAddr = aimbase.add(0x61bf4);
console.log(handle);
Interceptor.replace(targetFuncAddr, new NativeCallback(function (arg0,arg1,arg2,arg3,arg4,arg5) {
    console.log("memory_function called with pointer: " + ptr);
    var args =[arg0,arg1,arg2,arg3,arg4,arg5];
    var {argsPtr, argNum} = prepareArgs(args);
    var argPtr1 = Memory.allocUtf8String("/data/user/0/com.fenbi.android.leo/log.txt");
    var res =trace(targetFuncAddr, argsPtr,argNum,argPtr1,6);
    return ptr(res);
}, 'pointer', ['pointer','pointer','pointer','pointer','uint32']));
function call(){
    Java.perform(function() {
        console.log("gan_sign script loaded successfully");
 
        // 使用要 hook 的 Java 类
        var e = Java.use("com.fenbi.android.leo.utils.e");
 
        // 定义输入参数
        var str = "/leo-gateway/android/auth/password"// 要访问的链接
        var str2 = "wdi4n2t8edr"// 固定参数
        var intParam = -28673;  // 获取 int 参数
 
        // 调用目标方法并获取返回值
        var result = e.zcvsd1wr2t(str, str2, intParam);
 
        // 输出输入参数
        console.log("input: ", str, str2, intParam);
 
        // 发送返回值到 Frida 客户端
        send(result);
 
        // 输出返回结果
        console.log("output: ", result);
    });
 
 
}
function prepareArgs(args) {
    if (args === undefined || !Array.isArray(args)) {
        args = [];
    }
    var argNum = args.length;
    var argSize = Process.pointerSize * argNum;
    var argsPtr = Memory.alloc(argSize);
 
    for (var i = 0; i < argNum; i++) {
        var arg = args[i];
        var argPtr;
        if (!arg){
            arg=0
        }
        if (arg instanceof NativePointer) {
            // 如果是 NativePointer,直接使用
            argPtr = arg;
        } else if (typeof arg === 'number') {
            // 如果是数字,直接转换为指针
            argPtr = ptr(arg);
        } else if (typeof arg === 'string') {
            // 如果是字符串,分配内存并获取指针
            argPtr = Memory.allocUtf8String(arg);
        } else if (typeof arg === 'object' && arg.hasOwnProperty('handle')) {
            // 如果是带有 handle 属性的对象(如 JNIEnv)
            argPtr = arg.handle;
        } else if (typeof arg === 'object' && arg instanceof ArrayBuffer) {
            // 如果是二进制数据,分配内存并写入数据
            var dataPtr = Memory.alloc(arg.byteLength);
            Memory.writeByteArray(dataPtr, arg);
            argPtr = dataPtr;
        } else {
            console.error('Unsupported argument type at index ' + i + ':', typeof arg);
            throw new TypeError('Unsupported argument type at index ' + i + ': ' + typeof arg);
        }
 
        // 将参数指针写入参数数组
        Memory.writePointer(argsPtr.add(i * Process.pointerSize), argPtr);
    }
 
    return {
        argsPtr: argsPtr,
        argNum: argNum
    };
}
 
var  dlopenPtr = Module.findExportByName(null, 'dlopen');
var  dlopen = new NativeFunction(dlopenPtr, 'pointer', ['pointer', 'int']);
var soPath = "/data/local/tmp/test.so"; // 示例路径
var  soPathPtr = Memory.allocUtf8String(soPath);
var handle = dlopen(soPathPtr, 2);
 
var traceaddr = Module.findExportByName("test.so", 'start_trace');
var trace = new NativeFunction(traceaddr, 'pointer', ['pointer', 'pointer', 'uint32','pointer','uint32']);
var aimbase =Module.findBaseAddress("libRequestEncoder.so");
var targetFuncAddr = aimbase.add(0x61bf4);
console.log(handle);
Interceptor.replace(targetFuncAddr, new NativeCallback(function (arg0,arg1,arg2,arg3,arg4,arg5) {
    console.log("memory_function called with pointer: " + ptr);
    var args =[arg0,arg1,arg2,arg3,arg4,arg5];
    var {argsPtr, argNum} = prepareArgs(args);
    var argPtr1 = Memory.allocUtf8String("/data/user/0/com.fenbi.android.leo/log.txt");
    var res =trace(targetFuncAddr, argsPtr,argNum,argPtr1,6);
    return ptr(res);
}, 'pointer', ['pointer','pointer','pointer','pointer','uint32']));
function call(){
    Java.perform(function() {
        console.log("gan_sign script loaded successfully");
 
        // 使用要 hook 的 Java 类
        var e = Java.use("com.fenbi.android.leo.utils.e");
 
        // 定义输入参数
        var str = "/leo-gateway/android/auth/password"// 要访问的链接
        var str2 = "wdi4n2t8edr"// 固定参数
        var intParam = -28673;  // 获取 int 参数
 
        // 调用目标方法并获取返回值
        var result = e.zcvsd1wr2t(str, str2, intParam);
 
        // 输出输入参数
        console.log("input: ", str, str2, intParam);
 
        // 发送返回值到 Frida 客户端
        send(result);
 
        // 输出返回结果
        console.log("output: ", result);
    });
 
 
}
call()
gan_sign script loaded successfully
memory_function called with pointer: function value() {
    [native code]
}
input:  /leo-gateway/android/auth/password wdi4n2t8edr -28673
output:  d9b6b12a7352587971a9b3b007be672d
message: {'type': 'send', 'payload': 'd9b6b12a7352587971a9b3b007be672d'} data: None
call()
gan_sign script loaded successfully
memory_function called with pointer: function value() {
    [native code]
}
input:  /leo-gateway/android/auth/password wdi4n2t8edr -28673
output:  d9b6b12a7352587971a9b3b007be672d
message: {'type': 'send', 'payload': 'd9b6b12a7352587971a9b3b007be672d'} data: None
void AddrResolver::cacheModules() {
    modules.clear();
 
    for (const auto &map: QBDI::getCurrentProcessMaps(true)) {
        // 过滤匿名内存映射 (例如 "[anon:...]")
        if (map.name.empty() || map.name.find("[anon]") != std::string::npos) {
            continue;
        }
 
        // 过滤无效路径的映射 (不含 "/" 的无效路径)
        if (map.name.find("/") == std::string::npos) {
            continue;
        }
 
        // 过滤掉不可读和不可执行的映射 (只保留可读或可执行的映射)
        if ((map.permission & QBDI::PF_READ) == 0) {
            continue;
        }
 
 
        // 检查模块是否已存在,存在则追加,否则新增
        auto r = std::find_if(std::begin(modules), std::end(modules),
                              [&](const Module &m) {
                                  return m.path == map.name;
                              });
        if (r != std::end(modules)) {
            r->append(map);
        } else {
            modules.emplace_back(map);
        }
    }
}
void AddrResolver::cacheModules() {
    modules.clear();
 
    for (const auto &map: QBDI::getCurrentProcessMaps(true)) {
        // 过滤匿名内存映射 (例如 "[anon:...]")
        if (map.name.empty() || map.name.find("[anon]") != std::string::npos) {
            continue;
        }
 
        // 过滤无效路径的映射 (不含 "/" 的无效路径)
        if (map.name.find("/") == std::string::npos) {
            continue;
        }
 
        // 过滤掉不可读和不可执行的映射 (只保留可读或可执行的映射)
        if ((map.permission & QBDI::PF_READ) == 0) {
            continue;
        }
 
 
        // 检查模块是否已存在,存在则追加,否则新增
        auto r = std::find_if(std::begin(modules), std::end(modules),
                              [&](const Module &m) {
                                  return m.path == map.name;
                              });
        if (r != std::end(modules)) {
            r->append(map);
        } else {
            modules.emplace_back(map);
        }
    }
}
void AddrResolver::loadModules(const std::vector<const Module *> &modules) {
    for (const auto &m: modules) {
        if (loaded_path.find(m->path) != loaded_path.end()) {
            continue;
        }
 
        std::unique_ptr externlib = ELFTOOLS::ELF::Parser::parse(m->path);
        if (not externlib) {
            continue;
        }
 
        for (const auto &s: externlib->symbols()) {
            QBDI::rword addr = s.value() + m->range.start();
            resolv_cache[addr].emplace(s.demangled_name());
        }
 
        loaded_path.emplace(m->path);
    }
}
void AddrResolver::loadModules(const std::vector<const Module *> &modules) {
    for (const auto &m: modules) {
        if (loaded_path.find(m->path) != loaded_path.end()) {
            continue;
        }
 
        std::unique_ptr externlib = ELFTOOLS::ELF::Parser::parse(m->path);
        if (not externlib) {
            continue;
        }
 
        for (const auto &s: externlib->symbols()) {
            QBDI::rword addr = s.value() + m->range.start();
            resolv_cache[addr].emplace(s.demangled_name());
        }
 
        loaded_path.emplace(m->path);
    }
}
// 使用 process_vm_readv 读取自身进程内存并搜索可见字符串
inline void searchVisibleStringsInMemoryProcessVM(rword addr, size_t size, LogManager *logManager) {
    pid_t pid = getpid(); // 获取当前进程ID
 
    // 本地缓冲区
    std::vector<uint8_t> buffer(size);
 
    // 设置本地 iovec
    struct iovec local_iov;
    local_iov.iov_base = buffer.data();
    local_iov.iov_len = size;
 
    // 设置远程 iovec
    struct iovec remote_iov;
    remote_iov.iov_base = reinterpret_cast<void *>(addr);
    remote_iov.iov_len = size;
 
    // 调用 process_vm_readv
    ssize_t nread = process_vm_readv(pid, &local_iov, 1, &remote_iov, 1, 0);
    if (nread < 0) {
        std::stringstream ss;
        ss << "process_vm_readv 失败: " << strerror(errno) << "\n";
        logManager->logPrint(ss.str().c_str());
        return;
    }
 
    logManager->logPrint("内存读取成功。\n");
 
    // 搜索可见字符串
    std::string visibleString;
    for (size_t i = 0; i < static_cast<size_t>(nread); ++i) {
        if (std::isprint(buffer[i])) {
            visibleString += static_cast<char>(buffer[i]);
        } else {
            if (visibleString.length() >= minStringLength) {
                rword stringAddr = addr + i - visibleString.length();
                std::stringstream ss;
                ss << "地址: 0x" << std::hex << stringAddr
                   << ", 字符串: " << visibleString << "\n";
                logManager->logPrint(ss.str().c_str());
            }
            visibleString.clear();
        }
    }
 
    // 检查数据结尾是否有未处理的字符串
    if (visibleString.length() >= minStringLength) {
        rword stringAddr = addr + nread - visibleString.length();
        std::stringstream ss;
        ss << "地址: 0x" << std::hex << stringAddr
           << ", 字符串: " << visibleString << "\n";
        logManager->logPrint(ss.str().c_str());
    }
}
// 使用 process_vm_readv 读取自身进程内存并搜索可见字符串
inline void searchVisibleStringsInMemoryProcessVM(rword addr, size_t size, LogManager *logManager) {
    pid_t pid = getpid(); // 获取当前进程ID
 
    // 本地缓冲区
    std::vector<uint8_t> buffer(size);
 
    // 设置本地 iovec
    struct iovec local_iov;
    local_iov.iov_base = buffer.data();
    local_iov.iov_len = size;
 
    // 设置远程 iovec
    struct iovec remote_iov;
    remote_iov.iov_base = reinterpret_cast<void *>(addr);
    remote_iov.iov_len = size;
 
    // 调用 process_vm_readv
    ssize_t nread = process_vm_readv(pid, &local_iov, 1, &remote_iov, 1, 0);
    if (nread < 0) {
        std::stringstream ss;
        ss << "process_vm_readv 失败: " << strerror(errno) << "\n";
        logManager->logPrint(ss.str().c_str());
        return;
    }
 

[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

最后于 2025-4-14 14:25 被棕熊编辑 ,原因:
上传的附件:
收藏
免费 62
支持
分享
赞赏记录
参与人
雪币
留言
时间
听我讲故事吗.
这个讨论对我很有帮助,谢谢!
2小时前
mb_rqgxdcwg
你的分享对大家帮助很大,非常感谢!
1天前
zhnnmsl
期待更多优质内容的分享,论坛有你更精彩!
2天前
醉染
感谢你的积极参与,期待更多精彩内容!
2天前
wx_        _937851
谢谢你的细致分析,受益匪浅!
3天前
顽劣
你的帖子非常有用,感谢分享!
3天前
wx_啦啦啦~
这个讨论对我很有帮助,谢谢!
3天前
浮事青云
谢谢你的细致分析,受益匪浅!
3天前
陈某人
为你点赞!
4天前
Dr_Knox
这个讨论对我很有帮助,谢谢!
5天前
mb_ycvtvhqa
感谢你分享这么好的资源!
6天前
hwfdvd
感谢你分享这么好的资源!
6天前
Gift1a
为你点赞!
6天前
mb_qqnashwi
为你点赞!
6天前
涙涙涙
为你点赞!
6天前
VIPJK
你的分享对大家帮助很大,非常感谢!
2025-4-18 12:34
saykao
感谢你分享这么好的资源!
2025-4-17 19:18
mb_haaygihg
感谢你分享这么好的资源!
2025-4-17 16:26
mb_omdeihqm
感谢你的积极参与,期待更多精彩内容!
2025-4-17 11:53
沫水.
感谢你的积极参与,期待更多精彩内容!
2025-4-17 06:15
Loopher
为你点赞!
2025-4-16 22:22
爱吃菠菜
为你点赞!
2025-4-16 20:23
梧桐生
非常支持你的观点!
2025-4-16 17:29
我爱学习ing
感谢你的贡献,论坛因你而更加精彩!
2025-4-16 15:42
酒仙桥之虎
感谢你的积极参与,期待更多精彩内容!
2025-4-16 15:00
wx_byte
你的分享对大家帮助很大,非常感谢!
2025-4-16 11:34
suminglan
为你点赞!
2025-4-15 14:57
婷婷妈咪
非常支持你的观点!
2025-4-14 19:59
Cr0ssx2
为你点赞!
2025-4-14 11:17
starks
非常支持你的观点!
2025-4-7 17:25
螺丝兔
+1
谢谢你的细致分析,受益匪浅!
2025-3-10 15:03
海带
这个讨论对我很有帮助,谢谢!
2025-3-9 21:43
xdcs100
非常支持你的观点!
2025-3-6 17:00
mb_hlgwcshl
这个讨论对我很有帮助,谢谢!
2025-2-27 11:43
养只猫不好么
这个讨论对我很有帮助,谢谢!
2025-2-24 21:31
by_Lin
谢谢你的细致分析,受益匪浅!
2025-2-23 03:45
4Chan
+1
为你点赞!
2025-2-22 19:38
52niu
你的分享对大家帮助很大,非常感谢!
2025-2-19 12:17
Je2em1ah
谢谢你的细致分析,受益匪浅!
2025-2-13 20:51
mb_zfqvurgb
感谢你的贡献,论坛因你而更加精彩!
2025-2-13 18:32
xxf4
感谢你分享这么好的资源!
2025-2-13 12:39
Shangwendada
这个讨论对我很有帮助,谢谢!
2025-2-13 11:23
哈哥
为你点赞!
2025-2-13 11:17
周游列国
+1
感谢你的贡献,论坛因你而更加精彩!
2025-2-12 09:56
Ram98
感谢你的积极参与,期待更多精彩内容!
2025-2-12 09:55
天水姜伯约
你的帖子非常有用,感谢分享!
2025-2-11 18:40
令狐双
感谢你分享这么好的资源!
2025-2-11 16:44
C0rax
+5
这个讨论对我很有帮助,谢谢!
2025-2-10 23:16
OvO2333
感谢你的贡献,论坛因你而更加精彩!
2025-2-10 22:21
K4NG
+1
感谢你的贡献,论坛因你而更加精彩!
2025-2-10 15:14
AunCss
你的帖子非常有用,感谢分享!
2025-2-10 13:49
sun-shine
为你点赞!
2025-2-10 10:08
你瞒我瞒
感谢你分享这么好的资源!
2025-2-10 09:17
Taavi
谢谢你的细致分析,受益匪浅!
2025-2-9 20:14
东方玻璃
感谢你分享这么好的资源!
2025-2-9 19:16
ngiokweng
你的帖子非常有用,感谢分享!
2025-2-9 18:39
mb_vjpiriil
非常支持你的观点!
2025-2-9 18:06
新气象
你的帖子非常有用,感谢分享!
2025-2-9 15:59
嘎嘎真的很棒
+6
期待更多优质内容的分享,论坛有你更精彩!
2025-2-9 14:19
梦_魇
+10
期待更多优质内容的分享,论坛有你更精彩!
2025-2-9 13:07
sinker_
感谢你的贡献,论坛因你而更加精彩!
2025-2-9 12:57
Forgo7ten
+6
期待更多优质内容的分享,论坛有你更精彩!
2025-2-9 12:45
最新回复 (49)
雪    币: 3197
活跃值: (2239)
能力值: ( LV9,RANK:170 )
在线值:
发帖
回帖
粉丝
2
仓库需要整理一会,争取今天内发出
2025-2-9 12:34
0
雪    币: 2855
活跃值: (4092)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
3
火钳刘明
2025-2-9 12:34
1
雪    币: 3197
活跃值: (2239)
能力值: ( LV9,RANK:170 )
在线值:
发帖
回帖
粉丝
4
墨穹呢 火钳刘明
谢谢哈哈,火不火还不一定嘞
2025-2-9 12:52
0
雪    币: 670
活跃值: (541)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
火钳刘明
2025-2-9 12:58
0
雪    币: 3326
活跃值: (2611)
能力值: ( LV7,RANK:100 )
在线值:
发帖
回帖
粉丝
6
2025-2-9 13:07
0
雪    币: 10
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
7
太强了
2025-2-9 13:56
0
雪    币: 393
活跃值: (1880)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
8
太强了
2025-2-9 14:01
0
雪    币: 20
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
9
太强了
2025-2-9 14:27
0
雪    币: 420
活跃值: (280)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
10
666,,太强了
2025-2-9 14:36
0
雪    币: 2887
活跃值: (3542)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
11
太腻害了  楼主是在工作吗?
2025-2-9 14:55
0
雪    币: 2337
活跃值: (2943)
能力值: ( LV9,RANK:150 )
在线值:
发帖
回帖
粉丝
12

太強了

最后于 2025-2-9 18:40 被ngiokweng编辑 ,原因:
2025-2-9 18:40
0
雪    币: 561
活跃值: (5613)
能力值: ( LV5,RANK:70 )
在线值:
发帖
回帖
粉丝
13
感谢分享
2025-2-9 23:33
0
雪    币: 30
活跃值: (1435)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
14
厉害~厉害~
2025-2-10 08:46
0
雪    币: 3197
活跃值: (2239)
能力值: ( LV9,RANK:170 )
在线值:
发帖
回帖
粉丝
15
谢谢大家的支持,我就不一一回复了,现在群马上满200人,我后面会新放一个vx,拉大家入群,今天得上班,所以得晚上才能操作了
2025-2-10 09:52
0
雪    币: 2508
活跃值: (3027)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
16
太强啦,感谢分享
2025-2-10 10:19
0
雪    币: 1795
活跃值: (2539)
能力值: ( LV2,RANK:15 )
在线值:
发帖
回帖
粉丝
17
可以Xposed注入吗
2025-2-10 10:27
0
雪    币: 144
活跃值: (687)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
18
感谢分享,希望分享一下使用文档。使用说明放一下
2025-2-10 11:33
0
雪    币: 3197
活跃值: (2239)
能力值: ( LV9,RANK:170 )
在线值:
发帖
回帖
粉丝
19
又见飞刀z 可以Xposed注入吗
完全可以的
2025-2-10 12:33
0
雪    币: 3197
活跃值: (2239)
能力值: ( LV9,RANK:170 )
在线值:
发帖
回帖
粉丝
20
口艾口牙女马口牙 感谢分享,希望分享一下使用文档。使用说明放一下
计划晚上补,今天上班
2025-2-10 12:33
0
雪    币: 4509
活跃值: (4017)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
21
感谢分享, 跟qbdi比有什么优势吗?
2025-2-10 14:41
0
雪    币: 966
活跃值: (4830)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
22
StriveMario 感谢分享, 跟qbdi比有什么优势吗?
这就是qbdi啊
2025-2-10 15:01
0
雪    币: 20
活跃值: (943)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
23
佬就是佬,太牛x辣
2025-2-10 15:19
0
雪    币: 3197
活跃值: (2239)
能力值: ( LV9,RANK:170 )
在线值:
发帖
回帖
粉丝
24

readme文档已经补充好了,欢迎大家提意见,有问题交流群提问,会同步到readme

最后于 2025-2-10 22:02 被棕熊编辑 ,原因:
2025-2-10 22:01
0
雪    币: 1057
活跃值: (508)
能力值: ( LV4,RANK:40 )
在线值:
发帖
回帖
粉丝
25
太有实力了!
2025-2-10 23:16
0
游客
登录 | 注册 方可回帖
返回

账号登录
验证码登录

忘记密码?
没有账号?立即免费注册