寻找任务坐标的方法:

用CE寻找本人的x y z 坐标内存地址,并通过修改器实现效果,并找出基址

坐标比较精确 所以浮点数或者双浮点数

坐标在一些游戏中可能被加密过 变动的数值

初始值为未知 的初始值

x坐标地址 +4字节(十六进制)=Y坐标地址

y坐标地址 +4字节(十六进制)=Z坐标地址

x坐标地址 +4字节(十六进制) =Z坐标地址

Z坐标地址 +4字节(十六进制) =Y坐标地址

实现了一些小功能:

无限金币:

主要思路就是向内存中修改金币数量的地址写入新的值

//金币无限,可以修改为任意金币值
BOOL money_change(DWORD processId, LPVOID BaseAddress, int x) {
    int numOffsets = 3;
    intptr_t offsets[] = { 0x11069BC, 0x7C,0x1CC };
    int numOffsets2 = 2;
    intptr_t offsets2[] = { 0x11069BC, 0x14 };
    HANDLE hProcess = OpenProcess(PROCESS_VM_READ | PROCESS_VM_WRITE | PROCESS_VM_OPERATION, FALSE, processId);
    if (WriteProcessMemory(hProcess, VisitMemory(processId, BaseAddress, offsets, numOffsets), &x, sizeof(int), NULL)&& WriteProcessMemory(hProcess,(LPVOID)0x1A1B9FC, &x, sizeof(int),NULL))
        return 1;
}

血量无限:

思路和金币无限相同,但是有一个注意点就是,需要把是否掉血改为0,这样实现不掉血,不然血量再高还是会被杀死

//血量无限
BOOL Blood_change(DWORD processId, LPVOID BaseAddress,  int x) {
    int numOffsets =4;//血量多少地址
    intptr_t offsets[] = { 0x11069BC, 0x7C,0x4,0x160 };
    int numOffsets1 = 4;//是否掉血地址
    intptr_t offsets1[] = { 0x11069BC, 0x7C,0x4,0x16C };
    int y = 0;//这里将是否掉血改为0,就可以实现不掉血,即不会死,但是很奇怪一个点,定义一个变量为0然后进行写入就可以,但是直接进行写入,就写入失败
    HANDLE hProcess = OpenProcess(PROCESS_VM_READ | PROCESS_VM_WRITE | PROCESS_VM_OPERATION, FALSE, processId);
    //修改血量值为255,但是还是回掉血,最后会被杀死,需要修改程序为不掉血
    if (WriteProcessMemory(hProcess,VisitMemory(processId, BaseAddress, offsets, numOffsets), &x, sizeof(int), NULL)&& WriteProcessMemory(hProcess, VisitMemory(processId, BaseAddress, offsets1, numOffsets1), &y, sizeof(int), NULL))
        return 1;
}

随时购物

这里就是修改指令代码,上面金币和血量修改的是指令的操作数,这里是修改整个指令

BOOL Shopping_angtime(DWORD processId, LPVOID BaseAddress) {
    HANDLE hProcess = OpenProcess(PROCESS_VM_READ | PROCESS_VM_WRITE | PROCESS_VM_OPERATION, FALSE, processId);
    int numOffsets = 3;
    intptr_t offsets[] = { 0x11069BC, 0x7C,0x3c0};
    /*int x = 1;
    if (WriteProcessMemory(hProcess, VisitMemory(processId, BaseAddress, offsets, numOffsets), &x, sizeof(int), NULL))*/
    BYTE newBytes1[] = { 0xc7,0x86,0xc0,0x03,0x00,0x00,0x01 };
    if(WriteProcessMemory(hProcess, (LPVOID)0x1aa59d75, newBytes1, sizeof(newBytes1), NULL))
        return 1;
}

两秒17刀:

内存中+B8这个位置,如果持续点击左键的话,这个位置的数据会增加,所以把这里锁定为-1,这样实现两秒17刀效果

