新剑侠情缘辅助编写

新剑侠情缘——编写无限内力辅助

工具:Exeinfo PE、CheatEngine、OllyDbg、VS2019

游戏:新剑侠情缘之梦里回眸2.0(https://tieba.baidu.com/p/2715359831?red_tag=1716562167剑侠情缘吧内下载)

  • 拖入PEiD等工具查看是什么语言编写,是否带壳
    在这里插入图片描述
    在这里插入图片描述

  • 查看导入表,查看到一个Sword.dll,看函数英文名字,像是绘图、读档存档、跑步等函数,猜测攻击等函数可能也在里面

在这里插入图片描述

1 内力

1.1 CE附加查找内力有关地址

  • 先随意释放技能,内力会慢慢回复(看到这个界面是不是很亲切,玩过的亲们)
    在这里插入图片描述

  • 下面需要注意的是,使用CE查看是谁访问了这个地址时是附加查看的(坑1,必须回到游戏中运行一下,才有显示),再使用OD附加时需要用CE再打开一次才可以用附加(坑2,游戏不能窗口化,每次都要重新调分辨率)

在这里插入图片描述

  • OD中单步分析,发现疑似 ‘内力恢复’;
    在这里插入图片描述

    • 其中 [ECX] 应该是一个全局变量,所以通过一个全局变量,最终会找到 ‘当前内力值地址’;猜测下面可能还会比较 最大内力值,用以判断是否继续恢复内力值

在这里插入图片描述

  • 单步跟出,发现只是在恢复内力,去下一个地址里查看,发现几乎同样的操作;又看见SendMessage字样,猜测可能是在给窗口发消息?

在这里插入图片描述

  • 好吧,最后试了下,没找到,剩下的两个地址是把恢复的内力值更新显示到人物属性面板上

1.2 寻找消耗内力的地址

  • 上面的步骤没有找到消耗内力的地址,基本全是恢复内力的操作(因为站着不动,会慢慢恢复内力);这次手快一点,按了下《洗髓经》马上转出,看截图,好像找到了消耗内力的地址,比上图多出两个未知的地址:

在这里插入图片描述

  • OD附加,在0042EEF6处下断,恢复游戏运行并回到游戏中,没断下!!!因为之前下的断,都是恢复内力的,一回到游戏中就断下了,所以这次感觉终于找到地方了,释放个技能试试会不会断下

在这里插入图片描述

- hhhh,终于断下了,如上图,这个可恶的分辨率问题(坑2)。。。OD中分析吧
1.2.1 分析内力消耗函数
  • 直接先分析断点处,找到了释放技能时消耗位置

在这里插入图片描述

  • (因为更改这个游戏很简单,直接更改游戏内的配置文件即可:一些独孤剑本来不会的技能就是更改配置文件学的,比如洗髓经。所以在释放技能时肯定会读取技能的配置文件)向上层函数回溯,确实发现寄存器中有读取的文件名

在这里插入图片描述

1.2.2 编写辅助dll
  • 晚上睡觉前想了下:游戏修改起来很简单,如果不通过逆向,仅修改 .ini 文件里的内容即可

在这里插入图片描述

  • 其实从游戏的存档读档功能就可以联想到:读取文档中的内容到游戏;

    • 所以在技能释放,也是先读取如上图中的 .ini文件,获取该技能的内力消耗值 [edi+0x174],扯远了,回到主题
  • 所以要怎么写一个辅助呢 → 写一个怎样的dll注入呢 → 什么条件触发我写的辅助呢?

    • 游戏中释放技能是按 鼠标右键,切换技能是 键盘按键A~G;所以是不是可以更改它的窗口回调函数,在触发这两类消息时,把当前内力值设置为最大内力值(为了省事,选择鼠标事件吧)
  • 用VS内的工具Spy++,查找剑侠情缘的窗口标题和类名

  • VS -> 选择 MFC 动态链接库 -> 在DLL类型中选择 ‘ 静态链接到 MFC 的常规DLL ’

    • 主要逻辑:自己写的回调函数里响应鼠标右键(释放技能)消息
// 唯一的 CSwordCheatApp 对象

CSwordCheatApp theApp;

// --------------------------------------------------------------------------- //
HWND g_hWnd;      // 接收剑侠情缘窗口句柄
WNDPROC g_OldProc;    // 旧的窗口回调函数

PDWORD g_MagicNow = (PDWORD)0x004F1A40;    // 当前内力值
PDWORD g_MagicMax = (PDWORD)0x004F1A44;      // 最大内力值


// 自己的回调函数
LRESULT CALLBACK MyWindowProc(
  _In_ HWND hWnd,
  _In_ UINT Msg,
  _In_ WPARAM wParam,
  _In_ LPARAM lParam)
{
  // 1. 判断消息类型
  if (Msg == WM_RBUTTONDOWN)
  {
    OutputDebugString(L"释放技能");
    // 通过一个全局变量找到内力值相关的地址
    //  0042E007 | > \8 > mov eax, dword ptr ds : [ecx]            eax = 1
    //  0042E009 | .  8 > mov edx, eax                 edx = 1      
    //  0042E00B | .C > shl edx, 0x5                 edx = 32
    //  0042E00E | .  0 > add edx, eax                             edx = 33
    //  0042E010 | .  8 > lea edx, dword ptr ds : [eax + edx * 4]  edx = 1+33*4(133)
    //  0042E013 | .  8 > lea edx, dword ptr ds : [eax + edx * 4]  edx = 1+133*4(533)
    //  0042E016 | .  8 > lea eax, dword ptr ds : [eax + edx * 2]  eax = 1+533*2(1067)
    //  0042E019 | .C > shl eax, 0x4                 eax = 1067*16(17072)
    //  0042E01C | .  8 > mov edx, dword ptr ds : [eax + 0x4ED794] ;  edx 是最大内力值 004F1A44
    //  0042E022 | .  8 > mov edi, dword ptr ds : [eax + 0x4ED790] ;  edi 当前内力值   004F1A40
    * g_MagicNow = *g_MagicMax;
  }

  // 执行之前的窗口回调函数
  return CallWindowProc(g_OldProc, hWnd, Msg, wParam, lParam);
}

// CSwordCheatApp 初始化         <----- 这里当作主函数

BOOL CSwordCheatApp::InitInstance()
{
  CWinApp::InitInstance();

  // 1. 通过查找窗口,获取窗口句柄
  g_hWnd = ::FindWindow(L"Sword Class", L"Sword Window");
  if (NULL == g_hWnd)
  {
    OutputDebugString(L"没有找到剑侠情缘窗口!");
    return FALSE;
  }

  // 2. 设置窗口回调函数(SetWindowLong设置新的窗口回调,返回值是老的窗口回调函数)
  g_OldProc = (WNDPROC)SetWindowLong(g_hWnd, GWL_WNDPROC, (LONG)MyWindowProc);
  if (NULL == g_OldProc)
  {
    OutputDebugString(L"设置窗口回调函数失败!");
    return FALSE;
  }

  return TRUE;
}

  • 效果gif
    在这里插入图片描述

总结:童年不再有,,,这个15年前的游戏逆向起来还是比较简单的,比较适合我这样的新手分析;dll编写思路大家可以尽情发挥,做技术没有标准答案;兴趣和坚持才能一直走下去,共勉!

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值