├── bin ├── SuperF12.dll └── SuperF12.exe ├── lib └── SuperF12.lib ├── src ├── include │ └── SuperF12.h ├── SuperF12.dll │ ├── Common.h │ ├── Common.cpp │ ├── Globals.h │ ├── resource.h │ ├── DllMain.cpp │ ├── Globals.cpp │ ├── HookContext.h │ ├── SuperF12.cpp │ ├── DevToolsHost.h │ ├── HookContext.cpp │ ├── SuperF12.def │ ├── SuperF12.dll.rc │ ├── DevToolsHost.cpp │ ├── Lock.cpp │ ├── Lock.h │ ├── SuperF12.dll.vcproj │ └── Detours │ │ ├── detours.h │ │ ├── detours.cpp │ │ └── disasm.cpp ├── SuperF12.exe │ ├── Common.h │ ├── Common.cpp │ ├── Utility.h │ ├── Version.h │ ├── AttachDlg.cpp │ ├── AttachDlg.h │ ├── Utility.cpp │ ├── WinMain.cpp │ ├── res │ │ ├── F12.cur │ │ ├── toolbar.bmp │ │ ├── SuperF12.ico │ │ ├── manifest.xml │ │ └── version.rc2 │ ├── SuperF12.exe.rc │ ├── resource.h │ └── SuperF12.exe.vcproj └── SuperF12.sln ├── .gitignore ├── README.md └── LICENSE /bin/SuperF12.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/titilima/SuperF12/HEAD/bin/SuperF12.dll -------------------------------------------------------------------------------- /bin/SuperF12.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/titilima/SuperF12/HEAD/bin/SuperF12.exe -------------------------------------------------------------------------------- /lib/SuperF12.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/titilima/SuperF12/HEAD/lib/SuperF12.lib -------------------------------------------------------------------------------- /src/include/SuperF12.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/titilima/SuperF12/HEAD/src/include/SuperF12.h -------------------------------------------------------------------------------- /src/SuperF12.dll/Common.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/titilima/SuperF12/HEAD/src/SuperF12.dll/Common.h -------------------------------------------------------------------------------- /src/SuperF12.exe/Common.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/titilima/SuperF12/HEAD/src/SuperF12.exe/Common.h -------------------------------------------------------------------------------- /src/SuperF12.dll/Common.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/titilima/SuperF12/HEAD/src/SuperF12.dll/Common.cpp -------------------------------------------------------------------------------- /src/SuperF12.dll/Globals.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/titilima/SuperF12/HEAD/src/SuperF12.dll/Globals.h -------------------------------------------------------------------------------- /src/SuperF12.dll/resource.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/titilima/SuperF12/HEAD/src/SuperF12.dll/resource.h -------------------------------------------------------------------------------- /src/SuperF12.exe/Common.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/titilima/SuperF12/HEAD/src/SuperF12.exe/Common.cpp -------------------------------------------------------------------------------- /src/SuperF12.exe/Utility.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/titilima/SuperF12/HEAD/src/SuperF12.exe/Utility.h -------------------------------------------------------------------------------- /src/SuperF12.exe/Version.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/titilima/SuperF12/HEAD/src/SuperF12.exe/Version.h -------------------------------------------------------------------------------- /src/SuperF12.dll/DllMain.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/titilima/SuperF12/HEAD/src/SuperF12.dll/DllMain.cpp -------------------------------------------------------------------------------- /src/SuperF12.dll/Globals.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/titilima/SuperF12/HEAD/src/SuperF12.dll/Globals.cpp -------------------------------------------------------------------------------- /src/SuperF12.dll/HookContext.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/titilima/SuperF12/HEAD/src/SuperF12.dll/HookContext.h -------------------------------------------------------------------------------- /src/SuperF12.dll/SuperF12.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/titilima/SuperF12/HEAD/src/SuperF12.dll/SuperF12.cpp -------------------------------------------------------------------------------- /src/SuperF12.exe/AttachDlg.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/titilima/SuperF12/HEAD/src/SuperF12.exe/AttachDlg.cpp -------------------------------------------------------------------------------- /src/SuperF12.exe/AttachDlg.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/titilima/SuperF12/HEAD/src/SuperF12.exe/AttachDlg.h -------------------------------------------------------------------------------- /src/SuperF12.exe/Utility.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/titilima/SuperF12/HEAD/src/SuperF12.exe/Utility.cpp -------------------------------------------------------------------------------- /src/SuperF12.exe/WinMain.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/titilima/SuperF12/HEAD/src/SuperF12.exe/WinMain.cpp -------------------------------------------------------------------------------- /src/SuperF12.exe/res/F12.cur: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/titilima/SuperF12/HEAD/src/SuperF12.exe/res/F12.cur -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | Debug/ 2 | Release/ 3 | 4 | *.aps 5 | *.exp 6 | *.ncb 7 | *.pdb 8 | *.suo 9 | *.user 10 | 11 | -------------------------------------------------------------------------------- /src/SuperF12.dll/DevToolsHost.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/titilima/SuperF12/HEAD/src/SuperF12.dll/DevToolsHost.h -------------------------------------------------------------------------------- /src/SuperF12.dll/HookContext.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/titilima/SuperF12/HEAD/src/SuperF12.dll/HookContext.cpp -------------------------------------------------------------------------------- /src/SuperF12.dll/SuperF12.def: -------------------------------------------------------------------------------- 1 | LIBRARY "SuperF12" 2 | 3 | EXPORTS 4 | 5 | InitSuperF12 6 | ShowDevTools 7 | -------------------------------------------------------------------------------- /src/SuperF12.dll/SuperF12.dll.rc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/titilima/SuperF12/HEAD/src/SuperF12.dll/SuperF12.dll.rc -------------------------------------------------------------------------------- /src/SuperF12.exe/SuperF12.exe.rc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/titilima/SuperF12/HEAD/src/SuperF12.exe/SuperF12.exe.rc -------------------------------------------------------------------------------- /src/SuperF12.exe/res/toolbar.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/titilima/SuperF12/HEAD/src/SuperF12.exe/res/toolbar.bmp -------------------------------------------------------------------------------- /src/SuperF12.dll/DevToolsHost.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/titilima/SuperF12/HEAD/src/SuperF12.dll/DevToolsHost.cpp -------------------------------------------------------------------------------- /src/SuperF12.exe/res/SuperF12.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/titilima/SuperF12/HEAD/src/SuperF12.exe/res/SuperF12.ico -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | SuperF12 2 | ======== 3 | 4 | A powerful tool which can launch IE developer tools for all embedded IE windows. 5 | -------------------------------------------------------------------------------- /src/SuperF12.exe/res/manifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | SuperF12 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /src/SuperF12.exe/resource.h: -------------------------------------------------------------------------------- 1 | //{{NO_DEPENDENCIES}} 2 | // Microsoft Visual C++ generated include file. 3 | // Used by SuperF12.exe.rc 4 | // 5 | #define IDR_RT_MANIFEST 1 6 | #define IDI_ICON_MAIN 101 7 | #define IDC_CUR_F12 102 8 | #define IDD_DLG_ATTACH 201 9 | #define IDC_TREE 1001 10 | #define IDC_ST_INFO 1101 11 | #define IDC_ST_ARROW 1102 12 | #define IDC_ST_HWND 1103 13 | 14 | // Next default values for new objects 15 | // 16 | #ifdef APSTUDIO_INVOKED 17 | #ifndef APSTUDIO_READONLY_SYMBOLS 18 | #define _APS_NEXT_RESOURCE_VALUE 202 19 | #define _APS_NEXT_COMMAND_VALUE 40001 20 | #define _APS_NEXT_CONTROL_VALUE 1104 21 | #define _APS_NEXT_SYMED_VALUE 101 22 | #endif 23 | #endif 24 | -------------------------------------------------------------------------------- /src/SuperF12.exe/res/version.rc2: -------------------------------------------------------------------------------- 1 | #include "..\Version.h" 2 | 3 | VS_VERSION_INFO VERSIONINFO 4 | FILEVERSION F12_RCVER 5 | PRODUCTVERSION F12_RCVER 6 | FILEFLAGSMASK 0x17L 7 | #ifdef _DEBUG 8 | FILEFLAGS 0x1L 9 | #else 10 | FILEFLAGS 0x0L 11 | #endif 12 | FILEOS 0x4L 13 | FILETYPE 0x1L 14 | FILESUBTYPE 0x0L 15 | BEGIN 16 | BLOCK "StringFileInfo" 17 | BEGIN 18 | BLOCK "080404b0" 19 | BEGIN 20 | VALUE "CompanyName", "Titi Studio" 21 | VALUE "FileDescription", "SuperF12" 22 | VALUE "FileVersion", F12_RCVERSTR 23 | VALUE "InternalName", "SuperF12" 24 | VALUE "LegalCopyright", "Copyright (C) 2001-2013" 25 | VALUE "OriginalFilename", "SuperF12.exe" 26 | VALUE "ProductName", "SuperF12" 27 | VALUE "ProductVersion", F12_RCVERSTR 28 | END 29 | END 30 | BLOCK "VarFileInfo" 31 | BEGIN 32 | VALUE "Translation", 0x804, 1200 33 | END 34 | END 35 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2013 titilima 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /src/SuperF12.dll/Lock.cpp: -------------------------------------------------------------------------------- 1 | #include "Common.h" 2 | #include "Lock.h" 3 | 4 | Lock::Lock(PCTSTR pszName) : m_cntReaders(0), m_hDataLock(CreateSemaphore(NULL, 1, 1, pszName)) 5 | { 6 | ::InitializeCriticalSection(&m_cs); 7 | } 8 | 9 | Lock::~Lock(void) 10 | { 11 | CloseHandle(m_hDataLock); 12 | ::DeleteCriticalSection(&m_cs); 13 | } 14 | 15 | void Lock::AcquireForReading(void) 16 | { 17 | EnterCS(); 18 | if (1 == ++m_cntReaders) 19 | { 20 | WaitForSingleObject(m_hDataLock, INFINITE); 21 | } 22 | LeaveCS(); 23 | } 24 | 25 | void Lock::AcquireForWriting(void) 26 | { 27 | WaitForSingleObject(m_hDataLock, INFINITE); 28 | } 29 | 30 | void Lock::EnterCS(void) 31 | { 32 | ::EnterCriticalSection(&m_cs); 33 | } 34 | 35 | void Lock::LeaveCS(void) 36 | { 37 | ::LeaveCriticalSection(&m_cs); 38 | } 39 | 40 | void Lock::ReleaseForReading(void) 41 | { 42 | EnterCS(); 43 | if (0 == --m_cntReaders) 44 | ReleaseSemaphore(m_hDataLock, 1, NULL); 45 | LeaveCS(); 46 | } 47 | 48 | void Lock::ReleaseForWriting(void) 49 | { 50 | ReleaseSemaphore(m_hDataLock, 1, NULL); 51 | } 52 | -------------------------------------------------------------------------------- /src/SuperF12.dll/Lock.h: -------------------------------------------------------------------------------- 1 | #ifndef LOCK_H 2 | #define LOCK_H 3 | 4 | #pragma once 5 | 6 | class Lock 7 | { 8 | public: 9 | Lock(PCTSTR pszName = NULL); 10 | ~Lock(void); 11 | public: 12 | void AcquireForReading(void); 13 | void AcquireForWriting(void); 14 | void AssertIsLocked(void); 15 | void ReleaseForReading(void); 16 | void ReleaseForWriting(void); 17 | private: 18 | void EnterCS(void); 19 | void LeaveCS(void); 20 | private: 21 | CRITICAL_SECTION m_cs; 22 | size_t m_cntReaders; 23 | HANDLE m_hDataLock; 24 | }; 25 | 26 | class AutoReadLock 27 | { 28 | public: 29 | AutoReadLock(Lock& lock) : m_lock(lock) 30 | { 31 | m_lock.AcquireForReading(); 32 | } 33 | ~AutoReadLock(void) 34 | { 35 | m_lock.ReleaseForReading(); 36 | } 37 | private: 38 | Lock& m_lock; 39 | }; 40 | 41 | class AutoWriteLock 42 | { 43 | public: 44 | AutoWriteLock(Lock& lock) : m_lock(lock) 45 | { 46 | m_lock.AcquireForWriting(); 47 | } 48 | ~AutoWriteLock(void) 49 | { 50 | m_lock.ReleaseForWriting(); 51 | } 52 | private: 53 | Lock& m_lock; 54 | }; 55 | 56 | #endif // LOCK_H 57 | -------------------------------------------------------------------------------- /src/SuperF12.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 10.00 3 | # Visual Studio 2008 4 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SuperF12.exe", "SuperF12.exe\SuperF12.exe.vcproj", "{9163D946-B9EB-4048-A61F-D43DC9D965EB}" 5 | EndProject 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SuperF12.dll", "SuperF12.dll\SuperF12.dll.vcproj", "{A6B42641-F211-42A0-9DB7-8C7ACAA45DA4}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Win32 = Debug|Win32 11 | Release|Win32 = Release|Win32 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {9163D946-B9EB-4048-A61F-D43DC9D965EB}.Debug|Win32.ActiveCfg = Debug|Win32 15 | {9163D946-B9EB-4048-A61F-D43DC9D965EB}.Debug|Win32.Build.0 = Debug|Win32 16 | {9163D946-B9EB-4048-A61F-D43DC9D965EB}.Release|Win32.ActiveCfg = Release|Win32 17 | {9163D946-B9EB-4048-A61F-D43DC9D965EB}.Release|Win32.Build.0 = Release|Win32 18 | {A6B42641-F211-42A0-9DB7-8C7ACAA45DA4}.Debug|Win32.ActiveCfg = Debug|Win32 19 | {A6B42641-F211-42A0-9DB7-8C7ACAA45DA4}.Debug|Win32.Build.0 = Debug|Win32 20 | {A6B42641-F211-42A0-9DB7-8C7ACAA45DA4}.Release|Win32.ActiveCfg = Release|Win32 21 | {A6B42641-F211-42A0-9DB7-8C7ACAA45DA4}.Release|Win32.Build.0 = Release|Win32 22 | EndGlobalSection 23 | GlobalSection(SolutionProperties) = preSolution 24 | HideSolutionNode = FALSE 25 | EndGlobalSection 26 | EndGlobal 27 | -------------------------------------------------------------------------------- /src/SuperF12.exe/SuperF12.exe.vcproj: -------------------------------------------------------------------------------- 1 | 2 | 11 | 12 | 15 | 16 | 17 | 18 | 19 | 26 | 29 | 32 | 35 | 38 | 41 | 53 | 56 | 59 | 62 | 73 | 76 | 79 | 82 | 85 | 88 | 91 | 94 | 95 | 103 | 106 | 109 | 112 | 115 | 118 | 130 | 133 | 136 | 139 | 152 | 155 | 158 | 161 | 164 | 167 | 170 | 174 | 175 | 176 | 177 | 178 | 179 | 184 | 187 | 188 | 191 | 194 | 198 | 199 | 202 | 206 | 207 | 208 | 211 | 212 | 215 | 216 | 217 | 222 | 225 | 226 | 229 | 230 | 233 | 234 | 237 | 238 | 241 | 242 | 243 | 248 | 251 | 252 | 255 | 256 | 259 | 260 | 263 | 264 | 267 | 268 | 271 | 272 | 273 | 274 | 275 | 276 | 277 | -------------------------------------------------------------------------------- /src/SuperF12.dll/SuperF12.dll.vcproj: -------------------------------------------------------------------------------- 1 | 2 | 11 | 12 | 15 | 16 | 17 | 18 | 19 | 26 | 29 | 32 | 35 | 38 | 41 | 54 | 57 | 60 | 63 | 76 | 79 | 82 | 85 | 88 | 91 | 94 | 97 | 98 | 106 | 109 | 112 | 115 | 118 | 121 | 134 | 137 | 140 | 143 | 158 | 161 | 164 | 167 | 170 | 173 | 176 | 180 | 181 | 182 | 183 | 184 | 185 | 190 | 193 | 196 | 200 | 201 | 204 | 208 | 209 | 210 | 213 | 214 | 217 | 220 | 224 | 225 | 228 | 232 | 233 | 234 | 237 | 238 | 241 | 242 | 245 | 246 | 249 | 250 | 253 | 254 | 255 | 260 | 263 | 264 | 267 | 268 | 271 | 272 | 275 | 276 | 279 | 280 | 283 | 284 | 287 | 288 | 289 | 294 | 297 | 298 | 299 | 302 | 305 | 308 | 314 | 315 | 318 | 324 | 325 | 326 | 329 | 330 | 333 | 336 | 342 | 343 | 346 | 352 | 353 | 354 | 355 | 356 | 357 | 358 | 359 | -------------------------------------------------------------------------------- /src/SuperF12.dll/Detours/detours.h: -------------------------------------------------------------------------------- 1 | ////////////////////////////////////////////////////////////////////////////// 2 | // 3 | // Core Detours Functionality (detours.h of detours.lib) 4 | // 5 | // Microsoft Research Detours Package, Version 3.0 Build_316. 6 | // 7 | // Copyright (c) Microsoft Corporation. All rights reserved. 8 | // 9 | 10 | #pragma once 11 | #ifndef _DETOURS_H_ 12 | #define _DETOURS_H_ 13 | 14 | #define DETOURS_VERSION 30000 // 3.00.00 15 | 16 | ////////////////////////////////////////////////////////////////////////////// 17 | // 18 | 19 | #if (_MSC_VER < 1299) 20 | typedef LONG LONG_PTR; 21 | typedef ULONG ULONG_PTR; 22 | #endif 23 | 24 | #ifndef __in_z 25 | #define __in_z 26 | #endif 27 | 28 | ////////////////////////////////////////////////////////////////////////////// 29 | // 30 | #ifndef GUID_DEFINED 31 | #define GUID_DEFINED 32 | typedef struct _GUID 33 | { 34 | DWORD Data1; 35 | WORD Data2; 36 | WORD Data3; 37 | BYTE Data4[ 8 ]; 38 | } GUID; 39 | 40 | #ifdef INITGUID 41 | #define DEFINE_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \ 42 | const GUID name \ 43 | = { l, w1, w2, { b1, b2, b3, b4, b5, b6, b7, b8 } } 44 | #else 45 | #define DEFINE_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \ 46 | const GUID name 47 | #endif // INITGUID 48 | #endif // !GUID_DEFINED 49 | 50 | #if defined(__cplusplus) 51 | #ifndef _REFGUID_DEFINED 52 | #define _REFGUID_DEFINED 53 | #define REFGUID const GUID & 54 | #endif // !_REFGUID_DEFINED 55 | #else // !__cplusplus 56 | #ifndef _REFGUID_DEFINED 57 | #define _REFGUID_DEFINED 58 | #define REFGUID const GUID * const 59 | #endif // !_REFGUID_DEFINED 60 | #endif // !__cplusplus 61 | 62 | // 63 | ////////////////////////////////////////////////////////////////////////////// 64 | 65 | #ifdef __cplusplus 66 | extern "C" { 67 | #endif // __cplusplus 68 | 69 | /////////////////////////////////////////////////// Instruction Target Macros. 70 | // 71 | #define DETOUR_INSTRUCTION_TARGET_NONE ((PVOID)0) 72 | #define DETOUR_INSTRUCTION_TARGET_DYNAMIC ((PVOID)(LONG_PTR)-1) 73 | #define DETOUR_SECTION_HEADER_SIGNATURE 0x00727444 // "Dtr\0" 74 | 75 | extern const GUID DETOUR_EXE_RESTORE_GUID; 76 | extern const GUID DETOUR_EXE_HELPER_GUID; 77 | 78 | #define DETOUR_TRAMPOLINE_SIGNATURE 0x21727444 // Dtr! 79 | typedef struct _DETOUR_TRAMPOLINE DETOUR_TRAMPOLINE, *PDETOUR_TRAMPOLINE; 80 | 81 | /////////////////////////////////////////////////////////// Binary Structures. 82 | // 83 | #pragma pack(push, 8) 84 | typedef struct _DETOUR_SECTION_HEADER 85 | { 86 | DWORD cbHeaderSize; 87 | DWORD nSignature; 88 | DWORD nDataOffset; 89 | DWORD cbDataSize; 90 | 91 | DWORD nOriginalImportVirtualAddress; 92 | DWORD nOriginalImportSize; 93 | DWORD nOriginalBoundImportVirtualAddress; 94 | DWORD nOriginalBoundImportSize; 95 | 96 | DWORD nOriginalIatVirtualAddress; 97 | DWORD nOriginalIatSize; 98 | DWORD nOriginalSizeOfImage; 99 | DWORD cbPrePE; 100 | 101 | DWORD nOriginalClrFlags; 102 | DWORD reserved1; 103 | DWORD reserved2; 104 | DWORD reserved3; 105 | 106 | // Followed by cbPrePE bytes of data. 107 | } DETOUR_SECTION_HEADER, *PDETOUR_SECTION_HEADER; 108 | 109 | typedef struct _DETOUR_SECTION_RECORD 110 | { 111 | DWORD cbBytes; 112 | DWORD nReserved; 113 | GUID guid; 114 | } DETOUR_SECTION_RECORD, *PDETOUR_SECTION_RECORD; 115 | 116 | typedef struct _DETOUR_CLR_HEADER 117 | { 118 | // Header versioning 119 | ULONG cb; 120 | USHORT MajorRuntimeVersion; 121 | USHORT MinorRuntimeVersion; 122 | 123 | // Symbol table and startup information 124 | IMAGE_DATA_DIRECTORY MetaData; 125 | ULONG Flags; 126 | 127 | // Followed by the rest of the IMAGE_COR20_HEADER 128 | } DETOUR_CLR_HEADER, *PDETOUR_CLR_HEADER; 129 | 130 | typedef struct _DETOUR_EXE_RESTORE 131 | { 132 | DWORD cb; 133 | DWORD cbidh; 134 | DWORD cbinh; 135 | DWORD cbclr; 136 | 137 | PBYTE pidh; 138 | PBYTE pinh; 139 | PBYTE pclr; 140 | 141 | IMAGE_DOS_HEADER idh; 142 | union { 143 | IMAGE_NT_HEADERS inh; 144 | IMAGE_NT_HEADERS32 inh32; 145 | IMAGE_NT_HEADERS64 inh64; 146 | BYTE raw[sizeof(IMAGE_NT_HEADERS64) + 147 | sizeof(IMAGE_SECTION_HEADER) * 32]; 148 | }; 149 | DETOUR_CLR_HEADER clr; 150 | 151 | } DETOUR_EXE_RESTORE, *PDETOUR_EXE_RESTORE; 152 | 153 | typedef struct _DETOUR_EXE_HELPER 154 | { 155 | DWORD cb; 156 | DWORD pid; 157 | CHAR DllName[MAX_PATH]; 158 | 159 | } DETOUR_EXE_HELPER, *PDETOUR_EXE_HELPER; 160 | 161 | #pragma pack(pop) 162 | 163 | #define DETOUR_SECTION_HEADER_DECLARE(cbSectionSize) \ 164 | { \ 165 | sizeof(DETOUR_SECTION_HEADER),\ 166 | DETOUR_SECTION_HEADER_SIGNATURE,\ 167 | sizeof(DETOUR_SECTION_HEADER),\ 168 | (cbSectionSize),\ 169 | \ 170 | 0,\ 171 | 0,\ 172 | 0,\ 173 | 0,\ 174 | \ 175 | 0,\ 176 | 0,\ 177 | 0,\ 178 | 0,\ 179 | } 180 | 181 | /////////////////////////////////////////////////////////////// Helper Macros. 182 | // 183 | #define DETOURS_STRINGIFY(x) DETOURS_STRINGIFY_(x) 184 | #define DETOURS_STRINGIFY_(x) #x 185 | 186 | ///////////////////////////////////////////////////////////// Binary Typedefs. 187 | // 188 | typedef BOOL (CALLBACK *PF_DETOUR_BINARY_BYWAY_CALLBACK)(PVOID pContext, 189 | PCHAR pszFile, 190 | PCHAR *ppszOutFile); 191 | 192 | typedef BOOL (CALLBACK *PF_DETOUR_BINARY_FILE_CALLBACK)(PVOID pContext, 193 | PCHAR pszOrigFile, 194 | PCHAR pszFile, 195 | PCHAR *ppszOutFile); 196 | 197 | typedef BOOL (CALLBACK *PF_DETOUR_BINARY_SYMBOL_CALLBACK)(PVOID pContext, 198 | ULONG nOrigOrdinal, 199 | ULONG nOrdinal, 200 | ULONG *pnOutOrdinal, 201 | PCHAR pszOrigSymbol, 202 | PCHAR pszSymbol, 203 | PCHAR *ppszOutSymbol); 204 | 205 | typedef BOOL (CALLBACK *PF_DETOUR_BINARY_COMMIT_CALLBACK)(PVOID pContext); 206 | 207 | typedef BOOL (CALLBACK *PF_DETOUR_ENUMERATE_EXPORT_CALLBACK)(PVOID pContext, 208 | ULONG nOrdinal, 209 | PCHAR pszName, 210 | PVOID pCode); 211 | 212 | typedef BOOL (CALLBACK *PF_DETOUR_IMPORT_FILE_CALLBACK)(PVOID pContext, 213 | HMODULE hModule, 214 | PCSTR pszFile); 215 | 216 | typedef BOOL (CALLBACK *PF_DETOUR_IMPORT_FUNC_CALLBACK)(PVOID pContext, 217 | DWORD nOrdinal, 218 | PCSTR pszFunc, 219 | PVOID pvFunc); 220 | 221 | typedef VOID * PDETOUR_BINARY; 222 | typedef VOID * PDETOUR_LOADED_BINARY; 223 | 224 | //////////////////////////////////////////////////////////// Transaction APIs. 225 | // 226 | LONG WINAPI DetourTransactionBegin(VOID); 227 | LONG WINAPI DetourTransactionAbort(VOID); 228 | LONG WINAPI DetourTransactionCommit(VOID); 229 | LONG WINAPI DetourTransactionCommitEx(PVOID **pppFailedPointer); 230 | 231 | LONG WINAPI DetourUpdateThread(HANDLE hThread); 232 | 233 | LONG WINAPI DetourAttach(PVOID *ppPointer, 234 | PVOID pDetour); 235 | 236 | LONG WINAPI DetourAttachEx(PVOID *ppPointer, 237 | PVOID pDetour, 238 | PDETOUR_TRAMPOLINE *ppRealTrampoline, 239 | PVOID *ppRealTarget, 240 | PVOID *ppRealDetour); 241 | 242 | LONG WINAPI DetourDetach(PVOID *ppPointer, 243 | PVOID pDetour); 244 | 245 | BOOL WINAPI DetourSetIgnoreTooSmall(BOOL fIgnore); 246 | BOOL WINAPI DetourSetRetainRegions(BOOL fRetain); 247 | 248 | ////////////////////////////////////////////////////////////// Code Functions. 249 | // 250 | PVOID WINAPI DetourFindFunction(PCSTR pszModule, PCSTR pszFunction); 251 | PVOID WINAPI DetourCodeFromPointer(PVOID pPointer, PVOID *ppGlobals); 252 | PVOID WINAPI DetourCopyInstruction(PVOID pDst, 253 | PVOID *pDstPool, 254 | PVOID pSrc, 255 | PVOID *ppTarget, 256 | LONG *plExtra); 257 | 258 | ///////////////////////////////////////////////////// Loaded Binary Functions. 259 | // 260 | HMODULE WINAPI DetourGetContainingModule(PVOID pvAddr); 261 | HMODULE WINAPI DetourEnumerateModules(HMODULE hModuleLast); 262 | PVOID WINAPI DetourGetEntryPoint(HMODULE hModule); 263 | ULONG WINAPI DetourGetModuleSize(HMODULE hModule); 264 | BOOL WINAPI DetourEnumerateExports(HMODULE hModule, 265 | PVOID pContext, 266 | PF_DETOUR_ENUMERATE_EXPORT_CALLBACK pfExport); 267 | BOOL WINAPI DetourEnumerateImports(HMODULE hModule, 268 | PVOID pContext, 269 | PF_DETOUR_IMPORT_FILE_CALLBACK pfImportFile, 270 | PF_DETOUR_IMPORT_FUNC_CALLBACK pfImportFunc); 271 | 272 | PVOID WINAPI DetourFindPayload(HMODULE hModule, REFGUID rguid, DWORD *pcbData); 273 | PVOID WINAPI DetourFindPayloadEx(REFGUID rguid, DWORD * pcbData); 274 | DWORD WINAPI DetourGetSizeOfPayloads(HMODULE hModule); 275 | 276 | ///////////////////////////////////////////////// Persistent Binary Functions. 277 | // 278 | 279 | PDETOUR_BINARY WINAPI DetourBinaryOpen(HANDLE hFile); 280 | PVOID WINAPI DetourBinaryEnumeratePayloads(PDETOUR_BINARY pBinary, 281 | GUID *pGuid, 282 | DWORD *pcbData, 283 | DWORD *pnIterator); 284 | PVOID WINAPI DetourBinaryFindPayload(PDETOUR_BINARY pBinary, 285 | REFGUID rguid, 286 | DWORD *pcbData); 287 | PVOID WINAPI DetourBinarySetPayload(PDETOUR_BINARY pBinary, 288 | REFGUID rguid, 289 | PVOID pData, 290 | DWORD cbData); 291 | BOOL WINAPI DetourBinaryDeletePayload(PDETOUR_BINARY pBinary, REFGUID rguid); 292 | BOOL WINAPI DetourBinaryPurgePayloads(PDETOUR_BINARY pBinary); 293 | BOOL WINAPI DetourBinaryResetImports(PDETOUR_BINARY pBinary); 294 | BOOL WINAPI DetourBinaryEditImports(PDETOUR_BINARY pBinary, 295 | PVOID pContext, 296 | PF_DETOUR_BINARY_BYWAY_CALLBACK pfByway, 297 | PF_DETOUR_BINARY_FILE_CALLBACK pfFile, 298 | PF_DETOUR_BINARY_SYMBOL_CALLBACK pfSymbol, 299 | PF_DETOUR_BINARY_COMMIT_CALLBACK pfCommit); 300 | BOOL WINAPI DetourBinaryWrite(PDETOUR_BINARY pBinary, HANDLE hFile); 301 | BOOL WINAPI DetourBinaryClose(PDETOUR_BINARY pBinary); 302 | 303 | /////////////////////////////////////////////////// Create Process & Load Dll. 304 | // 305 | typedef BOOL (WINAPI *PDETOUR_CREATE_PROCESS_ROUTINEA) 306 | (LPCSTR lpApplicationName, 307 | LPSTR lpCommandLine, 308 | LPSECURITY_ATTRIBUTES lpProcessAttributes, 309 | LPSECURITY_ATTRIBUTES lpThreadAttributes, 310 | BOOL bInheritHandles, 311 | DWORD dwCreationFlags, 312 | LPVOID lpEnvironment, 313 | LPCSTR lpCurrentDirectory, 314 | LPSTARTUPINFOA lpStartupInfo, 315 | LPPROCESS_INFORMATION lpProcessInformation); 316 | 317 | typedef BOOL (WINAPI *PDETOUR_CREATE_PROCESS_ROUTINEW) 318 | (LPCWSTR lpApplicationName, 319 | LPWSTR lpCommandLine, 320 | LPSECURITY_ATTRIBUTES lpProcessAttributes, 321 | LPSECURITY_ATTRIBUTES lpThreadAttributes, 322 | BOOL bInheritHandles, 323 | DWORD dwCreationFlags, 324 | LPVOID lpEnvironment, 325 | LPCWSTR lpCurrentDirectory, 326 | LPSTARTUPINFOW lpStartupInfo, 327 | LPPROCESS_INFORMATION lpProcessInformation); 328 | 329 | BOOL WINAPI DetourCreateProcessWithDllA(LPCSTR lpApplicationName, 330 | __in_z LPSTR lpCommandLine, 331 | LPSECURITY_ATTRIBUTES lpProcessAttributes, 332 | LPSECURITY_ATTRIBUTES lpThreadAttributes, 333 | BOOL bInheritHandles, 334 | DWORD dwCreationFlags, 335 | LPVOID lpEnvironment, 336 | LPCSTR lpCurrentDirectory, 337 | LPSTARTUPINFOA lpStartupInfo, 338 | LPPROCESS_INFORMATION lpProcessInformation, 339 | LPCSTR lpDllName, 340 | PDETOUR_CREATE_PROCESS_ROUTINEA 341 | pfCreateProcessA); 342 | 343 | BOOL WINAPI DetourCreateProcessWithDllW(LPCWSTR lpApplicationName, 344 | __in_z LPWSTR lpCommandLine, 345 | LPSECURITY_ATTRIBUTES lpProcessAttributes, 346 | LPSECURITY_ATTRIBUTES lpThreadAttributes, 347 | BOOL bInheritHandles, 348 | DWORD dwCreationFlags, 349 | LPVOID lpEnvironment, 350 | LPCWSTR lpCurrentDirectory, 351 | LPSTARTUPINFOW lpStartupInfo, 352 | LPPROCESS_INFORMATION lpProcessInformation, 353 | LPCSTR lpDllName, 354 | PDETOUR_CREATE_PROCESS_ROUTINEW 355 | pfCreateProcessW); 356 | 357 | #ifdef UNICODE 358 | #define DetourCreateProcessWithDll DetourCreateProcessWithDllW 359 | #define PDETOUR_CREATE_PROCESS_ROUTINE PDETOUR_CREATE_PROCESS_ROUTINEW 360 | #else 361 | #define DetourCreateProcessWithDll DetourCreateProcessWithDllA 362 | #define PDETOUR_CREATE_PROCESS_ROUTINE PDETOUR_CREATE_PROCESS_ROUTINEA 363 | #endif // !UNICODE 364 | 365 | BOOL WINAPI DetourCreateProcessWithDllExA(LPCSTR lpApplicationName, 366 | __in_z LPSTR lpCommandLine, 367 | LPSECURITY_ATTRIBUTES lpProcessAttributes, 368 | LPSECURITY_ATTRIBUTES lpThreadAttributes, 369 | BOOL bInheritHandles, 370 | DWORD dwCreationFlags, 371 | LPVOID lpEnvironment, 372 | LPCSTR lpCurrentDirectory, 373 | LPSTARTUPINFOA lpStartupInfo, 374 | LPPROCESS_INFORMATION lpProcessInformation, 375 | LPCSTR lpDllName, 376 | PDETOUR_CREATE_PROCESS_ROUTINEA 377 | pfCreateProcessA); 378 | 379 | BOOL WINAPI DetourCreateProcessWithDllExW(LPCWSTR lpApplicationName, 380 | __in_z LPWSTR lpCommandLine, 381 | LPSECURITY_ATTRIBUTES lpProcessAttributes, 382 | LPSECURITY_ATTRIBUTES lpThreadAttributes, 383 | BOOL bInheritHandles, 384 | DWORD dwCreationFlags, 385 | LPVOID lpEnvironment, 386 | LPCWSTR lpCurrentDirectory, 387 | LPSTARTUPINFOW lpStartupInfo, 388 | LPPROCESS_INFORMATION lpProcessInformation, 389 | LPCSTR lpDllName, 390 | PDETOUR_CREATE_PROCESS_ROUTINEW 391 | pfCreateProcessW); 392 | 393 | #ifdef UNICODE 394 | #define DetourCreateProcessWithDllEx DetourCreateProcessWithDllExW 395 | #define PDETOUR_CREATE_PROCESS_ROUTINE PDETOUR_CREATE_PROCESS_ROUTINEW 396 | #else 397 | #define DetourCreateProcessWithDllEx DetourCreateProcessWithDllExA 398 | #define PDETOUR_CREATE_PROCESS_ROUTINE PDETOUR_CREATE_PROCESS_ROUTINEA 399 | #endif // !UNICODE 400 | 401 | BOOL WINAPI DetourProcessViaHelperA(DWORD dwTargetPid, 402 | LPCSTR lpDllName, 403 | PDETOUR_CREATE_PROCESS_ROUTINEA pfCreateProcessA); 404 | 405 | BOOL WINAPI DetourProcessViaHelperW(DWORD dwTargetPid, 406 | LPCSTR lpDllName, 407 | PDETOUR_CREATE_PROCESS_ROUTINEW pfCreateProcessW); 408 | 409 | #ifdef UNICODE 410 | #define DetourProcessViaHelper DetourProcessViaHelperW 411 | #else 412 | #define DetourProcessViaHelper DetourProcessViaHelperA 413 | #endif // !UNICODE 414 | 415 | BOOL WINAPI DetourUpdateProcessWithDll(HANDLE hProcess, 416 | LPCSTR *plpDlls, 417 | DWORD nDlls); 418 | 419 | BOOL WINAPI DetourCopyPayloadToProcess(HANDLE hProcess, 420 | REFGUID rguid, 421 | PVOID pvData, 422 | DWORD cbData); 423 | BOOL WINAPI DetourRestoreAfterWith(VOID); 424 | BOOL WINAPI DetourRestoreAfterWithEx(PVOID pvData, DWORD cbData); 425 | BOOL WINAPI DetourIsHelperProcess(VOID); 426 | VOID CALLBACK DetourFinishHelperProcess(HWND, HINSTANCE, LPSTR, INT); 427 | 428 | // 429 | ////////////////////////////////////////////////////////////////////////////// 430 | #ifdef __cplusplus 431 | } 432 | #endif // __cplusplus 433 | 434 | //////////////////////////////////////////////// Detours Internal Definitions. 435 | // 436 | #ifdef __cplusplus 437 | #ifdef DETOURS_INTERNAL 438 | 439 | #ifndef __deref_out 440 | #define __deref_out 441 | #endif 442 | 443 | #ifndef __deref 444 | #define __deref 445 | #endif 446 | 447 | ////////////////////////////////////////////////////////////////////////////// 448 | // 449 | #if (_MSC_VER < 1299) 450 | #include 451 | typedef IMAGEHLP_MODULE IMAGEHLP_MODULE64; 452 | typedef PIMAGEHLP_MODULE PIMAGEHLP_MODULE64; 453 | typedef IMAGEHLP_SYMBOL SYMBOL_INFO; 454 | typedef PIMAGEHLP_SYMBOL PSYMBOL_INFO; 455 | 456 | static inline 457 | LONG InterlockedCompareExchange(LONG *ptr, LONG nval, LONG oval) 458 | { 459 | return (LONG)::InterlockedCompareExchange((PVOID*)ptr, (PVOID)nval, (PVOID)oval); 460 | } 461 | #else 462 | #include 463 | #endif 464 | 465 | #ifdef IMAGEAPI // defined by DBGHELP.H 466 | typedef LPAPI_VERSION (NTAPI *PF_ImagehlpApiVersionEx)(LPAPI_VERSION AppVersion); 467 | 468 | typedef BOOL (NTAPI *PF_SymInitialize)(IN HANDLE hProcess, 469 | IN LPCSTR UserSearchPath, 470 | IN BOOL fInvadeProcess); 471 | typedef DWORD (NTAPI *PF_SymSetOptions)(IN DWORD SymOptions); 472 | typedef DWORD (NTAPI *PF_SymGetOptions)(VOID); 473 | typedef DWORD64 (NTAPI *PF_SymLoadModule64)(IN HANDLE hProcess, 474 | IN HANDLE hFile, 475 | IN PSTR ImageName, 476 | IN PSTR ModuleName, 477 | IN DWORD64 BaseOfDll, 478 | IN DWORD SizeOfDll); 479 | typedef BOOL (NTAPI *PF_SymGetModuleInfo64)(IN HANDLE hProcess, 480 | IN DWORD64 qwAddr, 481 | OUT PIMAGEHLP_MODULE64 ModuleInfo); 482 | typedef BOOL (NTAPI *PF_SymFromName)(IN HANDLE hProcess, 483 | IN LPSTR Name, 484 | OUT PSYMBOL_INFO Symbol); 485 | 486 | typedef struct _DETOUR_SYM_INFO 487 | { 488 | HANDLE hProcess; 489 | HMODULE hDbgHelp; 490 | PF_ImagehlpApiVersionEx pfImagehlpApiVersionEx; 491 | PF_SymInitialize pfSymInitialize; 492 | PF_SymSetOptions pfSymSetOptions; 493 | PF_SymGetOptions pfSymGetOptions; 494 | PF_SymLoadModule64 pfSymLoadModule64; 495 | PF_SymGetModuleInfo64 pfSymGetModuleInfo64; 496 | PF_SymFromName pfSymFromName; 497 | } DETOUR_SYM_INFO, *PDETOUR_SYM_INFO; 498 | 499 | PDETOUR_SYM_INFO DetourLoadDbgHelp(VOID); 500 | 501 | #endif // IMAGEAPI 502 | 503 | #ifndef DETOUR_TRACE 504 | #if DETOUR_DEBUG 505 | #define DETOUR_TRACE(x) printf x 506 | #define DETOUR_BREAK() __debugbreak() 507 | #include 508 | #include 509 | #else 510 | #define DETOUR_TRACE(x) 511 | #define DETOUR_BREAK() 512 | #endif 513 | #endif 514 | 515 | #ifdef DETOURS_IA64 516 | #error Feature not supported in this release. 517 | 518 | 519 | 520 | 521 | 522 | 523 | 524 | 525 | 526 | 527 | 528 | 529 | 530 | 531 | 532 | 533 | 534 | 535 | 536 | 537 | 538 | 539 | 540 | 541 | 542 | 543 | 544 | 545 | 546 | 547 | 548 | 549 | 550 | 551 | 552 | 553 | 554 | 555 | 556 | 557 | 558 | 559 | 560 | 561 | 562 | 563 | 564 | 565 | 566 | 567 | 568 | 569 | 570 | 571 | 572 | 573 | 574 | 575 | 576 | 577 | 578 | 579 | 580 | 581 | 582 | 583 | 584 | 585 | 586 | 587 | 588 | 589 | 590 | 591 | 592 | 593 | 594 | 595 | 596 | 597 | 598 | 599 | 600 | 601 | 602 | 603 | 604 | 605 | 606 | 607 | 608 | 609 | 610 | #endif // DETOURS_IA64 611 | 612 | #ifdef DETOURS_ARM 613 | #error Feature not supported in this release. 614 | 615 | 616 | 617 | #endif // DETOURS_ARM 618 | 619 | ////////////////////////////////////////////////////////////////////////////// 620 | 621 | #endif // DETOURS_INTERNAL 622 | #endif // __cplusplus 623 | 624 | #endif // _DETOURS_H_ 625 | // 626 | //////////////////////////////////////////////////////////////// End of File. 627 | -------------------------------------------------------------------------------- /src/SuperF12.dll/Detours/detours.cpp: -------------------------------------------------------------------------------- 1 | ////////////////////////////////////////////////////////////////////////////// 2 | // 3 | // Core Detours Functionality (detours.cpp of detours.lib) 4 | // 5 | // Microsoft Research Detours Package, Version 3.0 Build_316. 6 | // 7 | // Copyright (c) Microsoft Corporation. All rights reserved. 8 | // 9 | #include 10 | 11 | #if (_MSC_VER < 1299) 12 | #pragma warning(disable: 4710) 13 | #endif 14 | 15 | //#define DETOUR_DEBUG 1 16 | #define DETOURS_INTERNAL 17 | 18 | #include "detours.h" 19 | 20 | #if defined(DETOURS_X86) 21 | #elif defined(DETOURS_X64) 22 | #elif defined(DETOURS_IA64) 23 | #elif defined(DETOURS_ARM) 24 | #else 25 | #error Must define one of DETOURS_X86, DETOURS_X64, DETOURS_IA64, or DETOURS_ARM 26 | #endif 27 | 28 | #if !defined(DETOURS_32BIT) && !defined(DETOURS_64BIT) 29 | #error Must define one of DETOURS_32BIT or DETOURS_64BIT 30 | #endif 31 | 32 | ////////////////////////////////////////////////////////////////////////////// 33 | // 34 | struct _DETOUR_ALIGN 35 | { 36 | BYTE obTarget : 3; 37 | BYTE obTrampoline : 5; 38 | }; 39 | 40 | C_ASSERT(sizeof(_DETOUR_ALIGN) == 1); 41 | 42 | ////////////////////////////////////////////////////////////////////////////// 43 | // 44 | static bool detour_is_imported(PBYTE pbCode, PBYTE pbAddress) 45 | { 46 | MEMORY_BASIC_INFORMATION mbi; 47 | VirtualQuery((PVOID)pbCode, &mbi, sizeof(mbi)); 48 | __try { 49 | PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)mbi.AllocationBase; 50 | if (pDosHeader->e_magic != IMAGE_DOS_SIGNATURE) { 51 | return false; 52 | } 53 | 54 | PIMAGE_NT_HEADERS pNtHeader = (PIMAGE_NT_HEADERS)((PBYTE)pDosHeader + 55 | pDosHeader->e_lfanew); 56 | if (pNtHeader->Signature != IMAGE_NT_SIGNATURE) { 57 | return false; 58 | } 59 | 60 | if (pbAddress >= ((PBYTE)pDosHeader + 61 | pNtHeader->OptionalHeader 62 | .DataDirectory[IMAGE_DIRECTORY_ENTRY_IAT].VirtualAddress) && 63 | pbAddress < ((PBYTE)pDosHeader + 64 | pNtHeader->OptionalHeader 65 | .DataDirectory[IMAGE_DIRECTORY_ENTRY_IAT].VirtualAddress + 66 | pNtHeader->OptionalHeader 67 | .DataDirectory[IMAGE_DIRECTORY_ENTRY_IAT].Size)) { 68 | return true; 69 | } 70 | return false; 71 | } 72 | __except(EXCEPTION_EXECUTE_HANDLER) { 73 | return false; 74 | } 75 | } 76 | 77 | ///////////////////////////////////////////////////////////////////////// X86. 78 | // 79 | #ifdef DETOURS_X86 80 | 81 | struct _DETOUR_TRAMPOLINE 82 | { 83 | BYTE rbCode[30]; // target code + jmp to pbRemain 84 | BYTE cbCode; // size of moved target code. 85 | BYTE cbCodeBreak; // padding to make debugging easier. 86 | BYTE rbRestore[22]; // original target code. 87 | BYTE cbRestore; // size of original target code. 88 | BYTE cbRestoreBreak; // padding to make debugging easier. 89 | _DETOUR_ALIGN rAlign[8]; // instruction alignment array. 90 | PBYTE pbRemain; // first instruction after moved code. [free list] 91 | PBYTE pbDetour; // first instruction of detour function. 92 | }; 93 | 94 | C_ASSERT(sizeof(_DETOUR_TRAMPOLINE) == 72); 95 | 96 | enum { 97 | SIZE_OF_JMP = 5 98 | }; 99 | 100 | inline PBYTE detour_gen_jmp_immediate(PBYTE pbCode, PBYTE pbJmpVal) 101 | { 102 | PBYTE pbJmpSrc = pbCode + 5; 103 | *pbCode++ = 0xE9; // jmp +imm32 104 | *((INT32*&)pbCode)++ = (INT32)(pbJmpVal - pbJmpSrc); 105 | return pbCode; 106 | } 107 | 108 | inline PBYTE detour_gen_jmp_indirect(PBYTE pbCode, PBYTE *ppbJmpVal) 109 | { 110 | PBYTE pbJmpSrc = pbCode + 6; 111 | *pbCode++ = 0xff; // jmp [+imm32] 112 | *pbCode++ = 0x25; 113 | *((INT32*&)pbCode)++ = (INT32)((PBYTE)ppbJmpVal - pbJmpSrc); 114 | return pbCode; 115 | } 116 | 117 | inline PBYTE detour_gen_brk(PBYTE pbCode, PBYTE pbLimit) 118 | { 119 | while (pbCode < pbLimit) { 120 | *pbCode++ = 0xcc; // brk; 121 | } 122 | return pbCode; 123 | } 124 | 125 | inline PBYTE detour_skip_jmp(PBYTE pbCode, PVOID *ppGlobals) 126 | { 127 | if (pbCode == NULL) { 128 | return NULL; 129 | } 130 | if (ppGlobals != NULL) { 131 | *ppGlobals = NULL; 132 | } 133 | 134 | // First, skip over the import vector if there is one. 135 | if (pbCode[0] == 0xff && pbCode[1] == 0x25) { // jmp [imm32] 136 | // Looks like an import alias jump, then get the code it points to. 137 | PBYTE pbTarget = *(PBYTE *)&pbCode[2]; 138 | if (detour_is_imported(pbCode, pbTarget)) { 139 | PBYTE pbNew = *(PBYTE *)pbTarget; 140 | DETOUR_TRACE(("%p->%p: skipped over import table.\n", pbCode, pbNew)); 141 | pbCode = pbNew; 142 | } 143 | } 144 | 145 | // Then, skip over a patch jump 146 | if (pbCode[0] == 0xeb) { // jmp +imm8 147 | PBYTE pbNew = pbCode + 2 + *(CHAR *)&pbCode[1]; 148 | DETOUR_TRACE(("%p->%p: skipped over short jump.\n", pbCode, pbNew)); 149 | pbCode = pbNew; 150 | 151 | // First, skip over the import vector if there is one. 152 | if (pbCode[0] == 0xff && pbCode[1] == 0x25) { // jmp [imm32] 153 | // Looks like an import alias jump, then get the code it points to. 154 | PBYTE pbTarget = *(PBYTE *)&pbCode[2]; 155 | if (detour_is_imported(pbCode, pbTarget)) { 156 | PBYTE pbNew = *(PBYTE *)pbTarget; 157 | DETOUR_TRACE(("%p->%p: skipped over import table.\n", pbCode, pbNew)); 158 | pbCode = pbNew; 159 | } 160 | } 161 | // Finally, skip over a long jump if it is the target of the patch jump. 162 | else if (pbCode[0] == 0xe9) { // jmp +imm32 163 | PBYTE pbNew = pbCode + 5 + *(INT32 *)&pbCode[1]; 164 | DETOUR_TRACE(("%p->%p: skipped over long jump.\n", pbCode, pbNew)); 165 | pbCode = pbNew; 166 | } 167 | } 168 | return pbCode; 169 | } 170 | 171 | inline BOOL detour_does_code_end_function(PBYTE pbCode) 172 | { 173 | if (pbCode[0] == 0xeb || // jmp +imm8 174 | pbCode[0] == 0xe9 || // jmp +imm32 175 | pbCode[0] == 0xe0 || // jmp eax 176 | pbCode[0] == 0xc2 || // ret +imm8 177 | pbCode[0] == 0xc3 || // ret 178 | pbCode[0] == 0xcc) { // brk 179 | return TRUE; 180 | } 181 | else if (pbCode[0] == 0xff && pbCode[1] == 0x25) { // jmp [+imm32] 182 | return TRUE; 183 | } 184 | else if ((pbCode[0] == 0x26 || // jmp es: 185 | pbCode[0] == 0x2e || // jmp cs: 186 | pbCode[0] == 0x36 || // jmp ss: 187 | pbCode[0] == 0xe3 || // jmp ds: 188 | pbCode[0] == 0x64 || // jmp fs: 189 | pbCode[0] == 0x65) && // jmp gs: 190 | pbCode[1] == 0xff && // jmp [+imm32] 191 | pbCode[2] == 0x25) { 192 | return TRUE; 193 | } 194 | return FALSE; 195 | } 196 | 197 | inline ULONG detour_is_code_filler(PBYTE pbCode) 198 | { 199 | if (pbCode[0] == 0x90) { // nop 200 | return 1; 201 | } 202 | return 0; 203 | } 204 | 205 | #endif // DETOURS_X86 206 | 207 | ///////////////////////////////////////////////////////////////////////// X64. 208 | // 209 | #ifdef DETOURS_X64 210 | #error Feature not supported in this release. 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | 256 | 257 | 258 | 259 | 260 | 261 | 262 | 263 | 264 | 265 | 266 | 267 | 268 | 269 | 270 | 271 | 272 | 273 | 274 | 275 | 276 | 277 | 278 | 279 | 280 | 281 | 282 | 283 | 284 | 285 | 286 | 287 | 288 | 289 | 290 | 291 | 292 | 293 | 294 | 295 | 296 | 297 | 298 | 299 | 300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308 | 309 | 310 | 311 | 312 | 313 | 314 | 315 | 316 | 317 | 318 | 319 | 320 | 321 | 322 | 323 | 324 | 325 | 326 | 327 | 328 | 329 | 330 | 331 | 332 | 333 | 334 | 335 | 336 | 337 | 338 | #endif // DETOURS_X64 339 | 340 | //////////////////////////////////////////////////////////////////////// IA64. 341 | // 342 | #ifdef DETOURS_IA64 343 | #error Feature not supported in this release. 344 | 345 | 346 | 347 | 348 | 349 | 350 | 351 | 352 | 353 | 354 | 355 | 356 | 357 | 358 | 359 | 360 | 361 | 362 | 363 | 364 | 365 | 366 | 367 | 368 | 369 | 370 | 371 | 372 | 373 | 374 | 375 | 376 | 377 | 378 | 379 | 380 | 381 | 382 | 383 | 384 | 385 | 386 | 387 | 388 | 389 | 390 | 391 | 392 | 393 | 394 | 395 | 396 | 397 | 398 | 399 | 400 | 401 | 402 | 403 | 404 | 405 | 406 | 407 | 408 | 409 | 410 | 411 | 412 | 413 | 414 | 415 | 416 | 417 | 418 | 419 | 420 | 421 | 422 | 423 | 424 | 425 | 426 | 427 | 428 | 429 | 430 | 431 | 432 | 433 | 434 | 435 | 436 | 437 | 438 | 439 | 440 | 441 | 442 | 443 | 444 | 445 | 446 | 447 | 448 | 449 | 450 | 451 | 452 | 453 | 454 | 455 | 456 | 457 | 458 | 459 | 460 | 461 | 462 | 463 | 464 | 465 | 466 | 467 | 468 | 469 | 470 | 471 | 472 | 473 | 474 | 475 | 476 | 477 | 478 | 479 | 480 | 481 | 482 | 483 | 484 | 485 | 486 | 487 | 488 | 489 | 490 | 491 | 492 | 493 | 494 | 495 | 496 | 497 | 498 | 499 | #endif // DETOURS_IA64 500 | 501 | #ifdef DETOURS_ARM 502 | #error Feature not supported in this release. 503 | 504 | 505 | 506 | 507 | 508 | 509 | 510 | 511 | 512 | 513 | 514 | 515 | 516 | 517 | 518 | 519 | 520 | 521 | 522 | 523 | 524 | 525 | 526 | 527 | 528 | 529 | 530 | 531 | 532 | 533 | 534 | 535 | 536 | 537 | 538 | 539 | 540 | 541 | 542 | 543 | 544 | 545 | 546 | 547 | 548 | 549 | 550 | 551 | 552 | 553 | 554 | 555 | 556 | 557 | 558 | 559 | 560 | 561 | 562 | 563 | 564 | 565 | 566 | 567 | 568 | 569 | 570 | 571 | 572 | 573 | 574 | 575 | 576 | 577 | 578 | 579 | 580 | 581 | 582 | 583 | 584 | 585 | 586 | 587 | 588 | 589 | 590 | 591 | 592 | 593 | 594 | 595 | 596 | 597 | 598 | 599 | 600 | 601 | 602 | 603 | 604 | 605 | 606 | 607 | 608 | 609 | 610 | 611 | 612 | 613 | 614 | 615 | 616 | 617 | 618 | 619 | 620 | 621 | 622 | 623 | 624 | 625 | 626 | 627 | 628 | 629 | 630 | 631 | 632 | 633 | 634 | 635 | 636 | 637 | 638 | 639 | 640 | 641 | 642 | 643 | 644 | 645 | #endif // DETOURS_ARM 646 | 647 | //////////////////////////////////////////////// Trampoline Memory Management. 648 | // 649 | struct DETOUR_REGION 650 | { 651 | ULONG dwSignature; 652 | DETOUR_REGION * pNext; // Next region in list of regions. 653 | DETOUR_TRAMPOLINE * pFree; // List of free trampolines in this region. 654 | }; 655 | typedef DETOUR_REGION * PDETOUR_REGION; 656 | 657 | const ULONG DETOUR_REGION_SIGNATURE = 'Rrtd'; 658 | const ULONG DETOUR_REGION_SIZE = 0x10000; 659 | const ULONG DETOUR_TRAMPOLINES_PER_REGION = (DETOUR_REGION_SIZE 660 | / sizeof(DETOUR_TRAMPOLINE)) - 1; 661 | static PDETOUR_REGION s_pRegions = NULL; // List of all regions. 662 | static PDETOUR_REGION s_pRegion = NULL; // Default region. 663 | 664 | static void detour_writable_trampoline_regions() 665 | { 666 | // Mark all of the regions as writable. 667 | for (PDETOUR_REGION pRegion = s_pRegions; pRegion != NULL; pRegion = pRegion->pNext) { 668 | DWORD dwOld; 669 | VirtualProtect(pRegion, DETOUR_REGION_SIZE, PAGE_EXECUTE_READWRITE, &dwOld); 670 | } 671 | } 672 | 673 | static void detour_runnable_trampoline_regions() 674 | { 675 | HANDLE hProcess = GetCurrentProcess(); 676 | 677 | // Mark all of the regions as executable. 678 | for (PDETOUR_REGION pRegion = s_pRegions; pRegion != NULL; pRegion = pRegion->pNext) { 679 | DWORD dwOld; 680 | VirtualProtect(pRegion, DETOUR_REGION_SIZE, PAGE_EXECUTE_READ, &dwOld); 681 | FlushInstructionCache(hProcess, pRegion, DETOUR_REGION_SIZE); 682 | } 683 | } 684 | 685 | static PBYTE detour_alloc_round_down_to_region(PBYTE pbTry) 686 | { 687 | // WinXP64 returns free areas that aren't REGION aligned to 32-bit applications. 688 | ULONG_PTR extra = ((ULONG_PTR)pbTry) & (DETOUR_REGION_SIZE - 1); 689 | if (extra != 0) { 690 | pbTry -= extra; 691 | } 692 | return pbTry; 693 | } 694 | 695 | static PBYTE detour_alloc_round_up_to_region(PBYTE pbTry) 696 | { 697 | // WinXP64 returns free areas that aren't REGION aligned to 32-bit applications. 698 | ULONG_PTR extra = ((ULONG_PTR)pbTry) & (DETOUR_REGION_SIZE - 1); 699 | if (extra != 0) { 700 | ULONG_PTR adjust = DETOUR_REGION_SIZE - extra; 701 | pbTry += adjust; 702 | } 703 | return pbTry; 704 | } 705 | 706 | // Starting at pbLo, try to allocate a memory region, continue until pbHi. 707 | 708 | static PVOID detour_alloc_region_from_lo(PBYTE pbLo, PBYTE pbHi) 709 | { 710 | PBYTE pbTry = detour_alloc_round_up_to_region(pbLo); 711 | 712 | DETOUR_TRACE((" Looking for free region in %p..%p from %p:\n", pbLo, pbHi, pbTry)); 713 | 714 | for (; pbTry < pbHi;) { 715 | MEMORY_BASIC_INFORMATION mbi; 716 | 717 | if (pbTry >= (PBYTE)(ULONG_PTR)0x50000000 && 718 | pbTry <= (PBYTE)(ULONG_PTR)0x80000000) { 719 | // Skip region reserved for system DLLs. 720 | pbTry = (PBYTE)(ULONG_PTR)(0x80000000 + DETOUR_REGION_SIZE); 721 | continue; 722 | } 723 | 724 | ZeroMemory(&mbi, sizeof(mbi)); 725 | if (!VirtualQuery(pbTry, &mbi, sizeof(mbi))) { 726 | break; 727 | } 728 | 729 | DETOUR_TRACE((" Try %p => %p..%p %6x\n", 730 | pbTry, 731 | mbi.BaseAddress, 732 | (PBYTE)mbi.BaseAddress + mbi.RegionSize - 1, 733 | mbi.State)); 734 | 735 | if (mbi.State == MEM_FREE && mbi.RegionSize >= DETOUR_REGION_SIZE) { 736 | 737 | PVOID pv = VirtualAlloc(pbTry, 738 | DETOUR_REGION_SIZE, 739 | MEM_COMMIT|MEM_RESERVE, 740 | PAGE_EXECUTE_READWRITE); 741 | if (pv != NULL) { 742 | return pv; 743 | } 744 | pbTry += DETOUR_REGION_SIZE; 745 | } 746 | else { 747 | pbTry = detour_alloc_round_up_to_region((PBYTE)mbi.BaseAddress + mbi.RegionSize); 748 | } 749 | } 750 | return NULL; 751 | } 752 | 753 | // Starting at pbHi, try to allocate a memory region, continue until pbLo. 754 | 755 | static PVOID detour_alloc_region_from_hi(PBYTE pbLo, PBYTE pbHi) 756 | { 757 | PBYTE pbTry = detour_alloc_round_down_to_region(pbHi - DETOUR_REGION_SIZE); 758 | 759 | DETOUR_TRACE((" Looking for free region in %p..%p from %p:\n", pbLo, pbHi, pbTry)); 760 | 761 | for (; pbTry > pbLo;) { 762 | MEMORY_BASIC_INFORMATION mbi; 763 | 764 | DETOUR_TRACE((" Try %p\n", pbTry)); 765 | if (pbTry >= (PBYTE)(ULONG_PTR)0x50000000 && 766 | pbTry <= (PBYTE)(ULONG_PTR)0x80000000) { 767 | // Skip region reserved for system DLLs. 768 | pbTry = (PBYTE)(ULONG_PTR)(0x50000000 - DETOUR_REGION_SIZE); 769 | continue; 770 | } 771 | 772 | ZeroMemory(&mbi, sizeof(mbi)); 773 | if (!VirtualQuery(pbTry, &mbi, sizeof(mbi))) { 774 | break; 775 | } 776 | 777 | DETOUR_TRACE((" Try %p => %p..%p %6x\n", 778 | pbTry, 779 | mbi.BaseAddress, 780 | (PBYTE)mbi.BaseAddress + mbi.RegionSize - 1, 781 | mbi.State)); 782 | 783 | if (mbi.State == MEM_FREE && mbi.RegionSize >= DETOUR_REGION_SIZE) { 784 | 785 | PVOID pv = VirtualAlloc(pbTry, 786 | DETOUR_REGION_SIZE, 787 | MEM_COMMIT|MEM_RESERVE, 788 | PAGE_EXECUTE_READWRITE); 789 | if (pv != NULL) { 790 | return pv; 791 | } 792 | pbTry -= DETOUR_REGION_SIZE; 793 | } 794 | else { 795 | pbTry = detour_alloc_round_down_to_region((PBYTE)mbi.AllocationBase 796 | - DETOUR_REGION_SIZE); 797 | } 798 | } 799 | return NULL; 800 | } 801 | 802 | static PDETOUR_TRAMPOLINE detour_alloc_trampoline(PBYTE pbTarget) 803 | { 804 | // We have to place trampolines within +/- 2GB of target. 805 | 806 | PDETOUR_TRAMPOLINE pLo = (PDETOUR_TRAMPOLINE) 807 | ((pbTarget > (PBYTE)0x7ff80000) 808 | ? pbTarget - 0x7ff80000 : (PBYTE)(ULONG_PTR)DETOUR_REGION_SIZE); 809 | PDETOUR_TRAMPOLINE pHi = (PDETOUR_TRAMPOLINE) 810 | ((pbTarget < (PBYTE)0xffffffff80000000) 811 | ? pbTarget + 0x7ff80000 : (PBYTE)0xfffffffffff80000); 812 | DETOUR_TRACE(("[%p..%p..%p]\n", pLo, pbTarget, pHi)); 813 | 814 | PDETOUR_TRAMPOLINE pTrampoline = NULL; 815 | 816 | // Insure that there is a default region. 817 | if (s_pRegion == NULL && s_pRegions != NULL) { 818 | s_pRegion = s_pRegions; 819 | } 820 | 821 | // First check the default region for an valid free block. 822 | if (s_pRegion != NULL && s_pRegion->pFree != NULL && 823 | s_pRegion->pFree >= pLo && s_pRegion->pFree <= pHi) { 824 | 825 | found_region: 826 | pTrampoline = s_pRegion->pFree; 827 | // do a last sanity check on region. 828 | if (pTrampoline < pLo || pTrampoline > pHi) { 829 | return NULL; 830 | } 831 | s_pRegion->pFree = (PDETOUR_TRAMPOLINE)pTrampoline->pbRemain; 832 | memset(pTrampoline, 0xcc, sizeof(*pTrampoline)); 833 | return pTrampoline; 834 | } 835 | 836 | // Then check the existing regions for a valid free block. 837 | for (s_pRegion = s_pRegions; s_pRegion != NULL; s_pRegion = s_pRegion->pNext) { 838 | if (s_pRegion != NULL && s_pRegion->pFree != NULL && 839 | s_pRegion->pFree >= pLo && s_pRegion->pFree <= pHi) { 840 | goto found_region; 841 | } 842 | } 843 | 844 | // We need to allocate a new region. 845 | 846 | // Round pbTarget down to 64KB block. 847 | pbTarget = pbTarget - (PtrToUlong(pbTarget) & 0xffff); 848 | 849 | PVOID pbTry = NULL; 850 | 851 | // Try looking 1GB below or lower. 852 | if (pbTry == NULL && pbTarget > (PBYTE)0x40000000) { 853 | pbTry = detour_alloc_region_from_hi((PBYTE)pLo, pbTarget - 0x40000000); 854 | } 855 | // Try looking 1GB above or higher. 856 | if (pbTry == NULL && pbTarget < (PBYTE)0xffffffff40000000) { 857 | pbTry = detour_alloc_region_from_lo(pbTarget + 0x40000000, (PBYTE)pHi); 858 | } 859 | // Try looking 1GB below or higher. 860 | if (pbTry == NULL && pbTarget > (PBYTE)0x40000000) { 861 | pbTry = detour_alloc_region_from_lo(pbTarget - 0x40000000, pbTarget); 862 | } 863 | // Try looking 1GB above or lower. 864 | if (pbTry == NULL && pbTarget < (PBYTE)0xffffffff40000000) { 865 | pbTry = detour_alloc_region_from_hi(pbTarget, pbTarget + 0x40000000); 866 | } 867 | // Try anything below. 868 | if (pbTry == NULL) { 869 | pbTry = detour_alloc_region_from_hi((PBYTE)pLo, pbTarget); 870 | } 871 | // try anything above. 872 | if (pbTry == NULL) { 873 | pbTry = detour_alloc_region_from_lo(pbTarget, (PBYTE)pHi); 874 | } 875 | 876 | if (pbTry != NULL) { 877 | s_pRegion = (DETOUR_REGION*)pbTry; 878 | s_pRegion->dwSignature = DETOUR_REGION_SIGNATURE; 879 | s_pRegion->pFree = NULL; 880 | s_pRegion->pNext = s_pRegions; 881 | s_pRegions = s_pRegion; 882 | DETOUR_TRACE((" Allocated region %p..%p\n\n", 883 | s_pRegion, ((PBYTE)s_pRegion) + DETOUR_REGION_SIZE - 1)); 884 | 885 | // Put everything but the first trampoline on the free list. 886 | PBYTE pFree = NULL; 887 | pTrampoline = ((PDETOUR_TRAMPOLINE)s_pRegion) + 1; 888 | for (int i = DETOUR_TRAMPOLINES_PER_REGION - 1; i > 1; i--) { 889 | pTrampoline[i].pbRemain = pFree; 890 | pFree = (PBYTE)&pTrampoline[i]; 891 | } 892 | s_pRegion->pFree = (PDETOUR_TRAMPOLINE)pFree; 893 | goto found_region; 894 | } 895 | 896 | DETOUR_TRACE(("Couldn't find available memory region!\n")); 897 | return NULL; 898 | } 899 | 900 | static void detour_free_trampoline(PDETOUR_TRAMPOLINE pTrampoline) 901 | { 902 | PDETOUR_REGION pRegion = (PDETOUR_REGION) 903 | ((ULONG_PTR)pTrampoline & ~(ULONG_PTR)0xffff); 904 | 905 | memset(pTrampoline, 0, sizeof(*pTrampoline)); 906 | pTrampoline->pbRemain = (PBYTE)pRegion->pFree; 907 | pRegion->pFree = pTrampoline; 908 | } 909 | 910 | static BOOL detour_is_region_empty(PDETOUR_REGION pRegion) 911 | { 912 | // Stop if the region isn't a region (this would be bad). 913 | if (pRegion->dwSignature != DETOUR_REGION_SIGNATURE) { 914 | return FALSE; 915 | } 916 | 917 | PBYTE pbRegionBeg = (PBYTE)pRegion; 918 | PBYTE pbRegionLim = pbRegionBeg + DETOUR_REGION_SIZE; 919 | 920 | // Stop if any of the trampolines aren't free. 921 | PDETOUR_TRAMPOLINE pTrampoline = ((PDETOUR_TRAMPOLINE)pRegion) + 1; 922 | for (int i = 0; i < DETOUR_TRAMPOLINES_PER_REGION; i++) { 923 | if (pTrampoline[i].pbRemain != NULL && 924 | (pTrampoline[i].pbRemain < pbRegionBeg || 925 | pTrampoline[i].pbRemain >= pbRegionLim)) { 926 | return FALSE; 927 | } 928 | } 929 | 930 | // OK, the region is empty. 931 | return TRUE; 932 | } 933 | 934 | static void detour_free_unused_trampoline_regions() 935 | { 936 | PDETOUR_REGION *ppRegionBase = &s_pRegions; 937 | PDETOUR_REGION pRegion = s_pRegions; 938 | 939 | while (pRegion != NULL) { 940 | if (detour_is_region_empty(pRegion)) { 941 | *ppRegionBase = pRegion->pNext; 942 | 943 | VirtualFree(pRegion, 0, MEM_RELEASE); 944 | s_pRegion = NULL; 945 | } 946 | else { 947 | ppRegionBase = &pRegion->pNext; 948 | } 949 | pRegion = *ppRegionBase; 950 | } 951 | } 952 | 953 | ///////////////////////////////////////////////////////// Transaction Structs. 954 | // 955 | struct DetourThread 956 | { 957 | DetourThread * pNext; 958 | HANDLE hThread; 959 | }; 960 | 961 | struct DetourOperation 962 | { 963 | DetourOperation * pNext; 964 | BOOL fIsRemove; 965 | PBYTE * ppbPointer; 966 | PBYTE pbTarget; 967 | PDETOUR_TRAMPOLINE pTrampoline; 968 | ULONG dwPerm; 969 | }; 970 | 971 | static BOOL s_fIgnoreTooSmall = FALSE; 972 | static BOOL s_fRetainRegions = FALSE; 973 | 974 | static LONG s_nPendingThreadId = 0; // Thread owning pending transaction. 975 | static LONG s_nPendingError = NO_ERROR; 976 | static PVOID * s_ppPendingError = NULL; 977 | static DetourThread * s_pPendingThreads = NULL; 978 | static DetourOperation * s_pPendingOperations = NULL; 979 | 980 | ////////////////////////////////////////////////////////////////////////////// 981 | // 982 | PVOID WINAPI DetourCodeFromPointer(PVOID pPointer, PVOID *ppGlobals) 983 | { 984 | return detour_skip_jmp((PBYTE)pPointer, ppGlobals); 985 | } 986 | 987 | //////////////////////////////////////////////////////////// Transaction APIs. 988 | // 989 | BOOL WINAPI DetourSetIgnoreTooSmall(BOOL fIgnore) 990 | { 991 | BOOL fPrevious = s_fIgnoreTooSmall; 992 | s_fIgnoreTooSmall = fIgnore; 993 | return fPrevious; 994 | } 995 | 996 | BOOL WINAPI DetourSetRetainRegions(BOOL fRetain) 997 | { 998 | BOOL fPrevious = s_fRetainRegions; 999 | s_fRetainRegions = fRetain; 1000 | return fPrevious; 1001 | } 1002 | 1003 | LONG WINAPI DetourTransactionBegin() 1004 | { 1005 | // Only one transaction is allowed at a time. 1006 | if (s_nPendingThreadId != 0) { 1007 | return ERROR_INVALID_OPERATION; 1008 | } 1009 | // Make sure only one thread can start a transaction. 1010 | if (InterlockedCompareExchange(&s_nPendingThreadId, (LONG)GetCurrentThreadId(), 0) != 0) { 1011 | return ERROR_INVALID_OPERATION; 1012 | } 1013 | 1014 | s_pPendingOperations = NULL; 1015 | s_pPendingThreads = NULL; 1016 | s_nPendingError = NO_ERROR; 1017 | s_ppPendingError = NULL; 1018 | 1019 | // Make sure the trampoline pages are writable. 1020 | detour_writable_trampoline_regions(); 1021 | 1022 | return NO_ERROR; 1023 | } 1024 | 1025 | LONG WINAPI DetourTransactionAbort() 1026 | { 1027 | if (s_nPendingThreadId != (LONG)GetCurrentThreadId()) { 1028 | return ERROR_INVALID_OPERATION; 1029 | } 1030 | 1031 | // Restore all of the page permissions. 1032 | for (DetourOperation *o = s_pPendingOperations; o != NULL;) { 1033 | // We don't care if this fails, because the code is still accessible. 1034 | DWORD dwOld; 1035 | VirtualProtect(o->pbTarget, o->pTrampoline->cbRestore, 1036 | o->dwPerm, &dwOld); 1037 | 1038 | if (!o->fIsRemove) { 1039 | if (o->pTrampoline) { 1040 | detour_free_trampoline(o->pTrampoline); 1041 | o->pTrampoline = NULL; 1042 | } 1043 | } 1044 | 1045 | DetourOperation *n = o->pNext; 1046 | delete o; 1047 | o = n; 1048 | } 1049 | s_pPendingOperations = NULL; 1050 | 1051 | // Make sure the trampoline pages are no longer writable. 1052 | detour_runnable_trampoline_regions(); 1053 | 1054 | // Resume any suspended threads. 1055 | for (DetourThread *t = s_pPendingThreads; t != NULL;) { 1056 | // There is nothing we can do if this fails. 1057 | ResumeThread(t->hThread); 1058 | 1059 | DetourThread *n = t->pNext; 1060 | delete t; 1061 | t = n; 1062 | } 1063 | s_pPendingThreads = NULL; 1064 | s_nPendingThreadId = 0; 1065 | 1066 | return NO_ERROR; 1067 | } 1068 | 1069 | LONG WINAPI DetourTransactionCommit() 1070 | { 1071 | return DetourTransactionCommitEx(NULL); 1072 | } 1073 | 1074 | static BYTE detour_align_from_trampoline(PDETOUR_TRAMPOLINE pTrampoline, BYTE obTrampoline) 1075 | { 1076 | for (LONG n = 0; n < ARRAYSIZE(pTrampoline->rAlign); n++) { 1077 | if (pTrampoline->rAlign[n].obTrampoline == obTrampoline) { 1078 | return pTrampoline->rAlign[n].obTarget; 1079 | } 1080 | } 1081 | return 0; 1082 | } 1083 | 1084 | static LONG detour_align_from_target(PDETOUR_TRAMPOLINE pTrampoline, LONG obTarget) 1085 | { 1086 | for (LONG n = 0; n < ARRAYSIZE(pTrampoline->rAlign); n++) { 1087 | if (pTrampoline->rAlign[n].obTarget == obTarget) { 1088 | return pTrampoline->rAlign[n].obTrampoline; 1089 | } 1090 | } 1091 | return 0; 1092 | } 1093 | 1094 | LONG WINAPI DetourTransactionCommitEx(PVOID **pppFailedPointer) 1095 | { 1096 | if (pppFailedPointer != NULL) { 1097 | // Used to get the last error. 1098 | *pppFailedPointer = s_ppPendingError; 1099 | } 1100 | if (s_nPendingThreadId != (LONG)GetCurrentThreadId()) { 1101 | return ERROR_INVALID_OPERATION; 1102 | } 1103 | 1104 | // If any of the pending operations failed, then we abort the whole transaction. 1105 | if (s_nPendingError != NO_ERROR) { 1106 | DETOUR_BREAK(); 1107 | DetourTransactionAbort(); 1108 | return s_nPendingError; 1109 | } 1110 | 1111 | // Common variables. 1112 | DetourOperation *o; 1113 | DetourThread *t; 1114 | BOOL freed = FALSE; 1115 | 1116 | // Insert or remove each of the detours. 1117 | for (o = s_pPendingOperations; o != NULL; o = o->pNext) { 1118 | if (o->fIsRemove) { 1119 | CopyMemory(o->pbTarget, 1120 | o->pTrampoline->rbRestore, 1121 | o->pTrampoline->cbRestore); 1122 | #ifdef DETOURS_IA64 1123 | #error Feature not supported in this release. 1124 | #endif // DETOURS_IA64 1125 | 1126 | #ifdef DETOURS_X86 1127 | *o->ppbPointer = o->pbTarget; 1128 | #endif // DETOURS_X86 1129 | 1130 | #ifdef DETOURS_X64 1131 | #error Feature not supported in this release. 1132 | #endif // DETOURS_X64 1133 | 1134 | #ifdef DETOURS_ARM 1135 | #error Feature not supported in this release. 1136 | #endif // DETOURS_ARM 1137 | } 1138 | else { 1139 | DETOUR_TRACE(("detours: pbTramp =%p, pbRemain=%p, pbDetour=%p, cbRestore=%d\n", 1140 | o->pTrampoline, 1141 | o->pTrampoline->pbRemain, 1142 | o->pTrampoline->pbDetour, 1143 | o->pTrampoline->cbRestore)); 1144 | 1145 | DETOUR_TRACE(("detours: pbTarget=%p: " 1146 | "%02x %02x %02x %02x " 1147 | "%02x %02x %02x %02x " 1148 | "%02x %02x %02x %02x [before]\n", 1149 | o->pbTarget, 1150 | o->pbTarget[0], o->pbTarget[1], o->pbTarget[2], o->pbTarget[3], 1151 | o->pbTarget[4], o->pbTarget[5], o->pbTarget[6], o->pbTarget[7], 1152 | o->pbTarget[8], o->pbTarget[9], o->pbTarget[10], o->pbTarget[11])); 1153 | 1154 | #ifdef DETOURS_IA64 1155 | #error Feature not supported in this release. 1156 | 1157 | 1158 | #endif // DETOURS_IA64 1159 | 1160 | #ifdef DETOURS_X64 1161 | #error Feature not supported in this release. 1162 | 1163 | 1164 | 1165 | #endif // DETOURS_X64 1166 | 1167 | #ifdef DETOURS_X86 1168 | PBYTE pbCode = detour_gen_jmp_immediate(o->pbTarget, o->pTrampoline->pbDetour); 1169 | pbCode = detour_gen_brk(pbCode, o->pTrampoline->pbRemain); 1170 | *o->ppbPointer = o->pTrampoline->rbCode; 1171 | #endif // DETOURS_X86 1172 | 1173 | #ifdef DETOURS_ARM 1174 | #error Feature not supported in this release. 1175 | 1176 | 1177 | #endif // DETOURS_ARM 1178 | 1179 | DETOUR_TRACE(("detours: pbTarget=%p: " 1180 | "%02x %02x %02x %02x " 1181 | "%02x %02x %02x %02x " 1182 | "%02x %02x %02x %02x [after]\n", 1183 | o->pbTarget, 1184 | o->pbTarget[0], o->pbTarget[1], o->pbTarget[2], o->pbTarget[3], 1185 | o->pbTarget[4], o->pbTarget[5], o->pbTarget[6], o->pbTarget[7], 1186 | o->pbTarget[8], o->pbTarget[9], o->pbTarget[10], o->pbTarget[11])); 1187 | 1188 | DETOUR_TRACE(("detours: pbTramp =%p: " 1189 | "%02x %02x %02x %02x " 1190 | "%02x %02x %02x %02x " 1191 | "%02x %02x %02x %02x\n", 1192 | o->pTrampoline, 1193 | o->pTrampoline->rbCode[0], o->pTrampoline->rbCode[1], 1194 | o->pTrampoline->rbCode[2], o->pTrampoline->rbCode[3], 1195 | o->pTrampoline->rbCode[4], o->pTrampoline->rbCode[5], 1196 | o->pTrampoline->rbCode[6], o->pTrampoline->rbCode[7], 1197 | o->pTrampoline->rbCode[8], o->pTrampoline->rbCode[9], 1198 | o->pTrampoline->rbCode[10], o->pTrampoline->rbCode[11])); 1199 | 1200 | #ifdef DETOURS_IA64 1201 | #error Feature not supported in this release. 1202 | 1203 | 1204 | 1205 | 1206 | 1207 | 1208 | 1209 | 1210 | 1211 | 1212 | 1213 | 1214 | 1215 | 1216 | 1217 | 1218 | 1219 | 1220 | 1221 | 1222 | 1223 | 1224 | 1225 | 1226 | 1227 | 1228 | 1229 | 1230 | #endif // DETOURS_IA64 1231 | } 1232 | } 1233 | 1234 | // Update any suspended threads. 1235 | for (t = s_pPendingThreads; t != NULL; t = t->pNext) { 1236 | CONTEXT cxt; 1237 | cxt.ContextFlags = CONTEXT_CONTROL; 1238 | 1239 | #undef DETOURS_EIP 1240 | #undef DETOURS_EIP_TYPE 1241 | 1242 | #ifdef DETOURS_X86 1243 | #define DETOURS_EIP Eip 1244 | #define DETOURS_EIP_TYPE DWORD 1245 | #endif // DETOURS_X86 1246 | 1247 | #ifdef DETOURS_X64 1248 | #error Feature not supported in this release. 1249 | 1250 | #endif // DETOURS_X64 1251 | 1252 | #ifdef DETOURS_IA64 1253 | #error Feature not supported in this release. 1254 | 1255 | #endif // DETOURS_IA64 1256 | 1257 | #ifdef DETOURS_ARM 1258 | #error Feature not supported in this release. 1259 | 1260 | #endif // DETOURS_ARM 1261 | 1262 | if (GetThreadContext(t->hThread, &cxt)) { 1263 | for (DetourOperation *o = s_pPendingOperations; o != NULL; o = o->pNext) { 1264 | if (o->fIsRemove) { 1265 | if (cxt.DETOURS_EIP >= (DETOURS_EIP_TYPE)(ULONG_PTR)o->pTrampoline && 1266 | cxt.DETOURS_EIP < (DETOURS_EIP_TYPE)((ULONG_PTR)o->pTrampoline 1267 | + sizeof(o->pTrampoline)) 1268 | ) { 1269 | 1270 | cxt.DETOURS_EIP = (DETOURS_EIP_TYPE) 1271 | ((ULONG_PTR)o->pbTarget 1272 | + detour_align_from_trampoline(o->pTrampoline, 1273 | (BYTE)(cxt.DETOURS_EIP 1274 | - (DETOURS_EIP_TYPE)(ULONG_PTR) 1275 | o->pTrampoline))); 1276 | 1277 | SetThreadContext(t->hThread, &cxt); 1278 | } 1279 | } 1280 | else { 1281 | if (cxt.DETOURS_EIP >= (DETOURS_EIP_TYPE)(ULONG_PTR)o->pbTarget && 1282 | cxt.DETOURS_EIP < (DETOURS_EIP_TYPE)((ULONG_PTR)o->pbTarget 1283 | + o->pTrampoline->cbRestore) 1284 | ) { 1285 | 1286 | cxt.DETOURS_EIP = (DETOURS_EIP_TYPE) 1287 | ((ULONG_PTR)o->pTrampoline 1288 | + detour_align_from_target(o->pTrampoline, 1289 | (BYTE)(cxt.DETOURS_EIP 1290 | - (DETOURS_EIP_TYPE)(ULONG_PTR) 1291 | o->pbTarget))); 1292 | 1293 | SetThreadContext(t->hThread, &cxt); 1294 | } 1295 | } 1296 | } 1297 | } 1298 | #undef DETOURS_EIP 1299 | } 1300 | 1301 | // Restore all of the page permissions and flush the icache. 1302 | HANDLE hProcess = GetCurrentProcess(); 1303 | for (o = s_pPendingOperations; o != NULL;) { 1304 | // We don't care if this fails, because the code is still accessible. 1305 | DWORD dwOld; 1306 | VirtualProtect(o->pbTarget, o->pTrampoline->cbRestore, o->dwPerm, &dwOld); 1307 | FlushInstructionCache(hProcess, o->pbTarget, o->pTrampoline->cbRestore); 1308 | 1309 | if (o->fIsRemove && o->pTrampoline) { 1310 | detour_free_trampoline(o->pTrampoline); 1311 | o->pTrampoline = NULL; 1312 | freed = true; 1313 | } 1314 | 1315 | DetourOperation *n = o->pNext; 1316 | delete o; 1317 | o = n; 1318 | } 1319 | s_pPendingOperations = NULL; 1320 | 1321 | // Free any trampoline regions that are now unused. 1322 | if (freed && !s_fRetainRegions) { 1323 | detour_free_unused_trampoline_regions(); 1324 | } 1325 | 1326 | // Make sure the trampoline pages are no longer writable. 1327 | detour_runnable_trampoline_regions(); 1328 | 1329 | // Resume any suspended threads. 1330 | for (t = s_pPendingThreads; t != NULL;) { 1331 | // There is nothing we can do if this fails. 1332 | ResumeThread(t->hThread); 1333 | 1334 | DetourThread *n = t->pNext; 1335 | delete t; 1336 | t = n; 1337 | } 1338 | s_pPendingThreads = NULL; 1339 | s_nPendingThreadId = 0; 1340 | 1341 | if (pppFailedPointer != NULL) { 1342 | *pppFailedPointer = s_ppPendingError; 1343 | } 1344 | 1345 | return s_nPendingError; 1346 | } 1347 | 1348 | LONG WINAPI DetourUpdateThread(HANDLE hThread) 1349 | { 1350 | LONG error; 1351 | 1352 | // If any of the pending operations failed, then we don't need to do this. 1353 | if (s_nPendingError != NO_ERROR) { 1354 | return s_nPendingError; 1355 | } 1356 | 1357 | // Silently (and safely) drop any attempt to suspend our own thread. 1358 | if (hThread == GetCurrentThread()) { 1359 | return NO_ERROR; 1360 | } 1361 | 1362 | DetourThread *t = new DetourThread; 1363 | if (t == NULL) { 1364 | error = ERROR_NOT_ENOUGH_MEMORY; 1365 | fail: 1366 | if (t != NULL) { 1367 | delete t; 1368 | t = NULL; 1369 | } 1370 | s_nPendingError = error; 1371 | s_ppPendingError = NULL; 1372 | DETOUR_BREAK(); 1373 | return error; 1374 | } 1375 | 1376 | if (SuspendThread(hThread) == (DWORD)-1) { 1377 | error = GetLastError(); 1378 | DETOUR_BREAK(); 1379 | goto fail; 1380 | } 1381 | 1382 | t->hThread = hThread; 1383 | t->pNext = s_pPendingThreads; 1384 | s_pPendingThreads = t; 1385 | 1386 | return NO_ERROR; 1387 | } 1388 | 1389 | ///////////////////////////////////////////////////////////// Transacted APIs. 1390 | // 1391 | LONG WINAPI DetourAttach(PVOID *ppPointer, 1392 | PVOID pDetour) 1393 | { 1394 | return DetourAttachEx(ppPointer, pDetour, NULL, NULL, NULL); 1395 | } 1396 | 1397 | LONG WINAPI DetourAttachEx(PVOID *ppPointer, 1398 | PVOID pDetour, 1399 | PDETOUR_TRAMPOLINE *ppRealTrampoline, 1400 | PVOID *ppRealTarget, 1401 | PVOID *ppRealDetour) 1402 | { 1403 | LONG error = NO_ERROR; 1404 | 1405 | if (ppRealTrampoline != NULL) { 1406 | *ppRealTrampoline = NULL; 1407 | } 1408 | if (ppRealTarget != NULL) { 1409 | *ppRealTarget = NULL; 1410 | } 1411 | if (ppRealDetour != NULL) { 1412 | *ppRealDetour = NULL; 1413 | } 1414 | 1415 | if (s_nPendingThreadId != (LONG)GetCurrentThreadId()) { 1416 | DETOUR_TRACE(("transaction conflict with thread id=%d\n", s_nPendingThreadId)); 1417 | return ERROR_INVALID_OPERATION; 1418 | } 1419 | 1420 | // If any of the pending operations failed, then we don't need to do this. 1421 | if (s_nPendingError != NO_ERROR) { 1422 | DETOUR_TRACE(("pending transaction error=%d\n", s_nPendingError)); 1423 | return s_nPendingError; 1424 | } 1425 | 1426 | if (ppPointer == NULL) { 1427 | DETOUR_TRACE(("ppPointer is null\n")); 1428 | return ERROR_INVALID_HANDLE; 1429 | } 1430 | if (*ppPointer == NULL) { 1431 | error = ERROR_INVALID_HANDLE; 1432 | s_nPendingError = error; 1433 | s_ppPendingError = ppPointer; 1434 | DETOUR_TRACE(("*ppPointer is null (ppPointer=%p)\n", ppPointer)); 1435 | DETOUR_BREAK(); 1436 | return error; 1437 | } 1438 | 1439 | PBYTE pbTarget = (PBYTE)*ppPointer; 1440 | PDETOUR_TRAMPOLINE pTrampoline = NULL; 1441 | DetourOperation *o = NULL; 1442 | 1443 | #ifdef DETOURS_IA64 1444 | #error Feature not supported in this release. 1445 | 1446 | 1447 | 1448 | 1449 | 1450 | 1451 | 1452 | 1453 | 1454 | 1455 | #else // DETOURS_IA64 1456 | pbTarget = (PBYTE)DetourCodeFromPointer(pbTarget, NULL); 1457 | pDetour = DetourCodeFromPointer(pDetour, NULL); 1458 | #endif // !DETOURS_IA64 1459 | 1460 | // Don't follow a jump if its destination is the target function. 1461 | // This happens when the detour does nothing other than call the target. 1462 | if (pDetour == (PVOID)pbTarget) { 1463 | if (s_fIgnoreTooSmall) { 1464 | goto stop; 1465 | } 1466 | else { 1467 | DETOUR_BREAK(); 1468 | goto fail; 1469 | } 1470 | } 1471 | 1472 | if (ppRealTarget != NULL) { 1473 | *ppRealTarget = pbTarget; 1474 | } 1475 | if (ppRealDetour != NULL) { 1476 | *ppRealDetour = pDetour; 1477 | } 1478 | 1479 | o = new DetourOperation; 1480 | if (o == NULL) { 1481 | error = ERROR_NOT_ENOUGH_MEMORY; 1482 | fail: 1483 | s_nPendingError = error; 1484 | DETOUR_BREAK(); 1485 | stop: 1486 | if (pTrampoline != NULL) { 1487 | detour_free_trampoline(pTrampoline); 1488 | pTrampoline = NULL; 1489 | if (ppRealTrampoline != NULL) { 1490 | *ppRealTrampoline = NULL; 1491 | } 1492 | } 1493 | if (o != NULL) { 1494 | delete o; 1495 | o = NULL; 1496 | } 1497 | s_ppPendingError = ppPointer; 1498 | return error; 1499 | } 1500 | 1501 | pTrampoline = detour_alloc_trampoline(pbTarget); 1502 | if (pTrampoline == NULL) { 1503 | error = ERROR_NOT_ENOUGH_MEMORY; 1504 | DETOUR_BREAK(); 1505 | goto fail; 1506 | } 1507 | 1508 | if (ppRealTrampoline != NULL) { 1509 | *ppRealTrampoline = pTrampoline; 1510 | } 1511 | 1512 | DETOUR_TRACE(("detours: pbTramp=%p, pDetour=%p\n", pTrampoline, pDetour)); 1513 | 1514 | memset(pTrampoline->rAlign, 0, sizeof(pTrampoline->rAlign)); 1515 | 1516 | // Determine the number of movable target instructions. 1517 | PBYTE pbSrc = pbTarget; 1518 | PBYTE pbTrampoline = pTrampoline->rbCode; 1519 | PBYTE pbPool = pbTrampoline + sizeof(pTrampoline->rbCode); 1520 | ULONG cbTarget = 0; 1521 | ULONG cbJump = SIZE_OF_JMP; 1522 | ULONG nAlign = 0; 1523 | 1524 | #ifdef DETOURS_ARM 1525 | #error Feature not supported in this release. 1526 | 1527 | 1528 | 1529 | 1530 | 1531 | 1532 | 1533 | 1534 | 1535 | 1536 | 1537 | 1538 | 1539 | 1540 | 1541 | 1542 | 1543 | 1544 | 1545 | 1546 | 1547 | 1548 | 1549 | 1550 | 1551 | 1552 | #endif 1553 | 1554 | while (cbTarget < cbJump) { 1555 | PBYTE pbOp = pbSrc; 1556 | LONG lExtra = 0; 1557 | 1558 | DETOUR_TRACE((" DetourCopyInstruction(%p,%p)\n", 1559 | pbTrampoline, pbSrc)); 1560 | pbSrc = (PBYTE) 1561 | DetourCopyInstruction(pbTrampoline, (PVOID*)&pbPool, pbSrc, NULL, &lExtra); 1562 | DETOUR_TRACE((" DetourCopyInstruction() = %p (%d bytes)\n", 1563 | pbSrc, (int)(pbSrc - pbOp))); 1564 | pbTrampoline += (pbSrc - pbOp) + lExtra; 1565 | cbTarget = (LONG)(pbSrc - pbTarget); 1566 | pTrampoline->rAlign[nAlign].obTarget = cbTarget; 1567 | pTrampoline->rAlign[nAlign].obTrampoline = pbTrampoline - pTrampoline->rbCode; 1568 | 1569 | if (detour_does_code_end_function(pbOp)) { 1570 | break; 1571 | } 1572 | } 1573 | 1574 | // Consume, but don't duplicate padding if it is needed and available. 1575 | while (cbTarget < cbJump) { 1576 | LONG cFiller = detour_is_code_filler(pbSrc); 1577 | if (cFiller == 0) { 1578 | break; 1579 | } 1580 | 1581 | pbSrc += cFiller; 1582 | cbTarget = (LONG)(pbSrc - pbTarget); 1583 | } 1584 | 1585 | #if DETOUR_DEBUG 1586 | { 1587 | DETOUR_TRACE((" detours: rAlign [")); 1588 | LONG n = 0; 1589 | for (n = 0; n < ARRAYSIZE(pTrampoline->rAlign); n++) { 1590 | if (pTrampoline->rAlign[n].obTarget == 0 && 1591 | pTrampoline->rAlign[n].obTrampoline == 0) { 1592 | break; 1593 | } 1594 | DETOUR_TRACE((" %d/%d", 1595 | pTrampoline->rAlign[n].obTarget, 1596 | pTrampoline->rAlign[n].obTrampoline 1597 | )); 1598 | 1599 | } 1600 | DETOUR_TRACE((" ]\n")); 1601 | } 1602 | #endif 1603 | 1604 | if (cbTarget < cbJump || nAlign > ARRAYSIZE(pTrampoline->rAlign)) { 1605 | // Too few instructions. 1606 | 1607 | error = ERROR_INVALID_BLOCK; 1608 | if (s_fIgnoreTooSmall) { 1609 | goto stop; 1610 | } 1611 | else { 1612 | DETOUR_BREAK(); 1613 | goto fail; 1614 | } 1615 | } 1616 | 1617 | if (pbTrampoline > pbPool) { 1618 | __debugbreak(); 1619 | } 1620 | 1621 | #if 0 // [GalenH] 1622 | if (cbTarget < pbTrampoline - pTrampoline->rbCode) { 1623 | __debugbreak(); 1624 | } 1625 | #endif 1626 | 1627 | pTrampoline->cbCode = (BYTE)(pbTrampoline - pTrampoline->rbCode); 1628 | pTrampoline->cbRestore = (BYTE)cbTarget; 1629 | CopyMemory(pTrampoline->rbRestore, pbTarget, cbTarget); 1630 | 1631 | #if !defined(DETOURS_IA64) 1632 | if (cbTarget > sizeof(pTrampoline->rbCode) - cbJump) { 1633 | // Too many instructions. 1634 | error = ERROR_INVALID_HANDLE; 1635 | DETOUR_BREAK(); 1636 | goto fail; 1637 | } 1638 | #endif // !DETOURS_IA64 1639 | 1640 | pTrampoline->pbRemain = pbTarget + cbTarget; 1641 | pTrampoline->pbDetour = (PBYTE)pDetour; 1642 | 1643 | #ifdef DETOURS_IA64 1644 | #error Feature not supported in this release. 1645 | 1646 | 1647 | 1648 | 1649 | 1650 | 1651 | 1652 | 1653 | 1654 | 1655 | 1656 | 1657 | 1658 | 1659 | 1660 | 1661 | 1662 | 1663 | 1664 | 1665 | 1666 | 1667 | 1668 | 1669 | 1670 | 1671 | 1672 | 1673 | 1674 | 1675 | 1676 | 1677 | 1678 | 1679 | 1680 | 1681 | #endif // DETOURS_IA64 1682 | 1683 | pbTrampoline = pTrampoline->rbCode + pTrampoline->cbCode; 1684 | #ifdef DETOURS_X64 1685 | #error Feature not supported in this release. 1686 | 1687 | #endif // DETOURS_X64 1688 | 1689 | #ifdef DETOURS_X86 1690 | pbTrampoline = detour_gen_jmp_immediate(pbTrampoline, pTrampoline->pbRemain); 1691 | pbTrampoline = detour_gen_brk(pbTrampoline, pbPool); 1692 | #endif // DETOURS_X86 1693 | 1694 | #ifdef DETOURS_ARM 1695 | #error Feature not supported in this release. 1696 | 1697 | #endif // DETOURS_ARM 1698 | 1699 | DWORD dwOld = 0; 1700 | if (!VirtualProtect(pbTarget, cbTarget, PAGE_EXECUTE_READWRITE, &dwOld)) { 1701 | error = GetLastError(); 1702 | DETOUR_BREAK(); 1703 | goto fail; 1704 | } 1705 | 1706 | DETOUR_TRACE(("detours: pbTarget=%p: " 1707 | "%02x %02x %02x %02x " 1708 | "%02x %02x %02x %02x " 1709 | "%02x %02x %02x %02x\n", 1710 | pbTarget, 1711 | pbTarget[0], pbTarget[1], pbTarget[2], pbTarget[3], 1712 | pbTarget[4], pbTarget[5], pbTarget[6], pbTarget[7], 1713 | pbTarget[8], pbTarget[9], pbTarget[10], pbTarget[11])); 1714 | DETOUR_TRACE(("detours: pbTramp =%p: " 1715 | "%02x %02x %02x %02x " 1716 | "%02x %02x %02x %02x " 1717 | "%02x %02x %02x %02x\n", 1718 | pTrampoline, 1719 | pTrampoline->rbCode[0], pTrampoline->rbCode[1], 1720 | pTrampoline->rbCode[2], pTrampoline->rbCode[3], 1721 | pTrampoline->rbCode[4], pTrampoline->rbCode[5], 1722 | pTrampoline->rbCode[6], pTrampoline->rbCode[7], 1723 | pTrampoline->rbCode[8], pTrampoline->rbCode[9], 1724 | pTrampoline->rbCode[10], pTrampoline->rbCode[11])); 1725 | 1726 | o->fIsRemove = FALSE; 1727 | o->ppbPointer = (PBYTE*)ppPointer; 1728 | o->pTrampoline = pTrampoline; 1729 | o->pbTarget = pbTarget; 1730 | o->dwPerm = dwOld; 1731 | o->pNext = s_pPendingOperations; 1732 | s_pPendingOperations = o; 1733 | 1734 | return NO_ERROR; 1735 | } 1736 | 1737 | LONG WINAPI DetourDetach(PVOID *ppPointer, 1738 | PVOID pDetour) 1739 | { 1740 | LONG error = NO_ERROR; 1741 | 1742 | if (s_nPendingThreadId != (LONG)GetCurrentThreadId()) { 1743 | return ERROR_INVALID_OPERATION; 1744 | } 1745 | 1746 | // If any of the pending operations failed, then we don't need to do this. 1747 | if (s_nPendingError != NO_ERROR) { 1748 | return s_nPendingError; 1749 | } 1750 | 1751 | if (ppPointer == NULL) { 1752 | return ERROR_INVALID_HANDLE; 1753 | } 1754 | if (*ppPointer == NULL) { 1755 | error = ERROR_INVALID_HANDLE; 1756 | s_nPendingError = error; 1757 | s_ppPendingError = ppPointer; 1758 | DETOUR_BREAK(); 1759 | return error; 1760 | } 1761 | 1762 | DetourOperation *o = new DetourOperation; 1763 | if (o == NULL) { 1764 | error = ERROR_NOT_ENOUGH_MEMORY; 1765 | fail: 1766 | s_nPendingError = error; 1767 | DETOUR_BREAK(); 1768 | stop: 1769 | if (o != NULL) { 1770 | delete o; 1771 | o = NULL; 1772 | } 1773 | s_ppPendingError = ppPointer; 1774 | return error; 1775 | } 1776 | 1777 | 1778 | #ifdef DETOURS_IA64 1779 | #error Feature not supported in this release. 1780 | 1781 | 1782 | 1783 | 1784 | 1785 | 1786 | 1787 | 1788 | 1789 | 1790 | 1791 | 1792 | 1793 | 1794 | 1795 | 1796 | 1797 | 1798 | 1799 | 1800 | 1801 | 1802 | 1803 | 1804 | 1805 | 1806 | 1807 | 1808 | 1809 | 1810 | 1811 | 1812 | 1813 | 1814 | 1815 | 1816 | 1817 | 1818 | 1819 | 1820 | 1821 | 1822 | #else // !DETOURS_IA64 1823 | PDETOUR_TRAMPOLINE pTrampoline = 1824 | (PDETOUR_TRAMPOLINE)DetourCodeFromPointer(*ppPointer, NULL); 1825 | pDetour = DetourCodeFromPointer(pDetour, NULL); 1826 | #endif // !DETOURS_IA64 1827 | 1828 | ////////////////////////////////////// Verify that Trampoline is in place. 1829 | // 1830 | LONG cbTarget = pTrampoline->cbRestore; 1831 | PBYTE pbTarget = pTrampoline->pbRemain - cbTarget; 1832 | if (cbTarget == 0 || cbTarget > sizeof(pTrampoline->rbCode)) { 1833 | error = ERROR_INVALID_BLOCK; 1834 | if (s_fIgnoreTooSmall) { 1835 | goto stop; 1836 | } 1837 | else { 1838 | DETOUR_BREAK(); 1839 | goto fail; 1840 | } 1841 | } 1842 | 1843 | if (pTrampoline->pbDetour != pDetour) { 1844 | error = ERROR_INVALID_BLOCK; 1845 | if (s_fIgnoreTooSmall) { 1846 | goto stop; 1847 | } 1848 | else { 1849 | DETOUR_BREAK(); 1850 | goto fail; 1851 | } 1852 | } 1853 | 1854 | DWORD dwOld = 0; 1855 | if (!VirtualProtect(pbTarget, cbTarget, 1856 | PAGE_EXECUTE_READWRITE, &dwOld)) { 1857 | error = GetLastError(); 1858 | DETOUR_BREAK(); 1859 | goto fail; 1860 | } 1861 | 1862 | o->fIsRemove = TRUE; 1863 | o->ppbPointer = (PBYTE*)ppPointer; 1864 | o->pTrampoline = pTrampoline; 1865 | o->pbTarget = pbTarget; 1866 | o->dwPerm = dwOld; 1867 | o->pNext = s_pPendingOperations; 1868 | s_pPendingOperations = o; 1869 | 1870 | return NO_ERROR; 1871 | } 1872 | 1873 | // End of File 1874 | -------------------------------------------------------------------------------- /src/SuperF12.dll/Detours/disasm.cpp: -------------------------------------------------------------------------------- 1 | ////////////////////////////////////////////////////////////////////////////// 2 | // 3 | // Detours Disassembler (disasm.cpp of detours.lib) 4 | // 5 | // Microsoft Research Detours Package, Version 3.0 Build_316. 6 | // 7 | // Copyright (c) Microsoft Corporation. All rights reserved. 8 | // 9 | 10 | #include 11 | #include 12 | 13 | // #define DETOUR_DEBUG 1 14 | #define DETOURS_INTERNAL 15 | 16 | #include "detours.h" 17 | 18 | #if defined(DETOURS_X86) 19 | #elif defined(DETOURS_X64) 20 | #elif defined(DETOURS_IA64) 21 | #elif defined(DETOURS_ARM) 22 | #else 23 | #error Must define one of DETOURS_X86, DETOURS_X64, DETOURS_IA64, or DETOURS_ARM 24 | #endif 25 | 26 | #undef ASSERT 27 | #define ASSERT(x) 28 | 29 | ////////////////////////////////////////////////////////////////////////////// 30 | // 31 | // Function: 32 | // DetourCopyInstruction(PVOID pDst, 33 | // PVOID *ppDstPool 34 | // PVOID pSrc, 35 | // PVOID *ppTarget, 36 | // LONG *plExtra) 37 | // Purpose: 38 | // Copy a single instruction from pSrc to pDst. 39 | // 40 | // Arguments: 41 | // pDst: 42 | // Destination address for the instruction. May be NULL in which 43 | // case DetourCopyInstruction is used to measure an instruction. 44 | // If not NULL then the source instruction is copied to the 45 | // destination instruction and any relative arguments are adjusted. 46 | // ppDstPool: 47 | // Destination address for the end of the constant pool. The 48 | // constant pool works backwards toward pDst. All memory between 49 | // pDst and *ppDstPool must be available for use by this function. 50 | // ppDstPool may be NULL if pDst is NULL. 51 | // pSrc: 52 | // Source address of the instruction. 53 | // ppTarget: 54 | // Out parameter for any target instruction address pointed to by 55 | // the instruction. For example, a branch or a jump insruction has 56 | // a target, but a load or store instruction doesn't. A target is 57 | // another instruction that may be executed as a result of this 58 | // instruction. ppTarget may be NULL. 59 | // plExtra: 60 | // Out parameter for the number of extra bytes needed by the 61 | // instruction to reach the target. For example, lExtra = 3 if the 62 | // instruction had an 8-bit relative offset, but needs a 32-bit 63 | // relative offset. 64 | // 65 | // Returns: 66 | // Returns the address of the next instruction (following in the source) 67 | // instruction. By subtracting pSrc from the return value, the caller 68 | // can determinte the size of the instruction copied. 69 | // 70 | // Comments: 71 | // By following the pTarget, the caller can follow alternate 72 | // instruction streams. However, it is not always possible to determine 73 | // the target based on static analysis. For example, the destination of 74 | // a jump relative to a register cannot be determined from just the 75 | // instruction stream. The output value, pTarget, can have any of the 76 | // following outputs: 77 | // DETOUR_INSTRUCTION_TARGET_NONE: 78 | // The instruction has no targets. 79 | // DETOUR_INSTRUCTION_TARGET_DYNAMIC: 80 | // The instruction has a non-deterministic (dynamic) target. 81 | // (i.e. the jump is to an address held in a register.) 82 | // Address: The instruction has the specified target. 83 | // 84 | // When copying instructions, DetourCopyInstruction insures that any 85 | // targets remain constant. It does so by adjusting any IP relative 86 | // offsets. 87 | // 88 | 89 | //////////////////////////////////////////////////// X86 and X64 Disassembler. 90 | // 91 | // Includes full support for all x86 chips prior to the Pentium III. 92 | // 93 | #if defined(DETOURS_X64) || defined(DETOURS_X86) 94 | 95 | class CDetourDis 96 | { 97 | public: 98 | CDetourDis(PBYTE *ppbTarget, LONG *plExtra); 99 | 100 | PBYTE CopyInstruction(PBYTE pbDst, PBYTE pbSrc); 101 | static BOOL SanityCheckSystem(); 102 | 103 | public: 104 | struct COPYENTRY; 105 | typedef const COPYENTRY * REFCOPYENTRY; 106 | 107 | typedef PBYTE (CDetourDis::* COPYFUNC)(REFCOPYENTRY pEntry, PBYTE pbDst, PBYTE pbSrc); 108 | 109 | enum { 110 | DYNAMIC = 0x1u, 111 | ADDRESS = 0x2u, 112 | NOENLARGE = 0x4u, 113 | RAX = 0x8u, 114 | 115 | SIB = 0x10u, 116 | RIP = 0x20u, 117 | NOTSIB = 0x0fu, 118 | }; 119 | struct COPYENTRY 120 | { 121 | ULONG nOpcode : 8; // Opcode 122 | ULONG nFixedSize : 4; // Fixed size of opcode 123 | ULONG nFixedSize16 : 4; // Fixed size when 16 bit operand 124 | ULONG nModOffset : 4; // Offset to mod/rm byte (0=none) 125 | LONG nRelOffset : 4; // Offset to relative target. 126 | LONG nTargetBack : 4; // Offset back to absolute or rip target 127 | ULONG nFlagBits : 4; // Flags for DYNAMIC, etc. 128 | COPYFUNC pfCopy; // Function pointer. 129 | }; 130 | 131 | protected: 132 | // These macros define common uses of nFixedSize..pfCopy. 133 | #define ENTRY_CopyBytes1 1, 1, 0, 0, 0, 0, &CDetourDis::CopyBytes 134 | #define ENTRY_CopyBytes1Dynamic 1, 1, 0, 0, 0, DYNAMIC, &CDetourDis::CopyBytes 135 | #define ENTRY_CopyBytes2 2, 2, 0, 0, 0, 0, &CDetourDis::CopyBytes 136 | #define ENTRY_CopyBytes2Jump 2, 2, 0, 1, 0, 0, &CDetourDis::CopyBytesJump 137 | #define ENTRY_CopyBytes2CantJump 2, 2, 0, 1, 0, NOENLARGE, &CDetourDis::CopyBytes 138 | #define ENTRY_CopyBytes2Dynamic 2, 2, 0, 0, 0, DYNAMIC, &CDetourDis::CopyBytes 139 | #define ENTRY_CopyBytes3 3, 3, 0, 0, 0, 0, &CDetourDis::CopyBytes 140 | #define ENTRY_CopyBytes3Dynamic 3, 3, 0, 0, 0, DYNAMIC, &CDetourDis::CopyBytes 141 | #define ENTRY_CopyBytes3Or5 5, 3, 0, 0, 0, 0, &CDetourDis::CopyBytes 142 | #define ENTRY_CopyBytes3Or5Rax 5, 3, 0, 0, 0, RAX, &CDetourDis::CopyBytes 143 | #define ENTRY_CopyBytes3Or5Target 5, 3, 0, 1, 0, 0, &CDetourDis::CopyBytes 144 | #define ENTRY_CopyBytes5Or7Dynamic 7, 5, 0, 0, 0, DYNAMIC, &CDetourDis::CopyBytes 145 | #define ENTRY_CopyBytes3Or5Address 5, 3, 0, 0, 0, ADDRESS, &CDetourDis::CopyBytes 146 | #define ENTRY_CopyBytes4 4, 4, 0, 0, 0, 0, &CDetourDis::CopyBytes 147 | #define ENTRY_CopyBytes5 5, 5, 0, 0, 0, 0, &CDetourDis::CopyBytes 148 | #define ENTRY_CopyBytes7 7, 7, 0, 0, 0, 0, &CDetourDis::CopyBytes 149 | #define ENTRY_CopyBytes2Mod 2, 2, 1, 0, 0, 0, &CDetourDis::CopyBytes 150 | #define ENTRY_CopyBytes2Mod1 3, 3, 1, 0, 1, 0, &CDetourDis::CopyBytes 151 | #define ENTRY_CopyBytes2ModOperand 6, 4, 1, 0, 4, 0, &CDetourDis::CopyBytes 152 | #define ENTRY_CopyBytes3Mod 3, 3, 2, 0, 0, 0, &CDetourDis::CopyBytes 153 | #define ENTRY_CopyBytesPrefix 1, 1, 0, 0, 0, 0, &CDetourDis::CopyBytesPrefix 154 | #define ENTRY_CopyBytesRax 1, 1, 0, 0, 0, 0, &CDetourDis::CopyBytesRax 155 | #define ENTRY_Copy0F 1, 1, 0, 0, 0, 0, &CDetourDis::Copy0F 156 | #define ENTRY_Copy66 1, 1, 0, 0, 0, 0, &CDetourDis::Copy66 157 | #define ENTRY_Copy67 1, 1, 0, 0, 0, 0, &CDetourDis::Copy67 158 | #define ENTRY_CopyF6 0, 0, 0, 0, 0, 0, &CDetourDis::CopyF6 159 | #define ENTRY_CopyF7 0, 0, 0, 0, 0, 0, &CDetourDis::CopyF7 160 | #define ENTRY_CopyFF 0, 0, 0, 0, 0, 0, &CDetourDis::CopyFF 161 | #define ENTRY_Invalid 1, 1, 0, 0, 0, 0, &CDetourDis::Invalid 162 | #define ENTRY_End 0, 0, 0, 0, 0, 0, NULL 163 | 164 | PBYTE CopyBytes(REFCOPYENTRY pEntry, PBYTE pbDst, PBYTE pbSrc); 165 | PBYTE CopyBytesPrefix(REFCOPYENTRY pEntry, PBYTE pbDst, PBYTE pbSrc); 166 | PBYTE CopyBytesRax(REFCOPYENTRY pEntry, PBYTE pbDst, PBYTE pbSrc); 167 | PBYTE CopyBytesJump(REFCOPYENTRY pEntry, PBYTE pbDst, PBYTE pbSrc); 168 | 169 | PBYTE Invalid(REFCOPYENTRY pEntry, PBYTE pbDst, PBYTE pbSrc); 170 | 171 | PBYTE AdjustTarget(PBYTE pbDst, PBYTE pbSrc, LONG cbOp, 172 | LONG cbTargetOffset, LONG cbTargetSize); 173 | 174 | protected: 175 | PBYTE Copy0F(REFCOPYENTRY pEntry, PBYTE pbDst, PBYTE pbSrc); 176 | PBYTE Copy66(REFCOPYENTRY pEntry, PBYTE pbDst, PBYTE pbSrc); 177 | PBYTE Copy67(REFCOPYENTRY pEntry, PBYTE pbDst, PBYTE pbSrc); 178 | PBYTE CopyF6(REFCOPYENTRY pEntry, PBYTE pbDst, PBYTE pbSrc); 179 | PBYTE CopyF7(REFCOPYENTRY pEntry, PBYTE pbDst, PBYTE pbSrc); 180 | PBYTE CopyFF(REFCOPYENTRY pEntry, PBYTE pbDst, PBYTE pbSrc); 181 | 182 | protected: 183 | static const COPYENTRY s_rceCopyTable[257]; 184 | static const COPYENTRY s_rceCopyTable0F[257]; 185 | static const BYTE s_rbModRm[256]; 186 | 187 | protected: 188 | BOOL m_bOperandOverride; 189 | BOOL m_bAddressOverride; 190 | BOOL m_bRaxOverride; 191 | 192 | PBYTE * m_ppbTarget; 193 | LONG * m_plExtra; 194 | 195 | LONG m_lScratchExtra; 196 | PBYTE m_pbScratchTarget; 197 | BYTE m_rbScratchDst[64]; 198 | }; 199 | 200 | PVOID WINAPI DetourCopyInstruction(PVOID pDst, 201 | PVOID *ppDstPool, 202 | PVOID pSrc, 203 | PVOID *ppTarget, 204 | LONG *plExtra) 205 | { 206 | (void)ppDstPool; // x86 & x64 don't use a constant pool. 207 | CDetourDis oDetourDisasm((PBYTE*)ppTarget, plExtra); 208 | return oDetourDisasm.CopyInstruction((PBYTE)pDst, (PBYTE)pSrc); 209 | } 210 | 211 | /////////////////////////////////////////////////////////// Disassembler Code. 212 | // 213 | CDetourDis::CDetourDis(PBYTE *ppbTarget, LONG *plExtra) 214 | { 215 | m_bOperandOverride = FALSE; 216 | m_bAddressOverride = FALSE; 217 | m_bRaxOverride = FALSE; 218 | 219 | m_ppbTarget = ppbTarget ? ppbTarget : &m_pbScratchTarget; 220 | m_plExtra = plExtra ? plExtra : &m_lScratchExtra; 221 | 222 | *m_ppbTarget = (PBYTE)DETOUR_INSTRUCTION_TARGET_NONE; 223 | *m_plExtra = 0; 224 | } 225 | 226 | PBYTE CDetourDis::CopyInstruction(PBYTE pbDst, PBYTE pbSrc) 227 | { 228 | // Configure scratch areas if real areas are not available. 229 | if (NULL == pbDst) { 230 | pbDst = m_rbScratchDst; 231 | } 232 | if (NULL == pbSrc) { 233 | // We can't copy a non-existent instruction. 234 | SetLastError(ERROR_INVALID_DATA); 235 | return NULL; 236 | } 237 | 238 | // Figure out how big the instruction is, do the appropriate copy, 239 | // and figure out what the target of the instruction is if any. 240 | // 241 | REFCOPYENTRY pEntry = &s_rceCopyTable[pbSrc[0]]; 242 | return (this->*pEntry->pfCopy)(pEntry, pbDst, pbSrc); 243 | } 244 | 245 | PBYTE CDetourDis::CopyBytes(REFCOPYENTRY pEntry, PBYTE pbDst, PBYTE pbSrc) 246 | { 247 | #ifdef DETOURS_X64 248 | #error Feature not supported in this release. 249 | 250 | 251 | 252 | 253 | #else 254 | LONG nBytesFixed = (pEntry->nFlagBits & ADDRESS) 255 | ? (m_bAddressOverride ? pEntry->nFixedSize16 : pEntry->nFixedSize) 256 | : (m_bOperandOverride ? pEntry->nFixedSize16 : pEntry->nFixedSize); 257 | #endif 258 | 259 | LONG nBytes = nBytesFixed; 260 | LONG nRelOffset = pEntry->nRelOffset; 261 | LONG cbTarget = nBytes - nRelOffset; 262 | if (pEntry->nModOffset > 0) { 263 | BYTE bModRm = pbSrc[pEntry->nModOffset]; 264 | BYTE bFlags = s_rbModRm[bModRm]; 265 | 266 | nBytes += bFlags & NOTSIB; 267 | 268 | if (bFlags & SIB) { 269 | BYTE bSib = pbSrc[pEntry->nModOffset + 1]; 270 | 271 | if ((bSib & 0x07) == 0x05) { 272 | if ((bModRm & 0xc0) == 0x00) { 273 | nBytes += 4; 274 | } 275 | else if ((bModRm & 0xc0) == 0x40) { 276 | nBytes += 1; 277 | } 278 | else if ((bModRm & 0xc0) == 0x80) { 279 | nBytes += 4; 280 | } 281 | } 282 | cbTarget = nBytes - nRelOffset; 283 | } 284 | else if (bFlags & RIP) { 285 | #ifdef DETOURS_X64 286 | #error Feature not supported in this release. 287 | 288 | 289 | #endif 290 | } 291 | } 292 | CopyMemory(pbDst, pbSrc, nBytes); 293 | 294 | if (nRelOffset) { 295 | *m_ppbTarget = AdjustTarget(pbDst, pbSrc, nBytesFixed, nRelOffset, cbTarget); 296 | #ifdef DETOURS_X64 297 | #error Feature not supported in this release. 298 | 299 | 300 | 301 | #endif 302 | } 303 | if (pEntry->nFlagBits & NOENLARGE) { 304 | *m_plExtra = -*m_plExtra; 305 | } 306 | if (pEntry->nFlagBits & DYNAMIC) { 307 | *m_ppbTarget = (PBYTE)DETOUR_INSTRUCTION_TARGET_DYNAMIC; 308 | } 309 | return pbSrc + nBytes; 310 | } 311 | 312 | PBYTE CDetourDis::CopyBytesPrefix(REFCOPYENTRY pEntry, PBYTE pbDst, PBYTE pbSrc) 313 | { 314 | CopyBytes(pEntry, pbDst, pbSrc); 315 | 316 | pEntry = &s_rceCopyTable[pbSrc[1]]; 317 | return (this->*pEntry->pfCopy)(pEntry, pbDst + 1, pbSrc + 1); 318 | } 319 | 320 | PBYTE CDetourDis::CopyBytesRax(REFCOPYENTRY pEntry, PBYTE pbDst, PBYTE pbSrc) 321 | { 322 | CopyBytes(pEntry, pbDst, pbSrc); 323 | 324 | if (*pbSrc & 0x8) { 325 | m_bRaxOverride = TRUE; 326 | } 327 | 328 | pEntry = &s_rceCopyTable[pbSrc[1]]; 329 | return (this->*pEntry->pfCopy)(pEntry, pbDst + 1, pbSrc + 1); 330 | } 331 | 332 | PBYTE CDetourDis::CopyBytesJump(REFCOPYENTRY pEntry, PBYTE pbDst, PBYTE pbSrc) 333 | { 334 | (void)pEntry; 335 | 336 | PVOID pvSrcAddr = &pbSrc[1]; 337 | PVOID pvDstAddr = NULL; 338 | LONG_PTR nOldOffset = (LONG_PTR)*(CHAR*&)pvSrcAddr; 339 | LONG_PTR nNewOffset = 0; 340 | 341 | *m_ppbTarget = pbSrc + 2 + nOldOffset; 342 | 343 | if (pbSrc[0] == 0xeb) { 344 | pbDst[0] = 0xe9; 345 | pvDstAddr = &pbDst[1]; 346 | nNewOffset = nOldOffset - ((pbDst - pbSrc) + 3); 347 | *(LONG*&)pvDstAddr = (LONG)nNewOffset; 348 | 349 | *m_plExtra = 3; 350 | return pbSrc + 2; 351 | } 352 | 353 | ASSERT(pbSrc[0] >= 0x70 && pbSrc[0] <= 0x7f); 354 | 355 | pbDst[0] = 0x0f; 356 | pbDst[1] = 0x80 | (pbSrc[0] & 0xf); 357 | pvDstAddr = &pbDst[2]; 358 | nNewOffset = nOldOffset - ((pbDst - pbSrc) + 4); 359 | *(LONG*&)pvDstAddr = (LONG)nNewOffset; 360 | 361 | *m_plExtra = 4; 362 | return pbSrc + 2; 363 | } 364 | 365 | PBYTE CDetourDis::AdjustTarget(PBYTE pbDst, PBYTE pbSrc, LONG cbOp, 366 | LONG cbTargetOffset, LONG cbTargetSize) 367 | { 368 | PBYTE pbTarget = NULL; 369 | PVOID pvTargetAddr = &pbDst[cbTargetOffset]; 370 | LONG_PTR nOldOffset = 0; 371 | 372 | switch (cbTargetSize) { 373 | case 1: 374 | nOldOffset = (LONG_PTR)*(CHAR*&)pvTargetAddr; 375 | break; 376 | case 2: 377 | nOldOffset = (LONG_PTR)*(SHORT*&)pvTargetAddr; 378 | break; 379 | case 4: 380 | nOldOffset = (LONG_PTR)*(LONG*&)pvTargetAddr; 381 | break; 382 | case 8: 383 | nOldOffset = (LONG_PTR)*(LONG_PTR*&)pvTargetAddr; 384 | break; 385 | default: 386 | ASSERT(!"cbTargetSize is invalid."); 387 | break; 388 | } 389 | 390 | pbTarget = pbSrc + cbOp + nOldOffset; 391 | LONG_PTR nNewOffset = nOldOffset - (pbDst - pbSrc); 392 | 393 | switch (cbTargetSize) { 394 | case 1: 395 | *(CHAR*&)pvTargetAddr = (CHAR)nNewOffset; 396 | if (nNewOffset < SCHAR_MIN || nNewOffset > SCHAR_MAX) { 397 | *m_plExtra = sizeof(ULONG) - 1; 398 | } 399 | break; 400 | case 2: 401 | *(SHORT*&)pvTargetAddr = (SHORT)nNewOffset; 402 | if (nNewOffset < SHRT_MIN || nNewOffset > SHRT_MAX) { 403 | *m_plExtra = sizeof(ULONG) - 2; 404 | } 405 | break; 406 | case 4: 407 | *(LONG*&)pvTargetAddr = (LONG)nNewOffset; 408 | if (nNewOffset < LONG_MIN || nNewOffset > LONG_MAX) { 409 | *m_plExtra = sizeof(ULONG) - 4; 410 | } 411 | break; 412 | case 8: 413 | *(LONG_PTR*&)pvTargetAddr = (LONG_PTR)nNewOffset; 414 | break; 415 | } 416 | ASSERT(pbDst + cbOp + nNewOffset == pbTarget); 417 | return pbTarget; 418 | } 419 | 420 | PBYTE CDetourDis::Invalid(REFCOPYENTRY pEntry, PBYTE pbDst, PBYTE pbSrc) 421 | { 422 | (void)pbDst; 423 | (void)pEntry; 424 | ASSERT(!"Invalid Instruction"); 425 | return pbSrc + 1; 426 | } 427 | 428 | ////////////////////////////////////////////////////// Individual Bytes Codes. 429 | // 430 | PBYTE CDetourDis::Copy0F(REFCOPYENTRY pEntry, PBYTE pbDst, PBYTE pbSrc) 431 | { 432 | CopyBytes(pEntry, pbDst, pbSrc); 433 | 434 | pEntry = &s_rceCopyTable0F[pbSrc[1]]; 435 | return (this->*pEntry->pfCopy)(pEntry, pbDst + 1, pbSrc + 1); 436 | } 437 | 438 | PBYTE CDetourDis::Copy66(REFCOPYENTRY pEntry, PBYTE pbDst, PBYTE pbSrc) 439 | { // Operand-size override prefix 440 | m_bOperandOverride = TRUE; 441 | return CopyBytesPrefix(pEntry, pbDst, pbSrc); 442 | } 443 | 444 | PBYTE CDetourDis::Copy67(REFCOPYENTRY pEntry, PBYTE pbDst, PBYTE pbSrc) 445 | { // Address size override prefix 446 | m_bAddressOverride = TRUE; 447 | return CopyBytesPrefix(pEntry, pbDst, pbSrc); 448 | } 449 | 450 | PBYTE CDetourDis::CopyF6(REFCOPYENTRY pEntry, PBYTE pbDst, PBYTE pbSrc) 451 | { 452 | (void)pEntry; 453 | 454 | // TEST BYTE /0 455 | if (0x00 == (0x38 & pbSrc[1])) { // reg(bits 543) of ModR/M == 0 456 | const COPYENTRY ce = { 0xf6, ENTRY_CopyBytes2Mod1 }; 457 | return (this->*ce.pfCopy)(&ce, pbDst, pbSrc); 458 | } 459 | // DIV /6 460 | // IDIV /7 461 | // IMUL /5 462 | // MUL /4 463 | // NEG /3 464 | // NOT /2 465 | 466 | const COPYENTRY ce = { 0xf6, ENTRY_CopyBytes2Mod }; 467 | return (this->*ce.pfCopy)(&ce, pbDst, pbSrc); 468 | } 469 | 470 | PBYTE CDetourDis::CopyF7(REFCOPYENTRY pEntry, PBYTE pbDst, PBYTE pbSrc) 471 | { 472 | (void)pEntry; 473 | 474 | // TEST WORD /0 475 | if (0x00 == (0x38 & pbSrc[1])) { // reg(bits 543) of ModR/M == 0 476 | const COPYENTRY ce = { 0xf7, ENTRY_CopyBytes2ModOperand }; 477 | return (this->*ce.pfCopy)(&ce, pbDst, pbSrc); 478 | } 479 | 480 | // DIV /6 481 | // IDIV /7 482 | // IMUL /5 483 | // MUL /4 484 | // NEG /3 485 | // NOT /2 486 | const COPYENTRY ce = { 0xf7, ENTRY_CopyBytes2Mod }; 487 | return (this->*ce.pfCopy)(&ce, pbDst, pbSrc); 488 | } 489 | 490 | PBYTE CDetourDis::CopyFF(REFCOPYENTRY pEntry, PBYTE pbDst, PBYTE pbSrc) 491 | { // CALL /2 492 | // CALL /3 493 | // INC /0 494 | // JMP /4 495 | // JMP /5 496 | // PUSH /6 497 | (void)pEntry; 498 | 499 | if (0x15 == pbSrc[1] || 0x25 == pbSrc[1]) { // CALL [], JMP [] 500 | #ifdef DETOURS_X64 501 | #error Feature not supported in this release. 502 | 503 | 504 | #else 505 | PBYTE *ppbTarget = *(PBYTE**)&pbSrc[2]; 506 | *m_ppbTarget = *ppbTarget; 507 | #endif 508 | } 509 | else if (0x10 == (0x38 & pbSrc[1]) || // CALL /2 --> reg(bits 543) of ModR/M == 010 510 | 0x18 == (0x38 & pbSrc[1]) || // CALL /3 --> reg(bits 543) of ModR/M == 011 511 | 0x20 == (0x38 & pbSrc[1]) || // JMP /4 --> reg(bits 543) of ModR/M == 100 512 | 0x28 == (0x38 & pbSrc[1]) // JMP /5 --> reg(bits 543) of ModR/M == 101 513 | ) { 514 | *m_ppbTarget = (PBYTE)DETOUR_INSTRUCTION_TARGET_DYNAMIC; 515 | } 516 | const COPYENTRY ce = { 0xff, ENTRY_CopyBytes2Mod }; 517 | return (this->*ce.pfCopy)(&ce, pbDst, pbSrc); 518 | } 519 | 520 | ///////////////////////////////////////////////////////// Disassembler Tables. 521 | // 522 | const BYTE CDetourDis::s_rbModRm[256] = { 523 | 0,0,0,0, SIB|1,RIP|4,0,0, 0,0,0,0, SIB|1,RIP|4,0,0, // 0x 524 | 0,0,0,0, SIB|1,RIP|4,0,0, 0,0,0,0, SIB|1,RIP|4,0,0, // 1x 525 | 0,0,0,0, SIB|1,RIP|4,0,0, 0,0,0,0, SIB|1,RIP|4,0,0, // 2x 526 | 0,0,0,0, SIB|1,RIP|4,0,0, 0,0,0,0, SIB|1,RIP|4,0,0, // 3x 527 | 1,1,1,1, 2,1,1,1, 1,1,1,1, 2,1,1,1, // 4x 528 | 1,1,1,1, 2,1,1,1, 1,1,1,1, 2,1,1,1, // 5x 529 | 1,1,1,1, 2,1,1,1, 1,1,1,1, 2,1,1,1, // 6x 530 | 1,1,1,1, 2,1,1,1, 1,1,1,1, 2,1,1,1, // 7x 531 | 4,4,4,4, 5,4,4,4, 4,4,4,4, 5,4,4,4, // 8x 532 | 4,4,4,4, 5,4,4,4, 4,4,4,4, 5,4,4,4, // 9x 533 | 4,4,4,4, 5,4,4,4, 4,4,4,4, 5,4,4,4, // Ax 534 | 4,4,4,4, 5,4,4,4, 4,4,4,4, 5,4,4,4, // Bx 535 | 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, // Cx 536 | 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, // Dx 537 | 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, // Ex 538 | 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0 // Fx 539 | }; 540 | 541 | const CDetourDis::COPYENTRY CDetourDis::s_rceCopyTable[257] = 542 | { 543 | { 0x00, ENTRY_CopyBytes2Mod }, // ADD /r 544 | { 0x01, ENTRY_CopyBytes2Mod }, // ADD /r 545 | { 0x02, ENTRY_CopyBytes2Mod }, // ADD /r 546 | { 0x03, ENTRY_CopyBytes2Mod }, // ADD /r 547 | { 0x04, ENTRY_CopyBytes2 }, // ADD ib 548 | { 0x05, ENTRY_CopyBytes3Or5 }, // ADD iw 549 | { 0x06, ENTRY_CopyBytes1 }, // PUSH 550 | { 0x07, ENTRY_CopyBytes1 }, // POP 551 | { 0x08, ENTRY_CopyBytes2Mod }, // OR /r 552 | { 0x09, ENTRY_CopyBytes2Mod }, // OR /r 553 | { 0x0A, ENTRY_CopyBytes2Mod }, // OR /r 554 | { 0x0B, ENTRY_CopyBytes2Mod }, // OR /r 555 | { 0x0C, ENTRY_CopyBytes2 }, // OR ib 556 | { 0x0D, ENTRY_CopyBytes3Or5 }, // OR iw 557 | { 0x0E, ENTRY_CopyBytes1 }, // PUSH 558 | { 0x0F, ENTRY_Copy0F }, // Extension Ops 559 | { 0x10, ENTRY_CopyBytes2Mod }, // ADC /r 560 | { 0x11, ENTRY_CopyBytes2Mod }, // ADC /r 561 | { 0x12, ENTRY_CopyBytes2Mod }, // ADC /r 562 | { 0x13, ENTRY_CopyBytes2Mod }, // ADC /r 563 | { 0x14, ENTRY_CopyBytes2 }, // ADC ib 564 | { 0x15, ENTRY_CopyBytes3Or5 }, // ADC id 565 | { 0x16, ENTRY_CopyBytes1 }, // PUSH 566 | { 0x17, ENTRY_CopyBytes1 }, // POP 567 | { 0x18, ENTRY_CopyBytes2Mod }, // SBB /r 568 | { 0x19, ENTRY_CopyBytes2Mod }, // SBB /r 569 | { 0x1A, ENTRY_CopyBytes2Mod }, // SBB /r 570 | { 0x1B, ENTRY_CopyBytes2Mod }, // SBB /r 571 | { 0x1C, ENTRY_CopyBytes2 }, // SBB ib 572 | { 0x1D, ENTRY_CopyBytes3Or5 }, // SBB id 573 | { 0x1E, ENTRY_CopyBytes1 }, // PUSH 574 | { 0x1F, ENTRY_CopyBytes1 }, // POP 575 | { 0x20, ENTRY_CopyBytes2Mod }, // AND /r 576 | { 0x21, ENTRY_CopyBytes2Mod }, // AND /r 577 | { 0x22, ENTRY_CopyBytes2Mod }, // AND /r 578 | { 0x23, ENTRY_CopyBytes2Mod }, // AND /r 579 | { 0x24, ENTRY_CopyBytes2 }, // AND ib 580 | { 0x25, ENTRY_CopyBytes3Or5 }, // AND id 581 | { 0x26, ENTRY_CopyBytesPrefix }, // ES prefix 582 | { 0x27, ENTRY_CopyBytes1 }, // DAA 583 | { 0x28, ENTRY_CopyBytes2Mod }, // SUB /r 584 | { 0x29, ENTRY_CopyBytes2Mod }, // SUB /r 585 | { 0x2A, ENTRY_CopyBytes2Mod }, // SUB /r 586 | { 0x2B, ENTRY_CopyBytes2Mod }, // SUB /r 587 | { 0x2C, ENTRY_CopyBytes2 }, // SUB ib 588 | { 0x2D, ENTRY_CopyBytes3Or5 }, // SUB id 589 | { 0x2E, ENTRY_CopyBytesPrefix }, // CS prefix 590 | { 0x2F, ENTRY_CopyBytes1 }, // DAS 591 | { 0x30, ENTRY_CopyBytes2Mod }, // XOR /r 592 | { 0x31, ENTRY_CopyBytes2Mod }, // XOR /r 593 | { 0x32, ENTRY_CopyBytes2Mod }, // XOR /r 594 | { 0x33, ENTRY_CopyBytes2Mod }, // XOR /r 595 | { 0x34, ENTRY_CopyBytes2 }, // XOR ib 596 | { 0x35, ENTRY_CopyBytes3Or5 }, // XOR id 597 | { 0x36, ENTRY_CopyBytesPrefix }, // SS prefix 598 | { 0x37, ENTRY_CopyBytes1 }, // AAA 599 | { 0x38, ENTRY_CopyBytes2Mod }, // CMP /r 600 | { 0x39, ENTRY_CopyBytes2Mod }, // CMP /r 601 | { 0x3A, ENTRY_CopyBytes2Mod }, // CMP /r 602 | { 0x3B, ENTRY_CopyBytes2Mod }, // CMP /r 603 | { 0x3C, ENTRY_CopyBytes2 }, // CMP ib 604 | { 0x3D, ENTRY_CopyBytes3Or5 }, // CMP id 605 | { 0x3E, ENTRY_CopyBytesPrefix }, // DS prefix 606 | { 0x3F, ENTRY_CopyBytes1 }, // AAS 607 | #ifdef DETOURS_X64 // For Rax Prefix 608 | #error Feature not supported in this release. 609 | 610 | 611 | 612 | 613 | 614 | 615 | 616 | 617 | 618 | 619 | 620 | 621 | 622 | 623 | 624 | #else 625 | { 0x40, ENTRY_CopyBytes1 }, // INC 626 | { 0x41, ENTRY_CopyBytes1 }, // INC 627 | { 0x42, ENTRY_CopyBytes1 }, // INC 628 | { 0x43, ENTRY_CopyBytes1 }, // INC 629 | { 0x44, ENTRY_CopyBytes1 }, // INC 630 | { 0x45, ENTRY_CopyBytes1 }, // INC 631 | { 0x46, ENTRY_CopyBytes1 }, // INC 632 | { 0x47, ENTRY_CopyBytes1 }, // INC 633 | { 0x48, ENTRY_CopyBytes1 }, // DEC 634 | { 0x49, ENTRY_CopyBytes1 }, // DEC 635 | { 0x4A, ENTRY_CopyBytes1 }, // DEC 636 | { 0x4B, ENTRY_CopyBytes1 }, // DEC 637 | { 0x4C, ENTRY_CopyBytes1 }, // DEC 638 | { 0x4D, ENTRY_CopyBytes1 }, // DEC 639 | { 0x4E, ENTRY_CopyBytes1 }, // DEC 640 | { 0x4F, ENTRY_CopyBytes1 }, // DEC 641 | #endif 642 | { 0x50, ENTRY_CopyBytes1 }, // PUSH 643 | { 0x51, ENTRY_CopyBytes1 }, // PUSH 644 | { 0x52, ENTRY_CopyBytes1 }, // PUSH 645 | { 0x53, ENTRY_CopyBytes1 }, // PUSH 646 | { 0x54, ENTRY_CopyBytes1 }, // PUSH 647 | { 0x55, ENTRY_CopyBytes1 }, // PUSH 648 | { 0x56, ENTRY_CopyBytes1 }, // PUSH 649 | { 0x57, ENTRY_CopyBytes1 }, // PUSH 650 | { 0x58, ENTRY_CopyBytes1 }, // POP 651 | { 0x59, ENTRY_CopyBytes1 }, // POP 652 | { 0x5A, ENTRY_CopyBytes1 }, // POP 653 | { 0x5B, ENTRY_CopyBytes1 }, // POP 654 | { 0x5C, ENTRY_CopyBytes1 }, // POP 655 | { 0x5D, ENTRY_CopyBytes1 }, // POP 656 | { 0x5E, ENTRY_CopyBytes1 }, // POP 657 | { 0x5F, ENTRY_CopyBytes1 }, // POP 658 | { 0x60, ENTRY_CopyBytes1 }, // PUSHAD 659 | { 0x61, ENTRY_CopyBytes1 }, // POPAD 660 | { 0x62, ENTRY_CopyBytes2Mod }, // BOUND /r 661 | { 0x63, ENTRY_CopyBytes2Mod }, // ARPL /r 662 | { 0x64, ENTRY_CopyBytesPrefix }, // FS prefix 663 | { 0x65, ENTRY_CopyBytesPrefix }, // GS prefix 664 | { 0x66, ENTRY_Copy66 }, // Operand Prefix 665 | { 0x67, ENTRY_Copy67 }, // Address Prefix 666 | { 0x68, ENTRY_CopyBytes3Or5 }, // PUSH 667 | { 0x69, ENTRY_CopyBytes2ModOperand }, // 668 | { 0x6A, ENTRY_CopyBytes2 }, // PUSH 669 | { 0x6B, ENTRY_CopyBytes2Mod1 }, // IMUL /r ib 670 | { 0x6C, ENTRY_CopyBytes1 }, // INS 671 | { 0x6D, ENTRY_CopyBytes1 }, // INS 672 | { 0x6E, ENTRY_CopyBytes1 }, // OUTS/OUTSB 673 | { 0x6F, ENTRY_CopyBytes1 }, // OUTS/OUTSW 674 | { 0x70, ENTRY_CopyBytes2Jump }, // JO // 0f80 675 | { 0x71, ENTRY_CopyBytes2Jump }, // JNO // 0f81 676 | { 0x72, ENTRY_CopyBytes2Jump }, // JB/JC/JNAE // 0f82 677 | { 0x73, ENTRY_CopyBytes2Jump }, // JAE/JNB/JNC // 0f83 678 | { 0x74, ENTRY_CopyBytes2Jump }, // JE/JZ // 0f84 679 | { 0x75, ENTRY_CopyBytes2Jump }, // JNE/JNZ // 0f85 680 | { 0x76, ENTRY_CopyBytes2Jump }, // JBE/JNA // 0f86 681 | { 0x77, ENTRY_CopyBytes2Jump }, // JA/JNBE // 0f87 682 | { 0x78, ENTRY_CopyBytes2Jump }, // JS // 0f88 683 | { 0x79, ENTRY_CopyBytes2Jump }, // JNS // 0f89 684 | { 0x7A, ENTRY_CopyBytes2Jump }, // JP/JPE // 0f8a 685 | { 0x7B, ENTRY_CopyBytes2Jump }, // JNP/JPO // 0f8b 686 | { 0x7C, ENTRY_CopyBytes2Jump }, // JL/JNGE // 0f8c 687 | { 0x7D, ENTRY_CopyBytes2Jump }, // JGE/JNL // 0f8d 688 | { 0x7E, ENTRY_CopyBytes2Jump }, // JLE/JNG // 0f8e 689 | { 0x7F, ENTRY_CopyBytes2Jump }, // JG/JNLE // 0f8f 690 | { 0x80, ENTRY_CopyBytes2Mod1 }, // ADC/2 ib, etc.s 691 | { 0x81, ENTRY_CopyBytes2ModOperand }, // 692 | { 0x82, ENTRY_CopyBytes2 }, // MOV al,x 693 | { 0x83, ENTRY_CopyBytes2Mod1 }, // ADC/2 ib, etc. 694 | { 0x84, ENTRY_CopyBytes2Mod }, // TEST /r 695 | { 0x85, ENTRY_CopyBytes2Mod }, // TEST /r 696 | { 0x86, ENTRY_CopyBytes2Mod }, // XCHG /r @todo 697 | { 0x87, ENTRY_CopyBytes2Mod }, // XCHG /r @todo 698 | { 0x88, ENTRY_CopyBytes2Mod }, // MOV /r 699 | { 0x89, ENTRY_CopyBytes2Mod }, // MOV /r 700 | { 0x8A, ENTRY_CopyBytes2Mod }, // MOV /r 701 | { 0x8B, ENTRY_CopyBytes2Mod }, // MOV /r 702 | { 0x8C, ENTRY_CopyBytes2Mod }, // MOV /r 703 | { 0x8D, ENTRY_CopyBytes2Mod }, // LEA /r 704 | { 0x8E, ENTRY_CopyBytes2Mod }, // MOV /r 705 | { 0x8F, ENTRY_CopyBytes2Mod }, // POP /0 706 | { 0x90, ENTRY_CopyBytes1 }, // NOP 707 | { 0x91, ENTRY_CopyBytes1 }, // XCHG 708 | { 0x92, ENTRY_CopyBytes1 }, // XCHG 709 | { 0x93, ENTRY_CopyBytes1 }, // XCHG 710 | { 0x94, ENTRY_CopyBytes1 }, // XCHG 711 | { 0x95, ENTRY_CopyBytes1 }, // XCHG 712 | { 0x96, ENTRY_CopyBytes1 }, // XCHG 713 | { 0x97, ENTRY_CopyBytes1 }, // XCHG 714 | { 0x98, ENTRY_CopyBytes1 }, // CWDE 715 | { 0x99, ENTRY_CopyBytes1 }, // CDQ 716 | { 0x9A, ENTRY_CopyBytes5Or7Dynamic }, // CALL cp 717 | { 0x9B, ENTRY_CopyBytes1 }, // WAIT/FWAIT 718 | { 0x9C, ENTRY_CopyBytes1 }, // PUSHFD 719 | { 0x9D, ENTRY_CopyBytes1 }, // POPFD 720 | { 0x9E, ENTRY_CopyBytes1 }, // SAHF 721 | { 0x9F, ENTRY_CopyBytes1 }, // LAHF 722 | { 0xA0, ENTRY_CopyBytes3Or5Address }, // MOV 723 | { 0xA1, ENTRY_CopyBytes3Or5Address }, // MOV 724 | { 0xA2, ENTRY_CopyBytes3Or5Address }, // MOV 725 | { 0xA3, ENTRY_CopyBytes3Or5Address }, // MOV 726 | { 0xA4, ENTRY_CopyBytes1 }, // MOVS 727 | { 0xA5, ENTRY_CopyBytes1 }, // MOVS/MOVSD 728 | { 0xA6, ENTRY_CopyBytes1 }, // CMPS/CMPSB 729 | { 0xA7, ENTRY_CopyBytes1 }, // CMPS/CMPSW 730 | { 0xA8, ENTRY_CopyBytes2 }, // TEST 731 | { 0xA9, ENTRY_CopyBytes3Or5 }, // TEST 732 | { 0xAA, ENTRY_CopyBytes1 }, // STOS/STOSB 733 | { 0xAB, ENTRY_CopyBytes1 }, // STOS/STOSW 734 | { 0xAC, ENTRY_CopyBytes1 }, // LODS/LODSB 735 | { 0xAD, ENTRY_CopyBytes1 }, // LODS/LODSW 736 | { 0xAE, ENTRY_CopyBytes1 }, // SCAS/SCASB 737 | { 0xAF, ENTRY_CopyBytes1 }, // SCAS/SCASD 738 | { 0xB0, ENTRY_CopyBytes2 }, // MOV B0+rb 739 | { 0xB1, ENTRY_CopyBytes2 }, // MOV B0+rb 740 | { 0xB2, ENTRY_CopyBytes2 }, // MOV B0+rb 741 | { 0xB3, ENTRY_CopyBytes2 }, // MOV B0+rb 742 | { 0xB4, ENTRY_CopyBytes2 }, // MOV B0+rb 743 | { 0xB5, ENTRY_CopyBytes2 }, // MOV B0+rb 744 | { 0xB6, ENTRY_CopyBytes2 }, // MOV B0+rb 745 | { 0xB7, ENTRY_CopyBytes2 }, // MOV B0+rb 746 | { 0xB8, ENTRY_CopyBytes3Or5Rax }, // MOV B8+rb 747 | { 0xB9, ENTRY_CopyBytes3Or5 }, // MOV B8+rb 748 | { 0xBA, ENTRY_CopyBytes3Or5 }, // MOV B8+rb 749 | { 0xBB, ENTRY_CopyBytes3Or5 }, // MOV B8+rb 750 | { 0xBC, ENTRY_CopyBytes3Or5 }, // MOV B8+rb 751 | { 0xBD, ENTRY_CopyBytes3Or5 }, // MOV B8+rb 752 | { 0xBE, ENTRY_CopyBytes3Or5 }, // MOV B8+rb 753 | { 0xBF, ENTRY_CopyBytes3Or5 }, // MOV B8+rb 754 | { 0xC0, ENTRY_CopyBytes2Mod1 }, // RCL/2 ib, etc. 755 | { 0xC1, ENTRY_CopyBytes2Mod1 }, // RCL/2 ib, etc. 756 | { 0xC2, ENTRY_CopyBytes3 }, // RET 757 | { 0xC3, ENTRY_CopyBytes1 }, // RET 758 | { 0xC4, ENTRY_CopyBytes2Mod }, // LES 759 | { 0xC5, ENTRY_CopyBytes2Mod }, // LDS 760 | { 0xC6, ENTRY_CopyBytes2Mod1 }, // MOV 761 | { 0xC7, ENTRY_CopyBytes2ModOperand }, // MOV 762 | { 0xC8, ENTRY_CopyBytes4 }, // ENTER 763 | { 0xC9, ENTRY_CopyBytes1 }, // LEAVE 764 | { 0xCA, ENTRY_CopyBytes3Dynamic }, // RET 765 | { 0xCB, ENTRY_CopyBytes1Dynamic }, // RET 766 | { 0xCC, ENTRY_CopyBytes1Dynamic }, // INT 3 767 | { 0xCD, ENTRY_CopyBytes2Dynamic }, // INT ib 768 | { 0xCE, ENTRY_CopyBytes1Dynamic }, // INTO 769 | { 0xCF, ENTRY_CopyBytes1Dynamic }, // IRET 770 | { 0xD0, ENTRY_CopyBytes2Mod }, // RCL/2, etc. 771 | { 0xD1, ENTRY_CopyBytes2Mod }, // RCL/2, etc. 772 | { 0xD2, ENTRY_CopyBytes2Mod }, // RCL/2, etc. 773 | { 0xD3, ENTRY_CopyBytes2Mod }, // RCL/2, etc. 774 | { 0xD4, ENTRY_CopyBytes2 }, // AAM 775 | { 0xD5, ENTRY_CopyBytes2 }, // AAD 776 | { 0xD6, ENTRY_Invalid }, // 777 | { 0xD7, ENTRY_CopyBytes1 }, // XLAT/XLATB 778 | { 0xD8, ENTRY_CopyBytes2Mod }, // FADD, etc. 779 | { 0xD9, ENTRY_CopyBytes2Mod }, // F2XM1, etc. 780 | { 0xDA, ENTRY_CopyBytes2Mod }, // FLADD, etc. 781 | { 0xDB, ENTRY_CopyBytes2Mod }, // FCLEX, etc. 782 | { 0xDC, ENTRY_CopyBytes2Mod }, // FADD/0, etc. 783 | { 0xDD, ENTRY_CopyBytes2Mod }, // FFREE, etc. 784 | { 0xDE, ENTRY_CopyBytes2Mod }, // FADDP, etc. 785 | { 0xDF, ENTRY_CopyBytes2Mod }, // FBLD/4, etc. 786 | { 0xE0, ENTRY_CopyBytes2CantJump }, // LOOPNE cb 787 | { 0xE1, ENTRY_CopyBytes2CantJump }, // LOOPE cb 788 | { 0xE2, ENTRY_CopyBytes2CantJump }, // LOOP cb 789 | { 0xE3, ENTRY_CopyBytes2Jump }, // JCXZ/JECXZ 790 | { 0xE4, ENTRY_CopyBytes2 }, // IN ib 791 | { 0xE5, ENTRY_CopyBytes2 }, // IN id 792 | { 0xE6, ENTRY_CopyBytes2 }, // OUT ib 793 | { 0xE7, ENTRY_CopyBytes2 }, // OUT ib 794 | { 0xE8, ENTRY_CopyBytes3Or5Target }, // CALL cd 795 | { 0xE9, ENTRY_CopyBytes3Or5Target }, // JMP cd 796 | { 0xEA, ENTRY_CopyBytes5Or7Dynamic }, // JMP cp 797 | { 0xEB, ENTRY_CopyBytes2Jump }, // JMP cb 798 | { 0xEC, ENTRY_CopyBytes1 }, // IN ib 799 | { 0xED, ENTRY_CopyBytes1 }, // IN id 800 | { 0xEE, ENTRY_CopyBytes1 }, // OUT 801 | { 0xEF, ENTRY_CopyBytes1 }, // OUT 802 | { 0xF0, ENTRY_CopyBytesPrefix }, // LOCK prefix 803 | { 0xF1, ENTRY_Invalid }, // 804 | { 0xF2, ENTRY_CopyBytesPrefix }, // REPNE prefix 805 | { 0xF3, ENTRY_CopyBytesPrefix }, // REPE prefix 806 | { 0xF4, ENTRY_CopyBytes1 }, // HLT 807 | { 0xF5, ENTRY_CopyBytes1 }, // CMC 808 | { 0xF6, ENTRY_CopyF6 }, // TEST/0, DIV/6 809 | { 0xF7, ENTRY_CopyF7 }, // TEST/0, DIV/6 810 | { 0xF8, ENTRY_CopyBytes1 }, // CLC 811 | { 0xF9, ENTRY_CopyBytes1 }, // STC 812 | { 0xFA, ENTRY_CopyBytes1 }, // CLI 813 | { 0xFB, ENTRY_CopyBytes1 }, // STI 814 | { 0xFC, ENTRY_CopyBytes1 }, // CLD 815 | { 0xFD, ENTRY_CopyBytes1 }, // STD 816 | { 0xFE, ENTRY_CopyBytes2Mod }, // DEC/1,INC/0 817 | { 0xFF, ENTRY_CopyFF }, // CALL/2 818 | { 0, ENTRY_End }, 819 | }; 820 | 821 | const CDetourDis::COPYENTRY CDetourDis::s_rceCopyTable0F[257] = 822 | { 823 | { 0x00, ENTRY_CopyBytes2Mod }, // LLDT/2, etc. 824 | { 0x01, ENTRY_CopyBytes2Mod }, // INVLPG/7, etc. 825 | { 0x02, ENTRY_CopyBytes2Mod }, // LAR/r 826 | { 0x03, ENTRY_CopyBytes2Mod }, // LSL/r 827 | { 0x04, ENTRY_Invalid }, // _04 828 | { 0x05, ENTRY_Invalid }, // _05 829 | { 0x06, ENTRY_CopyBytes2 }, // CLTS 830 | { 0x07, ENTRY_Invalid }, // _07 831 | { 0x08, ENTRY_CopyBytes2 }, // INVD 832 | { 0x09, ENTRY_CopyBytes2 }, // WBINVD 833 | { 0x0A, ENTRY_Invalid }, // _0A 834 | { 0x0B, ENTRY_CopyBytes2 }, // UD2 835 | { 0x0C, ENTRY_Invalid }, // _0C 836 | { 0x0D, ENTRY_CopyBytes2Mod }, // PREFETCH 837 | { 0x0E, ENTRY_CopyBytes2 }, // FEMMS 838 | { 0x0F, ENTRY_CopyBytes3Mod }, // 3DNow Opcodes 839 | { 0x10, ENTRY_CopyBytes2Mod }, // MOVSS MOVUPD MOVSD 840 | { 0x11, ENTRY_CopyBytes2Mod }, // MOVSS MOVUPD MOVSD 841 | { 0x12, ENTRY_CopyBytes2Mod }, // MOVLPD 842 | { 0x13, ENTRY_CopyBytes2Mod }, // MOVLPD 843 | { 0x14, ENTRY_CopyBytes2Mod }, // UNPCKLPD 844 | { 0x15, ENTRY_CopyBytes2Mod }, // UNPCKHPD 845 | { 0x16, ENTRY_CopyBytes2Mod }, // MOVHPD 846 | { 0x17, ENTRY_CopyBytes2Mod }, // MOVHPD 847 | { 0x18, ENTRY_CopyBytes2Mod }, // PREFETCHINTA... 848 | { 0x19, ENTRY_Invalid }, // _19 849 | { 0x1A, ENTRY_Invalid }, // _1A 850 | { 0x1B, ENTRY_Invalid }, // _1B 851 | { 0x1C, ENTRY_Invalid }, // _1C 852 | { 0x1D, ENTRY_Invalid }, // _1D 853 | { 0x1E, ENTRY_Invalid }, // _1E 854 | { 0x1F, ENTRY_CopyBytes2Mod }, // NOP/r 855 | { 0x20, ENTRY_CopyBytes2Mod }, // MOV/r 856 | { 0x21, ENTRY_CopyBytes2Mod }, // MOV/r 857 | { 0x22, ENTRY_CopyBytes2Mod }, // MOV/r 858 | { 0x23, ENTRY_CopyBytes2Mod }, // MOV/r 859 | { 0x24, ENTRY_Invalid }, // _24 860 | { 0x25, ENTRY_Invalid }, // _25 861 | { 0x26, ENTRY_Invalid }, // _26 862 | { 0x27, ENTRY_Invalid }, // _27 863 | { 0x28, ENTRY_CopyBytes2Mod }, // MOVAPS MOVAPD 864 | { 0x29, ENTRY_CopyBytes2Mod }, // MOVAPS MOVAPD 865 | { 0x2A, ENTRY_CopyBytes2Mod }, // CVPI2PS & 866 | { 0x2B, ENTRY_CopyBytes2Mod }, // MOVNTPS MOVNTPD 867 | { 0x2C, ENTRY_CopyBytes2Mod }, // CVTTPS2PI & 868 | { 0x2D, ENTRY_CopyBytes2Mod }, // CVTPS2PI & 869 | { 0x2E, ENTRY_CopyBytes2Mod }, // UCOMISS UCOMISD 870 | { 0x2F, ENTRY_CopyBytes2Mod }, // COMISS COMISD 871 | { 0x30, ENTRY_CopyBytes2 }, // WRMSR 872 | { 0x31, ENTRY_CopyBytes2 }, // RDTSC 873 | { 0x32, ENTRY_CopyBytes2 }, // RDMSR 874 | { 0x33, ENTRY_CopyBytes2 }, // RDPMC 875 | { 0x34, ENTRY_CopyBytes2 }, // SYSENTER 876 | { 0x35, ENTRY_CopyBytes2 }, // SYSEXIT 877 | { 0x36, ENTRY_Invalid }, // _36 878 | { 0x37, ENTRY_Invalid }, // _37 879 | { 0x38, ENTRY_Invalid }, // _38 880 | { 0x39, ENTRY_Invalid }, // _39 881 | { 0x3A, ENTRY_Invalid }, // _3A 882 | { 0x3B, ENTRY_Invalid }, // _3B 883 | { 0x3C, ENTRY_Invalid }, // _3C 884 | { 0x3D, ENTRY_Invalid }, // _3D 885 | { 0x3E, ENTRY_Invalid }, // _3E 886 | { 0x3F, ENTRY_Invalid }, // _3F 887 | { 0x40, ENTRY_CopyBytes2Mod }, // CMOVO (0F 40) 888 | { 0x41, ENTRY_CopyBytes2Mod }, // CMOVNO (0F 41) 889 | { 0x42, ENTRY_CopyBytes2Mod }, // CMOVB & CMOVNE (0F 42) 890 | { 0x43, ENTRY_CopyBytes2Mod }, // CMOVAE & CMOVNB (0F 43) 891 | { 0x44, ENTRY_CopyBytes2Mod }, // CMOVE & CMOVZ (0F 44) 892 | { 0x45, ENTRY_CopyBytes2Mod }, // CMOVNE & CMOVNZ (0F 45) 893 | { 0x46, ENTRY_CopyBytes2Mod }, // CMOVBE & CMOVNA (0F 46) 894 | { 0x47, ENTRY_CopyBytes2Mod }, // CMOVA & CMOVNBE (0F 47) 895 | { 0x48, ENTRY_CopyBytes2Mod }, // CMOVS (0F 48) 896 | { 0x49, ENTRY_CopyBytes2Mod }, // CMOVNS (0F 49) 897 | { 0x4A, ENTRY_CopyBytes2Mod }, // CMOVP & CMOVPE (0F 4A) 898 | { 0x4B, ENTRY_CopyBytes2Mod }, // CMOVNP & CMOVPO (0F 4B) 899 | { 0x4C, ENTRY_CopyBytes2Mod }, // CMOVL & CMOVNGE (0F 4C) 900 | { 0x4D, ENTRY_CopyBytes2Mod }, // CMOVGE & CMOVNL (0F 4D) 901 | { 0x4E, ENTRY_CopyBytes2Mod }, // CMOVLE & CMOVNG (0F 4E) 902 | { 0x4F, ENTRY_CopyBytes2Mod }, // CMOVG & CMOVNLE (0F 4F) 903 | { 0x50, ENTRY_CopyBytes2Mod }, // MOVMSKPD MOVMSKPD 904 | { 0x51, ENTRY_CopyBytes2Mod }, // SQRTPS & 905 | { 0x52, ENTRY_CopyBytes2Mod }, // RSQRTTS RSQRTPS 906 | { 0x53, ENTRY_CopyBytes2Mod }, // RCPPS RCPSS 907 | { 0x54, ENTRY_CopyBytes2Mod }, // ANDPS ANDPD 908 | { 0x55, ENTRY_CopyBytes2Mod }, // ANDNPS ANDNPD 909 | { 0x56, ENTRY_CopyBytes2Mod }, // ORPS ORPD 910 | { 0x57, ENTRY_CopyBytes2Mod }, // XORPS XORPD 911 | { 0x58, ENTRY_CopyBytes2Mod }, // ADDPS & 912 | { 0x59, ENTRY_CopyBytes2Mod }, // MULPS & 913 | { 0x5A, ENTRY_CopyBytes2Mod }, // CVTPS2PD & 914 | { 0x5B, ENTRY_CopyBytes2Mod }, // CVTDQ2PS & 915 | { 0x5C, ENTRY_CopyBytes2Mod }, // SUBPS & 916 | { 0x5D, ENTRY_CopyBytes2Mod }, // MINPS & 917 | { 0x5E, ENTRY_CopyBytes2Mod }, // DIVPS & 918 | { 0x5F, ENTRY_CopyBytes2Mod }, // MASPS & 919 | { 0x60, ENTRY_CopyBytes2Mod }, // PUNPCKLBW/r 920 | { 0x61, ENTRY_CopyBytes2Mod }, // PUNPCKLWD/r 921 | { 0x62, ENTRY_CopyBytes2Mod }, // PUNPCKLWD/r 922 | { 0x63, ENTRY_CopyBytes2Mod }, // PACKSSWB/r 923 | { 0x64, ENTRY_CopyBytes2Mod }, // PCMPGTB/r 924 | { 0x65, ENTRY_CopyBytes2Mod }, // PCMPGTW/r 925 | { 0x66, ENTRY_CopyBytes2Mod }, // PCMPGTD/r 926 | { 0x67, ENTRY_CopyBytes2Mod }, // PACKUSWB/r 927 | { 0x68, ENTRY_CopyBytes2Mod }, // PUNPCKHBW/r 928 | { 0x69, ENTRY_CopyBytes2Mod }, // PUNPCKHWD/r 929 | { 0x6A, ENTRY_CopyBytes2Mod }, // PUNPCKHDQ/r 930 | { 0x6B, ENTRY_CopyBytes2Mod }, // PACKSSDW/r 931 | { 0x6C, ENTRY_CopyBytes2Mod }, // PUNPCKLQDQ 932 | { 0x6D, ENTRY_CopyBytes2Mod }, // PUNPCKHQDQ 933 | { 0x6E, ENTRY_CopyBytes2Mod }, // MOVD/r 934 | { 0x6F, ENTRY_CopyBytes2Mod }, // MOV/r 935 | { 0x70, ENTRY_CopyBytes2Mod1 }, // PSHUFW/r ib 936 | { 0x71, ENTRY_CopyBytes2Mod1 }, // PSLLW/6 ib,PSRAW/4 ib,PSRLW/2 ib 937 | { 0x72, ENTRY_CopyBytes2Mod1 }, // PSLLD/6 ib,PSRAD/4 ib,PSRLD/2 ib 938 | { 0x73, ENTRY_CopyBytes2Mod1 }, // PSLLQ/6 ib,PSRLQ/2 ib 939 | { 0x74, ENTRY_CopyBytes2Mod }, // PCMPEQB/r 940 | { 0x75, ENTRY_CopyBytes2Mod }, // PCMPEQW/r 941 | { 0x76, ENTRY_CopyBytes2Mod }, // PCMPEQD/r 942 | { 0x77, ENTRY_CopyBytes2 }, // EMMS 943 | { 0x78, ENTRY_Invalid }, // _78 944 | { 0x79, ENTRY_Invalid }, // _79 945 | { 0x7A, ENTRY_Invalid }, // _7A 946 | { 0x7B, ENTRY_Invalid }, // _7B 947 | { 0x7C, ENTRY_Invalid }, // _7C 948 | { 0x7D, ENTRY_Invalid }, // _7D 949 | { 0x7E, ENTRY_CopyBytes2Mod }, // MOVD/r 950 | { 0x7F, ENTRY_CopyBytes2Mod }, // MOV/r 951 | { 0x80, ENTRY_CopyBytes3Or5Target }, // JO 952 | { 0x81, ENTRY_CopyBytes3Or5Target }, // JNO 953 | { 0x82, ENTRY_CopyBytes3Or5Target }, // JB,JC,JNAE 954 | { 0x83, ENTRY_CopyBytes3Or5Target }, // JAE,JNB,JNC 955 | { 0x84, ENTRY_CopyBytes3Or5Target }, // JE,JZ,JZ 956 | { 0x85, ENTRY_CopyBytes3Or5Target }, // JNE,JNZ 957 | { 0x86, ENTRY_CopyBytes3Or5Target }, // JBE,JNA 958 | { 0x87, ENTRY_CopyBytes3Or5Target }, // JA,JNBE 959 | { 0x88, ENTRY_CopyBytes3Or5Target }, // JS 960 | { 0x89, ENTRY_CopyBytes3Or5Target }, // JNS 961 | { 0x8A, ENTRY_CopyBytes3Or5Target }, // JP,JPE 962 | { 0x8B, ENTRY_CopyBytes3Or5Target }, // JNP,JPO 963 | { 0x8C, ENTRY_CopyBytes3Or5Target }, // JL,NGE 964 | { 0x8D, ENTRY_CopyBytes3Or5Target }, // JGE,JNL 965 | { 0x8E, ENTRY_CopyBytes3Or5Target }, // JLE,JNG 966 | { 0x8F, ENTRY_CopyBytes3Or5Target }, // JG,JNLE 967 | { 0x90, ENTRY_CopyBytes2Mod }, // CMOVO (0F 40) 968 | { 0x91, ENTRY_CopyBytes2Mod }, // CMOVNO (0F 41) 969 | { 0x92, ENTRY_CopyBytes2Mod }, // CMOVB & CMOVC & CMOVNAE (0F 42) 970 | { 0x93, ENTRY_CopyBytes2Mod }, // CMOVAE & CMOVNB & CMOVNC (0F 43) 971 | { 0x94, ENTRY_CopyBytes2Mod }, // CMOVE & CMOVZ (0F 44) 972 | { 0x95, ENTRY_CopyBytes2Mod }, // CMOVNE & CMOVNZ (0F 45) 973 | { 0x96, ENTRY_CopyBytes2Mod }, // CMOVBE & CMOVNA (0F 46) 974 | { 0x97, ENTRY_CopyBytes2Mod }, // CMOVA & CMOVNBE (0F 47) 975 | { 0x98, ENTRY_CopyBytes2Mod }, // CMOVS (0F 48) 976 | { 0x99, ENTRY_CopyBytes2Mod }, // CMOVNS (0F 49) 977 | { 0x9A, ENTRY_CopyBytes2Mod }, // CMOVP & CMOVPE (0F 4A) 978 | { 0x9B, ENTRY_CopyBytes2Mod }, // CMOVNP & CMOVPO (0F 4B) 979 | { 0x9C, ENTRY_CopyBytes2Mod }, // CMOVL & CMOVNGE (0F 4C) 980 | { 0x9D, ENTRY_CopyBytes2Mod }, // CMOVGE & CMOVNL (0F 4D) 981 | { 0x9E, ENTRY_CopyBytes2Mod }, // CMOVLE & CMOVNG (0F 4E) 982 | { 0x9F, ENTRY_CopyBytes2Mod }, // CMOVG & CMOVNLE (0F 4F) 983 | { 0xA0, ENTRY_CopyBytes2 }, // PUSH 984 | { 0xA1, ENTRY_CopyBytes2 }, // POP 985 | { 0xA2, ENTRY_CopyBytes2 }, // CPUID 986 | { 0xA3, ENTRY_CopyBytes2Mod }, // BT (0F A3) 987 | { 0xA4, ENTRY_CopyBytes2Mod1 }, // SHLD 988 | { 0xA5, ENTRY_CopyBytes2Mod }, // SHLD 989 | { 0xA6, ENTRY_Invalid }, // _A6 990 | { 0xA7, ENTRY_Invalid }, // _A7 991 | { 0xA8, ENTRY_CopyBytes2 }, // PUSH 992 | { 0xA9, ENTRY_CopyBytes2 }, // POP 993 | { 0xAA, ENTRY_CopyBytes2 }, // RSM 994 | { 0xAB, ENTRY_CopyBytes2Mod }, // BTS (0F AB) 995 | { 0xAC, ENTRY_CopyBytes2Mod1 }, // SHRD 996 | { 0xAD, ENTRY_CopyBytes2Mod }, // SHRD 997 | { 0xAE, ENTRY_CopyBytes2Mod }, // FXRSTOR/1,FXSAVE/0 998 | { 0xAF, ENTRY_CopyBytes2Mod }, // IMUL (0F AF) 999 | { 0xB0, ENTRY_CopyBytes2Mod }, // CMPXCHG (0F B0) 1000 | { 0xB1, ENTRY_CopyBytes2Mod }, // CMPXCHG (0F B1) 1001 | { 0xB2, ENTRY_CopyBytes2Mod }, // LSS/r 1002 | { 0xB3, ENTRY_CopyBytes2Mod }, // BTR (0F B3) 1003 | { 0xB4, ENTRY_CopyBytes2Mod }, // LFS/r 1004 | { 0xB5, ENTRY_CopyBytes2Mod }, // LGS/r 1005 | { 0xB6, ENTRY_CopyBytes2Mod }, // MOVZX/r 1006 | { 0xB7, ENTRY_CopyBytes2Mod }, // MOVZX/r 1007 | { 0xB8, ENTRY_Invalid }, // _B8 1008 | { 0xB9, ENTRY_Invalid }, // _B9 1009 | { 0xBA, ENTRY_CopyBytes2Mod1 }, // BT & BTC & BTR & BTS (0F BA) 1010 | { 0xBB, ENTRY_CopyBytes2Mod }, // BTC (0F BB) 1011 | { 0xBC, ENTRY_CopyBytes2Mod }, // BSF (0F BC) 1012 | { 0xBD, ENTRY_CopyBytes2Mod }, // BSR (0F BD) 1013 | { 0xBE, ENTRY_CopyBytes2Mod }, // MOVSX/r 1014 | { 0xBF, ENTRY_CopyBytes2Mod }, // MOVSX/r 1015 | { 0xC0, ENTRY_CopyBytes2Mod }, // XADD/r 1016 | { 0xC1, ENTRY_CopyBytes2Mod }, // XADD/r 1017 | { 0xC2, ENTRY_CopyBytes2Mod }, // CMPPS & 1018 | { 0xC3, ENTRY_CopyBytes2Mod }, // MOVNTI 1019 | { 0xC4, ENTRY_CopyBytes2Mod1 }, // PINSRW /r ib 1020 | { 0xC5, ENTRY_CopyBytes2Mod1 }, // PEXTRW /r ib 1021 | { 0xC6, ENTRY_CopyBytes2Mod1 }, // SHUFPS & SHUFPD 1022 | { 0xC7, ENTRY_CopyBytes2Mod }, // CMPXCHG8B (0F C7) 1023 | { 0xC8, ENTRY_CopyBytes2 }, // BSWAP 0F C8 + rd 1024 | { 0xC9, ENTRY_CopyBytes2 }, // BSWAP 0F C8 + rd 1025 | { 0xCA, ENTRY_CopyBytes2 }, // BSWAP 0F C8 + rd 1026 | { 0xCB, ENTRY_CopyBytes2 }, //CVTPD2PI BSWAP 0F C8 + rd 1027 | { 0xCC, ENTRY_CopyBytes2 }, // BSWAP 0F C8 + rd 1028 | { 0xCD, ENTRY_CopyBytes2 }, // BSWAP 0F C8 + rd 1029 | { 0xCE, ENTRY_CopyBytes2 }, // BSWAP 0F C8 + rd 1030 | { 0xCF, ENTRY_CopyBytes2 }, // BSWAP 0F C8 + rd 1031 | { 0xD0, ENTRY_Invalid }, // _D0 1032 | { 0xD1, ENTRY_CopyBytes2Mod }, // PSRLW/r 1033 | { 0xD2, ENTRY_CopyBytes2Mod }, // PSRLD/r 1034 | { 0xD3, ENTRY_CopyBytes2Mod }, // PSRLQ/r 1035 | { 0xD4, ENTRY_CopyBytes2Mod }, // PADDQ 1036 | { 0xD5, ENTRY_CopyBytes2Mod }, // PMULLW/r 1037 | { 0xD6, ENTRY_CopyBytes2Mod }, // MOVDQ2Q / MOVQ2DQ 1038 | { 0xD7, ENTRY_CopyBytes2Mod }, // PMOVMSKB/r 1039 | { 0xD8, ENTRY_CopyBytes2Mod }, // PSUBUSB/r 1040 | { 0xD9, ENTRY_CopyBytes2Mod }, // PSUBUSW/r 1041 | { 0xDA, ENTRY_CopyBytes2Mod }, // PMINUB/r 1042 | { 0xDB, ENTRY_CopyBytes2Mod }, // PAND/r 1043 | { 0xDC, ENTRY_CopyBytes2Mod }, // PADDUSB/r 1044 | { 0xDD, ENTRY_CopyBytes2Mod }, // PADDUSW/r 1045 | { 0xDE, ENTRY_CopyBytes2Mod }, // PMAXUB/r 1046 | { 0xDF, ENTRY_CopyBytes2Mod }, // PANDN/r 1047 | { 0xE0, ENTRY_CopyBytes2Mod }, // PAVGB 1048 | { 0xE1, ENTRY_CopyBytes2Mod }, // PSRAW/r 1049 | { 0xE2, ENTRY_CopyBytes2Mod }, // PSRAD/r 1050 | { 0xE3, ENTRY_CopyBytes2Mod }, // PAVGW 1051 | { 0xE4, ENTRY_CopyBytes2Mod }, // PMULHUW/r 1052 | { 0xE5, ENTRY_CopyBytes2Mod }, // PMULHW/r 1053 | { 0xE6, ENTRY_CopyBytes2Mod }, // CTDQ2PD & 1054 | { 0xE7, ENTRY_CopyBytes2Mod }, // MOVNTQ 1055 | { 0xE8, ENTRY_CopyBytes2Mod }, // PSUBB/r 1056 | { 0xE9, ENTRY_CopyBytes2Mod }, // PSUBW/r 1057 | { 0xEA, ENTRY_CopyBytes2Mod }, // PMINSW/r 1058 | { 0xEB, ENTRY_CopyBytes2Mod }, // POR/r 1059 | { 0xEC, ENTRY_CopyBytes2Mod }, // PADDSB/r 1060 | { 0xED, ENTRY_CopyBytes2Mod }, // PADDSW/r 1061 | { 0xEE, ENTRY_CopyBytes2Mod }, // PMAXSW /r 1062 | { 0xEF, ENTRY_CopyBytes2Mod }, // PXOR/r 1063 | { 0xF0, ENTRY_Invalid }, // _F0 1064 | { 0xF1, ENTRY_CopyBytes2Mod }, // PSLLW/r 1065 | { 0xF2, ENTRY_CopyBytes2Mod }, // PSLLD/r 1066 | { 0xF3, ENTRY_CopyBytes2Mod }, // PSLLQ/r 1067 | { 0xF4, ENTRY_CopyBytes2Mod }, // PMULUDQ/r 1068 | { 0xF5, ENTRY_CopyBytes2Mod }, // PMADDWD/r 1069 | { 0xF6, ENTRY_CopyBytes2Mod }, // PSADBW/r 1070 | { 0xF7, ENTRY_CopyBytes2Mod }, // MASKMOVQ 1071 | { 0xF8, ENTRY_CopyBytes2Mod }, // PSUBB/r 1072 | { 0xF9, ENTRY_CopyBytes2Mod }, // PSUBW/r 1073 | { 0xFA, ENTRY_CopyBytes2Mod }, // PSUBD/r 1074 | { 0xFB, ENTRY_CopyBytes2Mod }, // FSUBQ/r 1075 | { 0xFC, ENTRY_CopyBytes2Mod }, // PADDB/r 1076 | { 0xFD, ENTRY_CopyBytes2Mod }, // PADDW/r 1077 | { 0xFE, ENTRY_CopyBytes2Mod }, // PADDD/r 1078 | { 0xFF, ENTRY_Invalid }, // _FF 1079 | { 0, ENTRY_End }, 1080 | }; 1081 | 1082 | BOOL CDetourDis::SanityCheckSystem() 1083 | { 1084 | ULONG n = 0; 1085 | for (; n < 256; n++) { 1086 | REFCOPYENTRY pEntry = &s_rceCopyTable[n]; 1087 | 1088 | if (n != pEntry->nOpcode) { 1089 | ASSERT(n == pEntry->nOpcode); 1090 | return FALSE; 1091 | } 1092 | } 1093 | if (s_rceCopyTable[256].pfCopy != NULL) { 1094 | ASSERT(!"Missing end marker."); 1095 | return FALSE; 1096 | } 1097 | 1098 | for (n = 0; n < 256; n++) { 1099 | REFCOPYENTRY pEntry = &s_rceCopyTable0F[n]; 1100 | 1101 | if (n != pEntry->nOpcode) { 1102 | ASSERT(n == pEntry->nOpcode); 1103 | return FALSE; 1104 | } 1105 | } 1106 | if (s_rceCopyTable0F[256].pfCopy != NULL) { 1107 | ASSERT(!"Missing end marker."); 1108 | return FALSE; 1109 | } 1110 | 1111 | return TRUE; 1112 | } 1113 | #endif // defined(DETOURS_X64) || defined(DETOURS_X86) 1114 | 1115 | /////////////////////////////////////////////////////////// IA64 Disassembler. 1116 | // 1117 | #ifdef DETOURS_IA64 1118 | #error Feature not supported in this release. 1119 | 1120 | 1121 | 1122 | 1123 | 1124 | 1125 | 1126 | 1127 | 1128 | 1129 | 1130 | 1131 | 1132 | 1133 | 1134 | 1135 | 1136 | 1137 | 1138 | 1139 | 1140 | 1141 | 1142 | 1143 | 1144 | 1145 | 1146 | 1147 | 1148 | 1149 | 1150 | 1151 | 1152 | 1153 | 1154 | 1155 | 1156 | 1157 | 1158 | 1159 | 1160 | 1161 | 1162 | 1163 | 1164 | 1165 | 1166 | 1167 | 1168 | 1169 | 1170 | 1171 | 1172 | 1173 | 1174 | 1175 | 1176 | 1177 | 1178 | 1179 | 1180 | 1181 | 1182 | 1183 | 1184 | 1185 | 1186 | 1187 | 1188 | 1189 | 1190 | 1191 | 1192 | 1193 | 1194 | 1195 | 1196 | 1197 | 1198 | 1199 | 1200 | 1201 | 1202 | 1203 | 1204 | 1205 | 1206 | 1207 | 1208 | 1209 | 1210 | 1211 | 1212 | 1213 | 1214 | 1215 | 1216 | 1217 | 1218 | 1219 | 1220 | 1221 | 1222 | 1223 | 1224 | 1225 | 1226 | 1227 | 1228 | 1229 | 1230 | 1231 | 1232 | 1233 | 1234 | 1235 | 1236 | 1237 | 1238 | 1239 | 1240 | 1241 | 1242 | 1243 | 1244 | 1245 | 1246 | 1247 | 1248 | 1249 | 1250 | 1251 | 1252 | 1253 | 1254 | 1255 | 1256 | 1257 | 1258 | 1259 | 1260 | 1261 | 1262 | 1263 | 1264 | 1265 | 1266 | 1267 | 1268 | 1269 | 1270 | 1271 | 1272 | 1273 | 1274 | 1275 | 1276 | 1277 | 1278 | 1279 | 1280 | 1281 | 1282 | 1283 | 1284 | 1285 | 1286 | 1287 | 1288 | 1289 | 1290 | 1291 | 1292 | 1293 | 1294 | 1295 | 1296 | 1297 | 1298 | 1299 | 1300 | 1301 | 1302 | 1303 | 1304 | 1305 | 1306 | 1307 | 1308 | 1309 | 1310 | 1311 | 1312 | 1313 | 1314 | 1315 | 1316 | 1317 | 1318 | 1319 | 1320 | 1321 | 1322 | 1323 | 1324 | 1325 | 1326 | 1327 | 1328 | 1329 | 1330 | 1331 | 1332 | 1333 | 1334 | 1335 | 1336 | 1337 | 1338 | 1339 | 1340 | 1341 | 1342 | 1343 | 1344 | 1345 | 1346 | 1347 | 1348 | 1349 | 1350 | 1351 | 1352 | 1353 | 1354 | 1355 | 1356 | 1357 | 1358 | 1359 | 1360 | 1361 | 1362 | 1363 | 1364 | 1365 | 1366 | 1367 | 1368 | 1369 | 1370 | 1371 | 1372 | 1373 | 1374 | 1375 | 1376 | 1377 | 1378 | 1379 | 1380 | 1381 | 1382 | 1383 | 1384 | 1385 | 1386 | 1387 | 1388 | 1389 | 1390 | 1391 | 1392 | 1393 | 1394 | 1395 | 1396 | 1397 | 1398 | 1399 | 1400 | 1401 | 1402 | 1403 | 1404 | 1405 | 1406 | 1407 | 1408 | 1409 | 1410 | 1411 | 1412 | 1413 | 1414 | 1415 | 1416 | 1417 | 1418 | 1419 | 1420 | 1421 | 1422 | 1423 | 1424 | 1425 | 1426 | 1427 | 1428 | 1429 | 1430 | 1431 | 1432 | 1433 | 1434 | 1435 | 1436 | 1437 | 1438 | 1439 | 1440 | 1441 | 1442 | 1443 | 1444 | 1445 | 1446 | 1447 | 1448 | 1449 | 1450 | 1451 | 1452 | 1453 | 1454 | 1455 | 1456 | 1457 | 1458 | 1459 | 1460 | 1461 | 1462 | 1463 | 1464 | 1465 | 1466 | 1467 | 1468 | 1469 | 1470 | 1471 | 1472 | 1473 | 1474 | 1475 | 1476 | 1477 | 1478 | 1479 | 1480 | 1481 | 1482 | 1483 | 1484 | 1485 | 1486 | 1487 | 1488 | 1489 | 1490 | 1491 | 1492 | 1493 | 1494 | 1495 | 1496 | 1497 | 1498 | 1499 | 1500 | 1501 | 1502 | 1503 | 1504 | 1505 | 1506 | 1507 | 1508 | 1509 | 1510 | 1511 | 1512 | 1513 | 1514 | 1515 | 1516 | 1517 | 1518 | 1519 | 1520 | 1521 | 1522 | 1523 | 1524 | 1525 | 1526 | 1527 | 1528 | 1529 | 1530 | 1531 | 1532 | 1533 | 1534 | 1535 | 1536 | 1537 | 1538 | 1539 | 1540 | 1541 | 1542 | 1543 | 1544 | 1545 | 1546 | 1547 | 1548 | 1549 | 1550 | 1551 | 1552 | 1553 | 1554 | 1555 | 1556 | 1557 | 1558 | 1559 | 1560 | 1561 | 1562 | 1563 | 1564 | 1565 | 1566 | 1567 | 1568 | 1569 | 1570 | 1571 | 1572 | 1573 | 1574 | 1575 | 1576 | 1577 | 1578 | 1579 | 1580 | 1581 | 1582 | 1583 | 1584 | 1585 | 1586 | 1587 | 1588 | 1589 | 1590 | 1591 | 1592 | #endif // DETOURS_IA64 1593 | 1594 | #ifdef DETOURS_ARM 1595 | #error Feature not supported in this release. 1596 | 1597 | 1598 | 1599 | 1600 | 1601 | 1602 | 1603 | 1604 | 1605 | 1606 | 1607 | 1608 | 1609 | 1610 | 1611 | 1612 | 1613 | 1614 | 1615 | 1616 | 1617 | 1618 | 1619 | 1620 | 1621 | 1622 | 1623 | 1624 | 1625 | 1626 | 1627 | 1628 | 1629 | 1630 | 1631 | 1632 | 1633 | 1634 | 1635 | 1636 | 1637 | 1638 | 1639 | 1640 | 1641 | 1642 | 1643 | 1644 | 1645 | 1646 | 1647 | 1648 | 1649 | 1650 | 1651 | 1652 | 1653 | 1654 | 1655 | 1656 | 1657 | 1658 | 1659 | 1660 | 1661 | 1662 | 1663 | 1664 | 1665 | 1666 | 1667 | 1668 | 1669 | 1670 | 1671 | 1672 | 1673 | 1674 | 1675 | 1676 | 1677 | 1678 | 1679 | 1680 | 1681 | 1682 | 1683 | 1684 | 1685 | 1686 | 1687 | 1688 | 1689 | 1690 | 1691 | 1692 | 1693 | 1694 | 1695 | 1696 | 1697 | 1698 | 1699 | 1700 | 1701 | 1702 | 1703 | 1704 | 1705 | 1706 | 1707 | 1708 | 1709 | 1710 | 1711 | 1712 | 1713 | 1714 | 1715 | 1716 | 1717 | 1718 | 1719 | 1720 | 1721 | 1722 | 1723 | 1724 | 1725 | 1726 | 1727 | 1728 | 1729 | 1730 | 1731 | 1732 | 1733 | 1734 | 1735 | 1736 | 1737 | 1738 | 1739 | 1740 | 1741 | 1742 | 1743 | 1744 | 1745 | 1746 | 1747 | 1748 | 1749 | 1750 | 1751 | 1752 | 1753 | 1754 | 1755 | 1756 | 1757 | 1758 | 1759 | 1760 | 1761 | 1762 | 1763 | 1764 | 1765 | 1766 | 1767 | 1768 | 1769 | 1770 | 1771 | 1772 | 1773 | 1774 | 1775 | 1776 | 1777 | 1778 | 1779 | 1780 | 1781 | 1782 | 1783 | 1784 | 1785 | 1786 | 1787 | 1788 | 1789 | 1790 | 1791 | 1792 | 1793 | 1794 | 1795 | 1796 | 1797 | 1798 | 1799 | 1800 | 1801 | 1802 | 1803 | 1804 | 1805 | 1806 | 1807 | 1808 | 1809 | 1810 | 1811 | 1812 | 1813 | 1814 | 1815 | 1816 | 1817 | 1818 | 1819 | 1820 | 1821 | 1822 | 1823 | 1824 | 1825 | 1826 | 1827 | 1828 | 1829 | 1830 | 1831 | 1832 | 1833 | 1834 | 1835 | 1836 | 1837 | 1838 | 1839 | 1840 | 1841 | 1842 | 1843 | 1844 | 1845 | 1846 | 1847 | 1848 | 1849 | 1850 | 1851 | 1852 | 1853 | 1854 | 1855 | 1856 | 1857 | 1858 | 1859 | 1860 | 1861 | 1862 | 1863 | 1864 | 1865 | 1866 | 1867 | 1868 | 1869 | 1870 | 1871 | 1872 | 1873 | 1874 | 1875 | 1876 | 1877 | 1878 | 1879 | 1880 | 1881 | 1882 | 1883 | 1884 | 1885 | 1886 | 1887 | 1888 | 1889 | 1890 | 1891 | 1892 | 1893 | 1894 | 1895 | 1896 | 1897 | 1898 | 1899 | 1900 | 1901 | 1902 | 1903 | 1904 | 1905 | 1906 | 1907 | 1908 | 1909 | 1910 | 1911 | 1912 | 1913 | 1914 | 1915 | 1916 | 1917 | 1918 | 1919 | 1920 | 1921 | 1922 | 1923 | 1924 | 1925 | 1926 | 1927 | 1928 | 1929 | 1930 | 1931 | 1932 | 1933 | 1934 | 1935 | 1936 | 1937 | 1938 | 1939 | 1940 | 1941 | 1942 | 1943 | 1944 | 1945 | 1946 | 1947 | 1948 | 1949 | 1950 | 1951 | 1952 | 1953 | 1954 | 1955 | 1956 | 1957 | 1958 | 1959 | 1960 | 1961 | 1962 | 1963 | 1964 | 1965 | 1966 | 1967 | 1968 | 1969 | 1970 | 1971 | 1972 | 1973 | 1974 | 1975 | 1976 | 1977 | 1978 | 1979 | 1980 | 1981 | 1982 | 1983 | 1984 | 1985 | 1986 | 1987 | 1988 | 1989 | 1990 | 1991 | 1992 | 1993 | 1994 | 1995 | 1996 | 1997 | 1998 | 1999 | 2000 | 2001 | 2002 | 2003 | 2004 | 2005 | 2006 | 2007 | 2008 | 2009 | 2010 | 2011 | 2012 | 2013 | 2014 | 2015 | 2016 | 2017 | 2018 | 2019 | 2020 | 2021 | 2022 | 2023 | 2024 | 2025 | 2026 | 2027 | 2028 | 2029 | 2030 | 2031 | 2032 | 2033 | 2034 | 2035 | 2036 | 2037 | 2038 | 2039 | 2040 | 2041 | 2042 | 2043 | 2044 | 2045 | 2046 | 2047 | 2048 | 2049 | 2050 | 2051 | 2052 | 2053 | 2054 | 2055 | 2056 | 2057 | 2058 | 2059 | 2060 | 2061 | 2062 | 2063 | 2064 | 2065 | 2066 | 2067 | 2068 | 2069 | 2070 | 2071 | 2072 | 2073 | 2074 | 2075 | 2076 | 2077 | 2078 | 2079 | 2080 | 2081 | 2082 | 2083 | 2084 | 2085 | 2086 | 2087 | 2088 | 2089 | 2090 | 2091 | 2092 | 2093 | 2094 | 2095 | 2096 | 2097 | 2098 | 2099 | 2100 | 2101 | 2102 | 2103 | 2104 | 2105 | 2106 | 2107 | 2108 | 2109 | 2110 | 2111 | 2112 | 2113 | 2114 | 2115 | 2116 | 2117 | 2118 | 2119 | 2120 | 2121 | 2122 | 2123 | 2124 | 2125 | 2126 | 2127 | 2128 | 2129 | 2130 | 2131 | 2132 | 2133 | 2134 | 2135 | 2136 | 2137 | 2138 | 2139 | 2140 | 2141 | 2142 | 2143 | 2144 | 2145 | 2146 | 2147 | 2148 | 2149 | 2150 | 2151 | 2152 | 2153 | 2154 | 2155 | 2156 | 2157 | 2158 | 2159 | 2160 | 2161 | 2162 | 2163 | 2164 | 2165 | 2166 | 2167 | 2168 | 2169 | 2170 | 2171 | 2172 | 2173 | 2174 | 2175 | 2176 | 2177 | 2178 | 2179 | 2180 | 2181 | 2182 | 2183 | 2184 | 2185 | 2186 | 2187 | 2188 | 2189 | 2190 | 2191 | 2192 | 2193 | 2194 | 2195 | 2196 | 2197 | 2198 | 2199 | 2200 | 2201 | 2202 | 2203 | 2204 | 2205 | 2206 | 2207 | 2208 | 2209 | 2210 | 2211 | 2212 | 2213 | 2214 | 2215 | 2216 | 2217 | 2218 | 2219 | 2220 | 2221 | 2222 | 2223 | 2224 | 2225 | 2226 | 2227 | 2228 | 2229 | 2230 | 2231 | 2232 | 2233 | 2234 | 2235 | 2236 | 2237 | 2238 | 2239 | 2240 | 2241 | 2242 | 2243 | 2244 | 2245 | 2246 | 2247 | 2248 | 2249 | 2250 | 2251 | 2252 | 2253 | 2254 | 2255 | 2256 | 2257 | 2258 | 2259 | 2260 | 2261 | 2262 | 2263 | 2264 | 2265 | 2266 | 2267 | 2268 | 2269 | 2270 | 2271 | 2272 | 2273 | 2274 | 2275 | 2276 | 2277 | 2278 | 2279 | 2280 | 2281 | 2282 | 2283 | 2284 | 2285 | 2286 | 2287 | 2288 | 2289 | 2290 | 2291 | 2292 | 2293 | 2294 | 2295 | 2296 | 2297 | 2298 | 2299 | 2300 | 2301 | 2302 | 2303 | 2304 | 2305 | 2306 | 2307 | 2308 | 2309 | 2310 | 2311 | 2312 | 2313 | 2314 | 2315 | 2316 | 2317 | 2318 | 2319 | 2320 | 2321 | 2322 | 2323 | 2324 | 2325 | 2326 | 2327 | 2328 | 2329 | 2330 | 2331 | 2332 | 2333 | 2334 | 2335 | 2336 | 2337 | 2338 | 2339 | 2340 | 2341 | 2342 | 2343 | 2344 | 2345 | 2346 | 2347 | 2348 | 2349 | 2350 | 2351 | 2352 | 2353 | 2354 | 2355 | 2356 | 2357 | 2358 | 2359 | 2360 | 2361 | 2362 | 2363 | 2364 | 2365 | 2366 | 2367 | 2368 | 2369 | 2370 | 2371 | 2372 | 2373 | 2374 | 2375 | 2376 | 2377 | 2378 | 2379 | 2380 | 2381 | 2382 | 2383 | 2384 | 2385 | 2386 | 2387 | 2388 | 2389 | 2390 | 2391 | 2392 | 2393 | 2394 | 2395 | 2396 | 2397 | 2398 | 2399 | 2400 | 2401 | 2402 | 2403 | 2404 | 2405 | 2406 | 2407 | 2408 | 2409 | 2410 | 2411 | 2412 | 2413 | 2414 | 2415 | 2416 | 2417 | 2418 | 2419 | 2420 | 2421 | 2422 | 2423 | 2424 | 2425 | 2426 | 2427 | 2428 | 2429 | 2430 | 2431 | 2432 | 2433 | 2434 | 2435 | 2436 | 2437 | 2438 | 2439 | 2440 | 2441 | 2442 | 2443 | 2444 | 2445 | 2446 | 2447 | 2448 | 2449 | 2450 | 2451 | 2452 | 2453 | 2454 | 2455 | 2456 | 2457 | 2458 | 2459 | 2460 | 2461 | 2462 | 2463 | 2464 | 2465 | 2466 | 2467 | 2468 | 2469 | 2470 | 2471 | 2472 | 2473 | 2474 | 2475 | 2476 | 2477 | 2478 | 2479 | 2480 | 2481 | 2482 | 2483 | 2484 | 2485 | 2486 | 2487 | 2488 | 2489 | 2490 | 2491 | 2492 | 2493 | 2494 | 2495 | 2496 | 2497 | 2498 | 2499 | 2500 | 2501 | 2502 | 2503 | 2504 | 2505 | 2506 | 2507 | 2508 | 2509 | 2510 | 2511 | 2512 | 2513 | 2514 | 2515 | 2516 | 2517 | 2518 | 2519 | 2520 | 2521 | 2522 | 2523 | 2524 | 2525 | 2526 | 2527 | 2528 | 2529 | 2530 | 2531 | 2532 | 2533 | 2534 | 2535 | 2536 | 2537 | 2538 | 2539 | 2540 | 2541 | 2542 | 2543 | 2544 | 2545 | 2546 | 2547 | 2548 | 2549 | 2550 | 2551 | 2552 | 2553 | 2554 | 2555 | 2556 | 2557 | 2558 | 2559 | 2560 | 2561 | 2562 | 2563 | 2564 | 2565 | 2566 | 2567 | 2568 | 2569 | 2570 | 2571 | 2572 | 2573 | 2574 | 2575 | 2576 | 2577 | 2578 | 2579 | 2580 | 2581 | 2582 | 2583 | 2584 | 2585 | 2586 | 2587 | 2588 | 2589 | 2590 | 2591 | 2592 | 2593 | 2594 | 2595 | 2596 | 2597 | 2598 | 2599 | 2600 | 2601 | 2602 | 2603 | 2604 | 2605 | 2606 | 2607 | 2608 | 2609 | 2610 | 2611 | 2612 | 2613 | 2614 | 2615 | 2616 | 2617 | 2618 | 2619 | 2620 | 2621 | 2622 | 2623 | 2624 | 2625 | 2626 | 2627 | 2628 | 2629 | 2630 | 2631 | 2632 | 2633 | 2634 | 2635 | 2636 | 2637 | 2638 | 2639 | 2640 | 2641 | 2642 | 2643 | 2644 | 2645 | 2646 | 2647 | 2648 | 2649 | 2650 | 2651 | 2652 | 2653 | 2654 | 2655 | 2656 | 2657 | 2658 | 2659 | 2660 | 2661 | 2662 | 2663 | 2664 | 2665 | 2666 | 2667 | 2668 | 2669 | 2670 | 2671 | 2672 | 2673 | 2674 | 2675 | 2676 | 2677 | 2678 | 2679 | 2680 | 2681 | 2682 | 2683 | 2684 | 2685 | 2686 | 2687 | 2688 | 2689 | 2690 | 2691 | 2692 | 2693 | 2694 | 2695 | 2696 | 2697 | 2698 | 2699 | 2700 | 2701 | 2702 | 2703 | 2704 | 2705 | 2706 | 2707 | 2708 | 2709 | 2710 | 2711 | 2712 | 2713 | 2714 | 2715 | 2716 | 2717 | 2718 | 2719 | 2720 | 2721 | 2722 | 2723 | 2724 | 2725 | 2726 | 2727 | 2728 | 2729 | 2730 | 2731 | 2732 | 2733 | 2734 | 2735 | 2736 | 2737 | 2738 | 2739 | 2740 | 2741 | 2742 | 2743 | 2744 | 2745 | 2746 | 2747 | 2748 | 2749 | 2750 | 2751 | 2752 | 2753 | 2754 | 2755 | 2756 | 2757 | 2758 | 2759 | 2760 | 2761 | 2762 | 2763 | 2764 | 2765 | 2766 | 2767 | 2768 | 2769 | 2770 | 2771 | 2772 | 2773 | 2774 | 2775 | 2776 | 2777 | 2778 | 2779 | 2780 | 2781 | 2782 | 2783 | 2784 | 2785 | 2786 | 2787 | 2788 | 2789 | 2790 | 2791 | 2792 | 2793 | 2794 | 2795 | 2796 | 2797 | 2798 | 2799 | 2800 | 2801 | 2802 | 2803 | 2804 | 2805 | 2806 | 2807 | 2808 | 2809 | 2810 | 2811 | 2812 | 2813 | 2814 | 2815 | 2816 | 2817 | 2818 | 2819 | 2820 | 2821 | 2822 | 2823 | 2824 | 2825 | 2826 | 2827 | 2828 | 2829 | 2830 | 2831 | 2832 | 2833 | 2834 | 2835 | 2836 | 2837 | 2838 | 2839 | 2840 | 2841 | 2842 | 2843 | 2844 | 2845 | 2846 | 2847 | 2848 | 2849 | 2850 | 2851 | 2852 | 2853 | 2854 | 2855 | 2856 | 2857 | 2858 | 2859 | 2860 | 2861 | 2862 | 2863 | 2864 | 2865 | 2866 | 2867 | 2868 | 2869 | 2870 | 2871 | 2872 | 2873 | 2874 | 2875 | 2876 | 2877 | 2878 | 2879 | 2880 | 2881 | 2882 | 2883 | 2884 | 2885 | 2886 | 2887 | 2888 | 2889 | 2890 | 2891 | 2892 | 2893 | 2894 | 2895 | 2896 | 2897 | 2898 | 2899 | #endif // DETOURS_ARM 2900 | 2901 | // 2902 | ///////////////////////////////////////////////////////////////// End of File. 2903 | --------------------------------------------------------------------------------