恶意软件开发——内存相关API
一、前言
Windows操作系统的内存有三种属性,分别为:可读、可写、可执行,并且操作系统将每个进程的内存都隔离开来,当进程运行时,创建一个虚拟的内存空间,系统的内存管理器将虚拟内存空间映射到物理内存上,所以每个进程的内存都是等大的。
操作系统给予每个进程申请内存的权利,使用不同的API,申请的内存具有不同的涵义。
在进程申请时,需要声明这块内存的基本信息:申请内存大小、申请内存起始内存基址、申请内存属性、申请内存对外的权限等。
二、相关API介绍
1.VirtualAlloc
该函数的功能是在调用进程的虚地址空间,预定或者提交一部分页,如果用于内存分配的话,并且分配类型未指定MEM_RESET,则系统将自动设置为0;其函数原型:
LPVOID VirtualAlloc{
LPVOID lpAddress, // 要分配的内存区域的地址
DWORD dwSize, // 分配的大小
DWORD flAllocationType, // 分配的类型
DWORD flProtect // 该内存的初始保护属性
};
参数说明:
1.LPVOID lpAddress, 分配内存区域的地址。当你使用VirtualAlloc来提交一块以前保留的内存块的时候,lpAddress参数可以用来识别以前保留的内存块。如果这个参数是NULL,系统将会决定分配内存区域的位置,并且按64-KB向上取整(roundup)。
2.SIZE_T dwSize, 要分配或者保留的区域的大小。这个参数以字节为单位,而不是页,系统会根据这个大小一直分配到下页的边界DWORD
3.flAllocationType, 分配类型 ,你可以指定或者合并以下标志:MEM_COMMIT,MEM_RESERVE和MEM_TOP_DOWN。
4.DWORD flProtect 指定了被分配区域的访问保护方式:PAGE_EXECUTE_READ,PAGE_EXECUTE_READWRITE
小结:
VirtualAlloc可以通过并行多次调用提交一个区域的部分或全部来保留一个大的内存区域。多重调用提交同一块区域不会引起失败。这使得一个应用程 序保留内存后可以随意提交将被写的页。当这种方式不在有效的时候,它会释放应用程序通过检测被保留页的状态看它是否在提交调用之前已经被提交。
VirtualAlloc对应的释放函数为VirtualFree。
2.HeapAlloc
该函数是从堆上分配一块内存,且分配的内存是不可移动的(即如果没有连续的空间能满足分配的大小,程序不能将其他零散的空间利用起来,从而导致分配失败)。该分配方法是从一指定地址开始分配,而不像GloabalAlloc是从全局堆上分配,这个有可能是全局,也有可能是局部,其函数原型:
LPVOID HeapAlloc(
HANDLE hHeap, //要分配堆的句柄
DWORD dwFlags, //堆分配时的可选参数
SIZE_T dwBytes, //要分配堆的字节数
);
参数说明:
1.HANDLE hHeap,要分配堆的句柄,可以通过HeapCreate()函数或GetProcessHeap()函数获得。
2.DWORD dwFlags,堆分配时的可选参数,其值可以为以下的一种或多种:HEAP_GENERATE_EXCEPTIONS(如果分配错误将会抛出异常,而不是返回NULL。异常值可能是STATUS_NO_MEMORY, 表示获得的内存容量不足,或是STATUS_ACCESS_VIOLATION,表示存取不合法),HEAP_NO_SERIALIZE(不使用连续存取),HEAP_ZERO_MEMORY(将分配的内存全部清零)。
3.SIZE_T dwBytes,要分配堆的字节数。
小结:
hHeap是进程堆内存开始位置,dwFlags是分配堆内存的标志。包括HEAP_ZERO_MEMORY,即使分配的空间清零,dwBytes是分配堆内存的大小,其对应的释放空间函数为HeapFree。
3.GlobalAlloc
该函数用于从全局堆中分配出内存供程序使用,函数原型为:
HGLOBALGlobalAlloc(
UINTuFlags, // 分配属性(方式)
DWORDdwBytes, // 分配的字节数
);
参数说明:
1.UINTuFlags,指定如何分配内存,若指定为0,则是默认的GMEM_FIXED.这个值可以是下面其中一个或几个位标识(那些指明不兼容的组合除外),标识:GHND(为GMEM_MOVEABLE 和 GMEM_ZEROINIT的组合),GMEM_FIXED(分配固定的内存,返回值是一个指针),GMEM_MOVEABLE(分配可移动的内存,在Win32中内存块在物理内存中是不可移动的,但在缺省堆中可以. 返回值是该内存对象的句柄,可使用函数 GlobalLock 将该句柄转换为一个指针,这个标识不能与 GMEM_FIXED 组合使用),GMEM_ZEROINIT(将所申请内存初始化为0),GPTR(为GMEM_FIXED和GMEM_ZEROINIT组合)。
2.DWORDdwBytes,指定要申请的字节数.若该参数为 0 且参数 uFlags 指定为 GMEM_MOVEABLE 则该函数返回一个内存对象的句柄,该内存对象被标识为discarded(可抛弃的)
小结:
使用此函数分配内存可以保证8字节的边界.所有的内存均在执行访问时创建;不需要特别的函数来动态执行所产生的代码,若函数调用成功,将至少分配所需内存.若实际分配量超过所需,则内存仍然能够充分利用之.可用函数 GlobalSize 来确定实际所分配的字节数,可使用 GlobalFree 来释放内存。
4.LocalAlloc
该函数用于从局部堆中分配内存供程序使用,函数原型为:
HLOCAL LocalAlloc(
UINT uFlags, //指定怎样去分配内存
UINT uBytes, //指定要分配的字节数
);
参数说明:
1.uFlags,指定怎样去分配内存。如果zero被指定,默认的是LMEM_FIXED标志。此参数有三种标志:LMEM_FIXED(分配固定内存,返回值是指向一个内存对象的指针),LMEM_ZEROINIT(初始化内存内容为zero),LPTR(结合了LMEM_FIXED和LMEM_ZEROINIT这两种标志),LMEM_MOVEABLE(分配可移动内存),LMEM_DISCARDABLE(分配可删除的内存)。
2.uBytes,指定要分配的字节数。
小结:
在16位Windows中是有区别的,因为在16位windows用一个全局堆和局部堆来管理内存,每一个应用程序或dll装入内存时,代码段被装入全局 堆,而系统又为每个实例从全局堆中分配了一个64kb的数据段作为该实例的局部堆,用来存放应用程序的堆栈和所有全局或静态变量。而 LocalAlloc/GlobalAlloc就是分别用于在局部堆或全局堆中分配内存。
由于每个进程的局部堆很小,所以在局部堆中分配内存会受到空间的限制。但这个堆是每个进程私有的,相对而言分配数据较安全,数据访问出错不至于影响到整个系统。
而在全局堆中分配的内存是为各个进程共享的,每个进程只要拥有这个内存块的句柄都可以访问这块内存,但是每个全局内存空间需要额外的内存开销,造成分配浪费。而且一旦发生严重错误,可能会影响到整个系统的稳定。
不过在Win32中,每个进程都只拥有一个省缺的私有堆,它只能被当前进程访问。应用程序也不可能直接访问系统内存。所以在Win32中全局堆和局部堆都 指向进程的省缺堆。用LocalAlloc/GlobalAlloc分配内存没有任何区别。甚至LocalAlloc分配的内存可以被 GlobalFree释放掉。所以在Win32下编程,无需注意Local和Global的区别,一般的内存分配都等效于 HeapAlloc(GetProcessHeap(),...)。
LocalAlloc对应的释放函数为LockFree。
5.Malloc
malloc与free是C++/C语言的标准库函数,可用于申请动态内存和释放内存。对于非内部数据类型的对象而言,光用 malloc/free无法满足动态对象的要求。对象在创建的同时要自动执行构造函数,对象在消亡之前要自动执行析构函数。由于malloc/free是 库函数而不是运算符,不在编译器控制权限之内,不能够把执行构造函数和析构函数的任务强加于malloc/free。
6.New
是C++的运算符,主要用来新建类,与C++的构造函数和异常机制有关,与上述其它函数的使用环境大相庭径。一般编译器中的new都是用malloc来分配内存的。
New对应的释放函数为delete。
三、拷贝/复制内存函数
1.memcpy
函数原型:
void *memcpy(void *destin, void *source, unsigned n);
参数:
- destin-- 指向用于存储复制内容的目标数组,类型强制转换为 void* 指针。
- source-- 指向要复制的数据源,类型强制转换为 void* 指针。
- n-- 要被复制的字节数。
2.CopyMemory
函数原型:
VOID CopyMemory(
PVOID Destination,
CONST VOID *Source,
SIZE_T Length
);
参数:
- Destination-- 要复制内存块的目的地址。
- Source-- 要复制内存块的源地址。
- Length-- 指定要复制内存块的大小,单位为字节
3.RtlCopyMemory
同CopyMemory一样
函数原型:
void RtlCopyMemory(
void* Destination,
const void* Source,
size_t Length
);
参数:
- Destination-- 要复制内存块的目的地址。
- Source-- 要复制内存块的源地址。
- Length-- 指定要复制内存块的大小,单位为字节
4.RtlMoveMemory
函数原型:
VOID RtlMoveMemory(
VOID UNALIGNED *Destination,
const VOID UNALIGNED *Source,
SIZE_T Length
);
参数:
Destination-- 指向移动目的地址的指针。
Source-- 指向要复制的内存地址的指针。
Length-- 指定要复制的字节数。
恶意软件开发——内存相关API的更多相关文章
- 恶意软件开发——编写第一个Loader加载器
一.什么是shellcode loader? 上一篇文章说了,我们说到了什么是shellcode,为了使我们的shellcode加载到内存并执行,我们需要shellcode加载器,也就是我们的shel ...
- [原创]java WEB学习笔记44:Filter 简介,模型,创建,工作原理,相关API,过滤器的部署及映射的方式,Demo
本博客为原创:综合 尚硅谷(http://www.atguigu.com)的系统教程(深表感谢)和 网络上的现有资源(博客,文档,图书等),资源的出处我会标明 本博客的目的:①总结自己的学习过程,相当 ...
- Day7:掌握APICloud应用管理相关服务的配置使用和相关API,包括:应用发布、版本管理、云修复、闪屏广告等。理解APICloud APP优化策略和编码规范;了解APICloud多Widget管理机制和SuperWebview的使用
主要内容: 1. 应用发布 1.1 云编译 1.2 全包加密 网页全包加密:对网页中全包的html,css,javascript代码进行加密,加密后的网友代码都是不可读的,并且不能通过常用的格式化工具 ...
- 小程序·云开发的HTTP API调用丨实战
小程序云开发之httpApi调用. 小程序云开发之httpApi调用(返回"47001处理") 技术栈 采用 nodejs + express 搭建web服务器,采用 axios ...
- OC中并发编程的相关API和面临的挑战
OC中并发编程的相关API和面临的挑战(1) 小引 http://www.objc.io/站点主要以杂志的形式,深入挖掘在OC中的最佳编程实践和高级技术,每个月探讨一个主题,每个主题都会有几篇相关的文 ...
- OpenGL FrameBufferCopy相关Api比较(glCopyPixels,glReadPixels,glCopyTexImage2D,glFramebufferTexture2D)
OpenGL FrameBufferCopy相关Api比较 glCopyPixels,glReadPixels,glCopyTexImage2D,glFramebufferTexture2D 标题所述 ...
- QQ音乐的各种相关API
QQ音乐的各种相关API 分类: oc2014-01-29 15:34 2676人阅读 评论(2) 收藏 举报 基本上论坛里做在线音乐的都在用百度的API,进来发现百度的API不仅歌曲的质量不可以保证 ...
- Myeclipse开发内存溢出问题
MyEclipse开发内存溢出问题 window --> preferences --> MyEclipse --> servers --> Tomcat --> J ...
- iOS开发之多媒体API(1)
iOS开发之多媒体API(1) 播放视频 视频文件介绍 视频格式可以分为适合本地播放的本地影像视频和适合在网络中播放的网络流媒体影像视频两大类.尽管后者在播放的稳定性和播放画面质量上可能没 ...
随机推荐
- React组件三大属性之 props
React组件三大属性之 props 理解1) 每个组件对象都会有props(properties的简写)属性2) 组件标签的所有属性都保存在props中 作用1) 通过标签属性从组件外向组件内传递变 ...
- FreeRTOS-01-任务相关函数
3 任务相关API函数 任务相关函数如下: 任务创建和删除API函数 任务创建和删除实验(动态方法) 任务创建和删除实验(静态方法) 任务挂起和恢复API函数 任务挂起和恢复实验 3.1 任务创建AP ...
- c# checkedListBox设置多列横向显示 经验总结
1. 设置checkedListBox的MultiColumn 属性为true; 2. 调整checkedListBox的宽度,调整ColumnWidth的宽度
- 每天五分钟Go - 闭包
闭包的示例代码 func getSequence() func() int{ i:=0 return func() int { i+=1 return i } } 首先,函数名getSequence, ...
- 虚拟机安装RHEL8.0.0
在VMware Workstations 15.0.0中安装RHEL8.0.0 使用到的软件和主机基本配置 此处宿主机基本硬件配置:i3-7100U 4核,内存:12G 虚拟化软件:VMware Wo ...
- Odoo的附件大小限制
Odoo使用binary类型来保存附件数据,可以直接支持附件数据的上传.但是在实际使用中,有可能遇到附件文件大小超过限制的情况,如下图: 但是ERP定制过程中难免会遇到客户确实需要上传超大附件,那么怎 ...
- 货币兑换问题(动态规划法)——Python实现
# 动态规划法求解货币兑换问题 # 货币系统有 n 种硬币,面值为 v1,v2,v3...vn,其中 v1=1,使用总值为money的钱与之兑换,求如何使硬币的数目最少,即 x1,x2,x3... ...
- springboot未授权
http://ip/actuator/heapdump http://ip/env http://ip/autoconfig http://ip/info http://ip/trace
- iptables中实现内外网互访,SNAT和DNAT
目录 一.SNAT原理与应用 二.DNAT原理与应用 DNAT转换:发布内网web服务 DNAT转换:发布时修改目标端口 三.防火墙规则的备份和还原 四.linux抓包 一.SNAT原理与应用 ① S ...
- Java Stream 自定义Collector
Collector的使用 使用Java Stream流操作数据时,经常会用到各种Collector收集器来进行数据收集. 这里便深入了解一点去了解Collector的工作原理和如何自定义Collect ...