首页
社区
课程
招聘
[原创]Frida 常见检测与绕过
发表于: 2025-12-8 16:36 2111

[原创]Frida 常见检测与绕过

2025-12-8 16:36
2111

这是最基础也是最常见的检测手段。由于绝大多数 Frida 教程都指导用户将服务端文件命名为 frida-server​ 并放置在 /data/local/tmp/ 目录下,App 的防护机制会针对这些“标准特征”进行扫描。

防护代码通常会在 App 启动时执行以下检查:

App 会尝试访问 Android 系统中的常见临时目录,查找是否存在包含 frida 关键字的文件。

代码示例 (伪代码)

App 可以通过 Shell 命令或读取系统文件来获取当前运行的所有进程列表,并匹配黑名单。

扫描方式:执行 ps -A 查看进程状态。

image

敏感关键字​:frida-server​, frida-helper​, frida-launcher

代码示例 (伪代码)

针对上述特征检测,最直接有效的方法就是 “改名”

这是最简单的一步。将 frida-server 重命名为类似系统进程的名字,既能避开文件扫描,启动后的进程名也会随之改变,从而避开进程扫描。

操作步骤

有些深度检测不仅仅匹配文件名,还会扫描二进制文件内部的字符串特征(如 frida:rpc​ 字符串)。
此时,单纯重命名文件无效。你需要使用 ​HLuda(魔改版 Frida)。

Frida 在运行时需要开启 TCP 端口与电脑端进行数据传输。如果不加配置,Frida 会默认绑定特定的特征端口,这成为了 App 检测的重要依据。

Frida 服务端启动后,默认会监听以下两个端口:

防护代码通常采用以下方式进行探测:

App 可以执行 netstat​ 命令,查看当前系统是否有名为 0.0.0.0:27042​ 或 127.0.0.1:27042 的监听状态。

image

绕过的核心思想是 ​ “避开默认” 。只要我们不使用 27042 端口,上述针对固定端口的扫描就会失效。

在手机端启动 frida-server​ 时,使用 -l​ (listen) 参数指定一个随机的非标准端口(例如 8888​ 或 6666)。

修改端口后,电脑端的 Frida 客户端不会自动识别,必须手动进行端口转发或指定连接地址。

方式 A:通过 USB 转发 (推荐)
我们需要将电脑的 8888​ 端口转发到手机的 8888 端口。

方式 B:通过 WiFi 连接
如果手机和电脑在同一局域网,可以直接指定手机 IP。

这是 Android Native 层反调试最经典的手段之一。

Linux/Android 内核规定:​同一个进程同时只能被一个调试器(Tracer)附加

Frida 的工作原理​:Frida 本质上也是一个调试器,它需要通过 ptrace 系统调用附加(Attach)到目标 App 进程上才能进行 Hook。

App 的防御手段​:App 在启动的极早期(通常在 .init_array​ 或 JNI_OnLoad​ 中),主动调用 ptrace(PTRACE_TRACEME, 0, 0, 0) 自己附加自己。

冲突结果

代码示例 (C/C++)

针对 ptrace​ 占坑,单纯的“Attach 模式”是必死的。我们需要利用 Frida 的 Spawn 模式 抢在 App 运行代码前介入,并修改 App 的检测逻辑。

Spawn 模式 (-f) 会由 Zygote 进程 fork 出目标 App,并在 App 执行任何自己的代码(包括反调试代码)之前将 Frida 的 Gadget/Agent 注入进去。

这给了我们一个“时间差”:Frida 先进去了,现在轮到 Frida 掌控局面。

仅仅进入是不够的。如果 Frida 保持附加状态,App 随后的 ptrace​ 调用会失败,App 依然会发现并退出。
根本的解决办法是​:Hook libc.so​ 中的 ptrace​ 函数,拦截 App 的调用,直接返回 0(假装成功),并且不要执行真正的 ptrace 系统调用。

示例脚本

Frida 的客户端与服务端通信基于 D-Bus 协议(一种进程间通信/RPC 机制)。即使我们将 Frida 服务端改名并迁移目录,其通信协议的特征(尤其是握手阶段)依然是固定的。

