如何确定PE文件中特定数据目录的图像地址(文件中的字节偏移量)?
例如,给定数据目录如下:
app.controller('UploadImageModalInstance', function($scope, $modalInstance, Upload){
$scope.image = 'img/default.png';
$scope.progress = 0;
$scope.files = [];
$scope.upload = function(){
Upload.upload({
url: 'api/upload',
fields: {'dir': 'img/uploads/'},
file: $scope.files[0],
method: 'POST'
}).progress(function (evt) {
$scope.progress = parseInt(100.0 * evt.loaded / evt.total);
}).success(function (data) {
$scope.progress = 0;
$scope.image = data.dir+data.filename;
});
};
$scope.insert = function(){
$modalInstance.close($scope.image);
};
})
导入目录(上面的#2)显示为RVA为0xAF974。但是,导入目录不位于EXE文件的字节0xAF974。如何计算文件中导入目录的字节偏移量,因为它写在磁盘上?
答案 0 :(得分:2)
这很有趣!您必须遍历各个部分才能根据虚拟地址找到正确的位置。这是我在很多
之后编写的一些代码我可以尝试解释这一点,但是我花了很多时间自己理解它并且几周后我没有看过它而且我已经忘记了很多技术内容。我正在编写一个C ++类来处理很多这个问题
在我的代码缓冲区中是一个指向MapViewOfFile的指针,但它可以是任何字符指针。
/* Example usage...I know not perfect but should help a bit. */
unsigned char * lpFile = (unsigned char *)(void *)MapViewOfFile(fileMap, FILE_MAP_ALL_ACCESS, 0,0, 0);
if(lpFile==NULL) {
printf("Failed to MapViewOfFile\r\n");
exit(0);
}
header_dos = (PIMAGE_DOS_HEADER)lpFile;
header_nt = (PIMAGE_NT_HEADERS32)&lpFile [header_dos->e_lfanew];
IMAGE_DATA_DIRECTORY import = header_nt->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT];
PIMAGE_IMPORT_DESCRIPTOR im = (PIMAGE_IMPORT_DESCRIPTOR)&lpFile[RVA2Offset(lpFile, import.VirtualAddress)];
/* RVA is relative to the section it resides in. */
int RVA2Offset(unsigned char * buffer, DWORD rva)
{
PIMAGE_NT_HEADERS header = (PIMAGE_NT_HEADERS) &buffer[ ((PIMAGE_DOS_HEADER)buffer)->e_lfanew ];
PIMAGE_SECTION_HEADER section = (PIMAGE_SECTION_HEADER) &buffer[ ((PIMAGE_DOS_HEADER)buffer)->e_lfanew + sizeof(IMAGE_NT_HEADERS) ];
for(int sectionIndex = 0; sectionIndex < header->FileHeader.NumberOfSections; sectionIndex++) {
/*
Check if the RVA is within the virtual addressing space of the section
Make sure the RVA is less than the VirtualAddress plus its raw data size
IMAGE_HEADER_SECTION.VirtualAddress = The address of the first byte of the section when loaded into memory, relative to the image base. For object files, this is the address of the first byte before relocation is applied.
Our ImageBase is 0, since we aren't loaded into actual memory
*/
section = (PIMAGE_SECTION_HEADER) &buffer[ ((PIMAGE_DOS_HEADER)buffer)->e_lfanew + sizeof(IMAGE_NT_HEADERS) + (sectionIndex*sizeof(IMAGE_SECTION_HEADER))];
if (rva >= section->VirtualAddress && (rva <= section->VirtualAddress + section->SizeOfRawData)) {
/**
PointerToRawData gives us the section's location within the file.
RVA - VirtualAddress = Offset WITHIN the address space
**/
return section->PointerToRawData + (rva - section->VirtualAddress);
}
}
return 0;
}