在地址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;
}
时间: 2024-11-05 21:35:59

在地址0上分配内存的相关文章

了解变量如何在内存上分配存储(一)

1.前言 在编写代码中,我们经常回调用这样或那样的方法(函数),但是我们真的了解各种参数类型在内存上市如何分配的么?不见得,至少在这之前我就不是很了解.我们也许认为这只是一个很小的问题,觉得知道方法是做什么的.会调用方法就行,所以就忽略了这一点.下面就了解一下方法中的参数是如何在内存上分配的.如有不妥之处,还请各位大牛指点. 2.值类型与引用类型的分配 一般来说,值类型是分配在栈中,而引用类型则在堆中分配存储单元.栈在编译的时候就分配好内存空间,在代码中有栈的明确定义,而堆是程序运行中动态分配的

Dalvik虚拟机为新创建对象分配内存的过程分析

在前面一文中,我们分析了Dalvik虚拟机创建Java堆的过程.有了Java堆之后,Dalvik虚拟机就可以在上面为对象分配内存了.在Java堆为对象分配内存需要解决内存碎片和内存不足两个问题.要解决内存碎片问题,就要找到一块大小最合适的空闲内存分配给对象使用.而内存不足有可能是内存配额用完引起的,也有可能是垃圾没有及时回收引起的,要区别对待.本文就详细分析Dalvik虚拟机是如何解决这些问题的. 老罗的新浪微博:http://weibo.com/shengyangluo,欢迎关注! 内存碎片问

ART运行时为新创建对象分配内存的过程分析

ART运行时和Dalvik虚拟机一样,在堆上为对象分配内存时都要解决内存碎片和内存不足问题.内存碎片问题可以使用dlmalloc技术解决.内存不足问题则通过垃圾回收和在允许范围内增长堆大小解决.由于垃圾回收会影响程序,因此ART运行时采用力度从小到大的进垃圾回收策略.一旦力度小的垃圾回收执行过后能满足分配要求,那就不需要进行力度大的垃圾回收了.本文就详细分析ART运行时在堆上为对象分配内存的过程. 本博参加博客之星评选,求投票:点击投票 老罗的新浪微博:http://weibo.com/shen

重新分配内存

realloc()函数可以重用前面通过malloc()huocalloc()(或realloc())分配的内存.函数需要两个参数:一个是指针,它包含前面调用malloc().calloc()或realloc()返回的地址,另一个是要分配的新内存的字节数. realloc()函数释放第一个指针参数引用的之前分配的内存,然后重新分配该内存区域,以满足第二个参数指定的新要求.显然,第二个参数的值不应超过以前分配的字节数.否则,新分配的内存将与以前分配的内存区域大小相同. 函数简介 原型: extern

8、Cocos2dx 3.0游戏开发找小三之3.0版本的内存管理

重开发者的劳动成果,转载的时候请务必注明出处:http://blog.csdn.net/haomengzhu/article/details/27693365 复杂的内存管理 移动设备上的硬件资源十分有限,内存尤为宝贵,开发者必须十分慎重地利用内存,避免不必要的消耗,更要防止内存泄漏. 基于 Cocos2d-iPhone 的 Objective-C风格的内存管理是 Cocos2d-x 的一个特色. 把 Objective-C 的内存管理方式引入 C++,使得游戏开发的内存管理难度下降了个层次.

十、逃逸分析和栈上分配

Java堆区已经不再是对象实例分配的唯一空间,可以在堆区之外分配内存以提升效率降低频率,逃逸分析即是如此. 什么是逃逸分析? 例如: 一个成员方法的内部实例化了一个对象,如果这个对象被方法外的引用指向了,那么就发生了逃逸现象.JVM在内存分配的时候会分析其是否发生逃逸,如果未发生逃逸的,那么就直接在栈上分配内存空间,其生命周期和线程相同.(也称之为"栈上分配") 原文地址:https://www.cnblogs.com/lay2017/p/8157760.html

垃圾回收GC:.Net自动内存管理 上(一)内存分配

垃圾回收GC:.Net自动内存管理 上(一)内存分配 前言 .Net下的GC完全解决了开发者跟踪内存使用以及控制释放内存的窘态.然而,你或许想要理解GC是怎么工作的.此系列文章中将会解释内存资源是怎么被合理分配及管理的,并包含非常详细的内在算法描述.同时,还将讨论GC的内存清理流程及什么时清理,怎么样强制清理. 引子 为你的应用程序实现合理的资源管理是一件困难的,乏味的工作.这可能会把你的注意力从你当前正在解决的实际问题中转移到它身上.那么,如果有一个现有的机制为开发者管理令人厌恶的内存管理,会

垃圾回收GC:.Net自己主动内存管理 上(一)内存分配

垃圾回收GC:.Net自己主动内存管理 上(一)内存分配 垃圾回收GC:.Net自己主动内存管理 上(一)内存分配 垃圾回收GC:.Net自己主动内存管理 上(二)内存算法 垃圾回收GC:.Net自己主动内存管理 上(三)终结器 前言 .Net下的GC全然攻克了开发人员跟踪内存使用以及控制释放内存的窘态.然而,你也许想要理解GC是怎么工作的.此系列文章中将会解释内存资源是怎么被合理分配及管理的,并包括很具体的内在算法描写叙述. 同一时候,还将讨论GC的内存清理流程及什么时清理.怎么样强制清理.

浅析Java的jvm上的内存位置的分配

浅析Java的jvm上的内存位置的分配 1.Java的内存区域简介 1>程序计数器: 一小块的内存空间,每个线程都有一个独立的计数器,线程私有;作用:作为当前线程代码行行号指示器,这个值可以选取下一条需要执行的字节码指令,例如分支,循环等,每创建一根线程会相应的产生一个程序计数器 2>栈 线程私有,用于存放局部变量,保存基本数据类型的值,操作数栈(保存着计算过程的中间结果),动态链接,方法入口和出口等信息:局部变量表中保存着函数的参数和局部变量,当调用结束以后,栈帧销毁,局部变量表也随之销毁