CSGO 服务端扩展插件开发记录之"DropClientReason"(1)
2014-11-24 15:49
357 查看
最近开始接触到了CSGO这款游戏,还是老套路,就是想千方百计的从里面增添新的游戏功能,当然刚开始想做到游刃有余是有点困难,
跟之前做CS1.6的第三方开发一样,都得自己慢慢的摸索过来,纵然CSGO所使用的游戏引擎与CS1.6的引擎不一样,但是从1.6学习到的
一些技能(暂且就称呼为技能吧^^),还是可以在CSGO上运用的.好了,废话不说了,马上进入正题.
今天的目标就是"Dropped K.K.Lv from server: Disconnect",没错,主要就是围绕这句内容来开展工作,首先得弄清楚这句话从哪来出来,
从以前经验告诉我,这肯定是在游戏引擎里的(CSGO使用的是Source,中文称之为"起源"引擎,这个可以通过百度或谷歌查一下就可以知道了),
所以我就通过IDA,打开了CSGO服务端文件目录下的引擎动态库engine.dll(我的目录是E:\steamcmd740server\bin\),这是windows平台下的,
linux平台的是engine.so,iMac平台下的是engine.dylib,我是把这三个平台的引擎动态库都打开等IDA把以上三个文件都分析完后,我试图从中查找
"Dropped K.K.Lv from server: Disconnect"这句话,当然,如果直接查找这句话,是肯定打不到的,因为"K.K.Lv"是用户名字,所以得转一下,
改成""Dropped %s from server: Disconnect",结果当然是可以肯定的,会看到类似以下信息
此时我们只需要双击这一行,就会看到以下的界面
按照提示,再跳转到函数体就如下
此时我们可以通过IDA的"F5"功能,就可以看到以下画面
把代码复制出来,这样显得方便一点
简单分析一下,此函数的参数应该只有一个,并且是一个类成员函数, 当中的int this应该是一个指向类的一个指针,
所以实际参数只有int a2,而我们又可以从"ConMsg("Dropped %s from server: %s\n", v7, a2);"这行中猜想到
a2肯定是一个指向文本信息的指针(类似char *, const char *),接着有以上相同的方法,分别在linux版本与iMac版本
上查找相应的函数,我在linux与iMac上都找到了以下函数
linux:
iMac:
所以就把此函数名定义为"PerformDisconnection"
至此,确定整个函数为void CBaseClient::PerformDisconnection(const char *reason);
接下来,就是要勾这个函数了,在SourceMod(同样可以百度或谷歌一下哈^^,我这里就不解释太多了)中有封装了一套框架,
可以直接勾取函数,我们只需要通过寻找正确的特征码,然后再通过特征码定位到函数地址,这样就可以直接勾取函数了,为何
要用特征码的方式,而不直接采用动态库基地址加偏移的方式定位函数地址,主要是因为游戏会经常更新,如果采用基地址加偏移
的方式,如果游戏的引擎做更新之后,那么就得更换偏移了,而使用特征码的话,只要函数体不做变化,就算动态库的其他代码更新了,
此函数的特征码还是不会变的(好像漏了编译器的情况了^^,是的,据了解,更换编译器的情况下,特征码也是会变的,但是一般一
个游戏引擎,更换编译器的情况不会太频繁),所以这就是为什么采用特征码的方式来寻址.接来就是查找特征码了,如下:
通过整理一些跳转的情况,就能得到以下内容
最后合并就成这样了
55 8B EC 53 56 8B F1 57 8B 4E ? E8 ? ? ? ? 56 B9 ? ? ? ? E8 ? ? ? ? 6A
最后就验证一下这个特征码是否正确,可用,唯一,可以通过以下方式
就可以得到如下的内容
由于SourceMod框架的需求,所以我们得把特征码中的"?"转换为"2A",然后再加添"\x"
最终为:"\x55\x8B\xEC\x53\x56\x8B\xF1\x57\x8B\x4E\x2A\xE8\x2A\x2A\x2A\x2A\x56\xB9\x2A\x2A\x2A\x2A\xE8\x2A\x2A\x2A\x2A\x6A"
下面就得开始C++上的工作喇
,将会在下篇讲解
跟之前做CS1.6的第三方开发一样,都得自己慢慢的摸索过来,纵然CSGO所使用的游戏引擎与CS1.6的引擎不一样,但是从1.6学习到的
一些技能(暂且就称呼为技能吧^^),还是可以在CSGO上运用的.好了,废话不说了,马上进入正题.
今天的目标就是"Dropped K.K.Lv from server: Disconnect",没错,主要就是围绕这句内容来开展工作,首先得弄清楚这句话从哪来出来,
从以前经验告诉我,这肯定是在游戏引擎里的(CSGO使用的是Source,中文称之为"起源"引擎,这个可以通过百度或谷歌查一下就可以知道了),
所以我就通过IDA,打开了CSGO服务端文件目录下的引擎动态库engine.dll(我的目录是E:\steamcmd740server\bin\),这是windows平台下的,
linux平台的是engine.so,iMac平台下的是engine.dylib,我是把这三个平台的引擎动态库都打开等IDA把以上三个文件都分析完后,我试图从中查找
"Dropped K.K.Lv from server: Disconnect"这句话,当然,如果直接查找这句话,是肯定打不到的,因为"K.K.Lv"是用户名字,所以得转一下,
改成""Dropped %s from server: Disconnect",结果当然是可以肯定的,会看到类似以下信息
此时我们只需要双击这一行,就会看到以下的界面
按照提示,再跳转到函数体就如下
此时我们可以通过IDA的"F5"功能,就可以看到以下画面
把代码复制出来,这样显得方便一点
int __thiscall sub_101A3050(int this, int a2) { int v2; // esi@1 int result; // eax@1 int v4; // ebx@2 int v5; // edi@3 int v6; // eax@5 int v7; // eax@10 int v8; // ecx@11 int v9; // eax@13 int v10; // ecx@14 v2 = this; sub_10177350(*(_DWORD *)(this + 92)); sub_101BE740(v2); result = sub_101A2620(0); if ( *(_DWORD *)(v2 + 92) >= 0 ) { v4 = *(_DWORD *)(v2 + 92); result = (*(int (**)(void))(**(_DWORD **)(v2 + 416) + 28))(); if ( v4 < result ) { v5 = v2 + 4; result = (*(int (__stdcall **)(int))(**(_DWORD **)(v2 + 416) + 24))(v4); if ( result == v2 + 4 ) { (*(void (__stdcall **)(_DWORD))(**(_DWORD **)(v2 + 416) + 200))(*(_DWORD *)(v2 + 92)); if ( (int (__stdcall ***)(char))dword_10516B1C == &off_10516B00 ) v6 = dword_10516B30; else v6 = (*(int (**)(void))(*(_DWORD *)dword_10516B1C + 52))(); if ( v6 > 1 || !(unsigned __int8)(*(int (__thiscall **)(int))(*(_DWORD *)v5 + 140))(v2 + 4) || (unsigned __int8)(*(int (__thiscall **)(int))(*(_DWORD *)v5 + 160))(v2 + 4) ) { v7 = (*(int (__thiscall **)(int))(*(_DWORD *)v5 + 72))(v2 + 4); ConMsg("Dropped %s from server: %s\n", v7, a2); } (*(void (__thiscall **)(int *, int))(dword_10750200 + 20))(&dword_10750200, v2); v8 = *(_DWORD *)(v2 + 84); if ( v8 && (*(int (__thiscall **)(int))(*(_DWORD *)(v8 + 4) + 76))(v8 + 4) ) { v9 = (*(int (**)(void))(*(_DWORD *)(*(_DWORD *)(v2 + 84) + 4) + 76))(); (*(void (__thiscall **)(int, _DWORD))(*(_DWORD *)v9 + 296))(v9, *(_DWORD *)(v2 + 72)); *(_DWORD *)(v2 + 84) = 0; } v10 = *(_DWORD *)(v2 + 464); if ( v10 ) { (*(void (__stdcall **)(int))(*(_DWORD *)v10 + 152))(a2); *(_DWORD *)(v2 + 464) = 0; } result = (*(int (__thiscall **)(int))(*(_DWORD *)v5 + 108))(v2 + 4); } } } return result; }
简单分析一下,此函数的参数应该只有一个,并且是一个类成员函数, 当中的int this应该是一个指向类的一个指针,
所以实际参数只有int a2,而我们又可以从"ConMsg("Dropped %s from server: %s\n", v7, a2);"这行中猜想到
a2肯定是一个指向文本信息的指针(类似char *, const char *),接着有以上相同的方法,分别在linux版本与iMac版本
上查找相应的函数,我在linux与iMac上都找到了以下函数
linux:
iMac:
所以就把此函数名定义为"PerformDisconnection"
至此,确定整个函数为void CBaseClient::PerformDisconnection(const char *reason);
接下来,就是要勾这个函数了,在SourceMod(同样可以百度或谷歌一下哈^^,我这里就不解释太多了)中有封装了一套框架,
可以直接勾取函数,我们只需要通过寻找正确的特征码,然后再通过特征码定位到函数地址,这样就可以直接勾取函数了,为何
要用特征码的方式,而不直接采用动态库基地址加偏移的方式定位函数地址,主要是因为游戏会经常更新,如果采用基地址加偏移
的方式,如果游戏的引擎做更新之后,那么就得更换偏移了,而使用特征码的话,只要函数体不做变化,就算动态库的其他代码更新了,
此函数的特征码还是不会变的(好像漏了编译器的情况了^^,是的,据了解,更换编译器的情况下,特征码也是会变的,但是一般一
个游戏引擎,更换编译器的情况不会太频繁),所以这就是为什么采用特征码的方式来寻址.接来就是查找特征码了,如下:
通过整理一些跳转的情况,就能得到以下内容
55 push ebp 8B EC mov ebp, esp 53 push ebx 56 push esi 8B F1 mov esi, ecx 57 push edi 8B 4E ? mov ecx, [esi+5Ch] E8 ? ? ? ? call sub_10177350 56 push esi B9 ? ? ? ? mov ecx, offset xmmword_1073FCF0 E8 ? ? ? ? call sub_101BE740 6A 00 push 0
最后合并就成这样了
55 8B EC 53 56 8B F1 57 8B 4E ? E8 ? ? ? ? 56 B9 ? ? ? ? E8 ? ? ? ? 6A
最后就验证一下这个特征码是否正确,可用,唯一,可以通过以下方式
就可以得到如下的内容
由于SourceMod框架的需求,所以我们得把特征码中的"?"转换为"2A",然后再加添"\x"
最终为:"\x55\x8B\xEC\x53\x56\x8B\xF1\x57\x8B\x4E\x2A\xE8\x2A\x2A\x2A\x2A\x56\xB9\x2A\x2A\x2A\x2A\xE8\x2A\x2A\x2A\x2A\x6A"
下面就得开始C++上的工作喇
,将会在下篇讲解
相关文章推荐
- firefox 插件扩展开发 入门记录
- Android"挂逼"修炼之行---微信定位聊天记录中照片的位置信息插件开发详解
- Sysdeo为Tomcat开发的Eclipse插件调试时,提示"Source Not Found"错误
- ie与FireFox下扩展开发插件收集
- Firefox插件开发(3)——我的第一个扩展
- FireFox插件和扩展开发(三)—— scriptable实例
- FireFox插件和扩展开发(二)——编写和使用XPCOM组件
- DTS开发记录(2)-- 数据管道及插件
- Firefox扩展开发 (插件开发) Extension开发 入门教程 5步走 五步走
- 学习"使用 Eclipse BPEL 插件开发和执行 WS-BPEL V2.0 业务流程"碰到的问题
- eclipse RCP 开发中删除插件扩展点
- Eclipse 插件开发 -- 深入理解菜单(Menu)功能及其扩展点
- 用JBuilder2007开发扩展JSF标签的插件
- MS IDE RAD技术入门----VC6插件开发入门(3)----扩展IDE命令
- Eclipse plugins 插件开发学习 - 扩展点介绍
- .NET插件开发 与 DTE扩展
- ie与FireFox下扩展开发插件收集
- 插件开发积累记录
- IE与FireFox下扩展开发插件收集[转]
- eclipse插件开发--popMenu扩展点--找不到菜单项