Skip to content

Latest commit

 

History

History
488 lines (352 loc) · 9.98 KB

File metadata and controls

488 lines (352 loc) · 9.98 KB

通过 9.9.12-25493 wrapper.node 反推签名函数名

目标

从已知可用的 QQ 版本 9.9.12-25493(偏移值 0xA996E0)中找到签名函数的真实名称。

准备工作

1. 获取 9.9.12-25493 的 wrapper.node

方式 A: 如果已安装旧版本 QQ

路径: C:\Program Files\Tencent\QQ\resources\app.asar.unpacked\node_modules\wrapper.node

方式 B: 下载旧版本

  • 从 QQ 官网下载历史版本
  • 或从网盘/镜像站获取
  • 安装后提取 wrapper.node 文件

方式 C: 使用备份

  • 检查是否有系统备份或快照
  • 从备份中提取 wrapper.node

2. 准备工具


方法一:使用 x64dbg 查找(最直接)

Step 1: 加载 wrapper.node

1. 打开 x64dbg (x64 版本)
2. 文件 → 打开
3. 选择 9.9.12-25493 的 wrapper.node
4. 等待加载完成

Step 2: 查看模块基址

加载后,记录模块基址,例如:180000000

Step 3: 计算函数地址

已知偏移值: 0xA996E0
模块基址: 0x180000000 (示例)

函数地址 = 基址 + 偏移
         = 0x180000000 + 0xA996E0
         = 0x180A996E0

使用 Windows 计算器(程序员模式)进行计算。

Step 4: 跳转到函数地址

1. 在 x64dbg 中按 Ctrl+G
2. 输入计算后的地址: 180A996E0
3. 按回车跳转

Step 5: 查看函数信息

到达地址后:

方式 A: 查看当前位置

  • 右键 → 在符号中跟随
  • 或右键 → 标签 → 查看函数名

方式 B: 查看导出表

  1. Ctrl+E 打开导出表
  2. 查找地址为 180A996E0 的函数
  3. 记录函数名称

方式 C: 查看反汇编窗口顶部

  • 函数开头通常会显示函数名或标签
  • 例如: wrapper.?FunctionName@@...sub_A996E0

Step 6: 分析函数特征

验证这是签名函数:

; 应该看到类似这样的代码:
wrapper+A996E0:
48 89 5C 24 08    mov [rsp+8], rbx       ; 保存寄存器
48 89 6C 24 10    mov [rsp+10], rbp
48 89 74 24 18    mov [rsp+18], rsi
57                push rdi
48 83 EC 50       sub rsp, 50             ; 分配栈空间

; 参数处理
48 8B F1          mov rsi, rcx            ; cmd (第1个参数)
48 8B EA          mov rbp, rdx            ; src (第2个参数)
4C 8B F0          mov r14, r8             ; src_len (第3个参数)
44 8B F9          mov r15d, r9d           ; seq (第4个参数)

确认特征:

  • ✅ 有 5 个参数的使用
  • ✅ 函数体较大(数百字节)
  • ✅ 包含复杂的位运算和循环
  • ✅ 操作字节数组

方法二:使用 dumpbin 命令行工具

前提条件

安装了 Visual Studio 或 Visual Studio Build Tools

操作步骤

  1. 打开 Visual Studio Developer Command Prompt

    开始菜单 → Visual Studio → Developer Command Prompt
    
  2. 运行 dumpbin

    cd "路径\到\wrapper.node所在目录"
    dumpbin /EXPORTS wrapper.node > exports.txt
  3. 分析输出文件

    打开 exports.txt,查找 RVA 为 A996E0 的导出:

    ordinal hint RVA      name
    
          1    0 00001000 node_register_module
          2    1 00A996E0 ?可能的函数名?
    
  4. 记录函数名

    找到对应 RVA 的函数名称


方法三:使用 IDA Pro 分析(专业方法)

Step 1: 加载文件

1. 打开 IDA Pro (64-bit)
2. File → Open
3. 选择 9.9.12-25493 的 wrapper.node
4. 选择 PE64 格式
5. 等待自动分析完成

Step 2: 跳转到偏移地址

1. 按 G (跳转)
2. 输入地址: imagebase+A996E0
   或直接输入: .text:00000000A996E0
3. 按回车

Step 3: 查看函数名

到达地址后:

查看函数窗口:

  1. ViewOpen subviewsFunctions
  2. 找到偏移为 A996E0 的函数
  3. 查看函数名列

查看反编译代码:

  1. 在函数地址处按 F5 反编译
  2. 查看函数签名和名称
// 可能看到类似这样的代码:
__int64 __fastcall sign_function_name(
    const char *cmd,
    const unsigned char *src,
    unsigned __int64 src_len,
    int seq,
    unsigned char *result)
{
    // 函数实现
}

Step 4: 查看导出表

1. View → Open subviews → Exports
2. 或按 Shift+F7
3. 查找 RVA 为 A996E0 的导出
4. 记录函数名

方法四:使用 Python 脚本自动化

安装依赖

pip install pefile

创建分析脚本

创建文件 find_sign_function.py:

import pefile
import sys

# wrapper.node 文件路径
wrapper_path = r"C:\path\to\9.9.12-25493\wrapper.node"

# 已知的偏移值
TARGET_OFFSET = 0xA996E0

