编程语言
首页 > 编程语言> > 【C++】从零开始的CS:GO逆向分析3——写出一个透视

【C++】从零开始的CS:GO逆向分析3——写出一个透视

作者:互联网

透视实现的方法介绍

  一般有两种方式,一种是外挂,一种是内挂,外挂是在创建一个透明窗口,在透明窗口上画线,让鼠标事件透过窗口,透明窗口覆盖在游戏窗口上。内挂是通过DLL注入,HOOK游戏中的绘制函数,在游戏绘制人物的时候绘制自己的线。还剩一种比较少用,但也可以实现,找到人物模型ID,在渲染到人物模型的时候关掉渲染缓冲(应该是叫这个?),使人物模型在墙模型前面渲染,导致可以直接看到人物。本篇文章采用的是外挂的形式,根据上篇文章已经可以创建出一个覆盖在屏幕上的透明窗口。


先把需要用到的全局变量声明一下(GetImformation.cpp)

变量名起的挺明白的,就不写注释了

DWORD g_process_id = NULL;
HANDLE g_process_handle = NULL;
UINT_PTR g_local_player = NULL;
UINT_PTR g_player_list_address = NULL;
UINT_PTR g_matrix_address = NULL;
UINT_PTR g_angle_address = NULL;
HWND g_game_hwnd = NULL;
module_information engine_module;
module_information client_module;
module_information server_module;
float g_client_width;
float g_client_height;

把需要用到的偏移也声明一下

#define dwViewMatrix 0x4DCF254
#define dwLocalPlayer 0xDC14CC
#define dwClientState 0x58CFDC
#define dwEntityList 0x4DDD93C
#define dwClientState_ViewAngles 0x4D90

#define m_vecOrigin 0x138
#define m_bDormant 0xED
#define m_lifeState 0x25F
#define m_iHealth 0x100
#define m_iTeamNum 0xF4

再把需要使用到的函数先声明和实现(GetImformation.cpp),实现思路写在后面

获取屏幕大小,保存到全局变量

void GetWindowSize()
{
    HDC hdc = GetDC(nullptr);
    g_client_width = GetDeviceCaps(hdc, DESKTOPHORZRES);
    g_client_height = GetDeviceCaps(hdc, DESKTOPVERTRES);
    ReleaseDC(nullptr, hdc);
}
先写一个错误获取函数,以方便获取出错的信息
void error(const char*text)
{
    MessageBoxA(nullptr, text, nullptr, MB_OK);
    exit(-1);
}
bool is_error()
{
    return GetLastError() != 0;
}

通过进程名获取进程id和进程句柄

使用CreateToolhelp32Snapshot函数,创建进程快照,遍历系统快照中的进程名,遍历到process_name,则返回该进程的进程ID

DWORD get_process_id(const char*process_name)
{
    HANDLE snap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
    if (is_error()) error("CreateToolhelp32Snapshot失败");
    PROCESSENTRY32 process_info;
    ZeroMemory(&process_info, sizeof(process_info));
    process_info.dwSize = sizeof(process_info);
    char target[1024];
    ZeroMemory(target, 1024);
    strncpy_s(target, process_name, strlen(process_name));
    _strupr(target);
    bool state = Process32First(snap, &process_info);
    while (state)
    {
        if (strncmp(_strupr(process_info.szExeFile), target, strlen(target)) == 0)
        {
            return process_info.th32ProcessID;
        }
        state = Process32Next(snap, &process_info);
    }
    CloseHandle(snap);
    return 0;
}

通过进程ID获取进程句柄

HANDLE get_process_handle(DWORD process_id)
{
    HANDLE process_handle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, process_id);
    if (is_error())
        error("get_process_handle失败");
return process_handle;
}
 

通过进程id获取进程中的模块信息(模块大小,模块地址,模块句柄)

可以发现偏移都是由 client.dll+xxxxx 此种形式构成,所以需要获取模块的地址

先创建一个模块结构体,需要获取模块的模块大小,模块地址,模块句柄

class module_information
{
public:
    HANDLE module_handle;
    char module_name[1024];
    char *module_data;
    UINT_PTR module_address;
    int module_size;
    void alloc(int size)
    {
        module_size = size;
        module_data = (char *)VirtualAlloc(nullptr, size, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
        if (is_error())error("申请内存失败");
    }
    void release()
    {
        if (module_data)VirtualFree(module_data, 0, MEM_RELEASE);
        module_data = nullptr;
    }
};

传入进程ID和需要获取的模块名,CreateToolhelp32Snapshot创建模块快照,遍历快照,比对模块名,获取模块信息

void get_moduel_info(DWORD process_id, const char *name, OUT module_information&info)
{
    HANDLE snap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, process_id);
    if (is_error())error("创建快照错误");
    MODULEENTRY32 module_info;
    ZeroMemory(&module_info, sizeof(module_info));
    module_info.dwSize = sizeof(module_info);
    char target[1024];
    ZeroMemory(target, 1024);
    strncpy(target, name, strlen(name));
    _strupr(target);
    bool status = Module32First(snap, &module_info);
    while (status)
    {
        if (strncmp(_strupr(module_info.szModule), target, sizeof(target)) == 0)
        {
            info.module_address = (UINT_PTR)module_info.modBaseAddr;
            info.module_handle = module_info.hModule;
            info.alloc(module_info.modBaseSize);
            DWORD size = read_memory(g_process_handle, info.module_address, info.module_data, info.module_size);//TODO
            CloseHandle(snap);
            return;
        }
        status = Module32Next(snap, &module_info);
    }
    error("未找到模块");
    return;
}

标签:c++,操作,代码,函数,地址
来源: