ParoXsitiC Newbie cheater
Reputation: 0
Joined: 22 Aug 2006 Posts: 10
|
Posted: Sun Aug 27, 2006 10:39 pm Post subject: Easy C++ Trainer maker (Need input) |
|
|
Hello all. It's been a while since I've dove into C++. 2-3 years and recently I've been getting into messing around with assembly and memory editing. I noticed there are alot of pages about using the WriteProcessMemory and ReadProcessMemory but I haven't found simple things that put all the variables together in order to make a quick memory editor (Trainer). The things like getting PIDs from process or window names, or simple calls to inject data. I've seen pages worth on how to do it but none the simplify it for someone to just copy and paste some code in and know how to do 80% of memory hacking with 3-4 commands. This class/code will allow beginners of memory hacking or C++ to simply paste the code, write a few lines and then compile. At least that is what I hope.
The reason I am posting this is simply for feedback. I want your suggestions on how to do things better, because I know there are better ways. Don't be shy about being overcritical. I want to meet all accepted standards and I want this code to be SUPER compatible and require few headers and libs. I also want all of it to make perfect sense to the novice C++ coder. If my comments don't do the job well enough or I just simply did something in a messed up way, let me know. I hope to improve this in the future and hopefully allow for inline ASM along with POKE commands.
Ideally someone who has never touched C++ or memory hacking could read a tutorial on the web and use a program like TSearch to convert BASIC POKEs to this program.
| Code: |
// Injection class
// This class is made to simplify injecting code into processes
// it uses the functions POKE and PEEK based mostly on from BASIC
// a popular memory hacker called TSearch converts ASM to BASIC POKEs
// Author: Brian Hare
#include "stdafx.h"
#include <afxwin.h>
#include <windows.h>
#include "psapi.h"
#pragma comment(lib, "psapi.lib")
// Macros used to call an object and pass it's name
#define win(object) object(#object)
#define exe(object) object(#object".exe")
// Macros used to convert varibles of no type
#define POKE(a, b) POKE_(#a, #b)
#define PEEK(a, b) PEEK_(#a, b)
// Type definitions
#define HWND struct HWND__ *
#define BYTE unsigned char *
#define HANDLE void *
#define DWORD unsigned long
// Constant Global varibles
const bool AUTO_PEEK = true;
const bool PROCESS_LIST = false;
const bool SYSTEM_ERRORS = true;
// Global variable used for detecting the process handle of the last inject class object
char * sProcessGlobal;
HANDLE hProcessGlobal;
HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
// General functions
void printError( char *);
void printLine(int);
void EnableDebugPriv();
// Main functions
void PEEK_(char *, int, HANDLE, char *);
void POKE_(char *, char *, int, HANDLE, char *);
class inject
{
private:
char * sProcessPrivate;
HANDLE hProcessPrivate;
DWORD FindProcess(char *);
public:
inject(char *);
~inject();
void PEEK_(char * sAddress, int iBytesHighlighted = 0)
{
::PEEK_(sAddress, iBytesHighlighted, hProcessPrivate, sProcessPrivate);
}
void POKE_(char * sAddress, char * sBytes, int iPeek = 1)
{
::POKE_(sAddress, sBytes, iPeek, hProcessPrivate, sProcessPrivate);
}
};
inject::inject(char * sProcess) // inject Constructor
{
DWORD dPID;
// Check is the incoming string has a .exe or not
if (strstr (sProcess,".exe") != NULL)
{
// Find the PID based on process name
dPID = FindProcess(sProcess);
if (dPID == NULL)
{
SetConsoleTextAttribute(hConsole, 12);
printf( "\nWARNING: FindProcess failed (%s was not found)\n", sProcess);
SetConsoleTextAttribute(hConsole, 7);
return;
}
}
// Find the PID based on window name
else {
HWND hwndWindow = FindWindow(NULL, sProcess);
if (GetLastError() != 0)
{
SetConsoleTextAttribute(hConsole, 12);
printf( "\nWARNING: FindWindow failed (%s was not found)\n", sProcess);
SetConsoleTextAttribute(hConsole, 7);
printError("FindWindow");
return;
}
GetWindowThreadProcessId(hwndWindow, &dPID);
}
// Set the private and global varibles so you can use them interchangably
hProcessPrivate = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dPID);
if (GetLastError() != 0) { printError("OpenProcess"); return; }
hProcessGlobal = hProcessPrivate;
sProcessGlobal = sProcess;
sProcessPrivate = sProcess;
}
inject::~inject() // inject Deconstructor
{
CloseHandle(hProcessPrivate);
if (GetLastError() != 0) { printError("CloseHandle"); return; }
}
// Find the process handle by name
DWORD inject::FindProcess(char * InputProcessName)
{
HANDLE hProcess;
DWORD aProcesses[1024];
DWORD cbNeeded;
DWORD cProcesses;
HMODULE hMod;
// Get the list of proccess and put them in aProccesses
EnumProcesses(aProcesses, sizeof(aProcesses), &cbNeeded );
if (GetLastError() != 0) { printError("EnumProcesses"); return 0; }
// Calculate the number of processes
cProcesses = cbNeeded / sizeof(DWORD);
char szProcessName[MAX_PATH] = "UnknownProcess";
if (PROCESS_LIST == true)
{
SetConsoleTextAttribute(hConsole, 15);
printf(" PID HANDLE PROCESS NAME\n");
printf(" --- ------ ------------\n");
SetConsoleTextAttribute(hConsole, 7);
}
DWORD dPID = NULL;
EnableDebugPriv();
for (unsigned int i = 2; i < cProcesses; i++ )
{
hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, aProcesses[i] );
if (GetLastError() != 0)
{
printError("OpenProcess");
CloseHandle( hProcess );
continue;
}
if (hProcess != NULL)
{
if ( EnumProcessModules( hProcess, &hMod, sizeof(hMod), &cbNeeded) )
{
GetModuleBaseName( hProcess, hMod, szProcessName, sizeof(szProcessName));
if(!_stricmp(szProcessName, InputProcessName))
{
if (PROCESS_LIST == true) SetConsoleTextAttribute(hConsole, 10);
dPID = aProcesses[i];
}
if (PROCESS_LIST == true)
{
printf("%5d %5d %s\n", aProcesses[i], hProcess, szProcessName);
SetConsoleTextAttribute(hConsole, 7);
}
}
}
CloseHandle( hProcess );
}
printf("\n");
return dPID;
}
// printError: shortcut for displaying error messages better.
void printError( char * func)
{
if (SYSTEM_ERRORS != true){ return;}
DWORD eNum;
char sysMsg[256];
char * p;
eNum = GetLastError( );
FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
NULL, eNum,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
sysMsg, 256, NULL );
// Trim the end of the line and terminate it with a null
p = sysMsg;
while( ( *p > 31 ) || ( *p == 9 ) )
++p;
do { *p-- = 0; } while( ( p >= sysMsg ) &&
( ( *p == '.' ) || ( *p < 33 ) ) );
// Display the message
SetConsoleTextAttribute(hConsole, 12);
printf( "\nWARNING: %s failed with error %d (%s)\n", func, eNum, sysMsg );
SetConsoleTextAttribute(hConsole, 7);
}
// printLine: Print a line that is based on the number of columns
void printLine(int iCols)
{
printf("---------");
for (int i = 1; i <= iCols; i++)
printf ("---");
printf("\n");
}
// EnableDebugPriv: Toggle for enabling privleges to get process handles
void EnableDebugPriv()
{
HANDLE hToken;
TOKEN_PRIVILEGES tp;
if(!OpenProcessToken(GetCurrentProcess(),TOKEN_ADJUST_PRIVILEGES,&hToken))
if (GetLastError() != 0) { printError("OpenProcessToken"); return; }
if(!LookupPrivilegeValue (NULL, SE_DEBUG_NAME, &tp.Privileges[0].Luid))
if (GetLastError() != 0) { printError("LookupPrivilegeValue"); return; }
tp.PrivilegeCount = 1;
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
if(!AdjustTokenPrivileges(hToken, FALSE, &tp, sizeof(tp), NULL, NULL))
if (GetLastError() != 0) { printError("AdjustTokenPrivileges"); return; }
}
// PEEK_: Used as reference function for the PEEK macro.
// This will output the address specified in the first parameter
// and all the bytes to that address.
// Defaults: 3 lines above and below hightlighted byte lines (iLineOffset)
// 16 columns (iCols)
void PEEK_(char * sAddress, int iBytesHighlighted = 0, HANDLE hProcess = hProcessGlobal, char * sProcess = sProcessGlobal)
{
// Convert the Address string into a hexadecimal DWORD value and store into dAddress
DWORD dAddress;
sscanf(sAddress, "%8X", &dAddress);
// iLineOffset: Number of lines above and below the highlighted line(s).
// iCols: Number of columns (NOTE: Anything less than 16 won't generate correct byte header)
int iLineOffset = 3;
int iCols = 16;
// iLinesHighlighted: Always round up. Similar to ceil function of math.h
int iLinesHighlighted = iBytesHighlighted/double(iCols) + 0.999999;
int iLines = (iLineOffset * 2)+ iLinesHighlighted;
int iBytesTotal = iLines * iCols;
int iHighlightStart = iLineOffset * iCols;
int i, ii, iByte = 0;
// new and memset are used to allow VLA (variable length arrays)
// vectors could of been used but might want to use in calculation later on.
BYTE bBuffer = new unsigned char [iBytesTotal];
memset (bBuffer,0x00,iBytesTotal);
// Look back iLineOffset * iCols bytes. This is to make the lines above.
dAddress -= iHighlightStart;
// Set console color to white (15) and echo the PEEK command they ran
SetConsoleTextAttribute(hConsole, 15);
printf ("PEEK %X %d -> ", dAddress + iHighlightStart, iBytesHighlighted);
SetConsoleTextAttribute(hConsole, 7);
// API to read memory of process
ReadProcessMemory(hProcess, (void *)dAddress, bBuffer, iBytesTotal, NULL);
if (GetLastError() != 0) { printError("ReadProcessMemory"); return; }
// Status message
printf ("Read %d bytes from %X\n",iBytesTotal,dAddress + iHighlightStart);
printLine(iCols);
// Set console color to white (15)
SetConsoleTextAttribute(hConsole, 15);
printf("ADDRESS ");
// Print the correct byte header for each column. Only correct if iCols = 16
if (iCols == 16)
{
int iLastByte = (dAddress + iHighlightStart) % 16;
int iColHeader = iLastByte;
do
{
printf(" %X", iColHeader);
if (iColHeader == 15)
iColHeader = 0;
else
iColHeader++;
} while (iColHeader != iLastByte);
} else {
for (i = 1; i <= iCols; i++)
printf (" ?");
}
printf("\n");
// Reset console color
SetConsoleTextAttribute(hConsole, 7);
printLine(iCols);
// For each line print the correct address and bytes that belong in that address
// iByte is used for a counter of each byte, once its time to start hightlighting
// the console color will change. When it's time to stop it will stop.
for (i = 0; i < iLines; i++)
{
if (iByte == iHighlightStart)
SetConsoleTextAttribute(hConsole, 10);
printf ("%08X:", dAddress + i * iCols);
for (ii = 1; ii <= iCols; ii++)
{
printf (" %02X",bBuffer[iByte]);
iByte++;
if(iByte >= iHighlightStart + iBytesHighlighted)
SetConsoleTextAttribute(hConsole, 7);
}
printf("\n");
}
printLine(iCols);
printf("\n");
// Clear the memory used for the new BYTE buffer
delete [] bBuffer;
}
// POKE_: Used as reference function for the POKE macro.
// This will inject the bytes specificed into the address passed.
// Defaults: PEEK_ function will follow this command to view results (iPeek)
// Process handle is recieved from the last call to the inject class
void POKE_(char * sAddress, char * sBytes, int iPeek = 1, HANDLE hProcess = hProcessGlobal, char * sProcess = sProcessGlobal)
{
// Convert the Address string into a hexadecimal DWORD value and store into dAddress
DWORD dAddress;
sscanf(sAddress, "%8X", &dAddress);
// Each byte is delimited by a space
int iBytecount = (strlen(sBytes) +1) / 3;
DWORD lBytes;
// new and memset are used to allow VLA (variable length arrays)
// vectors could of been used but might want to use in calculation later on.
BYTE bBuffer = new unsigned char [iBytecount+3];
// Convert the string of bytes passed into single bytes stored in the BYTE buffer
for (int i = 0; i < iBytecount; i++)
sscanf(sBytes+3*i, "%2X", bBuffer+i);
// Set console color to white (15) and echo the POKE command they ran
SetConsoleTextAttribute(hConsole, 15);
printf ("POKE %X %s -> ", dAddress, sBytes);
SetConsoleTextAttribute(hConsole, 7);
// API function that will inject the bytes into the address. Function outputs to lBytes
WriteProcessMemory(hProcess, (void *)dAddress, bBuffer, iBytecount, &lBytes );
if (GetLastError() != 0) { printError("WriteProcessMemory"); return; }
// Display information
printf("Wrote %d bytes into %X \n", lBytes, dAddress);
// If AUTO_PEEK is true then PEEK after POKE
if (AUTO_PEEK == true) PEEK_(sAddress, iBytecount);
// Clear the memory used for the new BYTE buffer
delete [] bBuffer;
}
void main()
{
// This example will show you the basis of commands
inject exe(winmine); // or inject win(Minesweeper)
// View the code before the injection
PEEK(01002ff5, 5); // or winmine.PEEK(01002ff5, 5) (Minesweeper if you used win)
// Disable timer
POKE(01002ff5,90 90 90 90 90 90); // or POKE(01002ff5,90 90 90 90 90 90); (Minesweeper if you used win)
// View the code before the ejection
//PEEK(01002ff5, 6);
// Enable timer
//POKE(01002ff5,FF 05 9C 57 00 01);
exit(0);
} |
|
|