欢迎来到 嗅灵易学

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

[翻译]Windows exploit开发系列教程第十二部分:内核利用程序之空指针引用

[翻译]Windows exploit开发系列教程第十二部分:内核利用程序之空指针引用

点击查看原文

Windows exploit开发系列教程第十二部分:内核利用程序之空指针引用

欢迎回到Windows exp开发系列教程的第12部分。今天我们来快速编写一个基于HEVD漏洞驱动的空指针引用exp。环境部署的更多细节请参考第十部分。让我们开始吧!

  • HackSysExtremeVulnerableDriver (hacksysteam) - here
  • Small Hax to avoid crashing ur prog - here

侦查挑战

先看一看有漏洞的函数部分(here).。

NTSTATUS TriggerNullPointerDereference(IN PVOID UserBuffer) {

    ULONG UserValue = 0;

    ULONG MagicValue = 0xBAD0B0B0;

    NTSTATUS Status = STATUS_SUCCESS;

    PNULL_POINTER_DEREFERENCE NullPointerDereference = NULL;

    PAGED_CODE();

    __try {

        // Verify if the buffer resides in user mode

        ProbeForRead(UserBuffer,

                     sizeof(NULL_POINTER_DEREFERENCE),

                     (ULONG)__alignof(NULL_POINTER_DEREFERENCE));

        // Allocate Pool chunk

        NullPointerDereference = (PNULL_POINTER_DEREFERENCE)

                                  ExAllocatePoolWithTag(NonPagedPool,

                                                        sizeof(NULL_POINTER_DEREFERENCE),

                                                        (ULONG)POOL_TAG);

        if (!NullPointerDereference) {

            // Unable to allocate Pool chunk

            DbgPrint("[-] Unable to allocate Pool chunk\n");

            Status = STATUS_NO_MEMORY;

            return Status;

        }

        else {

            DbgPrint("[+] Pool Tag: %s\n", STRINGIFY(POOL_TAG));

            DbgPrint("[+] Pool Type: %s\n", STRINGIFY(NonPagedPool));

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

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

        }

        // Get the value from user mode

        UserValue = *(PULONG)UserBuffer;

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

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

        // Validate the magic value

        if (UserValue == MagicValue) {

            NullPointerDereference->Value = UserValue;

            NullPointerDereference->Callback = &NullPointerDereferenceObjectCallback;

            DbgPrint("[+] NullPointerDereference->Value: 0x%p\n", NullPointerDereference->Value);

            DbgPrint("[+] NullPointerDereference->Callback: 0x%p\n", NullPointerDereference->Callback);

        }

        else {

            DbgPrint("[+] Freeing NullPointerDereference Object\n");

            DbgPrint("[+] Pool Tag: %s\n", STRINGIFY(POOL_TAG));

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

            // Free the allocated Pool chunk

            ExFreePoolWithTag((PVOID)NullPointerDereference, (ULONG)POOL_TAG);

            // Set to NULL to avoid dangling pointer

            NullPointerDereference = NULL;

        }

#ifdef SECURE

        // Secure Note: This is secure because the developer is checking if

        // 'NullPointerDereference' is not NULL before calling the callback function

        if (NullPointerDereference) {

            NullPointerDereference->Callback();

        }

#else

        DbgPrint("[+] Triggering Null Pointer Dereference\n");

        // Vulnerability Note: This is a vanilla Null Pointer Dereference vulnerability

        // because the developer is not validating if 'NullPointerDereference' is NULL

        // before calling the callback function

        NullPointerDereference->Callback();

#endif

    }

    __except (EXCEPTION_EXECUTE_HANDLER) {

        Status = GetExceptionCode();

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

    }

    return Status;

}

可以看到这里有一个魔数的检查。如果检查通过则打印该值和回调函数的地址(这是正常的执行流),反之则释放池内存,将指针置空。到这里都没有什么问题,但是此后,在有漏洞的版本中,该驱动程序仅仅简单的调用了回调函数而没有检查该回调函数此前是否被置空了。

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

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

0 0 0 举报
复制成功