[转载]内存偏移与文件偏移相互转换

RVA = 虚拟地址 - 基址 如: 00423562 - 00400000 = 23562

--------------------------------------------------

作 者: LeoF

时 间: 2010-03-23,17:53:48 链 接: http://bbs.pediy.com/showthread.php?t=109449 写此文源于前一阵写一个PE修改工具,需要用到内存偏移向文件偏移转化。想着这种简单的代码网上应该一大把,百度了一下,没找到。又google,又没找到,可能是自己搜索的功力太不到家了。着急用,只好自己写了一个函数用来转换。相信很多人做PE开发的时候都会有这个需求,把这个函数贴出来供大家参考,大牛莫耻笑。

原理比较简单:首先判断这个地址是否在PE头中,如果在,文件偏移和内存偏移相等,如果存在于文件的区段中,则利用以下公式:

内存偏移 - 该段起始的RVA(VirtualAddress) = 文件偏移 - 该段的PointerToRawData

内存偏移 = 该段起始的RVA(VirtualAddress) + (文件偏移 - 该段的PointerToRawData)

文件偏移 = 该段的PointerToRawData + (内存偏移 - 该段起始的RVA(VirtualAddress))

代码如下:

#include <stdio.h>
02./*
03.Purpose:PE文件的内存偏移与文件偏移相互转换,不考虑系统为对齐填充偏移转换
04.szFileName:文件名
05.dwAddr:需要转换的偏移值
06.bFile2RVA:是否是文件偏移到内存偏移的转换,1 - dwAddr代表的是文件偏移,此函数返回内存偏移
07.      0 - dwAddr代表的是内存偏移,此函数返回文件偏移
08.返回值:相对应的偏移值,失败返回-1
09.*/
10.
11.DWORD AddressConvert(char szFileName[], DWORD dwAddr, BOOL bFile2RVA)
12.{
13.  char *lpBase = NULL;
14.  DWORD dwRet = -1;
15.  //1.首先将文件读入内存
16.  if(szFileName[0] == 0)
17.  {
18.    return -1;
19.  }
20.
21.  FILE *fp = fopen(szFileName, "rb");
22.  if(fp == 0)
23.  {
24.    return -1;
25.  }
26.
27.  fseek(fp, 0, SEEK_END);
28.  DWORD dwFileSize = ftell(fp);
29.  if(dwFileSize == 0)
30.  {
31.    return -1;
32.  }
33.
34.  lpBase = new char[dwFileSize];
35.  memset(lpBase, 0, dwFileSize);
36.  fseek(fp, 0, SEEK_SET);
37.  fread(lpBase, 1, dwFileSize, fp);
38.  fclose(fp);
39.
40.  //2.读取该文件的信息(文件内存对齐方式以及区块数量,并将区块表指针指向区块表第一个区块头)
41.  PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)lpBase;
42.  PIMAGE_NT_HEADERS pNtHeader = (PIMAGE_NT_HEADERS)((unsigned long)lpBase + pDosHeader->e_lfanew);
43.
44.  DWORD dwMemAlign = pNtHeader->OptionalHeader.SectionAlignment;
45.  DWORD dwFileAlign = pNtHeader->OptionalHeader.FileAlignment;
46.  int dwSecNum = pNtHeader->FileHeader.NumberOfSections;
47.  PIMAGE_SECTION_HEADER pSecHeader = (PIMAGE_SECTION_HEADER)((char *)lpBase + pDosHeader->e_lfanew + sizeof(IMAGE_NT_HEADERS));
48.  DWORD dwHeaderSize = 0;
49.
50.  if(!bFile2RVA)  // 内存偏移转换为文件偏移
51.  {
52.    //看需要转移的偏移是否在PE头内,如果在则两个偏移相同
53.    dwHeaderSize = pNtHeader->OptionalHeader.SizeOfHeaders;
54.    if(dwAddr <= dwHeaderSize)
55.    {
56.      delete lpBase;
57.      lpBase = NULL;
58.      return dwAddr;
59.    }
60.    else //不再PE头里,查看该地址在哪个区块中
61.    {
62.      for(int i = 0; i < dwSecNum; i++)
63.      {
64.        DWORD dwSecSize = pSecHeader[i].Misc.VirtualSize;
65.        if((dwAddr >= pSecHeader[i].VirtualAddress) && (dwAddr <= pSecHeader[i].VirtualAddress + dwSecSize))
66.        {
67.          //3.找到该该偏移,则文件偏移 = 该区块的文件偏移 + (该偏移 - 该区块的内存偏移)
68.          dwRet = pSecHeader[i].PointerToRawData + dwAddr - pSecHeader[i].VirtualAddress;
69.        }
70.      }
71.    }
72.  }
73.  else // 文件偏移转换为内存偏移
74.  {
75.    dwHeaderSize = pNtHeader->OptionalHeader.SizeOfHeaders;
76.    //看需要转移的偏移是否在PE头内,如果在则两个偏移相同
77.    if(dwAddr <= dwHeaderSize)
78.    {
79.      delete lpBase;
80.      lpBase = NULL;
81.      return dwAddr;
82.    }
83.    else//不再PE头里,查看该地址在哪个区块中
84.    {
85.      for(int i = 0; i < dwSecNum; i++)
86.      {
87.        DWORD dwSecSize = pSecHeader[i].Misc.VirtualSize;
88.        if((dwAddr >= pSecHeader[i].PointerToRawData) && (dwAddr <= pSecHeader[i].PointerToRawData + dwSecSize))
89.        {
90.          //3.找到该该偏移,则内存偏移 = 该区块的内存偏移 + (该偏移 - 该区块的文件偏移)
91.          dwRet = pSecHeader[i].VirtualAddress + dwAddr - pSecHeader[i].PointerToRawData;
92.        }
93.      }
94.    }
95.  }
96.
97.  //5.释放内存
98.  delete lpBase;
99.  lpBase = NULL;
100.  return dwRet;
101.}   

