├── README.md ├── r5script.sln └── r5script ├── Detours.lib ├── detours.h ├── dllmain.cpp ├── lazy_importer.hh ├── r5script.vcxproj ├── r5script.vcxproj.filters ├── r5script.vcxproj.user └── skcrypter.h /README.md: -------------------------------------------------------------------------------- 1 | # r5script 2 | 3 | https://www.unknowncheats.me/forum/apex-legends/571695-custom-script-loader-rson.html 4 | -------------------------------------------------------------------------------- /r5script.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.33130.400 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "r5script", "r5script\r5script.vcxproj", "{0FDBEA6C-37CD-4F61-B7D0-36663C7D4955}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|x64 = Debug|x64 11 | Debug|x86 = Debug|x86 12 | Release|x64 = Release|x64 13 | Release|x86 = Release|x86 14 | EndGlobalSection 15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 16 | {0FDBEA6C-37CD-4F61-B7D0-36663C7D4955}.Debug|x64.ActiveCfg = Debug|x64 17 | {0FDBEA6C-37CD-4F61-B7D0-36663C7D4955}.Debug|x64.Build.0 = Debug|x64 18 | {0FDBEA6C-37CD-4F61-B7D0-36663C7D4955}.Debug|x86.ActiveCfg = Debug|Win32 19 | {0FDBEA6C-37CD-4F61-B7D0-36663C7D4955}.Debug|x86.Build.0 = Debug|Win32 20 | {0FDBEA6C-37CD-4F61-B7D0-36663C7D4955}.Release|x64.ActiveCfg = Release|x64 21 | {0FDBEA6C-37CD-4F61-B7D0-36663C7D4955}.Release|x64.Build.0 = Release|x64 22 | {0FDBEA6C-37CD-4F61-B7D0-36663C7D4955}.Release|x86.ActiveCfg = Release|Win32 23 | {0FDBEA6C-37CD-4F61-B7D0-36663C7D4955}.Release|x86.Build.0 = Release|Win32 24 | EndGlobalSection 25 | GlobalSection(SolutionProperties) = preSolution 26 | HideSolutionNode = FALSE 27 | EndGlobalSection 28 | GlobalSection(ExtensibilityGlobals) = postSolution 29 | SolutionGuid = {616A229C-0739-4D02-AF70-218783DCAC81} 30 | EndGlobalSection 31 | EndGlobal 32 | -------------------------------------------------------------------------------- /r5script/Detours.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Am3Chan/r5script/707f16e2c04d7654df0dd15a69374ae46850f8f6/r5script/Detours.lib -------------------------------------------------------------------------------- /r5script/detours.h: -------------------------------------------------------------------------------- 1 | 2 | 3 | #pragma once 4 | #ifndef _DETOURS_H_ 5 | #define _DETOURS_H_ 6 | 7 | #define DETOURS_VERSION 0x4c0c1 8 | 9 | 10 | #undef DETOURS_X64 11 | #undef DETOURS_X86 12 | #undef DETOURS_IA64 13 | #undef DETOURS_ARM 14 | #undef DETOURS_ARM64 15 | #undef DETOURS_BITS 16 | #undef DETOURS_32BIT 17 | #undef DETOURS_64BIT 18 | 19 | #if defined(_X86_) 20 | #define DETOURS_X86 21 | #define DETOURS_OPTION_BITS 64 22 | 23 | #elif defined(_AMD64_) 24 | #define DETOURS_X64 25 | #define DETOURS_OPTION_BITS 32 26 | 27 | #elif defined(_IA64_) 28 | #define DETOURS_IA64 29 | #define DETOURS_OPTION_BITS 32 30 | 31 | #elif defined(_ARM_) 32 | #define DETOURS_ARM 33 | 34 | #elif defined(_ARM64_) 35 | #define DETOURS_ARM64 36 | 37 | #else 38 | #error Unknown architecture (x86, amd64, ia64, arm, arm64) 39 | #endif 40 | 41 | #ifdef _WIN64 42 | #undef DETOURS_32BIT 43 | #define DETOURS_64BIT 1 44 | #define DETOURS_BITS 64 45 | // If all 64bit kernels can run one and only one 32bit architecture. 46 | //#define DETOURS_OPTION_BITS 32 47 | #else 48 | #define DETOURS_32BIT 1 49 | #undef DETOURS_64BIT 50 | #define DETOURS_BITS 32 51 | // If all 64bit kernels can run one and only one 32bit architecture. 52 | //#define DETOURS_OPTION_BITS 32 53 | #endif 54 | 55 | #define VER_DETOURS_BITS DETOUR_STRINGIFY(DETOURS_BITS) 56 | 57 | ////////////////////////////////////////////////////////////////////////////// 58 | // 59 | 60 | #if (_MSC_VER < 1299) 61 | typedef LONG LONG_PTR; 62 | typedef ULONG ULONG_PTR; 63 | #endif 64 | 65 | ///////////////////////////////////////////////// SAL 2.0 Annotations w/o SAL. 66 | // 67 | // These definitions are include so that Detours will build even if the 68 | // compiler doesn't have full SAL 2.0 support. 69 | // 70 | #ifndef DETOURS_DONT_REMOVE_SAL_20 71 | 72 | #ifdef DETOURS_TEST_REMOVE_SAL_20 73 | #undef _Analysis_assume_ 74 | #undef _Benign_race_begin_ 75 | #undef _Benign_race_end_ 76 | #undef _Field_range_ 77 | #undef _Field_size_ 78 | #undef _In_ 79 | #undef _In_bytecount_ 80 | #undef _In_count_ 81 | #undef _In_opt_ 82 | #undef _In_opt_bytecount_ 83 | #undef _In_opt_count_ 84 | #undef _In_opt_z_ 85 | #undef _In_range_ 86 | #undef _In_reads_ 87 | #undef _In_reads_bytes_ 88 | #undef _In_reads_opt_ 89 | #undef _In_reads_opt_bytes_ 90 | #undef _In_reads_or_z_ 91 | #undef _In_z_ 92 | #undef _Inout_ 93 | #undef _Inout_opt_ 94 | #undef _Inout_z_count_ 95 | #undef _Out_ 96 | #undef _Out_opt_ 97 | #undef _Out_writes_ 98 | #undef _Outptr_result_maybenull_ 99 | #undef _Readable_bytes_ 100 | #undef _Success_ 101 | #undef _Writable_bytes_ 102 | #undef _Pre_notnull_ 103 | #endif 104 | 105 | #if defined(_Deref_out_opt_z_) && !defined(_Outptr_result_maybenull_) 106 | #define _Outptr_result_maybenull_ _Deref_out_opt_z_ 107 | #endif 108 | 109 | #if defined(_In_count_) && !defined(_In_reads_) 110 | #define _In_reads_(x) _In_count_(x) 111 | #endif 112 | 113 | #if defined(_In_opt_count_) && !defined(_In_reads_opt_) 114 | #define _In_reads_opt_(x) _In_opt_count_(x) 115 | #endif 116 | 117 | #if defined(_In_opt_bytecount_) && !defined(_In_reads_opt_bytes_) 118 | #define _In_reads_opt_bytes_(x) _In_opt_bytecount_(x) 119 | #endif 120 | 121 | #if defined(_In_bytecount_) && !defined(_In_reads_bytes_) 122 | #define _In_reads_bytes_(x) _In_bytecount_(x) 123 | #endif 124 | 125 | #ifndef _In_ 126 | #define _In_ 127 | #endif 128 | 129 | #ifndef _In_bytecount_ 130 | #define _In_bytecount_(x) 131 | #endif 132 | 133 | #ifndef _In_count_ 134 | #define _In_count_(x) 135 | #endif 136 | 137 | #ifndef _In_opt_ 138 | #define _In_opt_ 139 | #endif 140 | 141 | #ifndef _In_opt_bytecount_ 142 | #define _In_opt_bytecount_(x) 143 | #endif 144 | 145 | #ifndef _In_opt_count_ 146 | #define _In_opt_count_(x) 147 | #endif 148 | 149 | #ifndef _In_opt_z_ 150 | #define _In_opt_z_ 151 | #endif 152 | 153 | #ifndef _In_range_ 154 | #define _In_range_(x,y) 155 | #endif 156 | 157 | #ifndef _In_reads_ 158 | #define _In_reads_(x) 159 | #endif 160 | 161 | #ifndef _In_reads_bytes_ 162 | #define _In_reads_bytes_(x) 163 | #endif 164 | 165 | #ifndef _In_reads_opt_ 166 | #define _In_reads_opt_(x) 167 | #endif 168 | 169 | #ifndef _In_reads_opt_bytes_ 170 | #define _In_reads_opt_bytes_(x) 171 | #endif 172 | 173 | #ifndef _In_reads_or_z_ 174 | #define _In_reads_or_z_ 175 | #endif 176 | 177 | #ifndef _In_z_ 178 | #define _In_z_ 179 | #endif 180 | 181 | #ifndef _Inout_ 182 | #define _Inout_ 183 | #endif 184 | 185 | #ifndef _Inout_opt_ 186 | #define _Inout_opt_ 187 | #endif 188 | 189 | #ifndef _Inout_z_count_ 190 | #define _Inout_z_count_(x) 191 | #endif 192 | 193 | #ifndef _Out_ 194 | #define _Out_ 195 | #endif 196 | 197 | #ifndef _Out_opt_ 198 | #define _Out_opt_ 199 | #endif 200 | 201 | #ifndef _Out_writes_ 202 | #define _Out_writes_(x) 203 | #endif 204 | 205 | #ifndef _Outptr_result_maybenull_ 206 | #define _Outptr_result_maybenull_ 207 | #endif 208 | 209 | #ifndef _Writable_bytes_ 210 | #define _Writable_bytes_(x) 211 | #endif 212 | 213 | #ifndef _Readable_bytes_ 214 | #define _Readable_bytes_(x) 215 | #endif 216 | 217 | #ifndef _Success_ 218 | #define _Success_(x) 219 | #endif 220 | 221 | #ifndef _Pre_notnull_ 222 | #define _Pre_notnull_ 223 | #endif 224 | 225 | #ifdef DETOURS_INTERNAL 226 | 227 | #pragma warning(disable:4615) // unknown warning type (suppress with older compilers) 228 | 229 | #ifndef _Benign_race_begin_ 230 | #define _Benign_race_begin_ 231 | #endif 232 | 233 | #ifndef _Benign_race_end_ 234 | #define _Benign_race_end_ 235 | #endif 236 | 237 | #ifndef _Field_size_ 238 | #define _Field_size_(x) 239 | #endif 240 | 241 | #ifndef _Field_range_ 242 | #define _Field_range_(x,y) 243 | #endif 244 | 245 | #ifndef _Analysis_assume_ 246 | #define _Analysis_assume_(x) 247 | #endif 248 | 249 | #endif // DETOURS_INTERNAL 250 | #endif // DETOURS_DONT_REMOVE_SAL_20 251 | 252 | ////////////////////////////////////////////////////////////////////////////// 253 | // 254 | #ifndef GUID_DEFINED 255 | #define GUID_DEFINED 256 | typedef struct _GUID 257 | { 258 | DWORD Data1; 259 | WORD Data2; 260 | WORD Data3; 261 | BYTE Data4[8]; 262 | } GUID; 263 | 264 | #ifdef INITGUID 265 | #define DEFINE_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \ 266 | const GUID name \ 267 | = { l, w1, w2, { b1, b2, b3, b4, b5, b6, b7, b8 } } 268 | #else 269 | #define DEFINE_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \ 270 | const GUID name 271 | #endif // INITGUID 272 | #endif // !GUID_DEFINED 273 | 274 | #if defined(__cplusplus) 275 | #ifndef _REFGUID_DEFINED 276 | #define _REFGUID_DEFINED 277 | #define REFGUID const GUID & 278 | #endif // !_REFGUID_DEFINED 279 | #else // !__cplusplus 280 | #ifndef _REFGUID_DEFINED 281 | #define _REFGUID_DEFINED 282 | #define REFGUID const GUID * const 283 | #endif // !_REFGUID_DEFINED 284 | #endif // !__cplusplus 285 | 286 | #ifndef ARRAYSIZE 287 | #define ARRAYSIZE(x) (sizeof(x)/sizeof(x[0])) 288 | #endif 289 | 290 | // 291 | ////////////////////////////////////////////////////////////////////////////// 292 | 293 | #ifdef __cplusplus 294 | extern "C" { 295 | #endif // __cplusplus 296 | 297 | /////////////////////////////////////////////////// Instruction Target Macros. 298 | // 299 | #define DETOUR_INSTRUCTION_TARGET_NONE ((PVOID)0) 300 | #define DETOUR_INSTRUCTION_TARGET_DYNAMIC ((PVOID)(LONG_PTR)-1) 301 | #define DETOUR_SECTION_HEADER_SIGNATURE 0x00727444 // "Dtr\0" 302 | 303 | extern const GUID DETOUR_EXE_RESTORE_GUID; 304 | extern const GUID DETOUR_EXE_HELPER_GUID; 305 | 306 | #define DETOUR_TRAMPOLINE_SIGNATURE 0x21727444 // Dtr! 307 | typedef struct _DETOUR_TRAMPOLINE DETOUR_TRAMPOLINE, *PDETOUR_TRAMPOLINE; 308 | 309 | /////////////////////////////////////////////////////////// Binary Structures. 310 | // 311 | #pragma pack(push, 8) 312 | typedef struct _DETOUR_SECTION_HEADER 313 | { 314 | DWORD cbHeaderSize; 315 | DWORD nSignature; 316 | DWORD nDataOffset; 317 | DWORD cbDataSize; 318 | 319 | DWORD nOriginalImportVirtualAddress; 320 | DWORD nOriginalImportSize; 321 | DWORD nOriginalBoundImportVirtualAddress; 322 | DWORD nOriginalBoundImportSize; 323 | 324 | DWORD nOriginalIatVirtualAddress; 325 | DWORD nOriginalIatSize; 326 | DWORD nOriginalSizeOfImage; 327 | DWORD cbPrePE; 328 | 329 | DWORD nOriginalClrFlags; 330 | DWORD reserved1; 331 | DWORD reserved2; 332 | DWORD reserved3; 333 | 334 | // Followed by cbPrePE bytes of data. 335 | } DETOUR_SECTION_HEADER, *PDETOUR_SECTION_HEADER; 336 | 337 | typedef struct _DETOUR_SECTION_RECORD 338 | { 339 | DWORD cbBytes; 340 | DWORD nReserved; 341 | GUID guid; 342 | } DETOUR_SECTION_RECORD, *PDETOUR_SECTION_RECORD; 343 | 344 | typedef struct _DETOUR_CLR_HEADER 345 | { 346 | // Header versioning 347 | ULONG cb; 348 | USHORT MajorRuntimeVersion; 349 | USHORT MinorRuntimeVersion; 350 | 351 | // Symbol table and startup information 352 | IMAGE_DATA_DIRECTORY MetaData; 353 | ULONG Flags; 354 | 355 | // Followed by the rest of the IMAGE_COR20_HEADER 356 | } DETOUR_CLR_HEADER, *PDETOUR_CLR_HEADER; 357 | 358 | typedef struct _DETOUR_EXE_RESTORE 359 | { 360 | DWORD cb; 361 | DWORD cbidh; 362 | DWORD cbinh; 363 | DWORD cbclr; 364 | 365 | PBYTE pidh; 366 | PBYTE pinh; 367 | PBYTE pclr; 368 | 369 | IMAGE_DOS_HEADER idh; 370 | union { 371 | IMAGE_NT_HEADERS inh; 372 | IMAGE_NT_HEADERS32 inh32; 373 | IMAGE_NT_HEADERS64 inh64; 374 | BYTE raw[sizeof(IMAGE_NT_HEADERS64) + 375 | sizeof(IMAGE_SECTION_HEADER) * 32]; 376 | }; 377 | DETOUR_CLR_HEADER clr; 378 | 379 | } DETOUR_EXE_RESTORE, *PDETOUR_EXE_RESTORE; 380 | 381 | typedef struct _DETOUR_EXE_HELPER 382 | { 383 | DWORD cb; 384 | DWORD pid; 385 | DWORD nDlls; 386 | CHAR rDlls[4]; 387 | } DETOUR_EXE_HELPER, *PDETOUR_EXE_HELPER; 388 | 389 | #pragma pack(pop) 390 | 391 | #define DETOUR_SECTION_HEADER_DECLARE(cbSectionSize) \ 392 | { \ 393 | sizeof(DETOUR_SECTION_HEADER),\ 394 | DETOUR_SECTION_HEADER_SIGNATURE,\ 395 | sizeof(DETOUR_SECTION_HEADER),\ 396 | (cbSectionSize),\ 397 | \ 398 | 0,\ 399 | 0,\ 400 | 0,\ 401 | 0,\ 402 | \ 403 | 0,\ 404 | 0,\ 405 | 0,\ 406 | 0,\ 407 | } 408 | 409 | /////////////////////////////////////////////////////////////// Helper Macros. 410 | // 411 | #define DETOURS_STRINGIFY(x) DETOURS_STRINGIFY_(x) 412 | #define DETOURS_STRINGIFY_(x) #x 413 | 414 | ///////////////////////////////////////////////////////////// Binary Typedefs. 415 | // 416 | typedef BOOL(CALLBACK *PF_DETOUR_BINARY_BYWAY_CALLBACK)( 417 | _In_opt_ PVOID pContext, 418 | _In_opt_ LPCSTR pszFile, 419 | _Outptr_result_maybenull_ LPCSTR *ppszOutFile); 420 | 421 | typedef BOOL(CALLBACK *PF_DETOUR_BINARY_FILE_CALLBACK)( 422 | _In_opt_ PVOID pContext, 423 | _In_ LPCSTR pszOrigFile, 424 | _In_ LPCSTR pszFile, 425 | _Outptr_result_maybenull_ LPCSTR *ppszOutFile); 426 | 427 | typedef BOOL(CALLBACK *PF_DETOUR_BINARY_SYMBOL_CALLBACK)( 428 | _In_opt_ PVOID pContext, 429 | _In_ ULONG nOrigOrdinal, 430 | _In_ ULONG nOrdinal, 431 | _Out_ ULONG *pnOutOrdinal, 432 | _In_opt_ LPCSTR pszOrigSymbol, 433 | _In_opt_ LPCSTR pszSymbol, 434 | _Outptr_result_maybenull_ LPCSTR *ppszOutSymbol); 435 | 436 | typedef BOOL(CALLBACK *PF_DETOUR_BINARY_COMMIT_CALLBACK)( 437 | _In_opt_ PVOID pContext); 438 | 439 | typedef BOOL(CALLBACK *PF_DETOUR_ENUMERATE_EXPORT_CALLBACK)(_In_opt_ PVOID pContext, 440 | _In_ ULONG nOrdinal, 441 | _In_opt_ LPCSTR pszName, 442 | _In_opt_ PVOID pCode); 443 | 444 | typedef BOOL(CALLBACK *PF_DETOUR_IMPORT_FILE_CALLBACK)(_In_opt_ PVOID pContext, 445 | _In_opt_ HMODULE hModule, 446 | _In_opt_ LPCSTR pszFile); 447 | 448 | typedef BOOL(CALLBACK *PF_DETOUR_IMPORT_FUNC_CALLBACK)(_In_opt_ PVOID pContext, 449 | _In_ DWORD nOrdinal, 450 | _In_opt_ LPCSTR pszFunc, 451 | _In_opt_ PVOID pvFunc); 452 | 453 | // Same as PF_DETOUR_IMPORT_FUNC_CALLBACK but extra indirection on last parameter. 454 | typedef BOOL(CALLBACK *PF_DETOUR_IMPORT_FUNC_CALLBACK_EX)(_In_opt_ PVOID pContext, 455 | _In_ DWORD nOrdinal, 456 | _In_opt_ LPCSTR pszFunc, 457 | _In_opt_ PVOID* ppvFunc); 458 | 459 | typedef VOID * PDETOUR_BINARY; 460 | typedef VOID * PDETOUR_LOADED_BINARY; 461 | 462 | //////////////////////////////////////////////////////////// Transaction APIs. 463 | // 464 | LONG WINAPI DetourTransactionBegin(VOID); 465 | LONG WINAPI DetourTransactionAbort(VOID); 466 | LONG WINAPI DetourTransactionCommit(VOID); 467 | LONG WINAPI DetourTransactionCommitEx(_Out_opt_ PVOID **pppFailedPointer); 468 | 469 | LONG WINAPI DetourUpdateThread(_In_ HANDLE hThread); 470 | 471 | LONG WINAPI DetourAttach(_Inout_ PVOID *ppPointer, 472 | _In_ PVOID pDetour); 473 | 474 | LONG WINAPI DetourAttachEx(_Inout_ PVOID *ppPointer, 475 | _In_ PVOID pDetour, 476 | _Out_opt_ PDETOUR_TRAMPOLINE *ppRealTrampoline, 477 | _Out_opt_ PVOID *ppRealTarget, 478 | _Out_opt_ PVOID *ppRealDetour); 479 | 480 | LONG WINAPI DetourDetach(_Inout_ PVOID *ppPointer, 481 | _In_ PVOID pDetour); 482 | 483 | BOOL WINAPI DetourSetIgnoreTooSmall(_In_ BOOL fIgnore); 484 | BOOL WINAPI DetourSetRetainRegions(_In_ BOOL fRetain); 485 | PVOID WINAPI DetourSetSystemRegionLowerBound(_In_ PVOID pSystemRegionLowerBound); 486 | PVOID WINAPI DetourSetSystemRegionUpperBound(_In_ PVOID pSystemRegionUpperBound); 487 | 488 | ////////////////////////////////////////////////////////////// Code Functions. 489 | // 490 | PVOID WINAPI DetourFindFunction(_In_ LPCSTR pszModule, 491 | _In_ LPCSTR pszFunction); 492 | PVOID WINAPI DetourCodeFromPointer(_In_ PVOID pPointer, 493 | _Out_opt_ PVOID *ppGlobals); 494 | PVOID WINAPI DetourCopyInstruction(_In_opt_ PVOID pDst, 495 | _Inout_opt_ PVOID *ppDstPool, 496 | _In_ PVOID pSrc, 497 | _Out_opt_ PVOID *ppTarget, 498 | _Out_opt_ LONG *plExtra); 499 | BOOL WINAPI DetourSetCodeModule(_In_ HMODULE hModule, 500 | _In_ BOOL fLimitReferencesToModule); 501 | 502 | ///////////////////////////////////////////////////// Loaded Binary Functions. 503 | // 504 | HMODULE WINAPI DetourGetContainingModule(_In_ PVOID pvAddr); 505 | HMODULE WINAPI DetourEnumerateModules(_In_opt_ HMODULE hModuleLast); 506 | PVOID WINAPI DetourGetEntryPoint(_In_opt_ HMODULE hModule); 507 | ULONG WINAPI DetourGetModuleSize(_In_opt_ HMODULE hModule); 508 | BOOL WINAPI DetourEnumerateExports(_In_ HMODULE hModule, 509 | _In_opt_ PVOID pContext, 510 | _In_ PF_DETOUR_ENUMERATE_EXPORT_CALLBACK pfExport); 511 | BOOL WINAPI DetourEnumerateImports(_In_opt_ HMODULE hModule, 512 | _In_opt_ PVOID pContext, 513 | _In_opt_ PF_DETOUR_IMPORT_FILE_CALLBACK pfImportFile, 514 | _In_opt_ PF_DETOUR_IMPORT_FUNC_CALLBACK pfImportFunc); 515 | 516 | BOOL WINAPI DetourEnumerateImportsEx(_In_opt_ HMODULE hModule, 517 | _In_opt_ PVOID pContext, 518 | _In_opt_ PF_DETOUR_IMPORT_FILE_CALLBACK pfImportFile, 519 | _In_opt_ PF_DETOUR_IMPORT_FUNC_CALLBACK_EX pfImportFuncEx); 520 | 521 | _Writable_bytes_(*pcbData) 522 | _Readable_bytes_(*pcbData) 523 | _Success_(return != NULL) 524 | PVOID WINAPI DetourFindPayload(_In_opt_ HMODULE hModule, 525 | _In_ REFGUID rguid, 526 | _Out_ DWORD *pcbData); 527 | 528 | _Writable_bytes_(*pcbData) 529 | _Readable_bytes_(*pcbData) 530 | _Success_(return != NULL) 531 | PVOID WINAPI DetourFindPayloadEx(_In_ REFGUID rguid, 532 | _Out_ DWORD * pcbData); 533 | 534 | DWORD WINAPI DetourGetSizeOfPayloads(_In_opt_ HMODULE hModule); 535 | 536 | ///////////////////////////////////////////////// Persistent Binary Functions. 537 | // 538 | 539 | PDETOUR_BINARY WINAPI DetourBinaryOpen(_In_ HANDLE hFile); 540 | 541 | _Writable_bytes_(*pcbData) 542 | _Readable_bytes_(*pcbData) 543 | _Success_(return != NULL) 544 | PVOID WINAPI DetourBinaryEnumeratePayloads(_In_ PDETOUR_BINARY pBinary, 545 | _Out_opt_ GUID *pGuid, 546 | _Out_ DWORD *pcbData, 547 | _Inout_ DWORD *pnIterator); 548 | 549 | _Writable_bytes_(*pcbData) 550 | _Readable_bytes_(*pcbData) 551 | _Success_(return != NULL) 552 | PVOID WINAPI DetourBinaryFindPayload(_In_ PDETOUR_BINARY pBinary, 553 | _In_ REFGUID rguid, 554 | _Out_ DWORD *pcbData); 555 | 556 | PVOID WINAPI DetourBinarySetPayload(_In_ PDETOUR_BINARY pBinary, 557 | _In_ REFGUID rguid, 558 | _In_reads_opt_(cbData) PVOID pData, 559 | _In_ DWORD cbData); 560 | BOOL WINAPI DetourBinaryDeletePayload(_In_ PDETOUR_BINARY pBinary, _In_ REFGUID rguid); 561 | BOOL WINAPI DetourBinaryPurgePayloads(_In_ PDETOUR_BINARY pBinary); 562 | BOOL WINAPI DetourBinaryResetImports(_In_ PDETOUR_BINARY pBinary); 563 | BOOL WINAPI DetourBinaryEditImports(_In_ PDETOUR_BINARY pBinary, 564 | _In_opt_ PVOID pContext, 565 | _In_opt_ PF_DETOUR_BINARY_BYWAY_CALLBACK pfByway, 566 | _In_opt_ PF_DETOUR_BINARY_FILE_CALLBACK pfFile, 567 | _In_opt_ PF_DETOUR_BINARY_SYMBOL_CALLBACK pfSymbol, 568 | _In_opt_ PF_DETOUR_BINARY_COMMIT_CALLBACK pfCommit); 569 | BOOL WINAPI DetourBinaryWrite(_In_ PDETOUR_BINARY pBinary, _In_ HANDLE hFile); 570 | BOOL WINAPI DetourBinaryClose(_In_ PDETOUR_BINARY pBinary); 571 | 572 | /////////////////////////////////////////////////// Create Process & Load Dll. 573 | // 574 | typedef BOOL(WINAPI *PDETOUR_CREATE_PROCESS_ROUTINEA)( 575 | _In_opt_ LPCSTR lpApplicationName, 576 | _Inout_opt_ LPSTR lpCommandLine, 577 | _In_opt_ LPSECURITY_ATTRIBUTES lpProcessAttributes, 578 | _In_opt_ LPSECURITY_ATTRIBUTES lpThreadAttributes, 579 | _In_ BOOL bInheritHandles, 580 | _In_ DWORD dwCreationFlags, 581 | _In_opt_ LPVOID lpEnvironment, 582 | _In_opt_ LPCSTR lpCurrentDirectory, 583 | _In_ LPSTARTUPINFOA lpStartupInfo, 584 | _Out_ LPPROCESS_INFORMATION lpProcessInformation); 585 | 586 | typedef BOOL(WINAPI *PDETOUR_CREATE_PROCESS_ROUTINEW)( 587 | _In_opt_ LPCWSTR lpApplicationName, 588 | _Inout_opt_ LPWSTR lpCommandLine, 589 | _In_opt_ LPSECURITY_ATTRIBUTES lpProcessAttributes, 590 | _In_opt_ LPSECURITY_ATTRIBUTES lpThreadAttributes, 591 | _In_ BOOL bInheritHandles, 592 | _In_ DWORD dwCreationFlags, 593 | _In_opt_ LPVOID lpEnvironment, 594 | _In_opt_ LPCWSTR lpCurrentDirectory, 595 | _In_ LPSTARTUPINFOW lpStartupInfo, 596 | _Out_ LPPROCESS_INFORMATION lpProcessInformation); 597 | 598 | BOOL WINAPI DetourCreateProcessWithDllA(_In_opt_ LPCSTR lpApplicationName, 599 | _Inout_opt_ LPSTR lpCommandLine, 600 | _In_opt_ LPSECURITY_ATTRIBUTES lpProcessAttributes, 601 | _In_opt_ LPSECURITY_ATTRIBUTES lpThreadAttributes, 602 | _In_ BOOL bInheritHandles, 603 | _In_ DWORD dwCreationFlags, 604 | _In_opt_ LPVOID lpEnvironment, 605 | _In_opt_ LPCSTR lpCurrentDirectory, 606 | _In_ LPSTARTUPINFOA lpStartupInfo, 607 | _Out_ LPPROCESS_INFORMATION lpProcessInformation, 608 | _In_ LPCSTR lpDllName, 609 | _In_opt_ PDETOUR_CREATE_PROCESS_ROUTINEA pfCreateProcessA); 610 | 611 | BOOL WINAPI DetourCreateProcessWithDllW(_In_opt_ LPCWSTR lpApplicationName, 612 | _Inout_opt_ LPWSTR lpCommandLine, 613 | _In_opt_ LPSECURITY_ATTRIBUTES lpProcessAttributes, 614 | _In_opt_ LPSECURITY_ATTRIBUTES lpThreadAttributes, 615 | _In_ BOOL bInheritHandles, 616 | _In_ DWORD dwCreationFlags, 617 | _In_opt_ LPVOID lpEnvironment, 618 | _In_opt_ LPCWSTR lpCurrentDirectory, 619 | _In_ LPSTARTUPINFOW lpStartupInfo, 620 | _Out_ LPPROCESS_INFORMATION lpProcessInformation, 621 | _In_ LPCSTR lpDllName, 622 | _In_opt_ PDETOUR_CREATE_PROCESS_ROUTINEW pfCreateProcessW); 623 | 624 | #ifdef UNICODE 625 | #define DetourCreateProcessWithDll DetourCreateProcessWithDllW 626 | #define PDETOUR_CREATE_PROCESS_ROUTINE PDETOUR_CREATE_PROCESS_ROUTINEW 627 | #else 628 | #define DetourCreateProcessWithDll DetourCreateProcessWithDllA 629 | #define PDETOUR_CREATE_PROCESS_ROUTINE PDETOUR_CREATE_PROCESS_ROUTINEA 630 | #endif // !UNICODE 631 | 632 | BOOL WINAPI DetourCreateProcessWithDllExA(_In_opt_ LPCSTR lpApplicationName, 633 | _Inout_opt_ LPSTR lpCommandLine, 634 | _In_opt_ LPSECURITY_ATTRIBUTES lpProcessAttributes, 635 | _In_opt_ LPSECURITY_ATTRIBUTES lpThreadAttributes, 636 | _In_ BOOL bInheritHandles, 637 | _In_ DWORD dwCreationFlags, 638 | _In_opt_ LPVOID lpEnvironment, 639 | _In_opt_ LPCSTR lpCurrentDirectory, 640 | _In_ LPSTARTUPINFOA lpStartupInfo, 641 | _Out_ LPPROCESS_INFORMATION lpProcessInformation, 642 | _In_ LPCSTR lpDllName, 643 | _In_opt_ PDETOUR_CREATE_PROCESS_ROUTINEA pfCreateProcessA); 644 | 645 | BOOL WINAPI DetourCreateProcessWithDllExW(_In_opt_ LPCWSTR lpApplicationName, 646 | _Inout_opt_ LPWSTR lpCommandLine, 647 | _In_opt_ LPSECURITY_ATTRIBUTES lpProcessAttributes, 648 | _In_opt_ LPSECURITY_ATTRIBUTES lpThreadAttributes, 649 | _In_ BOOL bInheritHandles, 650 | _In_ DWORD dwCreationFlags, 651 | _In_opt_ LPVOID lpEnvironment, 652 | _In_opt_ LPCWSTR lpCurrentDirectory, 653 | _In_ LPSTARTUPINFOW lpStartupInfo, 654 | _Out_ LPPROCESS_INFORMATION lpProcessInformation, 655 | _In_ LPCSTR lpDllName, 656 | _In_opt_ PDETOUR_CREATE_PROCESS_ROUTINEW pfCreateProcessW); 657 | 658 | #ifdef UNICODE 659 | #define DetourCreateProcessWithDllEx DetourCreateProcessWithDllExW 660 | #else 661 | #define DetourCreateProcessWithDllEx DetourCreateProcessWithDllExA 662 | #endif // !UNICODE 663 | 664 | BOOL WINAPI DetourCreateProcessWithDllsA(_In_opt_ LPCSTR lpApplicationName, 665 | _Inout_opt_ LPSTR lpCommandLine, 666 | _In_opt_ LPSECURITY_ATTRIBUTES lpProcessAttributes, 667 | _In_opt_ LPSECURITY_ATTRIBUTES lpThreadAttributes, 668 | _In_ BOOL bInheritHandles, 669 | _In_ DWORD dwCreationFlags, 670 | _In_opt_ LPVOID lpEnvironment, 671 | _In_opt_ LPCSTR lpCurrentDirectory, 672 | _In_ LPSTARTUPINFOA lpStartupInfo, 673 | _Out_ LPPROCESS_INFORMATION lpProcessInformation, 674 | _In_ DWORD nDlls, 675 | _In_reads_(nDlls) LPCSTR *rlpDlls, 676 | _In_opt_ PDETOUR_CREATE_PROCESS_ROUTINEA pfCreateProcessA); 677 | 678 | BOOL WINAPI DetourCreateProcessWithDllsW(_In_opt_ LPCWSTR lpApplicationName, 679 | _Inout_opt_ LPWSTR lpCommandLine, 680 | _In_opt_ LPSECURITY_ATTRIBUTES lpProcessAttributes, 681 | _In_opt_ LPSECURITY_ATTRIBUTES lpThreadAttributes, 682 | _In_ BOOL bInheritHandles, 683 | _In_ DWORD dwCreationFlags, 684 | _In_opt_ LPVOID lpEnvironment, 685 | _In_opt_ LPCWSTR lpCurrentDirectory, 686 | _In_ LPSTARTUPINFOW lpStartupInfo, 687 | _Out_ LPPROCESS_INFORMATION lpProcessInformation, 688 | _In_ DWORD nDlls, 689 | _In_reads_(nDlls) LPCSTR *rlpDlls, 690 | _In_opt_ PDETOUR_CREATE_PROCESS_ROUTINEW pfCreateProcessW); 691 | 692 | #ifdef UNICODE 693 | #define DetourCreateProcessWithDlls DetourCreateProcessWithDllsW 694 | #else 695 | #define DetourCreateProcessWithDlls DetourCreateProcessWithDllsA 696 | #endif // !UNICODE 697 | 698 | BOOL WINAPI DetourProcessViaHelperA(_In_ DWORD dwTargetPid, 699 | _In_ LPCSTR lpDllName, 700 | _In_ PDETOUR_CREATE_PROCESS_ROUTINEA pfCreateProcessA); 701 | 702 | BOOL WINAPI DetourProcessViaHelperW(_In_ DWORD dwTargetPid, 703 | _In_ LPCSTR lpDllName, 704 | _In_ PDETOUR_CREATE_PROCESS_ROUTINEW pfCreateProcessW); 705 | 706 | #ifdef UNICODE 707 | #define DetourProcessViaHelper DetourProcessViaHelperW 708 | #else 709 | #define DetourProcessViaHelper DetourProcessViaHelperA 710 | #endif // !UNICODE 711 | 712 | BOOL WINAPI DetourProcessViaHelperDllsA(_In_ DWORD dwTargetPid, 713 | _In_ DWORD nDlls, 714 | _In_reads_(nDlls) LPCSTR *rlpDlls, 715 | _In_ PDETOUR_CREATE_PROCESS_ROUTINEA pfCreateProcessA); 716 | 717 | BOOL WINAPI DetourProcessViaHelperDllsW(_In_ DWORD dwTargetPid, 718 | _In_ DWORD nDlls, 719 | _In_reads_(nDlls) LPCSTR *rlpDlls, 720 | _In_ PDETOUR_CREATE_PROCESS_ROUTINEW pfCreateProcessW); 721 | 722 | #ifdef UNICODE 723 | #define DetourProcessViaHelperDlls DetourProcessViaHelperDllsW 724 | #else 725 | #define DetourProcessViaHelperDlls DetourProcessViaHelperDllsA 726 | #endif // !UNICODE 727 | 728 | BOOL WINAPI DetourUpdateProcessWithDll(_In_ HANDLE hProcess, 729 | _In_reads_(nDlls) LPCSTR *rlpDlls, 730 | _In_ DWORD nDlls); 731 | 732 | BOOL WINAPI DetourUpdateProcessWithDllEx(_In_ HANDLE hProcess, 733 | _In_ HMODULE hImage, 734 | _In_ BOOL bIs32Bit, 735 | _In_reads_(nDlls) LPCSTR *rlpDlls, 736 | _In_ DWORD nDlls); 737 | 738 | BOOL WINAPI DetourCopyPayloadToProcess(_In_ HANDLE hProcess, 739 | _In_ REFGUID rguid, 740 | _In_reads_bytes_(cbData) PVOID pvData, 741 | _In_ DWORD cbData); 742 | BOOL WINAPI DetourRestoreAfterWith(VOID); 743 | BOOL WINAPI DetourRestoreAfterWithEx(_In_reads_bytes_(cbData) PVOID pvData, 744 | _In_ DWORD cbData); 745 | BOOL WINAPI DetourIsHelperProcess(VOID); 746 | VOID CALLBACK DetourFinishHelperProcess(_In_ HWND, 747 | _In_ HINSTANCE, 748 | _In_ LPSTR, 749 | _In_ INT); 750 | 751 | // 752 | ////////////////////////////////////////////////////////////////////////////// 753 | #ifdef __cplusplus 754 | } 755 | #endif // __cplusplus 756 | 757 | //////////////////////////////////////////////// Detours Internal Definitions. 758 | // 759 | #ifdef __cplusplus 760 | #ifdef DETOURS_INTERNAL 761 | 762 | #define NOTHROW 763 | // #define NOTHROW (nothrow) 764 | 765 | ////////////////////////////////////////////////////////////////////////////// 766 | // 767 | #if (_MSC_VER < 1299) 768 | #include 769 | typedef IMAGEHLP_MODULE IMAGEHLP_MODULE64; 770 | typedef PIMAGEHLP_MODULE PIMAGEHLP_MODULE64; 771 | typedef IMAGEHLP_SYMBOL SYMBOL_INFO; 772 | typedef PIMAGEHLP_SYMBOL PSYMBOL_INFO; 773 | 774 | static inline 775 | LONG InterlockedCompareExchange(_Inout_ LONG *ptr, _In_ LONG nval, _In_ LONG oval) 776 | { 777 | return (LONG)::InterlockedCompareExchange((PVOID*)ptr, (PVOID)nval, (PVOID)oval); 778 | } 779 | #else 780 | #pragma warning(push) 781 | #pragma warning(disable:4091) // empty typedef 782 | #include 783 | #pragma warning(pop) 784 | #endif 785 | 786 | #ifdef IMAGEAPI // defined by DBGHELP.H 787 | typedef LPAPI_VERSION(NTAPI *PF_ImagehlpApiVersionEx)(_In_ LPAPI_VERSION AppVersion); 788 | 789 | typedef BOOL(NTAPI *PF_SymInitialize)(_In_ HANDLE hProcess, 790 | _In_opt_ LPCSTR UserSearchPath, 791 | _In_ BOOL fInvadeProcess); 792 | typedef DWORD(NTAPI *PF_SymSetOptions)(_In_ DWORD SymOptions); 793 | typedef DWORD(NTAPI *PF_SymGetOptions)(VOID); 794 | typedef DWORD64(NTAPI *PF_SymLoadModule64)(_In_ HANDLE hProcess, 795 | _In_opt_ HANDLE hFile, 796 | _In_ LPSTR ImageName, 797 | _In_opt_ LPSTR ModuleName, 798 | _In_ DWORD64 BaseOfDll, 799 | _In_opt_ DWORD SizeOfDll); 800 | typedef BOOL(NTAPI *PF_SymGetModuleInfo64)(_In_ HANDLE hProcess, 801 | _In_ DWORD64 qwAddr, 802 | _Out_ PIMAGEHLP_MODULE64 ModuleInfo); 803 | typedef BOOL(NTAPI *PF_SymFromName)(_In_ HANDLE hProcess, 804 | _In_ LPSTR Name, 805 | _Out_ PSYMBOL_INFO Symbol); 806 | 807 | typedef struct _DETOUR_SYM_INFO 808 | { 809 | HANDLE hProcess; 810 | HMODULE hDbgHelp; 811 | PF_ImagehlpApiVersionEx pfImagehlpApiVersionEx; 812 | PF_SymInitialize pfSymInitialize; 813 | PF_SymSetOptions pfSymSetOptions; 814 | PF_SymGetOptions pfSymGetOptions; 815 | PF_SymLoadModule64 pfSymLoadModule64; 816 | PF_SymGetModuleInfo64 pfSymGetModuleInfo64; 817 | PF_SymFromName pfSymFromName; 818 | } DETOUR_SYM_INFO, *PDETOUR_SYM_INFO; 819 | 820 | PDETOUR_SYM_INFO DetourLoadImageHlp(VOID); 821 | 822 | #endif // IMAGEAPI 823 | 824 | #if defined(_INC_STDIO) && !defined(_CRT_STDIO_ARBITRARY_WIDE_SPECIFIERS) 825 | #error detours.h must be included before stdio.h (or at least define _CRT_STDIO_ARBITRARY_WIDE_SPECIFIERS earlier) 826 | #endif 827 | #define _CRT_STDIO_ARBITRARY_WIDE_SPECIFIERS 1 828 | 829 | #ifndef DETOUR_TRACE 830 | #if DETOUR_DEBUG 831 | #define DETOUR_TRACE(x) printf x 832 | #define DETOUR_BREAK() __debugbreak() 833 | #include 834 | #include 835 | #else 836 | #define DETOUR_TRACE(x) 837 | #define DETOUR_BREAK() 838 | #endif 839 | #endif 840 | 841 | #if 1 || defined(DETOURS_IA64) 842 | 843 | // 844 | // IA64 instructions are 41 bits, 3 per bundle, plus 5 bit bundle template => 128 bits per bundle. 845 | // 846 | 847 | #define DETOUR_IA64_INSTRUCTIONS_PER_BUNDLE (3) 848 | 849 | #define DETOUR_IA64_TEMPLATE_OFFSET (0) 850 | #define DETOUR_IA64_TEMPLATE_SIZE (5) 851 | 852 | #define DETOUR_IA64_INSTRUCTION_SIZE (41) 853 | #define DETOUR_IA64_INSTRUCTION0_OFFSET (DETOUR_IA64_TEMPLATE_SIZE) 854 | #define DETOUR_IA64_INSTRUCTION1_OFFSET (DETOUR_IA64_TEMPLATE_SIZE + DETOUR_IA64_INSTRUCTION_SIZE) 855 | #define DETOUR_IA64_INSTRUCTION2_OFFSET (DETOUR_IA64_TEMPLATE_SIZE + DETOUR_IA64_INSTRUCTION_SIZE + DETOUR_IA64_INSTRUCTION_SIZE) 856 | 857 | C_ASSERT(DETOUR_IA64_TEMPLATE_SIZE + DETOUR_IA64_INSTRUCTIONS_PER_BUNDLE * DETOUR_IA64_INSTRUCTION_SIZE == 128); 858 | 859 | __declspec(align(16)) struct DETOUR_IA64_BUNDLE 860 | { 861 | public: 862 | union 863 | { 864 | BYTE data[16]; 865 | UINT64 wide[2]; 866 | }; 867 | 868 | enum { 869 | A_UNIT = 1u, 870 | I_UNIT = 2u, 871 | M_UNIT = 3u, 872 | B_UNIT = 4u, 873 | F_UNIT = 5u, 874 | L_UNIT = 6u, 875 | X_UNIT = 7u, 876 | }; 877 | struct DETOUR_IA64_METADATA 878 | { 879 | ULONG nTemplate : 8; // Instruction template. 880 | ULONG nUnit0 : 4; // Unit for slot 0 881 | ULONG nUnit1 : 4; // Unit for slot 1 882 | ULONG nUnit2 : 4; // Unit for slot 2 883 | }; 884 | 885 | protected: 886 | static const DETOUR_IA64_METADATA s_rceCopyTable[33]; 887 | 888 | UINT RelocateBundle(_Inout_ DETOUR_IA64_BUNDLE* pDst, _Inout_opt_ DETOUR_IA64_BUNDLE* pBundleExtra) const; 889 | 890 | bool RelocateInstruction(_Inout_ DETOUR_IA64_BUNDLE* pDst, 891 | _In_ BYTE slot, 892 | _Inout_opt_ DETOUR_IA64_BUNDLE* pBundleExtra) const; 893 | 894 | // 120 112 104 96 88 80 72 64 56 48 40 32 24 16 8 0 895 | // f. e. d. c. b. a. 9. 8. 7. 6. 5. 4. 3. 2. 1. 0. 896 | 897 | // 00 898 | // f.e. d.c. b.a. 9.8. 7.6. 5.4. 3.2. 1.0. 899 | // 0000 0000 0000 0000 0000 0000 0000 001f : Template [4..0] 900 | // 0000 0000 0000 0000 0000 03ff ffff ffe0 : Zero [ 41.. 5] 901 | // 0000 0000 0000 0000 0000 3c00 0000 0000 : Zero [ 45.. 42] 902 | // 0000 0000 0007 ffff ffff c000 0000 0000 : One [ 82.. 46] 903 | // 0000 0000 0078 0000 0000 0000 0000 0000 : One [ 86.. 83] 904 | // 0fff ffff ff80 0000 0000 0000 0000 0000 : Two [123.. 87] 905 | // f000 0000 0000 0000 0000 0000 0000 0000 : Two [127..124] 906 | BYTE GetTemplate() const; 907 | // Get 4 bit opcodes. 908 | BYTE GetInst0() const; 909 | BYTE GetInst1() const; 910 | BYTE GetInst2() const; 911 | BYTE GetUnit(BYTE slot) const; 912 | BYTE GetUnit0() const; 913 | BYTE GetUnit1() const; 914 | BYTE GetUnit2() const; 915 | // Get 37 bit data. 916 | UINT64 GetData0() const; 917 | UINT64 GetData1() const; 918 | UINT64 GetData2() const; 919 | 920 | // Get/set the full 41 bit instructions. 921 | UINT64 GetInstruction(BYTE slot) const; 922 | UINT64 GetInstruction0() const; 923 | UINT64 GetInstruction1() const; 924 | UINT64 GetInstruction2() const; 925 | void SetInstruction(BYTE slot, UINT64 instruction); 926 | void SetInstruction0(UINT64 instruction); 927 | void SetInstruction1(UINT64 instruction); 928 | void SetInstruction2(UINT64 instruction); 929 | 930 | // Get/set bitfields. 931 | static UINT64 GetBits(UINT64 Value, UINT64 Offset, UINT64 Count); 932 | static UINT64 SetBits(UINT64 Value, UINT64 Offset, UINT64 Count, UINT64 Field); 933 | 934 | // Get specific read-only fields. 935 | static UINT64 GetOpcode(UINT64 instruction); // 4bit opcode 936 | static UINT64 GetX(UINT64 instruction); // 1bit opcode extension 937 | static UINT64 GetX3(UINT64 instruction); // 3bit opcode extension 938 | static UINT64 GetX6(UINT64 instruction); // 6bit opcode extension 939 | 940 | // Get/set specific fields. 941 | static UINT64 GetImm7a(UINT64 instruction); 942 | static UINT64 SetImm7a(UINT64 instruction, UINT64 imm7a); 943 | static UINT64 GetImm13c(UINT64 instruction); 944 | static UINT64 SetImm13c(UINT64 instruction, UINT64 imm13c); 945 | static UINT64 GetSignBit(UINT64 instruction); 946 | static UINT64 SetSignBit(UINT64 instruction, UINT64 signBit); 947 | static UINT64 GetImm20a(UINT64 instruction); 948 | static UINT64 SetImm20a(UINT64 instruction, UINT64 imm20a); 949 | static UINT64 GetImm20b(UINT64 instruction); 950 | static UINT64 SetImm20b(UINT64 instruction, UINT64 imm20b); 951 | 952 | static UINT64 SignExtend(UINT64 Value, UINT64 Offset); 953 | 954 | BOOL IsMovlGp() const; 955 | 956 | VOID SetInst(BYTE Slot, BYTE nInst); 957 | VOID SetInst0(BYTE nInst); 958 | VOID SetInst1(BYTE nInst); 959 | VOID SetInst2(BYTE nInst); 960 | VOID SetData(BYTE Slot, UINT64 nData); 961 | VOID SetData0(UINT64 nData); 962 | VOID SetData1(UINT64 nData); 963 | VOID SetData2(UINT64 nData); 964 | BOOL SetNop(BYTE Slot); 965 | BOOL SetNop0(); 966 | BOOL SetNop1(); 967 | BOOL SetNop2(); 968 | 969 | public: 970 | BOOL IsBrl() const; 971 | VOID SetBrl(); 972 | VOID SetBrl(UINT64 target); 973 | UINT64 GetBrlTarget() const; 974 | VOID SetBrlTarget(UINT64 target); 975 | VOID SetBrlImm(UINT64 imm); 976 | UINT64 GetBrlImm() const; 977 | 978 | UINT64 GetMovlGp() const; 979 | VOID SetMovlGp(UINT64 gp); 980 | 981 | VOID SetStop(); 982 | 983 | UINT Copy(_Out_ DETOUR_IA64_BUNDLE *pDst, _Inout_opt_ DETOUR_IA64_BUNDLE* pBundleExtra = NULL) const; 984 | }; 985 | #endif // DETOURS_IA64 986 | 987 | #ifdef DETOURS_ARM 988 | 989 | #define DETOURS_PFUNC_TO_PBYTE(p) ((PBYTE)(((ULONG_PTR)(p)) & ~(ULONG_PTR)1)) 990 | #define DETOURS_PBYTE_TO_PFUNC(p) ((PBYTE)(((ULONG_PTR)(p)) | (ULONG_PTR)1)) 991 | 992 | #endif // DETOURS_ARM 993 | 994 | ////////////////////////////////////////////////////////////////////////////// 995 | 996 | #ifdef __cplusplus 997 | extern "C" { 998 | #endif // __cplusplus 999 | 1000 | #define DETOUR_OFFLINE_LIBRARY(x) \ 1001 | PVOID WINAPI DetourCopyInstruction##x(_In_opt_ PVOID pDst, \ 1002 | _Inout_opt_ PVOID *ppDstPool, \ 1003 | _In_ PVOID pSrc, \ 1004 | _Out_opt_ PVOID *ppTarget, \ 1005 | _Out_opt_ LONG *plExtra); \ 1006 | \ 1007 | BOOL WINAPI DetourSetCodeModule##x(_In_ HMODULE hModule, \ 1008 | _In_ BOOL fLimitReferencesToModule); \ 1009 | 1010 | DETOUR_OFFLINE_LIBRARY(X86) 1011 | DETOUR_OFFLINE_LIBRARY(X64) 1012 | DETOUR_OFFLINE_LIBRARY(ARM) 1013 | DETOUR_OFFLINE_LIBRARY(ARM64) 1014 | DETOUR_OFFLINE_LIBRARY(IA64) 1015 | 1016 | #undef DETOUR_OFFLINE_LIBRARY 1017 | 1018 | ////////////////////////////////////////////////////////////////////////////// 1019 | // 1020 | // Helpers for manipulating page protection. 1021 | // 1022 | 1023 | _Success_(return != FALSE) 1024 | BOOL WINAPI DetourVirtualProtectSameExecuteEx(_In_ HANDLE hProcess, 1025 | _In_ PVOID pAddress, 1026 | _In_ SIZE_T nSize, 1027 | _In_ DWORD dwNewProtect, 1028 | _Out_ PDWORD pdwOldProtect); 1029 | 1030 | _Success_(return != FALSE) 1031 | BOOL WINAPI DetourVirtualProtectSameExecute(_In_ PVOID pAddress, 1032 | _In_ SIZE_T nSize, 1033 | _In_ DWORD dwNewProtect, 1034 | _Out_ PDWORD pdwOldProtect); 1035 | #ifdef __cplusplus 1036 | } 1037 | #endif // __cplusplus 1038 | 1039 | ////////////////////////////////////////////////////////////////////////////// 1040 | 1041 | #define MM_ALLOCATION_GRANULARITY 0x10000 1042 | 1043 | ////////////////////////////////////////////////////////////////////////////// 1044 | 1045 | #endif // DETOURS_INTERNAL 1046 | #endif // __cplusplus 1047 | 1048 | #endif // _DETOURS_H_ 1049 | // 1050 | //////////////////////////////////////////////////////////////// End of File. 1051 | -------------------------------------------------------------------------------- /r5script/dllmain.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include "skcrypter.h" 10 | #include "lazy_importer.hh" 11 | #include "detours.h" 12 | 13 | typedef wchar_t SQChar; 14 | typedef __int64 SQInteger; 15 | typedef unsigned __int64 SQUnsignedInteger; 16 | typedef SQUnsignedInteger SQBool; 17 | 18 | typedef SQInteger(__fastcall* load_rson_fn)(const SQChar*); 19 | typedef SQBool(__fastcall* load_script_fn)(void*, const SQChar*, const SQChar*, SQInteger); 20 | 21 | SQInteger __fastcall load_rson(const SQChar*); 22 | load_rson_fn original_load_rson = nullptr; 23 | 24 | SQBool __fastcall load_script(void*, const SQChar*, const SQChar*, SQInteger); 25 | load_script_fn original_load_script = nullptr; 26 | 27 | SQInteger __fastcall load_rson(const SQChar* rsonfile) 28 | { 29 | std::string file = std::string(skCrypt("custom/")) + std::string(reinterpret_cast(rsonfile)); 30 | std::ifstream file_stream(file); 31 | 32 | if (file_stream.good()) { 33 | 34 | const std::string content((std::istreambuf_iterator(file_stream)), (std::istreambuf_iterator())); 35 | printf(skCrypt("loading : %s\n"), file.c_str()); 36 | 37 | return original_load_rson(reinterpret_cast(file.c_str())); 38 | } 39 | else 40 | { 41 | return original_load_rson(rsonfile); 42 | } 43 | } 44 | 45 | SQBool load_script(void* sqvm, const SQChar* szScriptPath, const SQChar* szScriptName, SQInteger nFlag) 46 | { 47 | std::string file = std::string(skCrypt("custom/")) + std::string(reinterpret_cast(szScriptPath)); 48 | std::ifstream file_stream(file); 49 | 50 | if ( file_stream.good()) { 51 | 52 | const std::string content( ( std::istreambuf_iterator( file_stream ) ), ( std::istreambuf_iterator( ) ) ); 53 | printf(skCrypt("loading : %s\n"), file.c_str()); 54 | 55 | return original_load_script(sqvm, reinterpret_cast(file.c_str()), szScriptName, nFlag); 56 | } 57 | else 58 | { 59 | return original_load_script(sqvm, szScriptPath, szScriptName, nFlag); 60 | } 61 | } 62 | 63 | uint8_t* find_pattern(const char* signature, const char* module_name) { 64 | static auto pattern_to_byte = [](const char* pattern) { 65 | auto bytes = std::vector{ }; 66 | auto* const start = const_cast(pattern); 67 | const auto* const end = const_cast(pattern) + strlen(pattern); 68 | 69 | for (auto* current = start; current < end; ++current) { 70 | if (*current == '?') { 71 | ++current; 72 | if (*current == '?') 73 | ++current; 74 | bytes.push_back(-1); 75 | } 76 | else { 77 | bytes.push_back(strtoul(current, ¤t, 16)); 78 | } 79 | } 80 | return bytes; 81 | }; 82 | 83 | auto* const module = LI_FN(GetModuleHandleA).cached()(module_name); 84 | auto* const dos_headers = reinterpret_cast(module); 85 | if (!dos_headers) 86 | return nullptr; 87 | 88 | auto* const nt_headers = reinterpret_cast(reinterpret_cast(module) + dos_headers->e_lfanew); 89 | 90 | auto pattern_bytes = pattern_to_byte(signature); 91 | auto* const scan_bytes = reinterpret_cast(module); 92 | 93 | const auto s = pattern_bytes.size(); 94 | auto* const d = pattern_bytes.data(); 95 | 96 | for (auto i = 0ul; i < nt_headers->OptionalHeader.SizeOfImage - s; ++i) { 97 | auto found = true; 98 | for (auto j = 0ul; j < s; ++j) { 99 | if (scan_bytes[i + j] != d[j] && d[j] != -1) { 100 | found = false; 101 | break; 102 | } 103 | } 104 | if (found) { 105 | return &scan_bytes[i]; 106 | } 107 | } 108 | return nullptr; 109 | } 110 | 111 | bool __stdcall DllMain(const HMODULE module, const DWORD reason, LPVOID) 112 | { 113 | if (reason != reason) 114 | return false; 115 | 116 | AllocConsole(); 117 | FILE* fp; 118 | freopen_s(&fp, skCrypt("CONOUT$"), skCrypt("w"), stdout); 119 | freopen_s(&fp, skCrypt("CONOUT$"), skCrypt("w"), stderr); 120 | 121 | DetourTransactionBegin(); 122 | 123 | original_load_rson = reinterpret_cast(find_pattern(skCrypt("4C 8B DC 49 89 5B 08 49 89 73 10 57 48 81 EC A0"), nullptr)); 124 | original_load_script = reinterpret_cast(find_pattern(skCrypt("48 8B C4 4C 89 40 18 48 89 50 10 48 89 48 08 55 53 41"), nullptr)); 125 | 126 | DetourAttach((LPVOID*)&original_load_rson, &load_rson); 127 | DetourAttach((LPVOID*)&original_load_script, &load_script); 128 | 129 | DetourTransactionCommit(); 130 | 131 | return true; 132 | } 133 | -------------------------------------------------------------------------------- /r5script/lazy_importer.hh: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018-2022 Justas Masiulis 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | // === FAQ === documentation is available at https://github.com/JustasMasiulis/lazy_importer 18 | // * Code doesn't compile with errors about pointer conversion: 19 | // - Try using `nullptr` instead of `NULL` or call `get()` instead of using the overloaded operator() 20 | // * Lazy importer can't find the function I want: 21 | // - Double check that the module in which it's located in is actually loaded 22 | // - Try #define LAZY_IMPORTER_CASE_INSENSITIVE 23 | // This will start using case insensitive comparison globally 24 | // - Try #define LAZY_IMPORTER_RESOLVE_FORWARDED_EXPORTS 25 | // This will enable forwarded export resolution globally instead of needing explicit `forwarded()` calls 26 | 27 | #ifndef LAZY_IMPORTER_HPP 28 | #define LAZY_IMPORTER_HPP 29 | 30 | 31 | #define LI_FN(name) ::li::detail::lazy_function() 32 | 33 | #define LI_FN_DEF(name) ::li::detail::lazy_function() 34 | 35 | #define LI_MODULE(name) ::li::detail::lazy_module() 36 | 37 | #ifndef LAZY_IMPORTER_CPP_FORWARD 38 | #ifdef LAZY_IMPORTER_NO_CPP_FORWARD 39 | #define LAZY_IMPORTER_CPP_FORWARD(t, v) v 40 | #else 41 | #include 42 | #define LAZY_IMPORTER_CPP_FORWARD(t, v) std::forward( v ) 43 | #endif 44 | #endif 45 | 46 | #include 47 | 48 | #ifndef LAZY_IMPORTER_NO_FORCEINLINE 49 | #if defined(_MSC_VER) 50 | #define LAZY_IMPORTER_FORCEINLINE __forceinline 51 | #elif defined(__GNUC__) && __GNUC__ > 3 52 | #define LAZY_IMPORTER_FORCEINLINE inline __attribute__((__always_inline__)) 53 | #else 54 | #define LAZY_IMPORTER_FORCEINLINE inline 55 | #endif 56 | #else 57 | #define LAZY_IMPORTER_FORCEINLINE inline 58 | #endif 59 | 60 | 61 | #ifdef LAZY_IMPORTER_CASE_INSENSITIVE 62 | #define LAZY_IMPORTER_CASE_SENSITIVITY false 63 | #else 64 | #define LAZY_IMPORTER_CASE_SENSITIVITY true 65 | #endif 66 | 67 | #define LAZY_IMPORTER_STRINGIZE(x) #x 68 | #define LAZY_IMPORTER_STRINGIZE_EXPAND(x) LAZY_IMPORTER_STRINGIZE(x) 69 | 70 | #define LAZY_IMPORTER_KHASH(str) ::li::detail::khash(str, \ 71 | ::li::detail::khash_impl( __TIME__ __DATE__ LAZY_IMPORTER_STRINGIZE_EXPAND(__LINE__) LAZY_IMPORTER_STRINGIZE_EXPAND(__COUNTER__), 2166136261 )) 72 | 73 | namespace li { 74 | namespace detail { 75 | 76 | namespace win { 77 | 78 | struct LIST_ENTRY_T { 79 | const char* Flink; 80 | const char* Blink; 81 | }; 82 | 83 | struct UNICODE_STRING_T { 84 | unsigned short Length; 85 | unsigned short MaximumLength; 86 | wchar_t* Buffer; 87 | }; 88 | 89 | struct PEB_LDR_DATA_T { 90 | unsigned long Length; 91 | unsigned long Initialized; 92 | const char* SsHandle; 93 | LIST_ENTRY_T InLoadOrderModuleList; 94 | }; 95 | 96 | struct PEB_T { 97 | unsigned char Reserved1[2]; 98 | unsigned char BeingDebugged; 99 | unsigned char Reserved2[1]; 100 | const char* Reserved3[2]; 101 | PEB_LDR_DATA_T* Ldr; 102 | }; 103 | 104 | struct LDR_DATA_TABLE_ENTRY_T { 105 | LIST_ENTRY_T InLoadOrderLinks; 106 | LIST_ENTRY_T InMemoryOrderLinks; 107 | LIST_ENTRY_T InInitializationOrderLinks; 108 | const char* DllBase; 109 | const char* EntryPoint; 110 | union { 111 | unsigned long SizeOfImage; 112 | const char* _dummy; 113 | }; 114 | UNICODE_STRING_T FullDllName; 115 | UNICODE_STRING_T BaseDllName; 116 | 117 | LAZY_IMPORTER_FORCEINLINE const LDR_DATA_TABLE_ENTRY_T* 118 | load_order_next() const noexcept 119 | { 120 | return reinterpret_cast( 121 | InLoadOrderLinks.Flink); 122 | } 123 | }; 124 | 125 | struct IMAGE_DOS_HEADER { // DOS .EXE header 126 | unsigned short e_magic; // Magic number 127 | unsigned short e_cblp; // Bytes on last page of file 128 | unsigned short e_cp; // Pages in file 129 | unsigned short e_crlc; // Relocations 130 | unsigned short e_cparhdr; // Size of header in paragraphs 131 | unsigned short e_minalloc; // Minimum extra paragraphs needed 132 | unsigned short e_maxalloc; // Maximum extra paragraphs needed 133 | unsigned short e_ss; // Initial (relative) SS value 134 | unsigned short e_sp; // Initial SP value 135 | unsigned short e_csum; // Checksum 136 | unsigned short e_ip; // Initial IP value 137 | unsigned short e_cs; // Initial (relative) CS value 138 | unsigned short e_lfarlc; // File address of relocation table 139 | unsigned short e_ovno; // Overlay number 140 | unsigned short e_res[4]; // Reserved words 141 | unsigned short e_oemid; // OEM identifier (for e_oeminfo) 142 | unsigned short e_oeminfo; // OEM information; e_oemid specific 143 | unsigned short e_res2[10]; // Reserved words 144 | long e_lfanew; // File address of new exe header 145 | }; 146 | 147 | struct IMAGE_FILE_HEADER { 148 | unsigned short Machine; 149 | unsigned short NumberOfSections; 150 | unsigned long TimeDateStamp; 151 | unsigned long PointerToSymbolTable; 152 | unsigned long NumberOfSymbols; 153 | unsigned short SizeOfOptionalHeader; 154 | unsigned short Characteristics; 155 | }; 156 | 157 | struct IMAGE_EXPORT_DIRECTORY { 158 | unsigned long Characteristics; 159 | unsigned long TimeDateStamp; 160 | unsigned short MajorVersion; 161 | unsigned short MinorVersion; 162 | unsigned long Name; 163 | unsigned long Base; 164 | unsigned long NumberOfFunctions; 165 | unsigned long NumberOfNames; 166 | unsigned long AddressOfFunctions; // RVA from base of image 167 | unsigned long AddressOfNames; // RVA from base of image 168 | unsigned long AddressOfNameOrdinals; // RVA from base of image 169 | }; 170 | 171 | struct IMAGE_DATA_DIRECTORY { 172 | unsigned long VirtualAddress; 173 | unsigned long Size; 174 | }; 175 | 176 | struct IMAGE_OPTIONAL_HEADER64 { 177 | unsigned short Magic; 178 | unsigned char MajorLinkerVersion; 179 | unsigned char MinorLinkerVersion; 180 | unsigned long SizeOfCode; 181 | unsigned long SizeOfInitializedData; 182 | unsigned long SizeOfUninitializedData; 183 | unsigned long AddressOfEntryPoint; 184 | unsigned long BaseOfCode; 185 | unsigned long long ImageBase; 186 | unsigned long SectionAlignment; 187 | unsigned long FileAlignment; 188 | unsigned short MajorOperatingSystemVersion; 189 | unsigned short MinorOperatingSystemVersion; 190 | unsigned short MajorImageVersion; 191 | unsigned short MinorImageVersion; 192 | unsigned short MajorSubsystemVersion; 193 | unsigned short MinorSubsystemVersion; 194 | unsigned long Win32VersionValue; 195 | unsigned long SizeOfImage; 196 | unsigned long SizeOfHeaders; 197 | unsigned long CheckSum; 198 | unsigned short Subsystem; 199 | unsigned short DllCharacteristics; 200 | unsigned long long SizeOfStackReserve; 201 | unsigned long long SizeOfStackCommit; 202 | unsigned long long SizeOfHeapReserve; 203 | unsigned long long SizeOfHeapCommit; 204 | unsigned long LoaderFlags; 205 | unsigned long NumberOfRvaAndSizes; 206 | IMAGE_DATA_DIRECTORY DataDirectory[16]; 207 | }; 208 | 209 | struct IMAGE_OPTIONAL_HEADER32 { 210 | unsigned short Magic; 211 | unsigned char MajorLinkerVersion; 212 | unsigned char MinorLinkerVersion; 213 | unsigned long SizeOfCode; 214 | unsigned long SizeOfInitializedData; 215 | unsigned long SizeOfUninitializedData; 216 | unsigned long AddressOfEntryPoint; 217 | unsigned long BaseOfCode; 218 | unsigned long BaseOfData; 219 | unsigned long ImageBase; 220 | unsigned long SectionAlignment; 221 | unsigned long FileAlignment; 222 | unsigned short MajorOperatingSystemVersion; 223 | unsigned short MinorOperatingSystemVersion; 224 | unsigned short MajorImageVersion; 225 | unsigned short MinorImageVersion; 226 | unsigned short MajorSubsystemVersion; 227 | unsigned short MinorSubsystemVersion; 228 | unsigned long Win32VersionValue; 229 | unsigned long SizeOfImage; 230 | unsigned long SizeOfHeaders; 231 | unsigned long CheckSum; 232 | unsigned short Subsystem; 233 | unsigned short DllCharacteristics; 234 | unsigned long SizeOfStackReserve; 235 | unsigned long SizeOfStackCommit; 236 | unsigned long SizeOfHeapReserve; 237 | unsigned long SizeOfHeapCommit; 238 | unsigned long LoaderFlags; 239 | unsigned long NumberOfRvaAndSizes; 240 | IMAGE_DATA_DIRECTORY DataDirectory[16]; 241 | }; 242 | 243 | struct IMAGE_NT_HEADERS { 244 | unsigned long Signature; 245 | IMAGE_FILE_HEADER FileHeader; 246 | #ifdef _WIN64 247 | IMAGE_OPTIONAL_HEADER64 OptionalHeader; 248 | #else 249 | IMAGE_OPTIONAL_HEADER32 OptionalHeader; 250 | #endif 251 | }; 252 | 253 | } // namespace win 254 | 255 | struct forwarded_hashes { 256 | unsigned module_hash; 257 | unsigned function_hash; 258 | }; 259 | 260 | // 64 bit integer where 32 bits are used for the hash offset 261 | // and remaining 32 bits are used for the hash computed using it 262 | using offset_hash_pair = unsigned long long; 263 | 264 | LAZY_IMPORTER_FORCEINLINE constexpr unsigned get_hash(offset_hash_pair pair) noexcept { return (pair & 0xFFFFFFFF); } 265 | 266 | LAZY_IMPORTER_FORCEINLINE constexpr unsigned get_offset(offset_hash_pair pair) noexcept { return (pair >> 32); } 267 | 268 | template 269 | LAZY_IMPORTER_FORCEINLINE constexpr unsigned hash_single(unsigned value, char c) noexcept 270 | { 271 | return static_cast( 272 | (value ^ ((!CaseSensitive && c >= 'A' && c <= 'Z') ? (c | (1 << 5)) : c)) * 273 | static_cast(16777619)); 274 | } 275 | 276 | LAZY_IMPORTER_FORCEINLINE constexpr unsigned 277 | khash_impl(const char* str, unsigned value) noexcept 278 | { 279 | return (*str ? khash_impl(str + 1, hash_single(value, *str)) : value); 280 | } 281 | 282 | LAZY_IMPORTER_FORCEINLINE constexpr offset_hash_pair khash( 283 | const char* str, unsigned offset) noexcept 284 | { 285 | return ((offset_hash_pair{ offset } << 32) | khash_impl(str, offset)); 286 | } 287 | 288 | template 289 | LAZY_IMPORTER_FORCEINLINE unsigned hash(const CharT* str, unsigned offset) noexcept 290 | { 291 | unsigned value = offset; 292 | 293 | for (;;) { 294 | char c = *str++; 295 | if (!c) 296 | return value; 297 | value = hash_single(value, c); 298 | } 299 | } 300 | 301 | LAZY_IMPORTER_FORCEINLINE unsigned hash( 302 | const win::UNICODE_STRING_T& str, unsigned offset) noexcept 303 | { 304 | auto first = str.Buffer; 305 | const auto last = first + (str.Length / sizeof(wchar_t)); 306 | auto value = offset; 307 | for (; first != last; ++first) 308 | value = hash_single(value, static_cast(*first)); 309 | 310 | return value; 311 | } 312 | 313 | LAZY_IMPORTER_FORCEINLINE forwarded_hashes hash_forwarded( 314 | const char* str, unsigned offset) noexcept 315 | { 316 | forwarded_hashes res{ offset, offset }; 317 | 318 | for (; *str != '.'; ++str) 319 | res.module_hash = hash_single(res.module_hash, *str); 320 | 321 | ++str; 322 | 323 | for (; *str; ++str) 324 | res.function_hash = hash_single(res.function_hash, *str); 325 | 326 | return res; 327 | } 328 | 329 | // some helper functions 330 | LAZY_IMPORTER_FORCEINLINE const win::PEB_T* peb() noexcept 331 | { 332 | #if defined(_M_X64) || defined(__amd64__) 333 | return reinterpret_cast(__readgsqword(0x60)); 334 | #elif defined(_M_IX86) || defined(__i386__) 335 | return reinterpret_cast(__readfsdword(0x30)); 336 | #elif defined(_M_ARM) || defined(__arm__) 337 | return *reinterpret_cast(_MoveFromCoprocessor(15, 0, 13, 0, 2) + 0x30); 338 | #elif defined(_M_ARM64) || defined(__aarch64__) 339 | return *reinterpret_cast(__getReg(18) + 0x60); 340 | #elif defined(_M_IA64) || defined(__ia64__) 341 | return *reinterpret_cast(static_cast(_rdteb()) + 0x60); 342 | #else 343 | #error Unsupported platform. Open an issue and I'll probably add support. 344 | #endif 345 | } 346 | 347 | LAZY_IMPORTER_FORCEINLINE const win::PEB_LDR_DATA_T* ldr() 348 | { 349 | return reinterpret_cast(peb()->Ldr); 350 | } 351 | 352 | LAZY_IMPORTER_FORCEINLINE const win::IMAGE_NT_HEADERS* nt_headers( 353 | const char* base) noexcept 354 | { 355 | return reinterpret_cast( 356 | base + reinterpret_cast(base)->e_lfanew); 357 | } 358 | 359 | LAZY_IMPORTER_FORCEINLINE const win::IMAGE_EXPORT_DIRECTORY* image_export_dir( 360 | const char* base) noexcept 361 | { 362 | return reinterpret_cast( 363 | base + nt_headers(base)->OptionalHeader.DataDirectory->VirtualAddress); 364 | } 365 | 366 | LAZY_IMPORTER_FORCEINLINE const win::LDR_DATA_TABLE_ENTRY_T* ldr_data_entry() noexcept 367 | { 368 | return reinterpret_cast( 369 | ldr()->InLoadOrderModuleList.Flink); 370 | } 371 | 372 | struct exports_directory { 373 | const char* _base; 374 | const win::IMAGE_EXPORT_DIRECTORY* _ied; 375 | unsigned long _ied_size; 376 | 377 | public: 378 | using size_type = unsigned long; 379 | 380 | LAZY_IMPORTER_FORCEINLINE 381 | exports_directory(const char* base) noexcept : _base(base) 382 | { 383 | const auto ied_data_dir = nt_headers(base)->OptionalHeader.DataDirectory[0]; 384 | _ied = reinterpret_cast( 385 | base + ied_data_dir.VirtualAddress); 386 | _ied_size = ied_data_dir.Size; 387 | } 388 | 389 | LAZY_IMPORTER_FORCEINLINE explicit operator bool() const noexcept 390 | { 391 | return reinterpret_cast(_ied) != _base; 392 | } 393 | 394 | LAZY_IMPORTER_FORCEINLINE size_type size() const noexcept 395 | { 396 | return _ied->NumberOfNames; 397 | } 398 | 399 | LAZY_IMPORTER_FORCEINLINE const char* base() const noexcept { return _base; } 400 | LAZY_IMPORTER_FORCEINLINE const win::IMAGE_EXPORT_DIRECTORY* ied() const noexcept 401 | { 402 | return _ied; 403 | } 404 | 405 | LAZY_IMPORTER_FORCEINLINE const char* name(size_type index) const noexcept 406 | { 407 | return reinterpret_cast( 408 | _base + reinterpret_cast( 409 | _base + _ied->AddressOfNames)[index]); 410 | } 411 | 412 | LAZY_IMPORTER_FORCEINLINE const char* address(size_type index) const noexcept 413 | { 414 | const auto* const rva_table = 415 | reinterpret_cast(_base + _ied->AddressOfFunctions); 416 | 417 | const auto* const ord_table = reinterpret_cast( 418 | _base + _ied->AddressOfNameOrdinals); 419 | 420 | return _base + rva_table[ord_table[index]]; 421 | } 422 | 423 | LAZY_IMPORTER_FORCEINLINE bool is_forwarded( 424 | const char* export_address) const noexcept 425 | { 426 | const auto ui_ied = reinterpret_cast(_ied); 427 | return (export_address > ui_ied && export_address < ui_ied + _ied_size); 428 | } 429 | }; 430 | 431 | struct safe_module_enumerator { 432 | using value_type = const detail::win::LDR_DATA_TABLE_ENTRY_T; 433 | value_type* value; 434 | value_type* head; 435 | 436 | LAZY_IMPORTER_FORCEINLINE safe_module_enumerator() noexcept 437 | : safe_module_enumerator(ldr_data_entry()) 438 | {} 439 | 440 | LAZY_IMPORTER_FORCEINLINE 441 | safe_module_enumerator(const detail::win::LDR_DATA_TABLE_ENTRY_T* ldr) noexcept 442 | : value(ldr->load_order_next()), head(value) 443 | {} 444 | 445 | LAZY_IMPORTER_FORCEINLINE void reset() noexcept 446 | { 447 | value = head->load_order_next(); 448 | } 449 | 450 | LAZY_IMPORTER_FORCEINLINE bool next() noexcept 451 | { 452 | value = value->load_order_next(); 453 | 454 | return value != head && value->DllBase; 455 | } 456 | }; 457 | 458 | struct unsafe_module_enumerator { 459 | using value_type = const detail::win::LDR_DATA_TABLE_ENTRY_T*; 460 | value_type value; 461 | 462 | LAZY_IMPORTER_FORCEINLINE unsafe_module_enumerator() noexcept 463 | : value(ldr_data_entry()) 464 | {} 465 | 466 | LAZY_IMPORTER_FORCEINLINE void reset() noexcept { value = ldr_data_entry(); } 467 | 468 | LAZY_IMPORTER_FORCEINLINE bool next() noexcept 469 | { 470 | value = value->load_order_next(); 471 | return true; 472 | } 473 | }; 474 | 475 | // provides the cached functions which use Derive classes methods 476 | template 477 | class lazy_base { 478 | protected: 479 | // This function is needed because every templated function 480 | // with different args has its own static buffer 481 | LAZY_IMPORTER_FORCEINLINE static void*& _cache() noexcept 482 | { 483 | static void* value = nullptr; 484 | return value; 485 | } 486 | 487 | public: 488 | template 489 | LAZY_IMPORTER_FORCEINLINE static T safe() noexcept 490 | { 491 | return Derived::template get(); 492 | } 493 | 494 | template 495 | LAZY_IMPORTER_FORCEINLINE static T cached() noexcept 496 | { 497 | auto& cached = _cache(); 498 | if (!cached) 499 | cached = Derived::template get(); 500 | 501 | return (T)(cached); 502 | } 503 | 504 | template 505 | LAZY_IMPORTER_FORCEINLINE static T safe_cached() noexcept 506 | { 507 | return cached(); 508 | } 509 | }; 510 | 511 | template 512 | struct lazy_module : lazy_base> { 513 | template 514 | LAZY_IMPORTER_FORCEINLINE static T get() noexcept 515 | { 516 | Enum e; 517 | do { 518 | if (hash(e.value->BaseDllName, get_offset(OHP)) == get_hash(OHP)) 519 | return (T)(e.value->DllBase); 520 | } while (e.next()); 521 | return {}; 522 | } 523 | 524 | template 525 | LAZY_IMPORTER_FORCEINLINE static T in(Ldr ldr) noexcept 526 | { 527 | safe_module_enumerator e((const detail::win::LDR_DATA_TABLE_ENTRY_T*)(ldr)); 528 | do { 529 | if (hash(e.value->BaseDllName, get_offset(OHP)) == get_hash(OHP)) 530 | return (T)(e.value->DllBase); 531 | } while (e.next()); 532 | return {}; 533 | } 534 | 535 | template 536 | LAZY_IMPORTER_FORCEINLINE static T in_cached(Ldr ldr) noexcept 537 | { 538 | auto& cached = lazy_base>::_cache(); 539 | if (!cached) 540 | cached = in(ldr); 541 | 542 | return (T)(cached); 543 | } 544 | }; 545 | 546 | template 547 | struct lazy_function : lazy_base, T> { 548 | using base_type = lazy_base, T>; 549 | 550 | template 551 | LAZY_IMPORTER_FORCEINLINE decltype(auto) operator()(Args&&... args) const 552 | { 553 | #ifndef LAZY_IMPORTER_CACHE_OPERATOR_PARENS 554 | return get()(LAZY_IMPORTER_CPP_FORWARD(Args, args)...); 555 | #else 556 | return this->cached()(LAZY_IMPORTER_CPP_FORWARD(Args, args)...); 557 | #endif 558 | } 559 | 560 | template 561 | LAZY_IMPORTER_FORCEINLINE static F get() noexcept 562 | { 563 | // for backwards compatability. 564 | // Before 2.0 it was only possible to resolve forwarded exports when 565 | // this macro was enabled 566 | #ifdef LAZY_IMPORTER_RESOLVE_FORWARDED_EXPORTS 567 | return forwarded(); 568 | #else 569 | 570 | Enum e; 571 | 572 | do { 573 | #ifdef LAZY_IMPORTER_HARDENED_MODULE_CHECKS 574 | if (!e.value->DllBase || !e.value->FullDllName.Length) 575 | continue; 576 | #endif 577 | 578 | const exports_directory exports(e.value->DllBase); 579 | 580 | if (exports) { 581 | auto export_index = exports.size(); 582 | while (export_index--) 583 | if (hash(exports.name(export_index), get_offset(OHP)) == get_hash(OHP)) 584 | return (F)(exports.address(export_index)); 585 | } 586 | } while (e.next()); 587 | return {}; 588 | #endif 589 | } 590 | 591 | template 592 | LAZY_IMPORTER_FORCEINLINE static F forwarded() noexcept 593 | { 594 | detail::win::UNICODE_STRING_T name; 595 | forwarded_hashes hashes{ 0, get_hash(OHP) }; 596 | 597 | Enum e; 598 | do { 599 | name = e.value->BaseDllName; 600 | name.Length -= 8; // get rid of .dll extension 601 | 602 | if (!hashes.module_hash || hash(name, get_offset(OHP)) == hashes.module_hash) { 603 | const exports_directory exports(e.value->DllBase); 604 | 605 | if (exports) { 606 | auto export_index = exports.size(); 607 | while (export_index--) 608 | if (hash(exports.name(export_index), get_offset(OHP)) == hashes.function_hash) { 609 | const auto addr = exports.address(export_index); 610 | 611 | if (exports.is_forwarded(addr)) { 612 | hashes = hash_forwarded( 613 | reinterpret_cast(addr), 614 | get_offset(OHP)); 615 | 616 | e.reset(); 617 | break; 618 | } 619 | return (F)(addr); 620 | } 621 | } 622 | } 623 | } while (e.next()); 624 | return {}; 625 | } 626 | 627 | template 628 | LAZY_IMPORTER_FORCEINLINE static F forwarded_safe() noexcept 629 | { 630 | return forwarded(); 631 | } 632 | 633 | template 634 | LAZY_IMPORTER_FORCEINLINE static F forwarded_cached() noexcept 635 | { 636 | auto& value = base_type::_cache(); 637 | if (!value) 638 | value = forwarded(); 639 | return (F)(value); 640 | } 641 | 642 | template 643 | LAZY_IMPORTER_FORCEINLINE static F forwarded_safe_cached() noexcept 644 | { 645 | return forwarded_cached(); 646 | } 647 | 648 | template 649 | LAZY_IMPORTER_FORCEINLINE static F in(Module m) noexcept 650 | { 651 | if (IsSafe && !m) 652 | return {}; 653 | 654 | const exports_directory exports((const char*)(m)); 655 | if (IsSafe && !exports) 656 | return {}; 657 | 658 | for (unsigned long i{};; ++i) { 659 | if (IsSafe && i == exports.size()) 660 | break; 661 | 662 | if (hash(exports.name(i), get_offset(OHP)) == get_hash(OHP)) 663 | return (F)(exports.address(i)); 664 | } 665 | return {}; 666 | } 667 | 668 | template 669 | LAZY_IMPORTER_FORCEINLINE static F in_safe(Module m) noexcept 670 | { 671 | return in(m); 672 | } 673 | 674 | template 675 | LAZY_IMPORTER_FORCEINLINE static F in_cached(Module m) noexcept 676 | { 677 | auto& value = base_type::_cache(); 678 | if (!value) 679 | value = in(m); 680 | return (F)(value); 681 | } 682 | 683 | template 684 | LAZY_IMPORTER_FORCEINLINE static F in_safe_cached(Module m) noexcept 685 | { 686 | return in_cached(m); 687 | } 688 | 689 | template 690 | LAZY_IMPORTER_FORCEINLINE static F nt() noexcept 691 | { 692 | return in(ldr_data_entry()->load_order_next()->DllBase); 693 | } 694 | 695 | template 696 | LAZY_IMPORTER_FORCEINLINE static F nt_safe() noexcept 697 | { 698 | return in_safe(ldr_data_entry()->load_order_next()->DllBase); 699 | } 700 | 701 | template 702 | LAZY_IMPORTER_FORCEINLINE static F nt_cached() noexcept 703 | { 704 | return in_cached(ldr_data_entry()->load_order_next()->DllBase); 705 | } 706 | 707 | template 708 | LAZY_IMPORTER_FORCEINLINE static F nt_safe_cached() noexcept 709 | { 710 | return in_safe_cached(ldr_data_entry()->load_order_next()->DllBase); 711 | } 712 | }; 713 | 714 | } 715 | } // namespace li::detail 716 | 717 | #endif // include guard -------------------------------------------------------------------------------- /r5script/r5script.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | Debug 14 | x64 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | 16.0 23 | Win32Proj 24 | {0fdbea6c-37cd-4f61-b7d0-36663c7d4955} 25 | r5script 26 | 10.0 27 | 28 | 29 | 30 | DynamicLibrary 31 | true 32 | v142 33 | Unicode 34 | 35 | 36 | DynamicLibrary 37 | false 38 | v142 39 | true 40 | Unicode 41 | 42 | 43 | DynamicLibrary 44 | true 45 | v142 46 | Unicode 47 | 48 | 49 | DynamicLibrary 50 | false 51 | v142 52 | true 53 | Unicode 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | true 75 | 76 | 77 | false 78 | 79 | 80 | true 81 | 82 | 83 | false 84 | 85 | 86 | 87 | Level3 88 | true 89 | WIN32;_DEBUG;R5SCRIPT_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) 90 | true 91 | Use 92 | pch.h 93 | 94 | 95 | Windows 96 | true 97 | false 98 | 99 | 100 | 101 | 102 | Level3 103 | true 104 | true 105 | true 106 | WIN32;NDEBUG;R5SCRIPT_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) 107 | true 108 | Use 109 | pch.h 110 | 111 | 112 | Windows 113 | true 114 | true 115 | true 116 | false 117 | 118 | 119 | 120 | 121 | Level3 122 | true 123 | _DEBUG;R5SCRIPT_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) 124 | true 125 | Use 126 | pch.h 127 | 128 | 129 | Windows 130 | true 131 | false 132 | 133 | 134 | 135 | 136 | Level3 137 | true 138 | true 139 | true 140 | NDEBUG;R5SCRIPT_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) 141 | true 142 | NotUsing 143 | pch.h 144 | stdcpplatest 145 | 146 | 147 | Windows 148 | true 149 | true 150 | false 151 | false 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | -------------------------------------------------------------------------------- /r5script/r5script.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /r5script/r5script.vcxproj.user: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | -------------------------------------------------------------------------------- /r5script/skcrypter.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | /*____________________________________________________________________________________________________________ 4 | Original Author: skadro 5 | Github: https://github.com/skadro-official 6 | License: See end of file 7 | skCrypter 8 | Compile-time, Usermode + Kernelmode, safe and lightweight string crypter library for C++11+ 9 | *Not removing this part is appreciated* 10 | ____________________________________________________________________________________________________________*/ 11 | 12 | #ifdef _KERNEL_MODE 13 | namespace std 14 | { 15 | // STRUCT TEMPLATE remove_reference 16 | template 17 | struct remove_reference { 18 | using type = _Ty; 19 | }; 20 | 21 | template 22 | struct remove_reference<_Ty&> { 23 | using type = _Ty; 24 | }; 25 | 26 | template 27 | struct remove_reference<_Ty&&> { 28 | using type = _Ty; 29 | }; 30 | 31 | template 32 | using remove_reference_t = typename remove_reference<_Ty>::type; 33 | 34 | // STRUCT TEMPLATE remove_const 35 | template 36 | struct remove_const { // remove top-level const qualifier 37 | using type = _Ty; 38 | }; 39 | 40 | template 41 | struct remove_const { 42 | using type = _Ty; 43 | }; 44 | 45 | template 46 | using remove_const_t = typename remove_const<_Ty>::type; 47 | } 48 | #else 49 | #include 50 | #endif 51 | 52 | namespace skc 53 | { 54 | template 55 | using clean_type = typename std::remove_const_t>; 56 | 57 | template 58 | class skCrypter 59 | { 60 | public: 61 | __forceinline constexpr skCrypter(T* data) 62 | { 63 | crypt(data); 64 | } 65 | 66 | __forceinline T* get() 67 | { 68 | return _storage; 69 | } 70 | 71 | __forceinline int size() // (w)char count 72 | { 73 | return _size; 74 | } 75 | 76 | __forceinline char key() 77 | { 78 | return _key1; 79 | } 80 | 81 | __forceinline T* encrypt() 82 | { 83 | if (!isEncrypted()) 84 | crypt(_storage); 85 | 86 | return _storage; 87 | } 88 | 89 | __forceinline T* decrypt() 90 | { 91 | if (isEncrypted()) 92 | crypt(_storage); 93 | 94 | return _storage; 95 | } 96 | 97 | __forceinline bool isEncrypted() 98 | { 99 | return _storage[_size - 1] != 0; 100 | } 101 | 102 | __forceinline void clear() // set full storage to 0 103 | { 104 | for (int i = 0; i < _size; i++) 105 | { 106 | _storage[i] = 0; 107 | } 108 | } 109 | 110 | __forceinline operator T* () 111 | { 112 | decrypt(); 113 | 114 | return _storage; 115 | } 116 | 117 | private: 118 | __forceinline constexpr void crypt(T* data) 119 | { 120 | for (int i = 0; i < _size; i++) 121 | { 122 | _storage[i] = data[i] ^ (_key1 + i % (1 + _key2)); 123 | } 124 | } 125 | 126 | T _storage[_size]{}; 127 | }; 128 | } 129 | 130 | #define skCrypt(str) skCrypt_key(str, __TIME__[4], __TIME__[7]) 131 | #define skCrypt_key(str, key1, key2) []() { \ 132 | constexpr static auto crypted = skc::skCrypter \ 133 | >((skc::clean_type*)str); \ 134 | return crypted; }() 135 | 136 | /*________________________________________________________________________________ 137 | MIT License 138 | Copyright (c) 2020 skadro 139 | Permission is hereby granted, free of charge, to any person obtaining a copy 140 | of this software and associated documentation files (the "Software"), to deal 141 | in the Software without restriction, including without limitation the rights 142 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 143 | copies of the Software, and to permit persons to whom the Software is 144 | furnished to do so, subject to the following conditions: 145 | The above copyright notice and this permission notice shall be included in all 146 | copies or substantial portions of the Software. 147 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 148 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 149 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 150 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 151 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 152 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 153 | SOFTWARE. 154 | ________________________________________________________________________________*/ --------------------------------------------------------------------------------