最近开始接触到了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"功能,就可以看到以下画面

把代码复制出来,这样显得方便一点

 1 int __thiscall sub_101A3050(int this, int a2)
2 {
3 int v2; // esi@1
4 int result; // eax@1
5 int v4; // ebx@2
6 int v5; // edi@3
7 int v6; // eax@5
8 int v7; // eax@10
9 int v8; // ecx@11
10 int v9; // eax@13
11 int v10; // ecx@14
12
13 v2 = this;
14 sub_10177350(*(_DWORD *)(this + 92));
15 sub_101BE740(v2);
16 result = sub_101A2620(0);
17 if ( *(_DWORD *)(v2 + 92) >= 0 )
18 {
19 v4 = *(_DWORD *)(v2 + 92);
20 result = (*(int (**)(void))(**(_DWORD **)(v2 + 416) + 28))();
21 if ( v4 < result )
22 {
23 v5 = v2 + 4;
24 result = (*(int (__stdcall **)(int))(**(_DWORD **)(v2 + 416) + 24))(v4);
25 if ( result == v2 + 4 )
26 {
27 (*(void (__stdcall **)(_DWORD))(**(_DWORD **)(v2 + 416) + 200))(*(_DWORD *)(v2 + 92));
28 if ( (int (__stdcall ***)(char))dword_10516B1C == &off_10516B00 )
29 v6 = dword_10516B30;
30 else
31 v6 = (*(int (**)(void))(*(_DWORD *)dword_10516B1C + 52))();
32 if ( v6 > 1
33 || !(unsigned __int8)(*(int (__thiscall **)(int))(*(_DWORD *)v5 + 140))(v2 + 4)
34 || (unsigned __int8)(*(int (__thiscall **)(int))(*(_DWORD *)v5 + 160))(v2 + 4) )
35 {
36 v7 = (*(int (__thiscall **)(int))(*(_DWORD *)v5 + 72))(v2 + 4);
37 ConMsg("Dropped %s from server: %s\n", v7, a2);
38 }
39 (*(void (__thiscall **)(int *, int))(dword_10750200 + 20))(&dword_10750200, v2);
40 v8 = *(_DWORD *)(v2 + 84);
41 if ( v8 && (*(int (__thiscall **)(int))(*(_DWORD *)(v8 + 4) + 76))(v8 + 4) )
42 {
43 v9 = (*(int (**)(void))(*(_DWORD *)(*(_DWORD *)(v2 + 84) + 4) + 76))();
44 (*(void (__thiscall **)(int, _DWORD))(*(_DWORD *)v9 + 296))(v9, *(_DWORD *)(v2 + 72));
45 *(_DWORD *)(v2 + 84) = 0;
46 }
47 v10 = *(_DWORD *)(v2 + 464);
48 if ( v10 )
49 {
50 (*(void (__stdcall **)(int))(*(_DWORD *)v10 + 152))(a2);
51 *(_DWORD *)(v2 + 464) = 0;
52 }
53 result = (*(int (__thiscall **)(int))(*(_DWORD *)v5 + 108))(v2 + 4);
54 }
55 }
56 }
57 return result;
58 }

简单分析一下,此函数的参数应该只有一个,并且是一个类成员函数, 当中的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(同样可以百度或谷歌一下哈^^,我这里就不解释太多了)中有封装了一套框架,

可以直接勾取函数,我们只需要通过寻找正确的特征码,然后再通过特征码定位到函数地址,这样就可以直接勾取函数了,为何

要用特征码的方式,而不直接采用动态库基地址加偏移的方式定位函数地址,主要是因为游戏会经常更新,如果采用基地址加偏移

的方式,如果游戏的引擎做更新之后,那么就得更换偏移了,而使用特征码的话,只要函数体不做变化,就算动态库的其他代码更新了,

此函数的特征码还是不会变的(好像漏了编译器的情况了^^,是的,据了解,更换编译器的情况下,特征码也是会变的,但是一般一

个游戏引擎,更换编译器的情况不会太频繁),所以这就是为什么采用特征码的方式来寻址.接来就是查找特征码了,如下:

通过整理一些跳转的情况,就能得到以下内容

 1 55                                            push    ebp
2 8B EC mov ebp, esp
3 53 push ebx
4 56 push esi
5 8B F1 mov esi, ecx
6 57 push edi
7 8B 4E ? mov ecx, [esi+5Ch]
8 E8 ? ? ? ? call sub_10177350
9 56 push esi
10 B9 ? ? ? ? mov ecx, offset xmmword_1073FCF0
11 E8 ? ? ? ? call sub_101BE740
12 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++上的工作喇,将会在下篇讲解

