在地址0上分配内存

在 NULL 地址上分配内存看似是不可行的 ,因为对于内存分配函数  

NTSTATUS ZwAllocateVirtualMemory(
  _In_     HANDLE ProcessHandle,
  _Inout_  PVOID *BaseAddress,
  _In_     ULONG_PTR ZeroBits,
  _Inout_  PSIZE_T RegionSize,
  _In_     ULONG AllocationType,
  _In_     ULONG Protect
);

你将 BaseAddress 指向 0 传入,这个函数会认为你是想在任意可用的地址上分配内存,而不是0 (系统不会把0地址内存当中可用到 )。绕过的方法就是指定 AllocationType 为MEM_TOP_DOWN 也就是从上向下分配内存 ,此时指定 BaseAddress 为一个 低地址,例如 1,同时指定分配内存的大小 大于这个值 ,例如 8192(一个内存页),这样分配成功后 地址范围就是 0xFFFFE001 (-8191) 到 1 把 0 地址包含在内了,此时再去尝试向 NULL 指针执行的地址写数据,会发现程序不会异常了 。

    这个说到底是微软实现该函数的时候没有考虑全面导致一些安全措施被绕过 (0地址分配内存,应用层可以在高地址(内核空间)分配内存),在最新的系统补丁中微软已经修复了这个漏洞。

    该技巧主要利用在漏洞的利用上,例如使用 null 指针,或者函数失败返回负数,程序没有检查返回值,把这个负数当中指针来使用。这些情况可以使用这个技巧来利用漏洞。

 测试代码

// testnull.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include <Windows.h>

typedef NTSTATUS ( __stdcall *P_ZwAllocateVirtualMemory)(
	_In_     HANDLE ProcessHandle,
	_Inout_  PVOID *BaseAddress,
	_In_     ULONG_PTR ZeroBits,
	_Inout_  PSIZE_T RegionSize,
	_In_     ULONG AllocationType,
	_In_     ULONG Protect
	);


int _tmain(int argc, _TCHAR* argv[])
{
	HMODULE hnt = LoadLibraryA("ntdll.dll");
	P_ZwAllocateVirtualMemory pfZwAllocateVirtualMemory = (P_ZwAllocateVirtualMemory)GetProcAddress(hnt, "ZwAllocateVirtualMemory");
	ULONG base = 1;
	PVOID *p = (PVOID *)&base;
	SIZE_T s = 8192;
	ULONG eax = pfZwAllocateVirtualMemory((HANDLE)-1, p, 0, &s, MEM_COMMIT | MEM_RESERVE | MEM_TOP_DOWN, PAGE_EXECUTE_READWRITE);
	if (eax != 0)
	{
		printf("error %08x ",eax);
	}

	char *c = 0;
	*c = 'x'; //不会异常
	return 0;
}


转载于:https://my.oschina.net/sincoder/blog/336287

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值