Добрый день. Прошлая заметка о принципе создания чита, заинтересовала многих. Руководствуясь этим я предположил, что кому-то может оказаться интересным другой способ создания подобных программ. Перед тем как начать скажу: «Все ниже описанное Вы, если решите применить на деле, используете на свой страх и риск. Все описанное здесь приводится, исключительно, для общего развития».
Для примера будем использовать стандартную «рыбу» для подобных программ/трейнеров. Весь принцип работы заключается в нахождении нужных нам адресов/смещений в память программы и изменении их значений на свои.
И так, для начала нам понадобятся:
ArtMoney/TSearch — для поиска значений.
ollydbg — дебагер для поиска адресов.
Посмотреть ролик:
Разъясняю:
1) Первоначально находим адрес в памяти игры, по которому хранится флаг отвечающий за условие показывать/скрыть юнита.
2) Далее, в дебагере, находим этот адрес и ставим точку остановки на его вызов. Переходим туда откуда это произошло. Создаем микро сбой. Копируем значения (выделенные красным) — это и есть то, что мы должны записывать в память программы при активации чита — 6F3A1563 66:B9 0F00.
66:B9 0F00 это и есть наши волшебные байты, запишем их как 0x66 0xB9 0x0F 0x00. И запишем в 6F3A1563 со смещением на единицу.
Находим дескриптор окна и устанавливаем привилегии для нашего маркера.
Далее можно модифицировать память
Для удобства можно передать адреса относительно библиотеки Game.dll, что может увеличить срок жизни нашей программы без пересборки — если в игре будут обновлены другие библиотеки. Для этого нужно знать ее адрес
Вот в принципе и все.
Для примера будем использовать стандартную «рыбу» для подобных программ/трейнеров. Весь принцип работы заключается в нахождении нужных нам адресов/смещений в память программы и изменении их значений на свои.
И так, для начала нам понадобятся:
ArtMoney/TSearch — для поиска значений.
ollydbg — дебагер для поиска адресов.
Посмотреть ролик:
Разъясняю:
1) Первоначально находим адрес в памяти игры, по которому хранится флаг отвечающий за условие показывать/скрыть юнита.
2) Далее, в дебагере, находим этот адрес и ставим точку остановки на его вызов. Переходим туда откуда это произошло. Создаем микро сбой. Копируем значения (выделенные красным) — это и есть то, что мы должны записывать в память программы при активации чита — 6F3A1563 66:B9 0F00.
66:B9 0F00 это и есть наши волшебные байты, запишем их как 0x66 0xB9 0x0F 0x00. И запишем в 6F3A1563 со смещением на единицу.
Находим дескриптор окна и устанавливаем привилегии для нашего маркера.
LPSTR gameWindowTitle = "Warcraft III"; HWND hWnd=::FindWindow(NULL, gameWindowTitle); if (hWnd != NULL) { HANDLE currentProccess = GetCurrentProcess(); HANDLE token; BOOL retValue = OpenProcessToken(currentProccess, 40, &token); LUID luid; LPSTR debugPrivilege = "SeDebugPrivilege"; retValue = LookupPrivilegeValue(NULL, debugPrivilege, &luid); TOKEN_PRIVILEGES newState, preState; DWORD returnLength; newState.PrivilegeCount = 1; newState.Privileges[0].Luid = luid; newState.Privileges[0].Attributes = 2; retValue = AdjustTokenPrivileges(token, FALSE, &newState, 28, &preState, &returnLength); DWORD PID; DWORD TID = ::GetWindowThreadProcessId(hWnd, &PID); openedProccess = OpenProcess( PROCESS_ALL_ACCESS | PROCESS_TERMINATE | PROCESS_VM_OPERATION | PROCESS_VM_READ| PROCESS_VM_WRITE, FALSE, PID); ... }
Далее можно модифицировать память
DWORD data = 0x66; WriteProcessMemory(openedProccess, (LPVOID)(6F3A1563), &data, 1, 0); data = 0xB9; WriteProcessMemory(openedProccess, (LPVOID)(6F3A1564), &data, 1, 0); data = 0x0F; WriteProcessMemory(openedProccess, (LPVOID)(6F3A1565), &data, 1, 0); data = 0x00; WriteProcessMemory(openedProccess, (LPVOID)(6F3A1566), &data, 1, 0);
Для удобства можно передать адреса относительно библиотеки Game.dll, что может увеличить срок жизни нашей программы без пересборки — если в игре будут обновлены другие библиотеки. Для этого нужно знать ее адрес
DWORD GetModuleBase(HANDLE hProc, LPSTR sModuleName) { HMODULE hMods[8]; DWORD cbNeeded; unsigned int i; if(EnumProcessModules(hProc, hMods, sizeof(hMods), &cbNeeded)) { for ( i = 0; i < (cbNeeded / sizeof(HMODULE)); i++ ) { TCHAR szModName[MAX_PATH]; if ( GetModuleBaseName(hProc, hMods[i], szModName, sizeof(szModName) / sizeof(TCHAR))) { if(strstr(szModName, sModuleName)) { return (DWORD)hMods[i]; } _tprintf( TEXT("\t%s (0x%08X)\n"), szModName, hMods[i] ); } } } return 0x00; } bool WriteData(DWORD address, DWORD data) { return WriteProcessMemory(openedProccess, (LPVOID)(gameOffset + address), &data, 1, 0); } ... LPSTR gameLibraryName = "Game.dll"; gameOffset = GetModuleBase(openedProccess, gameLibraryName); ...
Вот в принципе и все.
