当R3与R0在进行通信的时候,采用了第三种通信方式(METHOD_NEITHER)直接将R3地址下传到内核,并在内核中,将一个R3地址中的任意数据(固定数据),赋值给R3的任意一个地址,那么就会造成严重的内核任意地址写入任意数据(固定数据)。因为攻击者完全可以在R3地址里构造一个任意的数据和设置一个任意的地址。
比如下面的内核代码,在该派遣分发函数中,使用了第三种通信方式(METHOD_NEITHER),直接将R3的内存地址传递到内核中,并在内核中通过:
*(ULONG *)UserBuffer = *(ULONG *)Type3InputBuffer;
NTSTATUS DrvDispatch(IN PDEVICE_OBJECT driverObject,IN PIRP
pIrp)
{
PIO_STACK_LOCATION pIrpStack;//当前的pIrp栈
PVOID
Type3InputBuffer;//用户态输入地址
PVOID
UserBuffer;//用户态输出地址
ULONG
inputBufferLength;//输入缓冲区的大小
ULONG
outputBufferLength;//输出缓冲区的大小
ULONG
ioControlCode;//DeviceIoControl的控制号
PIO_STATUS_BLOCK IoStatus;//pIrp的IO状态指针
NTSTATUS
ntStatus=STATUS_SUCCESS;//函数返回值
//获取数据
pIrpStack =
IoGetCurrentIrpStackLocation(pIrp);
Type3InputBuffer = pIrpStack->Parameters.DeviceIoControl.Type3InputBuffer;
UserBuffer
= pIrp->UserBuffer;
inputBufferLength = pIrpStack->Parameters.DeviceIoControl.InputBufferLength;
outputBufferLength = pIrpStack->Parameters.DeviceIoControl.OutputBufferLength;
ioControlCode = pIrpStack->Parameters.DeviceIoControl.IoControlCode;
IoStatus=&pIrp->IoStatus;
IoStatus->Status = STATUS_SUCCESS;// Assume success
IoStatus->Information = 0;// Assume nothing returned
//根据
ioControlCode 完成对应的任务
switch(ioControlCode)
{
case
IOCTL_EXPLOIT_ME:
if ( inputBufferLength >= 4 && outputBufferLength >= 4 )
{
*(ULONG *)UserBuffer = *(ULONG *)Type3InputBuffer;
IoStatus->Information = sizeof(ULONG);
}
break;
}
//返回
IoStatus->Status = ntStatus;
IoCompleteRequest(pIrp,IO_NO_INCREMENT);
return
ntStatus;
}
任意地址:R3传入一个内核地址(比如某个表中的函数地址,一般要很少被调用的函数)
任意数据:想办法将该内核地址的值设置为0
在R3里分配一个0地址空间(调用ZwAllocateVirtualMemory),并将R0 shellcode拷贝到此内存空间
然后,利用上面代码的漏洞,在R0里完成把这个R0地址(任意地址)设置为0(任意或固定数据),完成设置之后,然后通过调用函数,促发内核执行该内核地址代码,但该地址已经指向了0地址的shell code,因此,造成了恶意代码的执行。
shellcode代码可以用来:
1,提升进程的权限到system进程
2,恢复内核hook和inlinehook
3,添加调用门,中断门等
Copyright 2011-2020 © MallocFree. All rights reserved.