冰凌汇编

 找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 105|回复: 0
收起左侧

[原创] 对CS1.6游戏的分析及心得

[复制链接]
kugoumusic 发表于 2022-3-5 23:00:36
前言
前段时间分析了一下CS1.6游戏,一直没有时间整理思路写帖子,最近,由于疫情关系,忽然想起了这件事,又重新回顾了一下,写下这篇文章与网友们互相交流学习。
本文主要是讲一下指针扫描器和Ultimap的具体使用以及它的强大之处,然后讲一下自己分析游戏数据的一些心得,最后再用一个准星吸人的例子讲一下HOOK的心得


使用指针扫描器快速寻找基址
使用CE寻找基址,一般的思路就是


  • 查找游戏数据,找到数据的临时地址
  • 右键查看谁改变了这个地址指向的数据,得到一个地址X + 偏移
  • 然后我们再内存搜索地址X,得到很多地址Ys,一个个右键查看谁改变了这个地址Y指向的数据,刷新游戏然后再找地址



就这样,一层层的去上找,不断尝试,最终找到绿色的即为基址。可见这种找基址的方式非常的麻烦,这里介绍一个神奇的工具,CE的指针扫描器
我们开局游戏,添加几个机器人,(添加机器人的目的是,因为找到基址后,即便不刷新游戏,有的基址指向的数据是不断变化的,其实里面是敌人和队友的基址,为了排除这种情况,添加几个机器人)
拿HP做实现,找到HP的临时地址,右键->对这个地址进行指针扫描
对CS1.6游戏的分析及心得 - kugoumusic_冰凌汇编

可以发现找到了403个数据


对CS1.6游戏的分析及心得 - kugoumusic_冰凌汇编

然后我们进行筛选,这里我们可以通过最后一层偏移进行筛选,我们对HP数据右键->找出是什么改写了这个地址,扔个手雷使自己掉血


对CS1.6游戏的分析及心得 - kugoumusic_冰凌汇编

对CS1.6游戏的分析及心得 - kugoumusic_冰凌汇编

可以发现,最后一层偏移是160,现今HP是4,下面进行筛选


对CS1.6游戏的分析及心得 - kugoumusic_冰凌汇编

对CS1.6游戏的分析及心得 - kugoumusic_冰凌汇编

对CS1.6游戏的分析及心得 - kugoumusic_冰凌汇编

经过筛选后,进行排序,然后双击第一个,添加到数据列表,退出游戏重新打开,发现里面指向的数据仍然是自己的HP,它就是基址。
其实在筛选的过程中,还有一些其他技巧,比如这个例子,在找到改变HP的地址后,可以查看相关地区汇编代码来寻找倒数第2层偏移


对CS1.6游戏的分析及心得 - kugoumusic_冰凌汇编

比如这里,可以发现mov eax, [esi+04],而 eax + 160是HP的地址,所以可以判断倒数第2层偏移是4,这样在筛选的时候可以加上二层偏移,当然也可以再往上找寻找倒数第3层偏移,使筛选的结果更准确。


通过搜索部分数据猜测游戏结构体来分析其他数据

通过上面指针扫描器的方法,我们又找到了一些其他数据的基址



属性地址
坐标X[[[cstrike.exe+11069BC]+7C]+4]+8
坐标Y[[[cstrike.exe+11069BC]+7C]+4]+C
坐标Z[[[cstrike.exe+11069BC]+7C]+4]+10
HP [[[cstrike.exe+11069BC]+7C]+4]+160
是否掉血(0免疫伤害)[[[cstrike.exe+11069BC]+7C]+4]+16C
护甲 [[[cstrike.exe+11069BC]+7C]+4]+1BC
阵营(1恐怖分子2反恐精英) [[cstrike.exe+11069BC]+7C]+1C8
我的金钱 [[cstrike.exe+11069BC]+7C]+1CC
随地购物(1) [[cstrike.exe+11069BC]+7C]+3C0
准星指向(0墙1友2敌) [[cstrike.exe+11069BC]+7C]+710
当前枪子弹数目 [[[cstrike.exe+11069BC]+7C]+5EC]+CC
当前枪后坐力 [[[cstrike.exe+11069BC]+7C]+5EC]+100
是否正在使用武器[[[cstrike.exe+11069BC]+7C]+5EC]+D4
左键冷却 [[[cstrike.exe+11069BC]+7C]+5EC]+B8


