如何为sys文件提取资源?我相信exe,dll和sys文件有相同的标题。这是对的吗?
我不明白我应该如何处理资源表的VirtualAddress和Size。
#include <stdio.h>
#include <windows.h>
#include <string.h>
void main()
{
FILE *file = fopen( "example.sys", "r" );
IMAGE_DOS_HEADER dos_header;
IMAGE_NT_HEADERS nt_header;
IMAGE_DATA_DIRECTORY data_directory;
char *data;
if( file != NULL )
{
fseek( file, 0, SEEK_SET );
fread( &dos_header, sizeof( dos_header ), 1, file );
if( dos_header.e_magic != IMAGE_DOS_SIGNATURE )
return;
fseek( file, dos_header.e_lfanew, SEEK_SET );
fread( &nt_header, sizeof( nt_header ), 1, file );
if( nt_header.Signature != IMAGE_NT_SIGNATURE )
return;
data_directory = nt_header.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE];
data = malloc( data_directory.Size + 1 );
memset( data, 0, data_directory.Size + 1 );
fseek( file, data_directory.VirtualAddress, SEEK_SET ); // <- ????
fread( data, data_directory.Size, 1, file );
free( data );
fclose( file );
}
}
答案 0 :(得分:2)
VirtualAddress 实际上是数据结构的相对虚拟地址(RVA)。 例如,如果此结构用于导入符号,则此字段包含IMAGE_IMPORT_DESCRIPTOR数组的RVA。
isize 包含VirtualAddress引用的数据结构的字节大小。
查看THIS链接。这是一个很好的解释,如何深入到win32组装。
答案 1 :(得分:0)
我终于找到了回答我的问题的代码示例 - PEDump。
使用它我做了这个样本:
#include <stdio.h>
#include <windows.h>
#include <string.h>
#define MakePtr( cast, ptr, addValue ) (cast)( (DWORD)(ptr) + (DWORD)(addValue))
#define RESOURCE_ADDRESS( pdr, o ) ((PUCHAR) (pdr + 1) + (o))
typedef struct tag_VS_VERSIONINFO
{
USHORT wLength; // 00 length of entire version resource
USHORT wValueLength; // 02 length of fixed file info, if any
USHORT wType; // 04 type of resource (1 = text, 0 = binary)
WCHAR szKey[17]; // 06 key -- VS_VERSION_INFO + padding byte
VS_FIXEDFILEINFO Value; // 28 fixed information about this file (13 dwords)
}
VS_VERSIONINFO, *PVS_VERSIONINFO; // 5C
PIMAGE_SECTION_HEADER GetEnclosingSectionHeader(DWORD rva,
PIMAGE_NT_HEADERS pNTHeader)
{
PIMAGE_SECTION_HEADER section = IMAGE_FIRST_SECTION(pNTHeader);
unsigned i;
for ( i=0; i < pNTHeader->FileHeader.NumberOfSections; i++, section++ )
{
// Is the RVA within this section?
if ( (rva >= section->VirtualAddress) &&
(rva < (section->VirtualAddress + section->Misc.VirtualSize)))
return section;
}
return 0;
}
LPVOID GetPtrFromRVA( DWORD rva, PIMAGE_NT_HEADERS pNTHeader, DWORD imageBase )
{
PIMAGE_SECTION_HEADER pSectionHdr;
INT delta;
pSectionHdr = GetEnclosingSectionHeader( rva, pNTHeader );
if ( !pSectionHdr )
return 0;
delta = (INT)(pSectionHdr->VirtualAddress-pSectionHdr->PointerToRawData);
return (PVOID) ( imageBase + rva - delta );
}
void main()
{
unsigned int index;
PIMAGE_DOS_HEADER dos_header;
PIMAGE_NT_HEADERS nt_header;
PIMAGE_DATA_DIRECTORY data_directory;
PIMAGE_RESOURCE_DIRECTORY resources;
PIMAGE_RESOURCE_DIRECTORY_ENTRY listItem;
PIMAGE_RESOURCE_DIRECTORY child;
PIMAGE_RESOURCE_DIRECTORY_ENTRY version;
PIMAGE_RESOURCE_DATA_ENTRY data_entry;
PVS_VERSIONINFO version_info;
HANDLE hFile;
HANDLE hFileMapping;
LPVOID lpFileBase;
hFile = CreateFile( L"samples.sys",
GENERIC_READ,
FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
0
);
if ( hFile == INVALID_HANDLE_VALUE )
return;
hFileMapping = CreateFileMapping( hFile, NULL, PAGE_READONLY, 0, 0, NULL );
if ( hFileMapping == 0 )
{
CloseHandle(hFile);
return;
}
lpFileBase = MapViewOfFile( hFileMapping, FILE_MAP_READ, 0, 0, 0 );
if ( lpFileBase == 0 )
{
CloseHandle(hFileMapping);
CloseHandle(hFile);
return;
}
dos_header = MakePtr( PIMAGE_DOS_HEADER, lpFileBase, 0 );
if( dos_header->e_magic != IMAGE_DOS_SIGNATURE )
return;
nt_header = MakePtr( PIMAGE_NT_HEADERS, lpFileBase, dos_header->e_lfanew );
if( nt_header->Signature != IMAGE_NT_SIGNATURE )
return;
data_directory = &nt_header->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE];
resources = ( PIMAGE_RESOURCE_DIRECTORY )GetPtrFromRVA( data_directory->VirtualAddress, nt_header, ( DWORD )lpFileBase );
listItem = ( PIMAGE_RESOURCE_DIRECTORY_ENTRY )( resources + 1 );
for( index = 0; index < resources->NumberOfIdEntries; index++ )
{
if( listItem->Id == ( WORD )RT_VERSION )
{
if( listItem->DataIsDirectory )
{
child = ( PIMAGE_RESOURCE_DIRECTORY )( ( listItem->OffsetToData & 0x7FFFFFFF ) + (DWORD)resources );
version = ( PIMAGE_RESOURCE_DIRECTORY_ENTRY )( child + 1 );
if( version->DataIsDirectory )
{
child = ( PIMAGE_RESOURCE_DIRECTORY )( ( version->OffsetToData & 0x7FFFFFFF ) + (DWORD)resources );
version = ( PIMAGE_RESOURCE_DIRECTORY_ENTRY )( child + 1 );
data_entry = ( PIMAGE_RESOURCE_DATA_ENTRY )( ( version->OffsetToData & 0x7FFFFFFF ) + (DWORD)resources );
version_info = ( PVS_VERSIONINFO )GetPtrFromRVA( data_entry->OffsetToData, nt_header, ( DWORD )lpFileBase );
}
}
}
listItem += 1;
}
}
这里最有趣的部分是函数GetPtrFromRVA,它将用于将VirtualAddress转换为从文件开头的偏移量。