views:

75

answers:

1

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
A: 

Aha, I found my problem :)
In a_patch.h, I accidently forgot to remove the decleration of the install() function. (It was the predocessor for the init_patch() function)

kotarou3