(C++) "Bot"-Programm für Game schreiben.

Hallo

Ich habe (mehr oder weniger) vor ein sogenanntes "Bot"-Programm für das Spiel MapleStory zu schreiben.

Ich versuche kurz zu erklären, worum ess sich hierbei handlet. Wenn man ingame HP verliert, muss man diese wieder mit hilfe sogenannter "HP-Pots" auffüllen. Die Aufgabe des Botprogramms besteht nun darin, einen HP Pot zu benutzen, sobald die HP auf einen gewissen Wert gesunken sind, also es soll das ganze nur erleichtern, weil man so nicht immer auf den HP Balken achten muss.

Das ganze lässt sich mit den zwei Funktionen GetPixel() und keybd_event() bewerkstelligen. Ich hab das schon bei mehreren Games zuvor gemacht, allerdings will es diesmal einfach nicht funzen. Über google, habe ich dann herausgefunden, dass GameGuard diese Funktionen blockt, bzw. diese "hookt".

Nun meine Frage. Gibt es einen Weg diese Funktionen vor diesem Hook zu "schützen", oder den Hook rückgänig zu machen? Im I-net hab ich so gut wie garnix über api hooking gefunden und wenn, dann nur müll.
 
Probier mal sowas ähnliches wie in dem Beigefügtem Code,
wirst vielleicht nen bisschen brauchen das zu für deine Funktionen
umzuschreiben, aber dann solltest du Ruhe vor Gameguard haben...

Greets
Secure API.cpp
Code:
// Secure-Api Class
// Copyright (c) Marcin 'Organner' Jakacki 2004
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
// 
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

// Notes:
// 1) (*pOrig_GetModuleHandleA) is empty, you need to pick a value for it before sInitialize call.
// 2) Make sure you called sInitialize once before any Secure-Api call!
// 3) Crypt strings

#include <Windows.h>
#include "Secure Api.h"