App 可以遍历本地所有开放的 TCP 端口,并尝试建立 Socket 连接。一旦连接成功,App 会发送 D-Bus 协议特定的握手消息。如果服务端响应了特定的 D-Bus 关键字(如 REJECT),则可认定该端口运行着 Frida。

检测代码示例 (伪代码)

这是您提到的方法。原理是拦截 App 在处理网络响应时的比较逻辑。当 App 拿收到的数据去匹配 "REJECT" 时,我们欺骗它说“没匹配上”。

注意:strcmp​ 和 strstr​ 是系统底层极其高频调用的函数。直接 Hook 会导致 App 巨卡无比甚至崩溃,必须加严格的过滤条件

相比于在运行时 Hook 极不稳定的 strstr,最彻底的办法是从源码层面消除特征。

HLuda(或其他去特征版本)在编译 Frida 时做了如下修改:

使用此类版本后,App 发送探测包收到的将不再是标准的 REJECT,从而直接绕过检测机制,无需编写任何 Hook 脚本。

在 Linux/Android 系统中,一切皆文件。/proc/pid/fd/ 目录包含了当前进程打开的所有文件描述符(File Descriptors)。App 通过遍历该目录,可以获知进程加载了哪些文件、建立了哪些 Socket 连接。

App 遍历 /proc/self/fd​ 目录下的所有文件,并使用 readlink​ 读取符号链接指向的​真实路径

相关命令​:ls -l /proc/self/fd​ 或 readlink -f /proc/self/fd/<id>

检测代码示例 (伪代码)

如果 Frida 注入成功,该目录下可能会出现指向以下路径的链接:

传统特征 (旧版 Frida)

高版本 Frida (>=16) 时:

检查 FD 已经基本无法检测 Frida。

Android 10+ 中,Google 对 memfd 的名称做了更严格的匿名化,Frida 使用的 memfd 不再暴露名称

无论特征如何变化,检测的核心动作都是调用 readlink​ 或 readlinkat​ 系统函数。
核心思路​:Hook 这两个函数,当 App 试图读取的文件描述符指向包含 frida​、gum​ 或 memfd​ 的路径时,将其替换为合法的系统路径(如 /dev/null​ 或 libc.so)。

在 Android (Linux) 系统中,进程的每一个线程在 /proc/pid/task/ 目录下都有一个对应的子目录(目录名为线程 ID)。

App 可以遍历该目录,读取每个线程的 status​ 或 comm 文件,获取线程名称。由于 Frida 依赖 GLib 库,运行时会创建特定的辅助线程,这些线程的默认名称具有极高的辨识度。

如果 Frida 注入成功,进程中通常会出现以下命名的线程:

image

image

核心思路是拦截对 /proc​ 目录下 comm​ 或 status​ 文件的读取操作。当发现 App 试图读取特定线程的信息时,检查读取到的内容,如果是 gmain​ 等敏感名称,将其替换为合法的系统线程名(如 epoll​、config_store 等)。

由于 gmain​ 和 gdbus​ 是 GLib 库硬编码的名称,gum-js-loop​ 是 Frida 源码硬编码的。
HLuda 等修改版 Frida 在编译阶段修改了这些字符串常量(例如将 gmain​ 改为 fmain 或其他无意义字符串),从根本上规避了针对特定字符串的检测。这是最推荐的方式。

/proc/self/maps 是 Android/Linux 系统中极为关键的文件,它记录了当前进程所有连续的虚拟内存区域的分布情况。App 通过读取该文件,可以精准地知道进程加载了哪些 SO 库、DEX 文件,以及内存段的权限属性。

maps 文件的一行通常包含以下信息:

如果 Frida 注入成功,App 遍历该文件通常会发现以下痕迹:

既然 App 必须通过 open​ 打开文件,再通过 read​ 读取内容,我们可以在它打开 /proc/self/maps​ 的瞬间,将目标路径重定向到一个我们准备好的、内容干净的“假 maps”文件上。

在未注入 Frida 之前(或使用 Spawn 模式暂停时),先手动提取一份正常的 maps 文件:

并在该文件中手动删去可能存在的敏感行(如果有)。

编写 Frida 脚本,拦截系统底层的文件打开操作。