通过分析的这些数据可以猜测一下人物的结构体
[cstrike.exe+11069BC]+7c] 存放的是整个人物的基址
[[cstrike.exe+11069BC]+7c]+4] 存放的关于游戏内人物具体属性的具体地址
[[cstrike.exe+11069BC]+7c]+5EC] 存放的是使用武器的地址
我们通过猜测结构体,来到具体的内存位置,对人物进行操作,然后对内存进行观察,可以发现一些其他好玩的数据,这里我们来武器的地址为例



对CS1.6游戏的分析及心得 - kugoumusic_冰凌汇编


首先在地址列表中添加一个地址,指向当前的使用武器,通过切换武器来找到每个武器的地址,进而对相关内存区域进行对比
打开分析数据窗口,填入当前主武器,副武器,刀子的地址


对CS1.6游戏的分析及心得 - kugoumusic_冰凌汇编

对CS1.6游戏的分析及心得 - kugoumusic_冰凌汇编


我们切换武器和左键点击,观察内存,对3个数据进行对比
我们可以很明显的发现3个变化,即+D4这个区域,如果为1的话,表示当前武器正在使用
+B8这个位置,如果持续点击左键的话,这个位置的数据会增加



对CS1.6游戏的分析及心得 - kugoumusic_冰凌汇编

我们将刀子+B8的数据锁定为-1,就会出现2秒17刀的效果,,,


对CS1.6游戏的分析及心得 - kugoumusic_冰凌汇编

通过这种方式,不断进行内存数据的对比,也可以发现很多其他好玩的数据,感兴趣的网友自行尝试。这里讲解的主要目的主要是通过猜测游戏结构体来获取游戏的相关数据


对CS1.6游戏的分析及心得 - kugoumusic_冰凌汇编

使用Ultimap分析手雷CALL实现自定义手雷爆炸位置
CE有个强大的功能是Ultimap,Ultimap的功能其实是一个筛选代码的功能


对CS1.6游戏的分析及心得 - kugoumusic_冰凌汇编

对CS1.6游戏的分析及心得 - kugoumusic_冰凌汇编

类似于CE的内存数据筛选,只不过Ultimap是代码筛选,可以搜索程序中的CALL, 比如我们要找手雷爆炸的CALL,可以点击开始,然后晃动窗口,人物随机走动,发射子弹等操作,然后点代码没有运行,筛选除去很多没用的代码,然后扔个手雷,暂停游戏,点代码没有运行,等手雷爆炸后,点代码已经运行,上图中的 代码没有调用计数 可以筛选函数执行的次数,比如可以扔2个手雷等爆炸后,次数设置为2,点击代码没有调用计数按钮就可以筛选


启用Ultimap需要开启DBVM,这个需要电脑支持才可以,点击帮助,关于,可以看到电脑是否支持



对CS1.6游戏的分析及心得 - kugoumusic_冰凌汇编

强烈建议使用CE7.0版本,因为我用其他版本的时候,使用Ultimap会失败,甚至有的版本显示系统不支持DBVM,但是7.0不会。还有如果成功起开之后,Banch目标始终为0的话,需要用管理员身份打开目标程序,比如这里需要以管理员身份运行CS1.6


对CS1.6游戏的分析及心得 - kugoumusic_冰凌汇编

下面来找手雷爆炸CALL来实现自定义手雷爆炸的位置
我们按照上述的步骤进行一点点筛选



对CS1.6游戏的分析及心得 - kugoumusic_冰凌汇编

最终我们找到了这个地址


对CS1.6游戏的分析及心得 - kugoumusic_冰凌汇编

对其进行HOOK即可改变手雷爆炸位置


通过分析堆栈找到准星指向敌人基址,实现吸人

