1
2
3
4
5
6
7
8
9
10 package org.owasp.dependencycheck.utils;
11
12 import com.kichik.pecoff4j.COFFHeader;
13 import com.kichik.pecoff4j.DOSHeader;
14 import com.kichik.pecoff4j.DOSStub;
15 import com.kichik.pecoff4j.DebugDirectory;
16 import com.kichik.pecoff4j.ImageData;
17 import com.kichik.pecoff4j.OptionalHeader;
18 import com.kichik.pecoff4j.PE;
19 import com.kichik.pecoff4j.PESignature;
20 import com.kichik.pecoff4j.SectionData;
21 import com.kichik.pecoff4j.SectionTable;
22 import com.kichik.pecoff4j.io.DataEntry;
23 import com.kichik.pecoff4j.io.DataReader;
24 import com.kichik.pecoff4j.io.IDataReader;
25 import org.slf4j.Logger;
26 import org.slf4j.LoggerFactory;
27
28 import java.io.EOFException;
29 import java.io.File;
30 import java.io.FileInputStream;
31 import java.io.IOException;
32
33
34
35
36
37
38
39
40
41
42 public class PEParser {
43 private static final Logger LOGGER = LoggerFactory.getLogger(PEParser.class);
44
45 public static PE parse(File file) throws IOException {
46 try (FileInputStream is = new FileInputStream(file); DataReader dr = new DataReader(is)) {
47 return read(dr, file.getPath());
48 }
49 }
50
51
52
53
54
55
56 private static PE read(IDataReader dr, String context) throws IOException {
57 PE pe = new PE();
58 pe.setDosHeader(DOSHeader.read(dr));
59
60
61 if (pe.getDosHeader().getAddressOfNewExeHeader() == 0
62 || pe.getDosHeader().getAddressOfNewExeHeader() > 8192) {
63 return pe;
64 }
65
66 pe.setStub(DOSStub.read(pe.getDosHeader(), dr));
67 pe.setSignature(PESignature.read(dr));
68
69
70 if (!pe.getSignature().isValid()) {
71 return pe;
72 }
73
74 pe.setCoffHeader(COFFHeader.read(dr));
75 pe.setOptionalHeader(OptionalHeader.read(dr));
76 pe.setSectionTable(SectionTable.read(pe, dr));
77
78 pe.set64(pe.getOptionalHeader().isPE32plus());
79
80
81 DataEntry entry;
82 while ((entry = pe.findNextEntry(dr.getPosition())) != null) {
83 DataEntry finalEntry = entry;
84 if (finalEntry.isSection) {
85 SectionData.read(pe, finalEntry, dr);
86 } else if (entry.isDebugRawData) {
87 withEofSwallowing(() -> readDebugRawData(pe, finalEntry, dr), "debug raw data: " + context);
88 } else {
89 withEofSwallowing(() -> pe.getImageData().read(pe, finalEntry, dr), "image data: " + context);
90 }
91 }
92
93
94 withEofSwallowing(() -> {
95 byte[] tb = dr.readAll();
96 if (tb.length > 0) {
97 pe.getImageData().setTrailingData(tb);
98 }
99 }, "trailing data: " + context);
100
101 return pe;
102 }
103
104
105
106
107
108 private static void readDebugRawData(PE pe, DataEntry entry, IDataReader dr) throws IOException {
109
110 ImageData id = pe.getImageData();
111 byte[] pa = dr.readNonZeroOrNull(entry.pointer);
112 if (pa != null) {
113 id.setDebugRawDataPreamble(pa);
114 }
115 DebugDirectory dd = id.getDebug();
116 byte[] b = new byte[dd.getSizeOfData()];
117 dr.read(b);
118 id.setDebugRawData(b);
119 }
120
121 private static void withEofSwallowing(IOExceptionThrower throwingRunnable, String errorContext) throws IOException {
122 try {
123 throwingRunnable.read();
124 } catch (EOFException e) {
125 LOGGER.debug("Error reading {}. Trying to continue...", errorContext, e);
126 }
127 }
128
129 private interface IOExceptionThrower {
130 void read() throws IOException;
131 }
132 }