1 /* Capstone Disassembly Engine */ 2 /* By Satoshi Tanda <tanda.sat (at) gmail.com>, 2016 */ 3 4 #include <ntddk.h> 5 #include <capstone.h> 6 7 #ifdef __cplusplus 8 extern "C" { 9 #endif 10 11 #include "../utils.h" // for cs_snprintf 12 13 #ifdef __cplusplus 14 } 15 #endif 16 17 EXTERN_C DRIVER_INITIALIZE DriverEntry; 18 19 #pragma warning(push) 20 #pragma warning(disable : 4005) // 'identifier' : macro redefinition 21 #pragma warning(disable : 4007) // 'main': must be '__cdecl' 22 23 // Drivers must protect floating point hardware state. See use of float. 24 // Use KeSaveFloatingPointState/KeRestoreFloatingPointState around floating 25 // point operations. Display Drivers should use the corresponding Eng... routines. 26 #pragma warning(disable : 28110) // Suppress this, as it is false positive. 27 28 // "Import" existing tests into this file. All code is encaptured into unique 29 // namespace so that the same name does not conflict. Beware that those code 30 // is going to be compiled as C++ source file and not C files because this file 31 // is C++. 32 33 namespace unnamed { 34 #include "test.c" 35 } // namespace unnamed 36 37 namespace detail { 38 #include "test_detail.c" 39 } // namespace detail 40 41 namespace skipdata { 42 #include "test_skipdata.c" 43 } // namespace skipdata 44 45 namespace iter { 46 #include "test_iter.c" 47 } // namespace iter 48 49 namespace arm { 50 #include "test_arm.c" 51 } // namespace arm 52 53 namespace arm64 { 54 #include "test_arm64.c" 55 } // namespace arm64 56 57 namespace mips { 58 #include "test_mips.c" 59 } // namespace mips 60 61 namespace ppc { 62 #include "test_ppc.c" 63 } // namespace ppc 64 65 namespace sparc { 66 #include "test_sparc.c" 67 } // namespace sparc 68 69 namespace systemz { 70 #include "test_systemz.c" 71 } // namespace systemz 72 73 namespace x86 { 74 #include "test_x86.c" 75 } // namespace x86 76 77 namespace xcore { 78 #include "test_xcore.c" 79 } // namespace xcore 80 81 #pragma warning(pop) 82 83 // Exercises all existing regression tests 84 static void test() 85 { 86 KFLOATING_SAVE float_save; 87 NTSTATUS status; 88 89 // Any of Capstone APIs cannot be called at IRQL higher than DISPATCH_LEVEL 90 // since our malloc implementation using ExAllocatePoolWithTag() is able to 91 // allocate memory only up to the DISPATCH_LEVEL level. 92 NT_ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL); 93 94 // On a 32bit driver, KeSaveFloatingPointState() is required before using any 95 // Capstone function because Capstone can access to the MMX/x87 registers and 96 // 32bit Windows requires drivers to use KeSaveFloatingPointState() before and 97 // KeRestoreFloatingPointState() after accessing them. See "Using Floating 98 // Point or MMX in a WDM Driver" on MSDN for more details. 99 status = KeSaveFloatingPointState(&float_save); 100 if (!NT_SUCCESS(status)) { 101 printf("ERROR: Failed to save floating point state!\n"); 102 return; 103 } 104 105 unnamed::test(); 106 detail::test(); 107 skipdata::test(); 108 iter::test(); 109 arm::test(); 110 arm64::test(); 111 mips::test(); 112 ppc::test(); 113 sparc::test(); 114 systemz::test(); 115 x86::test(); 116 xcore::test(); 117 118 // Restores the nonvolatile floating-point context. 119 KeRestoreFloatingPointState(&float_save); 120 } 121 122 // Functional test for cs_winkernel_vsnprintf() 123 static void cs_winkernel_vsnprintf_test() 124 { 125 char buf[10]; 126 bool ok = true; 127 ok = (ok && cs_snprintf(buf, sizeof(buf), "%s", "") == 0 && strcmp(buf, "") == 0); 128 ok = (ok && cs_snprintf(buf, sizeof(buf), "%s", "0") == 1 && strcmp(buf, "0") == 0); 129 ok = (ok && cs_snprintf(buf, sizeof(buf), "%s", "012345678") == 9 && strcmp(buf, "012345678") == 0); 130 ok = (ok && cs_snprintf(buf, sizeof(buf), "%s", "0123456789") == 10 && strcmp(buf, "012345678") == 0); 131 ok = (ok && cs_snprintf(buf, sizeof(buf), "%s", "01234567890") == 11 && strcmp(buf, "012345678") == 0); 132 ok = (ok && cs_snprintf(buf, sizeof(buf), "%s", "0123456789001234567890") == 22 && strcmp(buf, "012345678") == 0); 133 if (!ok) { 134 printf("ERROR: cs_winkernel_vsnprintf_test() did not produce expected results!\n"); 135 } 136 } 137 138 // Driver entry point 139 EXTERN_C NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath) 140 { 141 UNREFERENCED_PARAMETER(DriverObject); 142 UNREFERENCED_PARAMETER(RegistryPath); 143 cs_winkernel_vsnprintf_test(); 144 test(); 145 return STATUS_CANCELLED; 146 } 147 148 // This functions mimics printf() but does not return the same value as printf() 149 // would do. printf() is required to exercise regression tests. 150 _Use_decl_annotations_ 151 int __cdecl printf(const char * format, ...) 152 { 153 NTSTATUS status; 154 va_list args; 155 156 va_start(args, format); 157 status = vDbgPrintEx(DPFLTR_DEFAULT_ID, DPFLTR_ERROR_LEVEL, format, args); 158 va_end(args); 159 return NT_SUCCESS(status); 160 } 161