/* Capstone Disassembly Engine */ /* By Satoshi Tanda , 2016 */ #include #include #include #ifdef __cplusplus extern "C" { #endif #include "../utils.h" // for cs_snprintf #ifdef __cplusplus } #endif EXTERN_C DRIVER_INITIALIZE DriverEntry; #pragma warning(push) #pragma warning(disable : 4005) // 'identifier' : macro redefinition #pragma warning(disable : 4007) // 'main': must be '__cdecl' // Drivers must protect floating point hardware state. See use of float. // Use KeSaveFloatingPointState/KeRestoreFloatingPointState around floating // point operations. Display Drivers should use the corresponding Eng... routines. #pragma warning(disable : 28110) // Suppress this, as it is false positive. // "Import" existing tests into this file. All code is encaptured into unique // namespace so that the same name does not conflict. Beware that those code // is going to be compiled as C++ source file and not C files because this file // is C++. namespace basic { #include "test_basic.c" } // namespace basic namespace detail { #include "test_detail.c" } // namespace detail namespace skipdata { #include "test_skipdata.c" } // namespace skipdata namespace iter { #include "test_iter.c" } // namespace iter namespace customized_mnem_ { #include "test_customized_mnem.c" } // namespace customized_mnem_ namespace arm { #include "test_arm.c" } // namespace arm namespace arm64 { #include "test_arm64.c" } // namespace arm64 namespace mips { #include "test_mips.c" } // namespace mips namespace m68k { #include "test_m68k.c" } // namespace m68k namespace ppc { #include "test_ppc.c" } // namespace ppc namespace sparc { #include "test_sparc.c" } // namespace sparc namespace systemz { #include "test_systemz.c" } // namespace systemz namespace x86 { #include "test_x86.c" } // namespace x86 namespace xcore { #include "test_xcore.c" } // namespace xcore #pragma warning(pop) // Exercises all existing regression tests static void test() { KFLOATING_SAVE float_save; NTSTATUS status; // Any of Capstone APIs cannot be called at IRQL higher than DISPATCH_LEVEL // since our malloc implementation using ExAllocatePoolWithTag() is able to // allocate memory only up to the DISPATCH_LEVEL level. NT_ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL); // On a 32bit driver, KeSaveFloatingPointState() is required before using any // Capstone function because Capstone can access to the MMX/x87 registers and // 32bit Windows requires drivers to use KeSaveFloatingPointState() before and // KeRestoreFloatingPointState() after accessing them. See "Using Floating // Point or MMX in a WDM Driver" on MSDN for more details. status = KeSaveFloatingPointState(&float_save); if (!NT_SUCCESS(status)) { printf("ERROR: Failed to save floating point state!\n"); return; } basic::test(); detail::test(); skipdata::test(); iter::test(); customized_mnem_::test(); arm::test(); arm64::test(); mips::test(); m68k::test(); ppc::test(); sparc::test(); systemz::test(); x86::test(); xcore::test(); // Restores the nonvolatile floating-point context. KeRestoreFloatingPointState(&float_save); } // Functional test for cs_winkernel_vsnprintf() static void cs_winkernel_vsnprintf_test() { char buf[10]; bool ok = true; ok = (ok && cs_snprintf(buf, sizeof(buf), "%s", "") == 0 && strcmp(buf, "") == 0); ok = (ok && cs_snprintf(buf, sizeof(buf), "%s", "0") == 1 && strcmp(buf, "0") == 0); ok = (ok && cs_snprintf(buf, sizeof(buf), "%s", "012345678") == 9 && strcmp(buf, "012345678") == 0); ok = (ok && cs_snprintf(buf, sizeof(buf), "%s", "0123456789") == 10 && strcmp(buf, "012345678") == 0); ok = (ok && cs_snprintf(buf, sizeof(buf), "%s", "01234567890") == 11 && strcmp(buf, "012345678") == 0); ok = (ok && cs_snprintf(buf, sizeof(buf), "%s", "0123456789001234567890") == 22 && strcmp(buf, "012345678") == 0); if (!ok) { printf("ERROR: cs_winkernel_vsnprintf_test() did not produce expected results!\n"); } } // Driver entry point EXTERN_C NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath) { UNREFERENCED_PARAMETER(DriverObject); UNREFERENCED_PARAMETER(RegistryPath); cs_winkernel_vsnprintf_test(); test(); return STATUS_CANCELLED; } // This functions mimics printf() but does not return the same value as printf() // would do. printf() is required to exercise regression tests. _Use_decl_annotations_ int __cdecl printf(const char * format, ...) { NTSTATUS status; va_list args; va_start(args, format); status = vDbgPrintEx(DPFLTR_DEFAULT_ID, DPFLTR_ERROR_LEVEL, format, args); va_end(args); return NT_SUCCESS(status); }