首页
社区
课程
招聘
[原创]HEVD内核漏洞学习(5)空指针解引用
发表于: 2020-11-1 22:01 6319

[原创]HEVD内核漏洞学习(5)空指针解引用

2020-11-1 22:01
6319

第五部分了 空指针解引用是程序中常见的一类动态内存错误 啊 还是直接开始正文吧

当指针设置为NULL时 试图通过空指针对数据进行访问 导致程序运行错误 即指针为空却被当作地址去引用时 就会产生漏洞

这个函数首先ExAllocatePoolWithTag申请内存 在用完内存后 将内存置为NULL 在漏洞版本下 未检查刚才申请的内存是否为NULL 就直接引用指向内存地址

TriggerNullPointerDereference

先下断点

断下后发现第二个值还没有被覆盖为shellcode的地址

单步指向后发现已被覆盖

即我们将NullPointerDereference的第二个值(+0x4)控制为shellcode的地址即可 使用NtAllocateVirtualMemory分配0页内存将第二个值(+0x4)控制为shellcode的地址

在common.c中分配0页内存

利用成功

啊这个比上个好理解多了 空指针解引用导致的问题在这个漏洞中也很好利用 在刚开始了解的时候只知道能引发崩溃 不知道如何去利用 后面学习完了之后也就懂了利用的思路了 然后去看了看小刀师傅复现的一个内核漏洞 完全就不一样了哈哈哈

这里传送门

 
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(UCHAR));
 
        //
        // 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;
}
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(UCHAR));
 
        //
        // 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

[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

最后于 2020-11-4 21:09 被Ring3编辑 ,原因:
收藏
免费 1
支持
分享
最新回复 (3)
雪    币: 7
活跃值: (4331)
能力值: ( LV9,RANK:270 )
在线值:
发帖
回帖
粉丝
2
6
2020-11-1 22:55
0
雪    币: 550
活跃值: (2995)
能力值: ( LV8,RANK:130 )
在线值:
发帖
回帖
粉丝
3
0x2l 6
你漏了一篇 淡了~
2020-11-1 23:05
0
雪    币: 7
活跃值: (4331)
能力值: ( LV9,RANK:270 )
在线值:
发帖
回帖
粉丝
4
Ring3 你漏了一篇 淡了~
确实
2020-11-1 23:10
0
游客
登录 | 注册 方可回帖
返回
//