This will not too complex. It a easy way to let you scan your process memory like some game cheater. Of course, there is a free tool named "Game Cheater". That is open source one.
But I just want to write a "string" scan for myself. You can modify this by your self. Totally free.
See the definition.
#ifndef __MEMORY_SCAN_TOOL_H__
#define __MEMORY_SCAN_TOOL_H__
#pragma once
#include <vector>
typedef struct _MEMBLOCK {
DWORD pid; // process id
HANDLE hProc; // handle of the process
unsigned char * addr; // block address (start address)
SIZE_T size; // memory block size
unsigned char * buffer; // a copy buffer of this memory block
unsigned char * searchmask; // used for searching
SIZE_T matches; // used for searching
SIZE_T data_size; // data size when search
struct _MEMBLOCK * next; // linked list
} MEMBLOCK, *PMEMBLOCK;
typedef struct _FOUNDADDR {
unsigned char * addr; // base address
unsigned long offset; // off set
} FOUNDADDR;
//#define IS_IN_SEARCH(mb, offset) (mb->searchmask[(offset)/8] & (1 << ((offset)%8)))
//#define REMOVE_FROM_SEARCH(mb, offset) mb->searchmask[(offset)/8] &= ~(1 << ((offset)%8));
///
// This class is used for memory scan
// 1. Get memory block for scaning
// 2. Get the scan result
///
class CMemoryScanTool
{
public:
CMemoryScanTool();
~CMemoryScanTool();
static CMemoryScanTool* GetMemoryScanToolInstance();
static void ReleaseMemoryScanToolInstance();
// create the memory list by using CreateMemoryBlock
PMEMBLOCK CreateMemoryList(unsigned int pid, int data_size);
// create the memory block
PMEMBLOCK CreateMemoryBlock(HANDLE hProc, MEMORY_BASIC_INFORMATION* meminfo, int data_size);
// free the memory block (one block with buffer)
void FreeMemoryBlock(PMEMBLOCK mb);
// free the memory block list (by using FreeMemoryBlock)
void FreeMemoryBlockList(PMEMBLOCK mb_list);
// update the memory block data by using ReadProcessMemory
void UpdateMemoryBlock(PMEMBLOCK mb);
// Dump the information into a file
void DumpScanInformation(FILE* f, PMEMBLOCK mb_list);
void DumpScanInformation(char* szFileName, PMEMBLOCK mb_list);
// scan the input string in the memory block list
// Return Value: true indicate that the input string is in the memory block, the nAddr indicate the offset of this block
bool ScanString(const wchar_t* szInput, PMEMBLOCK mb, unsigned long& nAddr);
bool ScanString(const char* szInput, PMEMBLOCK mb, unsigned long& nAddr);
// scan all memory block by using ScanString
bool ScanAllBlock(const wchar_t* szInput, PMEMBLOCK mb_list, std::vector<FOUNDADDR>& vecOut);
bool ScanAllBlock(const char* szInput, PMEMBLOCK mb_list, std::vector<FOUNDADDR>& vecOut);
};
#endif __MEMORY_SCAN_TOOL_H__
See the implementation.
#include "StdAfx.h"
#include "MemoryScanTool.h"
using namespace std;
namespace {
static CMemoryScanTool* g_pMemoryScanTool = NULL;
typedef LONG NTSTATUS;
typedef NTSTATUS (WINAPI *pFnRtlAdjustPrivilege)(ULONG Privilege, BOOLEAN Enable, BOOLEAN CurrentThread, PBOOLEAN Enabled);
pFnRtlAdjustPrivilege RtlAdjustPrivilege;
}
CMemoryScanTool::CMemoryScanTool()
{
RtlAdjustPrivilege = (pFnRtlAdjustPrivilege)GetProcAddress(LoadLibrary(_T("Ntdll.dll")), "RtlAdjustPrivilege");
BOOLEAN bEnabled = FALSE;
// get debug privilege
RtlAdjustPrivilege(20, 1, 0, &bEnabled);;
}
CMemoryScanTool::~CMemoryScanTool()
{
}
CMemoryScanTool* CMemoryScanTool::GetMemoryScanToolInstance() {
if(g_pMemoryScanTool == NULL)
g_pMemoryScanTool = new CMemoryScanTool();
return g_pMemoryScanTool;
}
void CMemoryScanTool::ReleaseMemoryScanToolInstance() {
if(g_pMemoryScanTool)
delete g_pMemoryScanTool;
g_pMemoryScanTool = NULL;
}
PMEMBLOCK CMemoryScanTool::CreateMemoryList(unsigned int pid, int data_size) {
MEMBLOCK* mb_list = NULL;
MEMORY_BASIC_INFORMATION meminfo;
unsigned char* addr = 0;
HANDLE hProc = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid);
if(hProc) {
while(true) {
if(VirtualQueryEx(hProc, addr, &meminfo, sizeof(meminfo)) == 0)
break;
#define WRITABLE (PAGE_READWRITE | PAGE_WRITECOPY | PAGE_EXECUTE_READWRITE | PAGE_EXECUTE_WRITECOPY)
if((meminfo.State & MEM_COMMIT) && (meminfo.Protect & WRITABLE)) {
MEMBLOCK* mb = CreateMemoryBlock(hProc, &meminfo, data_size);
if(mb) {
UpdateMemoryBlock(mb);
mb->pid = pid;
mb->next = mb_list;
mb_list = mb;
}
}
addr = (unsigned char*)meminfo.BaseAddress + meminfo.RegionSize;
}
}
return mb_list;
}
PMEMBLOCK CMemoryScanTool::CreateMemoryBlock(HANDLE hProc, MEMORY_BASIC_INFORMATION* meminfo, int data_size) {
PMEMBLOCK mb = (PMEMBLOCK)malloc(sizeof(MEMBLOCK));
if(mb) {
mb->hProc = hProc;
mb->addr = (unsigned char*)meminfo->BaseAddress;
mb->size = meminfo->RegionSize;
mb->buffer = (unsigned char*)malloc(meminfo->RegionSize);
mb->searchmask = (unsigned char*)malloc(meminfo->RegionSize/8);
memset(mb->searchmask, 0xff, meminfo->RegionSize/8); // mark the byte is in searching.
mb->matches = meminfo->RegionSize;
mb->data_size = data_size;
mb->next = NULL;
}
return mb;
}
void CMemoryScanTool::FreeMemoryBlock(PMEMBLOCK mb) {
if(mb) {
if(mb->buffer)
free(mb->buffer);
if(mb->searchmask)
free(mb->searchmask);
free(mb);
}
}
void CMemoryScanTool::FreeMemoryBlockList(PMEMBLOCK mb_list) {
CloseHandle(mb_list->hProc);
while(mb_list) {
PMEMBLOCK mb = mb_list;
mb_list = mb_list->next;
FreeMemoryBlock(mb);
}
}
// Read the memory data from a process id in MEMBLOCK
void CMemoryScanTool::UpdateMemoryBlock(PMEMBLOCK mb)
{
static unsigned char tmpbuf[128*1024];
SIZE_T bytes_left = 0;
SIZE_T total_read = 0;
SIZE_T bytes_to_read = 0;
SIZE_T bytes_read = 0;
if(mb->matches > 0) {
bytes_left = mb->size;
mb->matches = 0;
while(bytes_left) {
bytes_to_read = (bytes_left > sizeof(tmpbuf)) ? sizeof(tmpbuf) : bytes_left;
ReadProcessMemory(mb->hProc, mb->addr + total_read, tmpbuf, bytes_to_read, (SIZE_T *)&bytes_read);
if(bytes_read != bytes_to_read) break;
memcpy(mb->buffer + total_read, tmpbuf, bytes_read);
bytes_left -= bytes_read;
total_read += bytes_read;
}
mb->size = total_read;
}
}
void CMemoryScanTool::DumpScanInformation(FILE* f, PMEMBLOCK mb_list) {
MEMBLOCK* mb = mb_list;
while(mb) {
fprintf(f, "Process ID: %ldrn", GetProcessId(mb->hProc));
fprintf(f, "0x%08x %drn", mb->addr, mb->size);
for(unsigned int i = 0; i < mb->size; ++i) {
fprintf(f, "%c", mb->buffer[i]);
//if(i % 8 == 0)
// fprintf(f, " ");
//if(i % 16 == 0)
// fprintf(f, "rn");
}
fprintf(f, "rn");
mb = mb->next;
}
}
void CMemoryScanTool::DumpScanInformation(char* szFileName, PMEMBLOCK mb_list) {
FILE* f = fopen(szFileName, "w");
if(f) DumpScanInformation(f, mb_list);
}
bool CMemoryScanTool::ScanString(const wchar_t* szInput, PMEMBLOCK mb, unsigned long& nAddr) {
if(szInput == NULL || mb == NULL)
return false;
if(mb->size == 0)
return false;
SIZE_T nStringSize = wcslen(szInput);
// shift one byte per loop (may shift 2 byte?)
for(SIZE_T i = 0; i < mb->size - nStringSize; ++i) {
if(memcmp(szInput, mb->buffer + i, nStringSize*2) == 0) {
nAddr = i;
return true;
}
}
return false;
}
bool CMemoryScanTool::ScanString(const char* szInput, PMEMBLOCK mb, unsigned long& nAddr) {
if(szInput == NULL || mb == NULL)
return false;
if(mb->size == 0)
return false;
SIZE_T nStringSize = strlen(szInput);
// shift one byte per loop
for(SIZE_T i = 0; i < mb->size - nStringSize*2; ++i) {
if(memcmp(szInput, (mb->buffer + i), nStringSize*2) == 0) {
nAddr = (unsigned long)(mb->addr) + i;
return true;
}
}
return false;
}
bool CMemoryScanTool::ScanAllBlock(const wchar_t* szInput, PMEMBLOCK mb_list, vector<FOUNDADDR>& vecOut) {
MEMBLOCK* mb = mb_list;
unsigned long nAddr;
while(mb) {
if(ScanString(szInput, mb, nAddr)) {
FOUNDADDR fa;
fa.addr = mb->addr;
fa.offset = nAddr;
vecOut.push_back(fa);
}
mb = mb->next;
}
return (vecOut.size() != 0);
}
bool CMemoryScanTool::ScanAllBlock(const char* szInput, PMEMBLOCK mb_list, vector<FOUNDADDR>& vecOut) {
MEMBLOCK* mb = mb_list;
unsigned long nAddr;
while(mb) {
if(ScanString(szInput, mb, nAddr)) {
FOUNDADDR fa;
fa.addr = mb->addr;
fa.offset = nAddr;
vecOut.push_back(fa);
}
mb = mb->next;
}
return (vecOut.size() != 0);
}
Really easy to unders
沒有留言:
張貼留言