Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members   File Members  

pefile.cpp

Go to the documentation of this file.
00001 /*
00002 PeRdr - PE file disassembler
00003 Copyright (C) 1999-2002 Frediano Ziglio
00004 -----
00005 
00006 This program is free software; you can redistribute it and/or modify
00007 it under the terms of the GNU General Public License as published by
00008 the Free Software Foundation; either version 2 of the License, or
00009 (at your option) any later version.
00010 
00011 This program is distributed in the hope that it will be useful,
00012 but WITHOUT ANY WARRANTY; without even the implied warranty of
00013 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014 GNU General Public License for more details.
00015 
00016 You should have received a copy of the GNU General Public License
00017 along with this program; if not, write to the Free Software
00018 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00019 -----
00020 
00021 INFORMATION
00022   www: https://freddy77.tripod.com/perdr/
00023   e-mail: freddy77@angelfire.com
00024 */
00025 #include "global.h"
00026 #ifdef HAVE_HDRSTOP
00027 #pragma hdrstop
00028 #endif
00029 
00030 #include <ctime>
00031 #include <cstring>
00032 #include <cctype>
00033 #include <stdexcept>
00034 
00035 #include "rva.h"
00036 #include "pefile.hpp"
00037 #include "apicache.h"
00038 #include "utils/compilecheck.hpp"
00039 
00040 #define Error(s) { throw std::runtime_error(s); }
00041 
00042 static const char *const szDirectoryEntries[] =
00043 {
00044   "Export",
00045   "Import",
00046   "Resource",
00047   "Exception",
00048   "Security",
00049   "Relocation",
00050   "Debug",
00051   "Copyright",
00052   "GlobalPtr",
00053   "TLS",
00054   "Load Configuration",
00055   "Bound Import",
00056   "IAT",
00057   "Delayed Imports",
00058   "COM Runtime",
00059   "Reserved"
00060 };
00061 
00062 PeFile::PeFile(ICFile& _file):
00063   file(_file),rva(NULL)
00064 {
00065   file.Seek(0);
00066 
00067         PE_IMAGE_DOS_HEADER dos_hdr;
00068   RawRead(file,dos_hdr);
00069   if ( dos_hdr.e_magic != IMAGE_DOS_SIGNATURE )
00070         Error("File is not a valid DOS EXE");
00071   file.Seek(dos_hdr.e_lfanew);
00072 
00073   RawRead(file,nt_hdr);
00074   if ( nt_hdr.Signature != IMAGE_NT_SIGNATURE )
00075         Error("Invalid NT EXE file");
00076 
00077   if ( nt_hdr.OptionalHeader.Magic != IMAGE_NT_OPTIONAL_HDR_MAGIC )
00078         Error("Invalid NT optional header");
00079 
00080   long sections_pos =
00081       dos_hdr.e_lfanew + FIELD_OFFSET( PE_IMAGE_NT_HEADERS, OptionalHeader ) +
00082       nt_hdr.FileHeader.SizeOfOptionalHeader;
00083   file.Seek(sections_pos);
00084 
00085   numSection = nt_hdr.FileHeader.NumberOfSections;
00086   sections = new PE_IMAGE_SECTION_HEADER[numSection];
00087   for (unsigned i=0; i<numSection; ++i)
00088   {
00089         RawRead(file,sections[i]);
00090   }
00091 
00092 //  new (&GetRVA()) RVAFileTranslator(sections,numSection);
00093   rva = new RVAFileTranslator(sections,numSection);
00094 }
00095 
00096 PeFile::~PeFile()
00097 {
00098 //  GetRVA().RVAFileTranslator::~RVAFileTranslator();
00099   delete rva;
00100   delete [] sections;
00101 }
00102 
00103 void PeFile::WriteFileHdr(const PE_IMAGE_FILE_HEADER& hdr)
00104 {
00105 #define FIELD "%-30s"
00106   const char *machine = "Unknown";
00107   switch (hdr.Machine) {
00108   default:
00109   case IMAGE_FILE_MACHINE_UNKNOWN:
00110     break;
00111   case IMAGE_FILE_MACHINE_I386:    machine = "I386"; break;
00112   case IMAGE_FILE_MACHINE_R3000:   machine = "R3000"; break;
00113   case IMAGE_FILE_MACHINE_R4000:   machine = "R4000"; break;
00114   case IMAGE_FILE_MACHINE_R10000:  machine = "R10000"; break;
00115   case IMAGE_FILE_MACHINE_ALPHA:   machine = "Alpha"; break;
00116   case IMAGE_FILE_MACHINE_POWERPC: machine = "PowerPC"; break;
00117   }
00118   printf("File header information\n\n");
00119   printf(FIELD "%s\n","Machine",machine);
00120   printf(FIELD "%u\n","Section #",hdr.NumberOfSections);
00121   printf(FIELD "%08X\n","TimeStamp",hdr.TimeDateStamp);
00122   printf(FIELD "%08X\n","SymbolTable pointer",hdr.PointerToSymbolTable);
00123   printf(FIELD "%u\n","Symbol #",hdr.NumberOfSymbols);
00124   printf(FIELD "%u\n","Optional header size",hdr.SizeOfOptionalHeader);
00125   uint_fast16_t car = hdr.Characteristics;
00126   printf("Characteristics %X\n",(int)car);
00127   if ( car&IMAGE_FILE_RELOCS_STRIPPED )
00128     printf("  Relocation info stripped from file\n");
00129   if ( car&IMAGE_FILE_EXECUTABLE_IMAGE )
00130     printf("  File is executable\n");
00131   if ( car&IMAGE_FILE_LINE_NUMS_STRIPPED )
00132     printf("  Line nunbers stripped from file\n");
00133   if ( car&IMAGE_FILE_LOCAL_SYMS_STRIPPED )
00134     printf("  Local symbols stripped from file\n");
00135   if ( car&IMAGE_FILE_BYTES_REVERSED_LO )
00136     printf("  Bytes of machine word are reversed\n");
00137   if ( car&IMAGE_FILE_32BIT_MACHINE )
00138     printf("  32 bit word machine\n");
00139   if ( car&IMAGE_FILE_DEBUG_STRIPPED )
00140     printf("  Debugging info stripped from file in .DBG file\n");
00141   if ( car&IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP )
00142     printf("  If Image is on removable media, copy and run from the swap file\n");
00143   if ( car&IMAGE_FILE_NET_RUN_FROM_SWAP )
00144     printf("  If Image is on Net, copy and run from the swap file\n");
00145   if ( car&IMAGE_FILE_SYSTEM )
00146     printf("  System File\n");
00147   if ( car&IMAGE_FILE_DLL )
00148     printf("  File is a DLL\n");
00149   if ( car&IMAGE_FILE_BYTES_REVERSED_HI )
00150     printf("  Bytes of machine word are reversed\n");
00151   printf("\n");
00152 #undef FIELD
00153 }
00154 
00155 void PeFile::WriteOptionalHdr(const PE_IMAGE_OPTIONAL_HEADER& hdr)
00156 {
00157 #define FIELD "%-30s"
00158   printf("Optional header information\n\n");
00159   printf(FIELD "%04X\n","Magic",hdr.Magic);
00160   printf(FIELD "%d.%d\n","Linker",hdr.MajorLinkerVersion,hdr.MinorLinkerVersion);
00161   printf(FIELD "%08X\n","Code size",hdr.SizeOfCode);
00162   printf(FIELD "%08X\n","Initialized data size",hdr.SizeOfInitializedData);
00163   printf(FIELD "%08X\n","Uninitialized data size",hdr.SizeOfUninitializedData);
00164   printf(FIELD "%08X\n","Entry point RVA",hdr.AddressOfEntryPoint);
00165   printf(FIELD "%08X\n","Code base RVA",hdr.BaseOfCode);
00166   printf(FIELD "%08X\n","Data base RVA",hdr.BaseOfData);
00167 
00168   printf(FIELD "%08X\n","Image base",hdr.ImageBase);
00169   printf(FIELD "%08X/%08X\n","Section/File align",hdr.SectionAlignment,hdr.FileAlignment);
00170   printf(FIELD "%d.%d\n","O/S version",hdr.MajorOperatingSystemVersion,hdr.MinorOperatingSystemVersion);
00171   printf(FIELD "%d.%d\n","Image version",hdr.MajorImageVersion,hdr.MinorImageVersion);
00172   printf(FIELD "%d.%d\n","Subsystem version",hdr.MajorSubsystemVersion,hdr.MinorSubsystemVersion);
00173   printf(FIELD "%08X\n","Win32 version",hdr.Win32VersionValue);
00174   printf(FIELD "%08X\n","Image size",hdr.SizeOfImage);
00175   printf(FIELD "%08X\n","Headers size",hdr.SizeOfHeaders);
00176   printf(FIELD "%08X\n","Checksum",hdr.CheckSum);
00177   const char *subsystem= "Unknown";
00178   switch (hdr.Subsystem) {
00179   default:
00180   case IMAGE_SUBSYSTEM_UNKNOWN:
00181     break;
00182   case IMAGE_SUBSYSTEM_NATIVE:       subsystem="Native"; break;
00183   case IMAGE_SUBSYSTEM_WINDOWS_GUI:  subsystem="Windows GUI"; break;
00184   case IMAGE_SUBSYSTEM_WINDOWS_CUI:  subsystem="Windows Consolle"; break;
00185   case IMAGE_SUBSYSTEM_OS2_CUI:      subsystem="OS2 Consolle"; break;
00186   case IMAGE_SUBSYSTEM_POSIX_CUI:    subsystem="Posix Consolle"; break;
00187   }
00188   printf(FIELD "%d (%s)\n","Subsystem",hdr.Subsystem,subsystem);
00189   printf(FIELD "%08X\n","DLL flags",hdr.DllCharacteristics);
00190   printf(FIELD "%08X/%08X\n","Stack reserve/commit",hdr.SizeOfStackReserve,hdr.SizeOfStackCommit);
00191   printf(FIELD "%08X/%08X\n","Heap reserve/commit",hdr.SizeOfHeapReserve,hdr.SizeOfHeapCommit);
00192   printf(FIELD "%08X\n","Loader flags",hdr.LoaderFlags);
00193   printf(FIELD "%u\n","RVA #",hdr.NumberOfRvaAndSizes);
00194   printf("\n%-20s%-10sSize\n","Name","RVA");
00195   printf("-----------------------------\n");
00196   for(int i=0; i<16; ++i)
00197     printf("%-20s%08X  %08X\n",szDirectoryEntries[i],hdr.DataDirectory[i].VirtualAddress,hdr.DataDirectory[i].Size);
00198   printf("\n");
00199 #undef FIELD
00200 }
00201 
00202 void PeFile::WriteSectionHdr(const PE_IMAGE_SECTION_HEADER& hdr)
00203 {
00204 #define FIELD "%-30s"
00205   printf(FIELD "%-8.8s\n","Name",hdr.Name);
00206   printf(FIELD "%08X\n","PhysicalAddress",hdr.Misc.PhysicalAddress);
00207   printf(FIELD "%08X\n","VirtualAddress",hdr.VirtualAddress);
00208   printf(FIELD "%08X\n","Size of raw data",hdr.SizeOfRawData);
00209   printf(FIELD "%08X\n","Pointer to raw data",hdr.PointerToRawData);
00210   printf(FIELD "%08X\n","Pointer to relocations",hdr.PointerToRelocations);
00211   printf(FIELD "%08X\n","Pointer to linenumbers",hdr.PointerToLinenumbers);
00212   printf(FIELD "%04X\n","Number of relocations",hdr.NumberOfRelocations);
00213   printf(FIELD "%04X\n","Number of line numbers",hdr.NumberOfLinenumbers);
00214 
00215   printf("Characteristics\n");
00216   uint32_t car = hdr.Characteristics;
00217   if ( car&IMAGE_SCN_CNT_CODE )               printf("  Section contains code\n");
00218   if ( car&IMAGE_SCN_CNT_INITIALIZED_DATA )   printf("  Section contains initialized data\n");
00219   if ( car&IMAGE_SCN_CNT_UNINITIALIZED_DATA ) printf("  Section contains uninitialized data\n");
00220   if ( car&IMAGE_SCN_LNK_INFO )               printf("  Section contains comments or some other type of information\n");
00221   if ( car&IMAGE_SCN_LNK_REMOVE )             printf("  Section contents will not become part of image\n");
00222   if ( car&IMAGE_SCN_LNK_COMDAT )             printf("  Section contents comdat\n");
00223 
00224   if ( car&IMAGE_SCN_MEM_FARDATA )            printf("  FarData\n");
00225   if ( car&IMAGE_SCN_MEM_PURGEABLE )          printf("  Purgeable\n");
00226   if ( car&IMAGE_SCN_MEM_16BIT )              printf("  16bit\n");
00227   if ( car&IMAGE_SCN_MEM_LOCKED )             printf("  Locked\n");
00228   if ( car&IMAGE_SCN_MEM_PRELOAD )            printf("  Preload\n");
00229 
00230   if ( car&IMAGE_SCN_ALIGN_1BYTES )           printf("  Align 1 byte\n");
00231   if ( car&IMAGE_SCN_ALIGN_2BYTES )           printf("  Align 2 bytes\n");
00232   if ( car&IMAGE_SCN_ALIGN_4BYTES )           printf("  Align 4 bytes\n");
00233   if ( car&IMAGE_SCN_ALIGN_8BYTES )           printf("  Align 8 bytes\n");
00234   if ( car&IMAGE_SCN_ALIGN_16BYTES )          printf("  Align 16 bytes\n");
00235   if ( car&IMAGE_SCN_ALIGN_32BYTES )          printf("  Align 32 bytes\n");
00236   if ( car&IMAGE_SCN_ALIGN_64BYTES )          printf("  Align 64 bytes\n");
00237 
00238   if ( car&IMAGE_SCN_LNK_NRELOC_OVFL )        printf("  Section contains extended relocations\n");
00239   if ( car&IMAGE_SCN_MEM_DISCARDABLE )        printf("  Discardable\n");
00240   if ( car&IMAGE_SCN_MEM_NOT_CACHED )         printf("  Not cachable\n");
00241   if ( car&IMAGE_SCN_MEM_NOT_PAGED )          printf("  Not pageable\n");
00242   if ( car&IMAGE_SCN_MEM_SHARED )             printf("  Shareable\n");
00243   if ( car&IMAGE_SCN_MEM_EXECUTE )            printf("  Executable\n");
00244   if ( car&IMAGE_SCN_MEM_READ )               printf("  Readable\n");
00245   if ( car&IMAGE_SCN_MEM_WRITE )              printf("  Writeable\n");
00246   printf("\n");
00247 #undef FIELD
00248 }
00249 
00250 #ifdef __BORLANDC__
00251 #pragma argsused
00252 #endif
00253 void PeFile::WriteImport(uint32_t address,uint32_t hint,const char* dll_name,const char* func_name,void* param)
00254 {
00255   if (address == 0)
00256     printf("\nDLL: %s\n",dll_name);
00257   else
00258   {
00259     printf(" Addr:%08lX ",(long int)address);
00260     if (func_name==NULL)
00261                 {
00262                         std::string name;
00263                         if (ApiCache::GetFullApiName(name,dll_name,hint))
00264         printf("Ordinal:%u(%04X) (%s)\n",hint,hint,name.c_str());
00265                         else
00266         printf("Ordinal:%u(%04X)\n",hint,hint);
00267                 }
00268     else
00269         printf("hint:%u(%04X) Name:%s\n",hint,hint,func_name);
00270   }
00271 }
00272 
00273 #ifdef __BORLANDC__
00274 #pragma argsused
00275 #endif
00276 void PeFile::WriteExport(uint32_t address,uint32_t hint,const char* dll_name,const char* func_name,void* param)
00277 {
00278   if (address == 0)
00279     printf("\nDLL: %s\n",dll_name);
00280   else
00281   {
00282     printf(" Addr:%08lX ",(long int)address);
00283     if (func_name==NULL)
00284         printf("Ordinal:%u(%04X)\n",hint,hint);
00285     else
00286         printf("hint:%u(%04X) Name:%s\n",hint,hint,func_name);
00287   }
00288 }
00289 
00290 void PeFile::ParseImport(PImportProc proc,void* param)
00291 {
00292   const PE_IMAGE_DATA_DIRECTORY& imports =
00293     GetDataDirectory(IMAGE_DIRECTORY_ENTRY_IMPORT);
00294   if ( imports.VirtualAddress == 0 || imports.Size == 0 )
00295     return;
00296 
00297   file.Seek(GetRVA().RVA2FileSafe(imports.VirtualAddress));
00298   for (;;)
00299   {
00300     PE_IMAGE_IMPORT_DESCRIPTOR desc;
00301     RawRead(file,desc);
00302     long pos = file.Tell();
00303 
00304     // imports finished
00305     if (desc.Characteristics == 0 && desc.FirstThunk == 0)
00306       break;
00307 
00308     uint32_t address = desc.FirstThunk;
00309 
00310     // read DLL name
00311     file.Seek(GetRVA().RVA2FileSafe(desc.Name));
00312     char *pDllName = file.ReadString();
00313     proc(0,0,pDllName,NULL,param);
00314 
00315     // delete ".dll" after name
00316     int len = strlen(pDllName);
00317     if (len>=4 && stricmp(pDllName+(len-4),".dll") == 0)
00318         pDllName[len-4] = '\0';
00319 
00320     // scan import for this DLL
00321                 // hintname is at the same address of FirstThunk ?
00322                 if (desc.OriginalFirstThunk == 0)
00323                         file.Seek(GetRVA().RVA2FileSafe((uint32_t)desc.FirstThunk));
00324                 else
00325                         file.Seek(GetRVA().RVA2FileSafe((uint32_t)desc.OriginalFirstThunk));
00326     for (;;)
00327     {
00328       PE_IMAGE_THUNK_DATA thunk;
00329       RawRead(file,thunk);
00330       long pos2 = file.Tell();
00331 
00332       // finish with this DLL
00333       if (thunk.u1.Ordinal == 0)
00334         break;
00335 
00336       if (IMAGE_SNAP_BY_ORDINAL(thunk.u1.Ordinal))
00337       {
00338         // import by ordinal
00339         proc(address,IMAGE_ORDINAL(thunk.u1.Ordinal),pDllName,NULL,param);
00340       }
00341       else
00342       {
00343         // import by name
00344         uint16_t hint;
00345 
00346         // read hint and import name
00347         file.Seek(GetRVA().RVA2FileSafe((uint32_t)thunk.u1.AddressOfData));
00348         RawRead(file,hint);
00349         char *p = file.ReadString();
00350         proc(address,hint,pDllName,p,param);
00351         delete [] p;
00352       }
00353       address += sizeof(PE_IMAGE_THUNK_DATA);
00354 
00355       file.Seek(pos2);
00356     }
00357     file.Seek(pos);
00358     delete[] pDllName;
00359   }
00360 }
00361 
00362 void PeFile::ParseExport(PExportProc proc,void* param)
00363 {
00364   // export renamed to export_, in some compiler this is a keyword
00365   const PE_IMAGE_DATA_DIRECTORY& export_ =
00366     GetDataDirectory(IMAGE_DIRECTORY_ENTRY_EXPORT);
00367   if ( export_.VirtualAddress == 0 || export_.Size == 0 )
00368     return;
00369 
00370   file.Seek(GetRVA().RVA2FileSafe(export_.VirtualAddress));
00371 
00372   PE_IMAGE_EXPORT_DIRECTORY desc;
00373   RawRead(file,desc);
00374 
00375   // read DLL name
00376   file.Seek(GetRVA().RVA2FileSafe(desc.Name));
00377   char *pDllName = file.ReadString();
00378   proc(0,0,pDllName,NULL,param);
00379 
00380   // delete ".dll" after name
00381   int len = strlen(pDllName);
00382   if (len>=4 && stricmp(pDllName+(len-4),".dll") == 0)
00383         pDllName[len-4] = '\0';
00384 
00385   // scan export for this DLL
00386   int ordBase = desc.Base;
00387   long functionPos = GetRVA().RVA2FileSafe(desc.AddressOfFunctions);
00388   long ordinalPos  = GetRVA().RVA2FileSafe(desc.AddressOfNameOrdinals);
00389   long namePos     = GetRVA().RVA2FileSafe(desc.AddressOfNames);
00390 
00391   char **names= new char*[desc.NumberOfFunctions];
00392 
00393   // initialize functions
00394   unsigned n;
00395   for( n = 0; n<desc.NumberOfFunctions; ++n)
00396     names[n] = NULL;
00397 
00398   for( n = 0; n<desc.NumberOfNames; ++n)
00399   {
00400     uint16_t ordinal;
00401     char *pName;
00402 
00403     // read name pos
00404     uint32_t pos;
00405     file.Seek(namePos);
00406     RawRead(file,pos);
00407     namePos = file.Tell();
00408 
00409     // read name
00410     file.Seek(GetRVA().RVA2FileSafe(pos));
00411     pName = file.ReadString();
00412 
00413     // read ordinal
00414     file.Seek(ordinalPos);
00415     RawRead(file,ordinal);
00416     ordinalPos = file.Tell();
00417 
00418     // check ordinal
00419     if (ordinal >= desc.NumberOfFunctions )
00420       throw std::runtime_error("bad ordinal");
00421 
00422     names[ordinal] = pName;
00423   }
00424 
00425   file.Seek(functionPos);
00426   for( n = 0; n<desc.NumberOfFunctions; ++n)
00427   {
00428     // read function RVA
00429     uint32_t funcRVA;
00430     if (file.Tell() != functionPos)
00431       file.Seek(functionPos);
00432     RawRead(file,funcRVA);
00433 
00434     if (funcRVA != 0)
00435         proc(funcRVA,ordBase + n,pDllName,names[n],param);
00436     functionPos += 4;
00437 
00438     delete[] names[n];
00439   }
00440 
00441   delete[] names;
00442   delete[] pDllName;
00443 }
00444 
00445 typedef void (*PRelocationProc)(uint32_t address,unsigned type,void* param);
00446 #ifdef __BORLANDC__
00447 #pragma argsused
00448 #endif
00449 void PeFile::WriteRelocation(uint32_t address,unsigned type,void* param)
00450 {
00451   printf("%08lX ",(long int)address);
00452   switch(type)
00453   {
00454   case IMAGE_REL_BASED_ABSOLUTE:
00455         printf("Absolute\n"); break;
00456   case IMAGE_REL_BASED_HIGH:
00457         printf("Relative High\n"); break;
00458   case IMAGE_REL_BASED_LOW:
00459         printf("Relative Low\n"); break;
00460   case IMAGE_REL_BASED_HIGHLOW:
00461         printf("Relative HighLow\n"); break;
00462   case IMAGE_REL_BASED_HIGHADJ:
00463         printf("Relative HighAdj\n"); break;
00464   default:
00465         printf("Unknown\n"); break;
00466   }
00467 }
00468 
00469 void PeFile::ParseRelocations(PRelocationProc proc,void* param)
00470 {
00471   const PE_IMAGE_DATA_DIRECTORY& relocation =
00472     GetDataDirectory(IMAGE_DIRECTORY_ENTRY_BASERELOC);
00473   if ( relocation.VirtualAddress == 0 || relocation.Size == 0 )
00474     return;
00475 
00476   file.Seek(GetRVA().RVA2FileSafe(relocation.VirtualAddress));
00477   if (proc == PeFile::WriteRelocation)
00478   {
00479     printf("\nRelocations\n");
00480     printf("Address  Type\n");
00481   }
00482   for (;;)
00483   {
00484     PE_IMAGE_BASE_RELOCATION chunk;
00485     long pos = file.Tell();
00486     RawRead(file,chunk);
00487     if (chunk.VirtualAddress == 0)
00488       break;
00489     for (int i=(chunk.SizeOfBlock - sizeof(chunk))>>1; i>0; --i)
00490     {
00491       uint16_t info;
00492       RawRead(file,info);
00493       if (info == 0)
00494         break;
00495       proc(chunk.VirtualAddress+(info&0xFFFu),info>>12,param);
00496     }
00497     file.Seek(pos+chunk.SizeOfBlock);
00498   }
00499   printf("\n");
00500 }
00501 
00502 // !!! other file
00503 static void WriteBinary(const ICFile& file,int _len)
00504 {
00505   _PRG_ASSERT(_len>0);
00506   unsigned int len = (unsigned int)_len;
00507   unsigned address = 0;
00508   const unsigned nCarInRow = 16;
00509   char buffer[3*nCarInRow+nCarInRow+10];
00510   for(unsigned n=0;;++n)
00511   {
00512     unsigned part = n%nCarInRow;
00513     if (part==0)
00514     {
00515       if (n>=nCarInRow)
00516       {
00517         buffer[nCarInRow*3+nCarInRow+1] = '\0';
00518         printf("%08X %s\n",address+n-nCarInRow,buffer);
00519         if (n>=len)
00520           return;
00521       }
00522       // inizializza buffer
00523       memset(buffer,' ',sizeof(buffer));
00524     }
00525     if (n<len)
00526     {
00527       uint8_t car;
00528       file.RawRead(&car,1);
00529 
00530       // scrive il carattere in esadecimale e carattere relativo
00531       sprintf(buffer+part*3,"%02X",car);
00532       buffer[part*3+2] = part==(nCarInRow/2-1)?'-':' ';
00533       // !!! settare come opzione carattere ?
00534       buffer[nCarInRow*3+1+part] = isprint(car)?car:'.';
00535     }
00536   }
00537 }
00538 
00539 
00540 COMPILE_CHECK(error_Only_ASCII_charset_supported,
00541   ('0' == 0x30 && '9' == 0x39 && 'A' == 0x41 && 'Z' == (0x41+25) && 
00542    'a' == 0x61 && 'z' == (0x61+25) && ' ' == 32 && '\t' == 9 && '\n' == 10)
00543   );
00544 
00545 // !!! other file
00546 static void out_ws(const unicode_t* s)
00547 {
00548   for(;*s;++s)
00549   {
00550     char c;
00551     c = char((*s) & 0xff);
00552     // !!! bad conversion
00553     if ( (*s) < 256 && isprint(c) )
00554       printf("%c",c);
00555     else
00556       printf("\\x%04x",*s);
00557   }
00558 }
00559 
00560 
00561 // if data == 0 this is a directory entry
00562 // first info reference level level directory
00563 // 2nd info (info->highLevel) reference level-1 level and so on
00564 // if data != 0 file point to raw data
00565 // always info != 0
00566 static void WriteResource(ICFile& file,const PeResourceDirectoryData* data,const PeResourceDirectoryInfo* info,unsigned level,void*)
00567 {
00568   // se siamo all'apice dell'albero
00569   if (level == 0 && data == NULL)
00570   {
00571     printf("Resources\n");
00572     printf("%*s%-16s%08X\n",level*4,"","Characteristics",info->dir.Characteristics);
00573     time_t t = (time_t)info->dir.TimeDateStamp;
00574     printf("%*s%-16s%08X %s",level*4,"","TimeDateStamp",info->dir.TimeDateStamp,ctime(&t));
00575     printf("%*s%-16s%i:%i\n",level*4,"","Version",info->dir.MajorVersion,info->dir.MinorVersion);
00576   }
00577   else
00578   {
00579   // se c'e' un livello superiore stampa id o nome
00580   // se dati bisogna prendere il livello corrente
00581   const PeResourceId* p = data?(const PeResourceId*)data:(const PeResourceId*)info;
00582   if (p)
00583   {
00584     printf("%*s",(level)*4,"");
00585     switch(level-1)
00586     {
00587     case 0:
00588       printf("Type ");
00589       switch(p->id)
00590       {
00591       case 1: printf("cursor"); break;
00592       case 2: printf("bitmap"); break;
00593       case 3: printf("icon"); break;
00594       case 4: printf("menu"); break;
00595       case 5: printf("dialog"); break;
00596       case 6: printf("string table"); break;
00597       case 7: printf("font directory"); break;
00598       case 8: printf("font"); break;
00599       case 9: printf("accelerators"); break;
00600       case 10: printf("unformatted resource data"); break;
00601       case 11: printf("message table"); break;
00602       case 12: printf("group cursor"); break;
00603       case 14: printf("group icon"); break;
00604       case 16: printf("version information"); break;
00605       case 17: printf("dialog include"); break;
00606       case 19: printf("plug & play"); break;
00607       case 20: printf("vxd"); break;
00608       case 21: printf("animate cursor"); break;
00609       case 22: printf("animate icon"); break;
00610       case 23: printf("html"); break;
00611       default: printf("unknown"); break;
00612       }
00613       if (p->name)
00614       {
00615         printf(" (");
00616         out_ws(p->name);
00617         printf(")\n");
00618       }
00619       else
00620         printf(" (%i)\n",p->id);
00621       break;
00622     case 1:
00623       if (p->name)
00624       {
00625         printf("ID ");
00626         out_ws(p->name);
00627         printf("\n");
00628       }
00629       else
00630         printf("ID %i\n",p->id);
00631       break;
00632     case 2:
00633       if (p->name)
00634       {
00635         printf("LangID ");
00636         out_ws(p->name);
00637         printf("\n");
00638       }
00639       else
00640         printf("LangID %i\n",p->id);
00641       break;
00642     default:
00643       if (p->name)
00644       {
00645         printf("Name ");
00646         out_ws(p->name);
00647         printf("\n");
00648       }
00649       else
00650         printf("Name %08X\n",p->id);
00651       break;
00652     }
00653   }
00654   }
00655 
00656   // for directory write available entries
00657   if (data == NULL)
00658     printf("%*s%-16s%i named %i id\n",level*4,"","Entryes",info->dir.NumberOfNamedEntries,info->dir.NumberOfIdEntries);
00659 
00660   // for data write data information
00661   if (data)
00662   {
00663       printf("%*s%-16s%08X\n",(level)*4,"","OffsetToData",data->data.OffsetToData);
00664       printf("%*s%-16s%08X\n",(level)*4,"","Size",data->data.Size);
00665       printf("%*s%-16s%08X\n",(level)*4,"","CodePage",data->data.CodePage);
00666       printf("%*s%-16s%08X\n",(level)*4,"","Reserved",data->data.Reserved);
00667       // !!! use best method, save file ??
00668       WriteBinary(file,data->data.Size);
00669   }
00670 }
00671 
00672 static void ParseResourceDirectory(const RVAFileTranslator& rva,uint32_t start,PeResourceDirectoryInfo *info,unsigned level,ICFile& file,PeFile::PResourceProc proc,void* param)
00673 {
00674   // read raw directory info
00675   RawRead(file,info->dir);
00676 
00677   proc(file,NULL,info,level,param);
00678 
00679   int i = info->dir.NumberOfNamedEntries + info->dir.NumberOfIdEntries;
00680   for(;i>0;--i)
00681   {
00682     PE_IMAGE_RESOURCE_DIRECTORY_ENTRY entry;
00683     RawRead(file,entry);
00684     long pos = file.Tell();
00685     // finish (ID, Type, Language)
00686     unicode_t *pName = NULL;
00687     if ( RESOURCE_ENTRY_ISSTRING(entry) )
00688     {
00689 
00690       file.Seek(start+RESOURCE_ENTRY_NAME_OFFSET(entry));
00691       pName = (unicode_t*)file.ReadStringFlag(
00692         ICFile::strUcs2|ICFile::strLen16);
00693     }
00694 
00695     if ( RESOURCE_ENTRY_ISDIRECTORY(entry) )
00696     {
00697       file.Seek(start+RESOURCE_ENTRY_DATA_OFFSET(entry) );
00698 
00699       // init directory
00700       PeResourceDirectoryInfo _info;
00701       _info.name = pName;
00702       _info.id   = RESOURCE_ENTRY_GETID(entry);
00703       _info.highLevel = info;
00704 
00705       ParseResourceDirectory(rva,start,&_info,level+1,file,proc,param);
00706     }
00707     else
00708     {
00709       file.Seek(start+entry.u2.OffsetToData);
00710 
00711       // init data
00712       PeResourceDirectoryData data;
00713       RawRead(file,data.data);
00714       data.id = RESOURCE_ENTRY_GETID(entry);
00715       data.name = pName;
00716 
00717       file.Seek(rva.RVA2FileSafe(data.data.OffsetToData));
00718       proc(file,&data,info,level+1,param);
00719     }
00720     delete [] pName;
00721 
00722     file.Seek(pos);
00723   }
00724 }
00725 
00726 void PeFile::ParseResource(PResourceProc proc,void* param)
00727 {
00728   const PE_IMAGE_DATA_DIRECTORY& resource =
00729     GetDataDirectory(IMAGE_DIRECTORY_ENTRY_RESOURCE);
00730   if ( resource.VirtualAddress == 0 || resource.Size == 0 )
00731     return;
00732 
00733   uint32_t start = GetRVA().RVA2FileSafe(resource.VirtualAddress);
00734   file.Seek(start);
00735 
00736   // init directory info (root)
00737   PeResourceDirectoryInfo info;
00738   info.name = NULL;
00739   info.id   = 0;
00740   info.highLevel = NULL;
00741 
00742   ParseResourceDirectory(GetRVA(),start,&info,0,file,proc,param);
00743 }
00744 
00745 void PeFile::WriteResource()
00746 {
00747   ParseResource(::WriteResource,NULL);
00748 }
00749 

Generated on Mon Jan 13 22:20:34 2003 for perdr by doxygen1.2.15