Author | Message | Time |
---|---|---|
Telos | I wrote a small name spoofer for warcraft 3 a few weeks ago and ended up writing this class to improve it a little afterwards hope it helps someone. It is by no means perfect but for most basic patching it should get the job done [code] // CMemoryPatcher.hpp #ifndef _CMEMORYPATCHER_H_INCLUDED #define _CMEMORYPATCHER_H_INCLUDED #pragma once #include <windows.h> class CMemoryPatcher { public: CMemoryPatcher(); ~CMemoryPatcher(); void SetPatch( LPCSTR pszPatch, DWORD dwPatchLength ); bool ApplyPatch( LPCSTR pszWindowTitle ); bool RemovePatch( LPCSTR pszWindowTitle ); void SetPatchAddress( DWORD dwPatchAddress ) { m_PatchAddress = reinterpret_cast<LPVOID>(dwPatchAddress); } DWORD FindAddress( LPCSTR pszWindowTitle, LPVOID pvSearch, SIZE_T sizetLength, DWORD dwStartAddress, DWORD dwEndAddress, DWORD dwInterval, DWORD dwOptionalOffset ); private: DWORD GetProcessByName( LPCSTR WindowTitle ); bool Patch( LPCSTR pszWindowTitle, bool bApply ); LPVOID m_PatchAddress; LPBYTE m_PatchBuffer; LPBYTE m_OldBuffer; DWORD m_PatchLength; DWORD m_ProcessID; HWND m_WindowHandle; }; #endif // _CMEMORYPATCHER_H_INCLUDED [/code] [code] // CMemoryPatcher.cpp #include "CMemoryPatcher.h" CMemoryPatcher::CMemoryPatcher() { m_PatchAddress = NULL; m_PatchBuffer = NULL; m_OldBuffer = NULL; } CMemoryPatcher::~CMemoryPatcher() { if( m_PatchBuffer ) { delete [] m_PatchBuffer; delete [] m_OldBuffer; } } DWORD CMemoryPatcher::GetProcessByName( LPCSTR WindowTitle ) { m_WindowHandle = FindWindow( NULL, WindowTitle ); if( m_WindowHandle ) return GetWindowThreadProcessId( m_WindowHandle, &m_ProcessID ); return 0; } /* SetPatch (LPCSTR) The patch data (typically a string of hex) (DWORD ) The length of the patch */ void CMemoryPatcher::SetPatch( LPCSTR pszPatch, DWORD dwPatchLength ) { if( m_PatchBuffer ) { delete [] m_PatchBuffer; delete [] m_OldBuffer; } m_PatchLength = dwPatchLength; m_PatchBuffer = (LPBYTE)new char[ m_PatchLength ]; m_OldBuffer = (LPBYTE)new char[ m_PatchLength ]; memcpy( m_PatchBuffer, pszPatch, m_PatchLength ); } bool CMemoryPatcher::ApplyPatch( LPCSTR pszWindowTitle ) { return Patch( pszWindowTitle, true ); } bool CMemoryPatcher::RemovePatch( LPCSTR pszWindowTitle ) { return Patch( pszWindowTitle, false ); } /* Patch (LPCSTR) Title of the window to patch ( bool ) Apply/Remove Returns the success of the function */ bool CMemoryPatcher::Patch( LPCSTR pszWindowTitle, bool bApply ) { if( (bApply && !m_PatchBuffer) || (!bApply && !m_OldBuffer) ) return false; HANDLE hProcessHandle; bool bCompleted = false; GetProcessByName( pszWindowTitle ); if( m_ProcessID ) { hProcessHandle = OpenProcess( PROCESS_ALL_ACCESS, NULL, m_ProcessID ); if( hProcessHandle ) { DWORD dwOldMemoryAttributes; if( VirtualProtectEx( hProcessHandle, m_PatchAddress, m_PatchLength, PAGE_READWRITE, &dwOldMemoryAttributes ) ) { SIZE_T sizetWrittenBytes = 0; if( bApply ) ReadProcessMemory( hProcessHandle, m_PatchAddress, m_OldBuffer, m_PatchLength, &sizetWrittenBytes ); else ReadProcessMemory( hProcessHandle, m_PatchAddress, m_PatchBuffer, m_PatchLength, &sizetWrittenBytes ); if( bApply ) { if( WriteProcessMemory( hProcessHandle, m_PatchAddress, m_PatchBuffer, m_PatchLength, &sizetWrittenBytes ) ) { bCompleted = true; } } else { if( WriteProcessMemory( hProcessHandle, m_PatchAddress, m_OldBuffer, m_PatchLength, &sizetWrittenBytes ) ) { bCompleted = true; } } VirtualProtectEx( hProcessHandle, m_PatchAddress, m_PatchLength, dwOldMemoryAttributes, &dwOldMemoryAttributes ); } CloseHandle( hProcessHandle ); } } return bCompleted; } /* FindAddress (LPCSTR) Title of the window (LPVOID) The data to search for (SIZE_T) Length of the data to search for (DWORD ) The address at which to start searching (DWORD ) The address at which to end searching (DWORD ) The interval to search at (DWORD ) The [optional] offset to add to the start address Returns the address at which data was first found */ DWORD CMemoryPatcher::FindAddress( LPCSTR pszWindowTitle, LPVOID pvSearch, SIZE_T sizetLength, DWORD dwStartAddress, DWORD dwEndAddress, DWORD dwInterval, DWORD dwOptionalOffset ) { HANDLE hProcessHandle; LPBYTE pbyteReadContents; SIZE_T sizetBytesRead; pbyteReadContents = (LPBYTE)new char[ sizetLength ]; GetProcessByName( pszWindowTitle ); if( m_ProcessID ) { hProcessHandle = OpenProcess( PROCESS_ALL_ACCESS, NULL, m_ProcessID ); if( hProcessHandle ) { for( DWORD dwSearchAddress = dwStartAddress; dwSearchAddress <= dwEndAddress; dwSearchAddress += dwInterval ) { ReadProcessMemory( hProcessHandle, (LPCVOID)(dwSearchAddress+dwOptionalOffset), pbyteReadContents, sizetLength, &sizetBytesRead ); if( !memcmp( pvSearch, pbyteReadContents, sizetLength ) ) { delete [] pbyteReadContents; return dwSearchAddress+dwOptionalOffset; } } CloseHandle( hProcessHandle ); } } delete [] pbyteReadContents; return 0; } [/code] Snippet from the implementation [code] <snip> void SpoofName( int SpoofType ) { CMemoryPatcher MemoryPatcher; DWORD AddressToModify = 0; char Search[] = "PX3W"; char Name[20]; AddressToModify = MemoryPatcher.FindAddress( "Warcraft III", (LPVOID)Search, 4, 0x00100000, 0x0F000000, 0x00010000, 0x2d4 ); if( AddressToModify ) { cout << "AddressToModify: " << std::hex << AddressToModify << std::dec << endl; cout << "Query: What would you like to change your name to?" << endl; memset( static_cast<void *>(Name), 0, 20 ); cout << "Name: "; cin >> Name; if( SpoofType == 0 ) MemoryPatcher.SetPatchAddress( AddressToModify - 0x20 ); else MemoryPatcher.SetPatchAddress( AddressToModify - 0x10 ); MemoryPatcher.SetPatch( Name, strlen(Name) + 1 ); MemoryPatcher.ApplyPatch( "Warcraft III" ); } } <snip> [/code] | April 6, 2004, 5:57 PM |
iago | hmm, I have a similar class that works once the program is already in memory. I also have a program that takes in a window name/dll name and does the injecting for me. It's open source and I've posted it here before, contact me if you want to have a look. | April 6, 2004, 6:58 PM |
Telos | Thanks after I posted I actually remembered you having posted something similar and I looked back through to find it. If you have more than what you already put up Id be interested in seeing it | April 6, 2004, 7:01 PM |
iago | Nope, it's successfully worked for everything I've tried to do with it :) | April 6, 2004, 7:42 PM |
Noodlez | Link to your dll injector iago? | April 7, 2004, 4:31 AM |
Maddox | [quote author=iago link=board=30;threadid=6182;start=0#msg53734 date=1081277936] hmm, I have a similar class that works once the program is already in memory. I also have a program that takes in a window name/dll name and does the injecting for me. It's open source and I've posted it here before, contact me if you want to have a look. [/quote] What does it do? Look for space in the process memory to insert your LoadLibrary() code, or allocate memory to the proccess with VirtualAllocEx()? | April 7, 2004, 7:58 AM |
iago | [quote author=Maddox link=board=30;threadid=6182;start=0#msg53860 date=1081324686] [quote author=iago link=board=30;threadid=6182;start=0#msg53734 date=1081277936] hmm, I have a similar class that works once the program is already in memory. I also have a program that takes in a window name/dll name and does the injecting for me. It's open source and I've posted it here before, contact me if you want to have a look. [/quote] What does it do? Look for space in the process memory to insert your LoadLibrary() code, or allocate memory to the proccess with VirtualAllocEx()? [/quote] It uses CreateRemoteThread (which only works on Win 2k+) to run LoadLibrary in the remote address space. http://www.valhallalegends.com/iago/Injector.rar <Edit> Like I said before, though, it's up the the .dll to do the memory editing for itself. You can find my memory editor somewhere at the beginning of the Advanced Programming forum. <Edit 2> or, I just noticed, you can get it at http://www.valhallalegends.com/iago/MemoryPatcher.rar | April 7, 2004, 1:05 PM |