关键细节:直接修改 args[0]​ 指向的内存可能会导致缓冲区溢出(如果新路径比旧路径长)。安全的做法是 Memory.allocUtf8String​ 分配新内存,并将 args[0] 指针替换过去。

对于 fd​ (文件描述符)、status​ (线程状态)、maps​ (内存映射) 这三类基于 /proc​ 文件系统的检测,上述 IO 重定向 方案是通解。只要将敏感文件指向无害文件(如 /dev/null 或提前备份的正常文件),即可实现完美绕过。

Inline Hook 是 Frida Interceptor​ 模块的核心机制。它的原理是直接修改内存中目标函数的​前几条指令(Prologue) ,将其替换为一条跳转指令(Trampoline/跳板),从而将程序执行流引导至 Frida 的处理函数。

App 可以通过检查关键函数开头的机器码(Machine Code)是否被篡改来检测 Hook。

在 ARM64 架构下,Frida 通常需要替换前 16 个字节(4 条指令)来实现长跳转。它会将原始指令备份,并写入以下经典的 "LDR + BR" 跳板指令:

Hook 前 (原始指令)
这是函数原本正常的汇编指令(示例):

Hook 后 (Frida 特征)
内存中的指令变成了跳转逻辑:

App 会计算内存中函数前 N 个字节的 CRC32MD5 值,并与本地文件(SO 库)中该函数的原始机器码进行比对。

检测逻辑的核心在于“比对”。App 通常会读取磁盘上的 SO 文件内容与内存内容进行比较。我们可以 Hook libc.so​ 中的 memcmp​ 函数。
当发现 App 正在比对我们已 Hook 的函数地址时,强行让 memcmp 返回 0(即相等),从而“指鹿为马”。

Frida 的 Inline Hook 机制本质上是 “篡改内存代码” 。即使只修改了几个字节(写入跳转指令),也会导致该内存区域的校验和(Checksum)发生变化。

App 通常采用 “磁盘 vs 内存” 的比对方式来检测代码是否被篡改。

检测代码逻辑 (伪代码)

既然修改代码会被检测,那就不要修改代码。
Frida 提供了硬件断点功能(基于 CPU 的调试寄存器),可以在不修改内存字节的情况下实现拦截。

找到 App 计算或比对 CRC 的核心函数(如 memcmp​、自定义的 check_crc),对其进行 Hook。

如果 App 是通过 open​/read 读取磁盘文件来计算基准值的,我们可以 Hook 这些 IO 函数。

思路:当 App 试图读取磁盘上的 SO 文件时,我们将其重定向到内存中已经被 Hook 的那段数据上(或者反过来,当它读内存时给它返回磁盘数据)。

File file = new File("/data/local/tmp/frida-server");
if (file.exists()) {
    // 发现 Frida,触发闪退或上报
    killApp();
}
File file = new File("/data/local/tmp/frida-server");
if (file.exists()) {
    // 发现 Frida,触发闪退或上报
    killApp();
}
// 读取 /proc/[pid]/cmdline 或执行 ps 命令
Process process = Runtime.getRuntime().exec("ps -A");
BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
String line;
while ((line = reader.readLine()) != null) {
    if (line.contains("frida-server")) {
        // 发现 Frida 进程
        throw new RuntimeException("Frida detected!");
    }
}
// 读取 /proc/[pid]/cmdline 或执行 ps 命令
Process process = Runtime.getRuntime().exec("ps -A");
BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
String line;
while ((line = reader.readLine()) != null) {
    if (line.contains("frida-server")) {
        // 发现 Frida 进程
        throw new RuntimeException("Frida detected!");
    }
}
# 1. 停止当前运行的 frida-server
pkill -f frida-server
 
# 2. 进入目录
cd /data/local/tmp
 
# 3. 重命名 (例如改为 fs 或 system_server_custom)
mv frida-server-16.x.x-android-arm64 fs
 
# 4. 运行
chmod +x fs
./fs &
# 1. 停止当前运行的 frida-server
pkill -f frida-server
 
# 2. 进入目录
cd /data/local/tmp
 
# 3. 重命名 (例如改为 fs 或 system_server_custom)
mv frida-server-16.x.x-android-arm64 fs
 