//User32.dll's functions
FARPROC pOrig_MessageBoxA;
FARPROC pOrig_FindWindowA;
//Kernel32.dll's functions
FARPROC pOrig_LoadLibraryA;
FARPROC pOrig_GetModuleHandleA;
FARPROC pOrig_CreateFileA;
FARPROC pOrig_CreateThread;
FARPROC pOrig_GetTickCount;
FARPROC pOrig_IsDebuggerPresent;
FARPROC pOrig_Sleep;
FARPROC pOrig_ExitProcess;
FARPROC pOrig_WriteProcessMemory;
FARPROC pOrig_ReadProcessMemory;
FARPROC pOrig_VirtualProtect;
FARPROC pOrig_VirtualQuery;
FARPROC pOrig_VirtualAlloc;
//Variables
DWORD dwReturnValue;
CSecureApi sApi;
FARPROC ExportGet( const HMODULE Image, const char* Function );
//=====================================================================================
VOID CSecureApi::sInitialize( VOID )
{

	**HINSTANCE hTemp			= ::LoadLibrary( "Kernel32.dll" );
	**pOrig_GetModuleHandleA	= ::GetProcAddress( hTemp, "GetModuleHandleA" );
	// Call this far away... (not in sInitialize)

	HINSTANCE hUser32   = sApi.sGetModuleHandle( "USER32.dll"   );
	HINSTANCE hKernel32 = sApi.sGetModuleHandle( "KERNEL32.dll" );

	pOrig_MessageBoxA			= ExportGet( hUser32, "MessageBoxA" );
	pOrig_FindWindowA			= ExportGet( hUser32, "FindWindowA" );
	pOrig_LoadLibraryA			= ExportGet( hKernel32, "LoadLibraryA"	 );
	pOrig_CreateFileA			= ExportGet( hKernel32, "CreateFileA"	 );
	pOrig_CreateThread			= ExportGet( hKernel32, "CreateThread"	 );
	pOrig_GetTickCount			= ExportGet( hKernel32, "GetTickCount"	 );
	pOrig_IsDebuggerPresent		= ExportGet( hKernel32, "IsDebuggerPresent"		);
	pOrig_Sleep					= ExportGet( hKernel32, "Sleep"					);
	pOrig_ExitProcess			= ExportGet( hKernel32, "ExitProcess"			);
	pOrig_WriteProcessMemory	= ExportGet( hKernel32, "WriteProcessMemory"	);
	pOrig_ReadProcessMemory		= ExportGet( hKernel32, "ReadProcessMemory"		);
	pOrig_VirtualProtect		= ExportGet( hKernel32, "VirtualProtect"		);
	pOrig_VirtualQuery			= ExportGet( hKernel32, "VirtualQuery"			);
	pOrig_VirtualAlloc			= ExportGet( hKernel32, "VirtualAlloc"			);
}
//=====================================================================================
VOID CSecureApi::sMessageBox( HWND hWnd, LPCTSTR lpText, LPCTSTR lpCaption, UINT uType )
{
	_asm
	{
		push uType
		push lpCaption
		push lpText
		push hWnd
		call dword ptr [pOrig_MessageBoxA]
	}
}
//=====================================================================================
HWND CSecureApi::sFindWindow( LPCTSTR lpClassName, LPCTSTR lpWindowName )
{
	_asm
	{
		push lpWindowName
		push lpClassName
		call DWORD ptr [pOrig_FindWindowA]
		mov dwReturnValue, eax
	}

	return (HWND)dwReturnValue;
}
//=====================================================================================
HINSTANCE CSecureApi::sLoadLibrary( LPCTSTR szLibrary )
{
	_asm
	{   
		push szLibrary
		call dword ptr [pOrig_LoadLibraryA]
		mov dwReturnValue, eax
	}

	return (HINSTANCE)dwReturnValue;
}
//=====================================================================================
HMODULE CSecureApi::sGetModuleHandle( LPCTSTR lpModuleName )
{
	_asm
	{
		push lpModuleName
		call dword ptr [pOrig_GetModuleHandleA]
		mov dwReturnValue, eax
	}

	return (HMODULE)dwReturnValue;
}
//=====================================================================================
HANDLE CSecureApi::sCreateFile( LPCTSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, HANDLE hTemplateFile )
{
	_asm
	{
		push hTemplateFile
		push dwFlagsAndAttributes
		push dwCreationDisposition
		push lpSecurityAttributes
		push dwShareMode
		push dwDesiredAccess
		push lpFileName
		call dword ptr [pOrig_CreateFileA]
		mov dwReturnValue, eax
	}

	return (HANDLE)dwReturnValue;
}
//=====================================================================================
HANDLE CSecureApi::sCreateThread( LPSECURITY_ATTRIBUTES lpThreadAttributes, SIZE_T dwStackSize, LPTHREAD_START_ROUTINE lpStartAddress, LPVOID lpParameter, DWORD dwCreationFlags, LPDWORD lpThreadId )
{
	_asm
	{
		push lpThreadId
		push dwCreationFlags
		push lpParameter
		push lpStartAddress
		push dwStackSize
		push lpThreadAttributes
		call dword ptr [pOrig_CreateThread]
		mov dwReturnValue, eax
	}
	
	return (HANDLE)dwReturnValue;
}
//=====================================================================================
DWORD CSecureApi::sGetTickCount ( VOID )
{
	_asm
	{
		call dword ptr [pOrig_GetTickCount]
		mov dwReturnValue, eax
	}

	return dwReturnValue;
}

