1 /*
2  *  Copyright (C) 2005-2018 Team Kodi
3  *  This file is part of Kodi - https://kodi.tv
4  *
5  *  SPDX-License-Identifier: GPL-2.0-or-later
6  *  See LICENSES/README.md for more information.
7  */
8 
9 #include <stdlib.h>
10 #include <string.h>
11 #include "coff.h"
12 #include "coffldr.h"
13 
14 //#define DUMPING_DATA 1
15 
16 #ifndef __GNUC__
17 #pragma warning (disable:4806)
18 #endif
19 
20 #include "utils/log.h"
21 #define printf(format, ...) CLog::Log(LOGDEBUG, format , ##__VA_ARGS__)
22 
23 const char *DATA_DIR_NAME[16] =
24   {
25     "Export Table",
26     "Import Table",
27     "Resource Table",
28     "Exception Table",
29     "Certificate Table",
30     "Base Relocation Table",
31     "Debug",
32     "Architecture",
33     "Global Ptr",
34     "TLS Table",
35     "Load Config Table",
36     "Bound Import",
37     "IAT",
38     "Delay Import Descriptor",
39     "COM+ Runtime Header",
40     "Reserved"
41   };
42 
43 
CoffLoader()44 CoffLoader::CoffLoader()
45 {
46   CoffFileHeader = 0;
47   OptionHeader = 0;
48   WindowsHeader = 0;
49   Directory = 0;
50   SectionHeader = 0;
51   SymTable = 0;
52   StringTable = 0;
53   SectionData = 0;
54 
55   NumberOfSymbols = 0;
56   SizeOfStringTable = 0;
57   NumOfDirectories = 0;
58   NumOfSections = 0;
59   FileHeaderOffset = 0;
60   EntryAddress = 0;
61   hModule = NULL;
62 }
63 
~CoffLoader()64 CoffLoader::~CoffLoader()
65 {
66   if ( hModule )
67   {
68 #ifdef TARGET_POSIX
69     free(hModule);
70 #else
71     VirtualFree(hModule, 0, MEM_RELEASE);
72 #endif
73     hModule = NULL;
74   }
75   if ( SymTable )
76   {
77     delete [] SymTable;
78     SymTable = 0;
79   }
80   if ( StringTable )
81   {
82     delete [] StringTable;
83     StringTable = 0;
84   }
85   if ( SectionData )
86   {
87     delete [] SectionData;
88     SectionData = 0;
89   }
90 }
91 
92 // Has nothing to do with the coff loader itself
93 // it can be used to parse the headers of a dll
94 // already loaded into memory
ParseHeaders(void * hModule)95 int CoffLoader::ParseHeaders(void* hModule)
96 {
97   if (strncmp((char*)hModule, "MZ", 2) != 0)
98     return 0;
99 
100   int* Offset = (int*)((char*)hModule+0x3c);
101   if (*Offset <= 0)
102     return 0;
103 
104   if (strncmp((char*)hModule+*Offset, "PE\0\0", 4) != 0)
105     return 0;
106 
107   FileHeaderOffset = *Offset + 4;
108 
109   CoffFileHeader = (COFF_FileHeader_t *) ( (char*)hModule + FileHeaderOffset );
110   NumOfSections = CoffFileHeader->NumberOfSections;
111 
112   OptionHeader = (OptionHeader_t *) ( (char*)CoffFileHeader + sizeof(COFF_FileHeader_t) );
113   WindowsHeader = (WindowsHeader_t *) ( (char*)OptionHeader + OPTHDR_SIZE );
114   EntryAddress = OptionHeader->Entry;
115   NumOfDirectories = WindowsHeader->NumDirectories;
116 
117   Directory = (Image_Data_Directory_t *) ( (char*)WindowsHeader + WINHDR_SIZE);
118   SectionHeader = (SectionHeader_t *) ( (char*)Directory + sizeof(Image_Data_Directory_t) * NumOfDirectories);
119 
120   if (CoffFileHeader->MachineType != IMAGE_FILE_MACHINE_I386)
121     return 0;
122 
123 #ifdef DUMPING_DATA
124   PrintFileHeader(CoffFileHeader);
125 #endif
126 
127   if ( CoffFileHeader->SizeOfOptionHeader == 0 ) //not an image file, object file maybe
128     return 0;
129 
130   // process Option Header
131   if (OptionHeader->Magic == OPTMAGIC_PE32P)
132   {
133     printf("PE32+ not supported\n");
134     return 0;
135   }
136   else if (OptionHeader->Magic == OPTMAGIC_PE32)
137   {
138 
139 #ifdef DUMPING_DATA
140     PrintOptionHeader(OptionHeader);
141     PrintWindowsHeader(WindowsHeader);
142 #endif
143 
144   }
145   else
146   {
147     //add error message
148     return 0;
149   }
150 
151 #ifdef DUMPING_DATA
152   for (int DirCount = 0; DirCount < NumOfDirectories; DirCount++)
153   {
154     printf("Data Directory %02d: %s\n", DirCount + 1, DATA_DIR_NAME[DirCount]);
155     printf("                    RVA:  %08X\n", Directory[DirCount].RVA);
156     printf("                    Size: %08X\n\n", Directory[DirCount].Size);
157   }
158 #endif
159 
160   return 1;
161 
162 }
163 
LoadCoffHModule(FILE * fp)164 int CoffLoader::LoadCoffHModule(FILE *fp)
165 {
166   //test file signatures
167   char Sig[4];
168   rewind(fp);
169   memset(Sig, 0, sizeof(Sig));
170   if (!fread(Sig, 1, 2, fp) || strncmp(Sig, "MZ", 2) != 0)
171     return 0;
172 
173   if (fseek(fp, 0x3c, SEEK_SET) != 0)
174     return 0;
175 
176   int Offset = 0;
177   if (!fread(&Offset, sizeof(int), 1, fp) || (Offset <= 0))
178     return 0;
179 
180   if (fseek(fp, Offset, SEEK_SET) != 0)
181     return 0;
182 
183   memset(Sig, 0, sizeof(Sig));
184   if (!fread(Sig, 1, 4, fp) || strncmp(Sig, "PE\0\0", 4) != 0)
185     return 0;
186 
187   Offset += 4;
188   FileHeaderOffset = Offset;
189 
190   // Load and process Header
191   if (fseek(fp, FileHeaderOffset + sizeof(COFF_FileHeader_t) + OPTHDR_SIZE, SEEK_SET)) //skip to winows headers
192     return 0;
193 
194   WindowsHeader_t tempWindowsHeader;
195   size_t readcount = fread(&tempWindowsHeader, 1, WINHDR_SIZE, fp);
196   if (readcount != WINHDR_SIZE) //test file size error
197     return 0;
198 
199   // alloc aligned memory
200 #ifdef TARGET_POSIX
201   hModule = malloc(tempWindowsHeader.SizeOfImage);
202 #elif defined TARGET_WINDOWS_STORE
203   hModule = VirtualAllocFromApp(GetCurrentProcess(), tempWindowsHeader.SizeOfImage, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
204 #else
205   hModule = VirtualAllocEx(GetCurrentProcess(), (PVOID)tempWindowsHeader.ImageBase, tempWindowsHeader.SizeOfImage, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
206   if (hModule == NULL)
207     hModule = VirtualAlloc(GetCurrentProcess(), tempWindowsHeader.SizeOfImage, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
208 #endif
209   if (hModule == NULL)
210     return 0;   //memory allocation fails
211 
212   rewind(fp);
213   readcount = fread(hModule, 1, tempWindowsHeader.SizeOfHeaders, fp);
214   if (readcount != tempWindowsHeader.SizeOfHeaders)   //file size error
215     return 0;
216 
217   CoffFileHeader = (COFF_FileHeader_t *) ( (char*)hModule + FileHeaderOffset );
218   NumOfSections = CoffFileHeader->NumberOfSections;
219 
220   OptionHeader = (OptionHeader_t *) ( (char*)CoffFileHeader + sizeof(COFF_FileHeader_t) );
221   WindowsHeader = (WindowsHeader_t *) ( (char*)OptionHeader + OPTHDR_SIZE );
222   EntryAddress = OptionHeader->Entry;
223   NumOfDirectories = WindowsHeader->NumDirectories;
224 
225   Directory = (Image_Data_Directory_t *) ( (char*)WindowsHeader + WINHDR_SIZE);
226   SectionHeader = (SectionHeader_t *) ( (char*)Directory + sizeof(Image_Data_Directory_t) * NumOfDirectories);
227 
228   if (CoffFileHeader->MachineType != IMAGE_FILE_MACHINE_I386)
229     return 0;
230 
231 #ifdef DUMPING_DATA
232   PrintFileHeader(CoffFileHeader);
233 #endif
234 
235   if ( CoffFileHeader->SizeOfOptionHeader == 0 ) //not an image file, object file maybe
236     return 0;
237 
238   // process Option Header
239   if (OptionHeader->Magic == OPTMAGIC_PE32P)
240   {
241     printf("PE32+ not supported\n");
242     return 0;
243   }
244   else if (OptionHeader->Magic == OPTMAGIC_PE32)
245   {
246 
247 #ifdef DUMPING_DATA
248     PrintOptionHeader(OptionHeader);
249     PrintWindowsHeader(WindowsHeader);
250 #endif
251 
252   }
253   else
254   {
255     //add error message
256     return 0;
257   }
258 
259 #ifdef DUMPING_DATA
260   for (int DirCount = 0; DirCount < NumOfDirectories; DirCount++)
261   {
262     printf("Data Directory %02d: %s\n", DirCount + 1, DATA_DIR_NAME[DirCount]);
263     printf("                    RVA:  %08X\n", Directory[DirCount].RVA);
264     printf("                    Size: %08X\n\n", Directory[DirCount].Size);
265   }
266 #endif
267 
268   return 1;
269 
270 }
271 
LoadSymTable(FILE * fp)272 int CoffLoader::LoadSymTable(FILE *fp)
273 {
274   int Offset = ftell(fp);
275   if (Offset < 0)
276     return 0;
277 
278   if ( CoffFileHeader->PointerToSymbolTable == 0 )
279     return 1;
280 
281   if (fseek(fp, CoffFileHeader->PointerToSymbolTable /* + CoffBeginOffset*/, SEEK_SET) != 0)
282     return 0;
283 
284   SymbolTable_t *tmp = new SymbolTable_t[CoffFileHeader->NumberOfSymbols];
285   if (!tmp)
286   {
287     printf("Could not allocate memory for symbol table!\n");
288     return 0;
289   }
290   if (!fread((void *)tmp, CoffFileHeader->NumberOfSymbols, sizeof(SymbolTable_t), fp))
291   {
292     delete[] tmp;
293     return 0;
294   }
295   NumberOfSymbols = CoffFileHeader->NumberOfSymbols;
296   SymTable = tmp;
297   if (fseek(fp, Offset, SEEK_SET) != 0)
298     return 0;
299   return 1;
300 }
301 
LoadStringTable(FILE * fp)302 int CoffLoader::LoadStringTable(FILE *fp)
303 {
304   int StringTableSize;
305   char *tmp = NULL;
306 
307   int Offset = ftell(fp);
308   if (Offset < 0)
309     return 0;
310 
311   if ( CoffFileHeader->PointerToSymbolTable == 0 )
312     return 1;
313 
314   if (fseek(fp, CoffFileHeader->PointerToSymbolTable +
315         CoffFileHeader->NumberOfSymbols * sizeof(SymbolTable_t),
316         SEEK_SET) != 0)
317     return 0;
318 
319   if (!fread(&StringTableSize, 1, sizeof(int), fp))
320     return 0;
321   StringTableSize -= 4;
322   if (StringTableSize != 0)
323   {
324     tmp = new char[StringTableSize];
325     if (tmp == NULL)
326     {
327       printf("Could not allocate memory for string table\n");
328       return 0;
329     }
330     if (!fread((void *)tmp, StringTableSize, sizeof(char), fp))
331     {
332       delete[] tmp;
333       return 0;
334     }
335   }
336   SizeOfStringTable = StringTableSize;
337   StringTable = tmp;
338   if (fseek(fp, Offset, SEEK_SET) != 0)
339     return 0;
340   return 1;
341 }
342 
LoadSections(FILE * fp)343 int CoffLoader::LoadSections(FILE *fp)
344 {
345   NumOfSections = CoffFileHeader->NumberOfSections;
346 
347   SectionData = new char * [NumOfSections];
348   if ( !SectionData )
349     return 0;
350 
351   // Bobbin007: for debug dlls this check always fails
352 
353   //////check VMA size!!!!!
354   //unsigned long vma_size = 0;
355   //for (int SctnCnt = 0; SctnCnt < NumOfSections; SctnCnt++)
356   //{
357   //  SectionHeader_t *ScnHdr = (SectionHeader_t *)(SectionHeader + SctnCnt);
358   //  vma_size = max(vma_size, ScnHdr->VirtualAddress + ScnHdr->SizeOfRawData);
359   //  vma_size = max(vma_size, ScnHdr->VirtualAddress + ScnHdr->VirtualSize);
360   //}
361 
362   //if (WindowsHeader->SizeOfImage < vma_size)
363   //  return 0;   //something wrong with file
364 
365   for (int SctnCnt = 0; SctnCnt < NumOfSections; SctnCnt++)
366   {
367     SectionHeader_t *ScnHdr = SectionHeader + SctnCnt;
368     SectionData[SctnCnt] = ((char*)hModule + ScnHdr->VirtualAddress);
369 
370     if (fseek(fp, ScnHdr->PtrToRawData, SEEK_SET) != 0)
371       return 0;
372 
373     if (!fread(SectionData[SctnCnt], 1, ScnHdr->SizeOfRawData, fp))
374       return 0;
375 
376 #ifdef DUMPING_DATA
377     //debug blocks
378     char szBuf[128];
379     char namebuf[9];
380     for (int i = 0; i < 8; i++)
381       namebuf[i] = ScnHdr->Name[i];
382     namebuf[8] = '\0';
383     sprintf(szBuf, "Load code Sections %s Memory %p,Length %x\n", namebuf,
384             SectionData[SctnCnt], max(ScnHdr->VirtualSize, ScnHdr->SizeOfRawData));
385     OutputDebugString(szBuf);
386 #endif
387 
388     if ( ScnHdr->SizeOfRawData < ScnHdr->VirtualSize )  //initialize BSS data in the end of section
389     {
390       memset((char*)((long)(SectionData[SctnCnt]) + ScnHdr->SizeOfRawData), 0, ScnHdr->VirtualSize - ScnHdr->SizeOfRawData);
391     }
392 
393     if (ScnHdr->Characteristics & IMAGE_SCN_CNT_BSS)  //initialize whole .BSS section, pure .BSS is obsolete
394     {
395       memset(SectionData[SctnCnt], 0, ScnHdr->VirtualSize);
396     }
397 
398 #ifdef DUMPING_DATA
399     PrintSection(SectionHeader + SctnCnt, SectionData[SctnCnt]);
400 #endif
401 
402   }
403   return 1;
404 }
405 
406 //FIXME:  Add the Free Resources functions
407 
RVA2Section(unsigned long RVA)408 int CoffLoader::RVA2Section(unsigned long RVA)
409 {
410   NumOfSections = CoffFileHeader->NumberOfSections;
411   for ( int i = 0; i < NumOfSections; i++)
412   {
413     if ( SectionHeader[i].VirtualAddress <= RVA )
414     {
415       if ( i + 1 != NumOfSections )
416       {
417         if ( RVA < SectionHeader[i + 1].VirtualAddress )
418         {
419           if ( SectionHeader[i].VirtualAddress + SectionHeader[i].VirtualSize <= RVA )
420             printf("Warning! Address outside of Section: %lx!\n", RVA);
421           //                    else
422           return i;
423         }
424       }
425       else
426       {
427         if ( SectionHeader[i].VirtualAddress + SectionHeader[i].VirtualSize <= RVA )
428           printf("Warning! Address outside of Section: %lx!\n", RVA);
429         //                else
430         return i;
431       }
432     }
433   }
434   printf("RVA2Section lookup failure!\n");
435   return 0;
436 }
437 
RVA2Data(unsigned long RVA)438 void* CoffLoader::RVA2Data(unsigned long RVA)
439 {
440   int Sctn = RVA2Section(RVA);
441 
442   if( RVA < SectionHeader[Sctn].VirtualAddress
443    || RVA >= SectionHeader[Sctn].VirtualAddress + SectionHeader[Sctn].VirtualSize)
444   {
445     // RVA2Section is lying, let's use base address of dll instead, only works if
446     // DLL has been loaded fully into memory, wich we normally do
447     return (void*)(RVA + (unsigned long)hModule);
448   }
449   return SectionData[Sctn] + RVA - SectionHeader[Sctn].VirtualAddress;
450 }
451 
Data2RVA(void * address)452 unsigned long CoffLoader::Data2RVA(void* address)
453 {
454   for ( int i = 0; i < CoffFileHeader->NumberOfSections; i++)
455   {
456     if(address >= SectionData[i] && address < SectionData[i] + SectionHeader[i].VirtualSize)
457       return (unsigned long)address - (unsigned long)SectionData[i] + SectionHeader[i].VirtualAddress;
458   }
459 
460   // Section wasn't found, so use relative to main load of dll
461   return (unsigned long)address - (unsigned long)hModule;
462 }
463 
GetStringTblIndex(int index)464 char *CoffLoader::GetStringTblIndex(int index)
465 {
466   char *table = StringTable;
467 
468   while (index--)
469     table += strlen(table) + 1;
470   return table;
471 }
472 
GetStringTblOff(int Offset)473 char *CoffLoader::GetStringTblOff(int Offset)
474 {
475   return StringTable + Offset - 4;
476 }
477 
GetSymbolName(SymbolTable_t * sym)478 char *CoffLoader::GetSymbolName(SymbolTable_t *sym)
479 {
480   long long index = sym->Name.Offset;
481   int low = (int)(index & 0xFFFFFFFF);
482   int high = (int)((index >> 32) & 0xFFFFFFFF);
483 
484   if (low == 0)
485   {
486     return GetStringTblOff(high);
487   }
488   else
489   {
490     static char shortname[9];
491     memset(shortname, 0, 9);
492     strncpy(shortname, (char *)sym->Name.ShortName, 8);
493     return shortname;
494   }
495 }
496 
GetSymbolName(int index)497 char *CoffLoader::GetSymbolName(int index)
498 {
499   SymbolTable_t *sym = &(SymTable[index]);
500   return GetSymbolName(sym);
501 }
502 
PrintStringTable(void)503 void CoffLoader::PrintStringTable(void)
504 {
505   int size = SizeOfStringTable;
506   int index = 0;
507   char *table = StringTable;
508 
509   printf("\nSTRING TABLE\n");
510   while (size)
511   {
512     printf("%2d: %s\n", index++, table);
513     size -= strlen(table) + 1;
514     table += strlen(table) + 1;
515   }
516   printf("\n");
517 }
518 
519 
PrintSymbolTable(void)520 void CoffLoader::PrintSymbolTable(void)
521 {
522   int SymIndex;
523 
524   printf("COFF SYMBOL TABLE\n");
525   for (SymIndex = 0; SymIndex < NumberOfSymbols; SymIndex++)
526   {
527     printf("%03X ", SymIndex);
528     printf("%08lX ", SymTable[SymIndex].Value);
529 
530     if (SymTable[SymIndex].SectionNumber == IMAGE_SYM_ABSOLUTE)
531       printf("ABS     ");
532     else if (SymTable[SymIndex].SectionNumber == IMAGE_SYM_DEBUG)
533       printf("DEBUG   ");
534     else if (SymTable[SymIndex].SectionNumber == IMAGE_SYM_UNDEFINED)
535       printf("UNDEF   ");
536     else
537     {
538       printf("SECT%d ", SymTable[SymIndex].SectionNumber);
539       if (SymTable[SymIndex].SectionNumber < 10)
540         printf(" ");
541       if (SymTable[SymIndex].SectionNumber < 100)
542         printf(" ");
543     }
544 
545     if (SymTable[SymIndex].Type == 0)
546       printf("notype       ");
547     else
548     {
549       printf("%X         ", SymTable[SymIndex].Type);
550       if (SymTable[SymIndex].Type < 0x10)
551         printf(" ");
552       if (SymTable[SymIndex].Type < 0x100)
553         printf(" ");
554       if (SymTable[SymIndex].Type < 0x1000)
555         printf(" ");
556     }
557 
558     if (SymTable[SymIndex].StorageClass == IMAGE_SYM_CLASS_END_OF_FUNCTION)
559       printf("End of Function   ");
560     if (SymTable[SymIndex].StorageClass == IMAGE_SYM_CLASS_NULL)
561       printf("Null              ");
562     if (SymTable[SymIndex].StorageClass == IMAGE_SYM_CLASS_AUTOMATIC)
563       printf("Automatic         ");
564     if (SymTable[SymIndex].StorageClass == IMAGE_SYM_CLASS_EXTERNAL)
565       printf("External          ");
566     if (SymTable[SymIndex].StorageClass == IMAGE_SYM_CLASS_STATIC)
567       printf("Static            ");
568     if (SymTable[SymIndex].StorageClass == IMAGE_SYM_CLASS_REGISTER)
569       printf("Register          ");
570     if (SymTable[SymIndex].StorageClass == IMAGE_SYM_CLASS_EXTERNAL_DEF)
571       printf("External Def      ");
572     if (SymTable[SymIndex].StorageClass == IMAGE_SYM_CLASS_LABEL)
573       printf("Label             ");
574     if (SymTable[SymIndex].StorageClass == IMAGE_SYM_CLASS_UNDEFINED_LABEL)
575       printf("Undefined Label   ");
576     if (SymTable[SymIndex].StorageClass == IMAGE_SYM_CLASS_MEMBER_OF_STRUCT)
577       printf("Member Of Struct  ");
578     if (SymTable[SymIndex].StorageClass == IMAGE_SYM_CLASS_ARGUMENT)
579       printf("Argument          ");
580     if (SymTable[SymIndex].StorageClass == IMAGE_SYM_CLASS_STRUCT_TAG)
581       printf("Struct Tag        ");
582     if (SymTable[SymIndex].StorageClass == IMAGE_SYM_CLASS_MEMBER_OF_UNION)
583       printf("Member Of Union   ");
584     if (SymTable[SymIndex].StorageClass == IMAGE_SYM_CLASS_UNION_TAG)
585       printf("Union Tag         ");
586     if (SymTable[SymIndex].StorageClass == IMAGE_SYM_CLASS_TYPE_DEFINITION)
587       printf("Type Definition  ");
588     if (SymTable[SymIndex].StorageClass == IMAGE_SYM_CLASS_UNDEFINED_STATIC)
589       printf("Undefined Static  ");
590     if (SymTable[SymIndex].StorageClass == IMAGE_SYM_CLASS_ENUM_TAG)
591       printf("Enum Tag          ");
592     if (SymTable[SymIndex].StorageClass == IMAGE_SYM_CLASS_MEMBER_OF_ENUM)
593       printf("Member Of Enum    ");
594     if (SymTable[SymIndex].StorageClass == IMAGE_SYM_CLASS_REGISTER_PARAM)
595       printf("Register Param    ");
596     if (SymTable[SymIndex].StorageClass == IMAGE_SYM_CLASS_BIT_FIELD)
597       printf("Bit Field         ");
598     if (SymTable[SymIndex].StorageClass == IMAGE_SYM_CLASS_BLOCK)
599       printf("Block             ");
600     if (SymTable[SymIndex].StorageClass == IMAGE_SYM_CLASS_FUNCTION)
601       printf("Function          ");
602     if (SymTable[SymIndex].StorageClass == IMAGE_SYM_CLASS_END_OF_STRUCT)
603       printf("End Of Struct     ");
604     if (SymTable[SymIndex].StorageClass == IMAGE_SYM_CLASS_FILE)
605       printf("File              ");
606     if (SymTable[SymIndex].StorageClass == IMAGE_SYM_CLASS_SECTION)
607       printf("Section           ");
608     if (SymTable[SymIndex].StorageClass == IMAGE_SYM_CLASS_WEAK_EXTERNAL)
609       printf("Weak External     ");
610 
611     printf("| %s", GetSymbolName(SymIndex));
612 
613     SymIndex += SymTable[SymIndex].NumberOfAuxSymbols;
614     printf("\n");
615   }
616   printf("\n");
617 
618 }
619 
PrintFileHeader(COFF_FileHeader_t * FileHeader)620 void CoffLoader::PrintFileHeader(COFF_FileHeader_t *FileHeader)
621 {
622   printf("COFF Header\n");
623   printf("------------------------------------------\n\n");
624 
625   printf("MachineType:            0x%04X\n", FileHeader->MachineType);
626   printf("NumberOfSections:       0x%04X\n", FileHeader->NumberOfSections);
627   printf("TimeDateStamp:          0x%08lX\n",FileHeader->TimeDateStamp);
628   printf("PointerToSymbolTable:   0x%08lX\n",FileHeader->PointerToSymbolTable);
629   printf("NumberOfSymbols:        0x%08lX\n",FileHeader->NumberOfSymbols);
630   printf("SizeOfOptionHeader:     0x%04X\n", FileHeader->SizeOfOptionHeader);
631   printf("Characteristics:        0x%04X\n", FileHeader->Characteristics);
632 
633   if (FileHeader->Characteristics & IMAGE_FILE_RELOCS_STRIPPED)
634     printf("                        IMAGE_FILE_RELOCS_STRIPPED\n");
635 
636   if (FileHeader->Characteristics & IMAGE_FILE_EXECUTABLE_IMAGE)
637     printf("                        IMAGE_FILE_EXECUTABLE_IMAGE\n");
638 
639   if (FileHeader->Characteristics & IMAGE_FILE_LINE_NUMS_STRIPPED)
640     printf("                        IMAGE_FILE_LINE_NUMS_STRIPPED\n");
641 
642   if (FileHeader->Characteristics & IMAGE_FILE_LOCAL_SYMS_STRIPPED)
643     printf("                        IMAGE_FILE_LOCAL_SYMS_STRIPPED\n");
644 
645   if (FileHeader->Characteristics & IMAGE_FILE_AGGRESSIVE_WS_TRIM)
646     printf("                        IMAGE_FILE_AGGRESSIVE_WS_TRIM\n");
647 
648   if (FileHeader->Characteristics & IMAGE_FILE_LARGE_ADDRESS_AWARE)
649     printf("                        IMAGE_FILE_LARGE_ADDRESS_AWARE\n");
650 
651   if (FileHeader->Characteristics & IMAGE_FILE_16BIT_MACHINE)
652     printf("                        IMAGE_FILE_16BIT_MACHINE\n");
653 
654   if (FileHeader->Characteristics & IMAGE_FILE_BYTES_REVERSED_LO)
655     printf("                        IMAGE_FILE_BYTES_REVERSED_LO\n");
656 
657   if (FileHeader->Characteristics & IMAGE_FILE_32BIT_MACHINE)
658     printf("                        IMAGE_FILE_32BIT_MACHINE\n");
659 
660   if (FileHeader->Characteristics & IMAGE_FILE_DEBUG_STRIPPED)
661     printf("                        IMAGE_FILE_DEBUG_STRIPPED\n");
662 
663   if (FileHeader->Characteristics & IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP)
664     printf("                        IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP\n");
665 
666   if (FileHeader->Characteristics & IMAGE_FILE_SYSTEM)
667     printf("                        IMAGE_FILE_SYSTEM\n");
668 
669   if (FileHeader->Characteristics & IMAGE_FILE_DLL)
670     printf("                        IMAGE_FILE_DLL\n");
671 
672   if (FileHeader->Characteristics & IMAGE_FILE_UP_SYSTEM_ONLY)
673     printf("                        IMAGE_FILE_UP_SYSTEM_ONLY\n");
674 
675   if (FileHeader->Characteristics & IMAGE_FILE_BYTES_REVERSED_HI)
676     printf("                        IMAGE_FILE_BYTES_REVERSED_HI\n");
677 
678   printf("\n");
679 }
680 
PrintOptionHeader(OptionHeader_t * OptHdr)681 void CoffLoader::PrintOptionHeader(OptionHeader_t *OptHdr)
682 {
683   printf("Option Header\n");
684   printf("------------------------------------------\n\n");
685 
686   printf("Magic:              0x%04X\n", OptHdr->Magic);
687   printf("Linker Major Ver:   0x%02X\n", VERSION_MAJOR(OptHdr->LinkVersion));
688   printf("Linker Minor Ver:   0x%02X\n", VERSION_MINOR(OptHdr->LinkVersion));
689   printf("Code Size:          0x%08lX\n", OptHdr->CodeSize);
690   printf("Data Size:          0x%08lX\n", OptHdr->DataSize);
691   printf("BSS Size:           0x%08lX\n", OptHdr->BssSize);
692   printf("Entry:              0x%08lX\n", OptHdr->Entry);
693   printf("Code Base:          0x%08lX\n", OptHdr->CodeBase);
694   printf("Data Base:          0x%08lX\n", OptHdr->DataBase);
695   printf("\n");
696 }
697 
PrintWindowsHeader(WindowsHeader_t * WinHdr)698 void CoffLoader::PrintWindowsHeader(WindowsHeader_t *WinHdr)
699 {
700   printf("Windows Specific Option Header\n");
701   printf("------------------------------------------\n\n");
702 
703   printf("Image Base:         0x%08lX\n", WinHdr->ImageBase);
704   printf("Section Alignment:  0x%08lX\n", WinHdr->SectionAlignment);
705   printf("File Alignment:     0x%08lX\n", WinHdr->FileAlignment);
706   printf("OS Version:         %d.%08d\n", BIGVERSION_MAJOR(WinHdr->OSVer), BIGVERSION_MINOR(WinHdr->OSVer));
707   printf("Image Version:      %d.%08d\n", BIGVERSION_MAJOR(WinHdr->ImgVer), BIGVERSION_MINOR(WinHdr->ImgVer));
708   printf("SubSystem Version:  %d.%08d\n", BIGVERSION_MAJOR(WinHdr->SubSysVer), BIGVERSION_MINOR(WinHdr->SubSysVer));
709   printf("Size of Image:      0x%08lX\n", WinHdr->SizeOfImage);
710   printf("Size of Headers:    0x%08lX\n", WinHdr->SizeOfHeaders);
711   printf("Checksum:           0x%08lX\n", WinHdr->CheckSum);
712   printf("Subsystem:          0x%04X\n", WinHdr->Subsystem);
713   printf("DLL Flags:          0x%04X\n", WinHdr->DLLFlags);
714   printf("Sizeof Stack Resv:  0x%08lX\n", WinHdr->SizeOfStackReserve);
715   printf("Sizeof Stack Comm:  0x%08lX\n", WinHdr->SizeOfStackCommit);
716   printf("Sizeof Heap Resv:   0x%08lX\n", WinHdr->SizeOfHeapReserve);
717   printf("Sizeof Heap Comm:   0x%08lX\n", WinHdr->SizeOfHeapCommit);
718   printf("Loader Flags:       0x%08lX\n", WinHdr->LoaderFlags);
719   printf("Num Directories:    %ld\n", WinHdr->NumDirectories);
720   printf("\n");
721 }
722 
PrintSection(SectionHeader_t * ScnHdr,char * data)723 void CoffLoader::PrintSection(SectionHeader_t *ScnHdr, char* data)
724 {
725   char SectionName[9];
726 
727   strncpy(SectionName, (char *)ScnHdr->Name, 8);
728   SectionName[8] = 0;
729   printf("Section: %s\n", SectionName);
730   printf("------------------------------------------\n\n");
731 
732   printf("Virtual Size:       0x%08lX\n", ScnHdr->VirtualSize);
733   printf("Virtual Address:    0x%08lX\n", ScnHdr->VirtualAddress);
734   printf("Sizeof Raw Data:    0x%08lX\n", ScnHdr->SizeOfRawData);
735   printf("Ptr To Raw Data:    0x%08lX\n", ScnHdr->PtrToRawData);
736   printf("Ptr To Relocations: 0x%08lX\n", ScnHdr->PtrToRelocations);
737   printf("Ptr To Line Nums:   0x%08lX\n", ScnHdr->PtrToLineNums);
738   printf("Num Relocations:    0x%04X\n", ScnHdr->NumRelocations);
739   printf("Num Line Numbers:   0x%04X\n", ScnHdr->NumLineNumbers);
740   printf("Characteristics:    0x%08lX\n", ScnHdr->Characteristics);
741   if (ScnHdr->Characteristics & IMAGE_SCN_CNT_CODE)
742     printf("                    IMAGE_SCN_CNT_CODE\n");
743   if (ScnHdr->Characteristics & IMAGE_SCN_CNT_DATA)
744     printf("                    IMAGE_SCN_CNT_DATA\n");
745   if (ScnHdr->Characteristics & IMAGE_SCN_CNT_BSS)
746     printf("                    IMAGE_SCN_CNT_BSS\n");
747   if (ScnHdr->Characteristics & IMAGE_SCN_LNK_INFO)
748     printf("                    IMAGE_SCN_LNK_INFO\n");
749   if (ScnHdr->Characteristics & IMAGE_SCN_LNK_REMOVE)
750     printf("                    IMAGE_SCN_LNK_REMOVE\n");
751   if (ScnHdr->Characteristics & IMAGE_SCN_LNK_COMDAT)
752     printf("                    IMAGE_SCN_LNK_COMDAT\n");
753 
754   if ((ScnHdr->Characteristics & IMAGE_SCN_ALIGN_MASK) == IMAGE_SCN_ALIGN_1BYTES)
755     printf("                    IMAGE_SCN_ALIGN_1BYTES\n");
756   if ((ScnHdr->Characteristics & IMAGE_SCN_ALIGN_MASK) == IMAGE_SCN_ALIGN_2BYTES)
757     printf("                    IMAGE_SCN_ALIGN_2BYTES\n");
758   if ((ScnHdr->Characteristics & IMAGE_SCN_ALIGN_MASK) == IMAGE_SCN_ALIGN_4BYTES)
759     printf("                    IMAGE_SCN_ALIGN_4BYTES\n");
760   if ((ScnHdr->Characteristics & IMAGE_SCN_ALIGN_MASK) == IMAGE_SCN_ALIGN_8BYTES)
761     printf("                    IMAGE_SCN_ALIGN_8BYTES\n");
762   if ((ScnHdr->Characteristics & IMAGE_SCN_ALIGN_MASK) == IMAGE_SCN_ALIGN_16BYTES)
763     printf("                    IMAGE_SCN_ALIGN_16BYTES\n");
764   if ((ScnHdr->Characteristics & IMAGE_SCN_ALIGN_MASK) == IMAGE_SCN_ALIGN_32BYTES)
765     printf("                    IMAGE_SCN_ALIGN_32BYTES\n");
766   if ((ScnHdr->Characteristics & IMAGE_SCN_ALIGN_MASK) == IMAGE_SCN_ALIGN_64BYTES)
767     printf("                    IMAGE_SCN_ALIGN_64BYTES\n");
768   if ((ScnHdr->Characteristics & IMAGE_SCN_ALIGN_MASK) == IMAGE_SCN_ALIGN_128BYTES)
769     printf("                    IMAGE_SCN_ALIGN_128BYTES\n");
770   if ((ScnHdr->Characteristics & IMAGE_SCN_ALIGN_MASK) == IMAGE_SCN_ALIGN_256BYTES)
771     printf("                    IMAGE_SCN_ALIGN_256BYTES\n");
772   if ((ScnHdr->Characteristics & IMAGE_SCN_ALIGN_MASK) == IMAGE_SCN_ALIGN_512BYTES)
773     printf("                    IMAGE_SCN_ALIGN_512BYTES\n");
774   if ((ScnHdr->Characteristics & IMAGE_SCN_ALIGN_MASK) == IMAGE_SCN_ALIGN_1024BYTES)
775     printf("                    IMAGE_SCN_ALIGN_1024BYTES\n");
776   if ((ScnHdr->Characteristics & IMAGE_SCN_ALIGN_MASK) == IMAGE_SCN_ALIGN_2048BYTES)
777     printf("                    IMAGE_SCN_ALIGN_2048BYTES\n");
778   if ((ScnHdr->Characteristics & IMAGE_SCN_ALIGN_MASK) == IMAGE_SCN_ALIGN_4096BYTES)
779     printf("                    IMAGE_SCN_ALIGN_4096BYTES\n");
780   if ((ScnHdr->Characteristics & IMAGE_SCN_ALIGN_MASK) == IMAGE_SCN_ALIGN_8192BYTES)
781     printf("                    IMAGE_SCN_ALIGN_8192BYTES\n");
782 
783   if (ScnHdr->Characteristics & IMAGE_SCN_LNK_NRELOC_OVFL)
784     printf("                    IMAGE_SCN_LNK_NRELOC_OVFL\n");
785   if (ScnHdr->Characteristics & IMAGE_SCN_MEM_DISCARDABLE)
786     printf("                    IMAGE_SCN_MEM_DISCARDABLE\n");
787   if (ScnHdr->Characteristics & IMAGE_SCN_MEM_NOT_CACHED)
788     printf("                    IMAGE_SCN_MEM_NOT_CACHED\n");
789   if (ScnHdr->Characteristics & IMAGE_SCN_MEM_NOT_PAGED)
790     printf("                    IMAGE_SCN_MEM_NOT_PAGED\n");
791   if (ScnHdr->Characteristics & IMAGE_SCN_MEM_SHARED)
792     printf("                    IMAGE_SCN_MEM_SHARED\n");
793   if (ScnHdr->Characteristics & IMAGE_SCN_MEM_EXECUTE)
794     printf("                    IMAGE_SCN_MEM_EXECUTE\n");
795   if (ScnHdr->Characteristics & IMAGE_SCN_MEM_READ)
796     printf("                    IMAGE_SCN_MEM_READ\n");
797   if (ScnHdr->Characteristics & IMAGE_SCN_MEM_WRITE)
798     printf("                    IMAGE_SCN_MEM_WRITE\n");
799   printf("\n");
800 
801   // Read the section Data, Relocations, & Line Nums
802   //    Save the offset
803 
804   if (ScnHdr->SizeOfRawData > 0)
805   {
806     unsigned int i;
807     // Print the Raw Data
808 
809     printf("\nRAW DATA");
810     for (i = 0; i < ScnHdr->VirtualSize; i++)
811     {
812       if ((i % 16) == 0)
813         printf("\n  %08X: ", i);
814       char ch = data[i];
815       printf("%02X ", (unsigned int)ch);
816     }
817     printf("\n\n");
818   }
819 
820   /*
821   #if 0
822   if (ScnHdr->NumRelocations > 0)
823   {
824   // Print Section Relocations
825   ObjReloc_t ObjReloc;
826 
827   fseek(fp, ScnHdr->PtrToRelocations/ * + CoffBeginOffset* /, SEEK_SET);
828   printf("RELOCATIONS\n");
829   printf("                     Symbol    Symbol\n");
830   printf(" Offset    Type      Index     Name\n");
831   printf(" --------  --------  --------  ------\n");
832   for (int i = 0; i < ScnHdr->NumRelocations; i++)
833   {
834   fread(&ObjReloc, 1, sizeof(ObjReloc_t), fp);
835   printf(" %08X  ", ObjReloc.VirtualAddress);
836 
837   if (ObjReloc.Type == IMAGE_REL_I386_ABSOLUTE)
838   printf("ABSOLUTE  ");
839   if (ObjReloc.Type == IMAGE_REL_I386_DIR16)
840   printf("DIR16     ");
841   if (ObjReloc.Type == IMAGE_REL_I386_REL16)
842   printf("REL16     ");
843   if (ObjReloc.Type == IMAGE_REL_I386_DIR32)
844   printf("DIR32     ");
845   if (ObjReloc.Type == IMAGE_REL_I386_DIR32NB)
846   printf("DIR32NB   ");
847   if (ObjReloc.Type == IMAGE_REL_I386_SEG12)
848   printf("SEG12     ");
849   if (ObjReloc.Type == IMAGE_REL_I386_SECTION)
850   printf("SECTION   ");
851   if (ObjReloc.Type == IMAGE_REL_I386_SECREL)
852   printf("SECREL    ");
853   if (ObjReloc.Type == IMAGE_REL_I386_REL32)
854   printf("REL32     ");
855   printf("%8X  ", ObjReloc.SymTableIndex);
856   printf("%s\n", GetSymbolName(ObjReloc.SymTableIndex));
857   }
858   printf("\n");
859   }
860 
861   if (ScnHdr->NumLineNumbers > 0)
862   {
863   // Print The Line Number Info
864   LineNumbers_t LineNumber;
865   int LineCnt = 0;
866   int BaseLineNum = -1;
867 
868   fseek(fp, ScnHdr->PtrToLineNums/ * + CoffBeginOffset* /, SEEK_SET);
869   printf("LINE NUMBERS");
870   for (int i = 0; i < ScnHdr->NumLineNumbers; i++)
871   {
872   int LNOffset = ftell(fp);
873 
874   fread(&LineNumber, 1, sizeof(LineNumbers_t), fp);
875   if (LineNumber.LineNum == 0)
876   {
877   SymbolTable_t *Sym;
878   int SymIndex;
879 
880   printf("\n");
881   SymIndex = LineNumber.Type.SymbolTableIndex;
882   Sym = &(SymTable[SymIndex]);
883   if (Sym->NumberOfAuxSymbols > 0)
884   {
885   Sym = &(SymTable[SymIndex+1]);
886   AuxFuncDef_t *FuncDef = (AuxFuncDef_t *)Sym;
887 
888   if (FuncDef->PtrToLineNumber == LNOffset)
889   {
890   Sym = &(SymTable[FuncDef->TagIndex]);
891   if (Sym->NumberOfAuxSymbols > 0)
892   {
893   Sym = &(SymTable[FuncDef->TagIndex+1]);
894   AuxBfEf_t *Bf = (AuxBfEf_t *)Sym;
895   BaseLineNum = Bf->LineNumber;
896   }
897   }
898   }
899   printf(" Symbol Index: %8x ", SymIndex);
900   printf(" Base line number: %8d\n", BaseLineNum);
901   printf(" Symbol name = %s", GetSymbolName(SymIndex));
902   LineCnt = 0;
903   }
904   else
905   {
906   if ((LineCnt%4) == 0)
907   {
908   printf("\n ");
909   LineCnt = 0;
910   }
911   printf("%08X(%5d)  ", LineNumber.Type.VirtualAddress,
912   LineNumber.LineNum + BaseLineNum);
913   LineCnt ++;
914   }
915   }
916   printf("\n");
917   }
918   #endif
919   */
920 
921   printf("\n");
922 }
923 
ParseCoff(FILE * fp)924 int CoffLoader::ParseCoff(FILE *fp)
925 {
926   if ( !LoadCoffHModule(fp) )
927   {
928     printf("Failed to load/find COFF hModule header\n");
929     return 0;
930   }
931   if ( !LoadSymTable(fp) ||
932        !LoadStringTable(fp) ||
933        !LoadSections(fp) )
934     return 0;
935 
936   PerformFixups();
937 
938 #ifdef DUMPING_DATA
939   PrintSymbolTable();
940   PrintStringTable();
941 #endif
942   return 1;
943 }
944 
PerformFixups(void)945 void CoffLoader::PerformFixups(void)
946 {
947   int FixupDataSize;
948   char *FixupData;
949   char *EndData;
950 
951   EntryAddress = (unsigned long)RVA2Data(EntryAddress);
952 
953   if( reinterpret_cast<void*>(WindowsHeader->ImageBase) == hModule )
954     return;
955 
956   if ( !Directory )
957     return ;
958 
959   if ( NumOfDirectories <= BASE_RELOCATION_TABLE )
960     return ;
961 
962   if ( !Directory[BASE_RELOCATION_TABLE].Size )
963     return ;
964 
965   FixupDataSize = Directory[BASE_RELOCATION_TABLE].Size;
966   FixupData = (char*)RVA2Data(Directory[BASE_RELOCATION_TABLE].RVA);
967   EndData = FixupData + FixupDataSize;
968 
969   while (FixupData < EndData)
970   {
971     // Starting a new Fixup Block
972     unsigned long PageRVA = *((unsigned long*)FixupData);
973     FixupData += 4;
974     unsigned long BlockSize = *((unsigned long*)FixupData);
975     FixupData += 4;
976 
977     BlockSize -= 8;
978     for (unsigned int i = 0; i < BlockSize / 2; i++)
979     {
980       unsigned short Fixup = *((unsigned short*)FixupData);
981       FixupData += 2;
982       int Type = (Fixup >> 12) & 0x0f;
983       Fixup &= 0xfff;
984       if (Type == IMAGE_REL_BASED_HIGHLOW)
985       {
986         unsigned long *Off = (unsigned long*)RVA2Data(Fixup + PageRVA);
987         *Off = (unsigned long)RVA2Data(*Off - WindowsHeader->ImageBase);
988       }
989       else if (Type == IMAGE_REL_BASED_ABSOLUTE)
990       {}
991       else
992       {
993         printf("Unsupported fixup type!!\n");
994       }
995     }
996   }
997 }
998