ANTICHAT

ANTICHAT (https://forum.antichat.xyz/index.php)
-   Общие вопросы программирования (https://forum.antichat.xyz/forumdisplay.php?f=206)
-   -   unload internal cheat (https://forum.antichat.xyz/showthread.php?t=1546414)

rhjossss 28.12.2025 06:52

Всех приветствую, столкнулся с проблемой , при добавлении в чит функционал анлоада (всего чита), получаю краш игры, подскажите пожалуйста какую последовательность нужно соблюдать при анхуке функций и после удаления их самих.

Сейчас логика такая:

Этап 1 — Cheat::Unload() (синхронный):

main.cpp:





Код:

void
Cheat
::
Unload
(
)
{
// 1. Скрываем курсор SAMP если меню открыто
if
(
pMenu
->
bOpen
)
pSAMP
->
toggleSAMPCursor
(
0
)
;
// 2. Удаляем хуки и основные компоненты
delete
pHooks
;
// Снимаем хуки с игры
delete
pD3DHook
;
// Снимаем хук DirectX
delete
pKeyHook
;
// Снимаем хук клавиатуры
delete
pRakClient
;
// Отключаем сетевой клиент
delete
pAimbot
;
// Удаляем аимбот
delete
pVisuals
;
// Удаляем визуалы
// 3. Запускаем отдельный поток для финальной выгрузки
CreateThread
(
NULL
,
NULL
,
LPTHREAD_START_ROUTINE
(
UnloadThread
)
,
g_hModule
,
NULL
,
NULL
)
;
}



Этап 2 — UnloadThread() (асинхронный):

main.cpp:





Код:

DWORD WINAPI
UnloadThread
(
HMODULE hModule
)
{
Sleep
(
100
)
;
// Ждём 100мс чтобы основной поток завершил работу
delete
pMenu
;
// Удаляем меню
delete
pTextures
;
// Удаляем текстуры
delete
pSAMP
;
// Удаляем SAMP интерфейс
FreeLibraryAndExitThread
(
hModule
,
0
)
;
// Выгружаем DLL из памяти
}



Почему два этапа?

А потому что:

Нельзя вызвать FreeLibrary из того же потока, который выполняет код DLL — это приведёт к крашу

FreeLibraryAndExitThread — специальная WinAPI функция, которая атомарно выгружает DLL и завершает поток

Sleep(100) даёт время основному потоку завершить рендеринг текущего кадра

Если ошибся то поправьте

Связь с g_hModule

В main.cpp при загрузке DLL сохраняется её handle:

main.cpp:





Код:

HMODULE g_hModule
=
NULL
;
BOOL APIENTRY
DllMain
(
HMODULE hModule
,
DWORD dwReasonForCall
,
LPVOID lpReserved
)
{
case
DLL_PROCESS_ATTACH
:
g_hModule
=
hModule
;
// Сохраняем для последующей выгрузки
.
.
.
}



Этот g_hModule потом передаётся в UnloadThread для вызова FreeLibraryAndExitThread.

g305noobo 28.12.2025 12:34

Приатачься к процессу и посмотри https://www.blast.hk/threads/20320/

А так, мб хук какой то забыл снять и крашит.

opmbaby 28.12.2025 12:37

вот пример как делал я у меня все работает

unload.cpp:





Код:

#include "unload.h"
#include
#include "skStr.h"
extern
"C"
IMAGE_DOS_HEADER __ImageBase
;
#include "menu.h"
#include "wallhack.h"
#include "player.h"
#include "silent.h"
#include "misc.h"
#include "imgui/imgui.h"
#include "imgui/imgui_impl_dx9.h"
#include "imgui/imgui_impl_win32.h"
extern
volatile
bool
gShuttingDown
;
namespace
unload
{
static
void
ClearImGui
(
)
{
if
(
ImGui
::
GetCurrentContext
(
)
)
{
ImGui_ImplDX9_Shutdown
(
)
;
ImGui_ImplWin32_Shutdown
(
)
;
ImGui
::
DestroyContext
(
)
;
}
}
static
DWORD WINAPI
UnloadWorker
(
LPVOID param
)
{
gShuttingDown
=
true
;
Sleep
(
150
)
;
__try
{
wallhack
::
gESPEnabled
=
false
;
wallhack
::
gLinesEnabled
=
false
;
wallhack
::
gSkeletonEnabled
=
false
;
wallhack
::
gDistanceEnabled
=
false
;
wallhack
::
gHealthBarEnabled
=
false
;
wallhack
::
gArmorBarEnabled
=
false
;
wallhack
::
gNameEnabled
=
false
;
wallhack
::
gChamsEnabled
=
false
;
wallhack
::
gESPCarEnabled
=
false
;
wallhack
::
gPlatformDetectorEnabled
=
false
;
}
__except
(
1
)
{
}
HMODULE hMod
=
nullptr
;
if
(
GetModuleHandleEx
(
GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS
,
(
LPCTSTR
)
&
__ImageBase
,
&
hMod
)
&&
hMod
)
{
FreeLibraryAndExitThread
(
hMod
,
0
)
;
}
return
0
;
}
void
Unload
(
bool
removeFiles
)
{
CreateThread
(
nullptr
,
0
,
UnloadWorker
,
nullptr
,
0
,
nullptr
)
;
}
}


g305noobo 28.12.2025 12:43

Цитата:

Сообщение от opmbaby

вот пример как делал я у меня все работает

unload.cpp:





Код:

#include "unload.h"
#include
#include "skStr.h"
extern
"C"
IMAGE_DOS_HEADER __ImageBase
;
#include "menu.h"
#include "wallhack.h"
#include "player.h"
#include "silent.h"
#include "misc.h"
#include "imgui/imgui.h"
#include "imgui/imgui_impl_dx9.h"
#include "imgui/imgui_impl_win32.h"
extern
volatile
bool
gShuttingDown
;
namespace
unload
{
static
void
ClearImGui
(
)
{
if
(
ImGui
::
GetCurrentContext
(
)
)
{
ImGui_ImplDX9_Shutdown
(
)
;
ImGui_ImplWin32_Shutdown
(
)
;
ImGui
::
DestroyContext
(
)
;
}
}
static
DWORD WINAPI
UnloadWorker
(
LPVOID param
)
{
gShuttingDown
=
true
;
Sleep
(
150
)
;
__try
{
wallhack
::
gESPEnabled
=
false
;
wallhack
::
gLinesEnabled
=
false
;
wallhack
::
gSkeletonEnabled
=
false
;
wallhack
::
gDistanceEnabled
=
false
;
wallhack
::
gHealthBarEnabled
=
false
;
wallhack
::
gArmorBarEnabled
=
false
;
wallhack
::
gNameEnabled
=
false
;
wallhack
::
gChamsEnabled
=
false
;
wallhack
::
gESPCarEnabled
=
false
;
wallhack
::
gPlatformDetectorEnabled
=
false
;
}
__except
(
1
)
{
}
HMODULE hMod
=
nullptr
;
if
(
GetModuleHandleEx
(
GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS
,
(
LPCTSTR
)
&
__ImageBase
,
&
hMod
)
&&
hMod
)
{
FreeLibraryAndExitThread
(
hMod
,
0
)
;
}
return
0
;
}
void
Unload
(
bool
removeFiles
)
{
CreateThread
(
nullptr
,
0
,
UnloadWorker
,
nullptr
,
0
,
nullptr
)
;
}
}



Для чего булы обернул в SEH?

opmbaby 28.12.2025 12:48

Цитата:

Сообщение от g305noobo

Для чего булы обернул в SEH?

это чтобы игра не крашнулась при выгрузке, если при отключении функций возникнет ошибка памяти или конфликт потоков, seh её просто проигнорит и даст дллке спокойно выгрузиться, вместо того чтобы убить процесс игры

g305noobo 28.12.2025 13:47

Цитата:

Сообщение от opmbaby

это чтобы игра не крашнулась при выгрузке, если при отключении функций возникнет ошибка памяти или конфликт потоков, seh её просто проигнорит и даст дллке спокойно выгрузиться, вместо того чтобы убить процесс игры

Звучит как лютый костыль

opmbaby 28.12.2025 15:13

Цитата:

Сообщение от g305noobo

Звучит как лютый костыль

ну так и есть, но городить фулл синхронизацию потоков ради одного анлода — оверкилл. проще заглушить эксепшн, чем дебажить гонку в чужом процессе, главное что работает стабильно

sc6ut 29.12.2025 22:51

Цитата:

Сообщение от opmbaby

дебажить гонку в чужом процессе

на твоем куске единственные переменные которые ты изменяешь это свои - поэтому рейс ты сам и создал лол. хуевый аргумент какой-то

opmbaby 29.12.2025 23:28

Цитата:

Сообщение от sc6ut

на твоем куске единственные переменные которые ты изменяешь это свои - поэтому рейс ты сам и создал лол. хуевый аргумент какой-то

дело не в записи, а в чтении - эти переменные чекает рендер-поток игры каждый кадр, если в момент анлода игра находится внутри цикла отрисовки и пытается обратиться к памяти/структурам, которые я уже освобождаю — будет краш, я не могу повесить мьютекс на рендер самой игры, поэтому seh страхует от таймингов, когда дллка уже выходит, а игра еще пытается что-то отрисовать

вайега52 02.01.2026 22:11

Цитата:

Сообщение от opmbaby

дело не в записи, а в чтении - эти переменные чекает рендер-поток игры каждый кадр, если в момент анлода игра находится внутри цикла отрисовки и пытается обратиться к памяти/структурам, которые я уже освобождаю — будет краш, я не могу повесить мьютекс на рендер самой игры, поэтому seh страхует от таймингов, когда дллка уже выходит, а игра еще пытается что-то отрисовать

можно же по идее, если нет нужды, изменять переменные в методе Unload, либо заюзать std::atomic для какой-то переменной, которая будет проверяться в потоке игры и изменяться в твоем потоке


Время: 13:04