时间: 2024-11-05 19:38:33

[转载]内存偏移与文件偏移相互转换的相关文章

PE查找文件偏移地址

节(section) 相对虚拟偏移量RVA() 文件偏移量 .text 0x1000 0x0400 文件偏移地址 = 虚拟内存地址(VA) - 装载地址(ImageBase) - 节偏移(RVA-节偏移) 查找内存中0x404141 处的指令  ImageBase=0x400000 , 在文件中的偏移量: 文件偏移量 = 0x404141 - 0x400000 - (0x1000 - 0x400) = 0x3541

iOS将大文件映射到内存(读取大文件)

http://blog.csdn.net/xyt243135803/article/details/40995759 在<中国区GPS偏移纠正(适用于Google地图)>一文中曾读取一个78M的大数据文件,一开始采用了NSData的dataWithContentsOfFile:方法.不少人反馈说如果直接使用,将会耗尽iOS的内存.其实这个是可以改善的. NSData还有一个API: + (id)dataWithContentsOfFile:(NSString *)path options:(N

内存映像文件

Linux允许任何进程把一个磁盘文件映像到内存中. 使用内存映像文件有两个主要优点 –加速文件I/O操作,不同的I/O调用如read或者fputs通过内核缓冲读出或写入数据.虽然Linux具有一种快速而先进的磁盘缓冲算法,但最快的磁盘访问也总是要比最慢的内存访问慢. –共享数据,如果多个进程要访问一样的数据,这些数据就可以保存在一个内存映像文件中,所有的进程都可以访问它. mmap函数 #include <unistd.h> #include <sys/mman.h> void *

ios7中使用scrollview来横向滑动图片,自动产生偏移竖向的偏移 问题

ios7中使用scrollview来横向滑动图片,自动产生偏移竖向的偏移 问题 如图红色为scrollview的背景色,在scrollview上加了图片之后,总会有向下的偏移 设置contentOffset也不管用 在ios7中controller有个 automaticallyAdjustsScrollViewInsets属性,默认为YES if (iOS7&&[self respondsToSelector:@selector(automaticallyAdjustsScrollVie

[转载]eclipse中设置文件的编码格式为utf-8

免责声明:     本文转自网络文章,转载此文章仅为个人收藏,分享知识,如有侵权,请联系博主进行删除.     原文作者:ryxxlong     原文地址:http://ryxxlong.iteye.com/blog/788469 1.可以在 eclipse 中配置 workspace 项下 text file encoding 属性的值来决定此工作区间下所有的 eclipse 项目的文档的编码属性. Window-->Preferences-->General-->Workspace

[转载]VC6中的文件后缀

VC文件扩展名 .APS:存放二进制资源的中间文件,VC把当前资源文件转换成二进制格式,并存放在APS文件中,以加快资源装载速度. .BMP:位图资源文件. .BSC:浏览信息文件,由浏览信息维护工具(BSCMAKE)从原始浏览信息文件(.SBR)中生成,BSC文件可以用来在源代码编辑窗口中进行快速定位. .C:用C语言编写的源代码文件. .CLW:ClassWizard生成的用来存放类信息的文件. .CNT:用来定义帮助文件中“Contents”的结构. .CPP或.CXX:用C++语言编写的

Android转载一:Android文件命名规范

REF:http://blog.csdn.net/gulianchao/article/details/23391651 (一) Layout命名1.contentview命名:activity_功能模块.xml例如:activity_main.xml.activity_more.xml2.Dialog命名:dialog_描述.xml 例如:dlg_hint.xml2.PopupWindow命名:ppw_描述.xml 例如:ppw _info.xml 列表项命名listitem_描述.xml 例

内存运行PE文件

内存中运行文件 拿exe并在HxD或010中打开 - cntrl+a copy as C 粘贴到encrypt.cpp 编译并运行encrypt.cpp - 创建shellcode.txt 从shellcode.txt复制char数组,并替换runPE.cpp中的rawData [] 编译生成最终的runPE.exe 使用XOR密钥解密,加载到内存中执行. encrypt.cpp //encrypt shellcode prior to storing in stub //store in sh

检查打开的文件是不是ELF格式的文件,如果是就输出节头表的文件偏移

#include <stdio.h> #include <stdlib.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <unistd.h> #include <errno.h> #include "elf.h" #define FALSE 0 #define TURE 1 #define MAX_S