Windows API 之 CreateFile、CreateFileMapping 、MapViewOfFile

CreateFile

Creates or opens a file or I/O device. The most commonly used I/O devices are as follows: file, file stream, directory, physical disk, volume, console buffer, tape drive, communications resource, mailslot, and pipe. The function returns a handle that can be used to access the file or device for various types of I/O depending on the file or device and the flags and attributes specified.

HANDLE WINAPI CreateFile(
  _In_     LPCTSTR               lpFileName,
  _In_     DWORD                 dwDesiredAccess,
  _In_     DWORD                 dwShareMode,
  _In_opt_ LPSECURITY_ATTRIBUTES lpSecurityAttributes,
  _In_     DWORD                 dwCreationDisposition,
  _In_     DWORD                 dwFlagsAndAttributes,
  _In_opt_ HANDLE                hTemplateFile
);

Parameters

lpFileName [in]

The name of the file or device to be created or opened.(文件路径)

dwDesiredAccess [in]

The requested access to the file or device, which can be summarized as read, write, both or neither zero).

The most commonly used values are GENERIC_READ, GENERIC_WRITE, or both (GENERIC_READ | GENERIC_WRITE).

dwShareMode [in]

The requested sharing mode of the file or device, which can be read, write, both, delete, all of these, or none (refer to the following table).

lpSecurityAttributes [in, optional]

A pointer to a SECURITY_ATTRIBUTES structure that contains two separate but related data members: an optional security descriptor, and a Boolean value that determines whether the returned handle can be inherited by child processes.

This parameter can be NULL.

If this parameter is NULL, the handle returned by CreateFile cannot be inherited by any child processes the application may create and the file or device associated with the returned handle gets a default security descriptor.

The lpSecurityDescriptor member of the structure specifies a SECURITY_DESCRIPTOR for a file or device. If this member is NULL, the file or device associated with the returned handle is assigned a default security descriptor.

CreateFile ignores the lpSecurityDescriptor member when opening an existing file or device, but continues to use the bInheritHandle member.

The bInheritHandlemember of the structure specifies whether the returned handle can be inherited.

dwCreationDisposition [in]

An action to take on a file or device that exists or does not exist.

Return value

If the function succeeds, the return value is an open handle to the specified file, device, named pipe, or mail slot.

If the function fails, the return value is INVALID_HANDLE_VALUE. To get extended error information, call GetLastError.

 

 

 

CreateFileMapping  

Creates or opens a named or unnamed file mapping object for a specified file(文件映射内核对象).

HANDLE WINAPI CreateFileMapping(
  _In_     HANDLE                hFile,
  _In_opt_ LPSECURITY_ATTRIBUTES lpAttributes,
  _In_     DWORD                 flProtect,
  _In_     DWORD                 dwMaximumSizeHigh,
  _In_     DWORD                 dwMaximumSizeLow,
  _In_opt_ LPCTSTR               lpName
);
flProtect [in]

Specifies the page protection of the file mapping object. All mapped views of the object must be compatible with this protection.

 

MapViewOfFile

Maps a view of a file mapping into the address space of a calling process.

LPVOID WINAPI MapViewOfFile(
  _In_ HANDLE hFileMappingObject,
  _In_ DWORD  dwDesiredAccess,
  _In_ DWORD  dwFileOffsetHigh,
  _In_ DWORD  dwFileOffsetLow,
  _In_ SIZE_T dwNumberOfBytesToMap
);

Parameters

hFileMappingObject [in]

A handle to a file mapping object. The CreateFileMapping and OpenFileMapping functions return this handle.

dwDesiredAccess [in]

The type of access to a file mapping object, which determines the protection of the pages.

dwNumberOfBytesToMap [in]

The number of bytes of a file mapping to map to the view. All bytes must be within the maximum size specified by CreateFileMapping. If this parameter is 0 (zero), the mapping extends from the specified offset to the end of the file mapping.

Return value

If the function succeeds, the return value is the starting address of the mapped view.

If the function fails, the return value is NULL. To get extended error information, call GetLastError.

 

内存映射文件,是由一个文件到一块内存的映射。Win32提供了允许应用程序把文件映射到一个进程的函数 (CreateFileMapping)。内存映射文件与虚拟内存有些类似,通过内存映射文件可以保留一个地址空间的 区域,同时将物理存储器提交给此区域,内存文件映射的物理存储器来自一个已经存在于磁盘上的文件,而非系统的页文件,而且在对该文件进行操作之前必须首先对文件进行映射。使 用内存映射文件处理存储于磁盘上的文件时,将不必再对文件执行I/O操作,使得内存映射文件在处理大数据量的文件时能起到相当重要的作用。由于取消了将文件数据加载到内存、数据从内存到文件的回写以及释放内存块等步骤,使得内存映射文件在处理大数据量的文件时能起到相当重要的作用。另外,实际工程中的系统往往需要在多个进程之间共享数据,如果数据量小,处理方法是灵活多变的,如果共享数据容量巨大,那么就需要借助于内存映射文件来进行。实际上,内存映射文件正是解决本地多个进程间数据共享的最有效方法。

