// SpiderPatch.cpp : Defines the entry point for the console application. // #include "stdafx.h" UCHAR InjCode[] = { 0x50, 0x48, 0x31, 0xC0, 0x41, 0x8B, 0x43, 0x14, 0x83, 0xE8, 0x10, 0x41, 0x89, 0x43, 0x14, 0x48, 0x8B, 0xCE, 0x58, 0x90, 0x90, 0x90, 0x90, 0x90 }; UCHAR PointsSignature[] = { 0x41, 0xFF, 0x4B, 0x14, 0x48, 0x8B, 0xCE, 0xE8, 0xDA, 0x1B, 0x00, 0x00 }; VOID MakeJump( DWORD64 from, DWORD64 to, CHAR* jmpbytes ) //works only with 32bit code. { jmpbytes[0] = 0xE9; *(DWORD64*)(jmpbytes + 1) = to - from - 5; } VOID Make32Jump( DWORD64 from, DWORD64 to, CHAR* jmpbytes ) { jmpbytes[0] = 0xFF; jmpbytes[1] = 0x24; jmpbytes[2] = 0x25; *(DWORD*)(jmpbytes + 3) = to; } CHAR* FindSignature( CHAR* dwStart, CHAR* dwEnd, UCHAR* szSignature, DWORD dwSize ) { do { if( memcmp( reinterpret_cast< void* >( dwStart ), szSignature, dwSize ) == NULL ) { return dwStart; } } while( ++dwStart < dwEnd - dwSize ); return ( CHAR* ) -1; } BOOL FindProcessByName( TCHAR* ProcessName, PROCESSENTRY32* processEntry ) { HANDLE hSnapshot = CreateToolhelp32Snapshot( TH32CS_SNAPPROCESS, NULL ); if( Process32First( hSnapshot, processEntry ) ) { do { if( !_tcscmp( processEntry->szExeFile, ProcessName ) ) { CloseHandle( hSnapshot ); return TRUE; } } while ( Process32Next( hSnapshot, processEntry ) ); } CloseHandle( hSnapshot ); return FALSE; } BOOL FindModuleByName( TCHAR* ModuleName, MODULEENTRY32* moduleEntry, DWORD dwProcessId ) { HANDLE hSnapshot = CreateToolhelp32Snapshot( TH32CS_SNAPMODULE, dwProcessId ); if( hSnapshot == INVALID_HANDLE_VALUE ) { std::wcout << L"Something went wrong with ToolHelp func. Code: " << GetLastError( ) << L"\n"; return FALSE; } if( Module32First( hSnapshot, moduleEntry ) ) { do { std::wcout << moduleEntry->szModule << L"\n"; if( !_tcscmp( moduleEntry->szModule, ModuleName ) ) { return TRUE; } } while( Module32Next( hSnapshot, moduleEntry ) ); } else { std::wcout << L"Could not find first module. " << GetLastError() << "\n"; } CloseHandle( hSnapshot ); return FALSE; } int _tmain(int argc, _TCHAR* argv[]) { DWORD dwFuncAddress; TCHAR* szProcessName = _T( "SpiderSolitaire.exe" ); PROCESSENTRY32 *pProcessEntry = new PROCESSENTRY32; pProcessEntry->dwSize = sizeof( PROCESSENTRY32 ); if( FindProcessByName( szProcessName, pProcessEntry ) ) { MODULEENTRY32* moduleEntry = new MODULEENTRY32; moduleEntry->dwSize = sizeof( MODULEENTRY32 ); if( FindModuleByName( szProcessName, moduleEntry, pProcessEntry->th32ProcessID ) ) { HANDLE hProcess = OpenProcess( PROCESS_ALL_ACCESS, FALSE, pProcessEntry->th32ProcessID ); CHAR* ucModule = new CHAR[ moduleEntry->modBaseSize ]; if( ReadProcessMemory( hProcess, moduleEntry->modBaseAddr, ucModule, moduleEntry->modBaseSize, NULL ) ) { CHAR* cOffset = (CHAR*)(moduleEntry->modBaseAddr + (DWORD)FindSignature( ucModule, ucModule + moduleEntry->modBaseSize, PointsSignature, sizeof( PointsSignature ) ) - (DWORD)ucModule ); if( ( DWORD )cOffset != -1 ) { DWORD dwOlpProtect; CHAR cWriteMem[ sizeof( InjCode ) * 5 ] = { 0x0 }; DWORD dwFuncAddress = (DWORD)( moduleEntry->modBaseAddr + (DWORD)FindSignature( ucModule, ucModule + moduleEntry->modBaseSize, (UCHAR*)cWriteMem, sizeof( cWriteMem ) ) - (DWORD)ucModule ); if( dwFuncAddress != -1 ) { dwFuncAddress += sizeof( InjCode ) * 2; std::cout << "Function will be written in " << (DWORD*)dwFuncAddress << ".\n"; if( VirtualProtectEx( hProcess, (VOID*)dwFuncAddress, sizeof( InjCode ), PAGE_EXECUTE_READWRITE, &dwOlpProtect ) ) { CHAR cJmpCode[5]; MakeJump( (DWORD)dwFuncAddress + sizeof( InjCode ) - sizeof( cJmpCode ), (DWORD)(cOffset + sizeof( cJmpCode )), cJmpCode ); memcpy_s( InjCode + sizeof( InjCode ) - sizeof( cJmpCode ), sizeof( cJmpCode ), cJmpCode, sizeof( cJmpCode ) ); if( WriteProcessMemory( hProcess, (DWORD*)dwFuncAddress, InjCode, sizeof( InjCode ), NULL ) ) { CHAR cJmpToFunc[7]; MakeJump( (DWORD)cOffset, dwFuncAddress, cJmpToFunc ); *(SHORT*)(&cJmpToFunc[5]) = 0x9090; if( WriteProcessMemory( hProcess, cOffset, cJmpToFunc, sizeof( cJmpToFunc ), NULL ) ) { std::cout << "Memory patched!\n"; } else { std::cout << "Could not patch jump.\n"; } } else { std::cout << "Could not write function.\n"; } } else { std::cout << "Could not get permission to patch the memory. Code: " << GetLastError() << "\n"; } } } else { std::cout << "Could not find offset. Ask author to update this programm.\n"; } } delete [] ucModule; CloseHandle( hProcess ); } getchar(); } return 0; }