skamonkey@3513: #include skamonkey@3513: #include skamonkey@3513: #include skamonkey@3513: #include skamonkey@3513: #include skamonkey@3574: #include skamonkey@3513: #include "gdc.h" skamonkey@3513: #include "GameConfigs.h" skamonkey@3513: #include "MemoryUtils.h" skamonkey@3513: skamonkey@3513: MemoryUtils mu; skamonkey@3513: skamonkey@3513: char *game = NULL; skamonkey@3513: char *engine = NULL; skamonkey@3513: char *game_binary = NULL; skamonkey@3513: char *engine_binary = NULL; skamonkey@3513: char *wgame_binary = NULL; skamonkey@3513: char *wengine_binary = NULL; skamonkey@3742: char *symbols_file = NULL; skamonkey@3742: skamonkey@3742: bool use_symtab = true; Dr!fter@3954: CGameConfig symbols; Dr!fter@3954: CGameConfig gc; skamonkey@3513: skamonkey@3574: inline bool IsDigit( char c ) skamonkey@3574: { skamonkey@3574: return c < 58 && c > 47; skamonkey@3574: } skamonkey@3574: skamonkey@3742: void PrintUsage() skamonkey@3742: { skamonkey@3742: printf("Usage: ./gdc -g -e -f -b -x -w -y [-s ]\n"); skamonkey@3742: printf("Other options:\n"); skamonkey@3742: printf(" -d\tAdd debug output\n"); skamonkey@3742: printf(" -n\tDon't use symbol table for lookups (falls back to dlsym)\n"); skamonkey@3742: } skamonkey@3742: skamonkey@3513: int main(int argc, char **argv) skamonkey@3513: { skamonkey@3513: char *gamedata = NULL; skamonkey@3513: bool debug = false; skamonkey@3513: skamonkey@3513: opterr = 0; skamonkey@3513: int opt; skamonkey@3742: while ((opt = getopt(argc, argv, "b:nde:f:g:x:w:y:s:")) != -1) skamonkey@3742: { skamonkey@3513: switch (opt) skamonkey@3513: { skamonkey@3513: case 'd': skamonkey@3513: debug = true; skamonkey@3513: break; skamonkey@3742: skamonkey@3742: case 'n': skamonkey@3742: use_symtab = false; skamonkey@3742: break; skamonkey@3742: skamonkey@3513: case 'g': skamonkey@3513: game = optarg; skamonkey@3513: break; skamonkey@3513: skamonkey@3513: case 'e': skamonkey@3513: engine = optarg; skamonkey@3513: break; skamonkey@3513: skamonkey@3513: case 'f': skamonkey@3513: gamedata = optarg; skamonkey@3513: break; skamonkey@3513: skamonkey@3513: case 'b': skamonkey@3513: game_binary = optarg; skamonkey@3513: break; skamonkey@3513: skamonkey@3513: case 'x': skamonkey@3513: engine_binary = optarg; skamonkey@3513: break; skamonkey@3513: skamonkey@3513: case 'w': skamonkey@3513: wgame_binary = optarg; skamonkey@3513: break; skamonkey@3513: skamonkey@3513: case 'y': skamonkey@3513: wengine_binary = optarg; skamonkey@3513: break; skamonkey@3513: skamonkey@3742: case 's': skamonkey@3742: symbols_file = optarg; skamonkey@3742: break; skamonkey@3742: skamonkey@3513: case '?': skamonkey@3742: PrintUsage(); skamonkey@3513: return 0; skamonkey@3513: skamonkey@3513: default: skamonkey@3513: printf("WHAT\n"); skamonkey@3513: return 0; skamonkey@3513: } skamonkey@3742: } skamonkey@3513: skamonkey@3513: if (!game || !engine || !gamedata || !game_binary || !engine_binary || !wgame_binary || !wengine_binary) skamonkey@3513: { skamonkey@3742: PrintUsage(); skamonkey@3513: return 0; skamonkey@3513: } skamonkey@3513: skamonkey@3513: printf("Game: %s\n", game); skamonkey@3513: if (debug) skamonkey@3513: { skamonkey@3513: printf("Engine: %s\nGame binary: %s\nEngine binary: %s\nWin game binary: %s\nWin engine binary: %s\n", skamonkey@3513: engine, game_binary, engine_binary, wgame_binary, wengine_binary skamonkey@3513: ); skamonkey@3513: } skamonkey@3513: printf("Gamedata: %s\n\n", gamedata); skamonkey@3513: skamonkey@3513: void *ghandle; skamonkey@3513: ghandle = dlopen(game_binary, RTLD_LAZY); skamonkey@3513: if (!ghandle) skamonkey@3513: { skamonkey@3513: printf("Couldn't open %s (%s)\n", game_binary, dlerror()); skamonkey@3513: return 0; skamonkey@3513: } skamonkey@3513: void *ehandle; skamonkey@3513: ehandle = dlopen(engine_binary, RTLD_LAZY); skamonkey@3513: if (!ehandle) skamonkey@3513: { skamonkey@3513: printf("Couldn't open %s (%s)\n", engine_binary, dlerror()); skamonkey@3513: return 0; skamonkey@3513: } skamonkey@3513: skamonkey@3513: int wgfile = open(wgame_binary, O_RDONLY); skamonkey@3513: if (wgfile == -1) skamonkey@3513: { skamonkey@3513: printf("Couldn't open %s\n", wgame_binary); skamonkey@3513: return 0; skamonkey@3513: } skamonkey@3513: skamonkey@3513: int wefile = open(wengine_binary, O_RDONLY); skamonkey@3513: if (wefile == -1) skamonkey@3513: { skamonkey@3513: printf("Couldn't open %s\n", wengine_binary); skamonkey@3513: return 0; skamonkey@3513: } skamonkey@3513: skamonkey@3513: char err[512]; skamonkey@3513: if (!gc.EnterFile(gamedata, err, sizeof(err))) skamonkey@3513: { skamonkey@3513: printf("%s: %s\n", gamedata, err); skamonkey@3513: return 0; skamonkey@3513: } skamonkey@3513: skamonkey@3742: if (!symbols.EnterFile(symbols_file ? symbols_file : "symbols.txt", err, sizeof(err))) skamonkey@3513: { skamonkey@3513: printf("symbols.txt: %s\n", err); skamonkey@3513: return 0; skamonkey@3513: } skamonkey@3513: skamonkey@3513: for (list::iterator it = gc.m_Offsets.begin(); it != gc.m_Offsets.end(); it++) skamonkey@3513: { skamonkey@3513: if (debug) skamonkey@3513: { skamonkey@3513: printf("DEBUG %s - l: %d w: %d\n", it->name, it->lin, it->win); skamonkey@3513: } skamonkey@3513: skamonkey@3513: const char *symbol = symbols.GetKeyValue(it->name); skamonkey@3513: if (symbol) skamonkey@3513: { skamonkey@3574: char symvt[128] = "_ZTV"; skamonkey@3574: bool bGotFirstNumbers = false; skamonkey@3574: bool bLastNumberDigit = false; skamonkey@3574: unsigned int symlen = strlen(symbol); skamonkey@3574: unsigned int pos = strlen(symvt); skamonkey@3574: skamonkey@3574: for ( unsigned int i = 0; i < symlen && pos < (sizeof(symvt)-1); ++i ) skamonkey@3574: { skamonkey@3574: bool isDigit = IsDigit( symbol[i] ); skamonkey@3574: if( !isDigit && bLastNumberDigit ) skamonkey@3574: { skamonkey@3574: bGotFirstNumbers = true; skamonkey@3574: } skamonkey@3574: skamonkey@3574: // we're before the class len skamonkey@3574: if( !bGotFirstNumbers && !isDigit ) skamonkey@3574: continue; skamonkey@3574: skamonkey@3574: // we're at the function name len skamonkey@3574: if( bGotFirstNumbers && isDigit ) skamonkey@3574: { skamonkey@3574: symvt[pos] = 0; skamonkey@3574: break; skamonkey@3574: } skamonkey@3574: skamonkey@3574: // we're at the class len or class name. we want these skamonkey@3574: symvt[pos++] = symbol[i]; skamonkey@3574: if( isDigit ) skamonkey@3574: { skamonkey@3574: bLastNumberDigit = isDigit; skamonkey@3574: } skamonkey@3574: } skamonkey@3574: symvt[pos] = 0; skamonkey@3574: skamonkey@3513: int newOffset; skamonkey@3574: if (symvt[0]) skamonkey@3513: { skamonkey@3742: void **newvt = NULL; skamonkey@3742: if( use_symtab ) skamonkey@3742: { skamonkey@3742: newvt = (void**)mu.ResolveSymbol(ghandle, symvt); skamonkey@3742: } skamonkey@3742: else skamonkey@3742: { skamonkey@3742: newvt = (void **)dlsym(ghandle, symvt); skamonkey@3742: } skamonkey@3742: skamonkey@3742: if (!newvt) skamonkey@3513: { skamonkey@3574: printf("? O: %-22s - can't find, skipping\n", symvt); skamonkey@3513: continue; skamonkey@3513: } skamonkey@3513: skamonkey@3513: newOffset = findVFunc(ghandle, newvt, symbol); skamonkey@3513: } skamonkey@3513: skamonkey@3513: if (newOffset == it->lin) skamonkey@3513: { skamonkey@3574: printf(" O: %-22s - GOOD. current [ w: %3d, l: %3d ].\n", it->name, it->win, it->lin); skamonkey@3513: } skamonkey@3513: else skamonkey@3513: { skamonkey@3574: printf("! O: %-22s - CHANGED. old [ w: %3d, l: %3d ]. new [ w: %3d, l: %3d ].\n", skamonkey@3513: it->name, skamonkey@3513: it->win, it->lin, skamonkey@3513: newOffset - (it->lin - it->win), newOffset skamonkey@3513: ); skamonkey@3513: } skamonkey@3513: } skamonkey@3513: else // !symbol skamonkey@3513: { skamonkey@3574: printf(" O: %-22s - no Linux symbol, skipping\n", it->name); skamonkey@3513: } skamonkey@3513: } skamonkey@3513: Dr!fter@3954: printf("\nWindows offsets are (semi-)wild guesses!\n\nSignature offsets are wild guesses!\n\n"); skamonkey@3513: skamonkey@3513: for (list::iterator it = gc.m_Sigs.begin(); it != gc.m_Sigs.end(); it++) skamonkey@3513: { skamonkey@3513: if (debug) skamonkey@3513: { skamonkey@3513: printf("DEBUG %s - %s - l: %s\n", it->name, it->lib == Server ? "server" : "engine", it->lin); skamonkey@3513: } skamonkey@3513: skamonkey@3513: const char *linSymbol = it->lin; skamonkey@3513: const char *winSymbol = it->win; skamonkey@3513: bool hasLinux = (linSymbol && linSymbol[0]); skamonkey@3513: bool hasWindows = (winSymbol && winSymbol[0]); skamonkey@3513: if (!hasLinux && !hasWindows) skamonkey@3513: { skamonkey@3574: printf(" S: %-22s - hasn't linux nor windows data, skipping\n", it->name); skamonkey@3513: continue; skamonkey@3513: } skamonkey@3513: skamonkey@3513: int winFile; skamonkey@3513: void *linHandle; skamonkey@3513: if (it->lib == Server) skamonkey@3513: { skamonkey@3513: winFile = wgfile; skamonkey@3513: linHandle = ghandle; skamonkey@3513: } skamonkey@3513: else if (it->lib == Engine) skamonkey@3513: { skamonkey@3513: winFile = wefile; skamonkey@3513: linHandle = ehandle; skamonkey@3513: } skamonkey@3513: else skamonkey@3513: { skamonkey@3574: printf(" S: %-22s - isn't from server nor engine, skipping\n", it->name); skamonkey@3513: continue; skamonkey@3513: } skamonkey@3513: skamonkey@3574: int linuxMatches = 0, windowsMatches = 0; skamonkey@3574: if( hasLinux ) skamonkey@3574: linuxMatches = checkSigStringL(linHandle, linSymbol); skamonkey@3574: if( hasWindows ) skamonkey@3574: windowsMatches = checkSigStringW(winFile, winSymbol); skamonkey@3513: skamonkey@3574: if (linuxMatches == 1 && windowsMatches == 1) skamonkey@3513: { skamonkey@3513: // too much clutter to print current data if it matches anyway, unlike with offsets skamonkey@3513: /* skamonkey@3513: printf("%-22s (%s) - GOOD. current:\n\t[w:%s]\n\t[l:%s]\n", skamonkey@3513: it->name, skamonkey@3513: (it->lib == Server) ? "server" : "engine", skamonkey@3513: winSymbol ? winSymbol : "", skamonkey@3513: linSymbol ? linSymbol : "" skamonkey@3513: ); skamonkey@3513: */ skamonkey@3574: printf(" S: %-22s (%s) - w: GOOD - l: GOOD \n", skamonkey@3513: it->name, skamonkey@3513: (it->lib == Server) ? "server" : "engine" skamonkey@3513: ); Dr!fter@3954: Dr!fter@3954: //Check if they signature has a matching offset Dr!fter@3954: CheckWindowsSigOffset(it->name, winSymbol, winFile); Dr!fter@3954: CheckLinuxSigOffset(it->name, linSymbol, linHandle); Dr!fter@3954: skamonkey@3513: } skamonkey@3513: else skamonkey@3513: { skamonkey@3574: char winStatus[16]; skamonkey@3574: // right now the only option is to ignore skamonkey@3574: const char *options = symbols.GetOptionValue(it->name); skamonkey@3574: bool allowMulti = ( options && strstr(options, "allowmultiple") != NULL ); skamonkey@3574: bool allowMidfunc = ( options && strstr(options, "allowmidfunc") != NULL ); skamonkey@3574: skamonkey@3574: bool bWinGood = false; skamonkey@3574: if( !hasWindows ) { skamonkey@3574: snprintf( winStatus, sizeof(winStatus), "UNKNOWN" ); skamonkey@3574: } skamonkey@3574: else if( windowsMatches == -1 && !allowMidfunc) { skamonkey@3574: snprintf( winStatus, sizeof(winStatus), "MIDFUNC" ); skamonkey@3574: } skamonkey@3574: else if( windowsMatches == 0 ) { skamonkey@3574: snprintf( winStatus, sizeof(winStatus), "NOTFOUND" ); skamonkey@3574: } skamonkey@3574: else if( windowsMatches > 1 && !allowMulti) { skamonkey@3574: snprintf( winStatus, sizeof(winStatus), "MULTIPLE" ); skamonkey@3574: } skamonkey@3574: else { skamonkey@3574: bWinGood = true; skamonkey@3574: snprintf( winStatus, sizeof(winStatus), "GOOD" ); skamonkey@3574: } skamonkey@3574: skamonkey@3574: char linStatus[16]; skamonkey@3574: bool bLinGood = false; skamonkey@3574: if( !hasLinux ) { skamonkey@3574: snprintf( linStatus, sizeof(linStatus), "UNKNOWN" ); skamonkey@3574: } skamonkey@3574: else if( linuxMatches == 0 ) { skamonkey@3574: snprintf( linStatus, sizeof(linStatus), "NOTFOUND" ); skamonkey@3574: } skamonkey@3574: else if( linuxMatches == 1 ) { skamonkey@3574: bLinGood = true; skamonkey@3574: snprintf( linStatus, sizeof(linStatus), "GOOD" ); skamonkey@3574: } skamonkey@3574: else { skamonkey@3574: snprintf( linStatus, sizeof(linStatus), "CHECK" ); skamonkey@3574: } skamonkey@3574: skamonkey@3574: bool showWinExtra = (hasWindows && !bWinGood); skamonkey@3574: bool showLinExtra = ( ( hasLinux && !bLinGood ) || showWinExtra ); skamonkey@3574: skamonkey@3574: printf("%s S: %-22s (%s)", (showWinExtra || showLinExtra) ? "!" : " ", it->name, (it->lib == Server) ? "server" : "engine" ); skamonkey@3574: printf(" - w: %-8s - l: %-8s\n", winStatus, linStatus ); skamonkey@3574: skamonkey@3574: if( showWinExtra || showLinExtra ) skamonkey@3574: printf( "! current:\n" ); skamonkey@3574: skamonkey@3574: if( showWinExtra ) skamonkey@3574: { skamonkey@3574: printf("! w: \"%s\"\n", skamonkey@3574: winSymbol ? winSymbol : "" skamonkey@3513: ); skamonkey@3574: } skamonkey@3513: skamonkey@3574: if( showLinExtra ) skamonkey@3574: { skamonkey@3574: // extra \n at end is intentional to add buffer after possibly long sigs skamonkey@3574: printf("! l: \"%s\"\n\n", skamonkey@3574: linSymbol ? linSymbol : "" skamonkey@3574: ); skamonkey@3574: } skamonkey@3513: } skamonkey@3513: } skamonkey@3513: skamonkey@3513: return 0; skamonkey@3513: } Dr!fter@3954: void CheckWindowsSigOffset(char* name, const char* symbol, int file) Dr!fter@3954: { Dr!fter@3954: void *ptr = GetWindowsSigPtr(file, symbol); Dr!fter@3954: if(!ptr) Dr!fter@3954: { Dr!fter@3954: return; Dr!fter@3954: } Dr!fter@3954: const char* sigOffsetKey = NULL; Dr!fter@3954: const char* sigOffsetByte = NULL; Dr!fter@3954: int sigOffset = -1; Dr!fter@3954: char sigOffsetName[128]; Dr!fter@3954: char sigByteName[128]; skamonkey@3513: Dr!fter@3954: snprintf(sigOffsetName, sizeof(sigOffsetName), "%s_Offset", name); Dr!fter@3954: snprintf(sigByteName, sizeof(sigByteName), "%s_Byte_Win", name); Dr!fter@3954: Dr!fter@3954: sigOffsetKey = symbols.GetKeyValue((const char *)sigOffsetName); Dr!fter@3954: if(sigOffsetKey == NULL) Dr!fter@3954: { Dr!fter@3954: Dr!fter@3954: //Maybe it has multiple? Dr!fter@3954: for(unsigned int i = 1; i <= 4; i++) Dr!fter@3954: { Dr!fter@3954: snprintf(sigOffsetName, sizeof(sigOffsetName), "%s_Offset%i", name, i); Dr!fter@3954: snprintf(sigByteName, sizeof(sigByteName), "%s_Byte_Win%i", name, i); Dr!fter@3954: sigOffsetKey = symbols.GetKeyValue((const char *)sigOffsetName); Dr!fter@3954: Dr!fter@3954: if(sigOffsetKey == NULL) Dr!fter@3954: { Dr!fter@3954: break; Dr!fter@3954: } Dr!fter@3954: Dr!fter@3954: sigOffset = GetOffset(sigOffsetKey, true); Dr!fter@3954: sigOffsetByte = symbols.GetKeyValue((const char *)sigByteName); Dr!fter@3954: Dr!fter@3954: if(sigOffset != -1 && sigOffsetByte != NULL)//Got the offset in the function Dr!fter@3954: { Dr!fter@3954: uint8_t iByte = strtoul(sigOffsetByte, NULL, 16); Dr!fter@3954: Dr!fter@3954: if(iByte == *(uint8_t *)((intptr_t)ptr + sigOffset)) Dr!fter@3954: { Dr!fter@3954: printf(" w: %s -> %s (%4d) == \\x%s GOOD\n", name, sigOffsetKey, sigOffset, sigOffsetByte); Dr!fter@3954: } Dr!fter@3954: else Dr!fter@3954: { Dr!fter@3954: printf("! w: %s -> %s (%4d) != \\x%s BAD\n", name, sigOffsetKey, sigOffset, sigOffsetByte); Dr!fter@3954: } Dr!fter@3954: } Dr!fter@3954: } Dr!fter@3954: } Dr!fter@3954: else Dr!fter@3954: { Dr!fter@3954: sigOffset = GetOffset(sigOffsetKey, true); Dr!fter@3954: sigOffsetByte = symbols.GetKeyValue((const char *)sigByteName); Dr!fter@3954: Dr!fter@3954: if(sigOffset != -1 && sigOffsetByte != NULL)//Got the offset in the function Dr!fter@3954: { Dr!fter@3954: uint8_t iByte = strtoul(sigOffsetByte, NULL, 16); Dr!fter@3954: Dr!fter@3954: if(iByte == *(uint8_t *)((intptr_t)ptr + sigOffset)) Dr!fter@3954: { Dr!fter@3954: printf(" w: %s -> %s (%4d) == \\x%s GOOD\n", name, sigOffsetKey, sigOffset, sigOffsetByte); Dr!fter@3954: } Dr!fter@3954: else Dr!fter@3954: { Dr!fter@3954: printf("! w: %s -> %s (%4d) != \\x%s BAD\n", name, sigOffsetKey, sigOffset, sigOffsetByte); Dr!fter@3954: } Dr!fter@3954: } Dr!fter@3954: } Dr!fter@3954: } Dr!fter@3954: void CheckLinuxSigOffset(char* name, const char* symbol, void * handle) Dr!fter@3954: { Dr!fter@3954: void *ptr = GetLinuxSigPtr(handle, symbol); Dr!fter@3954: if(!ptr) Dr!fter@3954: { Dr!fter@3954: return; Dr!fter@3954: } Dr!fter@3954: const char* sigOffsetKey = NULL; Dr!fter@3954: const char* sigOffsetByte = NULL; Dr!fter@3954: int sigOffset = -1; Dr!fter@3954: char sigOffsetName[128]; Dr!fter@3954: char sigByteName[128]; Dr!fter@3954: Dr!fter@3954: snprintf(sigOffsetName, sizeof(sigOffsetName), "%s_Offset", name); Dr!fter@3954: snprintf(sigByteName, sizeof(sigByteName), "%s_Byte_Lin", name); Dr!fter@3954: Dr!fter@3954: sigOffsetKey = symbols.GetKeyValue((const char *)sigOffsetName); Dr!fter@3954: Dr!fter@3954: if(sigOffsetKey == NULL) Dr!fter@3954: { Dr!fter@3954: Dr!fter@3954: //Maybe it has multiple? Dr!fter@3954: for(unsigned int i = 1; i <= 4; i++) Dr!fter@3954: { Dr!fter@3954: snprintf(sigOffsetName, sizeof(sigOffsetName), "%s_Offset%i", name, i); Dr!fter@3954: snprintf(sigByteName, sizeof(sigByteName), "%s_Byte_Lin%i", name, i); Dr!fter@3954: sigOffsetKey = symbols.GetKeyValue((const char *)sigOffsetName); Dr!fter@3954: Dr!fter@3954: if(sigOffsetKey == NULL) Dr!fter@3954: { Dr!fter@3954: break; Dr!fter@3954: } Dr!fter@3954: Dr!fter@3954: sigOffset = GetOffset(sigOffsetKey, false); Dr!fter@3954: sigOffsetByte = symbols.GetKeyValue((const char *)sigByteName); Dr!fter@3954: Dr!fter@3954: if(sigOffset != -1 && sigOffsetByte != NULL)//Got the offset in the function Dr!fter@3954: { Dr!fter@3954: uint8_t iByte = strtoul(sigOffsetByte, NULL, 16); Dr!fter@3954: Dr!fter@3954: if(iByte == *(uint8_t *)((intptr_t)ptr + sigOffset)) Dr!fter@3954: { Dr!fter@3954: printf(" l: %s -> %s (%4d) == \\x%s GOOD\n", name, sigOffsetKey, sigOffset, sigOffsetByte); Dr!fter@3954: } Dr!fter@3954: else Dr!fter@3954: { Dr!fter@3954: printf("! l: %s -> %s (%4d) != \\x%s BAD\n", name, sigOffsetKey, sigOffset, sigOffsetByte); Dr!fter@3954: } Dr!fter@3954: } Dr!fter@3954: } Dr!fter@3954: } Dr!fter@3954: else Dr!fter@3954: { Dr!fter@3956: sigOffset = GetOffset(sigOffsetKey, false); Dr!fter@3954: sigOffsetByte = symbols.GetKeyValue((const char *)sigByteName); Dr!fter@3954: Dr!fter@3954: if(sigOffset != -1 && sigOffsetByte != NULL)//Got the offset in the function Dr!fter@3954: { Dr!fter@3954: uint8_t iByte = strtoul(sigOffsetByte, NULL, 16); Dr!fter@3954: Dr!fter@3954: if(iByte == *(uint8_t *)((intptr_t)ptr + sigOffset)) Dr!fter@3954: { Dr!fter@3954: printf(" l: %s -> %s (%4d) == \\x%s GOOD\n", name, sigOffsetKey, sigOffset, sigOffsetByte); Dr!fter@3954: } Dr!fter@3954: else Dr!fter@3954: { Dr!fter@3954: printf("! l: %s -> %s (%4d) != \\x%s BAD\n", name, sigOffsetKey, sigOffset, sigOffsetByte); Dr!fter@3954: } Dr!fter@3954: } Dr!fter@3954: } Dr!fter@3954: } Dr!fter@3954: int GetOffset(const char* key, bool windows) Dr!fter@3954: { Dr!fter@3954: for (list::iterator it = gc.m_Offsets.begin(); it != gc.m_Offsets.end(); it++) Dr!fter@3954: { Dr!fter@3954: if (strcmp(it->name, key) == 0) Dr!fter@3954: { Dr!fter@3954: if(windows) Dr!fter@3954: return it->win; Dr!fter@3954: else Dr!fter@3954: return it->lin; Dr!fter@3954: } Dr!fter@3954: } Dr!fter@3954: return -1; Dr!fter@3954: } Dr!fter@3954: void *GetWindowsSigPtr(int file, const char* symbol) Dr!fter@3954: { Dr!fter@3954: int matches = 0; Dr!fter@3954: bool atFuncStart = true; Dr!fter@3954: bool isAt = (symbol[0] == '@'); Dr!fter@3954: // we can't support this on windows from here Dr!fter@3954: if (isAt) Dr!fter@3954: return NULL; Dr!fter@3954: Dr!fter@3954: unsigned char real_sig[511]; Dr!fter@3954: size_t real_bytes = UTIL_DecodeHexString(real_sig, sizeof(real_sig), symbol); Dr!fter@3954: Dr!fter@3954: if (real_bytes >= 1) Dr!fter@3954: { Dr!fter@3954: return mu.FindPatternInFile(file, (char*)real_sig, real_bytes, matches, atFuncStart); Dr!fter@3954: } Dr!fter@3954: return NULL; Dr!fter@3954: Dr!fter@3954: } Dr!fter@3954: void *GetLinuxSigPtr(void *handle, const char* symbol) Dr!fter@3954: { Dr!fter@3954: bool isAt = (symbol[0] == '@' && symbol[1] != '\0'); Dr!fter@3954: int matches = 0; Dr!fter@3954: bool dummy; Dr!fter@3954: Dr!fter@3954: if (isAt) Dr!fter@3954: { Dr!fter@3954: if( use_symtab && mu.ResolveSymbol(handle, &symbol[1]) ) Dr!fter@3954: return mu.ResolveSymbol(handle, &symbol[1]); Dr!fter@3954: else if( !use_symtab && dlsym(handle, &symbol[1]) ) Dr!fter@3954: return dlsym(handle, &symbol[1]); Dr!fter@3954: } Dr!fter@3954: else Dr!fter@3954: { Dr!fter@3954: unsigned char real_sig[511]; Dr!fter@3954: size_t real_bytes = UTIL_DecodeHexString(real_sig, sizeof(real_sig), symbol); Dr!fter@3954: Dr!fter@3954: if (real_bytes >= 1) Dr!fter@3954: { Dr!fter@3954: return mu.FindPattern(handle, (char*)real_sig, real_bytes, matches, dummy); Dr!fter@3954: } Dr!fter@3954: } Dr!fter@3954: Dr!fter@3954: return NULL; Dr!fter@3954: } skamonkey@3574: int checkSigStringW(int file, const char* symbol) skamonkey@3513: { skamonkey@3574: int matches = 0; skamonkey@3574: bool atFuncStart = true; skamonkey@3513: bool isAt = (symbol[0] == '@'); skamonkey@3513: // we can't support this on windows from here skamonkey@3513: if (isAt) skamonkey@3513: return false; skamonkey@3513: skamonkey@3513: unsigned char real_sig[511]; skamonkey@3513: size_t real_bytes = UTIL_DecodeHexString(real_sig, sizeof(real_sig), symbol); skamonkey@3513: skamonkey@3513: if (real_bytes >= 1) skamonkey@3513: { skamonkey@3574: mu.FindPatternInFile(file, (char*)real_sig, real_bytes, matches, atFuncStart); skamonkey@3513: } skamonkey@3513: skamonkey@3574: if( !atFuncStart ) skamonkey@3574: return -1; skamonkey@3513: skamonkey@3574: return matches; skamonkey@3513: } skamonkey@3513: skamonkey@3574: int checkSigStringL(void *handle, const char* symbol) skamonkey@3513: { skamonkey@3742: bool isAt = (symbol[0] == '@' && symbol[1] != '\0'); skamonkey@3574: int matches = 0; skamonkey@3574: bool dummy; skamonkey@3513: skamonkey@3513: if (isAt) skamonkey@3513: { skamonkey@3742: if( use_symtab && mu.ResolveSymbol(handle, &symbol[1]) ) skamonkey@3742: matches = 1; skamonkey@3742: else if( !use_symtab && dlsym(handle, &symbol[1]) ) skamonkey@3574: matches = 1; skamonkey@3513: } skamonkey@3513: else skamonkey@3513: { skamonkey@3513: unsigned char real_sig[511]; skamonkey@3513: size_t real_bytes = UTIL_DecodeHexString(real_sig, sizeof(real_sig), symbol); skamonkey@3513: skamonkey@3513: if (real_bytes >= 1) skamonkey@3513: { skamonkey@3574: mu.FindPattern(handle, (char*)real_sig, real_bytes, matches, dummy); skamonkey@3513: } skamonkey@3513: } skamonkey@3513: skamonkey@3574: return matches; skamonkey@3513: } skamonkey@3513: skamonkey@3513: /* skamonkey@3513: takes a mangled member function symbol and returns the position where the function name and parameters start skamonkey@3513: 01234567890123456789012345678 skamonkey@3513: _ZN9CTFPlayer12ForceRespawnEv skamonkey@3513: ^13 ^28 skamonkey@3513: */ skamonkey@3513: void findFuncPos(const char *sym, int &func, int ¶ms) skamonkey@3513: { skamonkey@3513: int i = 0; skamonkey@3513: while ((sym[i] < '0') || (sym[i] > '9')) i++; skamonkey@3513: int classLen = atoi(sym + i); skamonkey@3513: func = i + (int)ceil(log10(classLen)) + classLen; skamonkey@3513: int funcLen = atoi(sym + func); skamonkey@3513: params = func + (int)ceil(log10(funcLen)) + funcLen; skamonkey@3513: } skamonkey@3513: skamonkey@3513: int findVFunc(void *handle, void **vt, const char *symbol) skamonkey@3513: { skamonkey@3742: if( !use_symtab ) skamonkey@3742: { skamonkey@3742: for (int i = 0; i < 1000; i++ ) skamonkey@3742: { skamonkey@3742: void *pFunc = vt[i]; skamonkey@3742: if( !pFunc ) skamonkey@3742: continue; skamonkey@3742: skamonkey@3742: if( pFunc == dlsym(handle, symbol ) ) skamonkey@3742: return i - 2; skamonkey@3742: } skamonkey@3742: skamonkey@3742: return -1; skamonkey@3742: } skamonkey@3742: skamonkey@3513: int funcPos, paramPos; skamonkey@3513: findFuncPos(symbol, funcPos, paramPos); skamonkey@3513: skamonkey@3513: for (int i = 0; i < 1000; i++) skamonkey@3513: { skamonkey@3513: void *pFunc = vt[i]; skamonkey@3742: if( !pFunc ) skamonkey@3742: continue; skamonkey@3742: skamonkey@3513: const char *s; skamonkey@3513: skamonkey@3513: if (!(s = mu.ResolveAddr(handle, pFunc))) skamonkey@3513: continue; skamonkey@3513: skamonkey@3513: if ((i > 1) && (strncmp(s, "_ZTI", 4) == 0)) skamonkey@3513: break; skamonkey@3513: skamonkey@3513: skamonkey@3513: int tempFuncPos, tempParamPos; skamonkey@3513: findFuncPos(s, tempFuncPos, tempParamPos); skamonkey@3513: skamonkey@3513: if (strcmp(s + tempFuncPos, symbol + funcPos) == 0) skamonkey@3513: { skamonkey@3742: return i - 2; skamonkey@3513: } skamonkey@3513: } skamonkey@3513: skamonkey@3742: return -1; skamonkey@3513: } skamonkey@3513: skamonkey@3513: unsigned int strncopy(char *dest, const char *src, size_t count) skamonkey@3513: { skamonkey@3513: if (!count) skamonkey@3513: { skamonkey@3513: return 0; skamonkey@3513: } skamonkey@3513: skamonkey@3513: char *start = dest; skamonkey@3513: while ((*src) && (--count)) skamonkey@3513: { skamonkey@3513: *dest++ = *src++; skamonkey@3513: } skamonkey@3513: *dest = '\0'; skamonkey@3513: skamonkey@3513: return (dest - start); skamonkey@3513: } skamonkey@3513: skamonkey@3513: size_t UTIL_Format(char *buffer, size_t maxlength, const char *fmt, ...) skamonkey@3513: { skamonkey@3513: va_list ap; skamonkey@3513: va_start(ap, fmt); skamonkey@3513: size_t len = vsnprintf(buffer, maxlength, fmt, ap); skamonkey@3513: va_end(ap); skamonkey@3513: skamonkey@3513: if (len >= maxlength) skamonkey@3513: { skamonkey@3513: buffer[maxlength - 1] = '\0'; skamonkey@3513: return (maxlength - 1); skamonkey@3513: } skamonkey@3513: else skamonkey@3513: { skamonkey@3513: return len; skamonkey@3513: } skamonkey@3513: } skamonkey@3513: skamonkey@3513: size_t UTIL_DecodeHexString(unsigned char *buffer, size_t maxlength, const char *hexstr) skamonkey@3513: { skamonkey@3513: size_t written = 0; skamonkey@3513: size_t length = strlen(hexstr); skamonkey@3513: skamonkey@3513: for (size_t i = 0; i < length; i++) skamonkey@3513: { skamonkey@3513: if (written >= maxlength) skamonkey@3513: break; skamonkey@3513: skamonkey@3513: buffer[written++] = hexstr[i]; skamonkey@3513: if (hexstr[i] == '\\' && hexstr[i + 1] == 'x') skamonkey@3513: { skamonkey@3513: if (i + 3 >= length) skamonkey@3513: continue; skamonkey@3513: /* Get the hex part. */ skamonkey@3513: char s_byte[3]; skamonkey@3513: int r_byte; skamonkey@3513: s_byte[0] = hexstr[i + 2]; skamonkey@3513: s_byte[1] = hexstr[i + 3]; skamonkey@3513: s_byte[2] = '\0'; skamonkey@3513: /* Read it as an integer */ skamonkey@3513: sscanf(s_byte, "%x", &r_byte); skamonkey@3513: /* Save the value */ skamonkey@3513: buffer[written - 1] = r_byte; skamonkey@3513: /* Adjust index */ skamonkey@3513: i += 3; skamonkey@3513: } skamonkey@3513: } skamonkey@3513: skamonkey@3513: return written; skamonkey@3513: } skamonkey@3513: