Информация Гайд Вызываем удаленно игровую функцию и WinAPI

_NeliN_

Новичок
10
1
У меня ошибка, @CleanLegend живой, поможешь?

Вообщем такое же окошко вылезает, без понятия что делать
@CleanLegend опять какая-то ерунда.
Посмотреть вложение 61639
Что уж теперь не так то? Я всё пофиксил из того, что ты сказал.
C++:
#include <iostream>
#include <string>
#include <Windows.h>
#include <TlHelp32.h>

int processId;
DWORD sampdll;

int GetProcessIdByWindowName(std::string windowName)
{
    HWND window = FindWindowA(NULL, reinterpret_cast<LPCSTR>(windowName.c_str()));
    int pId = 0;
    GetWindowThreadProcessId(window, reinterpret_cast<LPDWORD>(&pId));
    return pId;
}

DWORD GetModuleBaseAddress(DWORD pid, const char* name)
{
    HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, pid);
    MODULEENTRY32 mEntry;
    mEntry.dwSize = sizeof(MODULEENTRY32);
    do
    {
        if (!strcmp((const char*)mEntry.szModule, name))
        {
            CloseHandle(snapshot);
            return (DWORD)mEntry.modBaseAddr;
        }
    } while (Module32Next(snapshot, &mEntry));
}

template <typename T>
T readMem(int address)
{
    T buf;
    HANDLE h = OpenProcess(PROCESS_VM_READ, false, processId);
    ReadProcessMemory(h, reinterpret_cast<LPCVOID>(address), &buf, sizeof(T), NULL);
    CloseHandle(h);
    return buf;
}

template <typename T>
void writeMem(int address, T buf)
{
    HANDLE h = OpenProcess(PROCESS_VM_WRITE, false, processId);
    int oldProtect = 0;
    VirtualProtectEx(h, reinterpret_cast<LPVOID>(address), sizeof(T), PAGE_READWRITE, reinterpret_cast<PDWORD>(&oldProtect));
    WriteProcessMemory(h, reinterpret_cast<LPVOID>(address), &buf, sizeof(T), NULL);
    VirtualProtectEx(h, reinterpret_cast<LPVOID>(address), sizeof(T), oldProtect, reinterpret_cast<PDWORD>(&oldProtect));
    CloseHandle(h);
}

struct AddMessageArg
{
    DWORD arg1;
    int arg2;
    const char *arg3;
    int arg4;
    int arg5;
    int arg6;
    DWORD addr;
};

typedef void(__cdecl* AddMessage)(DWORD, int, const char*, int, int, int);

DWORD __stdcall RemoteThread(AddMessageArg* arg)
{
    AddMessage msg = (AddMessage)arg->addr;
    msg(arg->arg1, arg->arg2, arg->arg3, arg->arg4, arg->arg5, arg->arg6);
    return 0;
}

void __stdcall RemoteThread_end() {}

void AddSampMessage(std::string message, int color)
{
    AddMessageArg funcArg;
    funcArg.arg1 = readMem<DWORD>(sampdll + 0x21A0E4);
    funcArg.arg2 = 4;
    funcArg.arg3 = message.c_str();
    funcArg.arg4 = 0;
    funcArg.arg5 = color;
    funcArg.arg6 = 0;
    funcArg.addr = sampdll + 0x64010;
    HANDLE h = OpenProcess(PROCESS_ALL_ACCESS, false, processId);
    LPVOID pRemoteThread = VirtualAllocEx(h, NULL, reinterpret_cast<DWORD_PTR>(RemoteThread_end) - reinterpret_cast<DWORD_PTR>(RemoteThread), MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
    WriteProcessMemory(h, pRemoteThread, reinterpret_cast<LPVOID>(RemoteThread), (reinterpret_cast<DWORD_PTR>(RemoteThread_end) - reinterpret_cast<DWORD_PTR>(RemoteThread)), 0);
    AddMessageArg* myArg = reinterpret_cast<AddMessageArg*>(VirtualAllocEx(h, NULL, sizeof(AddMessageArg), MEM_COMMIT, PAGE_READWRITE));
    writeMem<AddMessageArg>(reinterpret_cast<int>(myArg), funcArg);
    HANDLE h2 = CreateRemoteThread(h, 0, 0, reinterpret_cast<LPTHREAD_START_ROUTINE>(pRemoteThread), myArg, 0, 0);
    WaitForSingleObject(h2, INFINITE);
    CloseHandle(h2);
    VirtualFreeEx(h, myArg, 0, MEM_RELEASE);
    CloseHandle(h);
}

int main()
{
    processId = GetProcessIdByWindowName("GTA:SA:MP");
    sampdll = GetModuleBaseAddress(processId, "samp.dll");
    AddSampMessage("This is C++, wow!", 0);
}
 

_NeliN_

Новичок
10
1
C++:
#include <windows.h>
#include <tlhelp32.h>
#include <iostream>
#include <string>
#include <Psapi.h>

using namespace std;


#define FUNC_CMessages__AddMessageJumpQ 0x69F1E0


DWORD GetProcessIdByName(const std::wstring& proc_name) {
    

    PROCESSENTRY32 entry;
    entry.dwSize = sizeof(PROCESSENTRY32);
    DWORD ids;
    DWORD mids;
    HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, NULL);

    if (Process32First(snapshot, &entry)) {
        while (Process32Next(snapshot, &entry))
            if (entry.szExeFile == proc_name) {
                mids = entry.th32ModuleID;
                ids = entry.th32ProcessID;
                cout << hex << mids;
                break;
            }
    }
    return ids;
}

