Raised This Month: $32 Target: $400
 8% 

[ANY] Memory Patcher (v1.03 1/10/2018)


Post New Thread Reply   
 
Thread Tools Display Modes
Author
Rachnus
Senior Member
Join Date: Jun 2016
Location: Funland
Plugin ID:
6284
Plugin Version:
1.03
Plugin Category:
Technical/Development
Plugin Game:
Any
Plugin Dependencies:
    Servers with this Plugin:
     
    Plugin Description:
    Patch memory
    Old 09-30-2018 , 18:12   [ANY] Memory Patcher (v1.03 1/10/2018)
    Reply With Quote #1

    Memory Patcher

    Description:
    Add "memory patches" to the plugin either by natives or gamedata files that are read from a folder (gamedata/memorypatcher.games/), and restore them at any time. Mem patches that are added from gamedata/memorypatcher.games/ are automatically applied. Patches that are added by natives (MP_AddMemoryPatch or MP_AddMemoryPatchEx) also needs to be applied by using MP_Patch

    "Preview":


    Installation:
    Quote:
    memorypatcher.smx should be the only file required for the plugin to work, gamedata/memorypatcher.games/temp directory should be created automatically by plugin
    Commands:
    Quote:
    sm_mp_patchall - z - Patch all existing memory patches
    sm_mp_restoreall - z - Restore all existing memory patches
    sm_mp_patch - z - Patch a single memory patch by siglabel
    sm_mp_restore - z - Restore a single memory patch by siglabel
    sm_mp_status - z - Print out status of existing memory patches
    sm_mp_refresh - z - Read from gamedata folder (gamedata/memorypatcher.games/)
    Gamedata template:

    Using Peace-Maker's CSGO Movement Unlocker as an example.

    csgo/addons/sourcemod/gamedata/memorypatcher.games/walkmove.games.txt
    PHP Code:
    "Games"
    {
        
    "csgo"
        
    {
            
    "Addresses"
            
    {
                
    "CGameMovement::WalkMove_Label"
                
    {
                    
    "windows"
                    
    {
                        
    "signature" "CGameMovement::WalkMove"
                    
    }
                    
    "linux"
                    
    {
                        
    "signature" "CGameMovement::WalkMove"
                    
    }
                }
            }
            
            
    "Signatures"
            
    {
                
    "CGameMovement::WalkMove"
                
    {
                    
    "library"    "server"
                    "windows"    "\xF3\x0F\x59\xC0\xF3\x0F\x59\xD2\xF3\x0F\x59\xC9\xF3\x0F\x58\xD0\xF3\x0F\x58\xD1\x0F\x28\xC2\xF3\x0F\x51\xC0\xF3\x0F\x5E\xD8"
                    "linux"        "\xF3\x0F\x10\xF0\x0F\x28\xC6\xF3\x0F\x51\xC6\xF3\x0F\x5E\xE8"
                
    }
            }
            
    "Offsets"
            
    {
                
    "PatchOffset"
                
    {
                    
    "windows"    "31"
                    "linux"    "27"
                
    }
                
    "PatchByteCount"
                
    {
                    
    "windows"    "42"
                    "linux"    "15"
                
    }
            }
            
    "Keys"
            
    {
                
    // If the amount of opcodes are less than the PatchByteCount, then it will just append the last opcode for the remaining bytes
                // in this case it will append 41 NOPs after the first one for windows, 14 for linux
                
    "opcodes_windows"    "\x90"
                "opcodes_linux"        "\x90"
                "siglabel"            "CGameMovement::WalkMove"
            
    }
        }

    memorypatcher.inc:
    PHP Code:
    #if defined _memorypatcher_included
     #endinput
    #endif

    #define _memorypatcher_included

    #define MP_PREFIX                        " \x09[\x04MemoryPatcher\x09]"
    #define MP_GAMEDATA_DIR                    "memorypatcher.games"
    #define MP_TEMP_GAMEDATA_DIR            "temp"
    #define MP_DEBUG_PREFIX                    "[memorypatcher.smx]"
    #define MP_TEMP_FILE                    "temp.memorypatcher.txt"
    #define MP_PATCH_MAX_NAME_LENGTH         32
    #define MP_PATCH_MAX_SIG_LENGTH         256
    #define MP_PATCH_MAX_OP_CODES            2048

    enum//OSType
    {
        
    OSType_Invalid 0,
        
    OSType_Windows,
        
    OSType_Linux,
        
    OSType_Mac,
        
        
    OSType_MAX,
    }

    enum//LIBType
    {
        
    LIBType_Server 0,
        
    LIBType_Engine,
        
        
    LIBType_MAX,
    }

    enum//AddMemoryPatchError
    {
        
    MP_PATCH_ADD_ERROR_EXCEEDED_OP_CODE_COUNT =     -2,            // Memory patch is too large
        
    MP_PATCH_ADD_ERROR_PATCH_EXISTS =                 -1,            // Memory patch already exists
        
    MP_PATCH_ADD_ERROR_INVALID_TEMP_FILE =             0,            // Should never happend, temp file could not be created (no permissions?)
        
    MP_PATCH_ADD_SUCCESS =                             1,            // If memory patch was successfully added
    }

    enum//ApplyMemoryPatchError
    {
        
    MP_PATCH_APPLY_ERROR_NOT_FOUND =                 -4,            // Memory patch sig label was not found
        
    MP_PATCH_APPLY_ERROR_IS_PATCHED =                 -3,            // Memory patch was already applied
        
    MP_PATCH_APPLY_ERROR_UNKNOWN_ADDRESS =             -2,            // Could not find the sig
        
    MP_PATCH_APPLY_ERROR_UNKNOWN_OFFSET =             -1,            // Should never happend, could not find offset in config file
        
    MP_PATCH_APPLY_ERROR_UNKNOWN_COUNT =             0,            // Should never happend, could not find patch byte count
        
    MP_PATCH_APPLY_SUCCESS =                         1            // If memory patch was successfully applied
    }

    enum//RestoreMemoryPatchError
    {
        
    MP_PATCH_RESTORE_ERROR_INDEX_NOT_FOUND =        -2,            // Should never happend, patch index was not found in stringmap
        
    MP_PATCH_RESTORE_ERROR_NOT_FOUND =                 -1,            // Memory patch sig label was not found
        
    MP_PATCH_RESTORE_ERROR_IS_RESTORED =             0,            // Memory patch was already restored
        
    MP_PATCH_RESTORE_SUCCESS =                         1            // If memory patch was successfully restored

    }

    /**
     * Get server Operating System
     * 
     * @return int                ostype
     */
    native int MP_GetServerOSType();

    /**
     * Add a memory patch which can be patched or restored at any time
     * 
     * @param ostype            which OS is this sig for (see OSType above)
     * @param libtype            which libtype is this sig for (see LIBType above)
     * @param siglabel            label of your sig
     * @param sig                function signature
     * @param offset            offset inside the function
     * @param opcodes            an array containing all opcodes you want to patch the function with
     * @param patchbytecount    amount of bytes to patch
     * @return int                memory patch error code (see MemoryPatchError above)
     */
    native int MP_AddMemoryPatch(int ostypeint libtype, const char[] siglabelchar[] sigint offsetint[] opcodesint patchbytecount);

    /**
     * Add a memory patch which can be patched or restored at any time (Single OP code instead of array of opcodes)
     * 
     * @param ostype            which OS is this sig for (see OSType above)
     * @param libtype            which libtype is this sig for (see LIBType above)
     * @param siglabel            label of your sig
     * @param sig                function signature
     * @param offset            offset inside the function
     * @param opcode            the opcode you wanna patch with
     * @param patchbytecount    amount of bytes to patch
     * @return int                memory patch error code (see MemoryPatchError above)
     */
    native int MP_AddMemoryPatchEx(int ostypeint libtype, const char[] siglabelchar[] sigint offsetint opcodeint patchbytecount);

    /**
     * Remove a memory patch (this also restores it to its previous state automatically)
     * 
     * @param siglabel            label of your sig
     * @return bool                true if removed, false if not found
     */
    native bool MP_RemoveMemoryPatch(const char[] siglabel);

    /**
     * Check if memory patch exists by label
     * 
     * @param siglabel            siglabel string
     * @return bool                true if exist
     */
    native bool MP_MemoryPatchExists(const char[] siglabel);

    /**
     * Check if existing memory patch was patched
     * 
     * @param siglabel            siglabel string
     * @return bool                true if patched, false if not found or if not patched
     */
    native bool MP_IsPatched(const char[] siglabel);

    /**
     * Patch all existing memory patches
     *
     * @return int                amount patched
     */
    native int MP_PatchAll();

    /**
     * Restores all patches to their original state
     *
     * @return int                amount restored
     */
    native int MP_RestoreAll();

    /**
     * Patch existing memory patch by sig label
     *
     * @return int                patch error code (see ApplyMemoryPatchError above)
     */
    native int MP_Patch(const char[] siglabel);

    /**
     * Restores existing memory patch by sig label
     *
     * @return bool                true if restored, false if not found
     */
    native bool MP_Restore(const char[] siglabel);

    /**
     * Returns amount of existing memory patches added to the plugin
     *
     * @return int                memory patch count
     */
    native int MP_GetMemoryPatchCount();

    /**
     * Returns amount of existing memory patches added to the plugin
     *
     * @return int                memory patch count
     */
    native int MP_GetMemoryPatchSigLabel(int indexchar[] bufferint maxlen);

    /**
     * AddMemoryPatch or AddMemoryPatchEx should be called here or later (This is called server_spawn event)
     *
     * @return void
     */
    forward void MP_OnMemoryPatcherReady();

    public 
    KeyValues MP_GenerateGameDataKeyvalues(int ostypeint libtype, const char[] siglabelchar[] sigint offsetint[] opcodesint opcodecount)
    {
        
    KeyValues conf = new KeyValues("Games");
        
        
    char game[32];
        
    GetGameFolderName(gamesizeof(game));
        
    conf.JumpToKey(gametrue);
        
    conf.JumpToKey("Addresses"true);
        
        
    char sigNameLabel[MP_PATCH_MAX_NAME_LENGTH 16];
        
    Format(sigNameLabelsizeof(sigNameLabel), "%s_Label"siglabel);
        
    conf.JumpToKey(sigNameLabeltrue);
        
        
    char szOsType[16], szLibType[16];
        
    MP_GetOSTypeName(ostypeszOsTypesizeof(szOsType));
        
    MP_GetLIBTypeName(libtypeszLibTypesizeof(szLibType));
        
        
    conf.JumpToKey(szOsTypetrue);
        
    conf.SetString("signature"siglabel);
        
        
    // Go back to SigLabel
        
    conf.GoBack();
        
        
    // Go back to Addresses
        
    conf.GoBack();
        
        
    // Go back to game version
        
    conf.GoBack();
        
        
    conf.JumpToKey("Signatures"true);
        
    conf.JumpToKey(siglabeltrue);
        
    conf.SetString("library"szLibType);
        
    conf.SetString(szOsTypesig);
        
        
    // Go back to Signatures
        
    conf.GoBack();
        
        
    // Go back to game version
        
    conf.GoBack();
        
        
    conf.JumpToKey("Offsets"true);
        
    conf.JumpToKey("PatchOffset"true);
        
    conf.SetNum(szOsTypeoffset);
        
        
    // Go back to Offsets
        
    conf.GoBack();
        
        
    conf.JumpToKey("PatchByteCount"true);
        
    conf.SetNum(szOsTypeopcodecount);
        
        
    // Go back to Offsets
        
    conf.GoBack();
        
        
    // Go back to game version
        
    conf.GoBack();
        
        
    conf.JumpToKey("Keys"true);
        
        
    char[] szOPcodes = new char[opcodecount 1]; // One OP code is 2 characters (NOP = 90) add 2 more characters to that '\x'
        
    for (int i 0opcodecounti++)
            
    Format(szOPcodes[4], opcodecount 4"\\x%x"opcodes[i]);
        
    szOPcodes[opcodecount 4] = '\0';

        
    char opcodesLabel[32];
        
    Format(opcodesLabelsizeof(opcodesLabel), "opcodes_%s"szOsType);

        
    conf.SetString(opcodesLabelszOPcodes);
        
    conf.SetString("siglabel"siglabel);
        
    conf.Rewind();
        return 
    conf;
    }

    public 
    void MP_ByteStringArrayToIntArray(const char[] byteStringArrayint[] opcodesint opcodeLength)
    {
        
    int byteStringLength strlen(byteStringArray);
    #if defined DEBUG#
        
    MP_Debug("(BYTE STRLEN: %d) (OPCODELENGTH: %d)"byteStringLengthopcodeLength);
    #endif    
        
    int opcode 0;
        for (
    int i 0byteStringLengthi++)
        {
            if(
    byteStringArray[i] == 'x')
            {
                
    char szHex[3];
                
    szHex[0] = byteStringArray[1];
                
    szHex[1] = byteStringArray[2];
                
    szHex[2] = '\0';
                
    opcode StringToInt(szHex16);
                
    opcodes[RoundToFloor(float(i) / 4.0)] = opcode;
    #if defined DEBUG
                
    MP_Debug("OPCODE: %x (%d)"opcodeopcode);
    #endif
            
    }
        }
        
        
    int itMax opcodeLength 4;
        if(
    byteStringLength itMax)
        {
    #if defined DEBUG
            
    MP_Debug("Not enough OPcodes to satisfy array, extending last op code (%x)"opcode);
    #endif
            
    for (int i RoundToFloor(float(byteStringLength) / float(4)); opcodeLengthi++)
            {
                
    opcodes[i] = opcode;
    #if defined DEBUG
                
    MP_Debug("EXTENDED OPCODE: %x (%d)"opcodeopcode);
    #endif
            
    }
        }
    }

    public 
    void MP_GetRestoreErrorCodeString(int errorCodechar[] bufferint maxlen)
    {
        switch(
    errorCode)
        {
            case 
    MP_PATCH_RESTORE_ERROR_INDEX_NOT_FOUND:
            {
                
    Format(buffermaxlen"Invalid patch index");
            }
            case 
    MP_PATCH_RESTORE_ERROR_NOT_FOUND:
            {
                
    Format(buffermaxlen"Not found");
            }
            case 
    MP_PATCH_RESTORE_ERROR_IS_RESTORED:
            {
                
    Format(buffermaxlen"Already restored");
            }
            case 
    MP_PATCH_RESTORE_SUCCESS:
            {
                
    Format(buffermaxlen"Success");
            }
        }
    }

    public 
    void MP_GetApplyErrorCodeString(int errorCodechar[] bufferint maxlen)
    {
        switch(
    errorCode)
        {
            case 
    MP_PATCH_APPLY_ERROR_NOT_FOUND:
            {
                
    Format(buffermaxlen"Not found");
            }
            case 
    MP_PATCH_APPLY_ERROR_IS_PATCHED:
            {
                
    Format(buffermaxlen"Already patched");
            }
            case 
    MP_PATCH_APPLY_ERROR_UNKNOWN_ADDRESS:
            {
                
    Format(buffermaxlen"Invalid address");
            }
            case 
    MP_PATCH_APPLY_ERROR_UNKNOWN_OFFSET:
            {
                
    Format(buffermaxlen"Offset not found");
            }
            case 
    MP_PATCH_APPLY_ERROR_UNKNOWN_COUNT:
            {
                
    Format(buffermaxlen"Patch byte count not found");
            }
            case 
    MP_PATCH_APPLY_SUCCESS:
            {
                
    Format(buffermaxlen"Success");
            }
        }
    }

    public 
    int MP_GetOSTypeByName(const char[] os)
    {
        if(
    StrContains(os"WIN32"false) != -1)
            return 
    OSType_Windows;
        else if(
    StrContains(os"LINUX"false) != -1)
            return 
    OSType_Linux;
        else
            return 
    OSType_Mac;
    }

    public 
    void MP_GetOSTypeName(int ostypechar[] bufferint maxlen)
    {
        switch(
    ostype)
        {
            case 
    OSType_Windows:
            {
                
    Format(buffermaxlen"windows");
            }
            case 
    OSType_Linux:
            {
                
    Format(buffermaxlen"linux");
            }
            case 
    OSType_Mac:
            {
                
    Format(buffermaxlen"mac");
            }
            default:
            {
                
    LogError("OSType: %d is invalid"ostype);
            }
        }
    }

    public 
    void MP_GetLIBTypeName(int libtypechar[] bufferint maxlen)
    {
        switch(
    libtype)
        {
            case 
    LIBType_Server:
            {
                
    Format(buffermaxlen"server");
            }
            case 
    LIBType_Engine:
            {
                
    Format(buffermaxlen"engine");
            }
            default:
            {
                
    LogError("LIBType: %d is invalid"libtype);
            }
        }
    }

    public 
    bool MP_IsValidOSType(int ostype)
    {
        return 
    ostype >= && ostype OSType_MAX;
    }

    public 
    bool MP_IsValidLIBType(int libtype)
    {
        return 
    libtype >= && libtype LIBType_MAX;
    }

    public 
    void MP_Debug(const char[] messageany ...)
    {
        
    char szBuffer[254];
        
    VFormat(szBuffersizeof(szBuffer), message2);
        
        
    PrintToChatAll("%s %s"MP_DEBUG_PREFIXszBuffer);
        
    PrintToServer("%s %s"MP_DEBUG_PREFIXszBuffer);
    }

    public 
    SharedPlugin __pl_memorypatcher  =
    {
        
    name "memorypatcher",
        
    file "memorypatcher.smx",
    #if defined REQUIRE_PLUGIN
        
    required 1
    #else
        
    required 0
    #endif
    };

    #if !defined REQUIRE_PLUGIN
    public __pl_memorypatcher_SetNTVOptional()
    {    
        
    MarkNativeAsOptional("MP_GetServerOSType");
        
    MarkNativeAsOptional("MP_AddMemoryPatch");
        
    MarkNativeAsOptional("MP_AddMemoryPatchEx");
        
    MarkNativeAsOptional("MP_RemoveMemoryPatch");
        
    MarkNativeAsOptional("MP_MemoryPatchExists");
        
    MarkNativeAsOptional("MP_IsPatched");
        
    MarkNativeAsOptional("MP_PatchAll");
        
    MarkNativeAsOptional("MP_Patch");
        
    MarkNativeAsOptional("MP_Restore");
        
    MarkNativeAsOptional("MP_GetMemoryPatchCount");
        
    MarkNativeAsOptional("MP_GetMemoryPatchSigLabel");
    }
    #endif 
    Extra:
    As it stands in the gamedata template. You are not required to enter every single OP code if you're simply patching all the data with a single OP code, if the amount of bytes are less than PatchByteCount, it will just keep on patching using the most recent OP code found in the "opcodes_<os>" keyvalue

    DOWNLOAD
    __________________
    Github: https://github.com/jimppan
    Steam: http://steamcommunity.com/id/jimppan
    _____________________________________________ _________
    Taking private requests

    Last edited by Rachnus; 02-21-2024 at 13:57.
    Rachnus is offline
    Reply


    Thread Tools
    Display Modes

    Posting Rules
    You may not post new threads
    You may not post replies
    You may not post attachments
    You may not edit your posts

    BB code is On
    Smilies are On
    [IMG] code is On
    HTML code is Off

    Forum Jump


    All times are GMT -4. The time now is 09:06.


    Powered by vBulletin®
    Copyright ©2000 - 2024, vBulletin Solutions, Inc.
    Theme made by Freecode