从sys文件中提取资源

时间:2015-02-05 11:58:57

标签: c windows

如何为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 );
    }
}

2 个答案:

答案 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转换为从文件开头的偏移量。