//=====================================================================================
BOOL CSecureApi::sIsDebuggerPresent( VOID )
{
	_asm
	{
		call dword ptr [pOrig_IsDebuggerPresent]
		mov dwReturnValue, eax
	}

	return (BOOL)dwReturnValue;
}
//=====================================================================================
VOID CSecureApi::sSleep( DWORD dwMilliseconds )
{
	_asm
	{
		push dwMilliseconds
		call dword ptr [pOrig_Sleep]
	}
}
//=====================================================================================
VOID CSecureApi::sExitProcess( UINT uExitCode )
{
	_asm
	{
		push uExitCode
		call dword ptr [pOrig_ExitProcess]
	}
}
//=====================================================================================
BOOL CSecureApi::sWriteProcessMemory( HANDLE hProcess, LPVOID lpBaseAddress, LPCVOID lpBuffer, SIZE_T nSize, SIZE_T* lpNumberOfBytesWritten )
{
	_asm
	{
		push lpNumberOfBytesWritten
		push nSize
		push lpBuffer
		push lpBaseAddress
		push hProcess
		call dword ptr [pOrig_WriteProcessMemory]
		mov dwReturnValue, eax
	}

	return (BOOL)dwReturnValue;
}
//=====================================================================================
BOOL CSecureApi::sReadProcessMemory( HANDLE hProcess, LPCVOID lpBaseAddress, LPVOID lpBuffer, SIZE_T nSize, SIZE_T* lpNumberOfBytesRead )
{
	_asm
	{
		push lpNumberOfBytesRead
		push nSize
		push lpBuffer
		push lpBaseAddress
		push hProcess
		call dword ptr [pOrig_ReadProcessMemory]
		mov dwReturnValue, eax
	}

	return (BOOL)dwReturnValue;
}
//=====================================================================================
BOOL CSecureApi::sVirtualProtect( LPVOID lpAddress, SIZE_T dwSize, DWORD flNewProtect, PDWORD lpflOldProtect )
{
	_asm
	{
		push lpflOldProtect
		push flNewProtect
		push dwSize
		push lpAddress
		call dword ptr [pOrig_VirtualProtect]
		mov dwReturnValue, eax
	}

	return (BOOL)dwReturnValue;
}
//=====================================================================================
SIZE_T CSecureApi::sVirtualQuery( LPCVOID lpAddress, PMEMORY_BASIC_INFORMATION lpBuffer, SIZE_T dwLength )
{
	_asm
	{
		push dwLength
		push lpBuffer
		push lpAddress
		call dword ptr [pOrig_VirtualQuery]
		mov dwReturnValue, eax
	}

	return (SIZE_T)dwReturnValue;
}
//=====================================================================================
LPVOID CSecureApi::sVirtualAlloc( LPVOID lpAddress, SIZE_T dwSize, DWORD flAllocationType, DWORD flProtect )
{
	_asm
	{
		push flProtect
		push flAllocationType
		push dwSize
		push lpAddress
		call dword ptr [pOrig_VirtualAlloc]
		mov dwReturnValue, eax
	}

	return (LPVOID)dwReturnValue;
}
//=====================================================================================



// FROM HLH 1.3 .by patrick and dominik
FARPROC ExportGet( const HMODULE Image, const char* Function )
{
	IMAGE_DOS_HEADER *DosHeader;
	IMAGE_NT_HEADERS *PeHeader;
	IMAGE_EXPORT_DIRECTORY *ExportDirectory;
	FARPROC *ExportAddressTable;
	char **ExportNameTable;
	WORD *ExportOrdinalTable;
	char *Name;
	int i,max;

	if (!Image) return NULL;

	DosHeader = (IMAGE_DOS_HEADER *)Image;

	if (DosHeader->e_magic != IMAGE_DOS_SIGNATURE) return NULL;

	if (!DosHeader->e_lfanew) return NULL;

	PeHeader = (IMAGE_NT_HEADERS *)((DWORD)Image + DosHeader->e_lfanew);

	if (PeHeader->Signature != IMAGE_NT_SIGNATURE) return NULL;
	
	if (PeHeader->FileHeader.Machine != IMAGE_FILE_MACHINE_I386) return NULL;	

	ExportDirectory = (IMAGE_EXPORT_DIRECTORY *)((DWORD)Image + PeHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress);

	ExportAddressTable = (FARPROC *)((DWORD)Image + ExportDirectory->AddressOfFunctions);
	ExportNameTable = (char **)((DWORD)Image + ExportDirectory->AddressOfNames);
	ExportOrdinalTable = (WORD *)((DWORD)Image + ExportDirectory->AddressOfNameOrdinals);

	max = ExportDirectory->NumberOfNames;

	for (i = 0; i < max; i++)
	{
		Name = (char *)((DWORD)Image + ExportNameTable[i]);

		if (!strcmp(Name,Function))
		{
			return (FARPROC)((DWORD)Image + (DWORD)ExportAddressTable[ExportOrdinalTable[i]]);
		}
	}

	return NULL;
}

