欢迎来到 嗅灵易学

零基础也能上手的脚本技术课,一对一答疑带你入门

[翻译]Windows exploit开发系列教程第十四部分:内核利用程序之整数溢出

[翻译]Windows exploit开发系列教程第十四部分:内核利用程序之整数溢出

点击查看原文

Windows exploit开发系列教程第十四部分:内核利用程序之整数溢出

欢迎回到Windows exp开发系列教程的第十四部分。今天我们来完成另一个基于HEVD漏洞驱动程序的exp。本次我们看一看整数溢出,这不包括GS栈溢出(后面会涉及到)和类型混淆(太简单了,exp在 GitHub),这将是最后一个简单的漏洞利用!调试环境的按照请参考本系列的第十部分。

  • HackSysExtremeVulnerableDriver (hacksysteam) - here

侦查挑战

让我们看看相关漏洞函数(here)。

NTSTATUS TriggerIntegerOverflow(IN PVOID UserBuffer, IN SIZE_T Size) {

    ULONG Count = 0;

    NTSTATUS Status = STATUS_SUCCESS;

    ULONG BufferTerminator = 0xBAD0B0B0;

    ULONG KernelBuffer[BUFFER_SIZE] = {0};

    SIZE_T TerminatorSize = sizeof(BufferTerminator);

    PAGED_CODE();

    __try {

        // Verify if the buffer resides in user mode

        ProbeForRead(UserBuffer, sizeof(KernelBuffer), (ULONG)__alignof(KernelBuffer));

        DbgPrint("[+] UserBuffer: 0x%p\n", UserBuffer);

        DbgPrint("[+] UserBuffer Size: 0x%X\n", Size);

        DbgPrint("[+] KernelBuffer: 0x%p\n", &KernelBuffer);

        DbgPrint("[+] KernelBuffer Size: 0x%X\n", sizeof(KernelBuffer));

#ifdef SECURE

        // Secure Note: This is secure because the developer is not doing any arithmetic

        // on the user supplied value. Instead, the developer is subtracting the size of

        // ULONG i.e. 4 on x86 from the size of KernelBuffer. Hence, integer overflow will

        // not occur and this check will not fail

        if (Size > (sizeof(KernelBuffer) - TerminatorSize)) {

            DbgPrint("[-] Invalid UserBuffer Size: 0x%X\n", Size);

            Status = STATUS_INVALID_BUFFER_SIZE;

            return Status;

        }

#else

        DbgPrint("[+] Triggering Integer Overflow\n");

        // Vulnerability Note: This is a vanilla Integer Overflow vulnerability because if

        // 'Size' is 0xFFFFFFFF and we do an addition with size of ULONG i.e. 4 on x86, the

        // integer will wrap down and will finally cause this check to fail

        if ((Size + TerminatorSize) > sizeof(KernelBuffer)) {

            DbgPrint("[-] Invalid UserBuffer Size: 0x%X\n", Size);

            Status = STATUS_INVALID_BUFFER_SIZE;

            return Status;

        }

#endif

        // Perform the copy operation

        while (Count < (Size / sizeof(ULONG))) {

            if (*(PULONG)UserBuffer != BufferTerminator) {

                KernelBuffer[Count] = *(PULONG)UserBuffer;

                UserBuffer = (PULONG)UserBuffer + 1;

                Count++;

            }

            else {

                break;

            }

        }

    }

    __except (EXCEPTION_EXECUTE_HANDLER) {

        Status = GetExceptionCode();

        DbgPrint("[-] Exception Code: 0x%X\n", Status);

    }

    return Status;

}

驱动函数比较了用户提供的缓冲区长度和驱动分配缓冲区的长度。然而在有漏洞的版本中,这一检查的执行是这样的:

BufferTerminator = 0xBAD0B0B0

InputBuffer.Size + BufferTerminator.Size > KernelAllocatedBuffer.Size

很明显的bug,terminator的大小是4字节,所以如果我们通过DeviceIoCtrl给驱动提供一个大小在0xfffffffc到0xffffffff的缓冲区的话,整数会溢出并借此通过了这一检查!我们可以在PowerShell控制台中做相似的操作来展示这一问题。

PS C:\Users\b33f> 0xfffffffc+4

0

PS C:\Users\b33f> 0xffffffff+4

3

该函数的IOCTL码为0x222027。可以参考本系列教程的第十和第十一部分来查看IOCTL码是如何获取的。快速跳入IDA,看看这个函数。下图中我们可以看到函数的开头存在着错误的长度检查。

注意:上传附件及图片大小不得大于30M。

⚠️ 版权声明:
本博客所有内容(含教程、源码、工具)仅供个人技术学习与研究交流使用,严禁商用、倒卖、二次分发及非法用途
未经作者书面授权,任何组织或个人不得转载、复制或用于其他平台,违者将追究相关责任。

0 0 0 举报
复制成功