View Javadoc
1   /** *****************************************************************************
2    * This program and the accompanying materials
3    * are made available under the terms of the Common Public License v1.0
4    * which accompanies this distribution, and is available at
5    * http://www.eclipse.org/legal/cpl-v10.html
6    *
7    * Contributors:
8    *	 Peter Smith
9    ****************************************************************************** */
10  /** ****************************************************************************
11   * This is a copy of https://github.com/kichik/pecoff4j/blob/2137804a7c1f1aa5f4272a9623bad452f7aab0ad/java/src/org/boris/pecoff4j/io/PEParser.java#L1
12   * Added a logger and more forgiving error handling while reading files per https://github.com/jeremylong/DependencyCheck/issues/2601
13   ***************************************************************************** */
14  package org.owasp.dependencycheck.utils;
15  
16  import org.boris.pecoff4j.*;
17  import org.boris.pecoff4j.constant.ImageDataDirectoryType;
18  import org.boris.pecoff4j.util.IntMap;
19  
20  import java.io.File;
21  import java.io.FileInputStream;
22  import java.io.IOException;
23  import java.io.InputStream;
24  import java.util.ArrayList;
25  import java.util.Collections;
26  import java.util.Comparator;
27  import java.util.List;
28  import org.boris.pecoff4j.io.ByteArrayDataReader;
29  import org.boris.pecoff4j.io.DataEntry;
30  import org.boris.pecoff4j.io.DataReader;
31  import org.boris.pecoff4j.io.IDataReader;
32  
33  import org.slf4j.Logger;
34  import org.slf4j.LoggerFactory;
35  
36  public class PEParser {
37  
38      /**
39       * Logger
40       */
41      private static final Logger LOGGER = LoggerFactory.getLogger(PEParser.class);
42  
43      public static PE parse(InputStream is) throws IOException {
44          return read(new DataReader(is));
45      }
46  
47      public static PE parse(String filename) throws IOException {
48          return parse(new File(filename));
49      }
50  
51      public static PE parse(File file) throws IOException {
52          return read(new DataReader(new FileInputStream(file)), file);
53      }
54  
55      public static PE read(IDataReader dr) throws IOException {
56          return read(dr, null);
57      }
58  
59      public static PE read(IDataReader dr, File file) throws IOException {
60          PE pe = new PE();
61          pe.setDosHeader(readDos(dr));
62  
63          // Check if we have an old file type
64          if (pe.getDosHeader().getAddressOfNewExeHeader() == 0
65                  || pe.getDosHeader().getAddressOfNewExeHeader() > 8192) {
66              return pe;
67          }
68  
69          pe.setStub(readStub(pe.getDosHeader(), dr));
70          pe.setSignature(readSignature(dr));
71  
72          // Check signature to ensure we have a pe/coff file
73          if (!pe.getSignature().isValid()) {
74              return pe;
75          }
76  
77          pe.setCoffHeader(readCOFF(dr));
78          pe.setOptionalHeader(readOptional(dr));
79          pe.setSectionTable(readSectionHeaders(pe, dr));
80  
81          pe.set64(pe.getOptionalHeader().isPE32plus());
82  
83          // Now read the rest of the file
84          DataEntry entry = null;
85          while ((entry = findNextEntry(pe, dr.getPosition())) != null) {
86              if (entry.isSection) {
87                  readSection(pe, entry, dr);
88              } else if (entry.isDebugRawData) {
89                  try {
90                      readDebugRawData(pe, entry, dr);
91                  } catch (java.io.EOFException eofEx) {
92                      if (file != null) {
93                          LOGGER.debug("Error reading debug raw data: " + file.getPath(), eofEx);
94                      }
95                  }
96  
97              } else {
98                  try {
99                      readImageData(pe, entry, dr);
100                 } catch (java.io.EOFException eofEx) {
101                     if (file != null) {
102                         LOGGER.debug("Error reading image data: " + file.getPath(), eofEx);
103                     }
104                 }
105 
106             }
107         }
108 
109         // Read any trailing data
110         try {
111             byte[] tb = dr.readAll();
112             if (tb.length > 0) {
113                 pe.getImageData().setTrailingData(tb);
114             }
115         } catch (java.io.EOFException eofEx) {
116             if (file != null) {
117                 LOGGER.debug("Error reading trailing data: " + file.getPath(), eofEx);
118             }
119         }
120 
121         return pe;
122     }
123 
124     public static DOSHeader readDos(IDataReader dr) throws IOException {
125         DOSHeader dh = new DOSHeader();
126         dh.setMagic(dr.readWord());
127         dh.setUsedBytesInLastPage(dr.readWord());
128         dh.setFileSizeInPages(dr.readWord());
129         dh.setNumRelocationItems(dr.readWord());
130         dh.setHeaderSizeInParagraphs(dr.readWord());
131         dh.setMinExtraParagraphs(dr.readWord());
132         dh.setMaxExtraParagraphs(dr.readWord());
133         dh.setInitialSS(dr.readWord());
134         dh.setInitialSP(dr.readWord());
135         dh.setChecksum(dr.readWord());
136         dh.setInitialIP(dr.readWord());
137         dh.setInitialRelativeCS(dr.readWord());
138         dh.setAddressOfRelocationTable(dr.readWord());
139         dh.setOverlayNumber(dr.readWord());
140         int[] reserved = new int[4];
141         for (int i = 0; i < reserved.length; i++) {
142             reserved[i] = dr.readWord();
143         }
144         dh.setReserved(reserved);
145         dh.setOemId(dr.readWord());
146         dh.setOemInfo(dr.readWord());
147         int[] reserved2 = new int[10];
148         for (int i = 0; i < reserved2.length; i++) {
149             reserved2[i] = dr.readWord();
150         }
151         dh.setReserved2(reserved2);
152         dh.setAddressOfNewExeHeader(dr.readDoubleWord());
153 
154         // calc stub size
155         int stubSize = dh.getFileSizeInPages() * 512
156                 - (512 - dh.getUsedBytesInLastPage());
157         if (stubSize > dh.getAddressOfNewExeHeader()) {
158             stubSize = dh.getAddressOfNewExeHeader();
159         }
160         stubSize -= dh.getHeaderSizeInParagraphs() * 16;
161         dh.setStubSize(stubSize);
162 
163         return dh;
164     }
165 
166     public static DOSStub readStub(DOSHeader header, IDataReader dr)
167             throws IOException {
168         DOSStub ds = new DOSStub();
169         int pos = dr.getPosition();
170         int add = header.getAddressOfNewExeHeader();
171         byte[] stub = new byte[add - pos];
172         dr.read(stub);
173         ds.setStub(stub);
174         return ds;
175     }
176 
177     public static PESignature readSignature(IDataReader dr) throws IOException {
178         PESignature ps = new PESignature();
179         byte[] signature = new byte[4];
180         dr.read(signature);
181         ps.setSignature(signature);
182         return ps;
183     }
184 
185     public static COFFHeader readCOFF(IDataReader dr) throws IOException {
186         COFFHeader h = new COFFHeader();
187         h.setMachine(dr.readWord());
188         h.setNumberOfSections(dr.readWord());
189         h.setTimeDateStamp(dr.readDoubleWord());
190         h.setPointerToSymbolTable(dr.readDoubleWord());
191         h.setNumberOfSymbols(dr.readDoubleWord());
192         h.setSizeOfOptionalHeader(dr.readWord());
193         h.setCharacteristics(dr.readWord());
194         return h;
195     }
196 
197     public static OptionalHeader readOptional(IDataReader dr)
198             throws IOException {
199         OptionalHeader oh = new OptionalHeader();
200         oh.setMagic(dr.readWord());
201         boolean is64 = oh.isPE32plus();
202         oh.setMajorLinkerVersion(dr.readByte());
203         oh.setMinorLinkerVersion(dr.readByte());
204         oh.setSizeOfCode(dr.readDoubleWord());
205         oh.setSizeOfInitializedData(dr.readDoubleWord());
206         oh.setSizeOfUninitializedData(dr.readDoubleWord());
207         oh.setAddressOfEntryPoint(dr.readDoubleWord());
208         oh.setBaseOfCode(dr.readDoubleWord());
209 
210         if (!is64) {
211             oh.setBaseOfData(dr.readDoubleWord());
212         }
213 
214         // NT additional fields.
215         oh.setImageBase(is64 ? dr.readLong() : dr.readDoubleWord());
216         oh.setSectionAlignment(dr.readDoubleWord());
217         oh.setFileAlignment(dr.readDoubleWord());
218         oh.setMajorOperatingSystemVersion(dr.readWord());
219         oh.setMinorOperatingSystemVersion(dr.readWord());
220         oh.setMajorImageVersion(dr.readWord());
221         oh.setMinorImageVersion(dr.readWord());
222         oh.setMajorSubsystemVersion(dr.readWord());
223         oh.setMinorSubsystemVersion(dr.readWord());
224         oh.setWin32VersionValue(dr.readDoubleWord());
225         oh.setSizeOfImage(dr.readDoubleWord());
226         oh.setSizeOfHeaders(dr.readDoubleWord());
227         oh.setCheckSum(dr.readDoubleWord());
228         oh.setSubsystem(dr.readWord());
229         oh.setDllCharacteristics(dr.readWord());
230         oh.setSizeOfStackReserve(is64 ? dr.readLong() : dr.readDoubleWord());
231         oh.setSizeOfStackCommit(is64 ? dr.readLong() : dr.readDoubleWord());
232         oh.setSizeOfHeapReserve(is64 ? dr.readLong() : dr.readDoubleWord());
233         oh.setSizeOfHeapCommit(is64 ? dr.readLong() : dr.readDoubleWord());
234         oh.setLoaderFlags(dr.readDoubleWord());
235         oh.setNumberOfRvaAndSizes(dr.readDoubleWord());
236 
237         // Data directories
238         ImageDataDirectory[] dds = new ImageDataDirectory[16];
239         for (int i = 0; i < dds.length; i++) {
240             dds[i] = readImageDD(dr);
241         }
242         oh.setDataDirectories(dds);
243 
244         return oh;
245     }
246 
247     public static ImageDataDirectory readImageDD(IDataReader dr)
248             throws IOException {
249         ImageDataDirectory idd = new ImageDataDirectory();
250         idd.setVirtualAddress(dr.readDoubleWord());
251         idd.setSize(dr.readDoubleWord());
252         return idd;
253     }
254 
255     public static SectionTable readSectionHeaders(PE pe, IDataReader dr)
256             throws IOException {
257         SectionTable st = new SectionTable();
258         int ns = pe.getCoffHeader().getNumberOfSections();
259         for (int i = 0; i < ns; i++) {
260             st.add(readSectionHeader(dr));
261         }
262 
263         SectionHeader[] sorted = st.getHeadersPointerSorted();
264         int[] virtualAddress = new int[sorted.length];
265         int[] pointerToRawData = new int[sorted.length];
266         for (int i = 0; i < sorted.length; i++) {
267             virtualAddress[i] = sorted[i].getVirtualAddress();
268             pointerToRawData[i] = sorted[i].getPointerToRawData();
269         }
270 
271         st.setRvaConverter(new RVAConverter(virtualAddress, pointerToRawData));
272         return st;
273     }
274 
275     public static SectionHeader readSectionHeader(IDataReader dr)
276             throws IOException {
277         SectionHeader sh = new SectionHeader();
278         sh.setName(dr.readUtf(8));
279         sh.setVirtualSize(dr.readDoubleWord());
280         sh.setVirtualAddress(dr.readDoubleWord());
281         sh.setSizeOfRawData(dr.readDoubleWord());
282         sh.setPointerToRawData(dr.readDoubleWord());
283         sh.setPointerToRelocations(dr.readDoubleWord());
284         sh.setPointerToLineNumbers(dr.readDoubleWord());
285         sh.setNumberOfRelocations(dr.readWord());
286         sh.setNumberOfLineNumbers(dr.readWord());
287         sh.setCharacteristics(dr.readDoubleWord());
288         return sh;
289     }
290 
291     public static DataEntry findNextEntry(PE pe, int pos) {
292         DataEntry de = new DataEntry();
293 
294         // Check sections first
295         int ns = pe.getCoffHeader().getNumberOfSections();
296         for (int i = 0; i < ns; i++) {
297             SectionHeader sh = pe.getSectionTable().getHeader(i);
298             if (sh.getSizeOfRawData() > 0
299                     && sh.getPointerToRawData() >= pos
300                     && (de.pointer == 0 || sh.getPointerToRawData() < de.pointer)) {
301                 de.pointer = sh.getPointerToRawData();
302                 de.index = i;
303                 de.isSection = true;
304             }
305         }
306 
307         // Now check image data directories
308         RVAConverter rvc = pe.getSectionTable().getRVAConverter();
309         int dc = pe.getOptionalHeader().getDataDirectoryCount();
310         for (int i = 0; i < dc; i++) {
311             ImageDataDirectory idd = pe.getOptionalHeader().getDataDirectory(i);
312             if (idd.getSize() > 0) {
313                 int prd = idd.getVirtualAddress();
314                 // Assume certificate live outside section ?
315                 if (i != ImageDataDirectoryType.CERTIFICATE_TABLE
316                         && isInsideSection(pe, idd)) {
317                     prd = rvc.convertVirtualAddressToRawDataPointer(idd
318                             .getVirtualAddress());
319                 }
320                 if (prd >= pos && (de.pointer == 0 || prd < de.pointer)) {
321                     de.pointer = prd;
322                     de.index = i;
323                     de.isSection = false;
324                 }
325             }
326         }
327 
328         // Check debug
329         ImageData id = pe.getImageData();
330         DebugDirectory dd = null;
331         if (id != null) {
332             dd = id.getDebug();
333         }
334         if (dd != null) {
335             int prd = dd.getPointerToRawData();
336             if (prd >= pos && (de.pointer == 0 || prd < de.pointer)) {
337                 de.pointer = prd;
338                 de.index = -1;
339                 de.isDebugRawData = true;
340                 de.isSection = false;
341                 de.baseAddress = prd;
342             }
343         }
344 
345         if (de.pointer == 0) {
346             return null;
347         }
348 
349         return de;
350     }
351 
352     private static boolean isInsideSection(PE pe, ImageDataDirectory idd) {
353         int prd = idd.getVirtualAddress();
354         int pex = prd + idd.getSize();
355         SectionTable st = pe.getSectionTable();
356         int ns = st.getNumberOfSections();
357         for (int i = 0; i < ns; i++) {
358             SectionHeader sh = st.getHeader(i);
359             int vad = sh.getVirtualAddress();
360             int vex = vad + sh.getVirtualSize();
361             if (prd >= vad && prd < vex && pex <= vex) {
362                 return true;
363             }
364         }
365         return false;
366     }
367 
368     private static void readImageData(PE pe, DataEntry entry, IDataReader dr)
369             throws IOException {
370 
371         // Read any preamble data
372         ImageData id = pe.getImageData();
373         byte[] pa = readPreambleData(entry.pointer, dr);
374         if (pa != null) {
375             id.put(entry.index, pa);
376         }
377 
378         // Read the image data
379         ImageDataDirectory idd = pe.getOptionalHeader().getDataDirectory(
380                 entry.index);
381         byte[] b = new byte[idd.getSize()];
382         dr.read(b);
383 
384         switch (entry.index) {
385             case ImageDataDirectoryType.EXPORT_TABLE:
386                 id.setExportTable(readExportDirectory(b));
387                 break;
388             case ImageDataDirectoryType.IMPORT_TABLE:
389                 id.setImportTable(readImportDirectory(b, entry.baseAddress));
390                 break;
391             case ImageDataDirectoryType.RESOURCE_TABLE:
392                 id.setResourceTable(readResourceDirectory(b, entry.baseAddress));
393                 break;
394             case ImageDataDirectoryType.EXCEPTION_TABLE:
395                 id.setExceptionTable(b);
396                 break;
397             case ImageDataDirectoryType.CERTIFICATE_TABLE:
398                 id.setCertificateTable(readAttributeCertificateTable(b));
399                 break;
400             case ImageDataDirectoryType.BASE_RELOCATION_TABLE:
401                 id.setBaseRelocationTable(b);
402                 break;
403             case ImageDataDirectoryType.DEBUG:
404                 id.setDebug(readDebugDirectory(b));
405                 break;
406             case ImageDataDirectoryType.ARCHITECTURE:
407                 id.setArchitecture(b);
408                 break;
409             case ImageDataDirectoryType.GLOBAL_PTR:
410                 id.setGlobalPtr(b);
411                 break;
412             case ImageDataDirectoryType.TLS_TABLE:
413                 id.setTlsTable(b);
414                 break;
415             case ImageDataDirectoryType.LOAD_CONFIG_TABLE:
416                 id.setLoadConfigTable(readLoadConfigDirectory(pe, b));
417                 break;
418             case ImageDataDirectoryType.BOUND_IMPORT:
419                 id.setBoundImports(readBoundImportDirectoryTable(b));
420                 break;
421             case ImageDataDirectoryType.IAT:
422                 id.setIat(b);
423                 break;
424             case ImageDataDirectoryType.DELAY_IMPORT_DESCRIPTOR:
425                 id.setDelayImportDescriptor(b);
426                 break;
427             case ImageDataDirectoryType.CLR_RUNTIME_HEADER:
428                 id.setClrRuntimeHeader(b);
429                 break;
430             case ImageDataDirectoryType.RESERVED:
431                 id.setReserved(b);
432                 break;
433             default:
434                 break;
435         }
436     }
437 
438     private static byte[] readPreambleData(int pointer, IDataReader dr)
439             throws IOException {
440         if (pointer > dr.getPosition()) {
441             byte[] pa = new byte[pointer - dr.getPosition()];
442             dr.read(pa);
443             boolean zeroes = true;
444             for (byte b : pa) {
445                 if (b != 0) {
446                     zeroes = false;
447                     break;
448                 }
449             }
450             if (!zeroes) {
451                 return pa;
452             }
453         }
454 
455         return null;
456     }
457 
458     private static void readDebugRawData(PE pe, DataEntry entry, IDataReader dr)
459             throws IOException {
460         // Read any preamble data
461         ImageData id = pe.getImageData();
462         byte[] pa = readPreambleData(entry.pointer, dr);
463         if (pa != null) {
464             id.setDebugRawDataPreamble(pa);
465         }
466         DebugDirectory dd = id.getDebug();
467         byte[] b = new byte[dd.getSizeOfData()];
468         dr.read(b);
469         id.setDebugRawData(b);
470     }
471 
472     private static void readSection(PE pe, DataEntry entry, IDataReader dr)
473             throws IOException {
474         SectionTable st = pe.getSectionTable();
475         SectionHeader sh = st.getHeader(entry.index);
476         SectionData sd = new SectionData();
477 
478         // Read any preamble - store if non-zero
479         byte[] pa = readPreambleData(sh.getPointerToRawData(), dr);
480         if (pa != null) {
481             sd.setPreamble(pa);
482         }
483 
484         // Read in the raw data block
485         dr.jumpTo(sh.getPointerToRawData());
486         byte[] b = new byte[sh.getSizeOfRawData()];
487         dr.read(b);
488         sd.setData(b);
489         st.put(entry.index, sd);
490 
491         // Check for an image directory within this section
492         int ddc = pe.getOptionalHeader().getDataDirectoryCount();
493         for (int i = 0; i < ddc; i++) {
494             if (i == ImageDataDirectoryType.CERTIFICATE_TABLE) {
495                 continue;
496             }
497             ImageDataDirectory idd = pe.getOptionalHeader().getDataDirectory(i);
498             if (idd.getSize() > 0) {
499                 int vad = sh.getVirtualAddress();
500                 int vex = vad + sh.getVirtualSize();
501                 int dad = idd.getVirtualAddress();
502                 if (dad >= vad && dad < vex) {
503                     int off = dad - vad;
504                     IDataReader idr = new ByteArrayDataReader(b, off,
505                             idd.getSize());
506                     DataEntry de = new DataEntry(i, 0);
507                     de.baseAddress = sh.getVirtualAddress();
508                     readImageData(pe, de, idr);
509                 }
510             }
511         }
512     }
513 
514     private static BoundImportDirectoryTable readBoundImportDirectoryTable(
515             byte[] b) throws IOException {
516         DataReader dr = new DataReader(b);
517         BoundImportDirectoryTable bidt = new BoundImportDirectoryTable();
518         List<BoundImport> imports = new ArrayList<>();
519         BoundImport bi = null;
520         while ((bi = readBoundImport(dr)) != null) {
521             bidt.add(bi);
522             imports.add(bi);
523         }
524         imports.sort((o1, o2) -> o1.getOffsetToModuleName() - o2.getOffsetToModuleName());
525         IntMap names = new IntMap();
526         for (BoundImport anImport : imports) {
527             bi = anImport;
528             int offset = bi.getOffsetToModuleName();
529             String n = (String) names.get(offset);
530             if (n == null) {
531                 dr.jumpTo(offset);
532                 n = dr.readUtf();
533                 names.put(offset, n);
534             }
535             bi.setModuleName(n);
536         }
537         return bidt;
538     }
539 
540     private static BoundImport readBoundImport(IDataReader dr)
541             throws IOException {
542         BoundImport bi = new BoundImport();
543         bi.setTimestamp(dr.readDoubleWord());
544         bi.setOffsetToModuleName(dr.readWord());
545         bi.setNumberOfModuleForwarderRefs(dr.readWord());
546 
547         if (bi.getTimestamp() == 0 && bi.getOffsetToModuleName() == 0
548                 && bi.getNumberOfModuleForwarderRefs() == 0) {
549             return null;
550         }
551 
552         return bi;
553     }
554 
555     public static ImportDirectory readImportDirectory(byte[] b, int baseAddress)
556             throws IOException {
557         DataReader dr = new DataReader(b);
558         ImportDirectory id = new ImportDirectory();
559         ImportDirectoryEntry ide = null;
560         while ((ide = readImportDirectoryEntry(dr)) != null) {
561             id.add(ide);
562         }
563 
564         /*
565 		 * FIXME - name table refer to data outside image directory for (int i =
566 		 * 0; i < id.size(); i++) { ImportDirectoryEntry e = id.getEntry(i);
567 		 * dr.jumpTo(e.getNameRVA() - baseAddress); String name = dr.readUtf();
568 		 * dr.jumpTo(e.getImportLookupTableRVA() - baseAddress);
569 		 * ImportDirectoryTable nt = readImportDirectoryTable(dr, baseAddress);
570 		 * dr.jumpTo(e.getImportAddressTableRVA() - baseAddress);
571 		 * ImportDirectoryTable at = null; // readImportDirectoryTable(dr, //
572 		 * baseAddress); id.add(name, nt, at); }
573          */
574         return id;
575     }
576 
577     public static ImportDirectoryEntry readImportDirectoryEntry(IDataReader dr)
578             throws IOException {
579         ImportDirectoryEntry id = new ImportDirectoryEntry();
580         id.setImportLookupTableRVA(dr.readDoubleWord());
581         id.setTimeDateStamp(dr.readDoubleWord());
582         id.setForwarderChain(dr.readDoubleWord());
583         id.setNameRVA(dr.readDoubleWord());
584         id.setImportAddressTableRVA(dr.readDoubleWord());
585 
586         // The last entry is null
587         if (id.getImportLookupTableRVA() == 0) {
588             return null;
589         }
590 
591         return id;
592     }
593 
594     public static ImportDirectoryTable readImportDirectoryTable(IDataReader dr,
595             int baseAddress) throws IOException {
596         ImportDirectoryTable idt = new ImportDirectoryTable();
597         ImportEntry ie = null;
598         while ((ie = readImportEntry(dr)) != null) {
599             idt.add(ie);
600         }
601 
602         for (int i = 0; i < idt.size(); i++) {
603             ImportEntry iee = idt.getEntry(i);
604             if ((iee.getVal() & 0x80000000) != 0) {
605                 iee.setOrdinal(iee.getVal() & 0x7fffffff);
606             } else {
607                 dr.jumpTo(iee.getVal() - baseAddress);
608                 dr.readWord(); // FIXME this is an index into the export table
609                 iee.setName(dr.readUtf());
610             }
611         }
612         return idt;
613     }
614 
615     public static ImportEntry readImportEntry(IDataReader dr)
616             throws IOException {
617         ImportEntry ie = new ImportEntry();
618         ie.setVal(dr.readDoubleWord());
619         if (ie.getVal() == 0) {
620             return null;
621         }
622 
623         return ie;
624     }
625 
626     public static ExportDirectory readExportDirectory(byte[] b)
627             throws IOException {
628         DataReader dr = new DataReader(b);
629         ExportDirectory edt = new ExportDirectory();
630         edt.set(b);
631         edt.setExportFlags(dr.readDoubleWord());
632         edt.setTimeDateStamp(dr.readDoubleWord());
633         edt.setMajorVersion(dr.readWord());
634         edt.setMinorVersion(dr.readWord());
635         edt.setNameRVA(dr.readDoubleWord());
636         edt.setOrdinalBase(dr.readDoubleWord());
637         edt.setAddressTableEntries(dr.readDoubleWord());
638         edt.setNumberOfNamePointers(dr.readDoubleWord());
639         edt.setExportAddressTableRVA(dr.readDoubleWord());
640         edt.setNamePointerRVA(dr.readDoubleWord());
641         edt.setOrdinalTableRVA(dr.readDoubleWord());
642         return edt;
643     }
644 
645     public static LoadConfigDirectory readLoadConfigDirectory(PE pe, byte[] b)
646             throws IOException {
647         DataReader dr = new DataReader(b);
648         LoadConfigDirectory lcd = new LoadConfigDirectory();
649         lcd.set(b);
650         lcd.setSize(dr.readDoubleWord());
651         lcd.setTimeDateStamp(dr.readDoubleWord());
652         lcd.setMajorVersion(dr.readWord());
653         lcd.setMinorVersion(dr.readWord());
654         lcd.setGlobalFlagsClear(dr.readDoubleWord());
655         lcd.setGlobalFlagsSet(dr.readDoubleWord());
656         lcd.setCriticalSectionDefaultTimeout(dr.readDoubleWord());
657         lcd.setDeCommitFreeBlockThreshold(pe.is64() ? dr.readLong() : dr.readDoubleWord());
658         lcd.setDeCommitTotalFreeThreshold(pe.is64() ? dr.readLong() : dr.readDoubleWord());
659         lcd.setLockPrefixTable(pe.is64() ? dr.readLong() : dr.readDoubleWord());
660         lcd.setMaximumAllocationSize(pe.is64() ? dr.readLong() : dr.readDoubleWord());
661         lcd.setVirtualMemoryThreshold(pe.is64() ? dr.readLong() : dr.readDoubleWord());
662         lcd.setProcessAffinityMask(pe.is64() ? dr.readLong() : dr.readDoubleWord());
663         lcd.setProcessHeapFlags(dr.readDoubleWord());
664         lcd.setCsdVersion(dr.readWord());
665         lcd.setReserved(dr.readWord());
666         lcd.setEditList(pe.is64() ? dr.readLong() : dr.readDoubleWord());
667         if (dr.hasMore()) // optional
668         {
669             lcd.setSecurityCookie(pe.is64() ? dr.readLong() : dr.readDoubleWord());
670         }
671         if (dr.hasMore()) // optional
672         {
673             lcd.setSeHandlerTable(pe.is64() ? dr.readLong() : dr.readDoubleWord());
674         }
675         if (dr.hasMore()) // optional
676         {
677             lcd.setSeHandlerCount(pe.is64() ? dr.readLong() : dr.readDoubleWord());
678         }
679 
680         return lcd;
681     }
682 
683     public static DebugDirectory readDebugDirectory(byte[] b)
684             throws IOException {
685         return readDebugDirectory(b, new DataReader(b));
686     }
687 
688     public static DebugDirectory readDebugDirectory(byte[] b, IDataReader dr)
689             throws IOException {
690         DebugDirectory dd = new DebugDirectory();
691         dd.set(b);
692         dd.setCharacteristics(dr.readDoubleWord());
693         dd.setTimeDateStamp(dr.readDoubleWord());
694         dd.setMajorVersion(dr.readWord());
695         dd.setMajorVersion(dr.readWord());
696         dd.setType(dr.readDoubleWord());
697         dd.setSizeOfData(dr.readDoubleWord());
698         dd.setAddressOfRawData(dr.readDoubleWord());
699         dd.setPointerToRawData(dr.readDoubleWord());
700         return dd;
701     }
702 
703     private static ResourceDirectory readResourceDirectory(byte[] b,
704             int baseAddress) throws IOException {
705         IDataReader dr = new ByteArrayDataReader(b);
706         return readResourceDirectory(dr, baseAddress);
707     }
708 
709     private static ResourceDirectory readResourceDirectory(IDataReader dr,
710             int baseAddress) throws IOException {
711         ResourceDirectory d = new ResourceDirectory();
712         d.setTable(readResourceDirectoryTable(dr));
713         int ne = d.getTable().getNumNameEntries()
714                 + d.getTable().getNumIdEntries();
715         for (int i = 0; i < ne; i++) {
716             d.add(readResourceEntry(dr, baseAddress));
717         }
718 
719         return d;
720     }
721 
722     private static ResourceEntry readResourceEntry(IDataReader dr,
723             int baseAddress) throws IOException {
724         ResourceEntry re = new ResourceEntry();
725         int id = dr.readDoubleWord();
726         int offset = dr.readDoubleWord();
727         re.setOffset(offset);
728         int pos = dr.getPosition();
729         if ((id & 0x80000000) != 0) {
730             dr.jumpTo(id & 0x7fffffff);
731             re.setName(dr.readUnicode(dr.readWord()));
732         } else {
733             re.setId(id);
734         }
735         if ((offset & 0x80000000) != 0) {
736             dr.jumpTo(offset & 0x7fffffff);
737             re.setDirectory(readResourceDirectory(dr, baseAddress));
738         } else {
739             dr.jumpTo(offset);
740             int rva = dr.readDoubleWord();
741             int size = dr.readDoubleWord();
742             int cp = dr.readDoubleWord();
743             int res = dr.readDoubleWord();
744             re.setDataRVA(rva);
745             re.setCodePage(cp);
746             re.setReserved(res);
747             dr.jumpTo(rva - baseAddress);
748             byte[] b = new byte[size];
749             dr.read(b);
750             re.setData(b);
751         }
752         dr.jumpTo(pos);
753         return re;
754     }
755 
756     private static ResourceDirectoryTable readResourceDirectoryTable(
757             IDataReader dr) throws IOException {
758         ResourceDirectoryTable t = new ResourceDirectoryTable();
759         t.setCharacteristics(dr.readDoubleWord());
760         t.setTimeDateStamp(dr.readDoubleWord());
761         t.setMajorVersion(dr.readWord());
762         t.setMinVersion(dr.readWord());
763         t.setNumNameEntries(dr.readWord());
764         t.setNumIdEntries(dr.readWord());
765 
766         return t;
767     }
768 
769     public static AttributeCertificateTable readAttributeCertificateTable(byte[] b)
770             throws IOException {
771         return readAttributeCertificateTable(b, new DataReader(b));
772     }
773 
774     public static AttributeCertificateTable readAttributeCertificateTable(byte[] b, IDataReader dr)
775             throws IOException {
776         AttributeCertificateTable dd = new AttributeCertificateTable();
777         dd.set(b);
778         dd.setLength(dr.readDoubleWord());
779         dd.setRevision(dr.readWord());
780         dd.setCertificateType(dr.readWord());
781         byte[] certificate = new byte[dd.getLength() - 8];
782         dr.read(certificate);
783         dd.setCertificate(certificate);
784         return dd;
785     }
786 
787 }