首页
社区
课程
招聘
[原创]ARM64 动态指令 trace 离线向后切片分析器 —— trace-slice
发表于: 1天前 701

[原创]ARM64 动态指令 trace 离线向后切片分析器 —— trace-slice

1天前
701

ARM64 动态指令 trace 离线向后切片分析器

项目地址:trace-slice 

逆向算法还原中,目标二进制(安卓 SO 库、IoT 固件、桌面应用等)常常被 VMP(虚拟机保护)、CFF(控制流平坦化)、OLLVM 等混淆方案层层加固,静态分析几乎无法看清算法逻辑。逆向工程师通常借助 unidbg 等模拟执行框架,对目标函数进行动态指令级 trace,记录每一条 ARM64 指令的执行过程以绕过混淆。然而,这样产生的 trace 文件动辄几千万行、数 GB 大小。

在这些海量指令中,大量是混淆引入的膨胀代码——虚拟机调度循环中的寄存器搬运、控制流平坦化的跳转分发、与目标值无直接关联的中间计算等。要从中还原出算法的真实计算逻辑,人工逐行分析虽然并非不可能,但异常困难且极度耗时,自动化工具能从 trace 中直接提取出与目标值相关的指令子集,将分析效率提升几个数量级。

trace-slice 实现了向后数据流切片(backward slicing):给定一个"你关心的值"——某个寄存器的最终状态或某个内存地址的内容——工具会自动从该值出发,沿数据依赖链反向追踪,找出所有直接或间接参与该值计算的指令,输出仅包含这些指令的最小子集。所有与目标值无关的指令(混淆代码、无关寄存器操作等)都被自动过滤掉。

向后数据流切片(backward slicing),自动去除与目标值无关的全部指令

字节粒度内存依赖追踪,精确处理不同宽度的 load/store(1/2/4/8/16 字节及 SIMD 128 位)

覆盖全部 150+ ARM64 助记符(40 个语义类别),包括 SIMD/NEON、原子操作等

可选控制依赖追踪(条件分支影响分析),通过 --with-control-dep 启用

值相等性剪枝(默认启用):当 LOAD 读取的值与对应 STORE 写入的值完全相等(纯值搬运)时,自动剪除 LOAD 的地址计算依赖链,大幅减少 VMP 地址噪音。可通过 --no-prune 禁用

高性能,实测 unidbg 的 2400 万行 2.8GB trace 日志文件,默认模式(含值剪枝)切片耗时约 8s,切片结果从 258 万行进一步精简至 128 万行(-50.3%)

run-log