CSGO 服务端扩展插件开发记录之"DropClientReason"(1)的更多相关文章

  1. <Linux多线程服务端编程>学习记录

    使用智能指针解决多线程下 类的解析冲突问题 有这样一个场景 使用StockFactory记录Stock的信息  容器是map<string,smart_ptr>; 代码如下: #inclu ...

  2. 第十二章 Odoo 12开发之报表和服务端 QWeb

    报表是业务应用非常有价值的功能,内置的 QWeb 引擎是报表的默认引擎.使用 QWeb 模板设计的报表可生成 HTML 文件并被转化成 PDF.也就是说我们可以很便捷地利用已学习的 QWeb 知识,应 ...

  3. TYPESDK手游聚合SDK服务端设计思路与架构之四:流程优化之信息安全与订单校验

    有了前文几个步骤的分析和设计,TYPESDK的信息交互流程已经可以正常工作了,但是,这个流程还没有考虑到支付这样的过程中,至关重要的信息安全问题. 在整个交互过程中,游戏服务端,SDK服务端,渠道服务 ...

  4. Netty 源码学习——服务端流程分析

    在上一篇我们已经介绍了客户端的流程分析,我们已经对启动已经大体上有了一定的认识,现在我们继续看对服务端的流程来看一看到底有什么区别. 服务端代码 public class NioServer { pr ...

  5. MVC扩展Filter,通过继承HandleErrorAttribute,使用log4net或ELMAH组件记录服务端500错误、HttpException、Ajax异常等

    □ 接口 public interface IExceptionFilter{    void OnException(ExceptionContext filterContext);} Except ...

  6. 源码详解openfire保存消息记录_修改服务端方式

    实现openfire消息记录通常有两种方式,修改服务端和添加消息记录插件. 今天,简单的说明一下修改服务端方式实现消息记录保存功能. 实现思路 修改前: 默认的,openfire只提供保存离线记录至o ...

  7. Swift3.0服务端开发(三) Mustache页面模板与日志记录

    本篇博客主要介绍如果在Perfect工程中引入和使用Mustache页面模板与日志记录系统.Mustache页面模板类似于PHP中的smarty模板引擎或者Java中的JSTL标签.当然Mustach ...

  8. linux上安装php7 memcache扩展 和 安装服务端memcached

    linux上安装memcached不算太困难.唯一让本人感到困难的是 php7的memcache扩展安装.真的蛋疼! 先说安装服务端 memcached 1. 首先安装Libevent事件触发管理器. ...

  9. 使用Zabbix服务端本地邮箱账号发送报警邮件及指定报警邮件操作记录

    邮件报警有两种情况:1)Zabbix服务端只是单纯的发送报警邮件到指定邮箱,发送报警邮件的这个邮箱账号是Zabbix服务端的本地邮箱账号(例如:root@localhost.localdomain), ...

随机推荐

  1. 你不得不知的Java基础知识

    本篇博客主要记录Java中面向对象的概念和Java语法的基础知识. 面向对象 什么是面向对象 面向对象是一种优秀的软件设计思想,是相对于面向过程.面向切面等设计思想的一种软件设计理念.它的核心思想是运 ...

  2. Spring security OAuth2.0认证授权学习第二天(基础概念-RBAC)

    RBAC 基于角色的访问控制 基于角色的访问控制用代码实现一下其实就是一个if的问题if(如果有角色1){ } 如果某个角色可以访问某个功能,当某一天其他的另一个角色也可以访问了,那么代码就需要变化, ...

  3. MyBatis源码流程分析

    mybatis核心流程三大阶段 Mybatis的初始化  建造者模式 建造者模式(Builder Pattern)使用多个简单的对象一步一步构建成一个复杂的对象.这种类型的设计模式属于创建型模式,它提 ...

  4. Java 多线程实现多窗口同时售票简单功能

    package day162020072701.day1603; import java.util.concurrent.locks.Lock; import java.util.concurrent ...

  5. Java自定义异常的用法

    package day162020072701.day1601; /** * @author liuwenlong * @create 2020-07-27 09:25:44 */ @Suppress ...

  6. JS中对获取一个标签的class的方法封一个库

    在JS中我们经常会会用到,获取一个标签的id var aId=document.getElementById("id") 现在虽然有getElementsByClassName这个 ...

  7. JAVA8--流处理和optional

    转载自https://www.cnblogs.com/invoker-/p/6896865.html 流与集合    众所周知,日常开发与操作中涉及到集合的操作相当频繁,而java中对于集合的操作又是 ...

  8. Netty之ChannelOption的各种参数之EpollChannelOption.SO_REUSEPORT

    socket选项 SO_REUSEPORT 转 miffa 发布于 2015/03/24 17:21 字数 3383 阅读 6076 收藏 6 点赞 1 评论 0 开发十年,就只剩下这套Java开发体 ...

  9. 如何使用二维码进行表白-一键制作二维码,gif二维码制作

    " 如何使用二维码进行表白-一键制作二维码" 二维码在我们现在生活中随处可见,因为一次突发奇想,那我们可不可以制作一个自己的二维码呢!然后让女朋友去扫描一下----嘿嘿嘿--不行, ...

  10. Python+Appium实现APP自动化测试

    一.环境准备 1.脚本语言:Python3.x IDE:安装Pycharm 2.安装Java JDK .Android SDK 3.adb环境,path添加E:\Software\Android_SD ...