利用AOB通过特征码动态劫持寄存器指向的地址 - Terraria背包监控实现

利用AOB通过特征码动态劫持寄存器指向的地址 - Terraria背包监控实现

原文章来自https://www.cnblogs.com/LynCandy/p/18825333


技术背景

动态寄存器劫持原理

寄存器级内存寻址的动态拦截技术,通过特征码定位关键指令流,建立符号化内存锚点(Symbol Anchor),实现寄存器指向地址的运行时重定向。相较于传统基址+偏移量模式,具有以下核心优势:

  1. 动态内存适应
    通过aobscan特征签名匹配,规避ASLR和动态内存分配带来的基址失效问题

  2. 寄存器上下文捕获
    在指令执行现场直接劫持寄存器值,避免多层指针追朔的地址稳定性风险

  3. 热更新支持
    通过registersymbol声明动态符号,支持运行时内存布局变更的热适应

  4. 跨版本兼容
    特征码扫描机制可兼容不同编译版本,减少游戏更新后的维护成本

实现步骤

1. 指令流定位

; Terraria物品数量更新指令原型
0045F2D1 - 01 81 B4000000  - add [ecx+000000B4],eax

通过Cheat Engine的Find out what writes to this address功能定位物品数量更新点,使用AOB签名:
01 81 B4 00 00 00 80 7D 15

2. 内存注入框架

aobscan(INJECT, 01 81 B4 00 00 00 80 7D 15) // 特征码模糊匹配
alloc(newmem, $1000)                        // 分配代码洞穴
alloc(vinv0item, 8)                         // 声明物品数量指针容器
registersymbol(vinv0item)                   // 注册动态符号

3. 寄存器劫持逻辑

newmem:
  add [ecx+000000B4],eax   ; 原始指令恢复
  mov [vinv0item], ecx      ; 捕获ECX寄存器值
  add [vinv0item], B4       ; 计算实际物品数量地址
  jmp return

code:
  add [ecx+000000B4],eax   ; 备用执行路径
  jmp return

INJECT:
  jmp newmem                // 劫持执行流
  nop                       // 指令对齐

实时监控实现

内存指针维护

registersymbol(vinv0item)  // 声明为全局符号

通过寄存器符号动态绑定,实现:

  1. CE脚本内vinv0item变量的地址热更新
  2. 外部调试器可通过vinv0item符号直接访问
  3. 多线程环境下的地址一致性保证

数据流验证

  1. 执行物品数量变动操作
  2. 观察vinv0item指针值变化(CE内存查看器)
  3. 验证[vinv0item]指向地址的数值实时性

优势对比分析

维度传统基址模式AOB寄存器劫持
内存稳定性依赖固定偏移链动态寄存器上下文捕获
更新成本需重新追朔指针链特征码自动适配
执行效率多层指针解引用寄存器直接操作
多版本支持需适配每个版本特征匹配自动定位
注入稳定性易受内存布局变化影响指令流级精准拦截

注意事项

  1. 寄存器生命周期
    确保在ECX有效期内完成劫持操作,避免使用易失性寄存器

  2. 指令对齐
    使用nop填充被覆盖的原始指令空间,防止执行流错位

  3. 符号管理
    通过registersymbol/unregistersymbol规范符号生命周期

  4. 内存释放
    dealloc需与alloc严格对应,防止内存泄漏

本方案已在Terraria 1.4.4.9实测通过,可稳定捕获物品数量变更事件

[ENABLE]

aobscan(INJECT,01 81 B4 00 00 00 80 7D 15)
alloc(newmem,$1000)

alloc(vinv0item, 8)
registersymbol(vinv0item)

label(code)
label(return)

newmem:
  add [ecx+000000B4],eax
  mov [vinv0item], ecx
  add [vinv0item], B4
  jmp return

code:
  add [ecx+000000B4],eax
  jmp return

INJECT:
  jmp newmem
  nop
return:
registersymbol(INJECT)

[DISABLE]

INJECT:
  db 01 81 B4 00 00 00

dealloc(vinv0item)
unregistersymbol(vinv0item)

unregistersymbol(INJECT)
dealloc(newmem)

{
// ORIGINAL CODE - INJECTION POINT: Terraria.Player::GetItem_FillIntoOccupiedSlot+107

Terraria.Player::GetItem_FillIntoOccupiedSlot+DB: 8B 96 D8 00 00 00  - mov edx,[esi+000000D8]
Terraria.Player::GetItem_FillIntoOccupiedSlot+E1: 3B 5A 04           - cmp ebx,[edx+04]
Terraria.Player::GetItem_FillIntoOccupiedSlot+E4: 0F 83 52 01 00 00  - jae Terraria.Player::GetItem_FillIntoOccupiedSlot+23C
Terraria.Player::GetItem_FillIntoOccupiedSlot+EA: 8B 4C 9A 08        - mov ecx,[edx+ebx*4+08]
Terraria.Player::GetItem_FillIntoOccupiedSlot+EE: 8B B9 B4 00 00 00  - mov edi,[ecx+000000B4]
Terraria.Player::GetItem_FillIntoOccupiedSlot+F4: 03 C7              - add eax,edi
Terraria.Player::GetItem_FillIntoOccupiedSlot+F6: 8B 91 B8 00 00 00  - mov edx,[ecx+000000B8]
Terraria.Player::GetItem_FillIntoOccupiedSlot+FC: 3B C2              - cmp eax,edx
Terraria.Player::GetItem_FillIntoOccupiedSlot+FE: 0F 8F 7F 00 00 00  - jg Terraria.Player::GetItem_FillIntoOccupiedSlot+183
Terraria.Player::GetItem_FillIntoOccupiedSlot+104: 8B 45 EC           - mov eax,[ebp-14]
// ---------- INJECTING HERE ----------
Terraria.Player::GetItem_FillIntoOccupiedSlot+107: 01 81 B4 00 00 00  - add [ecx+000000B4],eax
// ---------- DONE INJECTING  ----------
Terraria.Player::GetItem_FillIntoOccupiedSlot+10D: 80 7D 15 00        - cmp byte ptr [ebp+15],00
Terraria.Player::GetItem_FillIntoOccupiedSlot+111: 75 1E              - jne Terraria.Player::GetItem_FillIntoOccupiedSlot+131
Terraria.Player::GetItem_FillIntoOccupiedSlot+113: 8B 45 0C           - mov eax,[ebp+0C]
Terraria.Player::GetItem_FillIntoOccupiedSlot+116: 8B 80 B4 00 00 00  - mov eax,[eax+000000B4]
Terraria.Player::GetItem_FillIntoOccupiedSlot+11C: 89 45 EC           - mov [ebp-14],eax
Terraria.Player::GetItem_FillIntoOccupiedSlot+11F: 50                 - push eax
Terraria.Player::GetItem_FillIntoOccupiedSlot+120: 6A 00              - push 00
Terraria.Player::GetItem_FillIntoOccupiedSlot+122: 0F B6 45 14        - movzx eax,byte ptr [ebp+14]
Terraria.Player::GetItem_FillIntoOccupiedSlot+126: 50                 - push eax
Terraria.Player::GetItem_FillIntoOccupiedSlot+127: 8B 55 18           - mov edx,[ebp+18]
}

转载自https://www.cnblogs.com/LynCandy/p/18825333

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值