# 4. 运行
chmod +x fs
./fs &
# 格式:./frida-server -l 地址:端口
# 0.0.0.0 表示允许任何接口连接(包括 USB 和 WiFi)
./frida-server -l 0.0.0.0:8888 &
# 格式:./frida-server -l 地址:端口
# 0.0.0.0 表示允许任何接口连接(包括 USB 和 WiFi)
./frida-server -l 0.0.0.0:8888 &
# 1. 设置转发
adb forward tcp:8888 tcp:8888
 
# 2. 连接 (此时客户端可以像往常一样使用 -U 或 -R,或者指定 -H)
frida -H 127.0.0.1:8888 -l hook.js -f com.example.target
# 1. 设置转发
adb forward tcp:8888 tcp:8888
 
# 2. 连接 (此时客户端可以像往常一样使用 -U 或 -R,或者指定 -H)
frida -H 127.0.0.1:8888 -l hook.js -f com.example.target
# 假设手机 IP 为 192.168.1.10
frida -H 192.168.1.10:8888 -l hook.js -f com.example.target
# 假设手机 IP 为 192.168.1.10
frida -H 192.168.1.10:8888 -l hook.js -f com.example.target
// 简单的反调试逻辑
int status = ptrace(PTRACE_TRACEME, 0, 0, 0);
if (status == -1) {
    // ptrace 失败,说明已经被别人(如 Frida/IDA)附加了
    kill(getpid(), SIGKILL); // 自杀
}
// 简单的反调试逻辑
int status = ptrace(PTRACE_TRACEME, 0, 0, 0);
if (status == -1) {
    // ptrace 失败,说明已经被别人(如 Frida/IDA)附加了
    kill(getpid(), SIGKILL); // 自杀
}
function bypassPtrace() {
    var ptracePtr = Module.findExportByName("libc.so", "ptrace");
     
    if (ptracePtr) {
        // 使用 Interceptor.replace 完全替换掉 ptrace 的实现
        Interceptor.replace(ptracePtr, new NativeCallback(function(request, pid, addr, data) {
            console.log("[+] ptrace called - bypassing...");
            console.log("    request: " + request);
             
            // PTRACE_TRACEME 的常量值通常是 0
            if (request == 0) {
                console.log("    [+] Blocked PTRACE_TRACEME!");
                // 直接返回 0,欺骗 App 说“你已经成功附加自己了”
                return 0;
            }
             
            // 如果有其他 ptrace 需求,可以在这里放行,或者全部屏蔽
            return 0;
             
        }, 'long', ['int', 'int', 'pointer', 'pointer']));
         
        console.log("[+] ptrace bypass applied!");
    } else {
        console.log("[-] ptrace not found");
    }
}
 
setImmediate(function() {
    bypassPtrace();
});
function bypassPtrace() {
    var ptracePtr = Module.findExportByName("libc.so", "ptrace");
     
    if (ptracePtr) {
        // 使用 Interceptor.replace 完全替换掉 ptrace 的实现
        Interceptor.replace(ptracePtr, new NativeCallback(function(request, pid, addr, data) {
            console.log("[+] ptrace called - bypassing...");
            console.log("    request: " + request);
             
            // PTRACE_TRACEME 的常量值通常是 0
            if (request == 0) {
                console.log("    [+] Blocked PTRACE_TRACEME!");
                // 直接返回 0,欺骗 App 说“你已经成功附加自己了”
                return 0;
            }
             
            // 如果有其他 ptrace 需求,可以在这里放行,或者全部屏蔽
            return 0;
             
        }, 'long', ['int', 'int', 'pointer', 'pointer']));
         
        console.log("[+] ptrace bypass applied!");
    } else {
        console.log("[-] ptrace not found");
    }
}
 
setImmediate(function() {
    bypassPtrace();
});
Socket socket = new Socket("127.0.0.1", port);
InputStream is = socket.getInputStream();
OutputStream os = socket.getOutputStream();
 
// 发送 D-Bus 握手空字节
os.write(new byte[]{0});
 
// 读取响应
byte[] buffer = new byte[512];
int len = is.read(buffer);
String response = new String(buffer, 0, len);
 
// 检测 REJECT 关键字
if (response.contains("REJECT")) {
    // 发现 Frida!
}
Socket socket = new Socket("127.0.0.1", port);
InputStream is = socket.getInputStream();
OutputStream os = socket.getOutputStream();
 