try:
    pe = pefile.PE(wrapper_path)
    
    print("=" * 70)
    print("分析 wrapper.node (9.9.12-25493)")
    print("=" * 70)
    print(f"\n目标偏移值: 0x{TARGET_OFFSET:X}")
    print()
    
    # 查找导出函数
    if hasattr(pe, 'DIRECTORY_ENTRY_EXPORT'):
        print("导出函数列表:")
        print("-" * 70)
        print(f"{'序号':<6} {'RVA':<12} {'名称'}")
        print("-" * 70)
        
        found = False
        for export in pe.DIRECTORY_ENTRY_EXPORT.symbols:
            ordinal = export.ordinal
            address = export.address
            name = export.name.decode() if export.name else f"Ordinal_{ordinal}"
            
            # 检查是否是目标函数
            if address == TARGET_OFFSET:
                print(f"{ordinal:<6} 0x{address:08X}  {name}  ⭐⭐⭐ 找到了!")
                found = True
            else:
                print(f"{ordinal:<6} 0x{address:08X}  {name}")
        
        if found:
            print()
            print("=" * 70)
            print("✅ 成功找到偏移值对应的函数!")
            print("=" * 70)
        else:
            print()
            print("⚠️  未在导出表中找到该偏移值")
            print("可能是内部函数(未导出)")
    else:
        print("❌ 未找到导出表")
    
except Exception as e:
    print(f"❌ 错误: {e}")
    sys.exit(1)

运行脚本

python find_sign_function.py

可能的结果

情况 1: 找到明确的函数名

示例:

序号  RVA         名称
5     0x00A996E0  sign
或
5     0x00A996E0  createSign
或
5     0x00A996E0  doSignature

下一步:

  • 记录函数名称
  • 验证函数签名(5个参数)
  • 在 9.9.20 版本中查找同名函数

情况 2: C++ Mangled Name

示例:

5     0x00A996E0  ?sign@WrapperClass@@QEAAHPEBDPEBEKHPEAE@Z

解码 Mangled Name:

使用在线工具:https://demangler.com/

或使用命令行:

undname "?sign@WrapperClass@@QEAAHPEBDPEBEKHPEAE@Z"

解码后可能得到:

public: int __cdecl WrapperClass::sign(char const *, unsigned char const *, unsigned __int64, int, unsigned char *)

情况 3: 仅序号导出

示例:

5     0x00A996E0  Ordinal_5

说明:

  • 函数未导出名称,只有序号
  • 需要通过序号在 9.9.20 中查找
  • 或通过汇编代码特征匹配

情况 4: 未在导出表中

说明:

  • 函数可能是内部函数(static)
  • 未被导出到 DLL 外部
  • 只能通过特征码匹配

解决方案:

  • 记录函数的汇编特征码
  • 在 9.9.20 中搜索相同的特征码
  • 或使用 BinDiff 等工具对比两个版本

应用到 9.9.20 版本

如果找到了函数名

  1. 在 9.9.20 的 wrapper.node 中查找同名函数

    - 使用 x64dbg 打开 9.9.20 的 wrapper.node
    - 按 Ctrl+E 查看导出表
    - 搜索相同的函数名
    - 记录新版本中的偏移值
    
  2. 如果函数名相同但偏移不同

    - 这是正常的(版本更新导致地址变化)
    - 使用新版本的偏移值
    - 更新 sign.cpp 中的 addrMap
    
  3. 如果找不到同名函数

    - 函数可能被重命名
    - 或被内联/优化
    - 需要通过特征码匹配
    

如果是 Mangled Name

  1. 解码后在 9.9.20 中查找

    - 查找相同的类和方法名
    - 注意参数类型可能略有变化
    

如果只有序号

  1. 在 9.9.20 中查找相同序号

    - 序号通常保持一致
    - 但不是绝对的
    - 需要验证函数特征
    

特征码匹配方法(高级)

如果函数未导出或名称改变,可以使用特征码:

提取特征码

在 x64dbg 中:

  1. 跳转到 9.9.12-25493 的函数地址 (0xA996E0)
  2. 选择函数开头的 16-32 字节
  3. 右键 → 二进制复制选择
  4. 记录字节序列,例如:
    48 89 5C 24 08 48 89 6C 24 10 48 89 74 24 18 57 48 83 EC 50
    

在 9.9.20 中搜索

  1. 打开 9.9.20 的 wrapper.node
  2. 右键 → 搜索序列
  3. 输入特征字节码
  4. 查找匹配项
  5. 记录新的偏移值

记录模板

找到函数后,请填写以下信息:

=== 签名函数信息 ===

9.9.12-25493 版本:
  函数名称: [填写]
  偏移值: 0xA996E0
  导出序号: [填写]
  
9.9.20-37051 版本:
  函数名称: [填写]
  偏移值: [待确定]
  导出序号: [填写]
  
函数特征码:
  [前16字节的十六进制]
  
验证状态:
  [ ] 函数名匹配
  [ ] 参数数量正确 (5个)
  [ ] 特征码相似
  [ ] 测试通过

快速操作清单

如果你有 9.9.12-25493 的 wrapper.node

立即执行:

  1. 用 x64dbg 打开 9.9.12-25493 的 wrapper.node
  2. 按 Ctrl+E 查看导出表
  3. 查找 RVA 为 A996E0 的函数
  4. 记录函数名
  5. 告诉我结果!

如果没有旧版本

⏭️ 替代方案:

  1. 直接在 9.9.20 中测试已知偏移值
  2. 使用试错法找到正确偏移
  3. 或等待社区分享 9.9.20 的信息

提示

💡 最快的方法:

  • 如果能访问 9.9.12 版本,用 x64dbg 的 Ctrl+E 查看导出表最直接
  • 只需要 1-2 分钟就能找到函数名

💡 如果找到函数名:

  • 立即分享给我
  • 我们可以在 9.9.20 中快速定位
  • 提高成功率!

喵~ 准备好了就开始吧!🐾