DWORD getModuleBaseAddress(DWORD pID, const std::wstring& szModuleName) // функция, которая получает этот адрес "samp.dll". её трогать не надо
{
    DWORD dwModuleBaseAddress = 0;
    HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE | TH32CS_SNAPMODULE32, pID);
    if (hSnapshot != INVALID_HANDLE_VALUE)
    {
        
        MODULEENTRY32 ModuleEntry32;
        ModuleEntry32.dwSize = sizeof(MODULEENTRY32);
        if (Module32First(hSnapshot, &ModuleEntry32))
        {
            do
            {
                if (ModuleEntry32.szModule == szModuleName)
                {
                    dwModuleBaseAddress = (DWORD_PTR)ModuleEntry32.modBaseAddr;
                    break;
                }
            } while (Module32Next(hSnapshot, &ModuleEntry32));
        }
        CloseHandle(hSnapshot);
    }
    return dwModuleBaseAddress;
}

struct Struct
{
    char text[256];
    unsigned int time;
    unsigned short flag;
    bool bPreviousBrief;
    DWORD pAdr;
}FuncArgs;

typedef void(__cdecl* _SendMSG)(char*, unsigned int, unsigned short, bool);

DWORD __stdcall RemoteThread(Struct* sArg)
{
    _SendMSG msg = (_SendMSG)sArg->pAdr; // передаем адрес
    msg(sArg->text, sArg->time, sArg->flag, sArg->bPreviousBrief); // вызываем
    return 0;
}
void __stdcall RemoteThread_end() {}


int main() {

    setlocale(LC_ALL, "Russian");
    
    

    strcpy_s(FuncArgs.text, "Hello world!");
    FuncArgs.time = 500;
    FuncArgs.flag = NULL;
    FuncArgs.bPreviousBrief = false;
    FuncArgs.pAdr = 0x69F1E0;


    // получаем хэндл процесса
    HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, GetProcessIdByName(L"gta_sa.exe"));
    // Выделяем память под наш поток в gta_sa
    LPVOID pRemoteThread = VirtualAllocEx(hProcess, NULL, (DWORD_PTR)RemoteThread_end - (DWORD_PTR)RemoteThread, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
    // Записываем его
    WriteProcessMemory(hProcess, pRemoteThread, (LPVOID)RemoteThread, ((DWORD_PTR)RemoteThread_end - (DWORD_PTR)RemoteThread), 0);
    // Выделяем память для нашего объекта в gta_sa
    Struct* myArg = (Struct*)VirtualAllocEx(hProcess, NULL, sizeof(Struct), MEM_COMMIT, PAGE_READWRITE);
    // Записываем его
    WriteProcessMemory(hProcess, myArg, &FuncArgs, sizeof(Struct), NULL);
    // Запускаем наш поток pRemoteThread с аргументами myArg
    HANDLE hThread = CreateRemoteThread(hProcess, 0, 0, (LPTHREAD_START_ROUTINE)pRemoteThread, myArg, 0, 0);
    // Закрываем дескриптор потока
    CloseHandle(hThread);
    // Освобождаем выделенную память
    VirtualFreeEx(hProcess, myArg, sizeof(Struct), MEM_RELEASE);
    // Закрываем дескриптор процесса
    CloseHandle(hProcess);

}
практически не отличается от кода в заголовке, разве что функция получения pID другая (но 100 процентов рабочая), и strcpy заменил на strcpy_s, т.к. на что то ругался

я так то новичок в c++, пытаюсь постепенно понять значения неизвестных функций

UPD: нашел способ поставить strcpy как у автора темы, но все равно получаю ошибку.
SA-MP 0.3.7
Exception At Address: 0x13500013
Base: 0x041E0000

ОЙ ахахаах переключил на x86 и заработало). Не подскажите, а почему раньше не работало?

_SendMSG msg = (_SendMSG)sArg->pAdr; // передаем адрес . В этой строчке мы передаем адрес функции нашему прототипу функции, верно?

А для чего нужна пустая функция void __stdcall RemoteThread_end() {}?
 
Последнее редактирование:

CleanLegend

Известный
Автор темы
Всефорумный модератор
474
927
ОЙ ахахаах переключил на x86 и заработало). Не подскажите, а почему раньше не работало?
если собирал в x64, то отличие в инструкциях, регистрах и механике вызова функций. код x64 в x86 процессе запарно выполнять
А для чего нужна пустая функция void __stdcall RemoteThread_end() {}?
для расчет размера функции RemoteThread


C++:
(DWORD_PTR)RemoteThread_end - (DWORD_PTR)RemoteThread

например:
RemoteThread_end = 0x19100  adr
RemoteThread = 0x19000 adr


0x19100 - 0x19000 =  0x100
размер 0x100
 
  • Нравится
Реакции: Vintik и _NeliN_

etereon

MQ-Team
Проверенный
323
836
для расчет размера функции RemoteThread


C++:
(DWORD_PTR)RemoteThread_end - (DWORD_PTR)RemoteThread

например:
RemoteThread_end = 0x19100  adr
RemoteThread = 0x19000 adr


0x19100 - 0x19000 =  0x100
размер 0x100
Лучше по идее бежать по байтам функции RemoteThread и искать \xCC\xCC\xCC в конце, потому что нет гарантии, что RemoteThread_end будет после неё (наверно)
 
  • Нравится
Реакции: Vintik