Last active
April 21, 2016 21:44
-
-
Save robert-nix/4164860 to your computer and use it in GitHub Desktop.
SC2 ids dumper (23260, 24247 offset; 1.5+ only) + ASLR support
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /* Dump type ids for Units and Abils. SC2. | |
| * | |
| * Keep it simple: cl dump.cpp Version.lib | |
| * May need to enable LAA if 32 bit. | |
| */ | |
| #include <Windows.h> | |
| #include <psapi.h> | |
| #include <TlHelp32.h> | |
| #include <stdint.h> | |
| #include <stdio.h> | |
| #include <string.h> | |
| static int sc2Version = 0; | |
| static HANDLE sc2Handle = NULL; | |
| static uint32_t cUnitIndex = 0; | |
| static uint32_t stringNameOffset = 0; | |
| void DumpIds(uint32_t catalogRecordList); | |
| uint32_t ReadUInt(uint32_t address); | |
| uint32_t GetModuleBase(DWORD, char *); | |
| int main() { | |
| DWORD procIds[2048]; | |
| DWORD numProcs = 0; | |
| DWORD procId = 0; | |
| EnumProcesses(procIds, 2048, &numProcs); | |
| numProcs /= sizeof(DWORD); | |
| char sc2FilePath[512]; | |
| for (int i = 0; i < numProcs; ++i) { | |
| char buf[512]; | |
| sc2Handle = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, 0, procIds[i]); | |
| GetModuleBaseName(sc2Handle, 0, buf, 512); | |
| if (strcmp(buf, "SC2.exe")) { | |
| CloseHandle(sc2Handle); | |
| continue; | |
| } | |
| GetModuleFileNameEx(sc2Handle, 0, sc2FilePath, 512); | |
| procId = procIds[i]; | |
| printf("Found: %d %s\n", procId, sc2FilePath); | |
| // sc2Handle = procHandle; | |
| break; | |
| } | |
| if (sc2Handle == NULL) { | |
| printf("Error: SC2.exe not found\n"); | |
| ExitProcess(1); | |
| } | |
| uint32_t baseAddr = GetModuleBase(procId, "SC2.exe"); | |
| printf("Base: %x\n", baseAddr); | |
| DWORD infoSize = GetFileVersionInfoSize(sc2FilePath, 0); | |
| void *infoBuffer = malloc(infoSize); | |
| GetFileVersionInfo(sc2FilePath, 0, infoSize, infoBuffer); | |
| VS_FIXEDFILEINFO *sc2VersionInfo; | |
| VerQueryValue(infoBuffer, "\\", (LPVOID*)&sc2VersionInfo, 0); | |
| sc2Version = sc2VersionInfo->dwFileVersionLS & 0xffff; | |
| printf("Version %d\n", sc2Version); | |
| free(infoBuffer); | |
| uint32_t gameCatalog = 0; | |
| switch(sc2Version) { | |
| case 23260: | |
| gameCatalog = 0xF62BA0u; | |
| cUnitIndex = 0x110u; | |
| stringNameOffset = 0x64u; | |
| break; | |
| case 24247: // HotS beta 2.0.0.24247 | |
| gameCatalog = 0x10C9B28u; | |
| cUnitIndex = 0x11cu; | |
| stringNameOffset = 0x40u; | |
| break; | |
| default: | |
| printf("Error: Need offset for current version.\n"); | |
| ExitProcess(1); | |
| } | |
| uint32_t gameCatalogTable = ReadUInt(baseAddr + gameCatalog); | |
| printf("\n\n-- Begin dump --\n-- Catalog@0x%x --\n", gameCatalogTable); | |
| uint32_t abilCatalogList = ReadUInt(gameCatalogTable + 0x1c); | |
| uint32_t unitCatalogList = ReadUInt(gameCatalogTable + cUnitIndex); | |
| printf("\n-- CAbil@0x%x --\n", abilCatalogList); | |
| DumpIds(abilCatalogList); | |
| printf("\n-- CUnit@0x%x --\n", unitCatalogList); | |
| DumpIds(unitCatalogList); | |
| printf("\n-- End dump --\n"); | |
| CloseHandle(sc2Handle); | |
| return 0; | |
| } | |
| void DumpIds(uint32_t catalogRecordList) { | |
| uint32_t numEntries = ReadUInt(catalogRecordList + 0x50); | |
| uint32_t recordsList = ReadUInt(catalogRecordList + 0x5c); | |
| if (recordsList == 0) { | |
| printf("-- Error dumping table@%x: no list of catalog records found.\n", catalogRecordList); | |
| return; | |
| } | |
| char name[256]; | |
| for (uint32_t i = 0; i < numEntries; ++i) { | |
| memset(name, 0, 256); | |
| uint32_t recordPtr = ReadUInt(recordsList + 4 * i); | |
| if (recordPtr == 0) { | |
| printf("-- No record at index %d\n", i); | |
| continue; | |
| } | |
| uint32_t stringPtr = ReadUInt(ReadUInt(recordPtr + stringNameOffset) + 0x10) + 4; | |
| uint32_t stringLength = ReadUInt(stringPtr); | |
| uint32_t stringDataPtr; | |
| if (ReadUInt(stringPtr + 4) & 4) { | |
| stringDataPtr = ReadUInt(stringPtr + 8); | |
| } else { | |
| stringDataPtr = stringPtr + 8; | |
| } | |
| ReadProcessMemory(sc2Handle, (LPCVOID)stringDataPtr, &name, | |
| stringLength, 0); | |
| printf("(%d, %d, '%s'),\n", sc2Version, i, name); | |
| } | |
| } | |
| uint32_t ReadUInt(uint32_t address) { | |
| uint32_t result = 0; | |
| ReadProcessMemory(sc2Handle, (LPCVOID)address, &result, | |
| sizeof(uint32_t), 0); | |
| return result; | |
| } | |
| uint32_t GetModuleBase(DWORD procId, char* modName) | |
| { | |
| HANDLE snapshot; | |
| MODULEENTRY32 modInfo; | |
| snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, procId); | |
| modInfo.dwSize = sizeof(MODULEENTRY32); | |
| if (Module32First(snapshot, &modInfo)) | |
| { | |
| printf("mod %s\n", modInfo.szModule); | |
| if (!strcmp(modInfo.szModule, modName)) | |
| { | |
| CloseHandle(snapshot); | |
| return (uint32_t)modInfo.modBaseAddr; | |
| } | |
| while (Module32Next(snapshot, &modInfo)) | |
| { | |
| printf("mod %s\n", modInfo.szModule); | |
| if (!strcmp(modInfo.szModule, modName)) | |
| { | |
| CloseHandle(snapshot); | |
| return (uint32_t)modInfo.modBaseAddr; | |
| } | |
| } | |
| } | |
| CloseHandle(snapshot); | |
| return 0; | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Hello,
How do you determine the values for gameCatalog , cUnitIndex and stringNameOffset ? I'm trying to do the same for Heroes of the Storm but I don't know how to get that memory address. Thanks