diff --git a/README.md b/README.md index 61090ba..cad34fe 100644 --- a/README.md +++ b/README.md @@ -1,15 +1,78 @@ # freeze-dumper -# IN-PROGRESS (didnt finished yet) -## fully readme will be added when the dumper will be finished -# freeze-dumper -This project made for make cheats working dynamically without updating manually offsets or netvars. -Feel free to use this tool. +freeze-dumper is made for CS:GO cheats development, and contains offsets and netvars dumper that can make your cheats works dynamically. + +## Remarks + +- Recommended - build in x64 (debug or release mode) +- Run only when CS:GO is running +- Header file will be created in the same folder as the program is running in +- For now, this program is mainly used for CS:GO cheats, but you can also try to customize your own config file for whatever game / process you would like to scan +- Config file should be .txt file and follow the [instructions below](##Config-format) ## Features -- [ ] offsets dumper -- [ ] netvars dumper (csgo for now) -- [ ] automated config maker for dumping dynamically a bunch of offsets -## screenshots -TBD \ No newline at end of file +- [x] offsets dumper +- [ ] netvars dumper + +## How does offsets dumping work? + +In CS:GO, a process memory contains some real-time information about the game, for example: health pointer that points to an area in the module memory which holds the player's health. +These pointers are called offsets - offsets point to the locations where the desired information is stored at (like the heatlh pointer example). + +**So... how can we get these offsets?** +Offsets are usually represented as hex characters sequence in the module content (raw binary) inside the bracket that exist in r/m64 instructions, for example - `mov rax, [module_name.dll + ]`. +So, what we would like to to do is to take the `` part from the hex characters sequence by using a technique called 'Pattern Scanning'. + +*What is Pattern Scanning?* +First of all, as you know (or not), Valve is changing its offsets every single update, for this matter we would like to use Pattern Scanning techniqe that can let us get these offsets more dynamically. +Pattern Scanning is a technique which is made for extracting offsets from modules contents and more specifically from the r/m64 instructions as we mentioned above. +We are implementing this technique by looking for the surrounding instructions code and then extracting the offset from this bytes sequecne. + +For pattern scanning we need two main elements: +`Pattern` - a pattern is a number of instructions that are represented by a bytes sequence and includes a specific r/m64 instruction that contains the offset as mentioned above. +`Mask` - a mask defines which bytes of your pattern are wildcards and which are not, by using the characters '?' and 'x'. +The character 'x' means 'byte must match with the one from the module content' and the character '?' means 'the index of where we can find the offset in the module content respectively with the pattern' + +For example: +Pattern - `\xA1\x00\x00\x00\x00\x33\xD2\x6A\x00\x6A\x00\x33\xC9\x89\xB0` +Mask - `x????xxxxxxxxxx` + +To sum it up, we want to make our technique useable, by comparing each byte in the module content with the bytes in the pattern, and if we will end up in the same iteration with a wild card, we will skip this iteration cause we want to be sure that the whole pattern match this part in the module content. + +Fully implemntation of the tecnique can be found in the 'Pattern Scanning.c' file. + +TADA! we got the offset :) + +## Usage + +``` +[$] Usage: + freeze-dumper.exe +[*] Examples: + freeze-dumper.exe "config.h" +``` + +## Config-format + +Config file should be .txt file and follow this format (!): +``` + + : : : : : : + : : : : : : + : : : : : : +... +... + : : : : : : +``` + +For your convenience, I made a config file (config.txt) which contains the most important signatures. + +## Build + +freeze-dumper can be built with Visual Studio 2019, by opening the .sin file and build the project (Ctrl+Shift+B) in a Release Mode or a Debug Mode, whatever you want to (x64) + +## Issues + +If you have any issues with this tool, you can ping me on Discord: Lit3r4lly#8336 +If you have some critical bug, open an PR/Issue ticket \ No newline at end of file diff --git a/csgo.h b/csgo.h index 81bd965..8ca2d7e 100644 --- a/csgo.h +++ b/csgo.h @@ -2,16 +2,16 @@ // Signatures const unsigned int dwClientState = 0x58CFE4; -const unsigned int dwClientState_GetLocalPlayer = 0xEAF80180; -const unsigned int dwClientState_Map = 0xEAF8028C; -const unsigned int dwClientState_MapDirectory = 0xEAF80188; -const unsigned int dwClientState_MaxPlayer = 0xEAF80388; -const unsigned int dwClientState_PlayerInfo = 0xEAF852C0; -const unsigned int dwClientState_ViewAngles = 0xEAF84D90; -const unsigned int clientstate_delta_ticks = 0xEAF80174; -const unsigned int clientstate_last_outgoing_command = 0xEAF84D2C; -const unsigned int clientstate_choked_commands = 0xEAF84D30; -const unsigned int clientstate_net_channel = 0xEAF8009C; +const unsigned int dwClientState_GetLocalPlayer = 0xEA6F0180; +const unsigned int dwClientState_Map = 0xEA6F028C; +const unsigned int dwClientState_MapDirectory = 0xEA6F0188; +const unsigned int dwClientState_MaxPlayer = 0xEA6F0388; +const unsigned int dwClientState_PlayerInfo = 0xEA6F52C0; +const unsigned int dwClientState_ViewAngles = 0xEA6F4D90; +const unsigned int clientstate_delta_ticks = 0xEA6F0174; +const unsigned int clientstate_last_outgoing_command = 0xEA6F4D2C; +const unsigned int clientstate_choked_commands = 0xEA6F4D30; +const unsigned int clientstate_net_channel = 0xEA6F009C; const unsigned int dwEntityList = 0x4D523AC; const unsigned int dwForceAttack = 0x3183930; const unsigned int dwForceAttack2 = 0x318393C; @@ -29,20 +29,20 @@ const unsigned int dwLocalPlayer = 0xD3DD14; const unsigned int dwMouseEnable = 0xD438B8; const unsigned int dwMouseEnablePtr = 0xD43888; const unsigned int dwPlayerResource = 0x3181C80; -const unsigned int dwSetClanTag = 0x764F5653; +const unsigned int dwSetClanTag = 0x75C65653; const unsigned int dwViewMatrix = 0x4D43CC4; const unsigned int dwWeaponTable = 0x51A443C; -const unsigned int dwWeaponTableIndex = 0xD7A2325C; +const unsigned int dwWeaponTableIndex = 0xD73E325C; const unsigned int dwppDirect3DDevice9 = 0xA7050; -const unsigned int m_pStudioHdr = 0xD7A2294C; +const unsigned int m_pStudioHdr = 0xD73E294C; const unsigned int m_pitchClassPtr = 0x51873B0; const unsigned int interface_engine_cvar = 0x3E9EC; const unsigned int convar_name_hash_table = 0x2F0F8; -const unsigned int m_bDormant = 0xD7A200ED; -const unsigned int set_abs_angles = 0x5B8E8B55; -const unsigned int set_abs_origin = 0x5B8E8B55; -const unsigned int is_c4_owner = 0x5D938B56; -const unsigned int force_update_spectator_glow = 0xA32D0774; -const unsigned int anim_overlays = 0xD7A22980; -const unsigned int m_flSpawnTime = 0xD7A2A370; -const unsigned int find_hud_element = 0x2B8E8B55; +const unsigned int m_bDormant = 0xD73E00ED; +const unsigned int set_abs_angles = 0x5B2A8B55; +const unsigned int set_abs_origin = 0x5B2A8B55; +const unsigned int is_c4_owner = 0x5D2F8B56; +const unsigned int force_update_spectator_glow = 0xA2C90774; +const unsigned int anim_overlays = 0xD73E2980; +const unsigned int m_flSpawnTime = 0xD73EA370; +const unsigned int find_hud_element = 0x2B2A8B55; diff --git a/freeze-dumper/PatternScanning.h b/freeze-dumper/PatternScanning.h index 5158be3..dda45d9 100644 --- a/freeze-dumper/PatternScanning.h +++ b/freeze-dumper/PatternScanning.h @@ -17,6 +17,6 @@ typedef struct ModuleInformation { } ModuleInformation; DWORD getOffset(PatternScanningInfo* info); -int patternScanning(const BYTE* pattern, const BYTE* moduleContent, const int moduleSize, const char* mask, const int offset); +int patternScanning(const BYTE* pattern, const BYTE* moduleContent, const int moduleSize, const char* mask); DWORD getProcessIdByName(char* processName); HMODULE getModuleHandle(const int processId, const char* moduleName); \ No newline at end of file diff --git a/freeze-dumper/PatternsScanning.c b/freeze-dumper/PatternsScanning.c index cc18de0..4c31182 100644 --- a/freeze-dumper/PatternsScanning.c +++ b/freeze-dumper/PatternsScanning.c @@ -1,5 +1,14 @@ #include "includes.h" +/* + This function control the pattern scanning section + In: + a PatternScanningInfo with the required information + + Out: + the offset +*/ + DWORD getOffset(PatternScanningInfo* info) { int processId = 0; DWORD signatureIndex = 0; @@ -13,7 +22,6 @@ DWORD getOffset(PatternScanningInfo* info) { if (processId == FAILED_TO_FIND_PID || processId == FAILED_TO_COPY_PROCESS_ENTRY_LIST_TO_BUFFER || processId == FAILED_TO_OPEN_SNAPSHOT) { return FAILED_TO_FIND_OFFSET; } - //printf("[^] ProcessID found: %d\n", processId); hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, processId); if (hProcess == INVALID_HANDLE_VALUE) { @@ -27,7 +35,6 @@ DWORD getOffset(PatternScanningInfo* info) { } GetModuleInformation(hProcess, hModule, &moduleInfo, sizeof(moduleInfo)); - //printf("[^] Module handle found \n Module name: %s \n Module size: %d \n Module entry point: 0x%p \n Module base address: 0x%p\n", info->moduleName, moduleInfo.SizeOfImage, moduleInfo.EntryPoint, moduleInfo.lpBaseOfDll); moduleContent = (BYTE*)malloc(moduleInfo.SizeOfImage * sizeof(BYTE)); if (moduleContent == NULL) { @@ -62,7 +69,17 @@ DWORD getOffset(PatternScanningInfo* info) { CloseHandle(hProcess); return signatureOffset; } -int patternScanning(const BYTE* pattern, const BYTE* moduleContent, const int moduleSize, const char* mask, const int offset) { + +/* + This function execute the actual pattern scanning, its passing along the loop of the pattern and the module content and trying to match an equal bytes + In: + pattern for scanning, module content, module size, pattern mask + + Out: + an index where the offset is located in the byte array of the module content +*/ + +int patternScanning(const BYTE* pattern, const BYTE* moduleContent, const int moduleSize, const char* mask) { DWORD i, j = 0; int flag = TRUE; @@ -87,6 +104,15 @@ int patternScanning(const BYTE* pattern, const BYTE* moduleContent, const int mo return FAILED_TO_FIND_OFFSET; } +/* + This functuion returns process ID by the name + In: + process name + + Out: + process ID +*/ + DWORD getProcessIdByName(char* processName) { DWORD processId = 0; PROCESSENTRY32 processEntry = { 0 }; @@ -128,6 +154,15 @@ DWORD getProcessIdByName(char* processName) { return FAILED_TO_FIND_PID; } +/* + This function returns module handle - module base address + In: + process ID (parent process), module name + + Out: + module handle - module base address +*/ + HMODULE getModuleHandle(const int processId, const char* moduleName) { HMODULE hModule = NULL; HANDLE hSnapshot = NULL; diff --git a/freeze-dumper/Props.c b/freeze-dumper/Props.c deleted file mode 100644 index e69de29..0000000 diff --git a/freeze-dumper/Props.h b/freeze-dumper/Props.h deleted file mode 100644 index 50e9667..0000000 --- a/freeze-dumper/Props.h +++ /dev/null @@ -1 +0,0 @@ -#pragma once diff --git a/freeze-dumper/config.c b/freeze-dumper/config.c index 310e26a..0a24ad9 100644 --- a/freeze-dumper/config.c +++ b/freeze-dumper/config.c @@ -6,6 +6,8 @@ int parseConfigFile(char* configFilePath) { char* lineContent = 0; char* tempToWrite = 0; int numberWritten = 0; + int status = 0; + int seekLocation = 0; BYTE* patternByteArr = 0; char* processName = 0; @@ -50,7 +52,10 @@ int parseConfigFile(char* configFilePath) { } sprintf(tempToWrite, "// Porcess: %s \n\n// Signatures\n", processName); - writeResultFile(tempToWrite, numberWritten); + status = writeResultFile(tempToWrite, numberWritten); + if (status == WRITE_DATA_TO_FILE_FAILED) { + return WRITE_DATA_TO_FILE_FAILED; + } numberWritten++; while (EOF != fscanf(pFile, "%[^\n]\n", lineContent)) { @@ -82,7 +87,10 @@ int parseConfigFile(char* configFilePath) { } sprintf(tempToWrite, "const unsigned int %s = 0x%X;\n", info->signatureName, signatureOffset); - writeResultFile(tempToWrite, numberWritten); + status = writeResultFile(tempToWrite, numberWritten); + if (status == WRITE_DATA_TO_FILE_FAILED) { + return WRITE_DATA_TO_FILE_FAILED; + } free(patternByteArr); free(lineContent); @@ -103,20 +111,21 @@ int parseConfigFile(char* configFilePath) { free(lineContent); free(processName); + fclose(pFile); return TRUE; } int writeResultFile(char* stringToWrite, int numberWritten) { FILE* pFile = NULL; - if (numberWritten == 0 && fopen("C:\\Users\\משתמש\\OneDrive\\OneDrive\\Documents\\Projects\\freeze-dumper\\freeze-dumper\\csgo.h", "r") == NULL ) { - pFile = fopen("C:\\Users\\משתמש\\OneDrive\\OneDrive\\Documents\\Projects\\freeze-dumper\\freeze-dumper\\csgo.h", "wb"); + if (numberWritten == 0 && fopen("sgo.h", "r") == NULL ) { + pFile = fopen("csgo.h", "wb"); } - else if (numberWritten != 0 && fopen("C:\\Users\\משתמש\\OneDrive\\OneDrive\\Documents\\Projects\\freeze-dumper\\freeze-dumper\\csgo.h", "r") != NULL) { - pFile = fopen("C:\\Users\\משתמש\\OneDrive\\OneDrive\\Documents\\Projects\\freeze-dumper\\freeze-dumper\\csgo.h", "ab"); + else if (numberWritten != 0 && fopen("csgo.h", "r") != NULL) { + pFile = fopen("csgo.h", "ab"); } else { - pFile = fopen("C:\\Users\\משתמש\\OneDrive\\OneDrive\\Documents\\Projects\\freeze-dumper\\freeze-dumper\\csgo.h", "wb"); + pFile = fopen("csgo.h", "wb"); } if (pFile == NULL) { diff --git a/freeze-dumper/freeze-dumper.vcxproj b/freeze-dumper/freeze-dumper.vcxproj index 8c68f15..0808136 100644 --- a/freeze-dumper/freeze-dumper.vcxproj +++ b/freeze-dumper/freeze-dumper.vcxproj @@ -142,14 +142,12 @@ - - diff --git a/freeze-dumper/freeze-dumper.vcxproj.filters b/freeze-dumper/freeze-dumper.vcxproj.filters index 03d580f..c334974 100644 --- a/freeze-dumper/freeze-dumper.vcxproj.filters +++ b/freeze-dumper/freeze-dumper.vcxproj.filters @@ -21,9 +21,6 @@ Source Files - - Source Files - Source Files @@ -38,9 +35,6 @@ Header Files - - Header Files - Header Files diff --git a/freeze-dumper/includes.h b/freeze-dumper/includes.h index d15552b..bb91757 100644 --- a/freeze-dumper/includes.h +++ b/freeze-dumper/includes.h @@ -9,7 +9,6 @@ #include "Errors.h" #include "PatternScanning.h" -#include "Props.h" #include "config.h" #define MAX_ARGS 2 diff --git a/freeze-dumper/main.c b/freeze-dumper/main.c index 558daa0..9fdee2c 100644 --- a/freeze-dumper/main.c +++ b/freeze-dumper/main.c @@ -2,7 +2,7 @@ /* Args: - freeze-dumper.exe + freeze-dumper.exe */ int main(int argc, char** argv) { @@ -11,7 +11,7 @@ int main(int argc, char** argv) { printf("Welcme to freeze-dumper, a tool made for dumping offsets / netvars for CS:GO\n"); if (argc != MAX_ARGS) { - printf("[!] Not enough \ Too much arguments"); + printf("[!] Not enough \\ Too much arguments"); return NOT_ENOUGH_ARGS; } else if (fopen(argv[CONFIG_ARG], "r") == NULL) { @@ -28,6 +28,15 @@ int main(int argc, char** argv) { return TRUE; } +/* + This function returns a struct that handles the required info for the pattern scanning + In: + process name, module name, pattern for scanning, signature name, pattern mask, offset for the sig offset, extra to be added to the result offset + + Out: + PatternScanningInfo struct pointer +*/ + PatternScanningInfo* getPatternScanningInfo(char* processName, char* moduleName, BYTE* pattern, char* signatureName, char* mask, int offset, int extra) { PatternScanningInfo* info = NULL; @@ -58,6 +67,15 @@ PatternScanningInfo* getPatternScanningInfo(char* processName, char* moduleName, return info; } +/* + This function convert a char array (string) to a byte array + In: + string to convert, byte array length + + Out: + a byte array +*/ + BYTE* convertCharArrToByteArr(char* stringToConvert, size_t byteArrLength) { int i = 0; int j = 0; @@ -79,6 +97,15 @@ BYTE* convertCharArrToByteArr(char* stringToConvert, size_t byteArrLength) { return byteArr; } +/* + This function returns a hex value of hex digit as integer + In: + a required char for his value + + Out: + a integer value who holds the hex value +*/ + int getHexValue(char ch) { if (ch >= '0' && ch <= '9') return ch - '0';