Не находил на этом форуме толковых тем с ответом на данный вопрос. Думаю, пора бы одну такую написать.
И так, первое: будьте готовы, что на вдумчивое обучение уйдёт несколько месяцев. Так уж сложилось, что никаких книг по геймхакингу нет (upd. всё же есть — «Game Hacking — Developing Autonomous Bots for Online Games». Совсем забыл о ней. My bad), статей — почти нет. Есть только несколько каналов на YT (в том числе, как минимум 2 — русскоязычных, но там освещаются довольно простые вещи), от них и придётся плясать.
Второе: не думайте, что на все игры читы писать также просто, как на CS. Нет, далеко не все игры имеют хоть какой-то SDK. Придётся долго и кропотливо реверсить всё самому, вообще всё.
А теперь о том, что непосредственно необходимо знать:
1) Язык программирования (ЯП). Можно выбирать любой (буквально), но лучше C++. Для него есть огромное количество всевозможных библиотек, гайдов и прочего-прочего. К тому же, большинство читов пишутся именно на C++. Один из его плюсов, в отличие от того же C# — недекомпилируемость. Да, от реверсинга никто не защищён, но по крайней мере Ваш код не будет нагло скопирован Васей из интернета и запихнут в «его» приватный чит, продаваемый за деньги.
2) ASM. Он нужен Вам как для возможных asm-вставок в своём коде, так и для реверсинга в процессе создания чита. Реверсинг — 50% работы, или даже больше, если речь идёт о чите.
3) Собственно, само умение реверсить. Есть переведённый курс от Рикардо Нарваха, написанная на русском книга RE4B, множество другого материала по данной теме. Остаётся только курить.
4) Понимание структуры PE-файлов. Легко гуглится, прочесть стоит.
5) Наставник. Необязательно, но желательно, чтобы был человек, готовый отвечать на Ваши глупые вопросы (спасибо, Hardee)
6) Умение работать со следующим софтом (перечислю то, с чем сам работал):
1. IDA Pro — очень удобный дизассемблер с плагином HexRays, позволяющим приводить код функций к псевдо-коду на Си. Также имеется и множество других плагинов. В отличие от Ghydra, нормально находит энтрипоинты, распознает API-структуры, без каких-либо проблем дебажит и вообще работает намного быстрее. В этой программе Вы будете реверсить то, что Вам необходимо, изучать, как работает та или иная программа, а также отлаживать программу при надобности.
2. Сканер памяти — выбирайте любой. Сканер нужен для поиска адресов в памяти/оффсетов. Для иного я его не использовал, хотя можно, если хочется.
3. ReClass — удобная программа для реверса структур и классов.
И что мы имеем? Наверное, по крайней мере полгода обучения всему тому, что я перечислил выше. А теперь подумайте, действительно ли Вы так хотите писать читы?
Хорошо, допустим, вы изучили всё, что требуется. Что теперь?
Начните с простых вещей:
1) Запись Вашего значения в адрес памяти игры
2) Хуки отдельных функций и целых ВМТ (о хуках также стоит почитать)
3) Создание автооффсета для поиска в памяти какого-то определённого значения в регулярно обновляющейся игре (тут нужно смотреть в сторону сигнатурного сканирования)
Ну вот и всё. Если вы прошлись по всему изложенному, то можете считать, что готовы начать писать читы. Это увлекательное, хоть и требуемое времени (частенько — нервов) занятие. Надеюсь, пост был не слишком сумбурным. Чао!
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Полезные ссылки:
Добрый день.
Решил поделиться, с Вами, своим небольшим опытом создании чита для Counter-Strike Source v34. Данное приложение было написано исключительно ради спортивного интереса(служит, исключительно, для ознакомления), так как в годы своей юности (изрядно убил времени за этой игрой :() всегда интересовало как же устроены эти программы, хотя теоретически знал как они работают. И вот спустя пол десятка лет (в 2010 году), после игры с коллегами в канун одного из праздников я опять вспомнил о своем давнем *интересе*…
Думаю с прелюдиями стоит закончить, скучно это, переходим к практике.
Будет много кода.
Полных исходников выкладывать не буду, а отдам только абстрактные куски кода, но это рабочие фрагменты.
Для раззадоривания скажу, что в данном чите реализована функция, позволяющая стрелять в любое место и убивать противников которые могут находиться где угодно, главное, чтобы был прострел (можно бежать и убивать всех за спиной), ее я назвал AssShot — для настоящих читеров, не привыкших скрываться (что наглядно продемонстрировано в видео). VAC его не обнаруживает, но это пока кто-то не выложит его в свободный доступ.
Видео записалось с низким фпс, извиняюсь — камтазия, а так никаких фризов модуль не вызывает.
И так, для начала нам понадобится:
Microsoft DirectX — менюшки, есп, имя, хелсы, кросхайр рисовать.
Microsoft Detours — как нетрудно догадаться для подмены вызовов, как собрать и работать с данной либой есть на хабре , я на этом останавливаться не буду.
Source SDK — SDK CSS оно облегчит нам процесс.
Приступим. Создаем новый проект из Source SDK. Удаляем весь хлам в нем — все *.cpp, они нам не нужны.
И так в точке входа создаем свой виток, в котором запускаем бесконечный цикл (для хоткеев) и подменяем вызовы DX:
DllMain.cpp
DWORD MainThread ( LPVOID lpArgs )
{
HMODULE hClient = NULL;
for ( ; hClient == NULL ; Sleep(100) )
hClient = GetModuleHandle("client.dll");
CreateInterfaceFn IGCCreateInterface = (CreateInterfaceFn)GetProcAddress(GetModuleHandle("gameui.dll"), "CreateInterface");
IGameConsole *m_pIGameConsole = (IGameConsole *)IGCCreateInterface(GAMECONSOLE_INTERFACE_VERSION, NULL);
if (m_pIGameConsole->IsConsoleShown() == false)
m_pIGameConsole->Show();
ConMsg(0, "workeDDD!!!n");
//===========================================================================
//===========================================================================
SetupVariables();
DWORD* VTable;
DWORD D3D9ModuleBase;
do {
D3D9ModuleBase = (DWORD)GetModuleHandle(_T("d3d9.dll"));
Sleep(100);
} while(!D3D9ModuleBase);
DWORD DevicePTR = FindPattern(D3D9ModuleBase,0x128000,(PBYTE)"xC7x06x00x00x00x00x89x86x00x00x00x00x89x86","xx????xx????xx");
memcpy(&VTable,(void*)(DevicePTR+2),4);
VoidCSS.res = GetGameResources( );
if (VoidCSS.res != NULL)
{
const char *p0 = VoidCSS.res->GetPlayerName(3);
const char *p1 = VoidCSS.res->GetPlayerName(4);
const char *p2 = VoidCSS.res->GetPlayerName(5);
}
pDrawIndexedPrimitive = (DrawIndexedPrimitive_)DetourFunction((PBYTE)VTable[82],(PBYTE)nDrawIndexedPrimitive);
cPresent = (iPresent) DetourFunction((PBYTE)VTable[17], (PBYTE)fPresent);
cEndScene = (iEndScene) DetourFunction((PBYTE)VTable[42], (PBYTE)fEndScene);
for (;;Sleep (500))
{
if (GetAsyncKeyState (VK_F12) != 0)
{
Beep (2000,200);
VoidCSS.s_wallhack = !VoidCSS.s_wallhack;
}
if (GetAsyncKeyState (VK_INSERT)!= 0)
{
Beep (3000,200);
VoidCSS.s_espbox = !VoidCSS.s_espbox;
}
if (GetAsyncKeyState (VK_DELETE)!= 0)
{
Beep (4000,200);
VoidCSS.s_aimbot = !VoidCSS.s_aimbot;
}
}
return 1;
}
BOOL WINAPI DllMain( HINSTANCE hinstDLL, DWORD dwReason, LPVOID lpReserved )
{
if( dwReason == 1 )
{
DLLModule = hinstDLL;
DWORD dwThreadID;
CreateThread( NULL, NULL, (LPTHREAD_START_ROUTINE)MainThread, NULL, NULL, &dwThreadID);
}
return TRUE;
}
А вот и самая грязная функция, она то и подменяет вызовы CSS:
void SetupVariables()
{
HMODULE hModuleClient = NULL;
HMODULE hModuleEngine = NULL;
HMODULE hModuleVGUIFactory = NULL;
HMODULE hMaterialSysFactory = NULL;
while(!hModuleClient)
{
hModuleClient = GetModuleHandle("client.dll");
hModuleEngine = GetModuleHandle("engine.dll");
hModuleVGUIFactory = GetModuleHandle("vguimatsurface.dll");
hMaterialSysFactory = GetModuleHandle("materialsystem.dll");
Sleep(100);
}
VoidCSS.ClientFactory = (CreateInterfaceFn)GetProcAddress(hModuleClient, "CreateInterface");
VoidCSS.EngineFactory = (CreateInterfaceFn)GetProcAddress(hModuleEngine, "CreateInterface");
VoidCSS.VGUIFactory = (CreateInterfaceFn)GetProcAddress(hModuleVGUIFactory, "CreateInterface");
VoidCSS.MaterialSys = (CreateInterfaceFn)GetProcAddress(hMaterialSysFactory, "CreateInterface");
VoidCSS.g_pdwEngine = (DWORD*) VoidCSS.EngineFactory( VENGINE_CLIENT_INTERFACE_VERSION , NULL );
VoidCSS.g_pdwClient = (DWORD*) VoidCSS.ClientFactory( CLIENT_DLL_INTERFACE_VERSION , NULL );
VoidCSS.g_pdwModelRender = (DWORD*) VoidCSS.EngineFactory( VENGINE_HUDMODEL_INTERFACE_VERSION, NULL );
VoidCSS.g_pEntList = (IClientEntityList*) VoidCSS.ClientFactory( VCLIENTENTITYLIST_INTERFACE_VERSION , NULL );
VoidCSS.g_pEngClient = (IVEngineClient*) VoidCSS.EngineFactory("VEngineClient012", NULL);
VoidCSS.g_pSurface = (vgui::ISurface *) VoidCSS.VGUIFactory ( "VGUI_Surface028", NULL );
VoidCSS.g_pMatSystemSurface = ( IMatSystemSurface* )VoidCSS.g_pSurface->QueryInterface( "MatSystemSurface005" );
VoidCSS.g_pDraw = (IMatSystemSurface*) VoidCSS.g_pSurface->QueryInterface(MAT_SYSTEM_SURFACE_INTERFACE_VERSION);
VoidCSS.g_pEffects = (IVEfx*) VoidCSS.EngineFactory( VENGINE_EFFECTS_INTERFACE_VERSION, NULL );
VoidCSS.g_pCvar = (ICvar*) VoidCSS.EngineFactory( VENGINE_CVAR_INTERFACE_VERSION, NULL );
VoidCSS.g_pEnginetrace = (IEngineTrace*) VoidCSS.EngineFactory( INTERFACEVERSION_ENGINETRACE_CLIENT, NULL );
VoidCSS.g_pDebugoverlay = (IVDebugOverlay*) VoidCSS.EngineFactory( VDEBUG_OVERLAY_INTERFACE_VERSION, NULL );
VoidCSS.g_pEngineCache = (IVEngineCache*) VoidCSS.EngineFactory( VENGINE_CACHE_INTERFACE_VERSION, NULL );
VoidCSS.g_pModelinfo = (IVModelInfoClient*) VoidCSS.EngineFactory( VMODELINFO_CLIENT_INTERFACE_VERSION, NULL );
VoidCSS.g_pEnginevgui = (IEngineVGui*) VoidCSS.EngineFactory( VENGINE_VGUI_VERSION, NULL );
VoidCSS.g_pModelRender = (IVModelRender*) VoidCSS.EngineFactory( VENGINE_HUDMODEL_INTERFACE_VERSION, NULL );
VoidCSS.g_pRender = (IVRenderView*) VoidCSS.EngineFactory( VENGINE_RENDERVIEW_INTERFACE_VERSION, NULL);
VoidCSS.g_pMaterialSystem = (IMaterialSystem *) VoidCSS.MaterialSys( MATERIAL_SYSTEM_INTERFACE_VERSION, NULL );
VoidCSS.g_pBaseCDll = (IBaseClientDLL*) VoidCSS.ClientFactory(CLIENT_DLL_INTERFACE_VERSION, NULL);
VoidCSS.g_pMRender = (IVModelRender*) VoidCSS.EngineFactory(VENGINE_HUDMODEL_INTERFACE_VERSION, NULL);
VoidCSS.g_pdwBaseCDll = (PDWORD*)VoidCSS.g_pBaseCDll;
VoidCSS.g_pdwMRender = (PDWORD*)VoidCSS.g_pMRender;
DWORD dwOld;
memcpy( (void*) &VoidCSS.g_oldClient,(void*)*VoidCSS.g_pdwBaseCDll , sizeof(CClient) );
VoidCSS.gClientFuncs2 = (CClient*)*VoidCSS.g_pdwBaseCDll;
VirtualProtect( (LPVOID)&((CClient*)*VoidCSS.g_pdwBaseCDll)->Init, 4, PAGE_EXECUTE_READWRITE, &dwOld );
VoidCSS.gClientFuncs2->Init = &new_Init;
VirtualProtect( (LPVOID)&((CClient*)*VoidCSS.g_pdwBaseCDll)->CreateMove, 4, PAGE_EXECUTE_READWRITE, &dwOld );
VoidCSS.gClientFuncs2->CreateMove = &new_CreateMove;
VirtualProtect( (LPVOID)&((CClient*)*VoidCSS.g_pdwBaseCDll)->HudUpdate, 4, PAGE_EXECUTE_READWRITE, &dwOld );
VoidCSS.gClientFuncs2->HudUpdate = &new_HudUpdate;
if ( VoidCSS.g_pInput == NULL )
{
PDWORD pdwAddress = ( PDWORD ) ((( DWORD ) VoidCSS.g_oldClient.CreateMove ) + 0x20 );
PDWORD pdwTable = ( PDWORD ) *pdwAddress;
VoidCSS.g_pInput = ( CInput* ) *pdwTable;
}
VoidCSS.g_pGlobals = ( CGlobalVarsBase* )0x200D01A4;
}
Как вы помните мы переопредилили вызов iEndScene, которым и воспользуемся для отрисовки menu, esp, wallHack и Anti flash/smoke/fog:
HRESULT WINAPI fEndScene ( LPDIRECT3DDEVICE9 nDevice )
{
_asm pushad
try
{
if (VoidCSS.s_espbox)
{
if (VoidCSS.pLine == NULL)
D3DXCreateLine(nDevice, &VoidCSS.pLine);
else
{
VoidCSS.g_pEsp->DrawEsp();
VoidCSS.g_pEsp->DrawMap();
}
}
if (Red == NULL)
{
GenerateTexture(nDevice, &Red, D3DCOLOR_ARGB (255 , 255 , 0 , 0 ));
GenerateTexture(nDevice, &Yellow, D3DCOLOR_ARGB (255 , 255 , 255 , 0 ));
GenerateTexture(nDevice, &Green, D3DCOLOR_ARGB (255 , 0 , 255 , 0 ));
GenerateTexture(nDevice, &Blue, D3DCOLOR_ARGB (255 , 0 , 0 , 255 ));
GenerateTexture(nDevice, &Purple, D3DCOLOR_ARGB (255 , 102 , 0 , 153 ));
GenerateTexture(nDevice, &Pink, D3DCOLOR_ARGB (255 , 255 , 20 , 147 ));
GenerateTexture(nDevice, &Orange, D3DCOLOR_ARGB (255 , 255 , 165 , 0 ));
}
D3DVIEWPORT9 viewP;
nDevice->GetViewport( &viewP );
DWORD ScreenCenterX = viewP.Width / 2;
DWORD ScreenCenterY = viewP.Height / 2;
D3DRECT rec16 = {ScreenCenterX-20, ScreenCenterY, ScreenCenterX+ 20, ScreenCenterY+1};
D3DRECT rec17 = {ScreenCenterX, ScreenCenterY-20, ScreenCenterX+ 1,ScreenCenterY+20};
nDevice->Clear( 1, &rec16, D3DCLEAR_TARGET, D3DXCOLOR(1.0, 1.0, 1.0, 1.0), 0, 0 );//white
nDevice->Clear( 1, &rec17, D3DCLEAR_TARGET, D3DXCOLOR(1.0, 1.0, 1.0, 1.0), 0, 0 );
if(menu_setup == false)
{
g_pCMenu = new CDXMenu( nDevice, 10, 160 );
g_pCMenu->addHackBool( "WallHack", &VoidCSS.s_wallhack );
g_pCMenu->addHackBool( "Aimbot", &VoidCSS.s_aimbot );
g_pCMenu->addHackInt( "AimBotFOV", &VoidCSS.s_aimfov );
g_pCMenu->addHackBool( "AssShot", &VoidCSS.s_assshot );
g_pCMenu->addHackBool( "ESPBox", &VoidCSS.s_espbox );
menu_setup = true;
}
if(GetAsyncKeyState( VK_END ) &1)
{
VoidCSS.s_ShowMenu = !VoidCSS.s_ShowMenu;
}
g_pCMenu->showMenu( VoidCSS.s_ShowMenu );
g_pCMenu->updateMenu();
}
catch(...){}
_asm popad
return cEndScene ( nDevice );
}
Для wallHack и Anti то/се нам требуется получит материалы:
IMaterial* TTeam1 = VoidCSS.g_pMaterialSystem->FindMaterial("models\player\t_arctic\t_arctic", "Model textures");
IMaterial* TTeam2 = VoidCSS.g_pMaterialSystem->FindMaterial("models\player\t_guerilla\t_guerilla", "Model textures");
IMaterial* TTeam3 = VoidCSS.g_pMaterialSystem->FindMaterial("models\player\t_leet\t_leet", "Model textures");
IMaterial* TTeam4 = VoidCSS.g_pMaterialSystem->FindMaterial("models\player\t_phoenix\t_phoenix", "Model textures");
IMaterial* CTeam1 = VoidCSS.g_pMaterialSystem->FindMaterial("models\player\ct_gign\ct_gign", "Model textures");
IMaterial* CTeam2 = VoidCSS.g_pMaterialSystem->FindMaterial("models\player\ct_gsg9\ct_gsg9", "Model textures");
IMaterial* CTeam3 = VoidCSS.g_pMaterialSystem->FindMaterial("models\player\ct_sas\ct_sas", "Model textures");
IMaterial* CTeam4 = VoidCSS.g_pMaterialSystem->FindMaterial("models\player\ct_urban\ct_urban", "Model textures");
IMaterial* SmokeStack = VoidCSS.g_pMaterialSystem->FindMaterial( "SmokeStack", "ClientEffect textures" );
IMaterial* FlashEffect = VoidCSS.g_pMaterialSystem->FindMaterial( "effects/flashbang", "ClientEffect textures" );
IMaterial* FlashOverlay = VoidCSS.g_pMaterialSystem->FindMaterial( "effects/flashbang_white", "ClientEffect textures" );
IMaterial* SmokeParticle = VoidCSS.g_pMaterialSystem->FindMaterial( "particle/particle_smokegrenade", "ClientEffect textures" );
IMaterial* SmokeParticle1 = VoidCSS.g_pMaterialSystem->FindMaterial( "particle/particle_smokegrenade1", "ClientEffect textures" );
IMaterial* ScreenSpaceFog = VoidCSS.g_pMaterialSystem->FindMaterial( "particle/screenspace_fog", "ClientEffect textures" );
И говорим рисуем/игнорируем их или нет:
if(VoidCSS.s_wallhack)
{
TTeam1->SetMaterialVarFlag( MATERIAL_VAR_IGNOREZ, true );
TTeam2->SetMaterialVarFlag( MATERIAL_VAR_IGNOREZ, true );
CTeam1->SetMaterialVarFlag( MATERIAL_VAR_IGNOREZ, true );
CTeam2->SetMaterialVarFlag( MATERIAL_VAR_IGNOREZ, true );
TTeam3->SetMaterialVarFlag( MATERIAL_VAR_IGNOREZ, true );
TTeam4->SetMaterialVarFlag( MATERIAL_VAR_IGNOREZ, true );
CTeam3->SetMaterialVarFlag( MATERIAL_VAR_IGNOREZ, true );
CTeam4->SetMaterialVarFlag( MATERIAL_VAR_IGNOREZ, true );
FlashEffect->SetMaterialVarFlag( MATERIAL_VAR_NO_DRAW, true );
FlashOverlay->SetMaterialVarFlag( MATERIAL_VAR_NO_DRAW, true );
SmokeStack->SetMaterialVarFlag( MATERIAL_VAR_NO_DRAW, true );
SmokeParticle->SetMaterialVarFlag( MATERIAL_VAR_NO_DRAW, true );
SmokeParticle1->SetMaterialVarFlag( MATERIAL_VAR_NO_DRAW, true );
ScreenSpaceFog->SetMaterialVarFlag( MATERIAL_VAR_NO_DRAW, true );
}
else
{
TTeam1->SetMaterialVarFlag( MATERIAL_VAR_IGNOREZ, false );
TTeam2->SetMaterialVarFlag( MATERIAL_VAR_IGNOREZ, false );
CTeam1->SetMaterialVarFlag( MATERIAL_VAR_IGNOREZ, false );
CTeam2->SetMaterialVarFlag( MATERIAL_VAR_IGNOREZ, false );
TTeam3->SetMaterialVarFlag( MATERIAL_VAR_IGNOREZ, false );
TTeam4->SetMaterialVarFlag( MATERIAL_VAR_IGNOREZ, false );
CTeam3->SetMaterialVarFlag( MATERIAL_VAR_IGNOREZ, false );
CTeam4->SetMaterialVarFlag( MATERIAL_VAR_IGNOREZ, false );
FlashEffect->SetMaterialVarFlag( MATERIAL_VAR_NO_DRAW, false );
FlashOverlay->SetMaterialVarFlag( MATERIAL_VAR_NO_DRAW, false );
SmokeStack->SetMaterialVarFlag( MATERIAL_VAR_NO_DRAW, false );
SmokeParticle->SetMaterialVarFlag( MATERIAL_VAR_NO_DRAW, false );
SmokeParticle1->SetMaterialVarFlag( MATERIAL_VAR_NO_DRAW, false );
ScreenSpaceFog->SetMaterialVarFlag( MATERIAL_VAR_NO_DRAW, false );
}
Переопределенной функцией new_CreateMove воспользуемся для aimBot и, совсем забыл, bunnyHop:
void __stdcall new_CreateMove ( int sequence_number, float input_sample_frametime, bool active )
{
VoidCSS.g_oldClient.CreateMove( sequence_number , input_sample_frametime , active );
ModelHack();
if ( VoidCSS.g_pInput )
{
CUserCmd* cmd = VoidCSS.g_pInput->GetUserCmd( sequence_number );
if ( VoidCSS.g_pEngClient->IsInGame() )
{
//Aimbot Norecoil Nospread
if( cmd->buttons & IN_ATTACK && VoidCSS.s_aimbot)
VoidCSS.g_pAimbot->AimAtTarget( cmd );
//BunnyHop
if ( cmd->buttons & IN_JUMP )
{
int *iMyFlAgs = (int*) ( (DWORD)VoidCSS.g_pMyPlayer->BaseEnt() + (DWORD)0x2B4 );
int iFlags = *iMyFlAgs;
if( !(iFlags &FL_ONGROUND) )
cmd->buttons &= ~IN_JUMP;
}
}
}
}
В классе аимбота отслеживаем жертву (удостоверившись, что это игрок противоположной команды), перебирая кости находи нужную часть тела (в нашем случае голова) и перемещаем центр экрана в эту точку, делаем выстрел, попутно гася отдачу (antiRecoil). Да забыл сказать, что если включен assShot то возвращаем нашего персонажа в положение до стрельбы (так вот он работает).
void cCAimbot::AimAtTarget( CUserCmd* c )
{
if( VoidCSS.g_pEngClient->IsInGame() == false
|| VoidCSS.g_pEngClient->IsHLTV() == true
|| VoidCSS.g_pMyPlayer->BaseEnt() == NULL )
return;
DropTarget();
//----------------------------------//
player_info_t pinfo;
QAngle* pPunchAngle = ( QAngle* )( (DWORD)VoidCSS.g_pMyPlayer->BaseEnt() + 0xBB0 );
//----------------------------------//
//----------------------------------//
for( int index = 1; index <= VoidCSS.g_pEntList->NumberOfEntities( false ); ++index )
{
if ( index == VoidCSS.g_pEngClient->GetLocalPlayer() )
continue;
IClientEntity* ClientEntity = VoidCSS.g_pEntList->GetClientEntity( index );
if ( ClientEntity == NULL
|| ClientEntity->IsDormant() )
continue;
CBaseEntity* pBaseEntity = ClientEntity->GetBaseEntity();
//Get Life State
int *lifestate = (int*) ( ( DWORD )pBaseEntity + ( DWORD )0x87 );
float fov = (float)VoidCSS.s_aimfov;
if (VoidCSS.s_assshot)
fov = 360.0f;
if( pBaseEntity == NULL/* nothing */
|| pBaseEntity->IsDormant()/* not active */
|| !(*lifestate == LIFE_ALIVE)/* not alive */
|| VoidCSS.g_pEngClient->GetPlayerInfo( index, &pinfo ) == false/* not a player!*/
|| pBaseEntity->GetTeamNumber() == VoidCSS.g_pMyPlayer->BaseEnt()->GetTeamNumber()/*enemy*/
|| !GetBonePosition( 14/*Head*/, vPlayer, c->viewangles, index )
|| GetFov( VoidCSS.g_pMyPlayer->BaseEnt()->GetAbsAngles(), VoidCSS.g_pMyPlayer->BaseEnt()->EyePosition(), vPlayer ) > fov /*4.0f*/
|| !GetVisible( VoidCSS.g_pMyPlayer->BaseEnt()->EyePosition(), vPlayer, pBaseEntity )/* not visible */
|| flBestDist < GetFov( VoidCSS.g_pMyPlayer->BaseEnt()->GetAbsAngles(), VoidCSS.g_pMyPlayer->BaseEnt()->EyePosition(), vPlayer ))
continue;
flBestDist = GetFov( VoidCSS.g_pMyPlayer->BaseEnt()->GetAbsAngles(), VoidCSS.g_pMyPlayer->BaseEnt()->EyePosition(), vPlayer );
m_nTarget = index;
// Calculate the delta origin
Vector vDeltaOrigin = vPlayer - vPlayer;
// Calculate the Latency
float fLatency = VoidCSS.g_pEngClient->GetNetChannelInfo()->GetLatency( FLOW_OUTGOING );
// Compensate the latency
vDeltaOrigin[0] *= fLatency;
vDeltaOrigin[1] *= fLatency;
vDeltaOrigin[2] *= fLatency;
//Apply the prediction
PredictedTargetPosition = vPlayer + vDeltaOrigin;
}
if( m_nTarget == -1 )
return;
CalcAngle( VoidCSS.g_pMyPlayer->BaseEnt()->EyePosition(), PredictedTargetPosition, c->viewangles );
//recoil
c->viewangles.x -= ( pPunchAngle->x *2.0f );
c->viewangles.y -= ( pPunchAngle->y *2.0f );
//aimbot
VoidCSS.g_pEngClient->SetViewAngles( c->viewangles );//aim
//nospread
float flNew[3],flOld[3];
flOld[0] = c->viewangles[0];
flOld[1] = c->viewangles[1];
flOld[2] = c->viewangles[2];
//VoidCSS.g_pNoSpread->GetSpreadFix( c->random_seed, flOld, flNew );
c->viewangles[0] += flNew[0];
c->viewangles[1] += flNew[1];
c->viewangles[2] += flNew[2];
if (VoidCSS.s_assshot)
VoidCSS.g_pEngClient->SetViewAngles( m_angle );
DropTarget();
}
Вот в принципе самые главные части кода. Конечно есть небольшой пучек вспомогательных функций, а также классы для отрисовки меню, чтения файла настроек (у меня это setings.ini) и рисования esp, но в них вроде и так все понятно. На SpeedHack энтузиазма у меня уже не хватило, но подскажу — нужно баловаться с таймингами (правда чревато подвисаниями при плохом пинге).
И так перейдем к инъекции нашей сборки в процесс игры, 2 варианта c++ по хендлу окна или c# по процессу
с++
#include "stdafx.h"
#include <stdio.h>
#include <windows.h>
#define MAXINJECTSIZE 4096
typedef HINSTANCE (*LoadLibrary_Ptr)(LPCTSTR);
typedef FARPROC (*GetProcAddress_Ptr)(HMODULE, LPCSTR lpProcName);
typedef struct _injectionRoutineParam
{
LoadLibrary_Ptr _call_LoadLibrary;
GetProcAddress_Ptr _call_GetProcAddress;
HINSTANCE _ret;
FARPROC _proc;
char _dll_name[1024];
char _proc_name[256];
}InjectionRoutineParam;
DWORD __stdcall injectionThreadRoutine(InjectionRoutineParam* param)
{
HINSTANCE hinstance = param->_call_LoadLibrary((LPCTSTR)param->_dll_name);
param->_ret = hinstance;
FARPROC proc= param->_call_GetProcAddress(hinstance, param->_proc_name);
param->_proc = proc;
return 0;
}
void inject(HANDLE process, char *dllName)
{
char * procName ="HelloWorld";
InjectionRoutineParam param;
DWORD threadId;
void *p = VirtualAllocEx(process, 0, MAXINJECTSIZE, MEM_COMMIT, PAGE_EXECUTE_READWRITE );
void *data = VirtualAllocEx(process, 0, sizeof(InjectionRoutineParam), MEM_COMMIT, PAGE_EXECUTE_READWRITE );
HINSTANCE kernel32=LoadLibrary(_T("KERNEL32.DLL"));
param._call_LoadLibrary = (LoadLibrary_Ptr)GetProcAddress( kernel32, "LoadLibraryA" );
param._call_GetProcAddress = (GetProcAddress_Ptr)GetProcAddress( kernel32, "GetProcAddress" );
memcpy(param._dll_name,dllName,strlen(dllName));
memcpy(param._proc_name, procName, strlen(procName));
WriteProcessMemory(process, p, (void*)&injectionThreadRoutine, MAXINJECTSIZE, 0 );
WriteProcessMemory(process, data, (void*)¶m, sizeof(InjectionRoutineParam), 0 );
HANDLE remoteThread = CreateRemoteThread(process, NULL,0,(DWORD (__stdcall *)(LPVOID))p, data, 0, &threadId);
WaitForSingleObject(remoteThread, INFINITE);
DWORD read;
ReadProcessMemory(process, data, ¶m, sizeof(InjectionRoutineParam), &read);
VirtualFreeEx(process, p, 0, MEM_RELEASE );
VirtualFreeEx(process, data, 0, MEM_RELEASE );
FreeLibrary( kernel32 );
}
void die(char *msg)
{
fprintf(stderr, msg);
exit(-1);
}
#include <string>
#include <windows.h>
#define MAXWAIT 10000
bool insertDll(DWORD procID, std::string dll)
{
//Находим адрес LoadLibraryA, к счастью для нас, она загружается в один адрес для каждого процесса
HMODULE hLocKernel32 = GetModuleHandle(_T("Kernel32"));
FARPROC hLocLoadLibrary = GetProcAddress(hLocKernel32, "LoadLibraryA");
//Получаем привилегии на системный процесс
HANDLE hToken;
TOKEN_PRIVILEGES tkp;
if(OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken))
{
LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &tkp.Privileges[0].Luid);
tkp.PrivilegeCount = 1;
tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
AdjustTokenPrivileges(hToken, 0, &tkp, sizeof(tkp), NULL, NULL);
}
//открываем процесс на полный доступ
HANDLE hProc = OpenProcess(PROCESS_ALL_ACCESS, FALSE, procID);
//Выделите память для хранения пути к Dll файла в памяти процесса
dll += '';
LPVOID hRemoteMem = VirtualAllocEx(hProc, NULL, dll.size(), MEM_COMMIT, PAGE_READWRITE);
//записываем
DWORD numBytesWritten;
WriteProcessMemory(hProc, hRemoteMem, dll.c_str(), dll.size(), &numBytesWritten);
//Создаем удаленный поток
HANDLE hRemoteThread = CreateRemoteThread(hProc, NULL, 0, (LPTHREAD_START_ROUTINE)hLocLoadLibrary, hRemoteMem, 0, NULL);
// cout << hRemoteThread << endl;
//Подождем, пока нить закончится
bool res = false;
if (hRemoteThread)
res = (bool)WaitForSingleObject(hRemoteThread, MAXWAIT) != WAIT_TIMEOUT;
//Подчищаем за собой
VirtualFreeEx(hProc, hRemoteMem, dll.size(), MEM_RELEASE);
//И отпускаем процесс :)
CloseHandle(hProc);
return res;
}
int _tmain(int argc, _TCHAR* argv[])
{
HWND WindowHandle;
DWORD processId;
WindowHandle = FindWindow(NULL, _T("Counter-Strike Source"));
if (WindowHandle)
{
GetWindowThreadProcessId(WindowHandle, &processId);
insertDll(processId, "..\..\client.dll");
}
system("PAUSE");
return EXIT_SUCCESS;
}
с#
using System;
using System.Collections.Generic;
using System.Text;
using System.Diagnostics;
using System.Runtime.InteropServices;
namespace voidLoader
{
public static class Inject
{
private static class WINAPI
{
[DllImport("kernel32.dll", SetLastError = true)]
public static extern IntPtr OpenProcess(
UInt32 dwDesiredAccess,
Int32 bInheritHandle,
UInt32 dwProcessId);
[DllImport("kernel32.dll", SetLastError = true)]
public static extern Int32 CloseHandle(
IntPtr hObject);
[DllImport("kernel32.dll", SetLastError = true)]
public static extern IntPtr GetProcAddress(
IntPtr hModule,
string lpProcName);
[DllImport("kernel32.dll", SetLastError = true)]
public static extern IntPtr GetModuleHandle(
string lpModuleName);
[DllImport("kernel32.dll", SetLastError = true)]
public static extern IntPtr VirtualAllocEx(
IntPtr hProcess,
IntPtr lpAddress,
IntPtr dwSize,
uint flAllocationType,
uint flProtect);
[DllImport("kernel32.dll", SetLastError = true)]
public static extern Int32 WriteProcessMemory(
IntPtr hProcess,
IntPtr lpBaseAddress,
byte[] buffer,
uint size,
out IntPtr lpNumberOfBytesWritten);
[DllImport("kernel32.dll", SetLastError = true)]
public static extern IntPtr CreateRemoteThread(
IntPtr hProcess,
IntPtr lpThreadAttribute,
IntPtr dwStackSize,
IntPtr lpStartAddress,
IntPtr lpParameter,
uint dwCreationFlags,
IntPtr lpThreadId);
public static class VAE_Enums
{
public enum AllocationType
{
MEM_COMMIT = 0x1000,
MEM_RESERVE = 0x2000,
MEM_RESET = 0x80000,
}
public enum ProtectionConstants
{
PAGE_EXECUTE = 0X10,
PAGE_EXECUTE_READ = 0X20,
PAGE_EXECUTE_READWRITE = 0X40,
PAGE_EXECUTE_WRITECOPY = 0X80,
PAGE_NOACCESS = 0X01
}
}
}
public static bool DoInject(
Process pToBeInjected,
string sDllPath,
out string sError)
{
IntPtr hwnd = IntPtr.Zero;
if (!CRT(pToBeInjected, sDllPath, out sError, out hwnd))
{
if (hwnd != (IntPtr)0)
WINAPI.CloseHandle(hwnd);
return false;
}
int wee = Marshal.GetLastWin32Error();
return true;
}
private static bool CRT(
Process pToBeInjected,
string sDllPath,
out string sError,
out IntPtr hwnd)
{
sError = String.Empty;
IntPtr hndProc = WINAPI.OpenProcess(
(0x2 | 0x8 | 0x10 | 0x20 | 0x400),
1,
(uint)pToBeInjected.Id);
hwnd = hndProc;
if (hndProc == (IntPtr)0)
{
sError = "Unable to attatch to process.n";
sError += "Error code: " + Marshal.GetLastWin32Error();
return false;
}
IntPtr lpLLAddress = WINAPI.GetProcAddress(
WINAPI.GetModuleHandle("kernel32.dll"),
"LoadLibraryA");
if (lpLLAddress == (IntPtr)0)
{
sError = "Unable to find address of "LoadLibraryA".n";
sError += "Error code: " + Marshal.GetLastWin32Error();
return false;
}
IntPtr lpAddress = WINAPI.VirtualAllocEx(
hndProc,
(IntPtr)null,
(IntPtr)sDllPath.Length,
(uint)WINAPI.VAE_Enums.AllocationType.MEM_COMMIT |
(uint)WINAPI.VAE_Enums.AllocationType.MEM_RESERVE,
(uint)WINAPI.VAE_Enums.ProtectionConstants.PAGE_EXECUTE_READWRITE);
if (lpAddress == (IntPtr)0)
{
if (lpAddress == (IntPtr)0)
{
sError = "Unable to allocate memory to target process.n";
sError += "Error code: " + Marshal.GetLastWin32Error();
return false;
}
}
byte[] bytes = CalcBytes(sDllPath);
IntPtr ipTmp = IntPtr.Zero;
WINAPI.WriteProcessMemory(
hndProc,
lpAddress,
bytes,
(uint)bytes.Length,
out ipTmp);
if (Marshal.GetLastWin32Error() != 0)
{
sError = "Unable to write memory to process.";
sError += "Error code: " + Marshal.GetLastWin32Error();
return false;
}
IntPtr ipThread = WINAPI.CreateRemoteThread(
hndProc,
(IntPtr)null,
(IntPtr)0,
lpLLAddress,
lpAddress,
0,
(IntPtr)null);
if (ipThread == (IntPtr)0)
{
sError = "Unable to load dll into memory.";
sError += "Error code: " + Marshal.GetLastWin32Error();
return false;
}
return true;
}
private static byte[] CalcBytes(string sToConvert)
{
byte[] bRet = System.Text.Encoding.ASCII.GetBytes(sToConvert);
return bRet;
}
}
}
Ну собственно и сами файлики. (перезалиты на github)
Иногда, играя с какой-нибудь читом, ты думал, Как же его сделали? Смогу ли сделать?
Я попробую показать вам как можно написать простой чит на c++.
Что для этого нужно:
УМЕТЬ РАБОТАТЬ С CHEAT ENGINE(можно посмотреть видео на ютубе если кто не в теме)
VISUAL STUDIO И КАК С НИМ РАБОТАТЬ
В CHEAT ENGINEДЛЯ НАЧАЛА ВЫ НАХОДИТЕ НУЖНЫЙ АДРЕС(КОТОРЫЙ ВЫ ХОТИТЕ ЧТОБЫ ВАШЕ ПРИЛОЖЕНИЕ АВТОМАТИЧЕСКИ МЕНЯЛО ЗНАЧЕНИЕ НА УКАЗАННОЕ)
B VISUAL STUDIO СОЗДАЁМ ПРОЕКТ, ШАБЛОНЫ КОНСОЛЬНОЕ ПРИЛОЖЕНИЕ
И ТАМ ЖЕ ПИШЕМ:
C++:
#include <windows.h>
#include <iostream>
#include <string>
#include <stdio.h>
using namespace std;
int main()
{
DWORD addr = 0x101454D4;//здесь адрес из Cheat Engine, обратите внимание я поставил впереди 0х и потом адрес
DWORD pid;//pid процесса
int data;//эту переменную я буду использовать для записи и чтения
HWND hwd = FindWindow(0, L"Counter-Strike");
GetWindowThreadProcessId(hwd, &pid);
if (!hwd) {
std::cout << "Нету такого окна!" << endl;
//printf("oppa");
system("pause");
return -1;
}
HANDLE hnd = OpenProcess(PROCESS_ALL_ACCESS, false, pid);
if (!hnd) {
std::cout << "Ошибка!" << endl;
system("pause");
return -1;
}
ReadProcessMemory(hnd, (LPVOID)addr, &data, sizeof(nmon), 0);
std::cout << "Значение в Адресе: " <<data<<endl;
std::cout << "На что вы хотите поменять значение: ";
std::cin >> data;
WriteProcessMemory(hnd, (LPVOID)addr, &data, sizeof(nmon), 0);
std::cout<<"Значение изменено!"
system("pause");
}
Вот сам код, я попробую объяснить его.
Подключаем что нам нужно:
C++:
#include <windows.h>
#include <iostream>
#include <string>
#include <stdio.h>
using namespace std;
Создаём переменные
C++:
DWORD addr = 0x101454D4;//здесь адрес из Cheat Engine, обратите внимание я поставил впереди 0х и потом адрес
DWORD pid;
ПОлучаем pid процесса, обратите внимание, я использовал название окна и находил его pid, но вы можете делать так, как показывал дарвин
C++:
HWND hwd = FindWindow(0, L"Counter-Strike");
GetWindowThreadProcessId(hwd, &pid);
если делайте как дарвин вот код:
C++:
pid=GetProcessID("csgo.exe");
Проверка, есть ли такое окно,
C++:
if (!hnd) {
std::cout << "Ошибка!" << endl;
system("pause");
return -1;
}
обратите внимание если вы сделали как дарвин то проверку рекомендуется сделать так:
C++:
if (!pid) {
std::cout << "Ошибка!" << endl;
system("pause");
return -1;
}
тут мы читаем то, что лежит в указанном адресе(addr) и выводим на экран
C++:
ReadProcessMemory(hnd, (LPVOID)addr, &data, sizeof(nmon), 0);
std::cout << "Значение в Адресе: " << data<<endl;
тут мы меняем значение:
C++:
std::cout << "На что вы хотите поменять значение: ";
std::cin >> data;
WriteProcessMemory(hnd, (LPVOID)addr, &data, sizeof(nmon), 0);
std::cout<<"Значение изменено!"
system("pause");
Думаю вам был полезен данный гайд!
Listen to this article
Чтобы открыть контент, необходимо пройти быструю регистрацию или войти в свой профиль. После этого Вы получите полный доступ ко всем материалам на портале.
Спасибо что вы с нами!
ВНИМАНИЕ! Все представленные ссылки в статьях могут вести на вредоносные сайты либо содержать вирусы. Переходите по ним на свой страхъ и риск. Тот кто целенаправлено зашел на статью знает что делает. Не нажимайте на все подряд бездумно.
Некоторые статьи были переведены с английского языка с помощью системы машинного перевода и могут содержать неточности или грамматические ошибки.
ВСЯ РАЗМЕЩЕННАЯ ИНФОРМАЦИЯ НА СТРАНИЦАХ ПОРТАЛА ВЗЯТА ИЗ ОТКРЫТЫХ ИСТОЧНИКОВ
БОЛЬШАЯ ЧАСТЬ ИНФОРМАЦИИ ПРЕДОСТАВЛЯЕТСЯ АБСОЛЮТНО БЕСПЛАТНО
Если Вам понравилась статья — поделитесь с друзьями
36 просмотров
Любая информация, размещенная на сайте https://rucore.net, предназначена только для свободного изучения пользователями сайта. Наша команда прилагает все усилия для того, чтобы предоставить на этом сайте достоверную и полезную информацию, которая отвечает на вопросы пользователей сайта. Ни при каких обстоятельствах Администрация Сайта не несёт ответственности за какой-либо прямой, непрямой, особый или иной косвенный ущерб в результате использования информации на этом Сайте или на любом другом сайте, на который имеется гиперссылка с данного cайта, возникновение зависимости, снижения продуктивности, увольнения или прерывания трудовой активности, а равно отчисления из учебных учреждений, за любую упущенную выгоду, приостановку хозяйственной деятельности, потерю программ или данных в Ваших информационных системах или иным образом, возникшие в связи с доступом, использованием или невозможностью использования Сайта, Содержимого или какого-либо связанного интернет-сайта, или неработоспособностью, ошибкой, упущением, перебоем, дефектом, простоем в работе или задержкой в передаче, компьютерным вирусом или системным сбоем, даже если администрация будет явно поставлена в известность о возможности такого ущерба.
Используя данный Сайт, Вы выражаете свое согласие с «Отказом от ответственности» и установленными Правилами и принимаете всю ответственность, которая может быть на Вас возложена. А так же Вы можете ознакомиться с полной версией данного «отказа от ответственности» и нашей «политики конфиденциальности» по следующей ссылке.
Цель данного раздела сайта
Основной задачей закрытого раздела сайта, является сбор (парсинг) и сохраниение в базе данных наиболее интересных и качественных материалов из разнообразных источников. Более подробней можно ознакомиться по ссылке.
Если вам понравились материалы сайта, вы можете поддержать проект финансово, переведя некоторую сумму с банковской карты, счёта мобильного телефона или из кошелька ЮMoney.