diff options
Diffstat (limited to 'samples/impmunge')
-rw-r--r-- | samples/impmunge/Makefile | 56 | ||||
-rw-r--r-- | samples/impmunge/impmunge.cpp | 464 |
2 files changed, 520 insertions, 0 deletions
diff --git a/samples/impmunge/Makefile b/samples/impmunge/Makefile new file mode 100644 index 0000000..e320b0c --- /dev/null +++ b/samples/impmunge/Makefile @@ -0,0 +1,56 @@ +############################################################################## +## +## Makefile for Detours Test Programs. +## +## Microsoft Research Detours Package +## +## Copyright (c) Microsoft Corporation. All rights reserved. +## + +!include ..\common.mak + +LIBS=$(LIBS) kernel32.lib + +all: dirs \ + $(BIND)\impmunge.exe \ +!IF $(DETOURS_SOURCE_BROWSING)==1 + $(OBJD)\impmunge.bsc +!ENDIF + +############################################################################## + +clean: + -del *~ test.exe.* 2>nul + -del $(BIND)\impmunge.* 2>nul + -rmdir /q /s $(OBJD) 2>nul + +realclean: clean + -rmdir /q /s $(OBJDS) 2>nul + +############################################################################## + +dirs: + @if not exist $(BIND) mkdir $(BIND) && echo. Created $(BIND) + @if not exist $(OBJD) mkdir $(OBJD) && echo. Created $(OBJD) + +$(OBJD)\impmunge.obj : impmunge.cpp + +$(BIND)\impmunge.exe : $(OBJD)\impmunge.obj $(DEPS) + cl $(CFLAGS) /Fe$@ /Fd$(@R).pdb $(OBJD)\impmunge.obj \ + /link $(LINKFLAGS) $(LIBS) imagehlp.lib /subsystem:console + +$(OBJD)\impmunge.bsc : $(OBJD)\impmunge.obj + bscmake /v /n /o $@ $(OBJD)\impmunge.sbr + +############################################################################## + +test: $(BIND)\impmunge.exe + $(BIND)\impmunge.exe /m /o:test.exe.1 $(BIND)\impmunge.exe + $(BIND)\impmunge.exe /m /l- /o:test.exe.2 test.exe.1 + $(BIND)\impmunge.exe /m /l- /o:test.exe.3 test.exe.2 + $(BIND)\impmunge.exe /m /l- /o:test.exe.4 test.exe.3 + $(BIND)\impmunge.exe /l test.exe.4 + $(BIND)\impmunge.exe /r /l- /o:test.exe.0 test.exe.4 + $(BIND)\impmunge.exe /l test.exe.0 + +################################################################# End of File. diff --git a/samples/impmunge/impmunge.cpp b/samples/impmunge/impmunge.cpp new file mode 100644 index 0000000..95516dc --- /dev/null +++ b/samples/impmunge/impmunge.cpp @@ -0,0 +1,464 @@ +////////////////////////////////////////////////////////////////////////////// +// +// Detours Test Program (impmunge.cpp of impmunge.exe) +// +// Microsoft Research Detours Package +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +#include <stdio.h> +#include <stdlib.h> +#include <windows.h> +#pragma warning(push) +#if _MSC_VER > 1400 +#pragma warning(disable:6102 6103) // /analyze warnings +#endif +#include <strsafe.h> +#include <detours.h> +#pragma warning(disable:4091) // empty typedef +#include <imagehlp.h> +#pragma warning(pop) + +////////////////////////////////////////////////////////////// Error Messages. +// +VOID AssertMessage(PCSTR szMsg, PCSTR szFile, DWORD nLine) +{ + printf("ASSERT(%s) failed in %s, line %ld.", szMsg, szFile, nLine); +} + +#define ASSERT(x) \ +do { if (!(x)) { AssertMessage(#x, __FILE__, __LINE__); DebugBreak(); }} while (0) + ; + + +////////////////////////////////////////////////////////////////////////////// +// +static BOOLEAN s_fRestore = FALSE; +static BOOLEAN s_fList = TRUE; +static BOOLEAN s_fMunge = FALSE; +static BOOLEAN s_fToSymbols = FALSE; + +////////////////////////////////////////////////////////////////////////////// +// +static BOOL CALLBACK ListByway(_In_opt_ PVOID pContext, + _In_opt_ LPCSTR pszFile, + _Outptr_result_maybenull_ LPCSTR *ppszOutFile) +{ + (void)pContext; + (void)ppszOutFile; + + printf(" byway -------------------------------- %s\n", pszFile ? pszFile : ""); + return TRUE; +} + +static BOOL CALLBACK ListFile(_In_opt_ PVOID pContext, + _In_ LPCSTR pszOrigFile, + _In_ LPCSTR pszFile, + _Outptr_result_maybenull_ LPCSTR *ppszOutFile) +{ + (void)pContext; + (void)ppszOutFile; + + printf(" file %-32.32s %-32.32s\n", + pszOrigFile ? pszOrigFile : "", + pszFile ? pszFile : ""); + return TRUE; +} + +static BOOL CALLBACK ListSymbol(_In_opt_ PVOID pContext, + _In_ ULONG nOrigOrdinal, + _In_ ULONG nOrdinal, + _Out_ ULONG *pnOutOrdinal, + _In_opt_ LPCSTR pszOrigSymbol, + _In_opt_ LPCSTR pszSymbol, + _Outptr_result_maybenull_ LPCSTR *ppszOutSymbol) +{ + (void)pContext; + (void)pnOutOrdinal; + (void)ppszOutSymbol; + + char szOrig[80]; + char szLast[80]; + + if (pszOrigSymbol == NULL) { + StringCchPrintfA(szOrig, sizeof(szOrig), "#%d", nOrigOrdinal); + pszOrigSymbol = szOrig; + } + if (pszSymbol == NULL) { + StringCchPrintfA(szLast, sizeof(szLast), "#%d", nOrdinal); + pszSymbol = szLast; + } + + printf(" symbol %-32.32s %-32.32s\n", pszOrigSymbol, pszSymbol); + return TRUE; +} + +static BOOL CALLBACK ListCommit(PVOID pContext) +{ + (void)pContext; + + printf(" commit\n"); + return TRUE; +} + +////////////////////////////////////////////////////////////////////////////// +// +struct MUNGE_STATE +{ + BOOL fLastWasByway; + LONG nBywayCount; + CHAR szBuffer[512]; +}; + +static BOOL CALLBACK MungeByway(_In_opt_ PVOID pContext, + _In_opt_ LPCSTR pszFile, + _Outptr_result_maybenull_ LPCSTR *ppszOutFile) +{ + MUNGE_STATE *pState = (MUNGE_STATE *)pContext; + + printf("|"); + + if (pState->fLastWasByway) { + return TRUE; + } + + pState->fLastWasByway = TRUE; + + if (pszFile == NULL) { + StringCchPrintfA(pState->szBuffer, sizeof(pState->szBuffer), "mb_munge_%d.dll", pState->nBywayCount++); + *ppszOutFile = pState->szBuffer; + } + return TRUE; +} + +static BOOL CALLBACK MungeFile(_In_opt_ PVOID pContext, + _In_ LPCSTR pszOrigFile, + _In_ LPCSTR pszFile, + _Outptr_result_maybenull_ LPCSTR *ppszOutFile) +{ + (void)pszOrigFile; + MUNGE_STATE *pState = (MUNGE_STATE *)pContext; + + pState->fLastWasByway = FALSE; + + printf("*"); + StringCchPrintfA(pState->szBuffer, sizeof(pState->szBuffer), "mf_%s", pszFile); + *ppszOutFile = pState->szBuffer; + return TRUE; +} + +static BOOL CALLBACK MungeSymbol(_In_opt_ PVOID pContext, + _In_ ULONG nOrigOrdinal, + _In_ ULONG nOrdinal, + _Out_ ULONG *pnOutOrdinal, + _In_opt_ LPCSTR pszOrigSymbol, + _In_opt_ LPCSTR pszSymbol, + _Outptr_result_maybenull_ LPCSTR *ppszOutSymbol) +{ + (void)nOrigOrdinal; + (void)pszOrigSymbol; + MUNGE_STATE *pState = (MUNGE_STATE *)pContext; + + pState->fLastWasByway = FALSE; + + printf("."); + if (nOrdinal != 0) { + if (s_fToSymbols) { + StringCchPrintfA(pState->szBuffer, sizeof(pState->szBuffer), "mo_%d", (int)nOrdinal); + *pnOutOrdinal = 0; + *ppszOutSymbol = pState->szBuffer; + } + else { + *pnOutOrdinal = 10000 + nOrdinal; + *ppszOutSymbol = NULL; + } + } + else { + StringCchPrintfA(pState->szBuffer, sizeof(pState->szBuffer), "ms_%s", pszSymbol); + *pnOutOrdinal = 0; + *ppszOutSymbol = pState->szBuffer; + } + return TRUE; +} + +static BOOL CALLBACK MungeCommit(PVOID pContext) +{ + MUNGE_STATE *pState = (MUNGE_STATE *)pContext; + + pState->fLastWasByway = FALSE; + + printf("\n"); + (void)pContext; + return TRUE; +} + +////////////////////////////////////////////////////////////////////////////// +// +static BOOL CALLBACK RestoreByway(_In_opt_ PVOID pContext, + _In_opt_ LPCSTR pszFile, + _Outptr_result_maybenull_ LPCSTR *ppszOutFile) +{ + (void)pContext; + (void)pszFile; + + *ppszOutFile = NULL; + return TRUE; +} + +static BOOL CALLBACK RestoreFile(_In_opt_ PVOID pContext, + _In_ LPCSTR pszOrigFile, + _In_ LPCSTR pszFile, + _Outptr_result_maybenull_ LPCSTR *ppszOutFile) +{ + (void)pContext; + (void)pszFile; + + *ppszOutFile = pszOrigFile; + return TRUE; +} + +static BOOL CALLBACK RestoreSymbol(_In_opt_ PVOID pContext, + _In_ ULONG nOrigOrdinal, + _In_ ULONG nOrdinal, + _Out_ ULONG *pnOutOrdinal, + _In_opt_ LPCSTR pszOrigSymbol, + _In_opt_ LPCSTR pszSymbol, + _Outptr_result_maybenull_ LPCSTR *ppszOutSymbol) +{ + (void)pContext; + (void)nOrdinal; + (void)pszSymbol; + + *pnOutOrdinal = nOrigOrdinal; + *ppszOutSymbol = pszOrigSymbol; + return TRUE; +} + +static BOOL CALLBACK RestoreCommit(PVOID pContext) +{ + (void)pContext; + return TRUE; +} + +////////////////////////////////////////////////////////////////////////////// +// + +BOOL EditFile(PCHAR pszInput, PCHAR pszOutput) +{ + BOOL fGood = TRUE; + + HANDLE hOld = INVALID_HANDLE_VALUE; + HANDLE hNew = INVALID_HANDLE_VALUE; + PDETOUR_BINARY pBinary = NULL; + + if (pszOutput != NULL) { + printf("%s -> %s:\n", pszInput, pszOutput); + } + else { + printf("%s:\n", pszInput); + } + + hOld = CreateFileA(pszInput, + GENERIC_READ, + FILE_SHARE_READ, + NULL, + OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL, + NULL); + + if (hOld == INVALID_HANDLE_VALUE) { + printf("Couldn't open input file: %s, error: %ld\n", + pszInput, GetLastError()); + fGood = FALSE; + goto end; + } + + if ((pBinary = DetourBinaryOpen(hOld)) == NULL) { + printf("DetourBinaryOpen failed: %ld\n", GetLastError()); + goto end; + } + + if (hOld != INVALID_HANDLE_VALUE) { + CloseHandle(hOld); + hOld = INVALID_HANDLE_VALUE; + } + + if (s_fRestore) { + if (!DetourBinaryEditImports(pBinary, + NULL, + RestoreByway, + RestoreFile, + RestoreSymbol, + RestoreCommit)) { + + printf("DetourBinaryEditImports for munge failed: %ld\n", GetLastError()); + } + } + + if (s_fMunge) { + MUNGE_STATE state; + state.fLastWasByway = FALSE; + state.nBywayCount = 1; + + if (!DetourBinaryEditImports(pBinary, + &state, + MungeByway, + MungeFile, + MungeSymbol, + MungeCommit)) { + + printf("DetourBinaryEditImports for munge failed: %ld\n", GetLastError()); + } + } + + if (s_fList) { + if (!DetourBinaryEditImports(pBinary, + NULL, + ListByway, + ListFile, + ListSymbol, + ListCommit)) { + + printf("DetourBinaryEditImports for list failed: %ld\n", GetLastError()); + } + } + + if (pszOutput != NULL) { + hNew = CreateFileA(pszOutput, + GENERIC_WRITE | GENERIC_READ, 0, NULL, CREATE_ALWAYS, + FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, NULL); + if (hNew == INVALID_HANDLE_VALUE) { + printf("Couldn't open output file: %s, error: %ld\n", + pszOutput, GetLastError()); + fGood = FALSE; + goto end; + } + + if (!DetourBinaryWrite(pBinary, hNew)) { + printf("DetourBinaryWrite failed: %ld\n", GetLastError()); + fGood = FALSE; + } + + CloseHandle(hNew); + hNew = INVALID_HANDLE_VALUE; + } + + DetourBinaryClose(pBinary); + pBinary = NULL; + + + if (fGood && pszOutput != NULL) { + if (!BindImageEx(BIND_NO_BOUND_IMPORTS, pszOutput, ".", ".", NULL)) { + printf("Warning: Couldn't bind binary %s: %ld\n", pszOutput, GetLastError()); + } + } + + end: + if (pBinary) { + DetourBinaryClose(pBinary); + pBinary = NULL; + } + if (hNew != INVALID_HANDLE_VALUE) { + CloseHandle(hNew); + hNew = INVALID_HANDLE_VALUE; + } + if (hOld != INVALID_HANDLE_VALUE) { + CloseHandle(hOld); + hOld = INVALID_HANDLE_VALUE; + } + return fGood; +} + +////////////////////////////////////////////////////////////////////////////// +// +void PrintUsage(void) +{ + printf("Usage:\n" + " impmunge [options] binary_files\n" + "Options:\n" + " /l : List imports.\n" + " /l- : Don't list imports.\n" + " /m : Munge imports.\n" + " /r : Remove import munges.\n" + " /o:file : Set name of output file; must be include with /m or /r.\n" + " /? : This help screen.\n"); +} + +//////////////////////////////////////////////////////////////////////// main. +// +int CDECL main(int argc, char **argv) +{ + BOOL fNeedHelp = FALSE; + PCHAR pszOutput = NULL; + + int arg = 1; + for (; arg < argc && !fNeedHelp; arg++) { + if (argv[arg][0] == '-' || argv[arg][0] == '/') { + CHAR *argn = argv[arg] + 1; + CHAR *argp = argn; + while (*argp && *argp != ':') + argp++; + if (*argp == ':') + *argp++ = '\0'; + + switch (argn[0]) { + + case 'l': // List contents of import table. + case 'L': + s_fList = (argn[1] != '-'); + break; + + case 'm': // Munge import table. + case 'M': + s_fMunge = (argn[1] != '-'); + break; + + case 'o': // Set output file name. + case 'O': + pszOutput = argp; + break; + case 'r': // Restore file to unmunged state. + case 'R': + s_fRestore = (argn[1] != '-'); + break; + + case 's': // Munge ordinals to symbols + case 'S': + s_fToSymbols = true; + break; + + case '?': // Help + fNeedHelp = TRUE; + break; + + default: + fNeedHelp = TRUE; + printf("Bad argument: %s:%s\n", argn, argp); + break; + } + } + else { + if (!s_fList && !s_fMunge && !s_fRestore) { + fNeedHelp = TRUE; + break; + } + if (pszOutput == NULL && (s_fMunge || s_fRestore)) { + fNeedHelp = TRUE; + break; + } + + EditFile(argv[arg], pszOutput); + pszOutput = NULL; + } + } + if (argc == 1) { + fNeedHelp = TRUE; + } + if (fNeedHelp) { + PrintUsage(); + return 1; + } + return 0; +} + +// End of File |