一
测试原理
在Windows中,用户层和内核层通过DeviceIoControl来实现通信得,该函数定义如下:
BOOL WINAPI DeviceIoControl(
__in HANDLE hDevice,
__in DWORD dwIoControlCode,
__in_opt LPVOID lpInBuffer,
__in DWORD nInBufferSize,
__out_opt LPVOID lpOutBuffer,
__in DWORD nOutBufferSize,
__out_opt LPDWORD lpBytesReturned,
__inout_opt LPOVERLAPPED lpOverlapped);
DeviceIoControl函数最后会通过内核函数NtDeviceIoControlFile来实现通信,该函数定义如下:
NTSTATUS
NtDeviceIoControlFile(
IN HANDLE FileHandle,
IN HANDLE Event,
IN PIO_APC_ROUTINE ApcRoutine,
IN PVOID ApcContext,
OUT PIO_STATUS_BLOCK IoStatusBlock,
IN ULONG IoControlCode,
IN PVOID InputBuffer,
IN ULONG InputBufferLength,
OUT PVOID OutputBuffer,
IN ULONG OutputBufferLength
);
由于这两个函数包含了用户层和内核层通信的所有需要的数据,因此可以通过对这两个函数进行操作来实现驱动程序的模糊测试。根据实现模糊测试器实现的方法不同,可以分为以下两类:
-
IoControl MITM(Man-in-the-Middle) Fuzz -
IoControl Driver Fuzz
二
IoControl MITM(Man-in-the-Middle) Fuzz
下图是用户层与内核层实现通信的过程,可以看到,最后是通过NtDeviceIoControlFile来分发给相应驱动对象的派遣函数的,因此,可以通过对该函数进行HOOK操作。
三
IoControl Driver Fuzz
上述方法无法主动对驱动进行测试,只能被动地等待相应地通信发生,然后在对数据进行变异。想要主动地对相应派遣函数进行调用,就需要首先通过逆向地手段获得驱动的设备名称以及派遣函数对应的IoControlCode,接着对数据进行变异以后通过主动调用DeviceIoControl函数来完成测试。
根据IoControlCode中Method值的不同,数据变异策略有以下两种情况:
-
Method != METHOD_NEITHER:由于输入输出都有系统保护,因此修改地址没有意义,需要变异的数据只有:输入数据,输入长度,输出长度。 -
Method == NMETHOD_NEITHER:驱动中可能直接访问输入输出地址,而没有探测是否可写,因此需要变异的数据有:输入地址,输入数据,输出地址,输出长度。
四
IoctlFuzzer部分源码介绍
这个模糊测试器的源码在:https://github.com/Cr4sh/ioctlfuzzer/,该模糊测试器就是通过HOOK NtDeviceIoControlFile函数来构建的IoControl MITM Fuzzer,HOOK代码如下:
old_NtDeviceIoControlFile = (NT_DEVICE_IO_CONTROL_FILE)InterlockedExchange(
(PLONG)&SYSTEM_SERVICE(m_SDT_NtDeviceIoControlFile),
(LONG)new_NtDeviceIoControlFile
);
NTSTATUS NTAPI new_NtDeviceIoControlFile(
HANDLE FileHandle,
HANDLE Event,
PIO_APC_ROUTINE ApcRoutine,
PVOID ApcContext,
PIO_STATUS_BLOCK IoStatusBlock,
ULONG IoControlCode,
PVOID InputBuffer,
ULONG InputBufferLength,
PVOID OutputBuffer,
ULONG OutputBufferLength)
KPROCESSOR_MODE PrevMode = ExGetPreviousMode();
BOOLEAN bLogOutputBuffer = FALSE;
handle only user mode calls
if (PrevMode != KernelMode)
{
省略部分代码
}
内核模式,则调用原函数
NTSTATUS status = old_NtDeviceIoControlFile(
OutputBufferLength
return status;
}
POBJECT_NAME_INFORMATION DeviceObjectName = NULL, DriverObjectName = NULL;
PFILE_OBJECT pFileObject = NULL;
// get device object by handle
NTSTATUS ns = ObReferenceObjectByHandle(
FileHandle,
0, 0,
KernelMode,
(PVOID *)&pFileObject,
NULL
);
PVOID pDeviceObject = NULL;
// validate pointer to device object
if (MmIsAddressValid(pFileObject->DeviceObject))
{
pDeviceObject = pFileObject->DeviceObject;
}
else
{
goto end;
}
if (pDeviceObject == m_DeviceObject)
{
// don't handle requests to our driver
goto end;
}
// validate pointer to driver object
if (!MmIsAddressValid(pFileObject->DeviceObject->DriverObject))
{
goto end;
}
// get loader information entry for the driver module
PLDR_DATA_TABLE_ENTRY pModuleEntry = (PLDR_DATA_TABLE_ENTRY)
pFileObject->DeviceObject->DriverObject->DriverSection;
if (pModuleEntry == NULL)
{
goto end;
}
// validate pointer to loader's table and data from it
if (!MmIsAddressValid(pModuleEntry) ||
!ValidateUnicodeString(&pModuleEntry->FullDllName))
{
goto end;
}
if (InputBuffer != NULL && InputBufferLength > 0 &&
(m_FuzzOptions & FUZZ_OPT_FUZZ) && bProcessEvent)
{
// fuzz this request
Fuzz_NtDeviceIoControlFile(
PrevMode,
&DeviceObjectName->Name,
FileHandle,
IoStatusBlock,
IoControlCode,
InputBuffer,
InputBufferLength,
OutputBuffer,
OutputBufferLength
);
}
void Fuzz_NtDeviceIoControlFile(
KPROCESSOR_MODE PrevMode,
PUNICODE_STRING usDeviceName,
HANDLE FileHandle,
PIO_STATUS_BLOCK IoStatusBlock,
ULONG IoControlCode,
PVOID InputBuffer,
ULONG InputBufferLength,
PVOID OutputBuffer,
ULONG OutputBufferLength)
{
MAPPED_MDL InBuffMapped, OutBuffMapped;
KAPC_STATE ApcState;
BOOLEAN bInBuffMapped = FALSE, bOutBuffMapped = FALSE, bNeedToDetach = FALSE;
PVOID TmpInputBuffer = NULL, TmpOutputBuffer = NULL;
// save original parameters from the nt!NtDeviceIoControlFile()
FUZZ_THREAD_PARAMS ThreadParams;
ThreadParams.PrevMode = PrevMode;
ThreadParams.hFuzzHandle = FileHandle;
ThreadParams.cIoStatusBlock = IoStatusBlock;
ThreadParams.IoControlCode = IoControlCode;
ThreadParams.cInputBuffer = InputBuffer;
ThreadParams.cOutputBuffer = OutputBuffer;
ThreadParams.cInputBufferLength = InputBufferLength;
ThreadParams.cOutputBufferLength = OutputBufferLength;
if (m_FuzzOptions & FUZZ_OPT_FUZZ_FAIR)
{
// 省略部分代码
}
else
{
/**
* Sending IOCTL's from context of the original process.
*/
FuzzContinue_NtDeviceIoControlFile(
PrevMode,
ThreadParams.hFuzzHandle,
NULL, NULL, NULL,
ThreadParams.cIoStatusBlock,
IoControlCode,
ThreadParams.cInputBuffer,
ThreadParams.cInputBufferLength,
ThreadParams.cOutputBuffer,
ThreadParams.cOutputBufferLength
);
}
// 省略部分代码
}
if (m_FuzzProcess && m_FuzzThreadId && m_UserModeData)
{
if (InputBuffer != NULL && InputBufferLength > 0)
{
// 保存输入数据
if (TmpInputBuffer = M_ALLOC(InputBufferLength))
{
memcpy(TmpInputBuffer, InputBuffer, InputBufferLength);
}
}
if (OutputBuffer != NULL && OutputBufferLength > 0)
{
// 保存输出数据
if (TmpOutputBuffer = M_ALLOC(OutputBufferLength))
{
memcpy(TmpOutputBuffer, OutputBuffer, OutputBufferLength);
}
}
// 附加到模糊测试器进程
KeStackAttachProcess(m_FuzzProcess, &ApcState);
if (InputBuffer != NULL && InputBufferLength > 0)
{
// 在传递的参数中保存输入数据
if (bInBuffMapped = AllocateUserMemory(InputBufferLength, &InBuffMapped))
{
ThreadParams.cInputBuffer = InBuffMapped.MappedBuffer;
memcpy(ThreadParams.cInputBuffer, TmpInputBuffer, InputBufferLength);
}
}
if (OutputBuffer != NULL && OutputBufferLength > 0)
{
// 在传递的参数中保存输出数据
if (bOutBuffMapped = AllocateUserMemory(OutputBufferLength, &OutBuffMapped))
{
ThreadParams.cOutputBuffer = OutBuffMapped.MappedBuffer;
memcpy(ThreadParams.cOutputBuffer, TmpOutputBuffer, OutputBufferLength);
}
}
PETHREAD Thread = NULL;
KAPC Apc;
// 获取模糊测试器线程对象
ns = PsLookupThreadByThreadId(m_FuzzThreadId, &Thread);
if (NT_SUCCESS(ns))
{
// 初始化事件对象
KeInitializeEvent(
&ThreadParams.OperationComplete,
NotificationEvent,
FALSE
);
// 初始化APC对象
KeInitializeApc(
&Apc,
(PKTHREAD)Thread,
OriginalApcEnvironment,
ApcKernelRoutine,
NULL,
ApcNormalRoutine,
KernelMode,
&ThreadParams
);
// 插入APC队列
if (KeInsertQueueApc(&Apc, NULL, NULL, 0))
{
// waiting for APC execution
KeWaitForSingleObject(
&ThreadParams.OperationComplete,
Executive,
KernelMode,
FALSE, NULL
);
}
}
}
VOID ApcNormalRoutine(
PVOID NormalContext,
PVOID SystemArgument1,
PVOID SystemArgument2)
{
PFUZZ_THREAD_PARAMS ThreadParams = (PFUZZ_THREAD_PARAMS)NormalContext;
// continue fuzzing
FuzzContinue_NtDeviceIoControlFile(
ThreadParams->PrevMode,
ThreadParams->hFuzzHandle,
NULL, NULL, NULL,
ThreadParams->cIoStatusBlock,
ThreadParams->IoControlCode,
ThreadParams->cInputBuffer,
ThreadParams->cInputBufferLength,
ThreadParams->cOutputBuffer,
ThreadParams->cOutputBufferLength
);
KeSetEvent(&ThreadParams->OperationComplete, 0, FALSE);
}
VOID ApcKernelRoutine(
struct _KAPC *Apc,
PKNORMAL_ROUTINE *NormalRoutine,
PVOID *NormalContext,
PVOID *SystemArgument1,
PVOID *SystemArgument2)
{
/**
* This code exeuting in context of the fuzzer's process at APC_LEVEL.
* Nothing to do here...
*/
}
-
对输入数据按1字节或4字节为单位进行变异,其中按一字节进行变异的时候,也会变异输入数据的长度; -
对输出数据的地址进行变异; -
如果通信方式不是METHOD_BUFFERED,则会对输入输出的地址与长度进行变异。
void FuzzContinue_NtDeviceIoControlFile(
KPROCESSOR_MODE PrevMode,
HANDLE FileHandle,
HANDLE Event,
PIO_APC_ROUTINE ApcRoutine,
PVOID ApcContext,
PIO_STATUS_BLOCK IoStatusBlock,
ULONG IoControlCode,
PVOID InputBuffer,
ULONG InputBufferLength,
PVOID OutputBuffer,
ULONG OutputBufferLength)
{
// 分配输入数据长度的内存空间
PUCHAR NewBuff = (PUCHAR)M_ALLOC(InputBufferLength);
// 分配成功,则先对输入数据进行测试
if (NewBuff)
{
// 保存输入数据
RtlCopyMemory(NewBuff, InputBuffer, InputBufferLength);
// 对输入数据每个字节进行随机化
if (m_FuzzingType == FuzzingType_Random)
{
for (int i = 0; i < RANDOM_FUZZING_ITERATIONS; i++)
{
ULONG TmpInputLength = InputBufferLength;
// 对输入数据长度进行变异
if (m_FuzzOptions & FUZZ_OPT_FUZZ_SIZE)
{
TmpInputLength = getrand(1, TmpInputLength * 4);
}
// 对输入数据的每个字节进行变异
for (ULONG s = 0; s < InputBufferLength; s++)
{
*((PUCHAR)InputBuffer + s) = (UCHAR)getrand(1, 0xff);
}
// 调用原函数
NTSTATUS status = old_NtDeviceIoControlFile(
FileHandle,
Event, ApcRoutine,
ApcContext,
IoStatusBlock,
IoControlCode,
InputBuffer,
TmpInputLength,
OutputBuffer,
OutputBufferLength
);
}
}
else if (m_FuzzingType == FuzzingType_Dword)
{
// 以4字节为单位变异输入数据
// 对其输入数据长度
ULONG FuzzingLength = XALIGN_DOWN(InputBufferLength, sizeof(ULONG));
if (FuzzingLength <= DWORD_FUZZING_MAX_LENGTH && FuzzingLength >= sizeof(ULONG))
{
// fuzz each dword value in input buffer
for (ULONG i = 0; i < FuzzingLength; i += DWORD_FUZZING_DELTA)
{
for (ULONG i_v = 0; i_v < sizeof(m_DwordFuzzingConstants) / sizeof(ULONG); i_v++)
{
// 变异输入数据
ULONG OldBuffVal = *(PULONG)((PUCHAR)InputBuffer + i);
*(PULONG)((PUCHAR)InputBuffer + i) = m_DwordFuzzingConstants[i_v];
// 调用原函数
NTSTATUS status = old_NtDeviceIoControlFile(
FileHandle,
Event, ApcRoutine,
ApcContext,
IoStatusBlock,
IoControlCode,
InputBuffer,
InputBufferLength,
OutputBuffer,
OutputBufferLength
);
// 恢复原来的数据
*(PULONG)((PUCHAR)InputBuffer + i) = OldBuffVal;
}
}
}
}
// 恢复输入数据
RtlCopyMemory(InputBuffer, NewBuff, InputBufferLength);
ExFreePool(NewBuff);
}
// 对输出数据进行变异
if (OutputBufferLength > 0)
{
// 将输出数据地址改成用户空间的一个地址
PVOID TmpOutputBuffer = USER_BUFFER_ADDRESS;
// 调用原函数
NTSTATUS status = old_NtDeviceIoControlFile(
FileHandle,
Event, ApcRoutine,
ApcContext,
IoStatusBlock,
IoControlCode,
InputBuffer,
InputBufferLength,
TmpOutputBuffer, 0
);
// 将输出数据地址改成内核空间的一个地址
TmpOutputBuffer = KERNEL_BUFFER_ADDRESS;
// 调用原函数
status = old_NtDeviceIoControlFile(
FileHandle,
Event, ApcRoutine,
ApcContext,
IoStatusBlock,
IoControlCode,
InputBuffer,
InputBufferLength,
TmpOutputBuffer, 0
);
}
// 判断通信方式
ULONG Method = IoControlCode & 3;
if (Method != METHOD_BUFFERED)
{
// try to fuzz buffer addresses, if method is not buffered
for (int i = 0; i < BUFFERED_FUZZING_ITERATIONS; i++)
{
// 变异输入,输出地址与长度,其中地址变异为用户空间的地址
PVOID TmpInputBuffer = USER_BUFFER_ADDRESS;
PVOID TmpOutputBuffer = USER_BUFFER_ADDRESS;
ULONG TmpInputBufferLength = getrand(0, 0x100);
ULONG TmpOutputBufferLength = getrand(0, 0x100);
// 调用原函数
NTSTATUS status = old_NtDeviceIoControlFile(
FileHandle,
Event, ApcRoutine,
ApcContext,
IoStatusBlock,
IoControlCode,
TmpInputBuffer,
TmpInputBufferLength,
TmpOutputBuffer,
TmpOutputBufferLength
);
}
for (int i = 0; i < BUFFERED_FUZZING_ITERATIONS; i++)
{
// 变异输入,输出地址与长度,其中地址变异为内核空间的地址
PVOID TmpInputBuffer = KERNEL_BUFFER_ADDRESS;
PVOID TmpOutputBuffer = KERNEL_BUFFER_ADDRESS;
ULONG TmpInputBufferLength = getrand(0, 0x100);
ULONG TmpOutputBufferLength = getrand(0, 0x100);
// 调用原函数
NTSTATUS status = old_NtDeviceIoControlFile(
FileHandle,
Event,
ApcRoutine,
ApcContext,
IoStatusBlock,
IoControlCode,
TmpInputBuffer,
TmpInputBufferLength,
TmpOutputBuffer,
TmpOutputBufferLength
);
}
}
}
// constants for dword fuzzing
ULONG m_DwordFuzzingConstants[] =
{
0x00000000,
0x00001000,
0xFFFF0000,
0xFFFFFFFF
};
五
IoctlBf部分源码
这个模糊测试器源码在:https://github.com/koutto/ioctlbf,该模糊测试器则是IoControl Driver Fuzzer。因此,该模糊测试器会首先获取驱动的合法IoControlCode,然后在对这些合法的IoControlCode进行测试。
typedef struct IOCTLlist_ {
DWORD IOCTL; // 保存的IoControlCode
DWORD errorCode;
size_t minBufferLength; // 输入输出数据最小长度
size_t maxBufferLength; // 输入输出数据最大长度
struct IOCTLlist_ *previous; // 指向上一个IOCTLlist_结构,用来连接所有的合法IoControlCode
} IOCTLlist, *pIOCTLlist;
-
指定输入输出地址为NULL,调用DeviceIoControl。如果函数返回值为0,且GetLastError()的结果为ERROR_ACCESS_DENIED或ERROR_NOT_SUPPORT中的一个,则该IoControlCode不合法,结束本次循环; -
判断是否指定了filteralwaysok标志,如果指定了,则测试输入输出的数据是否大于4,如果是则结束本次循环; -
将输入输出长度从0到MAX_BUFSIZE一一测试,来查找输入输出数据最小长度,成功查找,则将其作为一个合法的IoControlCode,加入listIoctls中; -
从输入输出数据的最小长度+1开始测试,获取输入输出数据的最大长度。
for(currentIoctl = beginIoctl; currentIoctl<=endIoctl; currentIoctl++) {
// 发送IoControl
status = DeviceIoControl(deviceHandle,
currentIoctl,
NULL,
0,
NULL,
0,
&nbBytes,
NULL);
// 如果函数调用失败
if(status == 0) {
errorCode = GetLastError();
// 如果GetLastError的值为ERROR_ACCESS_DENIED或ERROR_NOT_SUPPORTED
// 则没有此IoControlCode,结束本次循环
if(errorCode == ERROR_ACCESS_DENIED ||
errorCode == ERROR_NOT_SUPPORTED)
{
continue;
}
}
// 是否指定了filteralwaysok标志
if(filteralwaysok) {
// 指定输入输出缓冲区为最大长度,发送IoControlCode
status = DeviceIoControl(deviceHandle,
currentIoctl,
&bufInput,
MAX_BUFSIZE,
&bufOutput,
MAX_BUFSIZE,
&nbBytes,
NULL);
if(status != 0) {
cont = TRUE;
status = 1;
for(j = 0; j < 4 && status != 0 && cont; j++)
{
status = DeviceIoControl(deviceHandle,
currentIoctl,
&bufInput,
j,
&bufOutput,
j,
&nbBytes,
NULL);
}
if(j == 4) {
// 输入输出长度均>4 则结束本次循环
continue;
}
}
}
// 查找最小输入输出长度
cont = TRUE;
for(j = 0; j < MAX_BUFSIZE && cont; j++) {
status = DeviceIoControl(deviceHandle,
currentIoctl,
&bufInput,
j,
&bufOutput,
j,
&nbBytes,
NULL);
if(status != 0) {
// 如果发送成功,则将其加入到listIoctls链表
listIoctls = addIoctlList(listIoctls,
currentIoctl,
0,
j,
MAX_BUFSIZE);
cont = FALSE;
i++;
}
}
// 找到了最小数据长度,接下来查找最长数据产犊
if(!cont) {
cont = TRUE;
// 发送限制的最长的数据长度
status = DeviceIoControl(deviceHandle,
currentIoctl,
&bufInput,
MAX_BUFSIZE,
&bufOutput,
MAX_BUFSIZE,
&nbBytes,
NULL);
if(status != 0)
{
// 如果发送成功,则指定最长数据长度
listIoctls->maxBufferLength = MAX_BUFSIZE;
cont = FALSE;
}
// 查找最长数据长度
for(j = listIoctls->minBufferLength + 1; j < MAX_BUFSIZE && cont; j++)
{
// 发送IoControlCode
status = DeviceIoControl(deviceHandle,
currentIoctl,
&bufInput,
j,
&bufOutput,
j,
&nbBytes,
NULL);
// 发送成功,则更新最长数据长度
if(status == 0) {
listIoctls->maxBufferLength = j - 1;
cont = FALSE;
}
}
if(cont)
{
listIoctls->maxBufferLength = MAX_BUFSIZE;
}
}
}
-
如果IoControlCode的method不为METHOD_BUFFERED,则将输入输出数据地址指定为整型数组invalidAddress中保存的不合法的地址完成测试; -
将输入数据初始化为0x41,并指定不同的数据长度测试是否存在缓冲区溢出漏洞; -
以4字节为单位,变异输入数据挖出测试; -
随机化输入数据,完成测试。
while(1) {
// 从链表中获取IoControl,choice由用户输入
posListIoctls = getIoctlListElement(listIoctls, choice);
// 如果method != METHOD_BUFFERED,则将输入输出数据地址赋值为非法的地址进行测试
if((posListIoctls->IOCTL & 0x00000003) != 0)
{
cont = TRUE;
for(i = 0; cont && i < INVALID_BUF_ADDR_ATTEMPTS; i++)
{
for(j = 0; cont && j < (sizeof(invalidAddresses) / 4); j++)
{
// 随机化输入输出长度
randomLength = getrand(posListIoctls->minBufferLength,
posListIoctls->maxBufferLength);
// 将输入输出地址指定为不合法的地址
status = DeviceIoControl(deviceHandle,
posListIoctls->IOCTL,
(LPVOID)invalidAddresses[j],
randomLength,
(LPVOID)invalidAddresses[j],
randomLength,
&nbBytes,
NULL);
}
}
}
// 测试是否存在缓冲区溢出漏洞
cont = TRUE;
// 初始化输入数据
memset(bufInput, 0x41, 0x10000);
// 指定不同输入数据长度,调用函数完成测试
for(i = 0x100; i <= 0x10000; i += 0x100)
{
status = DeviceIoControl(deviceHandle,
posListIoctls->IOCTL,
&bufInput,
i,
&bufOutput,
i,
&nbBytes,
NULL);
}
// 以4字节为单位,变异输入数据
cont = TRUE;
if(SetConsoleCtrlHandler((PHANDLER_ROUTINE) CtrlHandler, TRUE))
{
// 初始化输入数据
memset(bufInput, 0x00, MAX_BUFSIZE);
// 以4字节为单位,将输入数据修改为FuzzConstants整型数组中的某一元素
for(i = 0; cont && i < posListIoctls->maxBufferLength; i = i + 4)
{
// 随机化输入数据
for(j = 0; cont && j < posListIoctls->maxBufferLength; j++)
{
bufInput[j] = (BYTE)getrand(0x00, 0xff);
}
for(j = 0; cont && j < (sizeof(FuzzConstants) / 4); j++)
{
// 指定将输入数据变异为FuzzConstants中的某一元素
fuzzData = FuzzConstants[j];
bufInput[i] = fuzzData & 0x000000ff;
bufInput[i + 1] = (fuzzData & 0x0000ff00) >> 8;
bufInput[i + 2] = (fuzzData & 0x00ff0000) >> 16;
bufInput[i + 3] = (fuzzData & 0xff000000) >> 24;
// 调用函数,开始测试
status = DeviceIoControl(deviceHandle,
posListIoctls->IOCTL,
&bufInput,
posListIoctls->maxBufferLength,
&bufOutput,
posListIoctls->maxBufferLength,
&nbBytes,
NULL);
}
// 将输入数据随机赋值为FuzzConstants整型数组中的元素
while(cont)
{
// 随机选取输入数据长度
randomLength = getrand(posListIoctls->minBufferLength,
posListIoctls->maxBufferLength);
// 初始化输入数据
memset(bufInput, 0x00, MAX_BUFSIZE);
// 为输入数据赋值
for(i = 0; i < randomLength; i = i + 4)
{
// 从FuzzConstants随机选择元素赋值输入数据
fuzzData = FuzzConstants[getrand(0, (sizeof(FuzzConstants) / 4) - 1)];
bufInput[i] = fuzzData & 0x000000ff;
bufInput[i + 1] = (fuzzData & 0x0000ff00) >> 8;
bufInput[i + 2] = (fuzzData & 0x00ff0000) >> 16;
bufInput[i + 3] = (fuzzData & 0xff000000) >> 24;
}
// 调用函数完成测试
status = DeviceIoControl(deviceHandle,
posListIoctls->IOCTL,
&bufInput,
randomLength,
&bufOutput,
randomLength,
&nbBytes,
NULL);
}
}
// 将输入数据随机初始完成测试
cont = TRUE;
if(SetConsoleCtrlHandler((PHANDLER_ROUTINE) CtrlHandler, TRUE))
{
while(cont)
{
// 随机选取输入输出数据长度
randomLength = getrand(posListIoctls->minBufferLength,
posListIoctls->maxBufferLength);
// 随机化输入数据
memset(bufInput, 0x00, MAX_BUFSIZE);
for(i = 0; i < randomLength; i++)
{
bufInput[i] = (BYTE)getrand(0x00, 0xff);
}
// 调用函数完成测试
status = DeviceIoControl(deviceHandle,
posListIoctls->IOCTL,
&bufInput,
randomLength,
&bufOutput,
randomLength,
&nbBytes,
NULL);
}
}
}
Junk data used for fuzzing -------------------------------------------------
CHAR asciiString10[0x10];
CHAR asciiString100[0x100];
CHAR asciiString1000[0x1000];
WCHAR unicodeString10[0x10];
WCHAR unicodeString100[0x100];
WCHAR unicodeString1000[0x1000];
DWORD tableDwords[0x100];
DWORD FuzzConstants[] = { 0x00000000, 0x00000001, 0x00000004, 0xFFFFFFFF,
0xFFFF0000, 0xFFFFFFFE, 0xFFFFFFF0,
0x70000000, 0x7FFEFFFF, 0x7FFFFFFF,
(DWORD)asciiString1000,
(DWORD)unicodeString1000,
};
DWORD invalidAddresses[] = { 0xFFFF0000, 0x00001000 };
看雪ID:1900
https://bbs.pediy.com/user-home-835440.htm
# 往期推荐
球分享
球点赞
球在看
点击“阅读原文”,了解更多!
原文始发于微信公众号(看雪学苑):Windows内核模糊测试之IoControl Fuzz