diff options
author | Thorvald Natvig <slicer@users.sourceforge.net> | 2010-02-28 20:15:56 +0300 |
---|---|---|
committer | Thorvald Natvig <slicer@users.sourceforge.net> | 2010-02-28 20:16:27 +0300 |
commit | d44c84cb1aa6883864c4669cc6b0b9262a157c59 (patch) | |
tree | dcd5f854a827f80e4bd82f030feab74459a784ec /overlay | |
parent | f223a8292f93db1e287b2132758090cb92dfee0f (diff) |
This is not the window you are looking for
Diffstat (limited to 'overlay')
-rw-r--r-- | overlay/HardHook.cpp | 283 | ||||
-rw-r--r-- | overlay/HardHook.h | 70 | ||||
-rw-r--r-- | overlay/lib.cpp | 219 | ||||
-rw-r--r-- | overlay/lib.h | 23 | ||||
-rw-r--r-- | overlay/overlay.pro | 4 |
5 files changed, 356 insertions, 243 deletions
diff --git a/overlay/HardHook.cpp b/overlay/HardHook.cpp new file mode 100644 index 000000000..5f11f1f7f --- /dev/null +++ b/overlay/HardHook.cpp @@ -0,0 +1,283 @@ +/* Copyright (C) 2005-2010, Thorvald Natvig <thorvald@natvig.com> + + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + - Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + - Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + - Neither the name of the Mumble Developers nor the names of its + contributors may be used to endorse or promote products derived from this + software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR + CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include "HardHook.h" + +void *HardHook::pCode = NULL; +unsigned int HardHook::uiCode = 0; + +static void __cdecl ods(const char *format, ...) { + char buf[4096], *p = buf; + va_list args; + + va_start(args, format); + int len = _vsnprintf_s(p, sizeof(buf) - 1, _TRUNCATE, format, args); + va_end(args); + + if (len <= 0) + return; + + p += len; + + while (p > buf && isspace(p[-1])) + *--p = '\0'; + + *p++ = '\r'; + *p++ = '\n'; + *p = '\0'; + + OutputDebugStringA(buf); +} + + +HardHook::HardHook() { + int i; + baseptr = NULL; + for (i=0;i<6;i++) + orig[i]=replace[i]=0; +} + +HardHook::HardHook(voidFunc func, voidFunc replacement) { + int i; + baseptr = NULL; + for (i=0;i<6;i++) + orig[i]=replace[i]=0; + setup(func, replacement); +} + +static unsigned int modrmbytes(unsigned char a, unsigned char b) { + unsigned char lower = (a & 0x0f); + if (a >= 0xc0) { + return 0; + } else if (a >= 0x80) { + if ((lower == 4) || (lower == 12)) + return 5; + else + return 4; + } else if (a >= 0x40) { + if ((lower == 4) || (lower == 12)) + return 2; + else + return 1; + + } else { + if ((lower == 4) || (lower == 12)) { + if ((b & 0x07) == 0x05) + return 5; + else + return 1; + } else if ((lower == 5) || (lower == 13)) + return 4; + return 0; + } +} + +void *HardHook::cloneCode(void **porig) { + if (! pCode || uiCode > 4000) { + uiCode = 0; + pCode = VirtualAlloc(NULL, 4096, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); + } + + unsigned char *o = (unsigned char *) *porig; + unsigned char *n = (unsigned char *) pCode; + n += uiCode; + unsigned int idx = 0; + + while (*o == 0xe9) { + int *iptr = reinterpret_cast<int *>(o+1); + o += *iptr + 5; + + ods("HardHook: Chaining from %p to %p", *porig, o); + *porig = o; + } + + do { + unsigned char opcode = o[idx]; + unsigned char a = o[idx+1]; + unsigned char b = o[idx+2]; + unsigned int extra = 0; + + n[idx] = opcode; + idx++; + + switch (opcode) { + case 0x50: // PUSH + case 0x51: + case 0x52: + case 0x53: + case 0x54: + case 0x55: + case 0x56: + case 0x57: + case 0x58: // POP + case 0x59: + case 0x5a: + case 0x5b: + case 0x5c: + case 0x5d: + case 0x5e: + case 0x5f: + break; + case 0x68: + extra = 4; + break; + case 0x81: // CMP immediate + extra = modrmbytes(a,b) + 5; + break; + case 0x83: // CMP + extra = modrmbytes(a,b) + 2; + break; + case 0x8b: // MOV + extra = modrmbytes(a,b) + 1; + break; + default: + ods("HardHook: Unknown opcode at %d: %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x", idx-1, o[0], o[1], o[2], o[3], o[4], o[5], o[6], o[7], o[8], o[9], o[10], o[11]); + return NULL; + break; + } + for (unsigned int i=0;i<extra;++i) + n[idx+i] = o[idx+i]; + idx += extra; + + } while (idx < 6); + + n[idx++] = 0xe9; + int offs = o - n - 5; + + int *iptr = reinterpret_cast<int *>(&n[idx]); + *iptr = offs; + idx += 4; + + uiCode += idx; + FlushInstructionCache(GetCurrentProcess(), n, idx); + + return n; +} + +void HardHook::setup(voidFunc func, voidFunc replacement) { + int i; + DWORD oldProtect, restoreProtect; + + if (baseptr) + return; + + unsigned char *fptr = reinterpret_cast<unsigned char *>(func); + unsigned char *nptr = reinterpret_cast<unsigned char *>(replacement); + + ods("HardHook: Asked to replace %p with %p", func, replacement); + + if (VirtualProtect(fptr, 16, PAGE_EXECUTE_READ, &oldProtect)) { + call = (voidFunc) cloneCode((void **) &fptr); + + if (call) { + bTrampoline = true; + } else { + bTrampoline = false; + call = func; + } + + unsigned char **iptr = reinterpret_cast<unsigned char **>(&replace[1]); + *iptr = nptr; + replace[0] = 0x68; + replace[5] = 0xc3; + + for (i=0;i<6;i++) + orig[i]=fptr[i]; + + baseptr = fptr; + inject(true); + + VirtualProtect(fptr, 16, oldProtect, &restoreProtect); + } else { + ods("Failed initial vprotect"); + } +} + +void HardHook::setupInterface(IUnknown *unkn, LONG funcoffset, voidFunc replacement) { + ods("HardHook: Replacing %p function #%ld", unkn, funcoffset); + void **ptr = reinterpret_cast<void **>(unkn); + ptr = reinterpret_cast<void **>(ptr[0]); + setup(reinterpret_cast<voidFunc>(ptr[funcoffset]), replacement); +} + +void HardHook::inject(bool force) { + DWORD oldProtect, restoreProtect; + int i; + + if (! baseptr) + return; + if (! force && bTrampoline) + return; + + if (VirtualProtect(baseptr, 6, PAGE_EXECUTE_READWRITE, &oldProtect)) { + for (i=0;i<6;i++) + baseptr[i] = replace[i]; + VirtualProtect(baseptr, 6, oldProtect, &restoreProtect); + FlushInstructionCache(GetCurrentProcess(),baseptr, 6); + } + for (i=0;i<6;i++) + if (baseptr[i] != replace[i]) + ods("HH: Injection failure at byte %d", i); +} + +void HardHook::restore(bool force) { + DWORD oldProtect, restoreProtect; + int i; + + if (! baseptr) + return; + if (! force && bTrampoline) + return; + + if (VirtualProtect(baseptr, 6, PAGE_EXECUTE_READWRITE, &oldProtect)) { + for (i=0;i<6;i++) + baseptr[i] = orig[i]; + VirtualProtect(baseptr, 6, oldProtect, &restoreProtect); + FlushInstructionCache(GetCurrentProcess(),baseptr, 6); + } +} + +void HardHook::print() { + ods("HardHook: %02x %02x %02x %02x %02x => %02x %02x %02x %02x %02x (%02x %02x %02x %02x %02x)", + orig[0], orig[1], orig[2], orig[3], orig[4], + replace[0], replace[1], replace[2], replace[3], replace[4], + baseptr[0], baseptr[1], baseptr[2], baseptr[3], baseptr[4]); +} + +void HardHook::check() { + if (memcmp(baseptr, replace, 6) != 0) { + if (memcmp(baseptr, orig, 6) == 0) { + ods("HH: Restoring function %p", baseptr); + inject(true); + } else { + ods("HH: Function %p replaced by third party. Lost."); + } + } +} diff --git a/overlay/HardHook.h b/overlay/HardHook.h new file mode 100644 index 000000000..86488092a --- /dev/null +++ b/overlay/HardHook.h @@ -0,0 +1,70 @@ +/* Copyright (C) 2005-2010, Thorvald Natvig <thorvald@natvig.com> + + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + - Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + - Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + - Neither the name of the Mumble Developers nor the names of its + contributors may be used to endorse or promote products derived from this + software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR + CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef _HARDHOOK_H +#define _HARDHOOK_H + +#define _UNICODE +#ifndef _WIN32_WINNT +#define _WIN32_WINNT 0x0501 +#endif +#include <stdio.h> +#include <stdarg.h> +#include <ctype.h> +#include <windows.h> +#include <math.h> +#include <map> +#include <vector> +#include <string> + +typedef void *(*voidFunc)(); + +struct HardHook { + unsigned char *baseptr; + unsigned char orig[6]; + unsigned char replace[6]; + bool bTrampoline; + voidFunc call; + + static void *pCode; + static unsigned int uiCode; + + HardHook(); + HardHook(voidFunc func, voidFunc replacement); + void *cloneCode(void **orig); + void setup(voidFunc func, voidFunc replacement); + void setupInterface(IUnknown *intf, LONG funcoffset, voidFunc replacement); + void inject(bool force = false); + void restore(bool force = false); + void print(); + void check(); +}; + +#endif diff --git a/overlay/lib.cpp b/overlay/lib.cpp index 380158434..658abeda0 100644 --- a/overlay/lib.cpp +++ b/overlay/lib.cpp @@ -40,228 +40,9 @@ static BOOL bDebug = FALSE; static HardHook hhLoad; static HardHook hhLoadW; -void *HardHook::pCode = NULL; -unsigned int HardHook::uiCode = 0; static SharedData *sd; -HardHook::HardHook() { - int i; - baseptr = NULL; - for (i=0;i<6;i++) - orig[i]=replace[i]=0; -} - -static unsigned int modrmbytes(unsigned char a, unsigned char b) { - unsigned char lower = (a & 0x0f); - if (a >= 0xc0) { - return 0; - } else if (a >= 0x80) { - if ((lower == 4) || (lower == 12)) - return 5; - else - return 4; - } else if (a >= 0x40) { - if ((lower == 4) || (lower == 12)) - return 2; - else - return 1; - - } else { - if ((lower == 4) || (lower == 12)) { - if ((b & 0x07) == 0x05) - return 5; - else - return 1; - } else if ((lower == 5) || (lower == 13)) - return 4; - return 0; - } -} - -void *HardHook::cloneCode(void **porig) { - if (! pCode || uiCode > 4000) { - uiCode = 0; - pCode = VirtualAlloc(NULL, 4096, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); - } - - unsigned char *o = (unsigned char *) *porig; - unsigned char *n = (unsigned char *) pCode; - n += uiCode; - unsigned int idx = 0; - - while (*o == 0xe9) { - int *iptr = reinterpret_cast<int *>(o+1); - o += *iptr + 5; - - ods("Chaining from %p to %p", *porig, o); - *porig = o; - } - - do { - unsigned char opcode = o[idx]; - unsigned char a = o[idx+1]; - unsigned char b = o[idx+2]; - unsigned int extra = 0; - - n[idx] = opcode; - idx++; - - switch (opcode) { - case 0x50: // PUSH - case 0x51: - case 0x52: - case 0x53: - case 0x54: - case 0x55: - case 0x56: - case 0x57: - case 0x58: // POP - case 0x59: - case 0x5a: - case 0x5b: - case 0x5c: - case 0x5d: - case 0x5e: - case 0x5f: - break; - case 0x68: - extra = 4; - break; - case 0x81: // CMP immediate - extra = modrmbytes(a,b) + 5; - break; - case 0x83: // CMP - extra = modrmbytes(a,b) + 2; - break; - case 0x8b: // MOV - extra = modrmbytes(a,b) + 1; - break; - default: - fods("Unknown opcode at %d: %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x", idx-1, o[0], o[1], o[2], o[3], o[4], o[5], o[6], o[7], o[8], o[9], o[10], o[11]); - return NULL; - break; - } - for (unsigned int i=0;i<extra;++i) - n[idx+i] = o[idx+i]; - idx += extra; - - } while (idx < 6); - - n[idx++] = 0xe9; - int offs = o - n - 5; - - int *iptr = reinterpret_cast<int *>(&n[idx]); - *iptr = offs; - idx += 4; - - uiCode += idx; - FlushInstructionCache(GetCurrentProcess(), n, idx); - - return n; -} - -void HardHook::setup(voidFunc func, voidFunc replacement) { - int i; - DWORD oldProtect, restoreProtect; - - if (baseptr) - return; - - unsigned char *fptr = reinterpret_cast<unsigned char *>(func); - unsigned char *nptr = reinterpret_cast<unsigned char *>(replacement); - - ods("HH: Asked to replace %p with %p", func, replacement); - - if (VirtualProtect(fptr, 16, PAGE_EXECUTE_READ, &oldProtect)) { - call = (voidFunc) cloneCode((void **) &fptr); - - if (call) { - bTrampoline = true; - } else { - bTrampoline = false; - call = func; - } - - unsigned char **iptr = reinterpret_cast<unsigned char **>(&replace[1]); - *iptr = nptr; - replace[0] = 0x68; - replace[5] = 0xc3; - - for (i=0;i<6;i++) - orig[i]=fptr[i]; - - baseptr = fptr; - inject(true); - - VirtualProtect(fptr, 16, oldProtect, &restoreProtect); - } else { - ods("Failed initial vprotect"); - } -} - -void HardHook::setupInterface(IUnknown *unkn, LONG funcoffset, voidFunc replacement) { - ods("HH: Replacing %p function #%ld", unkn, funcoffset); - void **ptr = reinterpret_cast<void **>(unkn); - ptr = reinterpret_cast<void **>(ptr[0]); - setup(reinterpret_cast<voidFunc>(ptr[funcoffset]), replacement); -} - -void HardHook::inject(bool force) { - DWORD oldProtect, restoreProtect; - int i; - - if (! baseptr) - return; - if (! force && bTrampoline) - return; - - if (VirtualProtect(baseptr, 6, PAGE_EXECUTE_READWRITE, &oldProtect)) { - for (i=0;i<6;i++) - baseptr[i] = replace[i]; - VirtualProtect(baseptr, 6, oldProtect, &restoreProtect); - FlushInstructionCache(GetCurrentProcess(),baseptr, 6); - } - for (i=0;i<6;i++) - if (baseptr[i] != replace[i]) - ods("HH: Injection failure at byte %d", i); -} - -void HardHook::restore(bool force) { - DWORD oldProtect, restoreProtect; - int i; - - if (! baseptr) - return; - if (! force && bTrampoline) - return; - - if (VirtualProtect(baseptr, 6, PAGE_EXECUTE_READWRITE, &oldProtect)) { - for (i=0;i<6;i++) - baseptr[i] = orig[i]; - VirtualProtect(baseptr, 6, oldProtect, &restoreProtect); - FlushInstructionCache(GetCurrentProcess(),baseptr, 6); - } -} - -void HardHook::print() { - ods("HH: %02x %02x %02x %02x %02x => %02x %02x %02x %02x %02x (%02x %02x %02x %02x %02x)", - orig[0], orig[1], orig[2], orig[3], orig[4], - replace[0], replace[1], replace[2], replace[3], replace[4], - baseptr[0], baseptr[1], baseptr[2], baseptr[3], baseptr[4]); -} - -void HardHook::check() { - if (memcmp(baseptr, replace, 6) != 0) { - if (memcmp(baseptr, orig, 6) == 0) { - ods("HH: Restoring function %p", baseptr); - inject(true); - } else { - ods("HH: Function %p replaced by third party. Lost."); - } - } -} - FakeInterface::FakeInterface(IUnknown *orig, int entries) { this->pOriginal = orig; pAssembly = VirtualAlloc(NULL, entries * 256, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); diff --git a/overlay/lib.h b/overlay/lib.h index 216c6ad8c..f06b32957 100644 --- a/overlay/lib.h +++ b/overlay/lib.h @@ -42,6 +42,7 @@ #include <vector> #include <string> #include "overlay.h" +#include "HardHook.h" #define lround(x) static_cast<long int>((x) + (((x) >= 0.0) ? 0.5 : -0.5)) @@ -50,28 +51,6 @@ using namespace std; void __cdecl fods(const char *format, ...); void __cdecl ods(const char *format, ...); -typedef void *(*voidFunc)(); - -struct HardHook { - unsigned char *baseptr; - unsigned char orig[6]; - unsigned char replace[6]; - bool bTrampoline; - voidFunc call; - - static void *pCode; - static unsigned int uiCode; - - HardHook(); - void *cloneCode(void **orig); - void setup(voidFunc func, voidFunc replacement); - void setupInterface(IUnknown *intf, LONG funcoffset, voidFunc replacement); - void inject(bool force = false); - void restore(bool force = false); - void print(); - void check(); -}; - struct Direct3D9Data { int iOffsetCreate; int iOffsetCreateEx; diff --git a/overlay/overlay.pro b/overlay/overlay.pro index 4b5c52cff..59d919616 100644 --- a/overlay/overlay.pro +++ b/overlay/overlay.pro @@ -5,9 +5,9 @@ CONFIG -= qt CONFIG *= dll shared debug_and_release warn_on CONFIG -= embed_manifest_dll TARGET = mumble_ol -SOURCES = lib.cpp d3d9.cpp d3d10.cpp opengl.cpp +SOURCES = lib.cpp d3d9.cpp d3d10.cpp opengl.cpp HardHook.cpp EFFECTS = overlay.fx -DIST = overlay.h overlay.fx +DIST = overlay.h overlay.fx HardHook.h DEFINES -= UNICODE |