BOOL dao(DWORD processID, LPVOID BaseAddress) {
    int numOffsets = 4;
    intptr_t offsets[] = { 0x11069BC, 0x7C,0x5ec,0xb8 };
    HANDLE hProcess = OpenProcess(PROCESS_VM_READ | PROCESS_VM_WRITE | PROCESS_VM_OPERATION, FALSE, processId);
    int x = -1;
    if (WriteProcessMemory(hProcess, VisitMemory(processID, BaseAddress, offsets, numOffsets), &x, sizeof(int), NULL) )
        return 1;
}

完整代码:

#include <Windows.h>
#include <Psapi.h>
#include <stdio.h>
#include<iostream>
DWORD processId;//进程ID变量
//获取进程句柄
HWND GethWnd() {
    LPCWSTR targetWindowTitle = L"Counter-Strike";
    HWND hWnd = FindWindow(NULL, targetWindowTitle);//获取窗口句柄
    if (hWnd == NULL) {
        printf("未找到目标窗口\n");
    }
    else return hWnd;
}
//获取进程ID
DWORD  GetProcessID(HWND hWnd) {
    GetWindowThreadProcessId(hWnd, &processId);
    return processId;
}
//获取进程基地址
LPVOID GetProcessBaseAddress(DWORD ProcessID) {
    HANDLE hProcess = OpenProcess(PROCESS_VM_READ | PROCESS_VM_WRITE | PROCESS_VM_OPERATION, FALSE, ProcessID);
    HMODULE hModules[1024];
    DWORD needed;//枚举进程所有模块
    if (EnumProcessModules(hProcess, hModules, sizeof(hModules), &needed)) {
        int moduleCount = needed / sizeof(HMODULE);//计算模块数量
        //获取指定模块信息
        for (int i = 0; i < moduleCount; ++i) {
            TCHAR moduleName[MAX_PATH];
            if (GetModuleBaseName(hProcess, hModules[i], moduleName, sizeof(moduleName) / sizeof(TCHAR))) {
                if (_wcsicmp(moduleName, L"cstrike.exe") == 0) {
                    MODULEINFO moduleInfo;
                    if (GetModuleInformation(hProcess, hModules[i], &moduleInfo, sizeof(moduleInfo))) {
                        return  moduleInfo.lpBaseOfDll;
                    }
                    else {
                        printf("获取模块信息失败\n");
                    }
                }
            }
        }    printf("未找到名为\"cs\"的模块\n");
        CloseHandle(hProcess); // Close the handle before returning NULL
        return NULL;
    }
    else {
        printf("枚举进程模块失败\n");
    }

    CloseHandle(hProcess);//关闭
}
//访问内存数据(根据基地址+传进来的偏移值计算最后要写入数据前的地址)
LPVOID VisitMemory(DWORD processId, LPVOID BaseAddress, intptr_t* offsets, int numOffsets) {
    HANDLE hProcess = ::OpenProcess(PROCESS_ALL_ACCESS, FALSE, processId);
    int i;
    int value = 0;
    LPVOID  address;
    for (i = 0; i < numOffsets; i++) {//循环找完偏移值
        if (i == 0)
            address = (LPVOID)((DWORD)BaseAddress + offsets[i]);//第一次是基地址+偏移
        else
            address = (LPVOID)((DWORD)value + offsets[i]);//后面就是内存中的值加偏移
        if (i == numOffsets - 1) {
            printf("%x\n", address);
            return address;
        }
        ReadProcessMemory(hProcess, address, &value, sizeof(int), NULL);
    }
}
//金币无限,可以修改为任意金币值
BOOL money_change(DWORD processId, LPVOID BaseAddress, int x) {
    int numOffsets = 3;
    intptr_t offsets[] = { 0x11069BC, 0x7C,0x1CC };
    int numOffsets2 = 2;
    intptr_t offsets2[] = { 0x11069BC, 0x14 };
    HANDLE hProcess = OpenProcess(PROCESS_VM_READ | PROCESS_VM_WRITE | PROCESS_VM_OPERATION, FALSE, processId);
    if (WriteProcessMemory(hProcess, VisitMemory(processId, BaseAddress, offsets, numOffsets), &x, sizeof(int), NULL)&& WriteProcessMemory(hProcess,(LPVOID)0x1A1B9FC, &x, sizeof(int),NULL))
        return 1;
}
//血量无限
BOOL Blood_change(DWORD processId, LPVOID BaseAddress,  int x) {
    int numOffsets =4;//血量多少地址
    intptr_t offsets[] = { 0x11069BC, 0x7C,0x4,0x160 };
    int numOffsets1 = 4;//是否掉血地址
    intptr_t offsets1[] = { 0x11069BC, 0x7C,0x4,0x16C };
    int y = 0;//这里将是否掉血改为0,就可以实现不掉血,即不会死,但是很奇怪一个点,定义一个变量为0然后进行写入就可以,但是直接进行写入,就写入失败
    HANDLE hProcess = OpenProcess(PROCESS_VM_READ | PROCESS_VM_WRITE | PROCESS_VM_OPERATION, FALSE, processId);
    //修改血量值为255,但是还是回掉血,最后会被杀死,需要修改程序为不掉血
    if (WriteProcessMemory(hProcess,VisitMemory(processId, BaseAddress, offsets, numOffsets), &x, sizeof(int), NULL)&& WriteProcessMemory(hProcess, VisitMemory(processId, BaseAddress, offsets1, numOffsets1), &y, sizeof(int), NULL))
        return 1;
}
//两秒17刀
BOOL dao(DWORD processID, LPVOID BaseAddress) {
    int numOffsets = 4;
    intptr_t offsets[] = { 0x11069BC, 0x7C,0x5ec,0xb8 };
    HANDLE hProcess = OpenProcess(PROCESS_VM_READ | PROCESS_VM_WRITE | PROCESS_VM_OPERATION, FALSE, processId);
    int x = -1;
    if (WriteProcessMemory(hProcess, VisitMemory(processID, BaseAddress, offsets, numOffsets), &x, sizeof(int), NULL) )
        return 1;
}
//随地购物
BOOL Shopping_angtime(DWORD processId, LPVOID BaseAddress) {
    HANDLE hProcess = OpenProcess(PROCESS_VM_READ | PROCESS_VM_WRITE | PROCESS_VM_OPERATION, FALSE, processId);
    int numOffsets = 3;
    intptr_t offsets[] = { 0x11069BC, 0x7C,0x3c0};
    /*int x = 1;
    if (WriteProcessMemory(hProcess, VisitMemory(processId, BaseAddress, offsets, numOffsets), &x, sizeof(int), NULL))*/
    BYTE newBytes1[] = { 0xc7,0x86,0xc0,0x03,0x00,0x00,0x01 };
    if(WriteProcessMemory(hProcess, (LPVOID)0x1aa59d75, newBytes1, sizeof(newBytes1), NULL))
        return 1;
}
int main() {
    HWND hWnd = GethWnd();
    DWORD ProcessID = GetProcessID(hWnd);
    LPVOID   BaseAddress = GetProcessBaseAddress(ProcessID);
    printf("%d\n", ProcessID);
    printf("%x\n", BaseAddress);
    if(money_change(ProcessID, BaseAddress, 10000))printf("金币无限成功1");
    if (Blood_change(ProcessID, BaseAddress,0x437f0000))printf("血量无限成功2");
    if (Shopping_angtime(ProcessID, BaseAddress))printf("随时购物成功3");
    if (dao(ProcessID, BaseAddress))printf("两秒17刀成功4");
   // BLOOD_NO(ProcessID, BaseAddress);
    return 0;
}

参考文章

【C++】从零开始的CSGO逆向分析1——寻找偏移与基址的方法 - 水风井 - 博客园 (cnblogs.com)

FRK1/HazeTumper:最新的CSGO偏移量和HazeDucumper配置 (github.com)

cs1.6 人物地址查询_cs1.6的血量基址_thomas_blog的博客-CSDN博客

对CS1.6游戏的分析及心得_cs1.6文件解析_zsky_t的博客-CSDN博客