// 发送 D-Bus 握手空字节
os.write(new byte[]{0});
 
// 读取响应
byte[] buffer = new byte[512];
int len = is.read(buffer);
String response = new String(buffer, 0, len);
 
// 检测 REJECT 关键字
if (response.contains("REJECT")) {
    // 发现 Frida!
}
function bypassDBusDetection() {
    var strstr = Module.findExportByName("libc.so", "strstr");
     
    if (strstr) {
        Interceptor.attach(strstr, {
            onEnter: function(args) {
                // args[0]: haystack (被搜索的字符串)
                // args[1]: needle (要查找的关键词)
                 
                this.needle = Memory.readUtf8String(args[1]);
                 
                // 只有当 App 正在查找敏感关键词时才介入
                if (this.needle && (this.needle.indexOf("REJECT") !== -1 || this.needle.indexOf("frida") !== -1)) {
                    this.detected = true;
                    // console.log("[*] Detected suspicious strstr check: " + this.needle);
                }
            },
            onLeave: function(retval) {
                if (this.detected) {
                    // 如果找到了 REJECT,强行返回 0 (NULL),表示没找到
                    // 从而欺骗 App
                    retval.replace(0);
                    // console.log("[+] Bypassed D-Bus check!");
                }
            }
        });
    }
}
function bypassDBusDetection() {
    var strstr = Module.findExportByName("libc.so", "strstr");
     
    if (strstr) {
        Interceptor.attach(strstr, {
            onEnter: function(args) {
                // args[0]: haystack (被搜索的字符串)
                // args[1]: needle (要查找的关键词)
                 
                this.needle = Memory.readUtf8String(args[1]);
                 
                // 只有当 App 正在查找敏感关键词时才介入
                if (this.needle && (this.needle.indexOf("REJECT") !== -1 || this.needle.indexOf("frida") !== -1)) {
                    this.detected = true;
                    // console.log("[*] Detected suspicious strstr check: " + this.needle);
                }
            },
            onLeave: function(retval) {
                if (this.detected) {
                    // 如果找到了 REJECT,强行返回 0 (NULL),表示没找到
                    // 从而欺骗 App
                    retval.replace(0);
                    // console.log("[+] Bypassed D-Bus check!");
                }
            }
        });
    }
}
File fdDir = new File("/proc/self/fd");
for (File fd : fdDir.listFiles()) {
    // 读取软链接指向的路径
    String realPath = Os.readlink(fd.getAbsolutePath());
    if (realPath.contains("frida") || realPath.contains("gum-js")) {
        // 发现异常
    }
}
File fdDir = new File("/proc/self/fd");
for (File fd : fdDir.listFiles()) {
    // 读取软链接指向的路径
    String realPath = Os.readlink(fd.getAbsolutePath());
    if (realPath.contains("frida") || realPath.contains("gum-js")) {
        // 发现异常
    }
}
function bypassProcCheck() {
    // 获取 libc.so 中的导出函数
    var readlink = Module.findExportByName("libc.so", "readlink");
    var readlinkat = Module.findExportByName("libc.so", "readlinkat");
 
    // 定义处理逻辑:检查并伪造路径
    var handleReadlink = function(buffer, size, retval) {
        // 只有当返回值 > 0 (读取成功) 时才处理
        if (retval.toInt32() > 0) {
            // 读取原始路径
            var path = Memory.readUtf8String(buffer, retval.toInt32());
             
            // 匹配敏感关键字 (涵盖旧版文件和新版 memfd)
            if (path && (path.indexOf("frida") !== -1 ||
                         path.indexOf("gum-js") !== -1 ||
                         path.indexOf("gmain") !== -1 ||
                         path.indexOf("linjector") !== -1)) {
                 
                // console.log("[*] Detected fd check: " + path);
                 
                // 伪造为正常的系统库路径
                var fakePath = "/system/lib64/libc.so";
                 
                // 覆写缓冲区
                Memory.writeUtf8String(buffer, fakePath);
                 
                // 修正返回值为伪造路径的长度
                retval.replace(fakePath.length);
            }
        }
    };
 
    // Hook readlinkat (Android 常用)
    // ssize_t readlinkat(int dirfd, const char *pathname, char *buf, size_t bufsiz);
    if (readlinkat) {
        Interceptor.attach(readlinkat, {
            onEnter: function(args) {
                this.buf = args[2]; // buf 指针
            },
            onLeave: function(retval) {
                handleReadlink(this.buf, 0, retval);
            }
        });
    }
 
    // Hook readlink (备用)
    // ssize_t readlink(const char *path, char *buf, size_t bufsiz);
    if (readlink) {
        Interceptor.attach(readlink, {
            onEnter: function(args) {
                this.buf = args[1]; // buf 指针
            },
            onLeave: function(retval) {
                handleReadlink(this.buf, 0, retval);
            }
        });
    }
}
 