向后切片(backward slicing)是一种经典的程序分析技术,由 Mark Weiser 于 1981 年首次提出(ICSE'81),并在 1984 年的 IEEE TSE 论文 "Program Slicing" 中系统阐述。它的目标很简单:给定程序中某个变量的某次取值,找出所有影响了这个值的语句。

可以用刑侦溯源来类比:你知道了案件的结果(某个寄存器最终存放的值),现在需要追查这个值是怎么一步步计算出来的——哪些指令提供了原始数据,哪些指令做了运算,哪些指令把中间结果搬到了最终位置。只有真正参与了这条"因果链"的指令才会被保留,其余全部排除。

与正向分析形成对比:正向分析是"跟踪所有变量,看每条指令会产生什么影响",需要关注全局状态;而向后切片是"从结果反推,只保留真正参与计算的指令",天然具有过滤能力。关键洞察在于:一条两千万行的 trace 中,与某个特定输出值相关的指令通常只占原始行数的一成左右,向后切片能精准地把这部分指令提取出来。

以下是 5 行 unidbg 格式的 ARM64 trace(为说明原理而简化):

逐行说明:

目标:追踪 x0 的值从何而来

逐步反向追踪过程:

结论:5 行全部参与了 x0 的计算,全部保留在切片结果中。

依赖关系图(箭头表示"依赖于"):

在上面的例子中,假设第 2 行和第 3 行之间插入了一行无关指令:

这行指令给 x15 赋值为 999,但在 x0 的整条计算链中,x15 从未被使用过。从第 5 行出发反向追踪时,永远不会触及这条指令,因此它被自动排除在切片结果之外。

这就是向后切片的核心价值所在。在真实的 VMP 混淆 trace 中,大量指令与你所关心的目标值没有数据依赖关系。向后切片能自动识别并过滤掉这些无关指令——实测 2400 万行的 trace 切片后保留约 258 万行(10.8%)。在此基础上,值相等性剪枝进一步将结果精简至约 128 万行(5.4%),剪除了大量 VMP 地址搬运噪音(详见第 8 节更新日志)。需要注意的是,切片保留的是所有与目标值存在数据依赖的指令,其中仍会包含 VMP 虚拟机调度循环中参与数据传递的指令(如寄存器搬运、虚拟栈操作等),这些并非核心算法逻辑但无法被数据流切片去除。

数据依赖(默认启用)

数据依赖描述的是值的直接传递关系:一条指令读取了某个寄存器或内存地址,而这个寄存器或内存地址的当前值是由之前的某条指令写入的。这是最核心、最基础的依赖关系,涵盖了寄存器赋值和内存读写两大类。

控制依赖(通过 --with-control-dep 启用)

控制依赖描述的是条件分支对指令执行的影响:某条指令是否执行,取决于之前某个条件分支的判断结果。

用 3 行示例说明:

大多数场景下,仅使用数据依赖就足以提取核心算法逻辑。控制依赖适用于需要理解"为什么走了这条执行路径"的分析场景。

trace-slice 的分析过程分为三步:

Pass 1(正向扫描):从头到尾逐行扫描整个 trace 文件。对每一行,解析出指令的助记符和操作数,判断哪些寄存器/内存被读取(USE)、哪些被写入(DEF),然后记录行与行之间的依赖关系,构建完整的依赖图。

BFS 反向切片:从用户指定的目标(某个寄存器或内存地址在某一行的值)出发,沿依赖边进行反向广度优先遍历(BFS),标记所有传递可达的行。被标记的行就是与目标值相关的最小指令集合。

Pass 2(输出):再次遍历 trace 文件,只将被标记的行写入输出文件,未被标记的行全部跳过。

本工具默认解析 unidbg 模拟器输出的 ARM64 指令 trace 格式。每行记录一条指令的执行信息,包含时间戳、模块偏移、机器码、PC 地址、反汇编文本、寄存器输入/输出值以及内存操作注解等字段。

一行完整的 trace 示例(无内存操作):

各字段说明:

带内存写入操作(store)的完整行示例:

带内存读取操作(load)的完整行示例:

本工具默认为 unidbg trace 设计,但满足以下条件的其他 trace 格式也能兼容。

必要条件:

修改前缀跳过长度:

如果你的 trace 格式前缀长度不是 40 字节,需要修改源码中的跳过长度。具体位置在 src/parser.rs 文件的 find_disasm_with_pos 函数中:

寄存器命名要求:

必须使用 ARM64 标准寄存器名:

最小合规示例:

X 代表任意非 " 字符的填充,总共 40 个字符)

不合规示例(缺少内存注解):

缺少 ; mem[WRITE] abs=0x...,工具无法识别内存写入,依赖链在此处断裂。

RegId(u8 newtype):用一个字节紧凑编码 66 个 ARM64 寄存器 -- x0-x30(0-30)、sp(31)、xzr(32)、v0-v31(33-64)、nzcv(65)。作为 FxHashMap 键时仅占 1 字节,最大限度减少哈希开销。

ParsedLine:单行 trace 的解析结果,包含助记符、操作数列表、内存操作信息、箭头标记、基址寄存器、回写标志等。这是临时结构,每行创建、使用后即丢弃,不持久化存储。

InsnClass(enum,40 个变体):指令语义分类。每个变体对应唯一的 DEF/USE 模式,消除了在切片器中按助记符逐一匹配的需要。150+ 条助记符映射到 40 个类别后,determine_def_use 函数只需对 40 种情况做模式匹配。

ScanState:Pass 1 扫描的完整输出,包含三个核心表:

以第 2 节的 5 行示例为例,逐行展示 reg_last_defdeps 的变化过程:

对应的依赖关系图:

从行 4(ldr x0)出发做 BFS 反向切片:行 4 依赖行 3,行 3 依赖行 2,行 2 依赖行 0 和行 1。最终 5 行全部被标记,输出完整的切片结果。

ARM64 有多种不同宽度的 load/store 指令:ldrb(1 字节)、ldrh(2 字节)、ldr w(4 字节)、ldr x(8 字节)、stp x(16 字节)、str q(16 字节)。一条 stp x5, x6, [sp] 写入 16 字节,但后续的 ldrb w0, [sp, #8] 只读取其中第 9 个字节。如果只按起始地址匹配内存依赖,会产生大量虚假依赖或遗漏依赖。

trace-slice 采用字节粒度追踪:每个字节地址独立记录最后写入行。访问宽度(elem_width)从助记符和寄存器前缀推导 -- 助记符后缀优先(如 ldrb 对应 1 字节、ldrh 对应 2 字节),否则按首个操作数的寄存器前缀推导(w 对应 4 字节、x 对应 8 字节、q 对应 16 字节)。这样,一条 str x8, [sp] 会在 mem_last_def 中写入 8 个连续字节地址的记录,后续任何宽度的 load 都能精确匹配到实际存在数据依赖的那些字节。

构建完成后,生成的二进制文件位于 target/release/trace-slice(Windows 下为 trace-slice.exe)。

测试包含两部分:

测试 fixture 文件位于 tests/fixtures/ 目录,共 19 个 .trace 文件,涵盖各类指令组合和边界情况。

这是最重要的参数,用于指定向后切片的起点。可以多次指定,支持以下四种格式:

支持的寄存器名

通用寄存器 x0-x30w0-w30,栈指针 sp,零寄存器 xzrwzr,SIMD/FP 寄存器 v0-v31q0-q31d0-d31s0-s31,条件标志 nzcv

行号是 1-based

第一行是 1 不是 0。所有 @LINE 格式中的行号均从 1 开始计数。

多起点

可以多次使用 --from,结果是所有起点依赖链的并集。例如:

这会同时追踪 x0 和 x1 的来源,输出的切片包含两者所有相关指令的合集。

@LINE 自动回退

若指定行并未 DEF 该寄存器(例如该行是 USE 而非 DEF),工具自动回退到该行之前最近一次 DEF 该寄存器的行。这保证了即使行号不精确,也能找到正确的切片起点。

内存地址格式

支持带 0x 前缀(mem:0xbffff010@last)和不带前缀(mem:bffff010@last)两种写法,效果相同。

指定输出文件路径。

启用控制依赖追踪。

限定分析范围。

禁用值相等性剪枝,保留完整地址依赖链。

自验证模式。

输出各阶段耗时分解。

耗时信息输出到 stderr,示例:

示例 1:最简用法 -- 追踪 x0 的来源

stderr 输出示例:

示例 2:多起点 + 控制依赖

示例 3:限定范围 + 指定行号

功能说明

新增值相等性剪枝优化,默认启用。当 LOAD 指令从内存读取的值与对应 STORE 指令写入的值完全相等(纯值搬运,即 pass-through)时,自动跳过该 LOAD 的地址寄存器依赖,仅保留内存数据依赖(STORE→LOAD 链)。这大幅减少了 VMP 虚拟机中地址计算指令的噪音——指针递增、索引偏移、基址搬运等与算法逻辑无关的指令被精准剪除。

可通过 --no-prune 标志禁用,回退到完整切片。

原理

在 VMP 混淆的 trace 中,大量 LOAD 指令只是将值从一个内存位置搬运到寄存器,不涉及任何变换。例如虚拟栈的 push/pop 操作:STORE 将值写入栈地址,随后 LOAD 从同一地址原样读回。此时追踪 LOAD 的地址计算链(如何算出栈指针地址)对理解算法逻辑毫无意义。

值相等性剪枝在 Pass 1 扫描阶段判定每条 LOAD 是否为 pass-through:

安全性保障

实测效果(2400 万行 / 2.88GB trace)

关键算法指令验证(剪枝 vs 无剪枝):

剪枝结果是无剪枝结果的严格子集(comm -23 验证 0 行差异),不会引入任何新行。

[00:00:00 001][lib.so 0x100] [d2800108] 0x40000100: "mov x8, #5" => x8=0x5
[00:00:00 001][lib.so 0x104] [d2800149] 0x40000104: "mov x9, #10" => x9=0xa
[00:00:00 001][lib.so 0x108] [8b090108] 0x40000108: "add x8, x8, x9" x8=0x5 x9=0xa => x8=0xf
[00:00:00 001][lib.so 0x10c] [f9000be8] 0x4000010c: "str x8, [sp, #0x10]" ; mem[WRITE] abs=0xbffff010 x8=0xf sp=0xbffff000 => x8=0xf
[00:00:00 001][lib.so 0x110] [f9400be0] 0x40000110: "ldr x0, [sp, #0x10]" ; mem[READ] abs=0xbffff010 sp=0xbffff000 => x0=0xf
[00:00:00 001][lib.so 0x100] [d2800108] 0x40000100: "mov x8, #5" => x8=0x5
[00:00:00 001][lib.so 0x104] [d2800149] 0x40000104: "mov x9, #10" => x9=0xa
[00:00:00 001][lib.so 0x108] [8b090108] 0x40000108: "add x8, x8, x9" x8=0x5 x9=0xa => x8=0xf
[00:00:00 001][lib.so 0x10c] [f9000be8] 0x4000010c: "str x8, [sp, #0x10]" ; mem[WRITE] abs=0xbffff010 x8=0xf sp=0xbffff000 => x8=0xf
[00:00:00 001][lib.so 0x110] [f9400be0] 0x40000110: "ldr x0, [sp, #0x10]" ; mem[READ] abs=0xbffff010 sp=0xbffff000 => x0=0xf
[00:00:00 001][lib.so 0x106] [d280e1ef] 0x40000106: "mov x15, #999" => x15=0x3e7
[00:00:00 001][lib.so 0x106] [d280e1ef] 0x40000106: "mov x15, #999" => x15=0x3e7
1行: cmp x8, #0        -> 比较 x8 和 0,设置标志位 nzcv
2行: b.eq #0x40000200   -> 如果相等则跳转(控制流分支)
3行: mov x0, x9        -> 这行是否执行取决于 b.eq 的结果
1行: cmp x8, #0        -> 比较 x8 和 0,设置标志位 nzcv
2行: b.eq #0x40000200   -> 如果相等则跳转(控制流分支)
3行: mov x0, x9        -> 这行是否执行取决于 b.eq 的结果
[00:00:00 001][lib.so 0x108] [8b090108] 0x40000108: "add x8, x8, x9" x8=0x5 x9=0xa => x8=0xf
|              ||            | |        | |         | |               | |                |  |
|  时间戳      || 模块+偏移  | |指令编码| | PC 地址 | | 反汇编文本    | | 输入寄存器值   |  | 输出寄存器值
|              ||            | |        | |         | |               | |                |  |
+--------------++-----------+  +--------+ +---------+ +---------------+ +----------------+  +------------
     跳过            跳过        跳过        跳过          解析           仅 validate       箭头  仅 validate
[00:00:00 001][lib.so 0x108] [8b090108] 0x40000108: "add x8, x8, x9" x8=0x5 x9=0xa => x8=0xf
|              ||            | |        | |         | |               | |                |  |
|  时间戳      || 模块+偏移  | |指令编码| | PC 地址 | | 反汇编文本    | | 输入寄存器值   |  | 输出寄存器值
|              ||            | |        | |         | |               | |                |  |
+--------------++-----------+  +--------+ +---------+ +---------------+ +----------------+  +------------
     跳过            跳过        跳过        跳过          解析           仅 validate       箭头  仅 validate
字段 示例 工具是否解析 说明
时间戳 [00:00:00 001] 跳过 unidbg 固定格式前缀的一部分
模块+偏移 [lib.so 0x108] 跳过 unidbg 固定格式前缀的一部分
指令编码 [8b090108] 跳过 机器码十六进制
PC 地址 0x40000108: 跳过 运行时绝对地址
反汇编文本 "add x8, x8, x9" 解析 双引号包裹,工具从此提取助记符和操作数
输入寄存器值 x8=0x5 x9=0xa 仅 validate 模式 => 前的 reg=val 对
箭头 => 解析 区分有/无输出值的指令行
输出寄存器值 x8=0xf 仅 validate 模式 => 后的 reg=val 对
内存注解 ; mem[WRITE] abs=0xbffff010 解析 load/store 的内存绝对地址和读写方向
[00:00:00 001][lib.so 0x10c] [f9000be8] 0x4000010c: "str x8, [sp, #0x10]" ; mem[WRITE] abs=0xbffff010 x8=0xf sp=0xbffff000 => x8=0xf
[00:00:00 001][lib.so 0x10c] [f9000be8] 0x4000010c: "str x8, [sp, #0x10]" ; mem[WRITE] abs=0xbffff010 x8=0xf sp=0xbffff000 => x8=0xf
[00:00:00 001][lib.so 0x110] [f9400be0] 0x40000110: "ldr x0, [sp, #0x10]" ; mem[READ] abs=0xbffff010 sp=0xbffff000 => x0=0xf
[00:00:00 001][lib.so 0x110] [f9400be0] 0x40000110: "ldr x0, [sp, #0x10]" ; mem[READ] abs=0xbffff010 sp=0xbffff000 => x0=0xf
let skip = 40.min(line.len());  // 修改 40 为你的 trace 格式前缀长度
let skip = 40.min(line.len());  // 修改 40 为你的 trace 格式前缀长度
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"add x0, x1, x2" x1=0x1 x2=0x2 => x0=0x3
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"str x0, [sp]" ; mem[WRITE] abs=0xbffff000 x0=0x3 sp=0xbffff000 => x0=0x3
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"ldr x8, [sp]" ; mem[READ] abs=0xbffff000 sp=0xbffff000 => x8=0x3
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"add x0, x1, x2" x1=0x1 x2=0x2 => x0=0x3
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"str x0, [sp]" ; mem[WRITE] abs=0xbffff000 x0=0x3 sp=0xbffff000 => x0=0x3
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"ldr x8, [sp]" ; mem[READ] abs=0xbffff000 sp=0xbffff000 => x8=0x3
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"str x0, [sp]" x0=0x3 sp=0xbffff000 => x0=0x3
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"str x0, [sp]" x0=0x3 sp=0xbffff000 => x0=0x3
模块 文件 职责
types src/types.rs 核心类型定义:RegId、ParsedLine、Operand、MemOp 等
parser src/parser.rs 解析 trace 行文本,提取助记符、操作数、内存注解,生成 ParsedLine
insn_class src/insn_class.rs 将 150+ ARM64 助记符分类为 40 个 InsnClass 语义类别
def_use src/def_use.rs 根据指令类别确定每条指令的 DEF(写入)和 USE(读取)寄存器集合
scanner src/scanner.rs Pass 1 正向扫描,逐行构建依赖图,生成 ScanState
slicer src/slicer.rs BFS 反向切片标记相关行 + Pass 2 输出标记行
validate src/validate.rs 自验证模式:检查 DEF/USE 语义表与 trace 实际寄存器值的一致性
main src/main.rs CLI 入口,解析命令行参数,调用 lib 导出函数
处理行 指令 DEF USE 依赖查表结果 deps[行号] 状态更新
行 0 mov x8, #5 x8 (立即数) 无依赖 [] reg_last_def[x8] = 0
行 1 mov x9, #10 x9 (立即数) 无依赖 [] reg_last_def[x9] = 1
行 2 add x8, x8, x9 x8 x8, x9 x8->行0, x9->行1 [0, 1] reg_last_def[x8] = 2
行 3 str x8, [sp, #0x10] mem[0xbffff010] x8 x8->行2 [2] mem_last_def[0xbffff010] = 3
行 4 ldr x0, [sp, #0x10] x0 mem[0xbffff010] mem->行3 [3] reg_last_def[x0] = 4
git clone https://github.com/imj01y/trace-slice.git
cd /trace-slice
cargo build --release
git clone https://github.com/imj01y/trace-slice.git
cd /trace-slice
cargo build --release
cargo test
cargo test
依赖 版本 用途
clap 4.x 命令行参数解析(derive 模式)
smallvec 1.x 栈上小向量,减少堆分配
bitvec 1.x 位向量,用于标记切片行
rustc-hash 2.x FxHashMap,高速非加密哈希表
memchr 2.x SIMD 加速的字节和行搜索
memmap2 0.9.x 内存映射文件,实现零拷贝 I/O
anyhow 1.x 简洁的错误处理和传播
trace-slice <TRACE_FILE> --from <SPEC> [OPTIONS]
trace-slice <TRACE_FILE> --from <SPEC> [OPTIONS]
格式 含义 示例
reg:NAME@last 追踪寄存器在 trace 中最后一次被赋值的位置 --from reg:x0@last
reg:NAME@LINE 追踪寄存器在第 LINE 行(1-based)处的定义 --from reg:x8@5000
mem:ADDR@last 追踪内存地址最后一次被写入的位置 --from mem:0xbffff010@last
mem:ADDR@LINE 追踪内存地址在第 LINE 行处的写入 --from mem:0xbffff010@1234
trace-slice trace.txt --from reg:x0@last --from reg:x1@last
trace-slice trace.txt --from reg:x0@last --from reg:x1@last
trace-slice trace.txt --from reg:x0@last -o sliced.txt
trace-slice trace.txt --from reg:x0@last -o sliced.txt
# 仅数据依赖(默认)
trace-slice trace.txt --from reg:x0@last -o data_only.txt
 
# 数据 + 控制依赖
trace-slice trace.txt --from reg:x0@last --with-control-dep -o with_ctrl.txt
# 仅数据依赖(默认)
trace-slice trace.txt --from reg:x0@last -o data_only.txt
 
# 数据 + 控制依赖
trace-slice trace.txt --from reg:x0@last --with-control-dep -o with_ctrl.txt
# 只分析第 10000 到第 50000 行
trace-slice trace.txt --from reg:x0@last --start-seq 10000 --end-seq 50000
# 只分析第 10000 到第 50000 行
trace-slice trace.txt --from reg:x0@last --start-seq 10000 --end-seq 50000
# 默认模式(启用剪枝)
trace-slice trace.txt --from reg:x0@last -o sliced.txt
 
# 禁用剪枝,保留所有地址计算依赖
trace-slice trace.txt --from reg:x0@last --no-prune -o sliced_full.txt
# 默认模式(启用剪枝)
trace-slice trace.txt --from reg:x0@last -o sliced.txt
 
# 禁用剪枝,保留所有地址计算依赖
trace-slice trace.txt --from reg:x0@last --no-prune -o sliced_full.txt
trace-slice trace.txt --validate -o validation.txt
trace-slice trace.txt --validate -o validation.txt
trace-slice trace.txt --from reg:x0@last --profile

传播安全知识、拓宽行业人脉——看雪讲师团队等你加入!

最后于 22小时前 被j01y编辑 ,原因:
收藏
免费 48
支持
分享
最新回复 (13)
雪    币: 6
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
2
感谢分享
1天前
0
雪    币: 0
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
3
1
1天前
0
雪    币: 7
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
4
感谢分享
1天前
0
雪    币: 210
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
5
666
1天前
0
雪    币: 0
活跃值: (360)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
666666666666666666666
1天前
0
雪    币: 206
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
7
66666666
7小时前
0
雪    币: 1928
活跃值: (2228)
能力值: ( LV4,RANK:40 )
在线值:
发帖
回帖
粉丝
8
我去感谢分享
5小时前
0
雪    币: 104
活跃值: (7737)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
9
tql
3小时前
0
雪    币: 0
活跃值: (1511)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
10
666
3小时前
0
雪    币: 212
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
11
666
2小时前
0
雪    币: 0
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
12
1111
1小时前
0
雪    币: 260
活跃值: (450)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
13
1111
1小时前
0
雪    币: 51
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
14
tql
1小时前
0
游客
登录 | 注册 方可回帖
返回