Secure API.h
Code:
// Secure-Api Class
// Copyright (c) Marcin 'Organner' Jakacki 2004
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
// 
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

class CSecureApi
{
	public:
		VOID sInitialize( VOID );
		VOID sMessageBox( HWND hWnd, LPCTSTR lpText, LPCTSTR lpCaption, UINT uType );
		HWND sFindWindow( LPCTSTR lpClassName, LPCTSTR lpWindowName );
		HINSTANCE sLoadLibrary( LPCTSTR szLibrary );
		HMODULE sGetModuleHandle( LPCTSTR lpModuleName );
		HANDLE sCreateFile( LPCTSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, HANDLE hTemplateFile );
		HANDLE sCreateThread( LPSECURITY_ATTRIBUTES lpThreadAttributes, SIZE_T dwStackSize, LPTHREAD_START_ROUTINE lpStartAddress, LPVOID lpParameter, DWORD dwCreationFlags, LPDWORD lpThreadId );
		DWORD sGetTickCount ( VOID );
		BOOL sIsDebuggerPresent( VOID );
		VOID sSleep( DWORD dwMilliseconds );
		VOID sExitProcess( UINT uExitCode );
		BOOL sWriteProcessMemory( HANDLE hProcess, LPVOID lpBaseAddress, LPCVOID lpBuffer, SIZE_T nSize, SIZE_T* lpNumberOfBytesWritten );
		BOOL sReadProcessMemory( HANDLE hProcess, LPCVOID lpBaseAddress, LPVOID lpBuffer, SIZE_T nSize, SIZE_T* lpNumberOfBytesRead );
		BOOL sVirtualProtect( LPVOID lpAddress, SIZE_T dwSize, DWORD flNewProtect, PDWORD lpflOldProtect );
		SIZE_T sVirtualQuery( LPCVOID lpAddress, PMEMORY_BASIC_INFORMATION lpBuffer, SIZE_T dwLength );
		LPVOID sVirtualAlloc( LPVOID lpAddress, SIZE_T dwSize, DWORD flAllocationType, DWORD flProtect );
};
 
Hallo,

Erstmal vielen dank für deine Antworte (ich dachte eigentlich, dass ich erst garkeine kriegen würde :D) und für den Tipp. ich habs mal so ausprobiert

Secure_API.cpp
Code:
#include <Windows.h>
#include <iostream>
#include <conio.h>
#include "Secure_Api.h"
using namespace std;

FARPROC USER32_SendInput;
FARPROC KERNEL32_GetModuleHandleA;
//Variables
DWORD dwReturnValue;
CAPI Kernel;
FARPROC ExportGet( const HMODULE Image, const char* Function );

//=====================================================================================
VOID CAPI::sInitialize( VOID )
{

         HINSTANCE hTemp	 = ::LoadLibrary( "Kernel32.dll" );
         KERNEL32_GetModuleHandleA	 = ::GetProcAddress( hTemp, "GetModuleHandleA" );

	 HINSTANCE hUser32          = Kernel.sGetModuleHandle("USER32.dll");
	 USER32_SendInput = ExportGet(hUser32, "SendInput");

}
//=====================================================================================
HMODULE CAPI::sGetModuleHandle( LPCTSTR lpModuleName )
{
	_asm
	{
		push lpModuleName
		call dword ptr [KERNEL32_GetModuleHandleA]
		mov dwReturnValue, eax
	}

	return (HMODULE)dwReturnValue;
}
//=====================================================================================
UINT CAPI::sSendInput ( UINT diggi_mama1, LPINPUT diggi_mama2, int diggi_mama3 )
{
	_asm
	{
		push diggi_mama3
                push diggi_mama2
                push diggi_mama1
		call dword ptr [USER32_SendInput]
                mov dwReturnValue, eax
	}

        return (UINT)dwReturnValue;
}
//=====================================================================================