前面已经说过[[cstrike.exe+11069BC]+7C]+710 在这个地址处存放着准星指向的相关数据,比如如果对准敌人,这个地址的数据是2,对准队友是1,对准墙什么的是0,我想实现一个只要准星对准敌人敌人或队友就可以把他吸过来的功能,这个时候就需要获取准星指向人的地址


对 [[cstrike.exe+11069BC]+7C]+710 下断,看是什么改写了这个地址,游戏中添加3个机器人,控制台启用bot_stop 1使机器人停止行动


我们把准星从墙移动到队友身上



对CS1.6游戏的分析及心得 - kugoumusic_冰凌汇编
浏览内存区域


对CS1.6游戏的分析及心得 - kugoumusic_冰凌汇编


这里我最初是企图通过向上查汇编代码的方式来看看能不能找到队友基址的函数,但是失败了
虽然没有找到,但是肯定有,于是,换种思路,能不能先找到队友基址,然后再去内存中搜



对CS1.6游戏的分析及心得 - kugoumusic_冰凌汇编

我们在这个那个地址处下断点,将准星移动到敌人上,程序断下,搜索敌人基址


对CS1.6游戏的分析及心得 - kugoumusic_冰凌汇编

然后再把准星移动到队友身上,程序断下,发现地址又变为了队友的基址


对CS1.6游戏的分析及心得 - kugoumusic_冰凌汇编

再观察程序运行到此处时ESP,[ESP- 0XD8]就是指向人基址


mp.dll+9C0EC - 89 7D 00 - mov [ebp+00],edi


当然指向墙的时候,[esp - 0XD8]存放的是其他的数据,因此我们对此HOOK的时候需要判断一下数据是不是人物基址

[C++] 纯文本查看 复制代码
BOOL IsPeopleBase(DWORD base)  
{
        if (dwPointPeopleBase > 0){
                if (!(0XF0000000 & dwPointPeopleBase))//人物基址前4位通常是0
                        return TRUE;
                try{//如果不是的话也有可能是人物基址,判断血量即可
                        float blood = *(float *)(*(DWORD *)(dwMyBase + 4) + 160);
                        if (blood < 100 && blood > 0)
                                return TRUE;
                }
                catch (...)        {
                        return FALSE;
                }
        }        
        return FALSE;
}


这里贴出按E吸人,按T瞬移过去的全部代码

[C++] 纯文本查看 复制代码
#include "stdafx.h"

#define PATCHLENGTH        6
#define OFFSET 0X9C0C9                        //HOOK mp.dll的偏移位置

//0AD2C0C9    50              push eax
//0AD2C0CA    6A 00           push 0x0
//0AD2C0CC    51              push ecx
//0AD2C0CD    6A 01           push 0x1
typedef struct _stPos{
        float x;
        float y;
        float z;
}stPos, *pstPos;

HMODULE hMpdll = 0;                                                        //保存mp.dll的基址
HMODULE hModule = 0;                                                //保存cstrike.exe的基址
BYTE byHookPatch[PATCHLENGTH] = {};                        //保存打的补丁
DWORD dwHookAddr;                                                        //保存HOOK的地址
DWORD dwHookRetAddr = 0;                                        //保存HOOK函数的返回点
BOOL IsHooked = FALSE;
DWORD dwPointPeopleBase;                                        //保存指向人的基址
DWORD dwMyBase;                                                                //保存我的基址
pstPos pMyPos;                                                                //我的坐标
pstPos pOtherPos;                                                        //指向人坐标

void __declspec(naked) HookProc()
{
        __asm {
                pushad;
                pushfd;

                mov eax, dword ptr ss : [esp + 0X24 - 0XD8];        
                mov dword ptr ds : [dwPointPeopleBase], eax;        //保存指向人物的基址
                
                popfd;
                popad;

                push eax;
                push 0x0;
                push ecx;
                push 0x1;
                jmp dword ptr ds:[dwHookRetAddr];
        }
}