内存映射文件并不是简单的文件I/O操作,实际用到了Windows的核心编程技术--内存管理。所以,如果想对内存映射文件有更深刻的认识,必须对Windows操作系统的内存管理机制有清楚的认识,下面给出使用内存映射文件的一般方法:

首先要通过CreateFile()函数来创建或打开一个文件内核对象 这个对象标识了磁盘上将要用作内存映射文件的文件。再用CreateFile()将文件映像在物理存储器的位置通告给操作系统后,只指定了映像文件的路径,映像的长度还没有指定。为了指定文件映射对象需要多大的物理存储空间还需要通过CreateFileMapping()函数来创建一个文件映射内核对象告诉系统文件的尺寸以及访问文件的方式(其实就是一个数据结构,保存了要映射进来的文件的一些信息)。由MapViewOfFile()函数负责通过系统的管理而将文件映射对象的全部或部分映射到进程地址空间。此时,对内存映射文件的使用和处理同通常加载 到内存中的文件数据的处理方式基本一样,在完成了对内存映射文件的使用时,还要通过一系列的操作完成对其的清除和使用过资源的释放。这部分相对比较简单,可以通过UnmapViewOfFile()完成从进程的地址空间撤消文件数据的映像、通过CloseHandle()关闭前面创建的文件映射对象和文件 对象

  •  举例:
#include <iostream>
#include <windows.h>

using namespace std;

int main()
{
    TCHAR szFilePath[0x200] = "D:\\Coding\\test\\testDumpPE\\notepad.exe";

    HANDLE hFile = CreateFile(szFilePath, GENERIC_READ, 0, NULL, OPEN_EXISTING, NULL, NULL);
    if (hFile == INVALID_HANDLE_VALUE)
    {
        cout << "createfile failed:" << GetLastError() << endl;
        getchar();
        return 1;
    }

    HANDLE hMap = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, 0);
    if (hMap == NULL)
    {
        cout << "CreateFileMapping failed" << endl;
        getchar();
        return 1;
    }

    LPVOID pMapViewFile = MapViewOfFile(hMap, FILE_MAP_READ, 0, 0, 0);
    if (pMapViewFile == NULL)
    {
        cout << "MapViewOfFile failed" << endl;
        getchar();
        return 1;
    }
  //映射之后就可以查看到相应的PE字段了
    PIMAGE_DOS_HEADER pImageDOSHeader = nullptr;
    pImageDOSHeader = (PIMAGE_DOS_HEADER)pMapViewFile;
    PIMAGE_NT_HEADERS pImageNTHeader = (PIMAGE_NT_HEADERS)((LONG)pImageDOSHeader + pImageDOSHeader->e_lfanew);


    if (pImageNTHeader->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC)
    {
        cout << "PE32" << endl;
    }
    else if (pImageNTHeader->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC)
    {
        cout << "PE32+" << endl;
    }
    else
    {
        cout << "ROM" << endl;
    }
    UnmapViewOfFile(pMapViewFile);
    CloseHandle(hMap);
    CloseHandle(hFile);

    system("pause");
    return 0;
}

其中,winnt.h中保存着PE结构中所定义的各种结构体,可以跟进去查看:

例如,IMAGE DOS HEADER的结构:

 

各种Signature:

对应:

竟然有单独的PIMAGE_OPTIONAL_HEADER

  • 备注:

PE内存映像(PE装载器装载)和内存映射文件(MapViewofFile)的区别:

内存映射文件是指将硬盘上的文件不做修改的装载到内存中,(为什么?)在硬盘上,文件是被分割开存放的,当我们访问时,计算机需要先将不同位置的内容读取到内存,而有了内存文件映射,访问就会变得更轻松和快捷,由于读取磁盘操作放到了一起,读写效率会提高很多,所以许多大型的编辑软件经常会使用内存映射文件存取磁盘文件。

PE内存映像是指按照一定的规则装载到内存中,装入后的整个文件头内容不会发生变化,但PE文件的某一部分如节的内容会按照字段中的对齐方式在内存中对齐,从而使得内存中的PE映像与装载前的PE文件不同。(为什么不能像一般的内存映射一样?)PE文件是由操作系统装载进内存的,其目的是为了运行。为了配合操作系统的运行,方便调度,提高运行效率。

参考:

http://blog.csdn.net/sunnymov/article/details/5410449

获取DOS头和PE头:

http://www.2cto.com/Article/201201/116186.html

http://www.2cto.com/Article/201201/116187.html

虚拟地址RVA到文件偏移的转换:

http://blog.csdn.net/jccz_zys/article/details/1526971

 

转载于:https://www.cnblogs.com/predator-wang/p/4902793.html

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值