setImmediate(bypassProcCheck);
function bypassProcCheck() {
    // 获取 libc.so 中的导出函数
    var readlink = Module.findExportByName("libc.so", "readlink");
    var readlinkat = Module.findExportByName("libc.so", "readlinkat");
 
    // 定义处理逻辑:检查并伪造路径
    var handleReadlink = function(buffer, size, retval) {
        // 只有当返回值 > 0 (读取成功) 时才处理
        if (retval.toInt32() > 0) {
            // 读取原始路径
            var path = Memory.readUtf8String(buffer, retval.toInt32());
             
            // 匹配敏感关键字 (涵盖旧版文件和新版 memfd)
            if (path && (path.indexOf("frida") !== -1 ||
                         path.indexOf("gum-js") !== -1 ||
                         path.indexOf("gmain") !== -1 ||
                         path.indexOf("linjector") !== -1)) {
                 
                // console.log("[*] Detected fd check: " + path);
                 
                // 伪造为正常的系统库路径
                var fakePath = "/system/lib64/libc.so";
                 
                // 覆写缓冲区
                Memory.writeUtf8String(buffer, fakePath);
                 
                // 修正返回值为伪造路径的长度
                retval.replace(fakePath.length);
            }

[培训]Windows内核深度攻防:从Hook技术到Rootkit实战!

最后于 2025-12-8 16:59 被xiusi编辑 ,原因:
收藏
免费 80
支持
分享
最新回复 (64)
雪    币: 132
活跃值: (1547)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
2
666
2025-12-8 17:54
0
雪    币: 398
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
3
6666666666
2025-12-8 18:18
0
雪    币:
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
4
666
2025-12-8 18:30
0
雪    币: 3009
活跃值: (3844)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
过来瞧瞧
2025-12-8 18:42
0
雪    币: 2
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
6
11
2025-12-8 21:58
1
雪    币: 94
活跃值: (95)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
过来瞧瞧
2025-12-8 22:03
0
雪    币: 7
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
8
收藏学习
2025-12-8 23:53
0
雪    币: 4978
活跃值: (5039)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
9
6666
2025-12-9 08:11
0
雪    币: 293
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
10
666666666666
2025-12-9 10:00
0
雪    币: 1548
活跃值: (1715)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
11
感谢分享
2025-12-9 10:36
0
雪    币: 104
活跃值: (7074)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
12
tql
2025-12-9 10:47
0
雪    币: 6
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
13
感谢分享
2025-12-9 10:48
0
雪    币: 209
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
14
666
2025-12-9 11:19
0
雪    币: 377
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
15
666
2025-12-9 11:30
0
雪    币: 0
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
16
感谢分享
2025-12-9 13:14
0
雪    币: 200
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
17
感谢分享
2025-12-9 14:12
0
雪    币: 29
活跃值: (1355)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
18
666666666666
2025-12-9 14:20
0
雪    币: 43
活跃值: (2579)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
19
666
2025-12-9 15:15
0
雪    币:
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
20
666
2025-12-9 17:06
0
雪    币: 8202
活跃值: (4708)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
21
666
2025-12-10 01:26
0
雪    币: 533
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
22
看看
2025-12-10 09:18
0
雪    币: 5616
活跃值: (9387)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
23
学习了,谢谢
2025-12-10 09:25
0
雪    币: 1
活跃值: (930)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
24
6
2025-12-10 09:29
0
雪    币: 350
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
25
66
2025-12-10 09:33
0
游客
登录 | 注册 方可回帖
返回