mirror of
https://github.com/reactos/reactos.git
synced 2024-12-28 01:55:19 +00:00
update SVN properties
svn path=/trunk/; revision=17142
This commit is contained in:
parent
c3a96b7538
commit
100b8232d0
1 changed files with 375 additions and 375 deletions
|
@ -1,375 +1,375 @@
|
|||
/*
|
||||
* PE Fixup Utility
|
||||
* Copyright (C) 2005 Filip Navara
|
||||
*
|
||||
* The purpose of this utility is fix PE binaries generated by binutils and
|
||||
* to manipulate flags that can't be set by binutils.
|
||||
*
|
||||
* Currently two features are implemented:
|
||||
*
|
||||
* - Setting flags on PE sections for use by drivers. The sections
|
||||
* .text, .data, .idata, .bss are marked as non-pageable and
|
||||
* non-discarable, section PAGE is marked as pageable and section
|
||||
* INIT is marked as discaradable.
|
||||
*
|
||||
* - Sorting of export name table in executables. DLLTOOL has bug
|
||||
* in sorting algorithm when the --kill-at flag is used. The exports
|
||||
* are sorted in the decorated form and so the fastcall symbols are
|
||||
* incorrectly put at the beginning of export table. This option
|
||||
* allow to correct sort the table, so binary search can be used
|
||||
* to process them.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#ifndef O_BINARY
|
||||
#define O_BINARY 0
|
||||
#endif
|
||||
|
||||
/* The following definitions are ripped from MinGW W32API headers. We don't
|
||||
use these headers directly in order to allow compilation on Linux hosts. */
|
||||
|
||||
typedef unsigned char BYTE;
|
||||
typedef unsigned short WORD;
|
||||
typedef unsigned int DWORD;
|
||||
typedef int LONG;
|
||||
|
||||
#define IMAGE_NUMBEROF_DIRECTORY_ENTRIES 16
|
||||
#define IMAGE_SIZEOF_SHORT_NAME 8
|
||||
#define IMAGE_DOS_SIGNATURE 0x5A4D
|
||||
#define IMAGE_NT_SIGNATURE 0x00004550
|
||||
#define IMAGE_SCN_MEM_DISCARDABLE 0x2000000
|
||||
#define IMAGE_SCN_MEM_NOT_PAGED 0x8000000
|
||||
#define FIELD_OFFSET(t,f) ((LONG)&(((t*)0)->f))
|
||||
#define IMAGE_FIRST_SECTION(h) ((PIMAGE_SECTION_HEADER) ((DWORD)h+FIELD_OFFSET(IMAGE_NT_HEADERS,OptionalHeader)+((PIMAGE_NT_HEADERS)(h))->FileHeader.SizeOfOptionalHeader))
|
||||
#define IMAGE_DIRECTORY_ENTRY_EXPORT 0
|
||||
|
||||
#pragma pack(push,2)
|
||||
typedef struct _IMAGE_DOS_HEADER {
|
||||
WORD e_magic;
|
||||
WORD e_cblp;
|
||||
WORD e_cp;
|
||||
WORD e_crlc;
|
||||
WORD e_cparhdr;
|
||||
WORD e_minalloc;
|
||||
WORD e_maxalloc;
|
||||
WORD e_ss;
|
||||
WORD e_sp;
|
||||
WORD e_csum;
|
||||
WORD e_ip;
|
||||
WORD e_cs;
|
||||
WORD e_lfarlc;
|
||||
WORD e_ovno;
|
||||
WORD e_res[4];
|
||||
WORD e_oemid;
|
||||
WORD e_oeminfo;
|
||||
WORD e_res2[10];
|
||||
LONG e_lfanew;
|
||||
} IMAGE_DOS_HEADER,*PIMAGE_DOS_HEADER;
|
||||
#pragma pack(pop)
|
||||
#pragma pack(push,4)
|
||||
typedef struct _IMAGE_EXPORT_DIRECTORY {
|
||||
DWORD Characteristics;
|
||||
DWORD TimeDateStamp;
|
||||
WORD MajorVersion;
|
||||
WORD MinorVersion;
|
||||
DWORD Name;
|
||||
DWORD Base;
|
||||
DWORD NumberOfFunctions;
|
||||
DWORD NumberOfNames;
|
||||
DWORD AddressOfFunctions;
|
||||
DWORD AddressOfNames;
|
||||
DWORD AddressOfNameOrdinals;
|
||||
} IMAGE_EXPORT_DIRECTORY,*PIMAGE_EXPORT_DIRECTORY;
|
||||
typedef struct _IMAGE_FILE_HEADER {
|
||||
WORD Machine;
|
||||
WORD NumberOfSections;
|
||||
DWORD TimeDateStamp;
|
||||
DWORD PointerToSymbolTable;
|
||||
DWORD NumberOfSymbols;
|
||||
WORD SizeOfOptionalHeader;
|
||||
WORD Characteristics;
|
||||
} IMAGE_FILE_HEADER, *PIMAGE_FILE_HEADER;
|
||||
typedef struct _IMAGE_DATA_DIRECTORY {
|
||||
DWORD VirtualAddress;
|
||||
DWORD Size;
|
||||
} IMAGE_DATA_DIRECTORY,*PIMAGE_DATA_DIRECTORY;
|
||||
typedef struct _IMAGE_OPTIONAL_HEADER {
|
||||
WORD Magic;
|
||||
BYTE MajorLinkerVersion;
|
||||
BYTE MinorLinkerVersion;
|
||||
DWORD SizeOfCode;
|
||||
DWORD SizeOfInitializedData;
|
||||
DWORD SizeOfUninitializedData;
|
||||
DWORD AddressOfEntryPoint;
|
||||
DWORD BaseOfCode;
|
||||
DWORD BaseOfData;
|
||||
DWORD ImageBase;
|
||||
DWORD SectionAlignment;
|
||||
DWORD FileAlignment;
|
||||
WORD MajorOperatingSystemVersion;
|
||||
WORD MinorOperatingSystemVersion;
|
||||
WORD MajorImageVersion;
|
||||
WORD MinorImageVersion;
|
||||
WORD MajorSubsystemVersion;
|
||||
WORD MinorSubsystemVersion;
|
||||
DWORD Reserved1;
|
||||
DWORD SizeOfImage;
|
||||
DWORD SizeOfHeaders;
|
||||
DWORD CheckSum;
|
||||
WORD Subsystem;
|
||||
WORD DllCharacteristics;
|
||||
DWORD SizeOfStackReserve;
|
||||
DWORD SizeOfStackCommit;
|
||||
DWORD SizeOfHeapReserve;
|
||||
DWORD SizeOfHeapCommit;
|
||||
DWORD LoaderFlags;
|
||||
DWORD NumberOfRvaAndSizes;
|
||||
IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];
|
||||
} IMAGE_OPTIONAL_HEADER,*PIMAGE_OPTIONAL_HEADER;
|
||||
typedef struct _IMAGE_NT_HEADERS {
|
||||
DWORD Signature;
|
||||
IMAGE_FILE_HEADER FileHeader;
|
||||
IMAGE_OPTIONAL_HEADER OptionalHeader;
|
||||
} IMAGE_NT_HEADERS,*PIMAGE_NT_HEADERS;
|
||||
typedef struct _IMAGE_SECTION_HEADER {
|
||||
BYTE Name[IMAGE_SIZEOF_SHORT_NAME];
|
||||
union {
|
||||
DWORD PhysicalAddress;
|
||||
DWORD VirtualSize;
|
||||
} Misc;
|
||||
DWORD VirtualAddress;
|
||||
DWORD SizeOfRawData;
|
||||
DWORD PointerToRawData;
|
||||
DWORD PointerToRelocations;
|
||||
DWORD PointerToLinenumbers;
|
||||
WORD NumberOfRelocations;
|
||||
WORD NumberOfLinenumbers;
|
||||
DWORD Characteristics;
|
||||
} IMAGE_SECTION_HEADER,*PIMAGE_SECTION_HEADER;
|
||||
#pragma pack(pop)
|
||||
|
||||
/* End of ripped definitions */
|
||||
|
||||
typedef struct _export_t {
|
||||
DWORD name;
|
||||
WORD ordinal;
|
||||
} export_t;
|
||||
|
||||
unsigned char *buffer;
|
||||
PIMAGE_DOS_HEADER dos_header;
|
||||
PIMAGE_NT_HEADERS nt_header;
|
||||
|
||||
void *rva_to_ptr(DWORD rva)
|
||||
{
|
||||
PIMAGE_SECTION_HEADER section_header;
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0, section_header = IMAGE_FIRST_SECTION(nt_header);
|
||||
i < nt_header->OptionalHeader.NumberOfRvaAndSizes;
|
||||
i++, section_header++)
|
||||
{
|
||||
if (rva >= section_header->VirtualAddress &&
|
||||
rva < section_header->VirtualAddress +
|
||||
section_header->Misc.VirtualSize)
|
||||
{
|
||||
return buffer + rva - section_header->VirtualAddress +
|
||||
section_header->PointerToRawData;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int export_compare_func(const void *a, const void *b)
|
||||
{
|
||||
const export_t *ap = a;
|
||||
const export_t *bp = b;
|
||||
char *an = rva_to_ptr(ap->name);
|
||||
char *bn = rva_to_ptr(bp->name);
|
||||
return strcmp(an, bn);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int fd_in, fd_out;
|
||||
long len;
|
||||
PIMAGE_SECTION_HEADER section_header;
|
||||
PIMAGE_DATA_DIRECTORY data_dir;
|
||||
unsigned int i;
|
||||
unsigned long checksum;
|
||||
int fixup_exports = 0;
|
||||
int fixup_sections = 0;
|
||||
|
||||
/*
|
||||
* Process parameters.
|
||||
*/
|
||||
|
||||
if (argc < 2)
|
||||
{
|
||||
printf("Usage: %s <filename> <options>\n"
|
||||
"Options:\n"
|
||||
" -sections Sets section flags for PE image.\n"
|
||||
" -exports Sort the names in export table.\n",
|
||||
argv[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
for (i = 2; i < argc; i++)
|
||||
{
|
||||
if (!strcmp(argv[i], "-sections"))
|
||||
fixup_sections = 1;
|
||||
else if (!strcmp(argv[i], "-exports"))
|
||||
fixup_exports = 1;
|
||||
else
|
||||
{ printf("Invalid option: %s\n", argv[i]); return 1; }
|
||||
}
|
||||
|
||||
if (fixup_sections == 0 && fixup_exports == 0)
|
||||
{
|
||||
printf("Nothing to do.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Read the whole file to memory.
|
||||
*/
|
||||
|
||||
fd_in = open(argv[1], O_RDONLY | O_BINARY);
|
||||
if (fd_in == 0)
|
||||
{
|
||||
printf("Can't open input file.\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
len = lseek(fd_in, 0, SEEK_END);
|
||||
if (len < sizeof(IMAGE_DOS_HEADER))
|
||||
{
|
||||
close(fd_in);
|
||||
printf("'%s' isn't a PE image.\n", argv[1]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
buffer = malloc((len + 1) & ~1);
|
||||
if (buffer == NULL)
|
||||
{
|
||||
close(fd_in);
|
||||
printf("Not enough memory available.\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Read the whole input file into a buffer */
|
||||
lseek(fd_in, 0, SEEK_SET);
|
||||
read(fd_in, buffer, len);
|
||||
if (len & 1)
|
||||
buffer[len] = 0;
|
||||
|
||||
close(fd_in);
|
||||
|
||||
/*
|
||||
* Check the headers and save pointers to them.
|
||||
*/
|
||||
|
||||
dos_header = (PIMAGE_DOS_HEADER)buffer;
|
||||
nt_header = (PIMAGE_NT_HEADERS)(buffer + dos_header->e_lfanew);
|
||||
|
||||
if (dos_header->e_magic != IMAGE_DOS_SIGNATURE ||
|
||||
nt_header->Signature != IMAGE_NT_SIGNATURE)
|
||||
{
|
||||
printf("'%s' isn't a PE image.\n", argv[1]);
|
||||
free(buffer);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (fixup_exports)
|
||||
{
|
||||
/* Sort export directory */
|
||||
data_dir = &nt_header->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT];
|
||||
if (data_dir->Size != 0)
|
||||
{
|
||||
PIMAGE_EXPORT_DIRECTORY export_directory;
|
||||
DWORD *name_ptr;
|
||||
WORD *ordinal_ptr;
|
||||
export_t *exports;
|
||||
|
||||
export_directory = (PIMAGE_EXPORT_DIRECTORY)rva_to_ptr(data_dir->VirtualAddress);
|
||||
if (export_directory != NULL)
|
||||
{
|
||||
exports = malloc(sizeof(export_t) * export_directory->NumberOfNames);
|
||||
if (exports == NULL)
|
||||
{
|
||||
printf("Not enough memory.\n");
|
||||
free(buffer);
|
||||
return 1;
|
||||
}
|
||||
|
||||
name_ptr = (DWORD *)rva_to_ptr(export_directory->AddressOfNames);
|
||||
ordinal_ptr = (WORD *)rva_to_ptr(export_directory->AddressOfNameOrdinals);
|
||||
|
||||
for (i = 0; i < export_directory->NumberOfNames; i++)
|
||||
{
|
||||
exports[i].name = name_ptr[i];
|
||||
exports[i].ordinal = ordinal_ptr[i];
|
||||
}
|
||||
|
||||
qsort(exports, export_directory->NumberOfNames, sizeof(export_t),
|
||||
export_compare_func);
|
||||
|
||||
for (i = 0; i < export_directory->NumberOfNames; i++)
|
||||
{
|
||||
name_ptr[i] = exports[i].name;
|
||||
ordinal_ptr[i] = exports[i].ordinal;
|
||||
}
|
||||
|
||||
free(exports);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (fixup_sections)
|
||||
{
|
||||
/* Update section flags */
|
||||
for (i = 0, section_header = IMAGE_FIRST_SECTION(nt_header);
|
||||
i < nt_header->OptionalHeader.NumberOfRvaAndSizes;
|
||||
i++, section_header++)
|
||||
{
|
||||
if (!strcmp((char*)section_header->Name, ".text") ||
|
||||
!strcmp((char*)section_header->Name, ".data") ||
|
||||
!strcmp((char*)section_header->Name, ".idata") ||
|
||||
!strcmp((char*)section_header->Name, ".bss"))
|
||||
{
|
||||
section_header->Characteristics |= IMAGE_SCN_MEM_NOT_PAGED;
|
||||
section_header->Characteristics &= ~IMAGE_SCN_MEM_DISCARDABLE;
|
||||
}
|
||||
else if (!strcmp((char*)section_header->Name, "INIT"))
|
||||
{
|
||||
section_header->Characteristics |= IMAGE_SCN_MEM_DISCARDABLE;
|
||||
}
|
||||
else if (!strcmp((char*)section_header->Name, "PAGE"))
|
||||
{
|
||||
section_header->Characteristics |= IMAGE_SCN_MEM_NOT_PAGED;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Recalculate checksum */
|
||||
nt_header->OptionalHeader.CheckSum = 0;
|
||||
checksum = 0;
|
||||
for (i = 0; i < len; i += 2)
|
||||
{
|
||||
checksum += *(unsigned short *)(buffer + i);
|
||||
checksum = (checksum + (checksum >> 16)) & 0xffff;
|
||||
}
|
||||
checksum += len;
|
||||
nt_header->OptionalHeader.CheckSum = checksum;
|
||||
|
||||
/* Write the output file */
|
||||
fd_out = open(argv[1], O_WRONLY | O_BINARY);
|
||||
write(fd_out, buffer, len);
|
||||
close(fd_out);
|
||||
|
||||
return 0;
|
||||
}
|
||||
/*
|
||||
* PE Fixup Utility
|
||||
* Copyright (C) 2005 Filip Navara
|
||||
*
|
||||
* The purpose of this utility is fix PE binaries generated by binutils and
|
||||
* to manipulate flags that can't be set by binutils.
|
||||
*
|
||||
* Currently two features are implemented:
|
||||
*
|
||||
* - Setting flags on PE sections for use by drivers. The sections
|
||||
* .text, .data, .idata, .bss are marked as non-pageable and
|
||||
* non-discarable, section PAGE is marked as pageable and section
|
||||
* INIT is marked as discaradable.
|
||||
*
|
||||
* - Sorting of export name table in executables. DLLTOOL has bug
|
||||
* in sorting algorithm when the --kill-at flag is used. The exports
|
||||
* are sorted in the decorated form and so the fastcall symbols are
|
||||
* incorrectly put at the beginning of export table. This option
|
||||
* allow to correct sort the table, so binary search can be used
|
||||
* to process them.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#ifndef O_BINARY
|
||||
#define O_BINARY 0
|
||||
#endif
|
||||
|
||||
/* The following definitions are ripped from MinGW W32API headers. We don't
|
||||
use these headers directly in order to allow compilation on Linux hosts. */
|
||||
|
||||
typedef unsigned char BYTE;
|
||||
typedef unsigned short WORD;
|
||||
typedef unsigned int DWORD;
|
||||
typedef int LONG;
|
||||
|
||||
#define IMAGE_NUMBEROF_DIRECTORY_ENTRIES 16
|
||||
#define IMAGE_SIZEOF_SHORT_NAME 8
|
||||
#define IMAGE_DOS_SIGNATURE 0x5A4D
|
||||
#define IMAGE_NT_SIGNATURE 0x00004550
|
||||
#define IMAGE_SCN_MEM_DISCARDABLE 0x2000000
|
||||
#define IMAGE_SCN_MEM_NOT_PAGED 0x8000000
|
||||
#define FIELD_OFFSET(t,f) ((LONG)&(((t*)0)->f))
|
||||
#define IMAGE_FIRST_SECTION(h) ((PIMAGE_SECTION_HEADER) ((DWORD)h+FIELD_OFFSET(IMAGE_NT_HEADERS,OptionalHeader)+((PIMAGE_NT_HEADERS)(h))->FileHeader.SizeOfOptionalHeader))
|
||||
#define IMAGE_DIRECTORY_ENTRY_EXPORT 0
|
||||
|
||||
#pragma pack(push,2)
|
||||
typedef struct _IMAGE_DOS_HEADER {
|
||||
WORD e_magic;
|
||||
WORD e_cblp;
|
||||
WORD e_cp;
|
||||
WORD e_crlc;
|
||||
WORD e_cparhdr;
|
||||
WORD e_minalloc;
|
||||
WORD e_maxalloc;
|
||||
WORD e_ss;
|
||||
WORD e_sp;
|
||||
WORD e_csum;
|
||||
WORD e_ip;
|
||||
WORD e_cs;
|
||||
WORD e_lfarlc;
|
||||
WORD e_ovno;
|
||||
WORD e_res[4];
|
||||
WORD e_oemid;
|
||||
WORD e_oeminfo;
|
||||
WORD e_res2[10];
|
||||
LONG e_lfanew;
|
||||
} IMAGE_DOS_HEADER,*PIMAGE_DOS_HEADER;
|
||||
#pragma pack(pop)
|
||||
#pragma pack(push,4)
|
||||
typedef struct _IMAGE_EXPORT_DIRECTORY {
|
||||
DWORD Characteristics;
|
||||
DWORD TimeDateStamp;
|
||||
WORD MajorVersion;
|
||||
WORD MinorVersion;
|
||||
DWORD Name;
|
||||
DWORD Base;
|
||||
DWORD NumberOfFunctions;
|
||||
DWORD NumberOfNames;
|
||||
DWORD AddressOfFunctions;
|
||||
DWORD AddressOfNames;
|
||||
DWORD AddressOfNameOrdinals;
|
||||
} IMAGE_EXPORT_DIRECTORY,*PIMAGE_EXPORT_DIRECTORY;
|
||||
typedef struct _IMAGE_FILE_HEADER {
|
||||
WORD Machine;
|
||||
WORD NumberOfSections;
|
||||
DWORD TimeDateStamp;
|
||||
DWORD PointerToSymbolTable;
|
||||
DWORD NumberOfSymbols;
|
||||
WORD SizeOfOptionalHeader;
|
||||
WORD Characteristics;
|
||||
} IMAGE_FILE_HEADER, *PIMAGE_FILE_HEADER;
|
||||
typedef struct _IMAGE_DATA_DIRECTORY {
|
||||
DWORD VirtualAddress;
|
||||
DWORD Size;
|
||||
} IMAGE_DATA_DIRECTORY,*PIMAGE_DATA_DIRECTORY;
|
||||
typedef struct _IMAGE_OPTIONAL_HEADER {
|
||||
WORD Magic;
|
||||
BYTE MajorLinkerVersion;
|
||||
BYTE MinorLinkerVersion;
|
||||
DWORD SizeOfCode;
|
||||
DWORD SizeOfInitializedData;
|
||||
DWORD SizeOfUninitializedData;
|
||||
DWORD AddressOfEntryPoint;
|
||||
DWORD BaseOfCode;
|
||||
DWORD BaseOfData;
|
||||
DWORD ImageBase;
|
||||
DWORD SectionAlignment;
|
||||
DWORD FileAlignment;
|
||||
WORD MajorOperatingSystemVersion;
|
||||
WORD MinorOperatingSystemVersion;
|
||||
WORD MajorImageVersion;
|
||||
WORD MinorImageVersion;
|
||||
WORD MajorSubsystemVersion;
|
||||
WORD MinorSubsystemVersion;
|
||||
DWORD Reserved1;
|
||||
DWORD SizeOfImage;
|
||||
DWORD SizeOfHeaders;
|
||||
DWORD CheckSum;
|
||||
WORD Subsystem;
|
||||
WORD DllCharacteristics;
|
||||
DWORD SizeOfStackReserve;
|
||||
DWORD SizeOfStackCommit;
|
||||
DWORD SizeOfHeapReserve;
|
||||
DWORD SizeOfHeapCommit;
|
||||
DWORD LoaderFlags;
|
||||
DWORD NumberOfRvaAndSizes;
|
||||
IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];
|
||||
} IMAGE_OPTIONAL_HEADER,*PIMAGE_OPTIONAL_HEADER;
|
||||
typedef struct _IMAGE_NT_HEADERS {
|
||||
DWORD Signature;
|
||||
IMAGE_FILE_HEADER FileHeader;
|
||||
IMAGE_OPTIONAL_HEADER OptionalHeader;
|
||||
} IMAGE_NT_HEADERS,*PIMAGE_NT_HEADERS;
|
||||
typedef struct _IMAGE_SECTION_HEADER {
|
||||
BYTE Name[IMAGE_SIZEOF_SHORT_NAME];
|
||||
union {
|
||||
DWORD PhysicalAddress;
|
||||
DWORD VirtualSize;
|
||||
} Misc;
|
||||
DWORD VirtualAddress;
|
||||
DWORD SizeOfRawData;
|
||||
DWORD PointerToRawData;
|
||||
DWORD PointerToRelocations;
|
||||
DWORD PointerToLinenumbers;
|
||||
WORD NumberOfRelocations;
|
||||
WORD NumberOfLinenumbers;
|
||||
DWORD Characteristics;
|
||||
} IMAGE_SECTION_HEADER,*PIMAGE_SECTION_HEADER;
|
||||
#pragma pack(pop)
|
||||
|
||||
/* End of ripped definitions */
|
||||
|
||||
typedef struct _export_t {
|
||||
DWORD name;
|
||||
WORD ordinal;
|
||||
} export_t;
|
||||
|
||||
unsigned char *buffer;
|
||||
PIMAGE_DOS_HEADER dos_header;
|
||||
PIMAGE_NT_HEADERS nt_header;
|
||||
|
||||
void *rva_to_ptr(DWORD rva)
|
||||
{
|
||||
PIMAGE_SECTION_HEADER section_header;
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0, section_header = IMAGE_FIRST_SECTION(nt_header);
|
||||
i < nt_header->OptionalHeader.NumberOfRvaAndSizes;
|
||||
i++, section_header++)
|
||||
{
|
||||
if (rva >= section_header->VirtualAddress &&
|
||||
rva < section_header->VirtualAddress +
|
||||
section_header->Misc.VirtualSize)
|
||||
{
|
||||
return buffer + rva - section_header->VirtualAddress +
|
||||
section_header->PointerToRawData;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int export_compare_func(const void *a, const void *b)
|
||||
{
|
||||
const export_t *ap = a;
|
||||
const export_t *bp = b;
|
||||
char *an = rva_to_ptr(ap->name);
|
||||
char *bn = rva_to_ptr(bp->name);
|
||||
return strcmp(an, bn);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int fd_in, fd_out;
|
||||
long len;
|
||||
PIMAGE_SECTION_HEADER section_header;
|
||||
PIMAGE_DATA_DIRECTORY data_dir;
|
||||
unsigned int i;
|
||||
unsigned long checksum;
|
||||
int fixup_exports = 0;
|
||||
int fixup_sections = 0;
|
||||
|
||||
/*
|
||||
* Process parameters.
|
||||
*/
|
||||
|
||||
if (argc < 2)
|
||||
{
|
||||
printf("Usage: %s <filename> <options>\n"
|
||||
"Options:\n"
|
||||
" -sections Sets section flags for PE image.\n"
|
||||
" -exports Sort the names in export table.\n",
|
||||
argv[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
for (i = 2; i < argc; i++)
|
||||
{
|
||||
if (!strcmp(argv[i], "-sections"))
|
||||
fixup_sections = 1;
|
||||
else if (!strcmp(argv[i], "-exports"))
|
||||
fixup_exports = 1;
|
||||
else
|
||||
{ printf("Invalid option: %s\n", argv[i]); return 1; }
|
||||
}
|
||||
|
||||
if (fixup_sections == 0 && fixup_exports == 0)
|
||||
{
|
||||
printf("Nothing to do.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Read the whole file to memory.
|
||||
*/
|
||||
|
||||
fd_in = open(argv[1], O_RDONLY | O_BINARY);
|
||||
if (fd_in == 0)
|
||||
{
|
||||
printf("Can't open input file.\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
len = lseek(fd_in, 0, SEEK_END);
|
||||
if (len < sizeof(IMAGE_DOS_HEADER))
|
||||
{
|
||||
close(fd_in);
|
||||
printf("'%s' isn't a PE image.\n", argv[1]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
buffer = malloc((len + 1) & ~1);
|
||||
if (buffer == NULL)
|
||||
{
|
||||
close(fd_in);
|
||||
printf("Not enough memory available.\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Read the whole input file into a buffer */
|
||||
lseek(fd_in, 0, SEEK_SET);
|
||||
read(fd_in, buffer, len);
|
||||
if (len & 1)
|
||||
buffer[len] = 0;
|
||||
|
||||
close(fd_in);
|
||||
|
||||
/*
|
||||
* Check the headers and save pointers to them.
|
||||
*/
|
||||
|
||||
dos_header = (PIMAGE_DOS_HEADER)buffer;
|
||||
nt_header = (PIMAGE_NT_HEADERS)(buffer + dos_header->e_lfanew);
|
||||
|
||||
if (dos_header->e_magic != IMAGE_DOS_SIGNATURE ||
|
||||
nt_header->Signature != IMAGE_NT_SIGNATURE)
|
||||
{
|
||||
printf("'%s' isn't a PE image.\n", argv[1]);
|
||||
free(buffer);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (fixup_exports)
|
||||
{
|
||||
/* Sort export directory */
|
||||
data_dir = &nt_header->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT];
|
||||
if (data_dir->Size != 0)
|
||||
{
|
||||
PIMAGE_EXPORT_DIRECTORY export_directory;
|
||||
DWORD *name_ptr;
|
||||
WORD *ordinal_ptr;
|
||||
export_t *exports;
|
||||
|
||||
export_directory = (PIMAGE_EXPORT_DIRECTORY)rva_to_ptr(data_dir->VirtualAddress);
|
||||
if (export_directory != NULL)
|
||||
{
|
||||
exports = malloc(sizeof(export_t) * export_directory->NumberOfNames);
|
||||
if (exports == NULL)
|
||||
{
|
||||
printf("Not enough memory.\n");
|
||||
free(buffer);
|
||||
return 1;
|
||||
}
|
||||
|
||||
name_ptr = (DWORD *)rva_to_ptr(export_directory->AddressOfNames);
|
||||
ordinal_ptr = (WORD *)rva_to_ptr(export_directory->AddressOfNameOrdinals);
|
||||
|
||||
for (i = 0; i < export_directory->NumberOfNames; i++)
|
||||
{
|
||||
exports[i].name = name_ptr[i];
|
||||
exports[i].ordinal = ordinal_ptr[i];
|
||||
}
|
||||
|
||||
qsort(exports, export_directory->NumberOfNames, sizeof(export_t),
|
||||
export_compare_func);
|
||||
|
||||
for (i = 0; i < export_directory->NumberOfNames; i++)
|
||||
{
|
||||
name_ptr[i] = exports[i].name;
|
||||
ordinal_ptr[i] = exports[i].ordinal;
|
||||
}
|
||||
|
||||
free(exports);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (fixup_sections)
|
||||
{
|
||||
/* Update section flags */
|
||||
for (i = 0, section_header = IMAGE_FIRST_SECTION(nt_header);
|
||||
i < nt_header->OptionalHeader.NumberOfRvaAndSizes;
|
||||
i++, section_header++)
|
||||
{
|
||||
if (!strcmp((char*)section_header->Name, ".text") ||
|
||||
!strcmp((char*)section_header->Name, ".data") ||
|
||||
!strcmp((char*)section_header->Name, ".idata") ||
|
||||
!strcmp((char*)section_header->Name, ".bss"))
|
||||
{
|
||||
section_header->Characteristics |= IMAGE_SCN_MEM_NOT_PAGED;
|
||||
section_header->Characteristics &= ~IMAGE_SCN_MEM_DISCARDABLE;
|
||||
}
|
||||
else if (!strcmp((char*)section_header->Name, "INIT"))
|
||||
{
|
||||
section_header->Characteristics |= IMAGE_SCN_MEM_DISCARDABLE;
|
||||
}
|
||||
else if (!strcmp((char*)section_header->Name, "PAGE"))
|
||||
{
|
||||
section_header->Characteristics |= IMAGE_SCN_MEM_NOT_PAGED;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Recalculate checksum */
|
||||
nt_header->OptionalHeader.CheckSum = 0;
|
||||
checksum = 0;
|
||||
for (i = 0; i < len; i += 2)
|
||||
{
|
||||
checksum += *(unsigned short *)(buffer + i);
|
||||
checksum = (checksum + (checksum >> 16)) & 0xffff;
|
||||
}
|
||||
checksum += len;
|
||||
nt_header->OptionalHeader.CheckSum = checksum;
|
||||
|
||||
/* Write the output file */
|
||||
fd_out = open(argv[1], O_WRONLY | O_BINARY);
|
||||
write(fd_out, buffer, len);
|
||||
close(fd_out);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue