|
学习本章内容前请先把握上一章节知识(不把握问题也不是很大,直接拿程序走人)
红警2秒杀原理剖析干货级讲解和专用修改器实现
https://www.52pojie.cn/thread-937873-1-1.html
(出处: 吾爱破解论坛)
前言
不搞前言什么什么的了,直接开始本章内容。

正文
也许有部门人有分析过红警2,也许也有人看到下面这种代码,

在OD调试的时间,会有很多字符串的提示,看着对程序的分析很有帮助,跟进CALL里如下图

对,就直接RETN了,什么也没有。这个就是被阉割的调试输出,本章节将围绕开启调试功能举行深入展开。

我们以这个CALL为例,可以看到CALL的下面有ADD ESP,0x4之类的,而且CALL之前没有ECX EDX之类的操作,这个就是典型的__cdecl调用约定的特征。
啥是佩奇,不对,啥是__cdecl?__cdecl是一种常见于C语言和C++编写的程序里的调用约定,是种默认的调用约定。他的伪代码如下
[Asm] 纯文本查看 复制代码fun: retnmain: push 参数3 push 参数2 push 参数1 call fun add esp,4*3 retn
可以看到,这种调用约定调用者在调用完成后,必须负责规复栈指针(ESP寄存器)。遵循谁调用谁清理原则,这种调用的上风是什么?
在Windows API中大多数采用__stdcall(后面会介绍),但是少数的也会采用__cdecl约定,例如wsprintf可以或许支持不固定个数的参数,栈允许的情况下能支持无限多个,这自然需要归功于__cdecl这种调用机制的功劳。除别的,实在还有__stdcall __fastcall __pascal __thiscall等调用约定。
__stdcall比较常见的调用约定,被大多数程序所支持,调用者无需自己清理栈,伪代码如下
[Asm] 纯文本查看 复制代码fun: retn 4*3main: push 参数3 push 参数2 push 参数1 call fun retn
__fastcall在Windows中底层会采用此调用约定,因为顾名思义,因为使用ECX和EDX寄存器性能较其使用栈(内存寻址)更快,他的伪代码如下
[Asm] 纯文本查看 复制代码fun: retn 4main: push 参数3 mov edx,参数2 mov ecx,参数1 call fun retn
__pascal这个是pascal语言所采用的调用方式,他的调用顺序是从左到右,而__stdcall是从右到左,其他方面并没有任何差别,他的伪代码如下
[Asm] 纯文本查看 复制代码fun: retn 4*3main: push 参数1 push 参数2 push 参数3 call fun retn
delphi固然使用pascal语法,但从本坛的很多逆向资料来看,调用方式靠近于__fastcall,把参数会压入EAX和ECX寄存器。
__thiscall是C++ CLASS的调用方式,把*this会放进ECX寄存器,类似于__fastcall的__stdcall调用约定,较高性能的一种调用约定,他的伪代码如下
[Asm] 纯文本查看 复制代码fun: retn 4*2main: push 参数2 push 参数1 lea ecx,[this] call fun retn
那全部的调用约定原理都已经学习过了,我们接下来就做补丁吧,先按照上次课程所学的窗口消息(SetWindowsHookEx)的方式注入游戏。然后用今天我们所学的,__cdecl调用约定来重新实现个调试输出的补丁,而且会使用的上个章节提及但并没有演示的inline hook部门。

代码写完大概就是这个样子
[C] 纯文本查看 复制代码void dbgOut(DWORD p){//因为C语言里默认的调用方式__cdecl,所以可以不用形貌词 DWORD *d=(DWORD*)((DWORD)&p-4);//指针概念,p是进入的参数,&p是他的参数栈的地址,&p-4就是返回地址 if(!strstr(d[1],"Theme")){//过滤掉Theme消息,太多了 sprintf(&buf[0x200],d[1],d[2],d[3],d[4],d[5],d[6],d[7],d[8],d[9],d[10]);//sprintf也是__cdecl调用约定,所以我输入多少个参数和他这个API无关,始终能保持栈的平衡 sprintf(buf,"[Ra2DbgOut] %08X %s",d[0],&buf[0x200]);//加一个前缀,显得更酷炫,而且把返回地址显示出来 OutputDebugString(buf); //输出调试信息,可以或许在dbgView中举行查看 }}
接下来我们来耍一下吧

上图可以看到初始化信息,人和电脑选择的国家

上图可以看到终极的比分,和下面这个图上是一样的

然后我们可以实验建造,停息等操作

调试信息中能看到触发变乱,而且成功得到目标代码地址,然后一个调试器过去

接下来怎么做大家都懂的,
讲的比较粗,有问题可以在下面留言提问,我不一定会回答
Ra2DbgOut.zip
13.51 KB, 下载次数: 222, 下载积分: 吾爱币 -1 CB
来源:http://www.12558.net
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作! |
本帖子中包含更多资源
您需要 登录 才可以下载或查看,没有帐号?立即注册
x
|