I'm making a memory patcher for a game but when compiling it with only a single patch implemented, no vtable was created (Using mingw). Could someone tell me what is the problem and how I can fix it?
a_patch.cpp (Compile this)
#include "a_patch.h"
void a_patch::init_patch()
{
/* example initilisation */
init_var();
vector<WORD> replace;
vector<WORD> backup;
backup +=
0x8B, 0x01, // +00: MOV EAX, [ECX]
0x8A, 0x4C, 0x24, 0x04; // +02: MOV CL, [ESP+04h]
replace +=
-1, -1,
0x32, 0xC9, 0x90, 0x90; // +02: XOR CL, CL | NOP (x2)
patch = new patcher((LPBYTE)addr, replace, backup);
if (check())
log("Patch initialization successful: %s", patch_name.c_str());
else
log("Patch initialization failed: %s", patch_name.c_str());
}
a_patch.h
#pragma once
#ifndef _A_PATCH_H_
#define _A_PATCH_H_
#include "main.h"
class a_patch : public _patch
{
public:
bool install();
bool uninstall() {return false;}
protected:
void info()
{
dll = "Another.dll";
name = "AnotherFunc";
human_name = "AnotherFunc";
patch_name = "Another Patch";
}
void init_patch();
};
#endif
main.h
#pragma once
#ifndef _MAIN_H_
#define _MAIN_H_
#include <stdarg.h>
#include <windows.h>
#include <stdio.h>
#include "patcher.h"
bool log(const char* format, ...);
bool log_debug(const char* format, ...);
#include "patches.h"
#include "init.h"
#endif
init.h
#pragma once
#ifndef _INIT_H_
#define _INIT_H_
#include "main.h"
#include "a_patch.h"
#endif
patcher.h
#pragma once
#ifndef _PATCHER_H_
#define _PATCHER_H_
#include "main.h"
#include <psapi.h>
#include <vector>
using namespace std;
/* Format of the patch code:
* Each byte of memory is encoded as a WORD
* The low-order byte of the word is the memory value of that byte
* The high-order byte of the word is a tag
*
* Tagging for backup code:
* 0x00 = CHECK -> This byte is part of the memory checking key
* 0x?? = DEFAULT -> This byte is not part of the key
*
* Tagging for patch code:
* 0x00 = PATCH -> This byte should be written to memory at patch time
* 0x?? = ADDRESS -> PatchRelativeAddress() should rewrite bytes with this tag
* with a relative address to the supplied target
* 0x?? = IGNORE -> This byte should not be written to memory at patch time
*
* -1 is equivalent to 0xFFFF, which is an ignored byte.
*/
class patcher
{
public:
patcher(LPBYTE Address, vector<WORD> Patch, vector<WORD> Backup)
{
addr = Address;
patch = Patch;
backup = Backup;
}
bool check();
bool apply();
bool revert();
bool search(char* dllFile);
bool patchDword(BYTE tag, DWORD dword);
bool patchExactAddress(BYTE tag, LPBYTE address);
bool patchRelativeAddress(BYTE tag, LPBYTE address);
static void readMem(LPVOID lpAddress, LPVOID lpBuffer, SIZE_T nSize);
LPBYTE getAddr() { return addr; }
vector<WORD> getPatch() { return patch; }
vector<WORD> getBackup() { return backup; }
void setAddr(LPBYTE Address) { addr = Address; }
void setPatch(vector<WORD> Patch) { patch = Patch; }
void setBackup(vector<WORD> Backup) { backup = Backup; }
void dump();
private:
static void writeMem(LPVOID lpAddress, LPVOID lpBuffer, SIZE_T nSize);
LPBYTE addr;
vector<WORD> patch;
vector<WORD> backup;
};
#endif
patches.h
#pragma once
#ifndef _PATCHES_H_
#define _PATCHES_H_
#include <string>
#include <vector>
#include "main.h"
using namespace std;
class _patch
{
public:
virtual ~_patch()
{
if (patch != NULL)
delete patch;
}
virtual bool install()
{
if (patch != NULL)
{
if (patch->apply())
{
installed = true;
log("Success: %s successfully installed", patch_name.c_str());
return true;
}
log("Failed: %s did not install successfully", patch_name.c_str());
}
return false;
}
virtual bool uninstall()
{
if (patch == NULL)
return false;
patch->revert();
log("Info: %s has been uninstalled", patch_name.c_str());
return true;
}
virtual bool toggle()
{
if (installed)
return uninstall();
return install();
}
virtual bool isInstalled()
{
return installed;
}
virtual void init()
{
init_patch();
}
/****************************/
virtual string getdll() {return dll;}
virtual string getname() {return name;}
virtual string gethuman_name() {return human_name;}
virtual string getpatch_name() {return patch_name;}
virtual unsigned short getos_ver() {return os_ver;}
/****************************/
void* addr;
protected:
virtual void init_var()
{
os_ver = 50;
addr = NULL;
patch = NULL;
installed = false;
info();
}
virtual void info()
{
dll = "Generic.dll";
name = "GenericFunc";
human_name = "GenericFunc";
patch_name = "Generic Patch";
}
virtual void init_patch() {init_var();}
virtual bool check()
{
if (!patch->check())
{
log("Error: Patch at address 0x%08X failed key check.\n", patch->getAddr());
patch->dump();
delete patch;
patch = NULL;
return false;
}
return true;
}
string dll, name, human_name, patch_name;
unsigned short os_ver;
patcher* patch;
bool installed;
};
template <class patch>
patch* new_patch()
{
patch* p = new patch;
p->init();
return p;
}
template <class _Tp, class _Alloc = allocator<_Tp> >
struct push_back_wrapper
{
explicit push_back_wrapper(vector<_Tp, _Alloc>& v) : v_(&v) {}
push_back_wrapper& operator,(const _Tp& x)
{
v_->push_back(x);
return *this;
}
vector<_Tp>* v_;
};
template <class _Tp, class U, class _Alloc>
push_back_wrapper<_Tp, _Alloc> operator+=(vector<_Tp, _Alloc>& v, const U& x)
{
v.push_back(x);
return push_back_wrapper<_Tp, _Alloc>(v);
}
#endif