首页
社区
课程
招聘
[旧帖] 关于导入表在文件内的开始地址的计算!!! 0.00雪花
发表于: 2015-5-16 19:23 3709

[旧帖] 关于导入表在文件内的开始地址的计算!!! 0.00雪花

2015-5-16 19:23
3709
今天看导入表入口地址的计算,通过RVA计算出导入表在文件中的开始地址。

  但是有一句话,我始终没弄懂,求大神解惑:教材中说,先遍历节表,找出导入表所在的区块,然后根据区块表算出导入表在文件中的偏移,这句我理解。
   
  然后我以为完事了,导入表在文件中的偏移不就是导入表的入口么? 结果,随后教材又给出一句:用文件映射到内存的基地址加上导入表的在文件中的偏移地址就是结构数组   IMAGE_IMPORT_DESCRIPTOR开始的地址,也就是导入表在文件中的开始位置。然后我就彻底蒙了

导入表在文件中的偏移,不是导入表的入口地址么?为什么还要加上一个文件映射到内存的基地址呢?求大神解答!!!

[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

收藏
免费 0
支持
分享
最新回复 (7)
雪    币: 7333
活跃值: (4034)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
用文件映射到内存的基地址加上导入表的在文件中的偏移地址就是结构数组   IMAGE_IMPORT_DESCRIPTOR开始的地址,也就是导入表在文件中的开始位置。

这句话有误吧,最后一句应该是导入表在内存中的位置吧,不是文件中的位置。其实就是RVA和VA的关系,基地址加上RVA等于VA。
2015-5-16 21:42
0
雪    币: 4
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
哈哈哈哈哈哈哈哈哈哈
2015-5-17 07:05
0
雪    币: 84
活跃值: (30)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
我觉得这句话怎么说都有错,导入表在文件中的偏移就是导入表的入口地址了,但是这个入口地址只是文件中的,因为对齐的原因,导入表在内存中的地址无论如何是不可能与加载进内存的偏移地址是一样的,除非是数据与节区的相对偏移地址,加载进内存才会不变,所以这句怎么看怎么不对劲
2015-5-17 10:30
0
雪    币: 7333
活跃值: (4034)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
导入表在文件中对于其所处的区块的偏移和在内存中对于同一区块的偏移是一样的,例如导入表在区段A中,且对于区段A的文件偏移是B,那么当区段A载入内存后,导入表对区段A的偏移也是B,不同的只是区段A在文件中的偏移和在内存中的偏移,而导入表对于区段A的偏移都是相同的。

导入表在内存中相对于当前区段的偏移加上区段本身的偏移就是RVA再加上模块基地址就是导入表的确切虚拟地址了。

我是这样理解的
2015-5-17 11:19
0
雪    币: 11
活跃值: (11)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
首先声明:
      映像后(如LoadLibrary)文件在内存中的内容与直接读文件(OpenFile. ReadFile)在内存中内容是完全不同的.
     所有楼主所说的: "文件中", 标准应该是 " 映像后文件在内存中";

PIMAGE_DOS_HEADER pDosHdr = Buffer;  // Buffer 就是文件映像基址
typedef struct _IMAGE_DOS_HEADER {      // DOS .EXE header
    WORD   e_magic;                     // Magic number
     ...
    LONG   e_lfanew;                    // File address of new exe header
  } IMAGE_DOS_HEADER, *PIMAGE_DOS_HEADER;

PIMAGE_NT_HEADERS32 pNtHdr = Buffer +  pDosHdr->e_lfanew;
typedef struct _IMAGE_NT_HEADERS {
    DWORD Signature;
    IMAGE_FILE_HEADER FileHeader;
    IMAGE_OPTIONAL_HEADER32 OptionalHeader;
} IMAGE_NT_HEADERS32, *PIMAGE_NT_HEADERS32;

PIMAGE_EXPORT_DIRECTORY	pExportEntry = (PIMAGE_EXPORT_DIRECTORY)(
		Buffer + 
		pNtHdr->OptionalHeader.DataDirectory[0].VirtualAddress
		);
PIMAGE_IMPORT_DESCRIPTOR pImportEntry = (PIMAGE_IMPORT_DESCRIPTOR)(
		Buffer + 
		pNtHdr->OptionalHeader.DataDirectory[1].VirtualAddress
		);
PIMAGE_BASE_RELOCATION pBaseReloc = (PIMAGE_BASE_RELOCATION)(
		Buffer + 
		pNtHdr->OptionalHeader.DataDirectory[5].VirtualAddress
		);
//上面的三个VirtualAddress是RVA, 就是楼主所说的: "(导入表的)在文件中的偏移地址"
// RVA当然要加上 基地址 , 才是在 映像后的实际地址
2015-5-21 18:17
0
雪    币: 11
活跃值: (11)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
接上面:

/**
*@return 返回FilePos   // (即使用: OpenFile.ReadFile)  
*/
ULONG RVAToFilePos(
PIMAGE_SECTION_HEADER pSecHdr, 
ULONG uSecNum ,
ULONG RVA
)
{
	ULONG FilePos = 0;
	ULONG i = 0;

	for (i = 0; i < uSecNum; i++ )
	{
		if (RVA >=  pSecHdr[i].VirtualAddress &&
			RVA <  pSecHdr[i].VirtualAddress +  pe->pSecHdr[i].SizeOfRawData)
		{
			FilePos = RVA -  pSecHdr[i].VirtualAddress +  pSecHdr[i].PointerToRawData;
			break;
		}
	}

	return FilePos;
}
/**
*@brief FilePos到RVA的转换
*@return 返回RVA
*/
ULONG FilePosToRVA(
PIMAGE_SECTION_HEADER pSecHdr, 
ULONG uSecNum ,
ULONG FilePos)
{
	ULONG RVA = 0;
	ULONG i = 0;

	for (i = 0; i < uSecNum; i++ )
	{
		if (FilePos >=  pSecHdr[i].PointerToRawData &&
			FilePos <  pSecHdr[i].PointerToRawData +  pSecHdr[i].SizeOfRawData)
		{
			RVA = FilePos -  pSecHdr[i].PointerToRawData +  pSecHdr[i].VirtualAddress;
			break;
		}
	}

Exit0:
	return RVA;
}
2015-5-21 19:11
0
雪    币: 296
活跃值: (26)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
因为在PE文件静态分析时,偏移是相对于SEEK_SET(0)开始的,但是跑起来后,在虚拟内存中分配到的地址就不是从0开始了,而是基地址+偏移
2015-5-29 11:55
0
游客
登录 | 注册 方可回帖
返回
//