├── README.md ├── ShooterGameCheat.sln └── ShooterGameCheat ├── ShooterGameCheat.vcxproj ├── ShooterGameCheat.vcxproj.filters ├── detours ├── detours.cpp ├── detours.h ├── detver.h ├── disasm.cpp ├── disolarm.cpp ├── disolarm64.cpp ├── disolia64.cpp ├── disolx64.cpp ├── disolx86.cpp ├── image.cpp └── modules.cpp ├── dllmain.cpp ├── game ├── adapt_data.h ├── base_struct.h ├── game.cpp └── game.h ├── shooter_game_cheat.cpp └── utils.h /README.md: -------------------------------------------------------------------------------- 1 | A Simple Cheat for ShooterGame. -------------------------------------------------------------------------------- /ShooterGameCheat.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 15 4 | VisualStudioVersion = 15.0.28010.2003 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ShooterGameCheat", "ShooterGameCheat\ShooterGameCheat.vcxproj", "{C3C43A8E-EBDB-4E29-985E-E94E7D419459}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|x64 = Debug|x64 11 | Debug|x86 = Debug|x86 12 | exe|x64 = exe|x64 13 | exe|x86 = exe|x86 14 | Release|x64 = Release|x64 15 | Release|x86 = Release|x86 16 | EndGlobalSection 17 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 18 | {C3C43A8E-EBDB-4E29-985E-E94E7D419459}.Debug|x64.ActiveCfg = Debug|x64 19 | {C3C43A8E-EBDB-4E29-985E-E94E7D419459}.Debug|x64.Build.0 = Debug|x64 20 | {C3C43A8E-EBDB-4E29-985E-E94E7D419459}.Debug|x86.ActiveCfg = Debug|Win32 21 | {C3C43A8E-EBDB-4E29-985E-E94E7D419459}.Debug|x86.Build.0 = Debug|Win32 22 | {C3C43A8E-EBDB-4E29-985E-E94E7D419459}.exe|x64.ActiveCfg = exe|x64 23 | {C3C43A8E-EBDB-4E29-985E-E94E7D419459}.exe|x64.Build.0 = exe|x64 24 | {C3C43A8E-EBDB-4E29-985E-E94E7D419459}.exe|x86.ActiveCfg = exe|Win32 25 | {C3C43A8E-EBDB-4E29-985E-E94E7D419459}.exe|x86.Build.0 = exe|Win32 26 | {C3C43A8E-EBDB-4E29-985E-E94E7D419459}.Release|x64.ActiveCfg = Release|x64 27 | {C3C43A8E-EBDB-4E29-985E-E94E7D419459}.Release|x64.Build.0 = Release|x64 28 | {C3C43A8E-EBDB-4E29-985E-E94E7D419459}.Release|x86.ActiveCfg = Release|Win32 29 | {C3C43A8E-EBDB-4E29-985E-E94E7D419459}.Release|x86.Build.0 = Release|Win32 30 | EndGlobalSection 31 | GlobalSection(SolutionProperties) = preSolution 32 | HideSolutionNode = FALSE 33 | EndGlobalSection 34 | GlobalSection(ExtensibilityGlobals) = postSolution 35 | SolutionGuid = {AD903B6B-3EAD-4068-AF1A-AC7892D9B2E4} 36 | EndGlobalSection 37 | EndGlobal 38 | -------------------------------------------------------------------------------- /ShooterGameCheat/ShooterGameCheat.vcxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | exe 10 | Win32 11 | 12 | 13 | exe 14 | x64 15 | 16 | 17 | Release 18 | Win32 19 | 20 | 21 | Debug 22 | x64 23 | 24 | 25 | Release 26 | x64 27 | 28 | 29 | 30 | 15.0 31 | {C3C43A8E-EBDB-4E29-985E-E94E7D419459} 32 | Win32Proj 33 | ShooterGameCheat 34 | 10.0 35 | 36 | 37 | 38 | DynamicLibrary 39 | true 40 | v142 41 | Unicode 42 | 43 | 44 | DynamicLibrary 45 | true 46 | v142 47 | Unicode 48 | 49 | 50 | DynamicLibrary 51 | false 52 | v142 53 | true 54 | Unicode 55 | 56 | 57 | DynamicLibrary 58 | true 59 | v142 60 | Unicode 61 | 62 | 63 | Application 64 | true 65 | v142 66 | Unicode 67 | 68 | 69 | DynamicLibrary 70 | false 71 | v142 72 | true 73 | Unicode 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | true 101 | 102 | 103 | true 104 | 105 | 106 | true 107 | $(SolutionDir)$(Configuration)\ 108 | 109 | 110 | true 111 | 112 | 113 | false 114 | 115 | 116 | false 117 | 118 | 119 | 120 | Use 121 | Level3 122 | Disabled 123 | true 124 | WIN32;_DEBUG;SHOOTERGAMECHEAT_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) 125 | true 126 | 127 | 128 | Windows 129 | true 130 | 131 | 132 | 133 | 134 | Use 135 | Level3 136 | Disabled 137 | true 138 | WIN32;_DEBUG;SHOOTERGAMECHEAT_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) 139 | true 140 | 141 | 142 | Windows 143 | true 144 | 145 | 146 | 147 | 148 | NotUsing 149 | Level3 150 | Disabled 151 | true 152 | _DEBUG;SHOOTERGAMECHEAT_EXPORTS;_CRT_SECURE_NO_WARNINGS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) 153 | true 154 | 4099;4267;4996;%(DisableSpecificWarnings) 155 | true 156 | false 157 | EditAndContinue 158 | MultiThreadedDebug 159 | false 160 | Default 161 | 162 | 163 | Windows 164 | true 165 | 166 | 167 | 168 | 169 | NotUsing 170 | Level3 171 | Disabled 172 | true 173 | _DEBUG;SHOOTERGAMECHEAT_EXPORTS;_CRT_SECURE_NO_WARNINGS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) 174 | true 175 | 4099;4267;%(DisableSpecificWarnings) 176 | true 177 | false 178 | EditAndContinue 179 | MultiThreadedDebug 180 | false 181 | 182 | 183 | Console 184 | true 185 | 186 | 187 | 188 | 189 | Use 190 | Level3 191 | MaxSpeed 192 | true 193 | true 194 | true 195 | WIN32;NDEBUG;SHOOTERGAMECHEAT_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) 196 | true 197 | 198 | 199 | Windows 200 | true 201 | true 202 | true 203 | 204 | 205 | 206 | 207 | Use 208 | Level3 209 | MaxSpeed 210 | true 211 | true 212 | true 213 | NDEBUG;SHOOTERGAMECHEAT_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) 214 | true 215 | 216 | 217 | Windows 218 | true 219 | true 220 | true 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 | -------------------------------------------------------------------------------- /ShooterGameCheat/ShooterGameCheat.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;hm;inl;inc;ipp;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | {77bc882b-44cc-4946-8d01-cfd1c47bc059} 18 | 19 | 20 | {8a212da0-0d19-4d6a-8436-fbc9a937cb86} 21 | 22 | 23 | 24 | 25 | 源文件\detours 26 | 27 | 28 | 源文件\detours 29 | 30 | 31 | 源文件 32 | 33 | 34 | 源文件\game 35 | 36 | 37 | 源文件\game 38 | 39 | 40 | 源文件\game 41 | 42 | 43 | 44 | 45 | 源文件 46 | 47 | 48 | 源文件\detours 49 | 50 | 51 | 源文件\detours 52 | 53 | 54 | 源文件\detours 55 | 56 | 57 | 源文件\detours 58 | 59 | 60 | 源文件\detours 61 | 62 | 63 | 源文件\detours 64 | 65 | 66 | 源文件\detours 67 | 68 | 69 | 源文件\detours 70 | 71 | 72 | 源文件\detours 73 | 74 | 75 | 源文件\game 76 | 77 | 78 | 源文件 79 | 80 | 81 | -------------------------------------------------------------------------------- /ShooterGameCheat/detours/detours.h: -------------------------------------------------------------------------------- 1 | ///////////////////////////////////////////////////////////////////////////// 2 | // 3 | // Core Detours Functionality (detours.h of detours.lib) 4 | // 5 | // Microsoft Research Detours Package, Version 4.0.1 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 0x4c0c1 // 0xMAJORcMINORcPATCH 15 | 16 | ////////////////////////////////////////////////////////////////////////////// 17 | // 18 | 19 | #undef DETOURS_X64 20 | #undef DETOURS_X86 21 | #undef DETOURS_IA64 22 | #undef DETOURS_ARM 23 | #undef DETOURS_ARM64 24 | #undef DETOURS_BITS 25 | #undef DETOURS_32BIT 26 | #undef DETOURS_64BIT 27 | 28 | #if defined(_X86_) 29 | #define DETOURS_X86 30 | #define DETOURS_OPTION_BITS 64 31 | 32 | #elif defined(_AMD64_) 33 | #define DETOURS_X64 34 | #define DETOURS_OPTION_BITS 32 35 | 36 | #elif defined(_IA64_) 37 | #define DETOURS_IA64 38 | #define DETOURS_OPTION_BITS 32 39 | 40 | #elif defined(_ARM_) 41 | #define DETOURS_ARM 42 | 43 | #elif defined(_ARM64_) 44 | #define DETOURS_ARM64 45 | 46 | #else 47 | #error Unknown architecture (x86, amd64, ia64, arm, arm64) 48 | #endif 49 | 50 | #ifdef _WIN64 51 | #undef DETOURS_32BIT 52 | #define DETOURS_64BIT 1 53 | #define DETOURS_BITS 64 54 | // If all 64bit kernels can run one and only one 32bit architecture. 55 | //#define DETOURS_OPTION_BITS 32 56 | #else 57 | #define DETOURS_32BIT 1 58 | #undef DETOURS_64BIT 59 | #define DETOURS_BITS 32 60 | // If all 64bit kernels can run one and only one 32bit architecture. 61 | //#define DETOURS_OPTION_BITS 32 62 | #endif 63 | 64 | #define VER_DETOURS_BITS DETOUR_STRINGIFY(DETOURS_BITS) 65 | 66 | ////////////////////////////////////////////////////////////////////////////// 67 | // 68 | 69 | #if (_MSC_VER < 1299) 70 | typedef LONG LONG_PTR; 71 | typedef ULONG ULONG_PTR; 72 | #endif 73 | 74 | ///////////////////////////////////////////////// SAL 2.0 Annotations w/o SAL. 75 | // 76 | // These definitions are include so that Detours will build even if the 77 | // compiler doesn't have full SAL 2.0 support. 78 | // 79 | #ifndef DETOURS_DONT_REMOVE_SAL_20 80 | 81 | #ifdef DETOURS_TEST_REMOVE_SAL_20 82 | #undef _Analysis_assume_ 83 | #undef _Benign_race_begin_ 84 | #undef _Benign_race_end_ 85 | #undef _Field_range_ 86 | #undef _Field_size_ 87 | #undef _In_ 88 | #undef _In_bytecount_ 89 | #undef _In_count_ 90 | #undef _In_opt_ 91 | #undef _In_opt_bytecount_ 92 | #undef _In_opt_count_ 93 | #undef _In_opt_z_ 94 | #undef _In_range_ 95 | #undef _In_reads_ 96 | #undef _In_reads_bytes_ 97 | #undef _In_reads_opt_ 98 | #undef _In_reads_opt_bytes_ 99 | #undef _In_reads_or_z_ 100 | #undef _In_z_ 101 | #undef _Inout_ 102 | #undef _Inout_opt_ 103 | #undef _Inout_z_count_ 104 | #undef _Out_ 105 | #undef _Out_opt_ 106 | #undef _Out_writes_ 107 | #undef _Outptr_result_maybenull_ 108 | #undef _Readable_bytes_ 109 | #undef _Success_ 110 | #undef _Writable_bytes_ 111 | #undef _Pre_notnull_ 112 | #endif 113 | 114 | #if defined(_Deref_out_opt_z_) && !defined(_Outptr_result_maybenull_) 115 | #define _Outptr_result_maybenull_ _Deref_out_opt_z_ 116 | #endif 117 | 118 | #if defined(_In_count_) && !defined(_In_reads_) 119 | #define _In_reads_(x) _In_count_(x) 120 | #endif 121 | 122 | #if defined(_In_opt_count_) && !defined(_In_reads_opt_) 123 | #define _In_reads_opt_(x) _In_opt_count_(x) 124 | #endif 125 | 126 | #if defined(_In_opt_bytecount_) && !defined(_In_reads_opt_bytes_) 127 | #define _In_reads_opt_bytes_(x) _In_opt_bytecount_(x) 128 | #endif 129 | 130 | #if defined(_In_bytecount_) && !defined(_In_reads_bytes_) 131 | #define _In_reads_bytes_(x) _In_bytecount_(x) 132 | #endif 133 | 134 | #ifndef _In_ 135 | #define _In_ 136 | #endif 137 | 138 | #ifndef _In_bytecount_ 139 | #define _In_bytecount_(x) 140 | #endif 141 | 142 | #ifndef _In_count_ 143 | #define _In_count_(x) 144 | #endif 145 | 146 | #ifndef _In_opt_ 147 | #define _In_opt_ 148 | #endif 149 | 150 | #ifndef _In_opt_bytecount_ 151 | #define _In_opt_bytecount_(x) 152 | #endif 153 | 154 | #ifndef _In_opt_count_ 155 | #define _In_opt_count_(x) 156 | #endif 157 | 158 | #ifndef _In_opt_z_ 159 | #define _In_opt_z_ 160 | #endif 161 | 162 | #ifndef _In_range_ 163 | #define _In_range_(x,y) 164 | #endif 165 | 166 | #ifndef _In_reads_ 167 | #define _In_reads_(x) 168 | #endif 169 | 170 | #ifndef _In_reads_bytes_ 171 | #define _In_reads_bytes_(x) 172 | #endif 173 | 174 | #ifndef _In_reads_opt_ 175 | #define _In_reads_opt_(x) 176 | #endif 177 | 178 | #ifndef _In_reads_opt_bytes_ 179 | #define _In_reads_opt_bytes_(x) 180 | #endif 181 | 182 | #ifndef _In_reads_or_z_ 183 | #define _In_reads_or_z_ 184 | #endif 185 | 186 | #ifndef _In_z_ 187 | #define _In_z_ 188 | #endif 189 | 190 | #ifndef _Inout_ 191 | #define _Inout_ 192 | #endif 193 | 194 | #ifndef _Inout_opt_ 195 | #define _Inout_opt_ 196 | #endif 197 | 198 | #ifndef _Inout_z_count_ 199 | #define _Inout_z_count_(x) 200 | #endif 201 | 202 | #ifndef _Out_ 203 | #define _Out_ 204 | #endif 205 | 206 | #ifndef _Out_opt_ 207 | #define _Out_opt_ 208 | #endif 209 | 210 | #ifndef _Out_writes_ 211 | #define _Out_writes_(x) 212 | #endif 213 | 214 | #ifndef _Outptr_result_maybenull_ 215 | #define _Outptr_result_maybenull_ 216 | #endif 217 | 218 | #ifndef _Writable_bytes_ 219 | #define _Writable_bytes_(x) 220 | #endif 221 | 222 | #ifndef _Readable_bytes_ 223 | #define _Readable_bytes_(x) 224 | #endif 225 | 226 | #ifndef _Success_ 227 | #define _Success_(x) 228 | #endif 229 | 230 | #ifndef _Pre_notnull_ 231 | #define _Pre_notnull_ 232 | #endif 233 | 234 | #ifdef DETOURS_INTERNAL 235 | 236 | #pragma warning(disable:4615) // unknown warning type (suppress with older compilers) 237 | 238 | #ifndef _Benign_race_begin_ 239 | #define _Benign_race_begin_ 240 | #endif 241 | 242 | #ifndef _Benign_race_end_ 243 | #define _Benign_race_end_ 244 | #endif 245 | 246 | #ifndef _Field_size_ 247 | #define _Field_size_(x) 248 | #endif 249 | 250 | #ifndef _Field_range_ 251 | #define _Field_range_(x,y) 252 | #endif 253 | 254 | #ifndef _Analysis_assume_ 255 | #define _Analysis_assume_(x) 256 | #endif 257 | 258 | #endif // DETOURS_INTERNAL 259 | #endif // DETOURS_DONT_REMOVE_SAL_20 260 | 261 | ////////////////////////////////////////////////////////////////////////////// 262 | // 263 | #ifndef GUID_DEFINED 264 | #define GUID_DEFINED 265 | typedef struct _GUID 266 | { 267 | DWORD Data1; 268 | WORD Data2; 269 | WORD Data3; 270 | BYTE Data4[ 8 ]; 271 | } GUID; 272 | 273 | #ifdef INITGUID 274 | #define DEFINE_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \ 275 | const GUID name \ 276 | = { l, w1, w2, { b1, b2, b3, b4, b5, b6, b7, b8 } } 277 | #else 278 | #define DEFINE_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \ 279 | const GUID name 280 | #endif // INITGUID 281 | #endif // !GUID_DEFINED 282 | 283 | #if defined(__cplusplus) 284 | #ifndef _REFGUID_DEFINED 285 | #define _REFGUID_DEFINED 286 | #define REFGUID const GUID & 287 | #endif // !_REFGUID_DEFINED 288 | #else // !__cplusplus 289 | #ifndef _REFGUID_DEFINED 290 | #define _REFGUID_DEFINED 291 | #define REFGUID const GUID * const 292 | #endif // !_REFGUID_DEFINED 293 | #endif // !__cplusplus 294 | 295 | #ifndef ARRAYSIZE 296 | #define ARRAYSIZE(x) (sizeof(x)/sizeof(x[0])) 297 | #endif 298 | 299 | // 300 | ////////////////////////////////////////////////////////////////////////////// 301 | 302 | #ifdef __cplusplus 303 | extern "C" { 304 | #endif // __cplusplus 305 | 306 | /////////////////////////////////////////////////// Instruction Target Macros. 307 | // 308 | #define DETOUR_INSTRUCTION_TARGET_NONE ((PVOID)0) 309 | #define DETOUR_INSTRUCTION_TARGET_DYNAMIC ((PVOID)(LONG_PTR)-1) 310 | #define DETOUR_SECTION_HEADER_SIGNATURE 0x00727444 // "Dtr\0" 311 | 312 | extern const GUID DETOUR_EXE_RESTORE_GUID; 313 | extern const GUID DETOUR_EXE_HELPER_GUID; 314 | 315 | #define DETOUR_TRAMPOLINE_SIGNATURE 0x21727444 // Dtr! 316 | typedef struct _DETOUR_TRAMPOLINE DETOUR_TRAMPOLINE, *PDETOUR_TRAMPOLINE; 317 | 318 | /////////////////////////////////////////////////////////// Binary Structures. 319 | // 320 | #pragma pack(push, 8) 321 | typedef struct _DETOUR_SECTION_HEADER 322 | { 323 | DWORD cbHeaderSize; 324 | DWORD nSignature; 325 | DWORD nDataOffset; 326 | DWORD cbDataSize; 327 | 328 | DWORD nOriginalImportVirtualAddress; 329 | DWORD nOriginalImportSize; 330 | DWORD nOriginalBoundImportVirtualAddress; 331 | DWORD nOriginalBoundImportSize; 332 | 333 | DWORD nOriginalIatVirtualAddress; 334 | DWORD nOriginalIatSize; 335 | DWORD nOriginalSizeOfImage; 336 | DWORD cbPrePE; 337 | 338 | DWORD nOriginalClrFlags; 339 | DWORD reserved1; 340 | DWORD reserved2; 341 | DWORD reserved3; 342 | 343 | // Followed by cbPrePE bytes of data. 344 | } DETOUR_SECTION_HEADER, *PDETOUR_SECTION_HEADER; 345 | 346 | typedef struct _DETOUR_SECTION_RECORD 347 | { 348 | DWORD cbBytes; 349 | DWORD nReserved; 350 | GUID guid; 351 | } DETOUR_SECTION_RECORD, *PDETOUR_SECTION_RECORD; 352 | 353 | typedef struct _DETOUR_CLR_HEADER 354 | { 355 | // Header versioning 356 | ULONG cb; 357 | USHORT MajorRuntimeVersion; 358 | USHORT MinorRuntimeVersion; 359 | 360 | // Symbol table and startup information 361 | IMAGE_DATA_DIRECTORY MetaData; 362 | ULONG Flags; 363 | 364 | // Followed by the rest of the IMAGE_COR20_HEADER 365 | } DETOUR_CLR_HEADER, *PDETOUR_CLR_HEADER; 366 | 367 | typedef struct _DETOUR_EXE_RESTORE 368 | { 369 | DWORD cb; 370 | DWORD cbidh; 371 | DWORD cbinh; 372 | DWORD cbclr; 373 | 374 | PBYTE pidh; 375 | PBYTE pinh; 376 | PBYTE pclr; 377 | 378 | IMAGE_DOS_HEADER idh; 379 | union { 380 | IMAGE_NT_HEADERS inh; 381 | IMAGE_NT_HEADERS32 inh32; 382 | IMAGE_NT_HEADERS64 inh64; 383 | BYTE raw[sizeof(IMAGE_NT_HEADERS64) + 384 | sizeof(IMAGE_SECTION_HEADER) * 32]; 385 | }; 386 | DETOUR_CLR_HEADER clr; 387 | 388 | } DETOUR_EXE_RESTORE, *PDETOUR_EXE_RESTORE; 389 | 390 | typedef struct _DETOUR_EXE_HELPER 391 | { 392 | DWORD cb; 393 | DWORD pid; 394 | DWORD nDlls; 395 | CHAR rDlls[4]; 396 | } DETOUR_EXE_HELPER, *PDETOUR_EXE_HELPER; 397 | 398 | #pragma pack(pop) 399 | 400 | #define DETOUR_SECTION_HEADER_DECLARE(cbSectionSize) \ 401 | { \ 402 | sizeof(DETOUR_SECTION_HEADER),\ 403 | DETOUR_SECTION_HEADER_SIGNATURE,\ 404 | sizeof(DETOUR_SECTION_HEADER),\ 405 | (cbSectionSize),\ 406 | \ 407 | 0,\ 408 | 0,\ 409 | 0,\ 410 | 0,\ 411 | \ 412 | 0,\ 413 | 0,\ 414 | 0,\ 415 | 0,\ 416 | } 417 | 418 | /////////////////////////////////////////////////////////////// Helper Macros. 419 | // 420 | #define DETOURS_STRINGIFY(x) DETOURS_STRINGIFY_(x) 421 | #define DETOURS_STRINGIFY_(x) #x 422 | 423 | ///////////////////////////////////////////////////////////// Binary Typedefs. 424 | // 425 | typedef BOOL (CALLBACK *PF_DETOUR_BINARY_BYWAY_CALLBACK)( 426 | _In_opt_ PVOID pContext, 427 | _In_opt_ LPCSTR pszFile, 428 | _Outptr_result_maybenull_ LPCSTR *ppszOutFile); 429 | 430 | typedef BOOL (CALLBACK *PF_DETOUR_BINARY_FILE_CALLBACK)( 431 | _In_opt_ PVOID pContext, 432 | _In_ LPCSTR pszOrigFile, 433 | _In_ LPCSTR pszFile, 434 | _Outptr_result_maybenull_ LPCSTR *ppszOutFile); 435 | 436 | typedef BOOL (CALLBACK *PF_DETOUR_BINARY_SYMBOL_CALLBACK)( 437 | _In_opt_ PVOID pContext, 438 | _In_ ULONG nOrigOrdinal, 439 | _In_ ULONG nOrdinal, 440 | _Out_ ULONG *pnOutOrdinal, 441 | _In_opt_ LPCSTR pszOrigSymbol, 442 | _In_opt_ LPCSTR pszSymbol, 443 | _Outptr_result_maybenull_ LPCSTR *ppszOutSymbol); 444 | 445 | typedef BOOL (CALLBACK *PF_DETOUR_BINARY_COMMIT_CALLBACK)( 446 | _In_opt_ PVOID pContext); 447 | 448 | typedef BOOL (CALLBACK *PF_DETOUR_ENUMERATE_EXPORT_CALLBACK)(_In_opt_ PVOID pContext, 449 | _In_ ULONG nOrdinal, 450 | _In_opt_ LPCSTR pszName, 451 | _In_opt_ PVOID pCode); 452 | 453 | typedef BOOL (CALLBACK *PF_DETOUR_IMPORT_FILE_CALLBACK)(_In_opt_ PVOID pContext, 454 | _In_opt_ HMODULE hModule, 455 | _In_opt_ LPCSTR pszFile); 456 | 457 | typedef BOOL (CALLBACK *PF_DETOUR_IMPORT_FUNC_CALLBACK)(_In_opt_ PVOID pContext, 458 | _In_ DWORD nOrdinal, 459 | _In_opt_ LPCSTR pszFunc, 460 | _In_opt_ PVOID pvFunc); 461 | 462 | // Same as PF_DETOUR_IMPORT_FUNC_CALLBACK but extra indirection on last parameter. 463 | typedef BOOL (CALLBACK *PF_DETOUR_IMPORT_FUNC_CALLBACK_EX)(_In_opt_ PVOID pContext, 464 | _In_ DWORD nOrdinal, 465 | _In_opt_ LPCSTR pszFunc, 466 | _In_opt_ PVOID* ppvFunc); 467 | 468 | typedef VOID * PDETOUR_BINARY; 469 | typedef VOID * PDETOUR_LOADED_BINARY; 470 | 471 | //////////////////////////////////////////////////////////// Transaction APIs. 472 | // 473 | LONG WINAPI DetourTransactionBegin(VOID); 474 | LONG WINAPI DetourTransactionAbort(VOID); 475 | LONG WINAPI DetourTransactionCommit(VOID); 476 | LONG WINAPI DetourTransactionCommitEx(_Out_opt_ PVOID **pppFailedPointer); 477 | 478 | LONG WINAPI DetourUpdateThread(_In_ HANDLE hThread); 479 | 480 | LONG WINAPI DetourAttach(_Inout_ PVOID *ppPointer, 481 | _In_ PVOID pDetour); 482 | 483 | LONG WINAPI DetourAttachEx(_Inout_ PVOID *ppPointer, 484 | _In_ PVOID pDetour, 485 | _Out_opt_ PDETOUR_TRAMPOLINE *ppRealTrampoline, 486 | _Out_opt_ PVOID *ppRealTarget, 487 | _Out_opt_ PVOID *ppRealDetour); 488 | 489 | LONG WINAPI DetourDetach(_Inout_ PVOID *ppPointer, 490 | _In_ PVOID pDetour); 491 | 492 | BOOL WINAPI DetourSetIgnoreTooSmall(_In_ BOOL fIgnore); 493 | BOOL WINAPI DetourSetRetainRegions(_In_ BOOL fRetain); 494 | PVOID WINAPI DetourSetSystemRegionLowerBound(_In_ PVOID pSystemRegionLowerBound); 495 | PVOID WINAPI DetourSetSystemRegionUpperBound(_In_ PVOID pSystemRegionUpperBound); 496 | 497 | ////////////////////////////////////////////////////////////// Code Functions. 498 | // 499 | PVOID WINAPI DetourFindFunction(_In_ LPCSTR pszModule, 500 | _In_ LPCSTR pszFunction); 501 | PVOID WINAPI DetourCodeFromPointer(_In_ PVOID pPointer, 502 | _Out_opt_ PVOID *ppGlobals); 503 | PVOID WINAPI DetourCopyInstruction(_In_opt_ PVOID pDst, 504 | _Inout_opt_ PVOID *ppDstPool, 505 | _In_ PVOID pSrc, 506 | _Out_opt_ PVOID *ppTarget, 507 | _Out_opt_ LONG *plExtra); 508 | BOOL WINAPI DetourSetCodeModule(_In_ HMODULE hModule, 509 | _In_ BOOL fLimitReferencesToModule); 510 | 511 | ///////////////////////////////////////////////////// Loaded Binary Functions. 512 | // 513 | HMODULE WINAPI DetourGetContainingModule(_In_ PVOID pvAddr); 514 | HMODULE WINAPI DetourEnumerateModules(_In_opt_ HMODULE hModuleLast); 515 | PVOID WINAPI DetourGetEntryPoint(_In_opt_ HMODULE hModule); 516 | ULONG WINAPI DetourGetModuleSize(_In_opt_ HMODULE hModule); 517 | BOOL WINAPI DetourEnumerateExports(_In_ HMODULE hModule, 518 | _In_opt_ PVOID pContext, 519 | _In_ PF_DETOUR_ENUMERATE_EXPORT_CALLBACK pfExport); 520 | BOOL WINAPI DetourEnumerateImports(_In_opt_ HMODULE hModule, 521 | _In_opt_ PVOID pContext, 522 | _In_opt_ PF_DETOUR_IMPORT_FILE_CALLBACK pfImportFile, 523 | _In_opt_ PF_DETOUR_IMPORT_FUNC_CALLBACK pfImportFunc); 524 | 525 | BOOL WINAPI DetourEnumerateImportsEx(_In_opt_ HMODULE hModule, 526 | _In_opt_ PVOID pContext, 527 | _In_opt_ PF_DETOUR_IMPORT_FILE_CALLBACK pfImportFile, 528 | _In_opt_ PF_DETOUR_IMPORT_FUNC_CALLBACK_EX pfImportFuncEx); 529 | 530 | _Writable_bytes_(*pcbData) 531 | _Readable_bytes_(*pcbData) 532 | _Success_(return != NULL) 533 | PVOID WINAPI DetourFindPayload(_In_opt_ HMODULE hModule, 534 | _In_ REFGUID rguid, 535 | _Out_ DWORD *pcbData); 536 | 537 | _Writable_bytes_(*pcbData) 538 | _Readable_bytes_(*pcbData) 539 | _Success_(return != NULL) 540 | PVOID WINAPI DetourFindPayloadEx(_In_ REFGUID rguid, 541 | _Out_ DWORD * pcbData); 542 | 543 | DWORD WINAPI DetourGetSizeOfPayloads(_In_opt_ HMODULE hModule); 544 | 545 | ///////////////////////////////////////////////// Persistent Binary Functions. 546 | // 547 | 548 | PDETOUR_BINARY WINAPI DetourBinaryOpen(_In_ HANDLE hFile); 549 | 550 | _Writable_bytes_(*pcbData) 551 | _Readable_bytes_(*pcbData) 552 | _Success_(return != NULL) 553 | PVOID WINAPI DetourBinaryEnumeratePayloads(_In_ PDETOUR_BINARY pBinary, 554 | _Out_opt_ GUID *pGuid, 555 | _Out_ DWORD *pcbData, 556 | _Inout_ DWORD *pnIterator); 557 | 558 | _Writable_bytes_(*pcbData) 559 | _Readable_bytes_(*pcbData) 560 | _Success_(return != NULL) 561 | PVOID WINAPI DetourBinaryFindPayload(_In_ PDETOUR_BINARY pBinary, 562 | _In_ REFGUID rguid, 563 | _Out_ DWORD *pcbData); 564 | 565 | PVOID WINAPI DetourBinarySetPayload(_In_ PDETOUR_BINARY pBinary, 566 | _In_ REFGUID rguid, 567 | _In_reads_opt_(cbData) PVOID pData, 568 | _In_ DWORD cbData); 569 | BOOL WINAPI DetourBinaryDeletePayload(_In_ PDETOUR_BINARY pBinary, _In_ REFGUID rguid); 570 | BOOL WINAPI DetourBinaryPurgePayloads(_In_ PDETOUR_BINARY pBinary); 571 | BOOL WINAPI DetourBinaryResetImports(_In_ PDETOUR_BINARY pBinary); 572 | BOOL WINAPI DetourBinaryEditImports(_In_ PDETOUR_BINARY pBinary, 573 | _In_opt_ PVOID pContext, 574 | _In_opt_ PF_DETOUR_BINARY_BYWAY_CALLBACK pfByway, 575 | _In_opt_ PF_DETOUR_BINARY_FILE_CALLBACK pfFile, 576 | _In_opt_ PF_DETOUR_BINARY_SYMBOL_CALLBACK pfSymbol, 577 | _In_opt_ PF_DETOUR_BINARY_COMMIT_CALLBACK pfCommit); 578 | BOOL WINAPI DetourBinaryWrite(_In_ PDETOUR_BINARY pBinary, _In_ HANDLE hFile); 579 | BOOL WINAPI DetourBinaryClose(_In_ PDETOUR_BINARY pBinary); 580 | 581 | /////////////////////////////////////////////////// Create Process & Load Dll. 582 | // 583 | typedef BOOL (WINAPI *PDETOUR_CREATE_PROCESS_ROUTINEA)( 584 | _In_opt_ LPCSTR lpApplicationName, 585 | _Inout_opt_ LPSTR lpCommandLine, 586 | _In_opt_ LPSECURITY_ATTRIBUTES lpProcessAttributes, 587 | _In_opt_ LPSECURITY_ATTRIBUTES lpThreadAttributes, 588 | _In_ BOOL bInheritHandles, 589 | _In_ DWORD dwCreationFlags, 590 | _In_opt_ LPVOID lpEnvironment, 591 | _In_opt_ LPCSTR lpCurrentDirectory, 592 | _In_ LPSTARTUPINFOA lpStartupInfo, 593 | _Out_ LPPROCESS_INFORMATION lpProcessInformation); 594 | 595 | typedef BOOL (WINAPI *PDETOUR_CREATE_PROCESS_ROUTINEW)( 596 | _In_opt_ LPCWSTR lpApplicationName, 597 | _Inout_opt_ LPWSTR lpCommandLine, 598 | _In_opt_ LPSECURITY_ATTRIBUTES lpProcessAttributes, 599 | _In_opt_ LPSECURITY_ATTRIBUTES lpThreadAttributes, 600 | _In_ BOOL bInheritHandles, 601 | _In_ DWORD dwCreationFlags, 602 | _In_opt_ LPVOID lpEnvironment, 603 | _In_opt_ LPCWSTR lpCurrentDirectory, 604 | _In_ LPSTARTUPINFOW lpStartupInfo, 605 | _Out_ LPPROCESS_INFORMATION lpProcessInformation); 606 | 607 | BOOL WINAPI DetourCreateProcessWithDllA(_In_opt_ LPCSTR lpApplicationName, 608 | _Inout_opt_ LPSTR lpCommandLine, 609 | _In_opt_ LPSECURITY_ATTRIBUTES lpProcessAttributes, 610 | _In_opt_ LPSECURITY_ATTRIBUTES lpThreadAttributes, 611 | _In_ BOOL bInheritHandles, 612 | _In_ DWORD dwCreationFlags, 613 | _In_opt_ LPVOID lpEnvironment, 614 | _In_opt_ LPCSTR lpCurrentDirectory, 615 | _In_ LPSTARTUPINFOA lpStartupInfo, 616 | _Out_ LPPROCESS_INFORMATION lpProcessInformation, 617 | _In_ LPCSTR lpDllName, 618 | _In_opt_ PDETOUR_CREATE_PROCESS_ROUTINEA pfCreateProcessA); 619 | 620 | BOOL WINAPI DetourCreateProcessWithDllW(_In_opt_ LPCWSTR lpApplicationName, 621 | _Inout_opt_ LPWSTR lpCommandLine, 622 | _In_opt_ LPSECURITY_ATTRIBUTES lpProcessAttributes, 623 | _In_opt_ LPSECURITY_ATTRIBUTES lpThreadAttributes, 624 | _In_ BOOL bInheritHandles, 625 | _In_ DWORD dwCreationFlags, 626 | _In_opt_ LPVOID lpEnvironment, 627 | _In_opt_ LPCWSTR lpCurrentDirectory, 628 | _In_ LPSTARTUPINFOW lpStartupInfo, 629 | _Out_ LPPROCESS_INFORMATION lpProcessInformation, 630 | _In_ LPCSTR lpDllName, 631 | _In_opt_ PDETOUR_CREATE_PROCESS_ROUTINEW pfCreateProcessW); 632 | 633 | #ifdef UNICODE 634 | #define DetourCreateProcessWithDll DetourCreateProcessWithDllW 635 | #define PDETOUR_CREATE_PROCESS_ROUTINE PDETOUR_CREATE_PROCESS_ROUTINEW 636 | #else 637 | #define DetourCreateProcessWithDll DetourCreateProcessWithDllA 638 | #define PDETOUR_CREATE_PROCESS_ROUTINE PDETOUR_CREATE_PROCESS_ROUTINEA 639 | #endif // !UNICODE 640 | 641 | BOOL WINAPI DetourCreateProcessWithDllExA(_In_opt_ LPCSTR lpApplicationName, 642 | _Inout_opt_ LPSTR lpCommandLine, 643 | _In_opt_ LPSECURITY_ATTRIBUTES lpProcessAttributes, 644 | _In_opt_ LPSECURITY_ATTRIBUTES lpThreadAttributes, 645 | _In_ BOOL bInheritHandles, 646 | _In_ DWORD dwCreationFlags, 647 | _In_opt_ LPVOID lpEnvironment, 648 | _In_opt_ LPCSTR lpCurrentDirectory, 649 | _In_ LPSTARTUPINFOA lpStartupInfo, 650 | _Out_ LPPROCESS_INFORMATION lpProcessInformation, 651 | _In_ LPCSTR lpDllName, 652 | _In_opt_ PDETOUR_CREATE_PROCESS_ROUTINEA pfCreateProcessA); 653 | 654 | BOOL WINAPI DetourCreateProcessWithDllExW(_In_opt_ LPCWSTR lpApplicationName, 655 | _Inout_opt_ LPWSTR lpCommandLine, 656 | _In_opt_ LPSECURITY_ATTRIBUTES lpProcessAttributes, 657 | _In_opt_ LPSECURITY_ATTRIBUTES lpThreadAttributes, 658 | _In_ BOOL bInheritHandles, 659 | _In_ DWORD dwCreationFlags, 660 | _In_opt_ LPVOID lpEnvironment, 661 | _In_opt_ LPCWSTR lpCurrentDirectory, 662 | _In_ LPSTARTUPINFOW lpStartupInfo, 663 | _Out_ LPPROCESS_INFORMATION lpProcessInformation, 664 | _In_ LPCSTR lpDllName, 665 | _In_opt_ PDETOUR_CREATE_PROCESS_ROUTINEW pfCreateProcessW); 666 | 667 | #ifdef UNICODE 668 | #define DetourCreateProcessWithDllEx DetourCreateProcessWithDllExW 669 | #else 670 | #define DetourCreateProcessWithDllEx DetourCreateProcessWithDllExA 671 | #endif // !UNICODE 672 | 673 | BOOL WINAPI DetourCreateProcessWithDllsA(_In_opt_ LPCSTR lpApplicationName, 674 | _Inout_opt_ LPSTR lpCommandLine, 675 | _In_opt_ LPSECURITY_ATTRIBUTES lpProcessAttributes, 676 | _In_opt_ LPSECURITY_ATTRIBUTES lpThreadAttributes, 677 | _In_ BOOL bInheritHandles, 678 | _In_ DWORD dwCreationFlags, 679 | _In_opt_ LPVOID lpEnvironment, 680 | _In_opt_ LPCSTR lpCurrentDirectory, 681 | _In_ LPSTARTUPINFOA lpStartupInfo, 682 | _Out_ LPPROCESS_INFORMATION lpProcessInformation, 683 | _In_ DWORD nDlls, 684 | _In_reads_(nDlls) LPCSTR *rlpDlls, 685 | _In_opt_ PDETOUR_CREATE_PROCESS_ROUTINEA pfCreateProcessA); 686 | 687 | BOOL WINAPI DetourCreateProcessWithDllsW(_In_opt_ LPCWSTR lpApplicationName, 688 | _Inout_opt_ LPWSTR lpCommandLine, 689 | _In_opt_ LPSECURITY_ATTRIBUTES lpProcessAttributes, 690 | _In_opt_ LPSECURITY_ATTRIBUTES lpThreadAttributes, 691 | _In_ BOOL bInheritHandles, 692 | _In_ DWORD dwCreationFlags, 693 | _In_opt_ LPVOID lpEnvironment, 694 | _In_opt_ LPCWSTR lpCurrentDirectory, 695 | _In_ LPSTARTUPINFOW lpStartupInfo, 696 | _Out_ LPPROCESS_INFORMATION lpProcessInformation, 697 | _In_ DWORD nDlls, 698 | _In_reads_(nDlls) LPCSTR *rlpDlls, 699 | _In_opt_ PDETOUR_CREATE_PROCESS_ROUTINEW pfCreateProcessW); 700 | 701 | #ifdef UNICODE 702 | #define DetourCreateProcessWithDlls DetourCreateProcessWithDllsW 703 | #else 704 | #define DetourCreateProcessWithDlls DetourCreateProcessWithDllsA 705 | #endif // !UNICODE 706 | 707 | BOOL WINAPI DetourProcessViaHelperA(_In_ DWORD dwTargetPid, 708 | _In_ LPCSTR lpDllName, 709 | _In_ PDETOUR_CREATE_PROCESS_ROUTINEA pfCreateProcessA); 710 | 711 | BOOL WINAPI DetourProcessViaHelperW(_In_ DWORD dwTargetPid, 712 | _In_ LPCSTR lpDllName, 713 | _In_ PDETOUR_CREATE_PROCESS_ROUTINEW pfCreateProcessW); 714 | 715 | #ifdef UNICODE 716 | #define DetourProcessViaHelper DetourProcessViaHelperW 717 | #else 718 | #define DetourProcessViaHelper DetourProcessViaHelperA 719 | #endif // !UNICODE 720 | 721 | BOOL WINAPI DetourProcessViaHelperDllsA(_In_ DWORD dwTargetPid, 722 | _In_ DWORD nDlls, 723 | _In_reads_(nDlls) LPCSTR *rlpDlls, 724 | _In_ PDETOUR_CREATE_PROCESS_ROUTINEA pfCreateProcessA); 725 | 726 | BOOL WINAPI DetourProcessViaHelperDllsW(_In_ DWORD dwTargetPid, 727 | _In_ DWORD nDlls, 728 | _In_reads_(nDlls) LPCSTR *rlpDlls, 729 | _In_ PDETOUR_CREATE_PROCESS_ROUTINEW pfCreateProcessW); 730 | 731 | #ifdef UNICODE 732 | #define DetourProcessViaHelperDlls DetourProcessViaHelperDllsW 733 | #else 734 | #define DetourProcessViaHelperDlls DetourProcessViaHelperDllsA 735 | #endif // !UNICODE 736 | 737 | BOOL WINAPI DetourUpdateProcessWithDll(_In_ HANDLE hProcess, 738 | _In_reads_(nDlls) LPCSTR *rlpDlls, 739 | _In_ DWORD nDlls); 740 | 741 | BOOL WINAPI DetourUpdateProcessWithDllEx(_In_ HANDLE hProcess, 742 | _In_ HMODULE hImage, 743 | _In_ BOOL bIs32Bit, 744 | _In_reads_(nDlls) LPCSTR *rlpDlls, 745 | _In_ DWORD nDlls); 746 | 747 | BOOL WINAPI DetourCopyPayloadToProcess(_In_ HANDLE hProcess, 748 | _In_ REFGUID rguid, 749 | _In_reads_bytes_(cbData) PVOID pvData, 750 | _In_ DWORD cbData); 751 | BOOL WINAPI DetourRestoreAfterWith(VOID); 752 | BOOL WINAPI DetourRestoreAfterWithEx(_In_reads_bytes_(cbData) PVOID pvData, 753 | _In_ DWORD cbData); 754 | BOOL WINAPI DetourIsHelperProcess(VOID); 755 | VOID CALLBACK DetourFinishHelperProcess(_In_ HWND, 756 | _In_ HINSTANCE, 757 | _In_ LPSTR, 758 | _In_ INT); 759 | 760 | // 761 | ////////////////////////////////////////////////////////////////////////////// 762 | #ifdef __cplusplus 763 | } 764 | #endif // __cplusplus 765 | 766 | //////////////////////////////////////////////// Detours Internal Definitions. 767 | // 768 | #ifdef __cplusplus 769 | #ifdef DETOURS_INTERNAL 770 | 771 | #define NOTHROW 772 | // #define NOTHROW (nothrow) 773 | 774 | ////////////////////////////////////////////////////////////////////////////// 775 | // 776 | #if (_MSC_VER < 1299) 777 | #include 778 | typedef IMAGEHLP_MODULE IMAGEHLP_MODULE64; 779 | typedef PIMAGEHLP_MODULE PIMAGEHLP_MODULE64; 780 | typedef IMAGEHLP_SYMBOL SYMBOL_INFO; 781 | typedef PIMAGEHLP_SYMBOL PSYMBOL_INFO; 782 | 783 | static inline 784 | LONG InterlockedCompareExchange(_Inout_ LONG *ptr, _In_ LONG nval, _In_ LONG oval) 785 | { 786 | return (LONG)::InterlockedCompareExchange((PVOID*)ptr, (PVOID)nval, (PVOID)oval); 787 | } 788 | #else 789 | #pragma warning(push) 790 | #pragma warning(disable:4091) // empty typedef 791 | #include 792 | #pragma warning(pop) 793 | #endif 794 | 795 | #ifdef IMAGEAPI // defined by DBGHELP.H 796 | typedef LPAPI_VERSION (NTAPI *PF_ImagehlpApiVersionEx)(_In_ LPAPI_VERSION AppVersion); 797 | 798 | typedef BOOL (NTAPI *PF_SymInitialize)(_In_ HANDLE hProcess, 799 | _In_opt_ LPCSTR UserSearchPath, 800 | _In_ BOOL fInvadeProcess); 801 | typedef DWORD (NTAPI *PF_SymSetOptions)(_In_ DWORD SymOptions); 802 | typedef DWORD (NTAPI *PF_SymGetOptions)(VOID); 803 | typedef DWORD64 (NTAPI *PF_SymLoadModule64)(_In_ HANDLE hProcess, 804 | _In_opt_ HANDLE hFile, 805 | _In_ LPSTR ImageName, 806 | _In_opt_ LPSTR ModuleName, 807 | _In_ DWORD64 BaseOfDll, 808 | _In_opt_ DWORD SizeOfDll); 809 | typedef BOOL (NTAPI *PF_SymGetModuleInfo64)(_In_ HANDLE hProcess, 810 | _In_ DWORD64 qwAddr, 811 | _Out_ PIMAGEHLP_MODULE64 ModuleInfo); 812 | typedef BOOL (NTAPI *PF_SymFromName)(_In_ HANDLE hProcess, 813 | _In_ LPSTR Name, 814 | _Out_ PSYMBOL_INFO Symbol); 815 | 816 | typedef struct _DETOUR_SYM_INFO 817 | { 818 | HANDLE hProcess; 819 | HMODULE hDbgHelp; 820 | PF_ImagehlpApiVersionEx pfImagehlpApiVersionEx; 821 | PF_SymInitialize pfSymInitialize; 822 | PF_SymSetOptions pfSymSetOptions; 823 | PF_SymGetOptions pfSymGetOptions; 824 | PF_SymLoadModule64 pfSymLoadModule64; 825 | PF_SymGetModuleInfo64 pfSymGetModuleInfo64; 826 | PF_SymFromName pfSymFromName; 827 | } DETOUR_SYM_INFO, *PDETOUR_SYM_INFO; 828 | 829 | PDETOUR_SYM_INFO DetourLoadImageHlp(VOID); 830 | 831 | #endif // IMAGEAPI 832 | 833 | #if defined(_INC_STDIO) && !defined(_CRT_STDIO_ARBITRARY_WIDE_SPECIFIERS) 834 | #error detours.h must be included before stdio.h (or at least define _CRT_STDIO_ARBITRARY_WIDE_SPECIFIERS earlier) 835 | #endif 836 | #define _CRT_STDIO_ARBITRARY_WIDE_SPECIFIERS 1 837 | 838 | #ifndef DETOUR_TRACE 839 | #if DETOUR_DEBUG 840 | #define DETOUR_TRACE(x) printf x 841 | #define DETOUR_BREAK() __debugbreak() 842 | #include 843 | #include 844 | #else 845 | #define DETOUR_TRACE(x) 846 | #define DETOUR_BREAK() 847 | #endif 848 | #endif 849 | 850 | #if 1 || defined(DETOURS_IA64) 851 | 852 | // 853 | // IA64 instructions are 41 bits, 3 per bundle, plus 5 bit bundle template => 128 bits per bundle. 854 | // 855 | 856 | #define DETOUR_IA64_INSTRUCTIONS_PER_BUNDLE (3) 857 | 858 | #define DETOUR_IA64_TEMPLATE_OFFSET (0) 859 | #define DETOUR_IA64_TEMPLATE_SIZE (5) 860 | 861 | #define DETOUR_IA64_INSTRUCTION_SIZE (41) 862 | #define DETOUR_IA64_INSTRUCTION0_OFFSET (DETOUR_IA64_TEMPLATE_SIZE) 863 | #define DETOUR_IA64_INSTRUCTION1_OFFSET (DETOUR_IA64_TEMPLATE_SIZE + DETOUR_IA64_INSTRUCTION_SIZE) 864 | #define DETOUR_IA64_INSTRUCTION2_OFFSET (DETOUR_IA64_TEMPLATE_SIZE + DETOUR_IA64_INSTRUCTION_SIZE + DETOUR_IA64_INSTRUCTION_SIZE) 865 | 866 | C_ASSERT(DETOUR_IA64_TEMPLATE_SIZE + DETOUR_IA64_INSTRUCTIONS_PER_BUNDLE * DETOUR_IA64_INSTRUCTION_SIZE == 128); 867 | 868 | __declspec(align(16)) struct DETOUR_IA64_BUNDLE 869 | { 870 | public: 871 | union 872 | { 873 | BYTE data[16]; 874 | UINT64 wide[2]; 875 | }; 876 | 877 | enum { 878 | A_UNIT = 1u, 879 | I_UNIT = 2u, 880 | M_UNIT = 3u, 881 | B_UNIT = 4u, 882 | F_UNIT = 5u, 883 | L_UNIT = 6u, 884 | X_UNIT = 7u, 885 | }; 886 | struct DETOUR_IA64_METADATA 887 | { 888 | ULONG nTemplate : 8; // Instruction template. 889 | ULONG nUnit0 : 4; // Unit for slot 0 890 | ULONG nUnit1 : 4; // Unit for slot 1 891 | ULONG nUnit2 : 4; // Unit for slot 2 892 | }; 893 | 894 | protected: 895 | static const DETOUR_IA64_METADATA s_rceCopyTable[33]; 896 | 897 | UINT RelocateBundle(_Inout_ DETOUR_IA64_BUNDLE* pDst, _Inout_opt_ DETOUR_IA64_BUNDLE* pBundleExtra) const; 898 | 899 | bool RelocateInstruction(_Inout_ DETOUR_IA64_BUNDLE* pDst, 900 | _In_ BYTE slot, 901 | _Inout_opt_ DETOUR_IA64_BUNDLE* pBundleExtra) const; 902 | 903 | // 120 112 104 96 88 80 72 64 56 48 40 32 24 16 8 0 904 | // f. e. d. c. b. a. 9. 8. 7. 6. 5. 4. 3. 2. 1. 0. 905 | 906 | // 00 907 | // f.e. d.c. b.a. 9.8. 7.6. 5.4. 3.2. 1.0. 908 | // 0000 0000 0000 0000 0000 0000 0000 001f : Template [4..0] 909 | // 0000 0000 0000 0000 0000 03ff ffff ffe0 : Zero [ 41.. 5] 910 | // 0000 0000 0000 0000 0000 3c00 0000 0000 : Zero [ 45.. 42] 911 | // 0000 0000 0007 ffff ffff c000 0000 0000 : One [ 82.. 46] 912 | // 0000 0000 0078 0000 0000 0000 0000 0000 : One [ 86.. 83] 913 | // 0fff ffff ff80 0000 0000 0000 0000 0000 : Two [123.. 87] 914 | // f000 0000 0000 0000 0000 0000 0000 0000 : Two [127..124] 915 | BYTE GetTemplate() const; 916 | // Get 4 bit opcodes. 917 | BYTE GetInst0() const; 918 | BYTE GetInst1() const; 919 | BYTE GetInst2() const; 920 | BYTE GetUnit(BYTE slot) const; 921 | BYTE GetUnit0() const; 922 | BYTE GetUnit1() const; 923 | BYTE GetUnit2() const; 924 | // Get 37 bit data. 925 | UINT64 GetData0() const; 926 | UINT64 GetData1() const; 927 | UINT64 GetData2() const; 928 | 929 | // Get/set the full 41 bit instructions. 930 | UINT64 GetInstruction(BYTE slot) const; 931 | UINT64 GetInstruction0() const; 932 | UINT64 GetInstruction1() const; 933 | UINT64 GetInstruction2() const; 934 | void SetInstruction(BYTE slot, UINT64 instruction); 935 | void SetInstruction0(UINT64 instruction); 936 | void SetInstruction1(UINT64 instruction); 937 | void SetInstruction2(UINT64 instruction); 938 | 939 | // Get/set bitfields. 940 | static UINT64 GetBits(UINT64 Value, UINT64 Offset, UINT64 Count); 941 | static UINT64 SetBits(UINT64 Value, UINT64 Offset, UINT64 Count, UINT64 Field); 942 | 943 | // Get specific read-only fields. 944 | static UINT64 GetOpcode(UINT64 instruction); // 4bit opcode 945 | static UINT64 GetX(UINT64 instruction); // 1bit opcode extension 946 | static UINT64 GetX3(UINT64 instruction); // 3bit opcode extension 947 | static UINT64 GetX6(UINT64 instruction); // 6bit opcode extension 948 | 949 | // Get/set specific fields. 950 | static UINT64 GetImm7a(UINT64 instruction); 951 | static UINT64 SetImm7a(UINT64 instruction, UINT64 imm7a); 952 | static UINT64 GetImm13c(UINT64 instruction); 953 | static UINT64 SetImm13c(UINT64 instruction, UINT64 imm13c); 954 | static UINT64 GetSignBit(UINT64 instruction); 955 | static UINT64 SetSignBit(UINT64 instruction, UINT64 signBit); 956 | static UINT64 GetImm20a(UINT64 instruction); 957 | static UINT64 SetImm20a(UINT64 instruction, UINT64 imm20a); 958 | static UINT64 GetImm20b(UINT64 instruction); 959 | static UINT64 SetImm20b(UINT64 instruction, UINT64 imm20b); 960 | 961 | static UINT64 SignExtend(UINT64 Value, UINT64 Offset); 962 | 963 | BOOL IsMovlGp() const; 964 | 965 | VOID SetInst(BYTE Slot, BYTE nInst); 966 | VOID SetInst0(BYTE nInst); 967 | VOID SetInst1(BYTE nInst); 968 | VOID SetInst2(BYTE nInst); 969 | VOID SetData(BYTE Slot, UINT64 nData); 970 | VOID SetData0(UINT64 nData); 971 | VOID SetData1(UINT64 nData); 972 | VOID SetData2(UINT64 nData); 973 | BOOL SetNop(BYTE Slot); 974 | BOOL SetNop0(); 975 | BOOL SetNop1(); 976 | BOOL SetNop2(); 977 | 978 | public: 979 | BOOL IsBrl() const; 980 | VOID SetBrl(); 981 | VOID SetBrl(UINT64 target); 982 | UINT64 GetBrlTarget() const; 983 | VOID SetBrlTarget(UINT64 target); 984 | VOID SetBrlImm(UINT64 imm); 985 | UINT64 GetBrlImm() const; 986 | 987 | UINT64 GetMovlGp() const; 988 | VOID SetMovlGp(UINT64 gp); 989 | 990 | VOID SetStop(); 991 | 992 | UINT Copy(_Out_ DETOUR_IA64_BUNDLE *pDst, _Inout_opt_ DETOUR_IA64_BUNDLE* pBundleExtra = NULL) const; 993 | }; 994 | #endif // DETOURS_IA64 995 | 996 | #ifdef DETOURS_ARM 997 | 998 | #define DETOURS_PFUNC_TO_PBYTE(p) ((PBYTE)(((ULONG_PTR)(p)) & ~(ULONG_PTR)1)) 999 | #define DETOURS_PBYTE_TO_PFUNC(p) ((PBYTE)(((ULONG_PTR)(p)) | (ULONG_PTR)1)) 1000 | 1001 | #endif // DETOURS_ARM 1002 | 1003 | ////////////////////////////////////////////////////////////////////////////// 1004 | 1005 | #ifdef __cplusplus 1006 | extern "C" { 1007 | #endif // __cplusplus 1008 | 1009 | #define DETOUR_OFFLINE_LIBRARY(x) \ 1010 | PVOID WINAPI DetourCopyInstruction##x(_In_opt_ PVOID pDst, \ 1011 | _Inout_opt_ PVOID *ppDstPool, \ 1012 | _In_ PVOID pSrc, \ 1013 | _Out_opt_ PVOID *ppTarget, \ 1014 | _Out_opt_ LONG *plExtra); \ 1015 | \ 1016 | BOOL WINAPI DetourSetCodeModule##x(_In_ HMODULE hModule, \ 1017 | _In_ BOOL fLimitReferencesToModule); \ 1018 | 1019 | DETOUR_OFFLINE_LIBRARY(X86) 1020 | DETOUR_OFFLINE_LIBRARY(X64) 1021 | DETOUR_OFFLINE_LIBRARY(ARM) 1022 | DETOUR_OFFLINE_LIBRARY(ARM64) 1023 | DETOUR_OFFLINE_LIBRARY(IA64) 1024 | 1025 | #undef DETOUR_OFFLINE_LIBRARY 1026 | 1027 | ////////////////////////////////////////////////////////////////////////////// 1028 | // 1029 | // Helpers for manipulating page protection. 1030 | // 1031 | 1032 | _Success_(return != FALSE) 1033 | BOOL WINAPI DetourVirtualProtectSameExecuteEx(_In_ HANDLE hProcess, 1034 | _In_ PVOID pAddress, 1035 | _In_ SIZE_T nSize, 1036 | _In_ DWORD dwNewProtect, 1037 | _Out_ PDWORD pdwOldProtect); 1038 | 1039 | _Success_(return != FALSE) 1040 | BOOL WINAPI DetourVirtualProtectSameExecute(_In_ PVOID pAddress, 1041 | _In_ SIZE_T nSize, 1042 | _In_ DWORD dwNewProtect, 1043 | _Out_ PDWORD pdwOldProtect); 1044 | #ifdef __cplusplus 1045 | } 1046 | #endif // __cplusplus 1047 | 1048 | ////////////////////////////////////////////////////////////////////////////// 1049 | 1050 | #define MM_ALLOCATION_GRANULARITY 0x10000 1051 | 1052 | ////////////////////////////////////////////////////////////////////////////// 1053 | 1054 | #endif // DETOURS_INTERNAL 1055 | #endif // __cplusplus 1056 | 1057 | #endif // _DETOURS_H_ 1058 | // 1059 | //////////////////////////////////////////////////////////////// End of File. 1060 | -------------------------------------------------------------------------------- /ShooterGameCheat/detours/detver.h: -------------------------------------------------------------------------------- 1 | ////////////////////////////////////////////////////////////////////////////// 2 | // 3 | // Common version parameters. 4 | // 5 | // Microsoft Research Detours Package, Version 4.0.1 6 | // 7 | // Copyright (c) Microsoft Corporation. All rights reserved. 8 | // 9 | 10 | #define _USING_V110_SDK71_ 1 11 | #include "winver.h" 12 | #if 0 13 | #include 14 | #include 15 | #else 16 | #ifndef DETOURS_STRINGIFY 17 | #define DETOURS_STRINGIFY(x) DETOURS_STRINGIFY_(x) 18 | #define DETOURS_STRINGIFY_(x) #x 19 | #endif 20 | 21 | #define VER_FILEFLAGSMASK 0x3fL 22 | #define VER_FILEFLAGS 0x0L 23 | #define VER_FILEOS 0x00040004L 24 | #define VER_FILETYPE 0x00000002L 25 | #define VER_FILESUBTYPE 0x00000000L 26 | #endif 27 | #define VER_DETOURS_BITS DETOUR_STRINGIFY(DETOURS_BITS) 28 | -------------------------------------------------------------------------------- /ShooterGameCheat/detours/disolarm.cpp: -------------------------------------------------------------------------------- 1 | #define DETOURS_ARM_OFFLINE_LIBRARY 2 | #include "disasm.cpp" 3 | -------------------------------------------------------------------------------- /ShooterGameCheat/detours/disolarm64.cpp: -------------------------------------------------------------------------------- 1 | #define DETOURS_ARM64_OFFLINE_LIBRARY 2 | #include "disasm.cpp" 3 | -------------------------------------------------------------------------------- /ShooterGameCheat/detours/disolia64.cpp: -------------------------------------------------------------------------------- 1 | #define DETOURS_IA64_OFFLINE_LIBRARY 2 | #include "disasm.cpp" 3 | -------------------------------------------------------------------------------- /ShooterGameCheat/detours/disolx64.cpp: -------------------------------------------------------------------------------- 1 | #define DETOURS_X64_OFFLINE_LIBRARY 2 | #include "disasm.cpp" 3 | -------------------------------------------------------------------------------- /ShooterGameCheat/detours/disolx86.cpp: -------------------------------------------------------------------------------- 1 | #define DETOURS_X86_OFFLINE_LIBRARY 2 | #include "disasm.cpp" 3 | -------------------------------------------------------------------------------- /ShooterGameCheat/detours/image.cpp: -------------------------------------------------------------------------------- 1 | ////////////////////////////////////////////////////////////////////////////// 2 | // 3 | // Image manipulation functions (image.cpp of detours.lib) 4 | // 5 | // Microsoft Research Detours Package, Version 4.0.1 6 | // 7 | // Copyright (c) Microsoft Corporation. All rights reserved. 8 | // 9 | // Used for for payloads, byways, and imports. 10 | // 11 | 12 | #if _MSC_VER >= 1900 13 | #pragma warning(push) 14 | #pragma warning(disable:4091) // empty typedef 15 | #endif 16 | #define _CRT_STDIO_ARBITRARY_WIDE_SPECIFIERS 1 17 | #define _ARM_WINAPI_PARTITION_DESKTOP_SDK_AVAILABLE 1 18 | #include 19 | #if _MSC_VER >= 1310 20 | #pragma warning(push) 21 | #if _MSC_VER > 1400 22 | #pragma warning(disable:6102 6103) // /analyze warnings 23 | #endif 24 | #include 25 | #pragma warning(pop) 26 | #endif 27 | 28 | #if (_MSC_VER < 1299) 29 | #pragma warning(disable: 4710) 30 | #endif 31 | 32 | // #define DETOUR_DEBUG 1 33 | #define DETOURS_INTERNAL 34 | 35 | #include "detours.h" 36 | 37 | #if DETOURS_VERSION != 0x4c0c1 // 0xMAJORcMINORcPATCH 38 | #error detours.h version mismatch 39 | #endif 40 | 41 | #if _MSC_VER >= 1900 42 | #pragma warning(pop) 43 | #endif 44 | 45 | namespace Detour 46 | { 47 | ////////////////////////////////////////////////////////////////////////////// 48 | // 49 | #ifndef _STRSAFE_H_INCLUDED_ 50 | _Must_inspect_result_ 51 | static inline HRESULT StringCchLengthA( 52 | _In_reads_or_z_(cchMax) LPCSTR psz, 53 | _In_ 54 | _In_range_(1, STRSAFE_MAX_CCH) size_t cchMax, 55 | _Out_opt_ 56 | _Deref_out_range_(<, cchMax) 57 | _Deref_out_range_(<=, _String_length_(psz)) 58 | _Out_ size_t* pcch) 59 | { 60 | HRESULT hr = S_OK; 61 | size_t cchMaxPrev = cchMax; 62 | 63 | if (cchMax > 2147483647) { 64 | return ERROR_INVALID_PARAMETER; 65 | } 66 | 67 | while (cchMax && (*psz != '\0')) { 68 | psz++; 69 | cchMax--; 70 | } 71 | 72 | if (cchMax == 0) { 73 | // the string is longer than cchMax 74 | hr = ERROR_INVALID_PARAMETER; 75 | } 76 | 77 | if (SUCCEEDED(hr) && pcch) { 78 | *pcch = cchMaxPrev - cchMax; 79 | } 80 | 81 | return hr; 82 | } 83 | 84 | _Must_inspect_result_ 85 | static inline HRESULT StringCchCopyA( 86 | _Out_writes_(cchDest) _Always_(_Post_z_) LPSTR pszDest, 87 | _In_ size_t cchDest, 88 | _In_ LPCSTR pszSrc) 89 | { 90 | HRESULT hr = S_OK; 91 | 92 | if (cchDest == 0) { 93 | // can not null terminate a zero-byte dest buffer 94 | hr = ERROR_INVALID_PARAMETER; 95 | } 96 | else { 97 | while (cchDest && (*pszSrc != '\0')) { 98 | *pszDest++ = *pszSrc++; 99 | cchDest--; 100 | } 101 | 102 | if (cchDest == 0) { 103 | // we are going to truncate pszDest 104 | pszDest--; 105 | hr = ERROR_INVALID_PARAMETER; 106 | } 107 | 108 | *pszDest= '\0'; 109 | } 110 | 111 | return hr; 112 | } 113 | 114 | _Must_inspect_result_ 115 | static inline HRESULT StringCchCatA( 116 | _Out_writes_(cchDest) _Always_(_Post_z_) LPSTR pszDest, 117 | _In_ size_t cchDest, 118 | _In_ LPCSTR pszSrc) 119 | { 120 | HRESULT hr; 121 | size_t cchDestCurrent; 122 | 123 | if (cchDest > 2147483647){ 124 | return ERROR_INVALID_PARAMETER; 125 | } 126 | 127 | hr = StringCchLengthA(pszDest, cchDest, &cchDestCurrent); 128 | 129 | if (SUCCEEDED(hr) && cchDestCurrent < cchDest) { 130 | hr = StringCchCopyA(pszDest + cchDestCurrent, 131 | cchDest - cchDestCurrent, 132 | pszSrc); 133 | } 134 | 135 | return hr; 136 | } 137 | 138 | #endif 139 | 140 | /////////////////////////////////////////////////////////////////////////////// 141 | // 142 | class CImageData 143 | { 144 | friend class CImage; 145 | 146 | public: 147 | CImageData(PBYTE pbData, DWORD cbData); 148 | ~CImageData(); 149 | 150 | PBYTE Enumerate(GUID *pGuid, DWORD *pcbData, DWORD *pnIterator); 151 | PBYTE Find(REFGUID rguid, DWORD *pcbData); 152 | PBYTE Set(REFGUID rguid, PBYTE pbData, DWORD cbData); 153 | 154 | BOOL Delete(REFGUID rguid); 155 | BOOL Purge(); 156 | 157 | BOOL IsEmpty() { return m_cbData == 0; } 158 | BOOL IsValid(); 159 | 160 | protected: 161 | BOOL SizeTo(DWORD cbData); 162 | 163 | protected: 164 | _Field_size_(m_cbAlloc) 165 | PBYTE m_pbData; 166 | DWORD m_cbData; 167 | DWORD m_cbAlloc; 168 | }; 169 | 170 | class CImageImportFile 171 | { 172 | friend class CImage; 173 | friend class CImageImportName; 174 | 175 | public: 176 | CImageImportFile(); 177 | ~CImageImportFile(); 178 | 179 | public: 180 | CImageImportFile * m_pNextFile; 181 | BOOL m_fByway; 182 | 183 | _Field_size_(m_nImportNames) 184 | CImageImportName * m_pImportNames; 185 | DWORD m_nImportNames; 186 | 187 | DWORD m_rvaOriginalFirstThunk; 188 | DWORD m_rvaFirstThunk; 189 | 190 | DWORD m_nForwarderChain; 191 | LPCSTR m_pszOrig; 192 | LPCSTR m_pszName; 193 | }; 194 | 195 | class CImageImportName 196 | { 197 | friend class CImage; 198 | friend class CImageImportFile; 199 | 200 | public: 201 | CImageImportName(); 202 | ~CImageImportName(); 203 | 204 | public: 205 | WORD m_nHint; 206 | ULONG m_nOrig; 207 | ULONG m_nOrdinal; 208 | LPCSTR m_pszOrig; 209 | LPCSTR m_pszName; 210 | }; 211 | 212 | class CImage 213 | { 214 | friend class CImageThunks; 215 | friend class CImageChars; 216 | friend class CImageImportFile; 217 | friend class CImageImportName; 218 | 219 | public: 220 | CImage(); 221 | ~CImage(); 222 | 223 | static CImage * IsValid(PDETOUR_BINARY pBinary); 224 | 225 | public: // File Functions 226 | BOOL Read(HANDLE hFile); 227 | BOOL Write(HANDLE hFile); 228 | BOOL Close(); 229 | 230 | public: // Manipulation Functions 231 | PBYTE DataEnum(GUID *pGuid, DWORD *pcbData, DWORD *pnIterator); 232 | PBYTE DataFind(REFGUID rguid, DWORD *pcbData); 233 | PBYTE DataSet(REFGUID rguid, PBYTE pbData, DWORD cbData); 234 | BOOL DataDelete(REFGUID rguid); 235 | BOOL DataPurge(); 236 | 237 | BOOL EditImports(PVOID pContext, 238 | PF_DETOUR_BINARY_BYWAY_CALLBACK pfBywayCallback, 239 | PF_DETOUR_BINARY_FILE_CALLBACK pfFileCallback, 240 | PF_DETOUR_BINARY_SYMBOL_CALLBACK pfSymbolCallback, 241 | PF_DETOUR_BINARY_COMMIT_CALLBACK pfCommitCallback); 242 | 243 | protected: 244 | BOOL WriteFile(HANDLE hFile, 245 | LPCVOID lpBuffer, 246 | DWORD nNumberOfBytesToWrite, 247 | LPDWORD lpNumberOfBytesWritten); 248 | BOOL CopyFileData(HANDLE hFile, DWORD nOldPos, DWORD cbData); 249 | BOOL ZeroFileData(HANDLE hFile, DWORD cbData); 250 | BOOL AlignFileData(HANDLE hFile); 251 | 252 | BOOL SizeOutputBuffer(DWORD cbData); 253 | PBYTE AllocateOutput(DWORD cbData, DWORD *pnVirtAddr); 254 | 255 | PVOID RvaToVa(ULONG_PTR nRva); 256 | DWORD RvaToFileOffset(DWORD nRva); 257 | 258 | DWORD FileAlign(DWORD nAddr); 259 | DWORD SectionAlign(DWORD nAddr); 260 | 261 | BOOL CheckImportsNeeded(DWORD *pnTables, 262 | DWORD *pnThunks, 263 | DWORD *pnChars); 264 | 265 | CImageImportFile * NewByway(_In_ LPCSTR pszName); 266 | 267 | private: 268 | DWORD m_dwValidSignature; 269 | CImageData * m_pImageData; // Read & Write 270 | 271 | HANDLE m_hMap; // Read & Write 272 | PBYTE m_pMap; // Read & Write 273 | 274 | DWORD m_nNextFileAddr; // Write 275 | DWORD m_nNextVirtAddr; // Write 276 | 277 | IMAGE_DOS_HEADER m_DosHeader; // Read & Write 278 | IMAGE_NT_HEADERS m_NtHeader; // Read & Write 279 | IMAGE_SECTION_HEADER m_SectionHeaders[IMAGE_NUMBEROF_DIRECTORY_ENTRIES]; 280 | 281 | DWORD m_nPrePE; 282 | DWORD m_cbPrePE; 283 | DWORD m_cbPostPE; 284 | 285 | DWORD m_nPeOffset; 286 | DWORD m_nSectionsOffset; 287 | DWORD m_nExtraOffset; 288 | DWORD m_nFileSize; 289 | 290 | DWORD m_nOutputVirtAddr; 291 | DWORD m_nOutputVirtSize; 292 | DWORD m_nOutputFileAddr; 293 | 294 | _Field_size_(m_cbOutputBuffer) 295 | PBYTE m_pbOutputBuffer; 296 | DWORD m_cbOutputBuffer; 297 | 298 | CImageImportFile * m_pImportFiles; 299 | DWORD m_nImportFiles; 300 | 301 | BOOL m_fHadDetourSection; 302 | 303 | private: 304 | enum { 305 | DETOUR_IMAGE_VALID_SIGNATURE = 0xfedcba01, // "Dtr\0" 306 | }; 307 | }; 308 | 309 | ////////////////////////////////////////////////////////////////////////////// 310 | // 311 | static BYTE s_rbDosCode[0x10] = { 312 | 0x0E,0x1F,0xBA,0x0E,0x00,0xB4,0x09,0xCD, 313 | 0x21,0xB8,0x01,0x4C,0xCD,0x21,'*','*' 314 | }; 315 | 316 | static inline DWORD Max(DWORD a, DWORD b) 317 | { 318 | return a > b ? a : b; 319 | } 320 | 321 | static inline DWORD Align(DWORD a, DWORD size) 322 | { 323 | size--; 324 | return (a + size) & ~size; 325 | } 326 | 327 | static inline DWORD QuadAlign(DWORD a) 328 | { 329 | return Align(a, 8); 330 | } 331 | 332 | static LPCSTR DuplicateString(_In_ LPCSTR pszIn) 333 | { 334 | if (pszIn == NULL) { 335 | return NULL; 336 | } 337 | 338 | size_t cch; 339 | HRESULT hr = StringCchLengthA(pszIn, 8192, &cch); 340 | if (FAILED(hr)) { 341 | SetLastError(ERROR_INVALID_PARAMETER); 342 | return NULL; 343 | } 344 | 345 | PCHAR pszOut = new NOTHROW CHAR [cch + 1]; 346 | if (pszOut == NULL) { 347 | SetLastError(ERROR_OUTOFMEMORY); 348 | return NULL; 349 | } 350 | 351 | hr = StringCchCopyA(pszOut, cch + 1, pszIn); 352 | if (FAILED(hr)) { 353 | delete[] pszOut; 354 | return NULL; 355 | } 356 | 357 | return pszOut; 358 | } 359 | 360 | static VOID ReleaseString(_In_opt_ LPCSTR psz) 361 | { 362 | if (psz != NULL) { 363 | delete[] psz; 364 | } 365 | } 366 | 367 | ////////////////////////////////////////////////////////////////////////////// 368 | // 369 | CImageImportFile::CImageImportFile() 370 | { 371 | m_pNextFile = NULL; 372 | m_fByway = FALSE; 373 | 374 | m_pImportNames = NULL; 375 | m_nImportNames = 0; 376 | 377 | m_rvaOriginalFirstThunk = 0; 378 | m_rvaFirstThunk = 0; 379 | 380 | m_nForwarderChain = (UINT)0; 381 | m_pszName = NULL; 382 | m_pszOrig = NULL; 383 | } 384 | 385 | CImageImportFile::~CImageImportFile() 386 | { 387 | if (m_pNextFile) { 388 | delete m_pNextFile; 389 | m_pNextFile = NULL; 390 | } 391 | if (m_pImportNames) { 392 | delete[] m_pImportNames; 393 | m_pImportNames = NULL; 394 | m_nImportNames = 0; 395 | } 396 | if (m_pszName) { 397 | delete[] m_pszName; 398 | m_pszName = NULL; 399 | } 400 | if (m_pszOrig) { 401 | delete[] m_pszOrig; 402 | m_pszOrig = NULL; 403 | } 404 | } 405 | 406 | CImageImportName::CImageImportName() 407 | { 408 | m_nOrig = 0; 409 | m_nOrdinal = 0; 410 | m_nHint = 0; 411 | m_pszName = NULL; 412 | m_pszOrig = NULL; 413 | } 414 | 415 | CImageImportName::~CImageImportName() 416 | { 417 | if (m_pszName) { 418 | delete[] m_pszName; 419 | m_pszName = NULL; 420 | } 421 | if (m_pszOrig) { 422 | delete[] m_pszOrig; 423 | m_pszOrig = NULL; 424 | } 425 | } 426 | 427 | ////////////////////////////////////////////////////////////////////////////// 428 | // 429 | CImageData::CImageData(PBYTE pbData, DWORD cbData) 430 | { 431 | m_pbData = pbData; 432 | m_cbData = cbData; 433 | m_cbAlloc = 0; 434 | } 435 | 436 | CImageData::~CImageData() 437 | { 438 | IsValid(); 439 | 440 | if (m_cbAlloc == 0) { 441 | m_pbData = NULL; 442 | } 443 | if (m_pbData) { 444 | delete[] m_pbData; 445 | m_pbData = NULL; 446 | } 447 | m_cbData = 0; 448 | m_cbAlloc = 0; 449 | } 450 | 451 | BOOL CImageData::SizeTo(DWORD cbData) 452 | { 453 | IsValid(); 454 | 455 | if (cbData <= m_cbAlloc) { 456 | return TRUE; 457 | } 458 | 459 | PBYTE pbNew = new NOTHROW BYTE [cbData]; 460 | if (pbNew == NULL) { 461 | SetLastError(ERROR_OUTOFMEMORY); 462 | return FALSE; 463 | } 464 | 465 | if (m_pbData) { 466 | CopyMemory(pbNew, m_pbData, m_cbData); 467 | if (m_cbAlloc > 0) { 468 | delete[] m_pbData; 469 | } 470 | m_pbData = NULL; 471 | } 472 | m_pbData = pbNew; 473 | m_cbAlloc = cbData; 474 | 475 | IsValid(); 476 | 477 | return TRUE; 478 | } 479 | 480 | BOOL CImageData::Purge() 481 | { 482 | m_cbData = 0; 483 | 484 | IsValid(); 485 | 486 | return TRUE; 487 | } 488 | 489 | BOOL CImageData::IsValid() 490 | { 491 | if (m_pbData == NULL) { 492 | return TRUE; 493 | } 494 | 495 | PBYTE pbBeg = m_pbData; 496 | PBYTE pbEnd = m_pbData + m_cbData; 497 | 498 | for (PBYTE pbIter = pbBeg; pbIter < pbEnd;) { 499 | PDETOUR_SECTION_RECORD pRecord = (PDETOUR_SECTION_RECORD)pbIter; 500 | 501 | if (pRecord->cbBytes < sizeof(DETOUR_SECTION_RECORD)) { 502 | return FALSE; 503 | } 504 | if (pRecord->nReserved != 0) { 505 | return FALSE; 506 | } 507 | 508 | pbIter += pRecord->cbBytes; 509 | } 510 | return TRUE; 511 | } 512 | 513 | PBYTE CImageData::Enumerate(GUID *pGuid, DWORD *pcbData, DWORD *pnIterator) 514 | { 515 | IsValid(); 516 | 517 | if (pnIterator == NULL || 518 | m_cbData < *pnIterator + sizeof(DETOUR_SECTION_RECORD)) { 519 | 520 | if (pcbData) { 521 | *pcbData = 0; 522 | } 523 | if (pGuid) { 524 | ZeroMemory(pGuid, sizeof(*pGuid)); 525 | } 526 | return NULL; 527 | } 528 | 529 | PDETOUR_SECTION_RECORD pRecord = (PDETOUR_SECTION_RECORD)(m_pbData + *pnIterator); 530 | 531 | if (pGuid) { 532 | *pGuid = pRecord->guid; 533 | } 534 | if (pcbData) { 535 | *pcbData = pRecord->cbBytes - sizeof(DETOUR_SECTION_RECORD); 536 | } 537 | *pnIterator = (LONG)(((PBYTE)pRecord - m_pbData) + pRecord->cbBytes); 538 | 539 | return (PBYTE)(pRecord + 1); 540 | } 541 | 542 | PBYTE CImageData::Find(REFGUID rguid, DWORD *pcbData) 543 | { 544 | IsValid(); 545 | 546 | DWORD cbBytes = sizeof(DETOUR_SECTION_RECORD); 547 | for (DWORD nOffset = 0; nOffset < m_cbData; nOffset += cbBytes) { 548 | PDETOUR_SECTION_RECORD pRecord = (PDETOUR_SECTION_RECORD)(m_pbData + nOffset); 549 | 550 | cbBytes = pRecord->cbBytes; 551 | if (cbBytes > m_cbData) { 552 | break; 553 | } 554 | if (cbBytes < sizeof(DETOUR_SECTION_RECORD)) { 555 | continue; 556 | } 557 | 558 | if (pRecord->guid.Data1 == rguid.Data1 && 559 | pRecord->guid.Data2 == rguid.Data2 && 560 | pRecord->guid.Data3 == rguid.Data3 && 561 | pRecord->guid.Data4[0] == rguid.Data4[0] && 562 | pRecord->guid.Data4[1] == rguid.Data4[1] && 563 | pRecord->guid.Data4[2] == rguid.Data4[2] && 564 | pRecord->guid.Data4[3] == rguid.Data4[3] && 565 | pRecord->guid.Data4[4] == rguid.Data4[4] && 566 | pRecord->guid.Data4[5] == rguid.Data4[5] && 567 | pRecord->guid.Data4[6] == rguid.Data4[6] && 568 | pRecord->guid.Data4[7] == rguid.Data4[7]) { 569 | 570 | *pcbData = cbBytes - sizeof(DETOUR_SECTION_RECORD); 571 | return (PBYTE)(pRecord + 1); 572 | } 573 | } 574 | 575 | if (pcbData) { 576 | *pcbData = 0; 577 | } 578 | return NULL; 579 | } 580 | 581 | BOOL CImageData::Delete(REFGUID rguid) 582 | { 583 | IsValid(); 584 | 585 | PBYTE pbFound = NULL; 586 | DWORD cbFound = 0; 587 | 588 | pbFound = Find(rguid, &cbFound); 589 | if (pbFound == NULL) { 590 | SetLastError(ERROR_MOD_NOT_FOUND); 591 | return FALSE; 592 | } 593 | 594 | pbFound -= sizeof(DETOUR_SECTION_RECORD); 595 | cbFound += sizeof(DETOUR_SECTION_RECORD); 596 | 597 | PBYTE pbRestData = pbFound + cbFound; 598 | DWORD cbRestData = m_cbData - (LONG)(pbRestData - m_pbData); 599 | 600 | if (cbRestData) { 601 | MoveMemory(pbFound, pbRestData, cbRestData); 602 | } 603 | m_cbData -= cbFound; 604 | 605 | IsValid(); 606 | return TRUE; 607 | } 608 | 609 | PBYTE CImageData::Set(REFGUID rguid, PBYTE pbData, DWORD cbData) 610 | { 611 | IsValid(); 612 | Delete(rguid); 613 | 614 | DWORD cbAlloc = QuadAlign(cbData); 615 | 616 | if (!SizeTo(m_cbData + cbAlloc + sizeof(DETOUR_SECTION_RECORD))) { 617 | return NULL; 618 | } 619 | 620 | PDETOUR_SECTION_RECORD pRecord = (PDETOUR_SECTION_RECORD)(m_pbData + m_cbData); 621 | pRecord->cbBytes = cbAlloc + sizeof(DETOUR_SECTION_RECORD); 622 | pRecord->nReserved = 0; 623 | pRecord->guid = rguid; 624 | 625 | PBYTE pbDest = (PBYTE)(pRecord + 1); 626 | if (pbData) { 627 | CopyMemory(pbDest, pbData, cbData); 628 | if (cbData < cbAlloc) { 629 | ZeroMemory(pbDest + cbData, cbAlloc - cbData); 630 | } 631 | } 632 | else { 633 | if (cbAlloc > 0) { 634 | ZeroMemory(pbDest, cbAlloc); 635 | } 636 | } 637 | 638 | m_cbData += cbAlloc + sizeof(DETOUR_SECTION_RECORD); 639 | 640 | IsValid(); 641 | return pbDest; 642 | } 643 | 644 | ////////////////////////////////////////////////////////////////////////////// 645 | // 646 | class CImageThunks 647 | { 648 | private: 649 | CImage * m_pImage; 650 | PIMAGE_THUNK_DATA m_pThunks; 651 | DWORD m_nThunks; 652 | DWORD m_nThunksMax; 653 | DWORD m_nThunkVirtAddr; 654 | 655 | public: 656 | CImageThunks(CImage *pImage, DWORD nThunksMax, DWORD *pnAddr) 657 | { 658 | m_pImage = pImage; 659 | m_nThunks = 0; 660 | m_nThunksMax = nThunksMax; 661 | m_pThunks = (PIMAGE_THUNK_DATA) 662 | m_pImage->AllocateOutput(sizeof(IMAGE_THUNK_DATA) * nThunksMax, 663 | &m_nThunkVirtAddr); 664 | *pnAddr = m_nThunkVirtAddr; 665 | } 666 | 667 | PIMAGE_THUNK_DATA Current(DWORD *pnVirtAddr) 668 | { 669 | if (m_nThunksMax > 1) { 670 | *pnVirtAddr = m_nThunkVirtAddr; 671 | return m_pThunks; 672 | } 673 | *pnVirtAddr = 0; 674 | return NULL; 675 | } 676 | 677 | PIMAGE_THUNK_DATA Allocate(ULONG_PTR nData, DWORD *pnVirtAddr) 678 | { 679 | if (m_nThunks < m_nThunksMax) { 680 | *pnVirtAddr = m_nThunkVirtAddr; 681 | 682 | m_nThunks++; 683 | m_nThunkVirtAddr += sizeof(IMAGE_THUNK_DATA); 684 | m_pThunks->u1.Ordinal = nData; 685 | return m_pThunks++; 686 | } 687 | *pnVirtAddr = 0; 688 | return NULL; 689 | } 690 | 691 | DWORD Size() 692 | { 693 | return m_nThunksMax * sizeof(IMAGE_THUNK_DATA); 694 | } 695 | }; 696 | 697 | ////////////////////////////////////////////////////////////////////////////// 698 | // 699 | class CImageChars 700 | { 701 | private: 702 | CImage * m_pImage; 703 | PCHAR m_pChars; 704 | DWORD m_nChars; 705 | DWORD m_nCharsMax; 706 | DWORD m_nCharVirtAddr; 707 | 708 | public: 709 | CImageChars(CImage *pImage, _In_ DWORD nCharsMax, _Out_ DWORD *pnAddr) 710 | { 711 | m_pImage = pImage; 712 | m_nChars = 0; 713 | m_nCharsMax = nCharsMax; 714 | m_pChars = (PCHAR)m_pImage->AllocateOutput(nCharsMax, &m_nCharVirtAddr); 715 | *pnAddr = m_nCharVirtAddr; 716 | } 717 | 718 | LPCSTR Allocate(_In_ LPCSTR pszString, _Out_ DWORD *pnVirtAddr) 719 | { 720 | DWORD nLen = (DWORD)strlen(pszString) + 1; 721 | nLen += (nLen & 1); 722 | 723 | if (m_nChars + nLen > m_nCharsMax) { 724 | *pnVirtAddr = 0; 725 | return NULL; 726 | } 727 | 728 | *pnVirtAddr = m_nCharVirtAddr; 729 | HRESULT hrRet = StringCchCopyA(m_pChars, m_nCharsMax, pszString); 730 | 731 | if (FAILED(hrRet)) { 732 | return NULL; 733 | } 734 | 735 | pszString = m_pChars; 736 | 737 | m_pChars += nLen; 738 | m_nChars += nLen; 739 | m_nCharVirtAddr += nLen; 740 | 741 | return pszString; 742 | } 743 | 744 | LPCSTR Allocate(_In_ LPCSTR pszString, _In_ DWORD nHint, _Out_ DWORD *pnVirtAddr) 745 | { 746 | DWORD nLen = (DWORD)strlen(pszString) + 1 + sizeof(USHORT); 747 | nLen += (nLen & 1); 748 | 749 | if (m_nChars + nLen > m_nCharsMax) { 750 | *pnVirtAddr = 0; 751 | return NULL; 752 | } 753 | 754 | *pnVirtAddr = m_nCharVirtAddr; 755 | *(USHORT *)m_pChars = (USHORT)nHint; 756 | 757 | HRESULT hrRet = StringCchCopyA(m_pChars + sizeof(USHORT), m_nCharsMax, pszString); 758 | if (FAILED(hrRet)) { 759 | return NULL; 760 | } 761 | 762 | pszString = m_pChars + sizeof(USHORT); 763 | 764 | m_pChars += nLen; 765 | m_nChars += nLen; 766 | m_nCharVirtAddr += nLen; 767 | 768 | return pszString; 769 | } 770 | 771 | DWORD Size() 772 | { 773 | return m_nChars; 774 | } 775 | }; 776 | 777 | ////////////////////////////////////////////////////////////////////////////// 778 | // 779 | CImage * CImage::IsValid(PDETOUR_BINARY pBinary) 780 | { 781 | if (pBinary) { 782 | CImage *pImage = (CImage *)pBinary; 783 | 784 | if (pImage->m_dwValidSignature == DETOUR_IMAGE_VALID_SIGNATURE) { 785 | return pImage; 786 | } 787 | } 788 | SetLastError(ERROR_INVALID_HANDLE); 789 | return NULL; 790 | } 791 | 792 | CImage::CImage() 793 | { 794 | m_dwValidSignature = (DWORD)DETOUR_IMAGE_VALID_SIGNATURE; 795 | 796 | m_hMap = NULL; 797 | m_pMap = NULL; 798 | 799 | m_nPeOffset = 0; 800 | m_nSectionsOffset = 0; 801 | 802 | m_pbOutputBuffer = NULL; 803 | m_cbOutputBuffer = 0; 804 | 805 | m_pImageData = NULL; 806 | 807 | m_pImportFiles = NULL; 808 | m_nImportFiles = 0; 809 | 810 | m_fHadDetourSection = FALSE; 811 | } 812 | 813 | CImage::~CImage() 814 | { 815 | Close(); 816 | m_dwValidSignature = 0; 817 | } 818 | 819 | BOOL CImage::Close() 820 | { 821 | if (m_pImportFiles) { 822 | delete m_pImportFiles; 823 | m_pImportFiles = NULL; 824 | m_nImportFiles = 0; 825 | } 826 | 827 | if (m_pImageData) { 828 | delete m_pImageData; 829 | m_pImageData = NULL; 830 | } 831 | 832 | if (m_pMap != NULL) { 833 | UnmapViewOfFile(m_pMap); 834 | m_pMap = NULL; 835 | } 836 | 837 | if (m_hMap) { 838 | CloseHandle(m_hMap); 839 | m_hMap = NULL; 840 | } 841 | 842 | if (m_pbOutputBuffer) { 843 | delete[] m_pbOutputBuffer; 844 | m_pbOutputBuffer = NULL; 845 | m_cbOutputBuffer = 0; 846 | } 847 | return TRUE; 848 | } 849 | 850 | ////////////////////////////////////////////////////////////////////////////// 851 | // 852 | PBYTE CImage::DataEnum(GUID *pGuid, DWORD *pcbData, DWORD *pnIterator) 853 | { 854 | if (m_pImageData == NULL) { 855 | return NULL; 856 | } 857 | return m_pImageData->Enumerate(pGuid, pcbData, pnIterator); 858 | } 859 | 860 | PBYTE CImage::DataFind(REFGUID rguid, DWORD *pcbData) 861 | { 862 | if (m_pImageData == NULL) { 863 | return NULL; 864 | } 865 | return m_pImageData->Find(rguid, pcbData); 866 | } 867 | 868 | PBYTE CImage::DataSet(REFGUID rguid, PBYTE pbData, DWORD cbData) 869 | { 870 | if (m_pImageData == NULL) { 871 | return NULL; 872 | } 873 | return m_pImageData->Set(rguid, pbData, cbData); 874 | } 875 | 876 | BOOL CImage::DataDelete(REFGUID rguid) 877 | { 878 | if (m_pImageData == NULL) { 879 | return FALSE; 880 | } 881 | return m_pImageData->Delete(rguid); 882 | } 883 | 884 | BOOL CImage::DataPurge() 885 | { 886 | if (m_pImageData == NULL) { 887 | return TRUE; 888 | } 889 | return m_pImageData->Purge(); 890 | } 891 | 892 | ////////////////////////////////////////////////////////////////////////////// 893 | // 894 | BOOL CImage::SizeOutputBuffer(DWORD cbData) 895 | { 896 | if (m_cbOutputBuffer < cbData) { 897 | if (cbData < 1024) {//65536 898 | cbData = 1024; 899 | } 900 | cbData = FileAlign(cbData); 901 | 902 | PBYTE pOutput = new NOTHROW BYTE [cbData]; 903 | if (pOutput == NULL) { 904 | SetLastError(ERROR_OUTOFMEMORY); 905 | return FALSE; 906 | } 907 | 908 | if (m_pbOutputBuffer) { 909 | CopyMemory(pOutput, m_pbOutputBuffer, m_cbOutputBuffer); 910 | 911 | delete[] m_pbOutputBuffer; 912 | m_pbOutputBuffer = NULL; 913 | } 914 | 915 | ZeroMemory(pOutput + m_cbOutputBuffer, cbData - m_cbOutputBuffer), 916 | 917 | m_pbOutputBuffer = pOutput; 918 | m_cbOutputBuffer = cbData; 919 | } 920 | return TRUE; 921 | } 922 | 923 | PBYTE CImage::AllocateOutput(DWORD cbData, DWORD *pnVirtAddr) 924 | { 925 | cbData = QuadAlign(cbData); 926 | 927 | PBYTE pbData = m_pbOutputBuffer + m_nOutputVirtSize; 928 | 929 | *pnVirtAddr = m_nOutputVirtAddr + m_nOutputVirtSize; 930 | m_nOutputVirtSize += cbData; 931 | 932 | if (m_nOutputVirtSize > m_cbOutputBuffer) { 933 | SetLastError(ERROR_OUTOFMEMORY); 934 | return NULL; 935 | } 936 | 937 | ZeroMemory(pbData, cbData); 938 | 939 | return pbData; 940 | } 941 | 942 | ////////////////////////////////////////////////////////////////////////////// 943 | // 944 | DWORD CImage::FileAlign(DWORD nAddr) 945 | { 946 | return Align(nAddr, m_NtHeader.OptionalHeader.FileAlignment); 947 | } 948 | 949 | DWORD CImage::SectionAlign(DWORD nAddr) 950 | { 951 | return Align(nAddr, m_NtHeader.OptionalHeader.SectionAlignment); 952 | } 953 | 954 | ////////////////////////////////////////////////////////////////////////////// 955 | // 956 | PVOID CImage::RvaToVa(ULONG_PTR nRva) 957 | { 958 | if (nRva == 0) { 959 | return NULL; 960 | } 961 | 962 | for (DWORD n = 0; n < m_NtHeader.FileHeader.NumberOfSections; n++) { 963 | DWORD vaStart = m_SectionHeaders[n].VirtualAddress; 964 | DWORD vaEnd = vaStart + m_SectionHeaders[n].SizeOfRawData; 965 | 966 | if (nRva >= vaStart && nRva < vaEnd) { 967 | return (PBYTE)m_pMap 968 | + m_SectionHeaders[n].PointerToRawData 969 | + nRva - m_SectionHeaders[n].VirtualAddress; 970 | } 971 | } 972 | return NULL; 973 | } 974 | 975 | DWORD CImage::RvaToFileOffset(DWORD nRva) 976 | { 977 | DWORD n; 978 | for (n = 0; n < m_NtHeader.FileHeader.NumberOfSections; n++) { 979 | DWORD vaStart = m_SectionHeaders[n].VirtualAddress; 980 | DWORD vaEnd = vaStart + m_SectionHeaders[n].SizeOfRawData; 981 | 982 | if (nRva >= vaStart && nRva < vaEnd) { 983 | return m_SectionHeaders[n].PointerToRawData 984 | + nRva - m_SectionHeaders[n].VirtualAddress; 985 | } 986 | } 987 | return 0; 988 | } 989 | 990 | ////////////////////////////////////////////////////////////////////////////// 991 | // 992 | BOOL CImage::WriteFile(HANDLE hFile, LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite, 993 | LPDWORD lpNumberOfBytesWritten) 994 | { 995 | return ::WriteFile(hFile, 996 | lpBuffer, 997 | nNumberOfBytesToWrite, 998 | lpNumberOfBytesWritten, 999 | NULL); 1000 | } 1001 | 1002 | 1003 | BOOL CImage::CopyFileData(HANDLE hFile, DWORD nOldPos, DWORD cbData) 1004 | { 1005 | DWORD cbDone = 0; 1006 | return WriteFile(hFile, m_pMap + nOldPos, cbData, &cbDone); 1007 | } 1008 | 1009 | BOOL CImage::ZeroFileData(HANDLE hFile, DWORD cbData) 1010 | { 1011 | if (!SizeOutputBuffer(4096)) { 1012 | return FALSE; 1013 | } 1014 | 1015 | ZeroMemory(m_pbOutputBuffer, 4096); 1016 | 1017 | for (DWORD cbLeft = cbData; cbLeft > 0;) { 1018 | DWORD cbStep = cbLeft > sizeof(m_pbOutputBuffer) 1019 | ? sizeof(m_pbOutputBuffer) : cbLeft; 1020 | DWORD cbDone = 0; 1021 | 1022 | if (!WriteFile(hFile, m_pbOutputBuffer, cbStep, &cbDone)) { 1023 | return FALSE; 1024 | } 1025 | if (cbDone == 0) { 1026 | break; 1027 | } 1028 | 1029 | cbLeft -= cbDone; 1030 | } 1031 | return TRUE; 1032 | } 1033 | 1034 | BOOL CImage::AlignFileData(HANDLE hFile) 1035 | { 1036 | DWORD nLastFileAddr = m_nNextFileAddr; 1037 | 1038 | m_nNextFileAddr = FileAlign(m_nNextFileAddr); 1039 | m_nNextVirtAddr = SectionAlign(m_nNextVirtAddr); 1040 | 1041 | if (hFile != INVALID_HANDLE_VALUE) { 1042 | if (m_nNextFileAddr > nLastFileAddr) { 1043 | if (SetFilePointer(hFile, nLastFileAddr, NULL, FILE_BEGIN) == ~0u) { 1044 | return FALSE; 1045 | } 1046 | return ZeroFileData(hFile, m_nNextFileAddr - nLastFileAddr); 1047 | } 1048 | } 1049 | return TRUE; 1050 | } 1051 | 1052 | BOOL CImage::Read(HANDLE hFile) 1053 | { 1054 | DWORD n; 1055 | PBYTE pbData = NULL; 1056 | DWORD cbData = 0; 1057 | 1058 | if (hFile == INVALID_HANDLE_VALUE) { 1059 | SetLastError(ERROR_INVALID_HANDLE); 1060 | return FALSE; 1061 | } 1062 | 1063 | ///////////////////////////////////////////////////////// Create mapping. 1064 | // 1065 | m_nFileSize = GetFileSize(hFile, NULL); 1066 | if (m_nFileSize == (DWORD)-1) { 1067 | return FALSE; 1068 | } 1069 | 1070 | m_hMap = CreateFileMappingW(hFile, NULL, PAGE_READONLY, 0, 0, NULL); 1071 | if (m_hMap == NULL) { 1072 | return FALSE; 1073 | } 1074 | 1075 | m_pMap = (PBYTE)MapViewOfFileEx(m_hMap, FILE_MAP_READ, 0, 0, 0, NULL); 1076 | if (m_pMap == NULL) { 1077 | return FALSE; 1078 | } 1079 | 1080 | ////////////////////////////////////////////////////// Process DOS Header. 1081 | // 1082 | PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)m_pMap; 1083 | if (pDosHeader->e_magic != IMAGE_DOS_SIGNATURE) { 1084 | SetLastError(ERROR_BAD_EXE_FORMAT); 1085 | return FALSE; 1086 | } 1087 | m_nPeOffset = pDosHeader->e_lfanew; 1088 | m_nPrePE = 0; 1089 | m_cbPrePE = QuadAlign(pDosHeader->e_lfanew); 1090 | 1091 | if (m_nPeOffset > m_nFileSize || 1092 | m_nPeOffset + sizeof(m_NtHeader) > m_nFileSize) { 1093 | 1094 | SetLastError(ERROR_BAD_EXE_FORMAT); 1095 | return FALSE; 1096 | } 1097 | 1098 | CopyMemory(&m_DosHeader, m_pMap + m_nPrePE, sizeof(m_DosHeader)); 1099 | 1100 | /////////////////////////////////////////////////////// Process PE Header. 1101 | // 1102 | CopyMemory(&m_NtHeader, m_pMap + m_nPeOffset, sizeof(m_NtHeader)); 1103 | if (m_NtHeader.Signature != IMAGE_NT_SIGNATURE) { 1104 | SetLastError(ERROR_INVALID_EXE_SIGNATURE); 1105 | return FALSE; 1106 | } 1107 | if (m_NtHeader.FileHeader.SizeOfOptionalHeader == 0) { 1108 | SetLastError(ERROR_EXE_MARKED_INVALID); 1109 | return FALSE; 1110 | } 1111 | m_nSectionsOffset = m_nPeOffset 1112 | + sizeof(m_NtHeader.Signature) 1113 | + sizeof(m_NtHeader.FileHeader) 1114 | + m_NtHeader.FileHeader.SizeOfOptionalHeader; 1115 | 1116 | ///////////////////////////////////////////////// Process Section Headers. 1117 | // 1118 | if (m_NtHeader.FileHeader.NumberOfSections > ARRAYSIZE(m_SectionHeaders)) { 1119 | SetLastError(ERROR_EXE_MARKED_INVALID); 1120 | return FALSE; 1121 | } 1122 | CopyMemory(&m_SectionHeaders, 1123 | m_pMap + m_nSectionsOffset, 1124 | sizeof(m_SectionHeaders[0]) * m_NtHeader.FileHeader.NumberOfSections); 1125 | 1126 | /////////////////////////////////////////////////// Parse .detour Section. 1127 | // 1128 | DWORD rvaOriginalImageDirectory = 0; 1129 | DWORD rvaDetourBeg = 0; 1130 | DWORD rvaDetourEnd = 0; 1131 | 1132 | _Analysis_assume_(m_NtHeader.FileHeader.NumberOfSections <= ARRAYSIZE(m_SectionHeaders)); 1133 | 1134 | for (n = 0; n < m_NtHeader.FileHeader.NumberOfSections; n++) { 1135 | if (strcmp((PCHAR)m_SectionHeaders[n].Name, ".detour") == 0) { 1136 | DETOUR_SECTION_HEADER dh; 1137 | CopyMemory(&dh, 1138 | m_pMap + m_SectionHeaders[n].PointerToRawData, 1139 | sizeof(dh)); 1140 | 1141 | rvaOriginalImageDirectory = dh.nOriginalImportVirtualAddress; 1142 | if (dh.cbPrePE != 0) { 1143 | m_nPrePE = m_SectionHeaders[n].PointerToRawData + sizeof(dh); 1144 | m_cbPrePE = dh.cbPrePE; 1145 | } 1146 | rvaDetourBeg = m_SectionHeaders[n].VirtualAddress; 1147 | rvaDetourEnd = rvaDetourBeg + m_SectionHeaders[n].SizeOfRawData; 1148 | } 1149 | } 1150 | 1151 | //////////////////////////////////////////////////////// Get Import Table. 1152 | // 1153 | DWORD rvaImageDirectory = m_NtHeader.OptionalHeader 1154 | .DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress; 1155 | PIMAGE_IMPORT_DESCRIPTOR iidp 1156 | = (PIMAGE_IMPORT_DESCRIPTOR)RvaToVa(rvaImageDirectory); 1157 | PIMAGE_IMPORT_DESCRIPTOR oidp 1158 | = (PIMAGE_IMPORT_DESCRIPTOR)RvaToVa(rvaOriginalImageDirectory); 1159 | 1160 | if (oidp == NULL) { 1161 | oidp = iidp; 1162 | } 1163 | if (iidp == NULL || oidp == NULL) { 1164 | SetLastError(ERROR_EXE_MARKED_INVALID); 1165 | return FALSE; 1166 | } 1167 | 1168 | DWORD nFiles = 0; 1169 | for (; iidp[nFiles].OriginalFirstThunk != 0 || iidp[nFiles].FirstThunk != 0; nFiles++) { 1170 | } 1171 | 1172 | CImageImportFile **ppLastFile = &m_pImportFiles; 1173 | m_pImportFiles = NULL; 1174 | 1175 | for (n = 0; n < nFiles; n++, iidp++) { 1176 | ULONG_PTR rvaName = iidp->Name; 1177 | PCHAR pszName = (PCHAR)RvaToVa(rvaName); 1178 | if (pszName == NULL) { 1179 | SetLastError(ERROR_EXE_MARKED_INVALID); 1180 | goto fail; 1181 | } 1182 | 1183 | CImageImportFile *pImportFile = new NOTHROW CImageImportFile; 1184 | if (pImportFile == NULL) { 1185 | SetLastError(ERROR_OUTOFMEMORY); 1186 | goto fail; 1187 | } 1188 | 1189 | *ppLastFile = pImportFile; 1190 | ppLastFile = &pImportFile->m_pNextFile; 1191 | m_nImportFiles++; 1192 | 1193 | pImportFile->m_pszName = DuplicateString(pszName); 1194 | if (pImportFile->m_pszName == NULL) { 1195 | goto fail; 1196 | } 1197 | 1198 | pImportFile->m_rvaOriginalFirstThunk = iidp->OriginalFirstThunk; 1199 | pImportFile->m_rvaFirstThunk = iidp->FirstThunk; 1200 | pImportFile->m_nForwarderChain = iidp->ForwarderChain; 1201 | pImportFile->m_pImportNames = NULL; 1202 | pImportFile->m_nImportNames = 0; 1203 | pImportFile->m_fByway = FALSE; 1204 | 1205 | if ((ULONG)iidp->FirstThunk >= rvaDetourBeg && 1206 | (ULONG)iidp->FirstThunk < rvaDetourEnd) { 1207 | 1208 | pImportFile->m_pszOrig = NULL; 1209 | pImportFile->m_fByway = TRUE; 1210 | continue; 1211 | } 1212 | 1213 | rvaName = oidp->Name; 1214 | pszName = (PCHAR)RvaToVa(rvaName); 1215 | if (pszName == NULL) { 1216 | SetLastError(ERROR_EXE_MARKED_INVALID); 1217 | goto fail; 1218 | } 1219 | pImportFile->m_pszOrig = DuplicateString(pszName); 1220 | if (pImportFile->m_pszOrig == NULL) { 1221 | goto fail; 1222 | } 1223 | 1224 | DWORD rvaThunk = iidp->OriginalFirstThunk; 1225 | if( !rvaThunk ) { 1226 | rvaThunk = iidp->FirstThunk; 1227 | } 1228 | PIMAGE_THUNK_DATA pAddrThunk = (PIMAGE_THUNK_DATA)RvaToVa(rvaThunk); 1229 | rvaThunk = oidp->OriginalFirstThunk; 1230 | if( !rvaThunk ) { 1231 | rvaThunk = oidp->FirstThunk; 1232 | } 1233 | PIMAGE_THUNK_DATA pLookThunk = (PIMAGE_THUNK_DATA)RvaToVa(rvaThunk); 1234 | 1235 | DWORD nNames = 0; 1236 | if (pAddrThunk) { 1237 | for (; pAddrThunk[nNames].u1.Ordinal; nNames++) { 1238 | } 1239 | } 1240 | 1241 | if (pAddrThunk && nNames) { 1242 | pImportFile->m_nImportNames = nNames; 1243 | pImportFile->m_pImportNames = new NOTHROW CImageImportName [nNames]; 1244 | if (pImportFile->m_pImportNames == NULL) { 1245 | SetLastError(ERROR_OUTOFMEMORY); 1246 | goto fail; 1247 | } 1248 | 1249 | CImageImportName *pImportName = &pImportFile->m_pImportNames[0]; 1250 | 1251 | for (DWORD f = 0; f < nNames; f++, pImportName++) { 1252 | pImportName->m_nOrig = 0; 1253 | pImportName->m_nOrdinal = 0; 1254 | pImportName->m_nHint = 0; 1255 | pImportName->m_pszName = NULL; 1256 | pImportName->m_pszOrig = NULL; 1257 | 1258 | rvaName = pAddrThunk[f].u1.Ordinal; 1259 | if (rvaName & IMAGE_ORDINAL_FLAG) { 1260 | pImportName->m_nOrig = (ULONG)IMAGE_ORDINAL(rvaName); 1261 | pImportName->m_nOrdinal = pImportName->m_nOrig; 1262 | } 1263 | else { 1264 | PIMAGE_IMPORT_BY_NAME pName 1265 | = (PIMAGE_IMPORT_BY_NAME)RvaToVa(rvaName); 1266 | if (pName) { 1267 | pImportName->m_nHint = pName->Hint; 1268 | pImportName->m_pszName = DuplicateString((PCHAR)pName->Name); 1269 | if (pImportName->m_pszName == NULL) { 1270 | goto fail; 1271 | } 1272 | } 1273 | 1274 | rvaName = pLookThunk[f].u1.Ordinal; 1275 | if (rvaName & IMAGE_ORDINAL_FLAG) { 1276 | pImportName->m_nOrig = (ULONG)IMAGE_ORDINAL(rvaName); 1277 | pImportName->m_nOrdinal = (ULONG)IMAGE_ORDINAL(rvaName); 1278 | } 1279 | else { 1280 | pName = (PIMAGE_IMPORT_BY_NAME)RvaToVa(rvaName); 1281 | if (pName) { 1282 | pImportName->m_pszOrig 1283 | = DuplicateString((PCHAR)pName->Name); 1284 | if (pImportName->m_pszOrig == NULL) { 1285 | goto fail; 1286 | } 1287 | } 1288 | } 1289 | } 1290 | } 1291 | } 1292 | oidp++; 1293 | } 1294 | 1295 | ////////////////////////////////////////////////////////// Parse Sections. 1296 | // 1297 | m_nExtraOffset = 0; 1298 | for (n = 0; n < m_NtHeader.FileHeader.NumberOfSections; n++) { 1299 | m_nExtraOffset = Max(m_SectionHeaders[n].PointerToRawData + 1300 | m_SectionHeaders[n].SizeOfRawData, 1301 | m_nExtraOffset); 1302 | 1303 | if (strcmp((PCHAR)m_SectionHeaders[n].Name, ".detour") == 0) { 1304 | DETOUR_SECTION_HEADER dh; 1305 | CopyMemory(&dh, 1306 | m_pMap + m_SectionHeaders[n].PointerToRawData, 1307 | sizeof(dh)); 1308 | 1309 | if (dh.nDataOffset == 0) { 1310 | dh.nDataOffset = dh.cbHeaderSize; 1311 | } 1312 | 1313 | cbData = dh.cbDataSize - dh.nDataOffset; 1314 | pbData = (m_pMap + 1315 | m_SectionHeaders[n].PointerToRawData + 1316 | dh.nDataOffset); 1317 | 1318 | m_nExtraOffset = Max(m_SectionHeaders[n].PointerToRawData + 1319 | m_SectionHeaders[n].SizeOfRawData, 1320 | m_nExtraOffset); 1321 | 1322 | m_NtHeader.FileHeader.NumberOfSections--; 1323 | 1324 | m_NtHeader.OptionalHeader 1325 | .DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress 1326 | = dh.nOriginalImportVirtualAddress; 1327 | m_NtHeader.OptionalHeader 1328 | .DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Size 1329 | = dh.nOriginalImportSize; 1330 | 1331 | m_NtHeader.OptionalHeader 1332 | .DataDirectory[IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT].VirtualAddress 1333 | = dh.nOriginalBoundImportVirtualAddress; 1334 | m_NtHeader.OptionalHeader 1335 | .DataDirectory[IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT].Size 1336 | = dh.nOriginalBoundImportSize; 1337 | 1338 | m_NtHeader.OptionalHeader 1339 | .DataDirectory[IMAGE_DIRECTORY_ENTRY_IAT].VirtualAddress 1340 | = dh.nOriginalIatVirtualAddress; 1341 | m_NtHeader.OptionalHeader 1342 | .DataDirectory[IMAGE_DIRECTORY_ENTRY_IAT].Size 1343 | = dh.nOriginalIatSize; 1344 | 1345 | m_NtHeader.OptionalHeader.CheckSum = 0; 1346 | m_NtHeader.OptionalHeader.SizeOfImage 1347 | = dh.nOriginalSizeOfImage; 1348 | 1349 | m_fHadDetourSection = TRUE; 1350 | } 1351 | } 1352 | 1353 | m_pImageData = new NOTHROW CImageData(pbData, cbData); 1354 | if (m_pImageData == NULL) { 1355 | SetLastError(ERROR_OUTOFMEMORY); 1356 | } 1357 | return TRUE; 1358 | 1359 | fail: 1360 | return FALSE; 1361 | } 1362 | 1363 | static inline BOOL strneq(_In_ LPCSTR pszOne, _In_ LPCSTR pszTwo) 1364 | { 1365 | if (pszOne == pszTwo) { 1366 | return FALSE; 1367 | } 1368 | if (!pszOne || !pszTwo) { 1369 | return TRUE; 1370 | } 1371 | return (strcmp(pszOne, pszTwo) != 0); 1372 | } 1373 | 1374 | BOOL CImage::CheckImportsNeeded(DWORD *pnTables, DWORD *pnThunks, DWORD *pnChars) 1375 | { 1376 | DWORD nTables = 0; 1377 | DWORD nThunks = 0; 1378 | DWORD nChars = 0; 1379 | BOOL fNeedDetourSection = FALSE; 1380 | 1381 | for (CImageImportFile *pImportFile = m_pImportFiles; 1382 | pImportFile != NULL; pImportFile = pImportFile->m_pNextFile) { 1383 | 1384 | nChars += (int)strlen(pImportFile->m_pszName) + 1; 1385 | nChars += nChars & 1; 1386 | 1387 | if (pImportFile->m_fByway) { 1388 | fNeedDetourSection = TRUE; 1389 | nThunks++; 1390 | } 1391 | else { 1392 | if (!fNeedDetourSection && 1393 | strneq(pImportFile->m_pszName, pImportFile->m_pszOrig)) { 1394 | 1395 | fNeedDetourSection = TRUE; 1396 | } 1397 | for (DWORD n = 0; n < pImportFile->m_nImportNames; n++) { 1398 | CImageImportName *pImportName = &pImportFile->m_pImportNames[n]; 1399 | 1400 | if (!fNeedDetourSection && 1401 | strneq(pImportName->m_pszName, pImportName->m_pszOrig)) { 1402 | 1403 | fNeedDetourSection = TRUE; 1404 | } 1405 | 1406 | if (pImportName->m_pszName) { 1407 | nChars += sizeof(WORD); // Hint 1408 | nChars += (int)strlen(pImportName->m_pszName) + 1; 1409 | nChars += nChars & 1; 1410 | } 1411 | nThunks++; 1412 | } 1413 | } 1414 | nThunks++; 1415 | nTables++; 1416 | } 1417 | nTables++; 1418 | 1419 | *pnTables = nTables; 1420 | *pnThunks = nThunks; 1421 | *pnChars = nChars; 1422 | 1423 | return fNeedDetourSection; 1424 | } 1425 | 1426 | ////////////////////////////////////////////////////////////////////////////// 1427 | // 1428 | CImageImportFile * CImage::NewByway(_In_ LPCSTR pszName) 1429 | { 1430 | CImageImportFile *pImportFile = new NOTHROW CImageImportFile; 1431 | if (pImportFile == NULL) { 1432 | SetLastError(ERROR_OUTOFMEMORY); 1433 | goto fail; 1434 | } 1435 | 1436 | pImportFile->m_pNextFile = NULL; 1437 | pImportFile->m_fByway = TRUE; 1438 | 1439 | pImportFile->m_pszName = DuplicateString(pszName); 1440 | if (pImportFile->m_pszName == NULL) { 1441 | goto fail; 1442 | } 1443 | 1444 | pImportFile->m_rvaOriginalFirstThunk = 0; 1445 | pImportFile->m_rvaFirstThunk = 0; 1446 | pImportFile->m_nForwarderChain = (UINT)0; 1447 | pImportFile->m_pImportNames = NULL; 1448 | pImportFile->m_nImportNames = 0; 1449 | 1450 | m_nImportFiles++; 1451 | return pImportFile; 1452 | 1453 | fail: 1454 | if (pImportFile) { 1455 | delete pImportFile; 1456 | pImportFile = NULL; 1457 | } 1458 | return NULL; 1459 | } 1460 | 1461 | BOOL CImage::EditImports(PVOID pContext, 1462 | PF_DETOUR_BINARY_BYWAY_CALLBACK pfBywayCallback, 1463 | PF_DETOUR_BINARY_FILE_CALLBACK pfFileCallback, 1464 | PF_DETOUR_BINARY_SYMBOL_CALLBACK pfSymbolCallback, 1465 | PF_DETOUR_BINARY_COMMIT_CALLBACK pfCommitCallback) 1466 | { 1467 | CImageImportFile *pImportFile = NULL; 1468 | CImageImportFile **ppLastFile = &m_pImportFiles; 1469 | 1470 | SetLastError(ERROR_CALL_NOT_IMPLEMENTED); 1471 | 1472 | while ((pImportFile = *ppLastFile) != NULL) { 1473 | 1474 | if (pfBywayCallback != NULL) { 1475 | LPCSTR pszFile = NULL; 1476 | if (!(*pfBywayCallback)(pContext, NULL, &pszFile)) { 1477 | goto fail; 1478 | } 1479 | 1480 | if (pszFile != NULL) { 1481 | // Insert a new Byway. 1482 | CImageImportFile *pByway = NewByway(pszFile); 1483 | if (pByway == NULL) { 1484 | return FALSE; 1485 | } 1486 | 1487 | pByway->m_pNextFile = pImportFile; 1488 | *ppLastFile = pByway; 1489 | ppLastFile = &pByway->m_pNextFile; 1490 | continue; // Retry after Byway. 1491 | } 1492 | } 1493 | 1494 | if (pImportFile->m_fByway) { 1495 | if (pfBywayCallback != NULL) { 1496 | LPCSTR pszFile = NULL; 1497 | 1498 | if (!(*pfBywayCallback)(pContext, pImportFile->m_pszName, &pszFile)) { 1499 | goto fail; 1500 | } 1501 | 1502 | if (pszFile != NULL) { 1503 | // Replace? Byway 1504 | if (pszFile != pImportFile->m_pszName) { 1505 | LPCSTR pszLast = pImportFile->m_pszName; 1506 | pImportFile->m_pszName = DuplicateString(pszFile); 1507 | ReleaseString(pszLast); 1508 | 1509 | if (pImportFile->m_pszName == NULL) { 1510 | goto fail; 1511 | } 1512 | } 1513 | } 1514 | else { // Delete Byway 1515 | *ppLastFile = pImportFile->m_pNextFile; 1516 | pImportFile->m_pNextFile = NULL; 1517 | delete pImportFile; 1518 | m_nImportFiles--; 1519 | continue; // Retry after delete. 1520 | } 1521 | } 1522 | } 1523 | else { 1524 | if (pfFileCallback != NULL) { 1525 | LPCSTR pszFile = NULL; 1526 | 1527 | if (!(*pfFileCallback)(pContext, 1528 | pImportFile->m_pszOrig, 1529 | pImportFile->m_pszName, 1530 | &pszFile)) { 1531 | goto fail; 1532 | } 1533 | 1534 | if (pszFile != NULL) { 1535 | if (pszFile != pImportFile->m_pszName) { 1536 | LPCSTR pszLast = pImportFile->m_pszName; 1537 | pImportFile->m_pszName = DuplicateString(pszFile); 1538 | ReleaseString(pszLast); 1539 | 1540 | if (pImportFile->m_pszName == NULL) { 1541 | goto fail; 1542 | } 1543 | } 1544 | } 1545 | } 1546 | 1547 | if (pfSymbolCallback != NULL) { 1548 | for (DWORD n = 0; n < pImportFile->m_nImportNames; n++) { 1549 | CImageImportName *pImportName = &pImportFile->m_pImportNames[n]; 1550 | 1551 | LPCSTR pszName = NULL; 1552 | ULONG nOrdinal = 0; 1553 | if (!(*pfSymbolCallback)(pContext, 1554 | pImportName->m_nOrig, 1555 | pImportName->m_nOrdinal, 1556 | &nOrdinal, 1557 | pImportName->m_pszOrig, 1558 | pImportName->m_pszName, 1559 | &pszName)) { 1560 | goto fail; 1561 | } 1562 | 1563 | if (pszName != NULL) { 1564 | if (pszName != pImportName->m_pszName) { 1565 | pImportName->m_nOrdinal = 0; 1566 | 1567 | LPCSTR pszLast = pImportName->m_pszName; 1568 | pImportName->m_pszName = DuplicateString(pszName); 1569 | ReleaseString(pszLast); 1570 | 1571 | if (pImportName->m_pszName == NULL) { 1572 | goto fail; 1573 | } 1574 | } 1575 | } 1576 | else if (nOrdinal != 0) { 1577 | pImportName->m_nOrdinal = nOrdinal; 1578 | 1579 | if (pImportName->m_pszName != NULL) { 1580 | delete[] pImportName->m_pszName; 1581 | pImportName->m_pszName = NULL; 1582 | } 1583 | } 1584 | } 1585 | } 1586 | } 1587 | 1588 | ppLastFile = &pImportFile->m_pNextFile; 1589 | pImportFile = pImportFile->m_pNextFile; 1590 | } 1591 | 1592 | for (;;) { 1593 | if (pfBywayCallback != NULL) { 1594 | LPCSTR pszFile = NULL; 1595 | if (!(*pfBywayCallback)(pContext, NULL, &pszFile)) { 1596 | goto fail; 1597 | } 1598 | if (pszFile != NULL) { 1599 | // Insert a new Byway. 1600 | CImageImportFile *pByway = NewByway(pszFile); 1601 | if (pByway == NULL) { 1602 | return FALSE; 1603 | } 1604 | 1605 | pByway->m_pNextFile = pImportFile; 1606 | *ppLastFile = pByway; 1607 | ppLastFile = &pByway->m_pNextFile; 1608 | continue; // Retry after Byway. 1609 | } 1610 | } 1611 | break; 1612 | } 1613 | 1614 | if (pfCommitCallback != NULL) { 1615 | if (!(*pfCommitCallback)(pContext)) { 1616 | goto fail; 1617 | } 1618 | } 1619 | 1620 | SetLastError(NO_ERROR); 1621 | return TRUE; 1622 | 1623 | fail: 1624 | return FALSE; 1625 | } 1626 | 1627 | BOOL CImage::Write(HANDLE hFile) 1628 | { 1629 | DWORD cbDone; 1630 | 1631 | if (hFile == INVALID_HANDLE_VALUE) { 1632 | SetLastError(ERROR_INVALID_HANDLE); 1633 | return FALSE; 1634 | } 1635 | 1636 | m_nNextFileAddr = 0; 1637 | m_nNextVirtAddr = 0; 1638 | 1639 | DWORD nTables = 0; 1640 | DWORD nThunks = 0; 1641 | DWORD nChars = 0; 1642 | BOOL fNeedDetourSection = CheckImportsNeeded(&nTables, &nThunks, &nChars); 1643 | 1644 | //////////////////////////////////////////////////////////// Copy Headers. 1645 | // 1646 | if (SetFilePointer(hFile, 0, NULL, FILE_BEGIN) == ~0u) { 1647 | return FALSE; 1648 | } 1649 | if (!CopyFileData(hFile, 0, m_NtHeader.OptionalHeader.SizeOfHeaders)) { 1650 | return FALSE; 1651 | } 1652 | 1653 | if (fNeedDetourSection || !m_pImageData->IsEmpty()) { 1654 | // Replace the file's DOS header with our own. 1655 | m_nPeOffset = sizeof(m_DosHeader) + sizeof(s_rbDosCode); 1656 | m_nSectionsOffset = m_nPeOffset 1657 | + sizeof(m_NtHeader.Signature) 1658 | + sizeof(m_NtHeader.FileHeader) 1659 | + m_NtHeader.FileHeader.SizeOfOptionalHeader; 1660 | m_DosHeader.e_lfanew = m_nPeOffset; 1661 | 1662 | if (SetFilePointer(hFile, 0, NULL, FILE_BEGIN) == ~0u) { 1663 | return FALSE; 1664 | } 1665 | if (!WriteFile(hFile, &m_DosHeader, sizeof(m_DosHeader), &cbDone)) { 1666 | return FALSE; 1667 | } 1668 | if (!WriteFile(hFile, &s_rbDosCode, sizeof(s_rbDosCode), &cbDone)) { 1669 | return FALSE; 1670 | } 1671 | } 1672 | else { 1673 | // Restore the file's original DOS header. 1674 | if (m_nPrePE != 0) { 1675 | m_nPeOffset = m_cbPrePE; 1676 | m_nSectionsOffset = m_nPeOffset 1677 | + sizeof(m_NtHeader.Signature) 1678 | + sizeof(m_NtHeader.FileHeader) 1679 | + m_NtHeader.FileHeader.SizeOfOptionalHeader; 1680 | m_DosHeader.e_lfanew = m_nPeOffset; 1681 | 1682 | 1683 | if (SetFilePointer(hFile, 0, NULL, FILE_BEGIN) == ~0u) { 1684 | return FALSE; 1685 | } 1686 | if (!CopyFileData(hFile, m_nPrePE, m_cbPrePE)) { 1687 | return FALSE; 1688 | } 1689 | } 1690 | } 1691 | 1692 | m_nNextFileAddr = m_NtHeader.OptionalHeader.SizeOfHeaders; 1693 | m_nNextVirtAddr = 0; 1694 | if (!AlignFileData(hFile)) { 1695 | return FALSE; 1696 | } 1697 | 1698 | /////////////////////////////////////////////////////////// Copy Sections. 1699 | // 1700 | DWORD n = 0; 1701 | for (; n < m_NtHeader.FileHeader.NumberOfSections; n++) { 1702 | if (m_SectionHeaders[n].SizeOfRawData) { 1703 | if (SetFilePointer(hFile, 1704 | m_SectionHeaders[n].PointerToRawData, 1705 | NULL, FILE_BEGIN) == ~0u) { 1706 | return FALSE; 1707 | } 1708 | if (!CopyFileData(hFile, 1709 | m_SectionHeaders[n].PointerToRawData, 1710 | m_SectionHeaders[n].SizeOfRawData)) { 1711 | return FALSE; 1712 | } 1713 | } 1714 | m_nNextFileAddr = Max(m_SectionHeaders[n].PointerToRawData + 1715 | m_SectionHeaders[n].SizeOfRawData, 1716 | m_nNextFileAddr); 1717 | #if 0 1718 | m_nNextVirtAddr = Max(m_SectionHeaders[n].VirtualAddress + 1719 | m_SectionHeaders[n].Misc.VirtualSize, 1720 | m_nNextVirtAddr); 1721 | #else 1722 | m_nNextVirtAddr = Max(m_SectionHeaders[n].VirtualAddress + 1723 | (m_SectionHeaders[n].Misc.VirtualSize 1724 | ? m_SectionHeaders[n].Misc.VirtualSize 1725 | : SectionAlign(m_SectionHeaders[n].SizeOfRawData)), 1726 | m_nNextVirtAddr); 1727 | #endif 1728 | 1729 | m_nExtraOffset = Max(m_nNextFileAddr, m_nExtraOffset); 1730 | 1731 | if (!AlignFileData(hFile)) { 1732 | return FALSE; 1733 | } 1734 | } 1735 | 1736 | if (fNeedDetourSection || !m_pImageData->IsEmpty()) { 1737 | 1738 | if (m_NtHeader.FileHeader.NumberOfSections >= ARRAYSIZE(m_SectionHeaders)) { 1739 | SetLastError(ERROR_EXE_MARKED_INVALID); 1740 | return FALSE; 1741 | } 1742 | 1743 | ////////////////////////////////////////////// Insert .detour Section. 1744 | // 1745 | DWORD nSection = m_NtHeader.FileHeader.NumberOfSections++; 1746 | DETOUR_SECTION_HEADER dh; 1747 | 1748 | ZeroMemory(&dh, sizeof(dh)); 1749 | ZeroMemory(&m_SectionHeaders[nSection], sizeof(m_SectionHeaders[nSection])); 1750 | 1751 | dh.cbHeaderSize = sizeof(DETOUR_SECTION_HEADER); 1752 | dh.nSignature = DETOUR_SECTION_HEADER_SIGNATURE; 1753 | 1754 | dh.nOriginalImportVirtualAddress = m_NtHeader.OptionalHeader 1755 | .DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress; 1756 | dh.nOriginalImportSize = m_NtHeader.OptionalHeader 1757 | .DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Size; 1758 | 1759 | dh.nOriginalBoundImportVirtualAddress 1760 | = m_NtHeader.OptionalHeader 1761 | .DataDirectory[IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT].VirtualAddress; 1762 | dh.nOriginalBoundImportSize = m_NtHeader.OptionalHeader 1763 | .DataDirectory[IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT].Size; 1764 | 1765 | dh.nOriginalIatVirtualAddress = m_NtHeader.OptionalHeader 1766 | .DataDirectory[IMAGE_DIRECTORY_ENTRY_IAT].VirtualAddress; 1767 | dh.nOriginalIatSize = m_NtHeader.OptionalHeader 1768 | .DataDirectory[IMAGE_DIRECTORY_ENTRY_IAT].Size; 1769 | 1770 | dh.nOriginalSizeOfImage = m_NtHeader.OptionalHeader.SizeOfImage; 1771 | 1772 | DWORD clrAddr = m_NtHeader.OptionalHeader 1773 | .DataDirectory[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR].VirtualAddress; 1774 | DWORD clrSize = m_NtHeader.OptionalHeader 1775 | .DataDirectory[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR].Size; 1776 | if (clrAddr && clrSize) { 1777 | PDETOUR_CLR_HEADER pHdr = (PDETOUR_CLR_HEADER)RvaToVa(clrAddr); 1778 | if (pHdr != NULL) { 1779 | DETOUR_CLR_HEADER hdr; 1780 | hdr = *pHdr; 1781 | 1782 | dh.nOriginalClrFlags = hdr.Flags; 1783 | } 1784 | } 1785 | 1786 | HRESULT hrRet = StringCchCopyA((PCHAR)m_SectionHeaders[nSection].Name, IMAGE_SIZEOF_SHORT_NAME , ".detour"); 1787 | if (FAILED(hrRet)) 1788 | return FALSE; 1789 | 1790 | m_SectionHeaders[nSection].Characteristics 1791 | = IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE; 1792 | 1793 | m_nOutputVirtAddr = m_nNextVirtAddr; 1794 | m_nOutputVirtSize = 0; 1795 | m_nOutputFileAddr = m_nNextFileAddr; 1796 | 1797 | dh.nDataOffset = 0; // pbData 1798 | dh.cbDataSize = m_pImageData->m_cbData; 1799 | dh.cbPrePE = m_cbPrePE; 1800 | 1801 | ////////////////////////////////////////////////////////////////////////// 1802 | // 1803 | 1804 | DWORD rvaImportTable = 0; 1805 | DWORD rvaLookupTable = 0; 1806 | DWORD rvaBoundTable = 0; 1807 | DWORD rvaNameTable = 0; 1808 | DWORD nImportTableSize = nTables * sizeof(IMAGE_IMPORT_DESCRIPTOR); 1809 | 1810 | if (!SizeOutputBuffer(QuadAlign(sizeof(dh)) 1811 | + m_cbPrePE 1812 | + QuadAlign(m_pImageData->m_cbData) 1813 | + QuadAlign(sizeof(IMAGE_THUNK_DATA) * nThunks) 1814 | + QuadAlign(sizeof(IMAGE_THUNK_DATA) * nThunks) 1815 | + QuadAlign(nChars) 1816 | + QuadAlign(nImportTableSize))) { 1817 | return FALSE; 1818 | } 1819 | 1820 | DWORD vaHead = 0; 1821 | PBYTE pbHead = NULL; 1822 | DWORD vaPrePE = 0; 1823 | PBYTE pbPrePE = NULL; 1824 | DWORD vaData = 0; 1825 | PBYTE pbData = NULL; 1826 | 1827 | if ((pbHead = AllocateOutput(sizeof(dh), &vaHead)) == NULL) { 1828 | return FALSE; 1829 | } 1830 | 1831 | if ((pbPrePE = AllocateOutput(m_cbPrePE, &vaPrePE)) == NULL) { 1832 | return FALSE; 1833 | } 1834 | 1835 | CImageThunks lookupTable(this, nThunks, &rvaLookupTable); 1836 | CImageThunks boundTable(this, nThunks, &rvaBoundTable); 1837 | CImageChars nameTable(this, nChars, &rvaNameTable); 1838 | 1839 | if ((pbData = AllocateOutput(m_pImageData->m_cbData, &vaData)) == NULL) { 1840 | return FALSE; 1841 | } 1842 | 1843 | dh.nDataOffset = vaData - vaHead; 1844 | dh.cbDataSize = dh.nDataOffset + m_pImageData->m_cbData; 1845 | CopyMemory(pbHead, &dh, sizeof(dh)); 1846 | CopyMemory(pbPrePE, m_pMap + m_nPrePE, m_cbPrePE); 1847 | CopyMemory(pbData, m_pImageData->m_pbData, m_pImageData->m_cbData); 1848 | 1849 | PIMAGE_IMPORT_DESCRIPTOR piidDst = (PIMAGE_IMPORT_DESCRIPTOR) 1850 | AllocateOutput(nImportTableSize, &rvaImportTable); 1851 | if (piidDst == NULL) { 1852 | return FALSE; 1853 | } 1854 | 1855 | //////////////////////////////////////////////// Step Through Imports. 1856 | // 1857 | for (CImageImportFile *pImportFile = m_pImportFiles; 1858 | pImportFile != NULL; pImportFile = pImportFile->m_pNextFile) { 1859 | 1860 | ZeroMemory(piidDst, sizeof(piidDst)); 1861 | nameTable.Allocate(pImportFile->m_pszName, (DWORD *)&piidDst->Name); 1862 | piidDst->TimeDateStamp = 0; 1863 | piidDst->ForwarderChain = pImportFile->m_nForwarderChain; 1864 | 1865 | if (pImportFile->m_fByway) { 1866 | ULONG rvaIgnored; 1867 | 1868 | lookupTable.Allocate(IMAGE_ORDINAL_FLAG+1, 1869 | (DWORD *)&piidDst->OriginalFirstThunk); 1870 | boundTable.Allocate(IMAGE_ORDINAL_FLAG+1, 1871 | (DWORD *)&piidDst->FirstThunk); 1872 | 1873 | lookupTable.Allocate(0, &rvaIgnored); 1874 | boundTable.Allocate(0, &rvaIgnored); 1875 | } 1876 | else { 1877 | ULONG rvaIgnored; 1878 | 1879 | piidDst->FirstThunk = (ULONG)pImportFile->m_rvaFirstThunk; 1880 | lookupTable.Current((DWORD *)&piidDst->OriginalFirstThunk); 1881 | 1882 | for (n = 0; n < pImportFile->m_nImportNames; n++) { 1883 | CImageImportName *pImportName = &pImportFile->m_pImportNames[n]; 1884 | 1885 | if (pImportName->m_pszName) { 1886 | ULONG nDstName = 0; 1887 | 1888 | nameTable.Allocate(pImportName->m_pszName, 1889 | pImportName->m_nHint, 1890 | &nDstName); 1891 | lookupTable.Allocate(nDstName, &rvaIgnored); 1892 | } 1893 | else { 1894 | lookupTable.Allocate(IMAGE_ORDINAL_FLAG + pImportName->m_nOrdinal, 1895 | &rvaIgnored); 1896 | } 1897 | } 1898 | lookupTable.Allocate(0, &rvaIgnored); 1899 | } 1900 | piidDst++; 1901 | } 1902 | ZeroMemory(piidDst, sizeof(piidDst)); 1903 | 1904 | ////////////////////////////////////////////////////////////////////////// 1905 | // 1906 | m_nNextVirtAddr += m_nOutputVirtSize; 1907 | m_nNextFileAddr += FileAlign(m_nOutputVirtSize); 1908 | 1909 | if (!AlignFileData(hFile)) { 1910 | return FALSE; 1911 | } 1912 | 1913 | ////////////////////////////////////////////////////////////////////////// 1914 | // 1915 | m_SectionHeaders[nSection].VirtualAddress = m_nOutputVirtAddr; 1916 | m_SectionHeaders[nSection].Misc.VirtualSize = m_nOutputVirtSize; 1917 | m_SectionHeaders[nSection].PointerToRawData = m_nOutputFileAddr; 1918 | m_SectionHeaders[nSection].SizeOfRawData = FileAlign(m_nOutputVirtSize); 1919 | 1920 | m_NtHeader.OptionalHeader 1921 | .DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress 1922 | = rvaImportTable; 1923 | m_NtHeader.OptionalHeader 1924 | .DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Size 1925 | = nImportTableSize; 1926 | 1927 | m_NtHeader.OptionalHeader 1928 | .DataDirectory[IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT].VirtualAddress = 0; 1929 | m_NtHeader.OptionalHeader 1930 | .DataDirectory[IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT].Size = 0; 1931 | 1932 | ////////////////////////////////////////////////////////////////////////// 1933 | // 1934 | if (SetFilePointer(hFile, m_SectionHeaders[nSection].PointerToRawData, 1935 | NULL, FILE_BEGIN) == ~0u) { 1936 | return FALSE; 1937 | } 1938 | if (!WriteFile(hFile, m_pbOutputBuffer, m_SectionHeaders[nSection].SizeOfRawData, 1939 | &cbDone)) { 1940 | return FALSE; 1941 | } 1942 | } 1943 | 1944 | ///////////////////////////////////////////////////// Adjust Extra Data. 1945 | // 1946 | LONG nExtraAdjust = m_nNextFileAddr - m_nExtraOffset; 1947 | for (n = 0; n < m_NtHeader.FileHeader.NumberOfSections; n++) { 1948 | if (m_SectionHeaders[n].PointerToRawData > m_nExtraOffset) { 1949 | m_SectionHeaders[n].PointerToRawData += nExtraAdjust; 1950 | } 1951 | if (m_SectionHeaders[n].PointerToRelocations > m_nExtraOffset) { 1952 | m_SectionHeaders[n].PointerToRelocations += nExtraAdjust; 1953 | } 1954 | if (m_SectionHeaders[n].PointerToLinenumbers > m_nExtraOffset) { 1955 | m_SectionHeaders[n].PointerToLinenumbers += nExtraAdjust; 1956 | } 1957 | } 1958 | if (m_NtHeader.FileHeader.PointerToSymbolTable > m_nExtraOffset) { 1959 | m_NtHeader.FileHeader.PointerToSymbolTable += nExtraAdjust; 1960 | } 1961 | 1962 | m_NtHeader.OptionalHeader.CheckSum = 0; 1963 | m_NtHeader.OptionalHeader.SizeOfImage = m_nNextVirtAddr; 1964 | 1965 | ////////////////////////////////////////////////// Adjust Debug Directory. 1966 | // 1967 | DWORD debugAddr = m_NtHeader.OptionalHeader 1968 | .DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress; 1969 | DWORD debugSize = m_NtHeader.OptionalHeader 1970 | .DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].Size; 1971 | if (debugAddr && debugSize) { 1972 | DWORD nFileOffset = RvaToFileOffset(debugAddr); 1973 | if (SetFilePointer(hFile, nFileOffset, NULL, FILE_BEGIN) == ~0u) { 1974 | return FALSE; 1975 | } 1976 | 1977 | PIMAGE_DEBUG_DIRECTORY pDir = (PIMAGE_DEBUG_DIRECTORY)RvaToVa(debugAddr); 1978 | if (pDir == NULL) { 1979 | return FALSE; 1980 | } 1981 | 1982 | DWORD nEntries = debugSize / sizeof(*pDir); 1983 | for (n = 0; n < nEntries; n++) { 1984 | IMAGE_DEBUG_DIRECTORY dir = pDir[n]; 1985 | 1986 | if (dir.PointerToRawData > m_nExtraOffset) { 1987 | dir.PointerToRawData += nExtraAdjust; 1988 | } 1989 | if (!WriteFile(hFile, &dir, sizeof(dir), &cbDone)) { 1990 | return FALSE; 1991 | } 1992 | } 1993 | } 1994 | 1995 | /////////////////////////////////////////////////////// Adjust CLR Header. 1996 | // 1997 | DWORD clrAddr = m_NtHeader.OptionalHeader 1998 | .DataDirectory[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR].VirtualAddress; 1999 | DWORD clrSize = m_NtHeader.OptionalHeader 2000 | .DataDirectory[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR].Size; 2001 | if (clrAddr && clrSize && fNeedDetourSection) { 2002 | DWORD nFileOffset = RvaToFileOffset(clrAddr); 2003 | if (SetFilePointer(hFile, nFileOffset, NULL, FILE_BEGIN) == ~0u) { 2004 | return FALSE; 2005 | } 2006 | 2007 | PDETOUR_CLR_HEADER pHdr = (PDETOUR_CLR_HEADER)RvaToVa(clrAddr); 2008 | if (pHdr == NULL) { 2009 | return FALSE; 2010 | } 2011 | 2012 | DETOUR_CLR_HEADER hdr; 2013 | hdr = *pHdr; 2014 | hdr.Flags &= 0xfffffffe; // Clear the IL_ONLY flag. 2015 | 2016 | if (!WriteFile(hFile, &hdr, sizeof(hdr), &cbDone)) { 2017 | return FALSE; 2018 | } 2019 | } 2020 | 2021 | ///////////////////////////////////////////////// Copy Left-over Data. 2022 | // 2023 | if (m_nFileSize > m_nExtraOffset) { 2024 | if (SetFilePointer(hFile, m_nNextFileAddr, NULL, FILE_BEGIN) == ~0u) { 2025 | return FALSE; 2026 | } 2027 | if (!CopyFileData(hFile, m_nExtraOffset, m_nFileSize - m_nExtraOffset)) { 2028 | return FALSE; 2029 | } 2030 | } 2031 | 2032 | 2033 | //////////////////////////////////////////////////// Finalize Headers. 2034 | // 2035 | 2036 | if (SetFilePointer(hFile, m_nPeOffset, NULL, FILE_BEGIN) == ~0u) { 2037 | return FALSE; 2038 | } 2039 | if (!WriteFile(hFile, &m_NtHeader, sizeof(m_NtHeader), &cbDone)) { 2040 | return FALSE; 2041 | } 2042 | 2043 | if (SetFilePointer(hFile, m_nSectionsOffset, NULL, FILE_BEGIN) == ~0u) { 2044 | return FALSE; 2045 | } 2046 | if (!WriteFile(hFile, &m_SectionHeaders, 2047 | sizeof(m_SectionHeaders[0]) 2048 | * m_NtHeader.FileHeader.NumberOfSections, 2049 | &cbDone)) { 2050 | return FALSE; 2051 | } 2052 | 2053 | m_cbPostPE = SetFilePointer(hFile, 0, NULL, FILE_CURRENT); 2054 | if (m_cbPostPE == ~0u) { 2055 | return FALSE; 2056 | } 2057 | m_cbPostPE = m_NtHeader.OptionalHeader.SizeOfHeaders - m_cbPostPE; 2058 | 2059 | return TRUE; 2060 | } 2061 | 2062 | }; // namespace Detour 2063 | 2064 | ////////////////////////////////////////////////////////////////////////////// 2065 | // 2066 | PDETOUR_BINARY WINAPI DetourBinaryOpen(_In_ HANDLE hFile) 2067 | { 2068 | Detour::CImage *pImage = new NOTHROW 2069 | Detour::CImage; 2070 | if (pImage == NULL) { 2071 | SetLastError(ERROR_OUTOFMEMORY); 2072 | return FALSE; 2073 | } 2074 | 2075 | if (!pImage->Read(hFile)) { 2076 | delete pImage; 2077 | return FALSE; 2078 | } 2079 | 2080 | return (PDETOUR_BINARY)pImage; 2081 | } 2082 | 2083 | BOOL WINAPI DetourBinaryWrite(_In_ PDETOUR_BINARY pdi, 2084 | _In_ HANDLE hFile) 2085 | { 2086 | Detour::CImage *pImage = Detour::CImage::IsValid(pdi); 2087 | if (pImage == NULL) { 2088 | return FALSE; 2089 | } 2090 | 2091 | return pImage->Write(hFile); 2092 | } 2093 | 2094 | _Writable_bytes_(*pcbData) 2095 | _Readable_bytes_(*pcbData) 2096 | _Success_(return != NULL) 2097 | PVOID WINAPI DetourBinaryEnumeratePayloads(_In_ PDETOUR_BINARY pBinary, 2098 | _Out_opt_ GUID *pGuid, 2099 | _Out_ DWORD *pcbData, 2100 | _Inout_ DWORD *pnIterator) 2101 | { 2102 | Detour::CImage *pImage = Detour::CImage::IsValid(pBinary); 2103 | if (pImage == NULL) { 2104 | return FALSE; 2105 | } 2106 | 2107 | return pImage->DataEnum(pGuid, pcbData, pnIterator); 2108 | } 2109 | 2110 | _Writable_bytes_(*pcbData) 2111 | _Readable_bytes_(*pcbData) 2112 | _Success_(return != NULL) 2113 | PVOID WINAPI DetourBinaryFindPayload(_In_ PDETOUR_BINARY pBinary, 2114 | _In_ REFGUID rguid, 2115 | _Out_ DWORD *pcbData) 2116 | { 2117 | Detour::CImage *pImage = Detour::CImage::IsValid(pBinary); 2118 | if (pImage == NULL) { 2119 | return FALSE; 2120 | } 2121 | 2122 | return pImage->DataFind(rguid, pcbData); 2123 | } 2124 | 2125 | PVOID WINAPI DetourBinarySetPayload(_In_ PDETOUR_BINARY pBinary, 2126 | _In_ REFGUID rguid, 2127 | _In_reads_opt_(cbData) PVOID pvData, 2128 | _In_ DWORD cbData) 2129 | { 2130 | Detour::CImage *pImage = Detour::CImage::IsValid(pBinary); 2131 | if (pImage == NULL) { 2132 | return NULL; 2133 | } 2134 | 2135 | return pImage->DataSet(rguid, (PBYTE)pvData, cbData); 2136 | } 2137 | 2138 | BOOL WINAPI DetourBinaryDeletePayload(_In_ PDETOUR_BINARY pBinary, 2139 | _In_ REFGUID rguid) 2140 | { 2141 | Detour::CImage *pImage = Detour::CImage::IsValid(pBinary); 2142 | if (pImage == NULL) { 2143 | return FALSE; 2144 | } 2145 | 2146 | return pImage->DataDelete(rguid); 2147 | } 2148 | 2149 | BOOL WINAPI DetourBinaryPurgePayloads(_In_ PDETOUR_BINARY pBinary) 2150 | { 2151 | Detour::CImage *pImage = Detour::CImage::IsValid(pBinary); 2152 | if (pImage == NULL) { 2153 | return FALSE; 2154 | } 2155 | 2156 | return pImage->DataPurge(); 2157 | } 2158 | 2159 | ////////////////////////////////////////////////////////////////////////////// 2160 | // 2161 | static BOOL CALLBACK ResetBywayCallback(_In_opt_ PVOID pContext, 2162 | _In_opt_ LPCSTR pszFile, 2163 | _Outptr_result_maybenull_ LPCSTR *ppszOutFile) 2164 | { 2165 | UNREFERENCED_PARAMETER(pContext); 2166 | UNREFERENCED_PARAMETER(pszFile); 2167 | 2168 | *ppszOutFile = NULL; 2169 | return TRUE; 2170 | } 2171 | 2172 | static BOOL CALLBACK ResetFileCallback(_In_opt_ PVOID pContext, 2173 | _In_ LPCSTR pszOrigFile, 2174 | _In_ LPCSTR pszFile, 2175 | _Outptr_result_maybenull_ LPCSTR *ppszOutFile) 2176 | { 2177 | UNREFERENCED_PARAMETER(pContext); 2178 | UNREFERENCED_PARAMETER(pszFile); 2179 | 2180 | *ppszOutFile = pszOrigFile; 2181 | return TRUE; 2182 | } 2183 | 2184 | static BOOL CALLBACK ResetSymbolCallback(_In_opt_ PVOID pContext, 2185 | _In_ ULONG nOrigOrdinal, 2186 | _In_ ULONG nOrdinal, 2187 | _Out_ ULONG *pnOutOrdinal, 2188 | _In_opt_ LPCSTR pszOrigSymbol, 2189 | _In_opt_ LPCSTR pszSymbol, 2190 | _Outptr_result_maybenull_ LPCSTR *ppszOutSymbol) 2191 | { 2192 | UNREFERENCED_PARAMETER(pContext); 2193 | UNREFERENCED_PARAMETER(nOrdinal); 2194 | UNREFERENCED_PARAMETER(pszSymbol); 2195 | 2196 | *pnOutOrdinal = nOrigOrdinal; 2197 | *ppszOutSymbol = pszOrigSymbol; 2198 | return TRUE; 2199 | } 2200 | 2201 | BOOL WINAPI DetourBinaryResetImports(_In_ PDETOUR_BINARY pBinary) 2202 | { 2203 | Detour::CImage *pImage = Detour::CImage::IsValid(pBinary); 2204 | if (pImage == NULL) { 2205 | return FALSE; 2206 | } 2207 | 2208 | return pImage->EditImports(NULL, 2209 | ResetBywayCallback, 2210 | ResetFileCallback, 2211 | ResetSymbolCallback, 2212 | NULL); 2213 | } 2214 | 2215 | ////////////////////////////////////////////////////////////////////////////// 2216 | // 2217 | BOOL WINAPI DetourBinaryEditImports(_In_ PDETOUR_BINARY pBinary, 2218 | _In_opt_ PVOID pContext, 2219 | _In_opt_ PF_DETOUR_BINARY_BYWAY_CALLBACK pfByway, 2220 | _In_opt_ PF_DETOUR_BINARY_FILE_CALLBACK pfFile, 2221 | _In_opt_ PF_DETOUR_BINARY_SYMBOL_CALLBACK pfSymbol, 2222 | _In_opt_ PF_DETOUR_BINARY_COMMIT_CALLBACK pfCommit) 2223 | { 2224 | Detour::CImage *pImage = Detour::CImage::IsValid(pBinary); 2225 | if (pImage == NULL) { 2226 | return FALSE; 2227 | } 2228 | 2229 | return pImage->EditImports(pContext, 2230 | pfByway, 2231 | pfFile, 2232 | pfSymbol, 2233 | pfCommit); 2234 | } 2235 | 2236 | BOOL WINAPI DetourBinaryClose(_In_ PDETOUR_BINARY pBinary) 2237 | { 2238 | Detour::CImage *pImage = Detour::CImage::IsValid(pBinary); 2239 | if (pImage == NULL) { 2240 | return FALSE; 2241 | } 2242 | 2243 | BOOL bSuccess = pImage->Close(); 2244 | delete pImage; 2245 | pImage = NULL; 2246 | 2247 | return bSuccess; 2248 | } 2249 | 2250 | // 2251 | ///////////////////////////////////////////////////////////////// End of File. 2252 | -------------------------------------------------------------------------------- /ShooterGameCheat/detours/modules.cpp: -------------------------------------------------------------------------------- 1 | ////////////////////////////////////////////////////////////////////////////// 2 | // 3 | // Module Enumeration Functions (modules.cpp of detours.lib) 4 | // 5 | // Microsoft Research Detours Package, Version 4.0.1 6 | // 7 | // Copyright (c) Microsoft Corporation. All rights reserved. 8 | // 9 | // Module enumeration functions. 10 | // 11 | 12 | #define _CRT_STDIO_ARBITRARY_WIDE_SPECIFIERS 1 13 | 14 | #pragma warning(disable:4068) // unknown pragma (suppress) 15 | 16 | #if _MSC_VER >= 1900 17 | #pragma warning(push) 18 | #pragma warning(disable:4091) // empty typedef 19 | #endif 20 | 21 | #define _ARM_WINAPI_PARTITION_DESKTOP_SDK_AVAILABLE 1 22 | #include 23 | #if (_MSC_VER < 1310) 24 | #else 25 | #pragma warning(push) 26 | #if _MSC_VER > 1400 27 | #pragma warning(disable:6102 6103) // /analyze warnings 28 | #endif 29 | #include 30 | #pragma warning(pop) 31 | #endif 32 | 33 | // #define DETOUR_DEBUG 1 34 | #define DETOURS_INTERNAL 35 | #include "detours.h" 36 | 37 | #if DETOURS_VERSION != 0x4c0c1 // 0xMAJORcMINORcPATCH 38 | #error detours.h version mismatch 39 | #endif 40 | 41 | #if _MSC_VER >= 1900 42 | #pragma warning(pop) 43 | #endif 44 | 45 | #define CLR_DIRECTORY OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR] 46 | #define IAT_DIRECTORY OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IAT] 47 | 48 | ////////////////////////////////////////////////////////////////////////////// 49 | // 50 | const GUID DETOUR_EXE_RESTORE_GUID = { 51 | 0x2ed7a3ff, 0x3339, 0x4a8d, 52 | { 0x80, 0x5c, 0xd4, 0x98, 0x15, 0x3f, 0xc2, 0x8f }}; 53 | 54 | ////////////////////////////////////////////////////////////////////////////// 55 | // 56 | PDETOUR_SYM_INFO DetourLoadImageHlp(VOID) 57 | { 58 | static DETOUR_SYM_INFO symInfo; 59 | static PDETOUR_SYM_INFO pSymInfo = NULL; 60 | static BOOL failed = false; 61 | 62 | if (failed) { 63 | return NULL; 64 | } 65 | if (pSymInfo != NULL) { 66 | return pSymInfo; 67 | } 68 | 69 | ZeroMemory(&symInfo, sizeof(symInfo)); 70 | // Create a real handle to the process. 71 | #if 0 72 | DuplicateHandle(GetCurrentProcess(), 73 | GetCurrentProcess(), 74 | GetCurrentProcess(), 75 | &symInfo.hProcess, 76 | 0, 77 | FALSE, 78 | DUPLICATE_SAME_ACCESS); 79 | #else 80 | symInfo.hProcess = GetCurrentProcess(); 81 | #endif 82 | 83 | symInfo.hDbgHelp = LoadLibraryExW(L"dbghelp.dll", NULL, 0); 84 | if (symInfo.hDbgHelp == NULL) { 85 | abort: 86 | failed = true; 87 | if (symInfo.hDbgHelp != NULL) { 88 | FreeLibrary(symInfo.hDbgHelp); 89 | } 90 | symInfo.pfImagehlpApiVersionEx = NULL; 91 | symInfo.pfSymInitialize = NULL; 92 | symInfo.pfSymSetOptions = NULL; 93 | symInfo.pfSymGetOptions = NULL; 94 | symInfo.pfSymLoadModule64 = NULL; 95 | symInfo.pfSymGetModuleInfo64 = NULL; 96 | symInfo.pfSymFromName = NULL; 97 | return NULL; 98 | } 99 | 100 | symInfo.pfImagehlpApiVersionEx 101 | = (PF_ImagehlpApiVersionEx)GetProcAddress(symInfo.hDbgHelp, 102 | "ImagehlpApiVersionEx"); 103 | symInfo.pfSymInitialize 104 | = (PF_SymInitialize)GetProcAddress(symInfo.hDbgHelp, "SymInitialize"); 105 | symInfo.pfSymSetOptions 106 | = (PF_SymSetOptions)GetProcAddress(symInfo.hDbgHelp, "SymSetOptions"); 107 | symInfo.pfSymGetOptions 108 | = (PF_SymGetOptions)GetProcAddress(symInfo.hDbgHelp, "SymGetOptions"); 109 | symInfo.pfSymLoadModule64 110 | = (PF_SymLoadModule64)GetProcAddress(symInfo.hDbgHelp, "SymLoadModule64"); 111 | symInfo.pfSymGetModuleInfo64 112 | = (PF_SymGetModuleInfo64)GetProcAddress(symInfo.hDbgHelp, "SymGetModuleInfo64"); 113 | symInfo.pfSymFromName 114 | = (PF_SymFromName)GetProcAddress(symInfo.hDbgHelp, "SymFromName"); 115 | 116 | API_VERSION av; 117 | ZeroMemory(&av, sizeof(av)); 118 | av.MajorVersion = API_VERSION_NUMBER; 119 | 120 | if (symInfo.pfImagehlpApiVersionEx == NULL || 121 | symInfo.pfSymInitialize == NULL || 122 | symInfo.pfSymLoadModule64 == NULL || 123 | symInfo.pfSymGetModuleInfo64 == NULL || 124 | symInfo.pfSymFromName == NULL) { 125 | goto abort; 126 | } 127 | 128 | symInfo.pfImagehlpApiVersionEx(&av); 129 | if (av.MajorVersion < API_VERSION_NUMBER) { 130 | goto abort; 131 | } 132 | 133 | if (!symInfo.pfSymInitialize(symInfo.hProcess, NULL, FALSE)) { 134 | // We won't retry the initialize if it fails. 135 | goto abort; 136 | } 137 | 138 | if (symInfo.pfSymGetOptions != NULL && symInfo.pfSymSetOptions != NULL) { 139 | DWORD dw = symInfo.pfSymGetOptions(); 140 | 141 | dw &= ~(SYMOPT_CASE_INSENSITIVE | 142 | SYMOPT_UNDNAME | 143 | SYMOPT_DEFERRED_LOADS | 144 | 0); 145 | dw |= ( 146 | #if defined(SYMOPT_EXACT_SYMBOLS) 147 | SYMOPT_EXACT_SYMBOLS | 148 | #endif 149 | #if defined(SYMOPT_NO_UNQUALIFIED_LOADS) 150 | SYMOPT_NO_UNQUALIFIED_LOADS | 151 | #endif 152 | SYMOPT_DEFERRED_LOADS | 153 | #if defined(SYMOPT_FAIL_CRITICAL_ERRORS) 154 | SYMOPT_FAIL_CRITICAL_ERRORS | 155 | #endif 156 | #if defined(SYMOPT_INCLUDE_32BIT_MODULES) 157 | SYMOPT_INCLUDE_32BIT_MODULES | 158 | #endif 159 | 0); 160 | symInfo.pfSymSetOptions(dw); 161 | } 162 | 163 | pSymInfo = &symInfo; 164 | return pSymInfo; 165 | } 166 | 167 | PVOID WINAPI DetourFindFunction(_In_ PCSTR pszModule, 168 | _In_ PCSTR pszFunction) 169 | { 170 | /////////////////////////////////////////////// First, try GetProcAddress. 171 | // 172 | #pragma prefast(suppress:28752, "We don't do the unicode conversion for LoadLibraryExA.") 173 | HMODULE hModule = LoadLibraryExA(pszModule, NULL, 0); 174 | if (hModule == NULL) { 175 | return NULL; 176 | } 177 | 178 | PBYTE pbCode = (PBYTE)GetProcAddress(hModule, pszFunction); 179 | if (pbCode) { 180 | return pbCode; 181 | } 182 | 183 | ////////////////////////////////////////////////////// Then try ImageHelp. 184 | // 185 | DETOUR_TRACE(("DetourFindFunction(%hs, %hs)\n", pszModule, pszFunction)); 186 | PDETOUR_SYM_INFO pSymInfo = DetourLoadImageHlp(); 187 | if (pSymInfo == NULL) { 188 | DETOUR_TRACE(("DetourLoadImageHlp failed: %d\n", 189 | GetLastError())); 190 | return NULL; 191 | } 192 | 193 | if (pSymInfo->pfSymLoadModule64(pSymInfo->hProcess, NULL, 194 | (PCHAR)pszModule, NULL, 195 | (DWORD64)hModule, 0) == 0) { 196 | if (ERROR_SUCCESS != GetLastError()) { 197 | DETOUR_TRACE(("SymLoadModule64(%p) failed: %d\n", 198 | pSymInfo->hProcess, GetLastError())); 199 | return NULL; 200 | } 201 | } 202 | 203 | HRESULT hrRet; 204 | CHAR szFullName[512]; 205 | IMAGEHLP_MODULE64 modinfo; 206 | ZeroMemory(&modinfo, sizeof(modinfo)); 207 | modinfo.SizeOfStruct = sizeof(modinfo); 208 | if (!pSymInfo->pfSymGetModuleInfo64(pSymInfo->hProcess, (DWORD64)hModule, &modinfo)) { 209 | DETOUR_TRACE(("SymGetModuleInfo64(%p, %p) failed: %d\n", 210 | pSymInfo->hProcess, hModule, GetLastError())); 211 | return NULL; 212 | } 213 | 214 | hrRet = StringCchCopyA(szFullName, sizeof(szFullName)/sizeof(CHAR), modinfo.ModuleName); 215 | if (FAILED(hrRet)) { 216 | DETOUR_TRACE(("StringCchCopyA failed: %08x\n", hrRet)); 217 | return NULL; 218 | } 219 | hrRet = StringCchCatA(szFullName, sizeof(szFullName)/sizeof(CHAR), "!"); 220 | if (FAILED(hrRet)) { 221 | DETOUR_TRACE(("StringCchCatA failed: %08x\n", hrRet)); 222 | return NULL; 223 | } 224 | hrRet = StringCchCatA(szFullName, sizeof(szFullName)/sizeof(CHAR), pszFunction); 225 | if (FAILED(hrRet)) { 226 | DETOUR_TRACE(("StringCchCatA failed: %08x\n", hrRet)); 227 | return NULL; 228 | } 229 | 230 | struct CFullSymbol : SYMBOL_INFO { 231 | CHAR szRestOfName[512]; 232 | } symbol; 233 | ZeroMemory(&symbol, sizeof(symbol)); 234 | //symbol.ModBase = (ULONG64)hModule; 235 | symbol.SizeOfStruct = sizeof(SYMBOL_INFO); 236 | #ifdef DBHLPAPI 237 | symbol.MaxNameLen = sizeof(symbol.szRestOfName)/sizeof(symbol.szRestOfName[0]); 238 | #else 239 | symbol.MaxNameLength = sizeof(symbol.szRestOfName)/sizeof(symbol.szRestOfName[0]); 240 | #endif 241 | 242 | if (!pSymInfo->pfSymFromName(pSymInfo->hProcess, szFullName, &symbol)) { 243 | DETOUR_TRACE(("SymFromName(%hs) failed: %d\n", szFullName, GetLastError())); 244 | return NULL; 245 | } 246 | 247 | #if defined(DETOURS_IA64) 248 | // On the IA64, we get a raw code pointer from the symbol engine 249 | // and have to convert it to a wrapped [code pointer, global pointer]. 250 | // 251 | PPLABEL_DESCRIPTOR pldEntry = (PPLABEL_DESCRIPTOR)DetourGetEntryPoint(hModule); 252 | PPLABEL_DESCRIPTOR pldSymbol = new PLABEL_DESCRIPTOR; 253 | 254 | pldSymbol->EntryPoint = symbol.Address; 255 | pldSymbol->GlobalPointer = pldEntry->GlobalPointer; 256 | return (PBYTE)pldSymbol; 257 | #elif defined(DETOURS_ARM) 258 | // On the ARM, we get a raw code pointer, which we must convert into a 259 | // valied Thumb2 function pointer. 260 | return DETOURS_PBYTE_TO_PFUNC(symbol.Address); 261 | #else 262 | return (PBYTE)symbol.Address; 263 | #endif 264 | } 265 | 266 | //////////////////////////////////////////////////// Module Image Functions. 267 | // 268 | 269 | HMODULE WINAPI DetourEnumerateModules(_In_opt_ HMODULE hModuleLast) 270 | { 271 | PBYTE pbLast = (PBYTE)hModuleLast + MM_ALLOCATION_GRANULARITY; 272 | 273 | MEMORY_BASIC_INFORMATION mbi; 274 | ZeroMemory(&mbi, sizeof(mbi)); 275 | 276 | // Find the next memory region that contains a mapped PE image. 277 | // 278 | for (;; pbLast = (PBYTE)mbi.BaseAddress + mbi.RegionSize) { 279 | if (VirtualQuery(pbLast, &mbi, sizeof(mbi)) <= 0) { 280 | break; 281 | } 282 | 283 | // Skip uncommitted regions and guard pages. 284 | // 285 | if ((mbi.State != MEM_COMMIT) || 286 | ((mbi.Protect & 0xff) == PAGE_NOACCESS) || 287 | (mbi.Protect & PAGE_GUARD)) { 288 | continue; 289 | } 290 | 291 | __try { 292 | PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)pbLast; 293 | if (pDosHeader->e_magic != IMAGE_DOS_SIGNATURE || 294 | (DWORD)pDosHeader->e_lfanew > mbi.RegionSize || 295 | (DWORD)pDosHeader->e_lfanew < sizeof(*pDosHeader)) { 296 | continue; 297 | } 298 | 299 | PIMAGE_NT_HEADERS pNtHeader = (PIMAGE_NT_HEADERS)((PBYTE)pDosHeader + 300 | pDosHeader->e_lfanew); 301 | if (pNtHeader->Signature != IMAGE_NT_SIGNATURE) { 302 | continue; 303 | } 304 | 305 | return (HMODULE)pDosHeader; 306 | } 307 | #pragma prefast(suppress:28940, "A bad pointer means this probably isn't a PE header.") 308 | __except(GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ? 309 | EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) { 310 | continue; 311 | } 312 | } 313 | return NULL; 314 | } 315 | 316 | PVOID WINAPI DetourGetEntryPoint(_In_opt_ HMODULE hModule) 317 | { 318 | PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)hModule; 319 | if (hModule == NULL) { 320 | pDosHeader = (PIMAGE_DOS_HEADER)GetModuleHandleW(NULL); 321 | } 322 | 323 | __try { 324 | #pragma warning(suppress:6011) // GetModuleHandleW(NULL) never returns NULL. 325 | if (pDosHeader->e_magic != IMAGE_DOS_SIGNATURE) { 326 | SetLastError(ERROR_BAD_EXE_FORMAT); 327 | return NULL; 328 | } 329 | 330 | PIMAGE_NT_HEADERS pNtHeader = (PIMAGE_NT_HEADERS)((PBYTE)pDosHeader + 331 | pDosHeader->e_lfanew); 332 | if (pNtHeader->Signature != IMAGE_NT_SIGNATURE) { 333 | SetLastError(ERROR_INVALID_EXE_SIGNATURE); 334 | return NULL; 335 | } 336 | if (pNtHeader->FileHeader.SizeOfOptionalHeader == 0) { 337 | SetLastError(ERROR_EXE_MARKED_INVALID); 338 | return NULL; 339 | } 340 | 341 | PDETOUR_CLR_HEADER pClrHeader = NULL; 342 | if (pNtHeader->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC) { 343 | if (((PIMAGE_NT_HEADERS32)pNtHeader)->CLR_DIRECTORY.VirtualAddress != 0 && 344 | ((PIMAGE_NT_HEADERS32)pNtHeader)->CLR_DIRECTORY.Size != 0) { 345 | pClrHeader = (PDETOUR_CLR_HEADER) 346 | (((PBYTE)pDosHeader) 347 | + ((PIMAGE_NT_HEADERS32)pNtHeader)->CLR_DIRECTORY.VirtualAddress); 348 | } 349 | } 350 | else if (pNtHeader->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC) { 351 | if (((PIMAGE_NT_HEADERS64)pNtHeader)->CLR_DIRECTORY.VirtualAddress != 0 && 352 | ((PIMAGE_NT_HEADERS64)pNtHeader)->CLR_DIRECTORY.Size != 0) { 353 | pClrHeader = (PDETOUR_CLR_HEADER) 354 | (((PBYTE)pDosHeader) 355 | + ((PIMAGE_NT_HEADERS64)pNtHeader)->CLR_DIRECTORY.VirtualAddress); 356 | } 357 | } 358 | 359 | if (pClrHeader != NULL) { 360 | // For MSIL assemblies, we want to use the _Cor entry points. 361 | 362 | HMODULE hClr = GetModuleHandleW(L"MSCOREE.DLL"); 363 | if (hClr == NULL) { 364 | return NULL; 365 | } 366 | 367 | SetLastError(NO_ERROR); 368 | return GetProcAddress(hClr, "_CorExeMain"); 369 | } 370 | 371 | SetLastError(NO_ERROR); 372 | 373 | // Pure resource DLLs have neither an entry point nor CLR information 374 | // so handle them by returning NULL (LastError is NO_ERROR) 375 | if (pNtHeader->OptionalHeader.AddressOfEntryPoint == 0) { 376 | return NULL; 377 | } 378 | 379 | return ((PBYTE)pDosHeader) + 380 | pNtHeader->OptionalHeader.AddressOfEntryPoint; 381 | } 382 | __except(GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ? 383 | EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) { 384 | SetLastError(ERROR_EXE_MARKED_INVALID); 385 | return NULL; 386 | } 387 | } 388 | 389 | ULONG WINAPI DetourGetModuleSize(_In_opt_ HMODULE hModule) 390 | { 391 | PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)hModule; 392 | if (hModule == NULL) { 393 | pDosHeader = (PIMAGE_DOS_HEADER)GetModuleHandleW(NULL); 394 | } 395 | 396 | __try { 397 | #pragma warning(suppress:6011) // GetModuleHandleW(NULL) never returns NULL. 398 | if (pDosHeader->e_magic != IMAGE_DOS_SIGNATURE) { 399 | SetLastError(ERROR_BAD_EXE_FORMAT); 400 | return NULL; 401 | } 402 | 403 | PIMAGE_NT_HEADERS pNtHeader = (PIMAGE_NT_HEADERS)((PBYTE)pDosHeader + 404 | pDosHeader->e_lfanew); 405 | if (pNtHeader->Signature != IMAGE_NT_SIGNATURE) { 406 | SetLastError(ERROR_INVALID_EXE_SIGNATURE); 407 | return NULL; 408 | } 409 | if (pNtHeader->FileHeader.SizeOfOptionalHeader == 0) { 410 | SetLastError(ERROR_EXE_MARKED_INVALID); 411 | return NULL; 412 | } 413 | SetLastError(NO_ERROR); 414 | 415 | return (pNtHeader->OptionalHeader.SizeOfImage); 416 | } 417 | __except(GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ? 418 | EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) { 419 | SetLastError(ERROR_EXE_MARKED_INVALID); 420 | return NULL; 421 | } 422 | } 423 | 424 | HMODULE WINAPI DetourGetContainingModule(_In_ PVOID pvAddr) 425 | { 426 | MEMORY_BASIC_INFORMATION mbi; 427 | ZeroMemory(&mbi, sizeof(mbi)); 428 | 429 | __try { 430 | if (VirtualQuery(pvAddr, &mbi, sizeof(mbi)) <= 0) { 431 | SetLastError(ERROR_BAD_EXE_FORMAT); 432 | return NULL; 433 | } 434 | 435 | // Skip uncommitted regions and guard pages. 436 | // 437 | if ((mbi.State != MEM_COMMIT) || 438 | ((mbi.Protect & 0xff) == PAGE_NOACCESS) || 439 | (mbi.Protect & PAGE_GUARD)) { 440 | SetLastError(ERROR_BAD_EXE_FORMAT); 441 | return NULL; 442 | } 443 | 444 | PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)mbi.AllocationBase; 445 | if (pDosHeader->e_magic != IMAGE_DOS_SIGNATURE) { 446 | SetLastError(ERROR_BAD_EXE_FORMAT); 447 | return NULL; 448 | } 449 | 450 | PIMAGE_NT_HEADERS pNtHeader = (PIMAGE_NT_HEADERS)((PBYTE)pDosHeader + 451 | pDosHeader->e_lfanew); 452 | if (pNtHeader->Signature != IMAGE_NT_SIGNATURE) { 453 | SetLastError(ERROR_INVALID_EXE_SIGNATURE); 454 | return NULL; 455 | } 456 | if (pNtHeader->FileHeader.SizeOfOptionalHeader == 0) { 457 | SetLastError(ERROR_EXE_MARKED_INVALID); 458 | return NULL; 459 | } 460 | SetLastError(NO_ERROR); 461 | 462 | return (HMODULE)pDosHeader; 463 | } 464 | __except(GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ? 465 | EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) { 466 | SetLastError(ERROR_INVALID_EXE_SIGNATURE); 467 | return NULL; 468 | } 469 | } 470 | 471 | 472 | static inline PBYTE RvaAdjust(_Pre_notnull_ PIMAGE_DOS_HEADER pDosHeader, _In_ DWORD raddr) 473 | { 474 | if (raddr != NULL) { 475 | return ((PBYTE)pDosHeader) + raddr; 476 | } 477 | return NULL; 478 | } 479 | 480 | BOOL WINAPI DetourEnumerateExports(_In_ HMODULE hModule, 481 | _In_opt_ PVOID pContext, 482 | _In_ PF_DETOUR_ENUMERATE_EXPORT_CALLBACK pfExport) 483 | { 484 | PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)hModule; 485 | if (hModule == NULL) { 486 | pDosHeader = (PIMAGE_DOS_HEADER)GetModuleHandleW(NULL); 487 | } 488 | 489 | __try { 490 | #pragma warning(suppress:6011) // GetModuleHandleW(NULL) never returns NULL. 491 | if (pDosHeader->e_magic != IMAGE_DOS_SIGNATURE) { 492 | SetLastError(ERROR_BAD_EXE_FORMAT); 493 | return NULL; 494 | } 495 | 496 | PIMAGE_NT_HEADERS pNtHeader = (PIMAGE_NT_HEADERS)((PBYTE)pDosHeader + 497 | pDosHeader->e_lfanew); 498 | if (pNtHeader->Signature != IMAGE_NT_SIGNATURE) { 499 | SetLastError(ERROR_INVALID_EXE_SIGNATURE); 500 | return FALSE; 501 | } 502 | if (pNtHeader->FileHeader.SizeOfOptionalHeader == 0) { 503 | SetLastError(ERROR_EXE_MARKED_INVALID); 504 | return FALSE; 505 | } 506 | 507 | PIMAGE_EXPORT_DIRECTORY pExportDir 508 | = (PIMAGE_EXPORT_DIRECTORY) 509 | RvaAdjust(pDosHeader, 510 | pNtHeader->OptionalHeader 511 | .DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress); 512 | 513 | if (pExportDir == NULL) { 514 | SetLastError(ERROR_EXE_MARKED_INVALID); 515 | return FALSE; 516 | } 517 | 518 | PBYTE pExportDirEnd = (PBYTE)pExportDir + pNtHeader->OptionalHeader 519 | .DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].Size; 520 | PDWORD pdwFunctions = (PDWORD)RvaAdjust(pDosHeader, pExportDir->AddressOfFunctions); 521 | PDWORD pdwNames = (PDWORD)RvaAdjust(pDosHeader, pExportDir->AddressOfNames); 522 | PWORD pwOrdinals = (PWORD)RvaAdjust(pDosHeader, pExportDir->AddressOfNameOrdinals); 523 | 524 | for (DWORD nFunc = 0; nFunc < pExportDir->NumberOfFunctions; nFunc++) { 525 | PBYTE pbCode = (pdwFunctions != NULL) 526 | ? (PBYTE)RvaAdjust(pDosHeader, pdwFunctions[nFunc]) : NULL; 527 | PCHAR pszName = NULL; 528 | 529 | // if the pointer is in the export region, then it is a forwarder. 530 | if (pbCode > (PBYTE)pExportDir && pbCode < pExportDirEnd) { 531 | pbCode = NULL; 532 | } 533 | 534 | for (DWORD n = 0; n < pExportDir->NumberOfNames; n++) { 535 | if (pwOrdinals[n] == nFunc) { 536 | pszName = (pdwNames != NULL) 537 | ? (PCHAR)RvaAdjust(pDosHeader, pdwNames[n]) : NULL; 538 | break; 539 | } 540 | } 541 | ULONG nOrdinal = pExportDir->Base + nFunc; 542 | 543 | if (!pfExport(pContext, nOrdinal, pszName, pbCode)) { 544 | break; 545 | } 546 | } 547 | SetLastError(NO_ERROR); 548 | return TRUE; 549 | } 550 | __except(GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ? 551 | EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) { 552 | SetLastError(ERROR_EXE_MARKED_INVALID); 553 | return NULL; 554 | } 555 | } 556 | 557 | BOOL WINAPI DetourEnumerateImportsEx(_In_opt_ HMODULE hModule, 558 | _In_opt_ PVOID pContext, 559 | _In_opt_ PF_DETOUR_IMPORT_FILE_CALLBACK pfImportFile, 560 | _In_opt_ PF_DETOUR_IMPORT_FUNC_CALLBACK_EX pfImportFunc) 561 | { 562 | PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)hModule; 563 | if (hModule == NULL) { 564 | pDosHeader = (PIMAGE_DOS_HEADER)GetModuleHandleW(NULL); 565 | } 566 | 567 | __try { 568 | #pragma warning(suppress:6011) // GetModuleHandleW(NULL) never returns NULL. 569 | if (pDosHeader->e_magic != IMAGE_DOS_SIGNATURE) { 570 | SetLastError(ERROR_BAD_EXE_FORMAT); 571 | return FALSE; 572 | } 573 | 574 | PIMAGE_NT_HEADERS pNtHeader = (PIMAGE_NT_HEADERS)((PBYTE)pDosHeader + 575 | pDosHeader->e_lfanew); 576 | if (pNtHeader->Signature != IMAGE_NT_SIGNATURE) { 577 | SetLastError(ERROR_INVALID_EXE_SIGNATURE); 578 | return FALSE; 579 | } 580 | if (pNtHeader->FileHeader.SizeOfOptionalHeader == 0) { 581 | SetLastError(ERROR_EXE_MARKED_INVALID); 582 | return FALSE; 583 | } 584 | 585 | PIMAGE_IMPORT_DESCRIPTOR iidp 586 | = (PIMAGE_IMPORT_DESCRIPTOR) 587 | RvaAdjust(pDosHeader, 588 | pNtHeader->OptionalHeader 589 | .DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress); 590 | 591 | if (iidp == NULL) { 592 | SetLastError(ERROR_EXE_MARKED_INVALID); 593 | return FALSE; 594 | } 595 | 596 | for (; iidp->OriginalFirstThunk != 0; iidp++) { 597 | 598 | PCSTR pszName = (PCHAR)RvaAdjust(pDosHeader, iidp->Name); 599 | if (pszName == NULL) { 600 | SetLastError(ERROR_EXE_MARKED_INVALID); 601 | return FALSE; 602 | } 603 | 604 | PIMAGE_THUNK_DATA pThunks = (PIMAGE_THUNK_DATA) 605 | RvaAdjust(pDosHeader, iidp->OriginalFirstThunk); 606 | PVOID * pAddrs = (PVOID *) 607 | RvaAdjust(pDosHeader, iidp->FirstThunk); 608 | 609 | HMODULE hFile = DetourGetContainingModule(pAddrs[0]); 610 | 611 | if (pfImportFile != NULL) { 612 | if (!pfImportFile(pContext, hFile, pszName)) { 613 | break; 614 | } 615 | } 616 | 617 | DWORD nNames = 0; 618 | if (pThunks) { 619 | for (; pThunks[nNames].u1.Ordinal; nNames++) { 620 | DWORD nOrdinal = 0; 621 | PCSTR pszFunc = NULL; 622 | 623 | if (IMAGE_SNAP_BY_ORDINAL(pThunks[nNames].u1.Ordinal)) { 624 | nOrdinal = (DWORD)IMAGE_ORDINAL(pThunks[nNames].u1.Ordinal); 625 | } 626 | else { 627 | pszFunc = (PCSTR)RvaAdjust(pDosHeader, 628 | (DWORD)pThunks[nNames].u1.AddressOfData + 2); 629 | } 630 | 631 | if (pfImportFunc != NULL) { 632 | if (!pfImportFunc(pContext, 633 | nOrdinal, 634 | pszFunc, 635 | &pAddrs[nNames])) { 636 | break; 637 | } 638 | } 639 | } 640 | if (pfImportFunc != NULL) { 641 | pfImportFunc(pContext, 0, NULL, NULL); 642 | } 643 | } 644 | } 645 | if (pfImportFile != NULL) { 646 | pfImportFile(pContext, NULL, NULL); 647 | } 648 | SetLastError(NO_ERROR); 649 | return TRUE; 650 | } 651 | __except(GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ? 652 | EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) { 653 | SetLastError(ERROR_EXE_MARKED_INVALID); 654 | return FALSE; 655 | } 656 | } 657 | 658 | // Context for DetourEnumerateImportsThunk, which adapts "regular" callbacks for use with "Ex". 659 | struct _DETOUR_ENUMERATE_IMPORTS_THUNK_CONTEXT 660 | { 661 | PVOID pContext; 662 | PF_DETOUR_IMPORT_FUNC_CALLBACK pfImportFunc; 663 | }; 664 | 665 | // Callback for DetourEnumerateImportsEx that adapts DetourEnumerateImportsEx 666 | // for use with a DetourEnumerateImports callback -- derefence the IAT and pass the value on. 667 | 668 | static 669 | BOOL 670 | CALLBACK 671 | DetourEnumerateImportsThunk(_In_ PVOID VoidContext, 672 | _In_ DWORD nOrdinal, 673 | _In_opt_ PCSTR pszFunc, 674 | _In_opt_ PVOID* ppvFunc) 675 | { 676 | _DETOUR_ENUMERATE_IMPORTS_THUNK_CONTEXT const * const 677 | pContext = (_DETOUR_ENUMERATE_IMPORTS_THUNK_CONTEXT*)VoidContext; 678 | return pContext->pfImportFunc(pContext->pContext, nOrdinal, pszFunc, ppvFunc ? *ppvFunc : NULL); 679 | } 680 | 681 | BOOL WINAPI DetourEnumerateImports(_In_opt_ HMODULE hModule, 682 | _In_opt_ PVOID pContext, 683 | _In_opt_ PF_DETOUR_IMPORT_FILE_CALLBACK pfImportFile, 684 | _In_opt_ PF_DETOUR_IMPORT_FUNC_CALLBACK pfImportFunc) 685 | { 686 | _DETOUR_ENUMERATE_IMPORTS_THUNK_CONTEXT const context = { pContext, pfImportFunc }; 687 | 688 | return DetourEnumerateImportsEx(hModule, 689 | (PVOID)&context, 690 | pfImportFile, 691 | &DetourEnumerateImportsThunk); 692 | } 693 | 694 | static PDETOUR_LOADED_BINARY WINAPI GetPayloadSectionFromModule(HMODULE hModule) 695 | { 696 | PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)hModule; 697 | if (hModule == NULL) { 698 | pDosHeader = (PIMAGE_DOS_HEADER)GetModuleHandleW(NULL); 699 | } 700 | 701 | __try { 702 | #pragma warning(suppress:6011) // GetModuleHandleW(NULL) never returns NULL. 703 | if (pDosHeader->e_magic != IMAGE_DOS_SIGNATURE) { 704 | SetLastError(ERROR_BAD_EXE_FORMAT); 705 | return NULL; 706 | } 707 | 708 | PIMAGE_NT_HEADERS pNtHeader = (PIMAGE_NT_HEADERS)((PBYTE)pDosHeader + 709 | pDosHeader->e_lfanew); 710 | if (pNtHeader->Signature != IMAGE_NT_SIGNATURE) { 711 | SetLastError(ERROR_INVALID_EXE_SIGNATURE); 712 | return NULL; 713 | } 714 | if (pNtHeader->FileHeader.SizeOfOptionalHeader == 0) { 715 | SetLastError(ERROR_EXE_MARKED_INVALID); 716 | return NULL; 717 | } 718 | 719 | PIMAGE_SECTION_HEADER pSectionHeaders 720 | = (PIMAGE_SECTION_HEADER)((PBYTE)pNtHeader 721 | + sizeof(pNtHeader->Signature) 722 | + sizeof(pNtHeader->FileHeader) 723 | + pNtHeader->FileHeader.SizeOfOptionalHeader); 724 | 725 | for (DWORD n = 0; n < pNtHeader->FileHeader.NumberOfSections; n++) { 726 | if (strcmp((PCHAR)pSectionHeaders[n].Name, ".detour") == 0) { 727 | if (pSectionHeaders[n].VirtualAddress == 0 || 728 | pSectionHeaders[n].SizeOfRawData == 0) { 729 | 730 | break; 731 | } 732 | 733 | PBYTE pbData = (PBYTE)pDosHeader + pSectionHeaders[n].VirtualAddress; 734 | DETOUR_SECTION_HEADER *pHeader = (DETOUR_SECTION_HEADER *)pbData; 735 | if (pHeader->cbHeaderSize < sizeof(DETOUR_SECTION_HEADER) || 736 | pHeader->nSignature != DETOUR_SECTION_HEADER_SIGNATURE) { 737 | 738 | break; 739 | } 740 | 741 | if (pHeader->nDataOffset == 0) { 742 | pHeader->nDataOffset = pHeader->cbHeaderSize; 743 | } 744 | SetLastError(NO_ERROR); 745 | return (PBYTE)pHeader; 746 | } 747 | } 748 | SetLastError(ERROR_EXE_MARKED_INVALID); 749 | return NULL; 750 | } 751 | __except(GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ? 752 | EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) { 753 | SetLastError(ERROR_EXE_MARKED_INVALID); 754 | return NULL; 755 | } 756 | } 757 | 758 | DWORD WINAPI DetourGetSizeOfPayloads(_In_opt_ HMODULE hModule) 759 | { 760 | PDETOUR_LOADED_BINARY pBinary = GetPayloadSectionFromModule(hModule); 761 | if (pBinary == NULL) { 762 | // Error set by GetPayloadSectionFromModule. 763 | return 0; 764 | } 765 | 766 | __try { 767 | DETOUR_SECTION_HEADER *pHeader = (DETOUR_SECTION_HEADER *)pBinary; 768 | if (pHeader->cbHeaderSize < sizeof(DETOUR_SECTION_HEADER) || 769 | pHeader->nSignature != DETOUR_SECTION_HEADER_SIGNATURE) { 770 | 771 | SetLastError(ERROR_INVALID_HANDLE); 772 | return 0; 773 | } 774 | SetLastError(NO_ERROR); 775 | return pHeader->cbDataSize; 776 | } 777 | __except(GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ? 778 | EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) { 779 | SetLastError(ERROR_INVALID_HANDLE); 780 | return 0; 781 | } 782 | } 783 | 784 | _Writable_bytes_(*pcbData) 785 | _Readable_bytes_(*pcbData) 786 | _Success_(return != NULL) 787 | PVOID WINAPI DetourFindPayload(_In_opt_ HMODULE hModule, 788 | _In_ REFGUID rguid, 789 | _Out_ DWORD *pcbData) 790 | { 791 | PBYTE pbData = NULL; 792 | if (pcbData) { 793 | *pcbData = 0; 794 | } 795 | 796 | PDETOUR_LOADED_BINARY pBinary = GetPayloadSectionFromModule(hModule); 797 | if (pBinary == NULL) { 798 | // Error set by GetPayloadSectionFromModule. 799 | return NULL; 800 | } 801 | 802 | __try { 803 | DETOUR_SECTION_HEADER *pHeader = (DETOUR_SECTION_HEADER *)pBinary; 804 | if (pHeader->cbHeaderSize < sizeof(DETOUR_SECTION_HEADER) || 805 | pHeader->nSignature != DETOUR_SECTION_HEADER_SIGNATURE) { 806 | 807 | SetLastError(ERROR_INVALID_EXE_SIGNATURE); 808 | return NULL; 809 | } 810 | 811 | PBYTE pbBeg = ((PBYTE)pHeader) + pHeader->nDataOffset; 812 | PBYTE pbEnd = ((PBYTE)pHeader) + pHeader->cbDataSize; 813 | 814 | for (pbData = pbBeg; pbData < pbEnd;) { 815 | DETOUR_SECTION_RECORD *pSection = (DETOUR_SECTION_RECORD *)pbData; 816 | 817 | if (pSection->guid.Data1 == rguid.Data1 && 818 | pSection->guid.Data2 == rguid.Data2 && 819 | pSection->guid.Data3 == rguid.Data3 && 820 | pSection->guid.Data4[0] == rguid.Data4[0] && 821 | pSection->guid.Data4[1] == rguid.Data4[1] && 822 | pSection->guid.Data4[2] == rguid.Data4[2] && 823 | pSection->guid.Data4[3] == rguid.Data4[3] && 824 | pSection->guid.Data4[4] == rguid.Data4[4] && 825 | pSection->guid.Data4[5] == rguid.Data4[5] && 826 | pSection->guid.Data4[6] == rguid.Data4[6] && 827 | pSection->guid.Data4[7] == rguid.Data4[7]) { 828 | 829 | if (pcbData) { 830 | *pcbData = pSection->cbBytes - sizeof(*pSection); 831 | SetLastError(NO_ERROR); 832 | return (PBYTE)(pSection + 1); 833 | } 834 | } 835 | 836 | pbData = (PBYTE)pSection + pSection->cbBytes; 837 | } 838 | SetLastError(ERROR_INVALID_HANDLE); 839 | return NULL; 840 | } 841 | __except(GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ? 842 | EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) { 843 | SetLastError(ERROR_INVALID_HANDLE); 844 | return NULL; 845 | } 846 | } 847 | 848 | _Writable_bytes_(*pcbData) 849 | _Readable_bytes_(*pcbData) 850 | _Success_(return != NULL) 851 | PVOID WINAPI DetourFindPayloadEx(_In_ REFGUID rguid, 852 | _Out_ DWORD * pcbData) 853 | { 854 | for (HMODULE hMod = NULL; (hMod = DetourEnumerateModules(hMod)) != NULL;) { 855 | PVOID pvData; 856 | 857 | pvData = DetourFindPayload(hMod, rguid, pcbData); 858 | if (pvData != NULL) { 859 | return pvData; 860 | } 861 | } 862 | SetLastError(ERROR_MOD_NOT_FOUND); 863 | return NULL; 864 | } 865 | 866 | BOOL WINAPI DetourRestoreAfterWithEx(_In_reads_bytes_(cbData) PVOID pvData, 867 | _In_ DWORD cbData) 868 | { 869 | PDETOUR_EXE_RESTORE pder = (PDETOUR_EXE_RESTORE)pvData; 870 | 871 | if (pder->cb != sizeof(*pder) || pder->cb > cbData) { 872 | SetLastError(ERROR_BAD_EXE_FORMAT); 873 | return FALSE; 874 | } 875 | 876 | DWORD dwPermIdh = ~0u; 877 | DWORD dwPermInh = ~0u; 878 | DWORD dwPermClr = ~0u; 879 | DWORD dwIgnore; 880 | BOOL fSucceeded = FALSE; 881 | BOOL fUpdated32To64 = FALSE; 882 | 883 | if (pder->pclr != NULL && pder->clr.Flags != ((PDETOUR_CLR_HEADER)pder->pclr)->Flags) { 884 | // If we had to promote the 32/64-bit agnostic IL to 64-bit, we can't restore 885 | // that. 886 | fUpdated32To64 = TRUE; 887 | } 888 | 889 | if (DetourVirtualProtectSameExecute(pder->pidh, pder->cbidh, 890 | PAGE_EXECUTE_READWRITE, &dwPermIdh)) { 891 | if (DetourVirtualProtectSameExecute(pder->pinh, pder->cbinh, 892 | PAGE_EXECUTE_READWRITE, &dwPermInh)) { 893 | 894 | CopyMemory(pder->pidh, &pder->idh, pder->cbidh); 895 | CopyMemory(pder->pinh, &pder->inh, pder->cbinh); 896 | 897 | if (pder->pclr != NULL && !fUpdated32To64) { 898 | if (DetourVirtualProtectSameExecute(pder->pclr, pder->cbclr, 899 | PAGE_EXECUTE_READWRITE, &dwPermClr)) { 900 | CopyMemory(pder->pclr, &pder->clr, pder->cbclr); 901 | VirtualProtect(pder->pclr, pder->cbclr, dwPermClr, &dwIgnore); 902 | fSucceeded = TRUE; 903 | } 904 | } 905 | else { 906 | fSucceeded = TRUE; 907 | } 908 | VirtualProtect(pder->pinh, pder->cbinh, dwPermInh, &dwIgnore); 909 | } 910 | VirtualProtect(pder->pidh, pder->cbidh, dwPermIdh, &dwIgnore); 911 | } 912 | return fSucceeded; 913 | } 914 | 915 | BOOL WINAPI DetourRestoreAfterWith() 916 | { 917 | PVOID pvData; 918 | DWORD cbData; 919 | 920 | pvData = DetourFindPayloadEx(DETOUR_EXE_RESTORE_GUID, &cbData); 921 | 922 | if (pvData != NULL && cbData != 0) { 923 | return DetourRestoreAfterWithEx(pvData, cbData); 924 | } 925 | SetLastError(ERROR_MOD_NOT_FOUND); 926 | return FALSE; 927 | } 928 | 929 | // End of File 930 | -------------------------------------------------------------------------------- /ShooterGameCheat/dllmain.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Expost/GameCheat/fba8e1343797d79ae2fae1f40b2e32538f195fe7/ShooterGameCheat/dllmain.cpp -------------------------------------------------------------------------------- /ShooterGameCheat/game/adapt_data.h: -------------------------------------------------------------------------------- 1 | #ifndef _SHOOTERCLIENT_WIN64_SHIPPING_DEF_H_ 2 | #define _SHOOTERCLIENT_WIN64_SHIPPING_DEF_H_ 3 | 4 | #define GAME_GWORLD (0x2F70070) 5 | #define GAME_GENGINE (0x2F6D6F8) 6 | #define GAME_NAMES_PTR (0x2E6D0F8) 7 | #define GAME_PERSISTENT_LEVEL_OFFSET (0x30) 8 | #define GAME_GAMEINSTANCE_OFFSET (0x160) 9 | #define GAME_LOCALPLAYER_OFFSET (0x38) 10 | #define GAME_PLAYERCONTROLLER_OFFSET (0x30) 11 | #define GAME_ALL_ACTORS_OFFSET (0x98) 12 | #define GAME_OBJ_NAME_OFFSET (0x18) 13 | #define GAME_MEDIUM_FONT (0x70) 14 | #define GAME_CANVAS_OFFSET (0x380) 15 | #define GAME_ACKNOWLEDEGED_PAWN_OFFSET (0x3B0) 16 | #define GAME_CONTROLROTATION_OFFSET (0x398) 17 | #define GAME_PLAYERCONTROLLER_HUD_OFFSET (0x3C0) 18 | #define GAME_PLAYER_CAMERA_MANAGER (0x3C8) 19 | #define GAME_CAMERACACHEPRIVATE (0x1A20) 20 | #define GAME_CAMERA_POV (0x10) 21 | #define GAME_CAMERA_ROTATION (0xC) 22 | #define GAME_CAMERA_LOCATION (0x0) 23 | #define GAME_CAMERA_FOV (0x18) 24 | #define GAME_PAWN_PLAYERSTATE_OFFSET (0x350) 25 | #define GAME_PAWN_HEALTH_OFFSET (0x92C) 26 | #define GAME_PAWN_NAME (0x438) 27 | #define GAME_PAWN_ROOTCOMMENT (0x158) 28 | #define GAME_PAWN_LOCATION (0x164) 29 | #define GAME_GET_CAMERADAMAGESTARTLOCATION_OFFSET (0x524080) 30 | #define GAME_WORLD_TO_SCREEN_OFFSET (0x1542850) 31 | #define GAME_LINEOFSIGHTTO_OFFSET (0x148B970) 32 | #define GAME_GET_VIEWPORT_SIZE (0x175BD00) 33 | #define GAME_DRAWTEXT_OFFSET (0x155E920) 34 | #define GAME_DRAW_HUD_OFFSET (0x155E280) 35 | #define GAME_DRAW_RECT_OFFSET (0x155E870) 36 | #define GAME_DRAW_LINE_OFFSET (0x155E350) 37 | 38 | 39 | #endif //_SHOOTERCLIENT_WIN64_SHIPPING_DEF_H_ 40 | -------------------------------------------------------------------------------- /ShooterGameCheat/game/base_struct.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #ifdef _MSC_VER 8 | #pragma pack(push, 0x8) 9 | #endif 10 | 11 | struct FVector 12 | { 13 | float X; // 0x0000(0x0004) (Edit, BlueprintVisible, ZeroConstructor, SaveGame, IsPlainOldData) 14 | float Y; // 0x0004(0x0004) (Edit, BlueprintVisible, ZeroConstructor, SaveGame, IsPlainOldData) 15 | float Z; // 0x0008(0x0004) (Edit, BlueprintVisible, ZeroConstructor, SaveGame, IsPlainOldData) 16 | 17 | FVector(float f_x = 0, float f_y = 0, float f_z = 0) 18 | { 19 | X = f_x; 20 | Y = f_y; 21 | Z = f_z; 22 | } 23 | 24 | float Dot(const FVector& v) const 25 | { 26 | return (X * v.X + Y * v.Y + Z * v.Z); 27 | } 28 | 29 | FVector operator-(FVector v) const 30 | { 31 | return FVector(X - v.X, Y - v.Y, Z - v.Z); 32 | } 33 | }; 34 | 35 | struct FVector2D 36 | { 37 | float X; // 0x0000(0x0004) (Edit, BlueprintVisible, ZeroConstructor, SaveGame, IsPlainOldData) 38 | float Y; // 0x0004(0x0004) (Edit, BlueprintVisible, ZeroConstructor, SaveGame, IsPlainOldData) 39 | 40 | inline FVector2D() 41 | : X(0), Y(0) 42 | { } 43 | 44 | inline FVector2D(float x, float y) 45 | : X(x), 46 | Y(y) 47 | { } 48 | 49 | }; 50 | 51 | struct FLinearColor 52 | { 53 | float R; // 0x0000(0x0004) (Edit, BlueprintVisible, ZeroConstructor, SaveGame, IsPlainOldData) 54 | float G; // 0x0004(0x0004) (Edit, BlueprintVisible, ZeroConstructor, SaveGame, IsPlainOldData) 55 | float B; // 0x0008(0x0004) (Edit, BlueprintVisible, ZeroConstructor, SaveGame, IsPlainOldData) 56 | float A; // 0x000C(0x0004) (Edit, BlueprintVisible, ZeroConstructor, SaveGame, IsPlainOldData) 57 | 58 | inline FLinearColor() 59 | : R(0), G(0), B(0), A(0) 60 | { } 61 | 62 | inline FLinearColor(float r, float g, float b, float a) 63 | : R(r), 64 | G(g), 65 | B(b), 66 | A(a) 67 | { } 68 | 69 | }; 70 | 71 | // 72 | //struct vector3D 73 | //{ 74 | // float x; 75 | // float y; 76 | // float z; 77 | // 78 | // vector3D(float f_x = 0, float f_y = 0, float f_z = 0) 79 | // { 80 | // x = f_x; 81 | // y = f_y; 82 | // z = f_z; 83 | // } 84 | // 85 | // 86 | // float Dot(const vector3D& v) const 87 | // { 88 | // return (x * v.x + y * v.y + z * v.z); 89 | // } 90 | // 91 | // vector3D operator-(vector3D v) const 92 | // { 93 | // return vector3D(x - v.x, y - v.y, z - v.z); 94 | // } 95 | // 96 | // float distance(vector3D v) 97 | // { 98 | // return sqrt(pow((v.x - x), 2) + pow((v.y - y), 2) + pow((v.z - z), 2)); 99 | // } 100 | // 101 | // vector3D(float* v) 102 | // { 103 | // x = v[0]; 104 | // y = v[1]; 105 | // z = v[2]; 106 | // } 107 | //}; 108 | 109 | 110 | 111 | struct vector2D 112 | { 113 | float x; 114 | float y; 115 | 116 | vector2D(float f_x = 0, float f_y = 0) 117 | { 118 | x = f_x; 119 | y = f_y; 120 | } 121 | 122 | float distance(vector2D v) 123 | { 124 | return sqrt(pow((v.x - x), 2) + pow((v.y - y), 2)); 125 | } 126 | }; 127 | 128 | struct vMatrix 129 | { 130 | vMatrix() {} 131 | vMatrix( 132 | float m00, float m01, float m02, float m03, 133 | float m10, float m11, float m12, float m13, 134 | float m20, float m21, float m22, float m23) 135 | { 136 | m_flMatVal[0][0] = m00; m_flMatVal[0][1] = m01; m_flMatVal[0][2] = m02; m_flMatVal[0][3] = m03; 137 | m_flMatVal[1][0] = m10; m_flMatVal[1][1] = m11; m_flMatVal[1][2] = m12; m_flMatVal[1][3] = m13; 138 | m_flMatVal[2][0] = m20; m_flMatVal[2][1] = m21; m_flMatVal[2][2] = m22; m_flMatVal[2][3] = m23; 139 | } 140 | 141 | float* operator[](int i) 142 | { 143 | /* Assert((i >= 0) && (i < 3));*/ 144 | return m_flMatVal[i]; 145 | } 146 | const float* operator[](int i) const 147 | { 148 | /*Assert((i >= 0) && (i < 3)); */ 149 | return m_flMatVal[i]; 150 | } 151 | 152 | float* Base() { return &m_flMatVal[0][0]; } 153 | const float* Base() const { return &m_flMatVal[0][0]; } 154 | 155 | float m_flMatVal[3][4]; 156 | }; 157 | 158 | template 159 | class TArray 160 | { 161 | friend class FString; 162 | 163 | public: 164 | inline TArray() 165 | { 166 | Data = nullptr; 167 | Count = Max = 0; 168 | }; 169 | 170 | inline int Num() const 171 | { 172 | return Count; 173 | }; 174 | 175 | inline T& operator[](int i) 176 | { 177 | return Data[i]; 178 | }; 179 | 180 | inline const T& operator[](int i) const 181 | { 182 | return Data[i]; 183 | }; 184 | 185 | inline bool IsValidIndex(int i) const 186 | { 187 | return i < Num(); 188 | } 189 | 190 | public: 191 | T* Data; 192 | int32_t Count; 193 | int32_t Max; 194 | }; 195 | 196 | class FString : public TArray 197 | { 198 | public: 199 | inline FString() 200 | { 201 | }; 202 | 203 | FString(const wchar_t* other) 204 | { 205 | Max = Count = *other ? std::wcslen(other) + 1 : 0; 206 | 207 | if (Count) 208 | { 209 | Data = const_cast(other); 210 | } 211 | }; 212 | 213 | inline bool IsValid() const 214 | { 215 | return Data != nullptr; 216 | } 217 | 218 | inline const wchar_t* c_str() const 219 | { 220 | return Data; 221 | } 222 | 223 | std::string ToString() const 224 | { 225 | const auto length = std::wcslen(Data); 226 | 227 | std::string str(length, '\0'); 228 | 229 | std::use_facet>(std::locale()).narrow(Data, Data + length, '?', &str[0]); 230 | 231 | return str; 232 | } 233 | }; 234 | 235 | class FNameEntry 236 | { 237 | public: 238 | static const auto NAME_WIDE_MASK = 0x1; 239 | static const auto NAME_INDEX_SHIFT = 1; 240 | 241 | int32_t Index; 242 | char UnknownData00[0x04]; 243 | FNameEntry* HashNext; 244 | union 245 | { 246 | char AnsiName[1024]; 247 | wchar_t WideName[1024]; 248 | }; 249 | 250 | inline const int32_t GetIndex() const 251 | { 252 | return Index >> NAME_INDEX_SHIFT; 253 | } 254 | 255 | inline bool IsWide() const 256 | { 257 | return Index & NAME_WIDE_MASK; 258 | } 259 | 260 | inline const char* GetAnsiName() const 261 | { 262 | return AnsiName; 263 | } 264 | 265 | inline const wchar_t* GetWideName() const 266 | { 267 | return WideName; 268 | } 269 | }; 270 | 271 | template 272 | class TStaticIndirectArrayThreadSafeRead 273 | { 274 | public: 275 | inline size_t Num() const 276 | { 277 | return NumElements; 278 | } 279 | 280 | inline bool IsValidIndex(int32_t index) const 281 | { 282 | return index < Num() && index >= 0; 283 | } 284 | 285 | inline ElementType const* const& operator[](int32_t index) const 286 | { 287 | return *GetItemPtr(index); 288 | } 289 | 290 | private: 291 | inline ElementType const* const* GetItemPtr(int32_t Index) const 292 | { 293 | const auto ChunkIndex = Index / ElementsPerChunk; 294 | const auto WithinChunkIndex = Index % ElementsPerChunk; 295 | const auto Chunk = Chunks[ChunkIndex]; 296 | return Chunk + WithinChunkIndex; 297 | } 298 | 299 | enum 300 | { 301 | ChunkTableSize = (MaxTotalElements + ElementsPerChunk - 1) / ElementsPerChunk 302 | }; 303 | 304 | ElementType** Chunks[ChunkTableSize]; 305 | int32_t NumElements; 306 | int32_t NumChunks; 307 | }; 308 | 309 | using TNameEntryArray = TStaticIndirectArrayThreadSafeRead; 310 | 311 | 312 | struct FName 313 | { 314 | union 315 | { 316 | struct 317 | { 318 | int32_t ComparisonIndex; 319 | int32_t Number; 320 | }; 321 | 322 | uint64_t CompositeComparisonValue; 323 | }; 324 | 325 | inline FName() 326 | : ComparisonIndex(0), 327 | Number(0) 328 | { 329 | }; 330 | 331 | inline FName(int32_t i) 332 | : ComparisonIndex(i), 333 | Number(0) 334 | { 335 | }; 336 | 337 | FName(const char* nameToFind) 338 | : ComparisonIndex(0), 339 | Number(0) 340 | { 341 | static std::unordered_set cache; 342 | 343 | for (auto i : cache) 344 | { 345 | if (!std::strcmp(GetGlobalNames()[i]->GetAnsiName(), nameToFind)) 346 | { 347 | ComparisonIndex = i; 348 | 349 | return; 350 | } 351 | } 352 | 353 | for (auto i = 0; i < GetGlobalNames().Num(); ++i) 354 | { 355 | if (GetGlobalNames()[i] != nullptr) 356 | { 357 | if (!std::strcmp(GetGlobalNames()[i]->GetAnsiName(), nameToFind)) 358 | { 359 | cache.insert(i); 360 | 361 | ComparisonIndex = i; 362 | 363 | return; 364 | } 365 | } 366 | } 367 | }; 368 | 369 | static TNameEntryArray *GNames; 370 | static inline TNameEntryArray& GetGlobalNames() 371 | { 372 | return *GNames; 373 | }; 374 | 375 | inline const char* GetName() const 376 | { 377 | return GetGlobalNames()[ComparisonIndex]->GetAnsiName(); 378 | }; 379 | 380 | inline bool operator==(const FName &other) const 381 | { 382 | return ComparisonIndex == other.ComparisonIndex; 383 | }; 384 | }; 385 | 386 | #ifdef _MSC_VER 387 | #pragma pack(pop) 388 | #endif 389 | -------------------------------------------------------------------------------- /ShooterGameCheat/game/game.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Expost/GameCheat/fba8e1343797d79ae2fae1f40b2e32538f195fe7/ShooterGameCheat/game/game.cpp -------------------------------------------------------------------------------- /ShooterGameCheat/game/game.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "base_struct.h" 4 | 5 | namespace Game { 6 | 7 | using DrawHUDType = void(__fastcall*)(void *); 8 | using WorldToScreenType = bool(__fastcall*)(uint8_t*, FVector&, FVector2D&); 9 | using GetCameraDamageStartLocationType = FVector * (__fastcall*) (void*, FVector*, FVector*); 10 | using LineOfSightToType = bool(__fastcall*)(uint8_t*, uint8_t*, FVector, bool); 11 | using GetViewportSizeType = void(__thiscall*)(uint8_t*, int*, int*); 12 | using DrawTextType = float(__fastcall*)(uint8_t*, FString const&, FLinearColor, float, float, uint8_t*, float, bool); 13 | using DrawRectType = void(__fastcall*)(uint8_t*, FLinearColor, float, float, float, float); 14 | using DrawLineType = void(__fastcall*)(uint8_t*, float, float, float, float, FLinearColor, float); 15 | 16 | extern uint8_t** g_engine; 17 | extern uint8_t** g_world; 18 | extern WorldToScreenType g_w2s_func; 19 | extern DrawHUDType g_draw_hud_func; 20 | extern GetCameraDamageStartLocationType g_get_damage_start_location_func; 21 | extern LineOfSightToType g_line_of_sight_to_func; 22 | extern GetViewportSizeType g_get_viewport_size_func; 23 | extern DrawTextType g_draw_text_func; 24 | extern DrawRectType g_draw_rect_func; 25 | extern DrawLineType g_draw_line_func; 26 | 27 | uint8_t *get_local_player_controller(uint8_t **world); 28 | bool is_local_player(uint8_t **world, uint8_t* actor); 29 | uint8_t* get_pawn_state(uint8_t *pawn); 30 | float get_pawn_health(uint8_t *pawn); 31 | FString get_pawn_name(uint8_t *pawn); 32 | bool get_pawn_location(uint8_t *pawn, FVector *location); 33 | void get_local_player_location(uint8_t *controller, FVector *location); 34 | uint8_t *get_all_actors(uint8_t **world); 35 | std::string get_object_name(uint8_t *obj); 36 | void draw_text(uint8_t *hud, const FString& text, float x, float y, const FLinearColor& color); 37 | uint8_t* get_closest_visible_player(uint8_t** world); 38 | void cal_new_rotation(FVector local_pos, FVector target_pos, float &pitch, float &yaw); 39 | void set_local_player_rotation(uint8_t *controller, float &pitch, float &yaw); 40 | 41 | void draw_box(uint8_t *hud, float a, float b, float c, float d, FLinearColor color); 42 | 43 | FVector2D get_box_size(uint8_t *player_controller, FVector target_pos); 44 | bool world_to_screen(uint8_t *player_controller, FVector target_pos, FVector2D* screen_pos); 45 | } -------------------------------------------------------------------------------- /ShooterGameCheat/shooter_game_cheat.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Expost/GameCheat/fba8e1343797d79ae2fae1f40b2e32538f195fe7/ShooterGameCheat/shooter_game_cheat.cpp -------------------------------------------------------------------------------- /ShooterGameCheat/utils.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | 5 | namespace Utils { 6 | 7 | _inline void dbg_out(const char *str, ...) 8 | { 9 | char szMsg[1024] = { 0 }; 10 | 11 | va_list ap; 12 | va_start(ap, str); 13 | _vsnprintf_s(szMsg, 1024 - 1, str, ap); 14 | va_end(ap); 15 | 16 | OutputDebugStringA(szMsg); 17 | } 18 | 19 | _inline float get_distance_3d(FVector x, FVector y) 20 | { 21 | FVector z; 22 | z.X = x.X - y.X; 23 | z.Y = x.Y - y.Y; 24 | z.Z = x.Z - y.Z; 25 | 26 | return sqrt(z.X * z.X + z.Y * z.Y + z.Z * z.Z); 27 | } 28 | 29 | _inline float get_distance_2d(FVector2D point1, FVector2D point2) 30 | { 31 | FVector2D heading; 32 | heading.X = point1.X - point2.X; 33 | heading.Y = point1.Y - point2.Y; 34 | 35 | float distanceSquared; 36 | float distance; 37 | 38 | distanceSquared = heading.X * heading.X + heading.Y * heading.Y; 39 | distance = sqrt(distanceSquared); 40 | 41 | return distance; 42 | } 43 | } --------------------------------------------------------------------------------