ReactOS  0.4.15-dev-1150-g593bcce
pefixup.c
Go to the documentation of this file.
1 /*
2  * PE Fixup Utility
3  * Copyright (C) 2005 Filip Navara
4  * Copyright (C) 2020 Mark Jansen
5  *
6  * The purpose of this utility is fix PE binaries generated by binutils and
7  * to manipulate flags that can't be set by binutils.
8  *
9  * Currently one features is implemented:
10  *
11  * - Updating the PE header to use a LOAD_CONFIG,
12  * when the struct is exported with the name '_load_config_used'
13  */
14 
15 #include <stdio.h>
16 #include <stdlib.h>
17 #include <string.h>
18 
19 // host_includes
20 #include <typedefs.h>
21 #include <pecoff.h>
22 #include "../../dll/win32/dbghelp/compat.h"
23 
24 static const char* g_ApplicationName;
25 static const char* g_Target;
26 
27 void *rva_to_ptr(unsigned char *buffer, PIMAGE_NT_HEADERS nt_header, DWORD rva)
28 {
29  unsigned int i;
31 
32  for (i = 0; i < nt_header->FileHeader.NumberOfSections; i++, section_header++)
33  {
34  if (rva >= section_header->VirtualAddress &&
35  rva < section_header->VirtualAddress + section_header->Misc.VirtualSize)
36  {
37  return buffer + rva - section_header->VirtualAddress + section_header->PointerToRawData;
38  }
39  }
40 
41  return NULL;
42 }
43 
44 static void error(const char* message, ...)
45 {
46  va_list args;
47 
48  fprintf(stderr, "%s ERROR: '%s': ", g_ApplicationName, g_Target);
49 
52  va_end(args);
53 }
54 
55 static void fix_checksum(unsigned char *buffer, long len, PIMAGE_NT_HEADERS nt_header)
56 {
57  unsigned int checksum = 0;
58  long n;
59 
61 
62  for (n = 0; n < len; n += 2)
63  {
64  checksum += *(unsigned short *)(buffer + n);
65  checksum = (checksum + (checksum >> 16)) & 0xffff;
66  }
67 
68  checksum += len;
70 }
71 
72 static int add_loadconfig(unsigned char *buffer, PIMAGE_NT_HEADERS nt_header)
73 {
75  PIMAGE_EXPORT_DIRECTORY export_directory;
76 
78  if (export_dir->Size != 0)
79  {
80  export_directory = rva_to_ptr(buffer, nt_header, export_dir->VirtualAddress);
81  if (export_directory != NULL)
82  {
83  DWORD *name_ptr, *function_ptr, n;
84  WORD *ordinal_ptr;
85 
86  name_ptr = rva_to_ptr(buffer, nt_header, export_directory->AddressOfNames);
87  ordinal_ptr = rva_to_ptr(buffer, nt_header, export_directory->AddressOfNameOrdinals);
88  function_ptr = rva_to_ptr(buffer, nt_header, export_directory->AddressOfFunctions);
89 
90  for (n = 0; n < export_directory->NumberOfNames; n++)
91  {
92  const char* name = rva_to_ptr(buffer, nt_header, name_ptr[n]);
93  if (!strcmp(name, "_load_config_used"))
94  {
95  PIMAGE_DATA_DIRECTORY load_config_dir;
96  DWORD load_config_rva = function_ptr[ordinal_ptr[n]];
97  DWORD* load_config_ptr = rva_to_ptr(buffer, nt_header, load_config_rva);
98 
99  /* Update the DataDirectory pointer / size
100  The first entry of the LOAD_CONFIG struct is the size, use that as DataDirectory.Size */
102  load_config_dir->VirtualAddress = load_config_rva;
103  load_config_dir->Size = *load_config_ptr;
104 
105  return 0;
106  }
107  }
108 
109  error("Export '_load_config_used' not found\n");
110  }
111  else
112  {
113  error("Invalid rva for export directory\n");
114  }
115  }
116  else
117  {
118  error("No export directory\n");
119  }
120 
121  return 1;
122 }
123 
124 int main(int argc, char **argv)
125 {
126  FILE* file;
127  long len;
128  unsigned char *buffer;
130  int result = 1;
131 
132  g_ApplicationName = argv[0];
133 
134  if (argc < 2)
135  {
136  printf("Usage: %s <filename>\n", g_ApplicationName);
137  return 1;
138  }
139 
140  g_Target = argv[1];
141 
142  /* Read the whole file to memory. */
143  file = fopen(argv[1], "r+b");
144  if (!file)
145  {
146  fprintf(stderr, "%s ERROR: Can't open '%s'.\n", g_ApplicationName, g_Target);
147  return 1;
148  }
149 
150  fseek(file, 0, SEEK_END);
151  len = ftell(file);
152  if (len < sizeof(IMAGE_DOS_HEADER))
153  {
154  fclose(file);
155  error("Image size too small to be a PE image\n");
156  return 1;
157  }
158 
159  /* Add one byte extra for the case where the input file size is odd.
160  We rely on this in our crc calculation */
161  buffer = calloc(len + 1, 1);
162  if (buffer == NULL)
163  {
164  fclose(file);
165  error("Not enough memory available: (Needed %u bytes).\n", len + 1);
166  return 1;
167  }
168 
169  /* Read the whole input file into a buffer */
170  fseek(file, 0, SEEK_SET);
171  fread(buffer, 1, len, file);
172 
173  /* Check the headers and save pointers to them. */
176  {
178 
180 
182  {
184  {
186 
187  /* We could 'optimize by only writing the changed parts, but keep it simple for now */
188  fseek(file, 0, SEEK_SET);
189  fwrite(buffer, 1, len, file);
190 
191  /* Success */
192  result = 0;
193  }
194  else
195  {
196  /* Error already printed inside add_loadconfig */
197  }
198  }
199  else
200  {
201  error("Invalid PE signature: %x\n", nt_header->Signature);
202  }
203  }
204  else
205  {
206  error("Invalid DOS signature: %x\n", dos_header->e_magic);
207  }
208 
209  free(buffer);
210  fclose(file);
211 
212  return result;
213 }
int main(int argc, char **argv)
Definition: pefixup.c:124
static int argc
Definition: ServiceArgs.c:12
void * rva_to_ptr(unsigned char *buffer, PIMAGE_NT_HEADERS nt_header, DWORD rva)
Definition: pefixup.c:27
Definition: tftpd.h:59
IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES]
Definition: ntddk_ex.h:178
static const char * g_Target
Definition: pefixup.c:25
#define free
Definition: debug_ros.c:5
GLdouble n
Definition: glext.h:7729
GLuint buffer
Definition: glext.h:5915
DWORD PointerToRawData
Definition: pedump.c:290
_Check_return_opt_ _CRTIMP size_t __cdecl fwrite(_In_reads_bytes_(_Size *_Count) const void *_Str, _In_ size_t _Size, _In_ size_t _Count, _Inout_ FILE *_File)
#define argv
Definition: mplay32.c:18
Definition: match.c:390
DWORD AddressOfNameOrdinals
Definition: compat.h:167
static const char * g_ApplicationName
Definition: pefixup.c:24
#define IMAGE_DOS_SIGNATURE
Definition: pedump.c:89
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
#define IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG
Definition: compat.h:153
_Check_return_opt_ _CRTIMP size_t __cdecl fread(_Out_writes_bytes_(_ElementSize *_Count) void *_DstBuf, _In_ size_t _ElementSize, _In_ size_t _Count, _Inout_ FILE *_File)
#define va_end(ap)
Definition: acmsvcex.h:90
#define IMAGE_FIRST_SECTION(NtHeader)
Definition: ntimage.h:427
_Check_return_opt_ _CRTIMP int __cdecl fprintf(_Inout_ FILE *_File, _In_z_ _Printf_format_string_ const char *_Format,...)
smooth NULL
Definition: ftsmooth.c:416
_Check_return_opt_ _CRTIMP int __cdecl fseek(_Inout_ FILE *_File, _In_ long _Offset, _In_ int _Origin)
union _IMAGE_SECTION_HEADER::@1553 Misc
struct _IMAGE_DOS_HEADER * PIMAGE_DOS_HEADER
char * va_list
Definition: acmsvcex.h:78
static export_section_t export_dir
Definition: data.c:448
IMAGE_FILE_HEADER FileHeader
Definition: ntddk_ex.h:183
#define IMAGE_NT_SIGNATURE
Definition: pedump.c:93
#define SEEK_SET
Definition: jmemansi.c:26
static IMAGE_DOS_HEADER dos_header
Definition: data.c:13
const char file[]
Definition: icontest.c:11
unsigned short WORD
Definition: ntddk_ex.h:93
unsigned long DWORD
Definition: ntddk_ex.h:95
GLenum GLsizei len
Definition: glext.h:6722
_Check_return_opt_ _CRTIMP int __cdecl fclose(_Inout_ FILE *_File)
_Check_return_ _CRTIMP FILE *__cdecl fopen(_In_z_ const char *_Filename, _In_z_ const char *_Mode)
static cab_ULONG checksum(const cab_UBYTE *data, cab_UWORD bytes, cab_ULONG csum)
Definition: fdi.c:353
_In_ ULONG _In_ BOOLEAN _Must_inspect_result_ PVOID * VirtualAddress
Definition: ndis.h:3791
#define IMAGE_DIRECTORY_ENTRY_EXPORT
Definition: compat.h:151
IMAGE_OPTIONAL_HEADER32 OptionalHeader
Definition: ntddk_ex.h:184
static void fix_checksum(unsigned char *buffer, long len, PIMAGE_NT_HEADERS nt_header)
Definition: pefixup.c:55
static int add_loadconfig(unsigned char *buffer, PIMAGE_NT_HEADERS nt_header)
Definition: pefixup.c:72
#define va_start(ap, A)
Definition: acmsvcex.h:91
Definition: name.c:38
#define calloc
Definition: rosglue.h:14
_Check_return_ _CRTIMP long __cdecl ftell(_Inout_ FILE *_File)
FILE * stderr
int strcmp(const char *String1, const char *String2)
Definition: utclib.c:469
#define SEEK_END
Definition: cabinet.c:27
GLuint64EXT * result
Definition: glext.h:11304
#define args
Definition: format.c:66
static IMAGE_NT_HEADERS32 nt_header
Definition: data.c:36
#define printf
Definition: config.h:203
static void error(const char *message,...)
Definition: pefixup.c:44
PIMAGE_NT_HEADERS32 PIMAGE_NT_HEADERS
Definition: ntddk_ex.h:187
Definition: fci.c:126