void GetHookInfo() {
        hMpdll = GetModuleHandle("mp.dll");
        hModule = GetModuleHandle(NULL);
        dwHookAddr = (DWORD)hMpdll + OFFSET;
        dwHookRetAddr = dwHookAddr + PATCHLENGTH;
        memset(&byHookPatch[0], 0X90, PATCHLENGTH);
        byHookPatch[0] = 0XE9;
        *(DWORD *)&byHookPatch[1] = (DWORD)HookProc - dwHookAddr - 5;
}

void SetHook() {
        DWORD dwOldProtect;
        if (!IsHooked) {
                VirtualProtect((LPVOID)(hMpdll + OFFSET), PATCHLENGTH, PAGE_EXECUTE_READWRITE, &dwOldProtect);
                WriteProcessMemory(GetCurrentProcess(), (LPVOID)dwHookAddr, byHookPatch, PATCHLENGTH, NULL);
                VirtualProtect((LPVOID)(hMpdll + OFFSET), PATCHLENGTH, dwOldProtect, NULL);
                IsHooked = TRUE;
        }
}

void GetPosInfo() {
        dwMyBase = *(DWORD *)((DWORD)((DWORD *)*((DWORD *)((DWORD)hModule + 0X11069BC))) + 0X7C);
        pMyPos = pstPos(*(DWORD *)(dwMyBase + 4) + 8);
}

void CopyPos(pstPos a, pstPos b)
{
        a->x = b->x;
        a->y = b->y;
        a->z = b->z;
}

BOOL IsPeopleBase(DWORD base)
{
        if (dwPointPeopleBase > 0){
                if (!(0XF0000000 & dwPointPeopleBase))
                        return TRUE;
                try{
                        float blood = *(float *)(*(DWORD *)(dwMyBase + 4) + 160);
                        if (blood < 100 && blood > 0)
                                return TRUE;
                }
                catch (...)        {
                        return FALSE;
                }
        }        
        return FALSE;
}

DWORD WINAPI ThreadFunc(LPVOID lParam)
{
        GetHookInfo();
        SetHook();;
        GetPosInfo();
        while(TRUE){
                if (GetAsyncKeyState('E')){                        //按E吸人
                        if (IsPeopleBase(dwPointPeopleBase)) {
                                pOtherPos = pstPos(*(DWORD *)(dwPointPeopleBase + 4) + 8);
                                CopyPos(pOtherPos, pMyPos);
                        }
                }
                else if (GetAsyncKeyState('T')) {        //按T瞬移至指向人身边
                        if (IsPeopleBase(dwPointPeopleBase)) {
                                pOtherPos = pstPos(*(DWORD *)(dwPointPeopleBase + 4) + 8);
                                CopyPos(pMyPos, pOtherPos);
                        }
                }
                Sleep(100);
        }
        return 0;
}

BOOL APIENTRY DllMain( HMODULE hModule,DWORD  ul_reason_for_call,LPVOID lpReserved){
    switch (ul_reason_for_call){
    case DLL_PROCESS_ATTACH:
                CreateThread(NULL, 0, ThreadFunc, NULL, 0, NULL);
                break;
    }
    return TRUE;
}


对CS1.6游戏的分析及心得 - kugoumusic_冰凌汇编

成果展示
最终,经过不断尝试,自己另外还制作了一个CS1.6的小辅助


对CS1.6游戏的分析及心得 - kugoumusic_冰凌汇编

辅助源码:
对CS1.6游戏的分析及心得 - kugoumusic_冰凌汇编 CS1.6_Hook-master.zip (8.16 MB, 下载次数: 2)

参考视频:
https://www.bilibili.com/video/av68192542
冰凌汇编免责声明
以上内容均来自网友转发或原创,如存在侵权请发送到站方邮件9003554@qq.com处理。
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|小黑屋|站点统计|Archiver|小黑屋|RSS|冰凌汇编 ( 滇ICP备2022002049号 滇公网安备 53032102000029号)|网站地图

GMT+8, 2022-9-25 07:00 , Processed in 0.138846 second(s), 12 queries , Redis On.

冰凌汇编 - 建立于2021年12月20日

Powered by Discuz! © 2001-2022 Comsenz Inc.

快速回复 返回顶部 返回列表