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
// 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
// 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;
}
Snippet from the implementation
<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>
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.
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
Nope, it's successfully worked for everything I've tried to do with it :)
Link to your dll injector iago?
Quote from: iago on April 06, 2004, 01:58 PM
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.
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 from: Maddox on April 07, 2004, 02:58 AM
Quote from: iago on April 06, 2004, 01:58 PM
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.
What does it do? Look for space in the process memory to insert your LoadLibrary() code, or allocate memory to the proccess with VirtualAllocEx()?
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