// FROM HLH 1.3 .by patrick and dominik
FARPROC ExportGet( const HMODULE Image, const char* Function )
{
	IMAGE_DOS_HEADER *DosHeader;
	IMAGE_NT_HEADERS *PeHeader;
	IMAGE_EXPORT_DIRECTORY *ExportDirectory;
	FARPROC *ExportAddressTable;
	char **ExportNameTable;
	WORD *ExportOrdinalTable;
	char *Name;
	int i,max;

	if (!Image) return NULL;

	DosHeader = (IMAGE_DOS_HEADER *)Image;

	if (DosHeader->e_magic != IMAGE_DOS_SIGNATURE) return NULL;

	if (!DosHeader->e_lfanew) return NULL;

	PeHeader = (IMAGE_NT_HEADERS *)((DWORD)Image + DosHeader->e_lfanew);

	if (PeHeader->Signature != IMAGE_NT_SIGNATURE) return NULL;

	if (PeHeader->FileHeader.Machine != IMAGE_FILE_MACHINE_I386) return NULL;

	ExportDirectory = (IMAGE_EXPORT_DIRECTORY *)((DWORD)Image + PeHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress);

	ExportAddressTable = (FARPROC *)((DWORD)Image + ExportDirectory->AddressOfFunctions);
	ExportNameTable = (char **)((DWORD)Image + ExportDirectory->AddressOfNames);
	ExportOrdinalTable = (WORD *)((DWORD)Image + ExportDirectory->AddressOfNameOrdinals);

	max = ExportDirectory->NumberOfNames;

	for (i = 0; i < max; i++)
	{
		Name = (char *)((DWORD)Image + ExportNameTable[i]);

		if (!strcmp(Name,Function))
		{
			return (FARPROC)((DWORD)Image + (DWORD)ExportAddressTable[ExportOrdinalTable[i]]);
		}
	}

	return NULL;
}

int main(){

   INPUT      Input;
   MOUSEINPUT mInput;

   Input.type     = INPUT_MOUSE;
   Input.mi       = mInput;
   mInput.dwFlags = MOUSEEVENTF_LEFTDOWN | MOUSEEVENTF_LEFTUP;

   while(1){

      Sleep(1000);
      Kernel.sInitialize();
      Kernel.sSendInput(2, &Input, sizeof(Input));

   }

}

Secure_Api.h
Code:
class CAPI
{
	public:
		VOID sInitialize( VOID );
                UINT sSendInput( UINT diggi_mama1, LPINPUT diggi_mama2, int diggi_mama3 );
		HMODULE sGetModuleHandle( LPCTSTR lpModuleName );


};


Das Simulieren des Mausklicks funktioniert zwar, aber im Game regt sich nach wie vor nichts ...
 
Wenn man Cheats für Spiele schreiben will, die mit Anticheatmaßnahmen geschützt werden, dann kommt man um eines nicht herum. Reverse-Engineering.
Du müsstest also ersteinmal herausfinden, wie GameGuard hookt, wie es darüber hinaus noch schützt und dann kann man sich Gegenmaßnahmen überlegen.
Sonst muss man jedesmal spekulieren, ins Blaue raten, nachfragen. "Take your matters into your own hands" ;)
 
Ach und wenn du nähere Infos zum API-Hooking haben willst schau
mal ins HaBo Wiki unter afaik API da hat NeonZero mein Tutorial dazu
reingestellt.

Xalon
 
Original von Xalon
Ach und wenn du nähere Infos zum API-Hooking haben willst schau
mal ins HaBo Wiki unter afaik API da hat NeonZero mein Tutorial dazu
reingestellt.

Xalon

Danke für den Tipp, echt gutes Tutorial, gefällt mir, Respekt :D
Aber noch zwei Fragen.

Wenn ich das ganze mit MessageBox versuche, wie im Tutorial beschrieben, also wenn ich die Adresse der Funktion mittels GetProcAddress ermittle, kann ich die Funktion (also new_address) nicht mehr verwenden, da kaggt mein prog immer ab. Wenn ich die Addresse aber ganz normal ermittle, also mithilfe von Typecast zu unsigned int, kann ich die Funktion (new_address) weiterhin verwenden, warum?^^

Und mit Borland kann ich kein nop-array erstellen, bei asm("NOP") kommt immer ..
"[C++ Fehler] main.cpp(76): E2188 Ausdruckssyntax"
 
Zurück
Oben