161 lines
4.4 KiB
C++
161 lines
4.4 KiB
C++
|
/* Capstone Disassembly Engine */
|
||
|
/* By Satoshi Tanda <tanda.sat@gmail.com>, 2016 */
|
||
|
|
||
|
#include <ntddk.h>
|
||
|
#include <capstone.h>
|
||
|
|
||
|
#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 unnamed {
|
||
|
#include "test.c"
|
||
|
} // namespace unnamed
|
||
|
|
||
|
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 arm {
|
||
|
#include "test_arm.c"
|
||
|
} // namespace arm
|
||
|
|
||
|
namespace arm64 {
|
||
|
#include "test_arm64.c"
|
||
|
} // namespace arm64
|
||
|
|
||
|
namespace mips {
|
||
|
#include "test_mips.c"
|
||
|
} // namespace mips
|
||
|
|
||
|
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;
|
||
|
}
|
||
|
|
||
|
unnamed::test();
|
||
|
detail::test();
|
||
|
skipdata::test();
|
||
|
iter::test();
|
||
|
arm::test();
|
||
|
arm64::test();
|
||
|
mips::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);
|
||
|
}
|