Как пишутся читы для игр

Не находил на этом форуме толковых тем с ответом на данный вопрос. Думаю, пора бы одну такую написать.

И так, первое: будьте готовы, что на вдумчивое обучение уйдёт несколько месяцев. Так уж сложилось, что никаких книг по геймхакингу нет (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) Наставник. Необязательно, но желательно, чтобы был человек, готовый отвечать на Ваши глупые вопросы :D (спасибо, 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*)&param, sizeof(InjectionRoutineParam), 0 );
     
     HANDLE remoteThread = CreateRemoteThread(process, NULL,0,(DWORD (__stdcall *)(LPVOID))p, data, 0, &threadId);
     WaitForSingleObject(remoteThread, INFINITE);
     DWORD read;
     ReadProcessMemory(process, data, &param, 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.

  • Как правильно пишется ваша честь
  • Как пишутся цифры от одного до 10 по английски
  • Как правильно пишется ватрушка или ватрушка
  • Как пишутся слова с приставкой пол
  • Как пишутся римские цифры на клавиатуре телефона