Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Parser and Assembler refactoring #31

Merged
merged 5 commits into from
Jun 26, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,8 @@ import com.kichik.pecoff4j.PE;
import com.kichik.pecoff4j.ResourceDirectory;
import com.kichik.pecoff4j.ResourceEntry;
import com.kichik.pecoff4j.constant.ResourceType;
import com.kichik.pecoff4j.io.DataReader;
import com.kichik.pecoff4j.io.PEParser;
import com.kichik.pecoff4j.io.ResourceParser;
import com.kichik.pecoff4j.resources.StringFileInfo;
import com.kichik.pecoff4j.resources.StringTable;
import com.kichik.pecoff4j.resources.VersionInfo;
Expand All @@ -61,7 +61,7 @@ public class Main {
ResourceEntry[] entries = ResourceHelper.findResources(rd, ResourceType.VERSION_INFO);
for (int i = 0; i < entries.length; i++) {
byte[] data = entries[i].getData();
VersionInfo version = ResourceParser.readVersionInfo(data);
VersionInfo version = VersionInfo.read(new DataReader(data));

StringFileInfo strings = version.getStringFileInfo();
StringTable table = strings.getTable(0);
Expand Down
7 changes: 3 additions & 4 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,7 @@

<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<!-- must be marked as 7 instead of 1.7; otherwise: "Fatal error compiling: release version 1.7 not supported" -->
<maven.compiler.release>7</maven.compiler.release>
<maven.compiler.release>8</maven.compiler.release>
</properties>

<scm>
Expand Down Expand Up @@ -114,9 +113,9 @@
<release>9</release>
</configuration>
</execution>
<!-- compile sources for Java 7 -->
<!-- compile sources for Java 8 -->
<execution>
<id>java-7-compile</id>
<id>java-8-compile</id>
<goals>
<goal>compile</goal>
</goals>
Expand Down
16 changes: 16 additions & 0 deletions src/main/java/com/kichik/pecoff4j/AttributeCertificateTable.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,11 @@
*******************************************************************************/
package com.kichik.pecoff4j;

import com.kichik.pecoff4j.io.DataReader;
import com.kichik.pecoff4j.util.DataObject;

import java.io.IOException;

/**
* Encapsulates the Attribute Certificate Table (Image Only). Section 5.7 of the PE/COFF
* spec Rev10.
Expand All @@ -21,6 +24,19 @@ public class AttributeCertificateTable extends DataObject {
private int certificateType;
private byte[] certificate;

public static AttributeCertificateTable read(byte[] b) throws IOException {
AttributeCertificateTable dd = new AttributeCertificateTable();
dd.set(b);
DataReader dr = new DataReader(b);
dd.setLength(dr.readDoubleWord());
dd.setRevision(dr.readWord());
dd.setCertificateType(dr.readWord());
byte[] certificate = new byte[dd.getLength() - 8];
dr.read(certificate);
dd.setCertificate(certificate);
return dd;
}

public int getLength() {
return length;
}
Expand Down
17 changes: 17 additions & 0 deletions src/main/java/com/kichik/pecoff4j/BoundImport.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,29 @@
*******************************************************************************/
package com.kichik.pecoff4j;

import com.kichik.pecoff4j.io.IDataReader;

import java.io.IOException;

public class BoundImport {
private long timestamp;
private int offsetToModuleName;
private String moduleName;
private int numModuleForwarderRefs;

public static BoundImport read(IDataReader dr) throws IOException {
BoundImport bi = new BoundImport();
bi.setTimestamp(dr.readDoubleWord());
bi.setOffsetToModuleName(dr.readWord());
bi.setNumberOfModuleForwarderRefs(dr.readWord());

if (bi.getTimestamp() == 0 && bi.getOffsetToModuleName() == 0
&& bi.getNumberOfModuleForwarderRefs() == 0)
return null;

return bi;
}

public long getTimestamp() {
return timestamp;
}
Expand Down
81 changes: 81 additions & 0 deletions src/main/java/com/kichik/pecoff4j/BoundImportDirectoryTable.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,93 @@
*******************************************************************************/
package com.kichik.pecoff4j;

import com.kichik.pecoff4j.constant.ImageDataDirectoryType;
import com.kichik.pecoff4j.io.DataReader;
import com.kichik.pecoff4j.io.IDataWriter;
import com.kichik.pecoff4j.util.IntMap;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

public class BoundImportDirectoryTable {
private List<BoundImport> imports = new ArrayList();

public static BoundImportDirectoryTable read(DataReader dr) throws IOException {
BoundImportDirectoryTable bidt = new BoundImportDirectoryTable();
List<BoundImport> imports = new ArrayList<BoundImport>();
BoundImport bi = null;
while ((bi = BoundImport.read(dr)) != null) {
bidt.add(bi);
imports.add(bi);
}
Collections.sort(imports, new Comparator<BoundImport>() {
@Override
public int compare(BoundImport o1, BoundImport o2) {
return o1.getOffsetToModuleName() - o2.getOffsetToModuleName();
}
});
IntMap names = new IntMap();
for (int i = 0; i < imports.size(); i++) {
bi = imports.get(i);
int offset = bi.getOffsetToModuleName();
String n = (String) names.get(offset);
if (n == null) {
dr.jumpTo(offset);
n = dr.readUtf();
names.put(offset, n);
}
bi.setModuleName(n);
}
return bidt;
}

public void write(PE pe, IDataWriter dw) throws IOException {
int pos = dw.getPosition();
List<BoundImport> bil = new ArrayList();

for (int i = 0; i < size(); i++) {
BoundImport bi = get(i);
bil.add(bi);
dw.writeDoubleWord((int) bi.getTimestamp());
dw.writeWord(bi.getOffsetToModuleName());
dw.writeWord(bi.getNumberOfModuleForwarderRefs());
}

Collections.sort(bil, new Comparator<BoundImport>() {
@Override
public int compare(BoundImport o1, BoundImport o2) {
return o1.getOffsetToModuleName() - o2.getOffsetToModuleName();
}
});

// Now write out empty block
dw.writeDoubleWord(0);
dw.writeDoubleWord(0);

// Now write out module names
Set names = new HashSet();
for (int i = 0; i < bil.size(); i++) {
String s = bil.get(i).getModuleName();
if (!names.contains(s))
dw.writeUtf(s);
names.add(s);
}

// Check for empty block at end - padding for alignment
int dpos = dw.getPosition() - pos;
int bis = pe.getOptionalHeader()
.getDataDirectory(ImageDataDirectoryType.BOUND_IMPORT)
.getSize();
if (bis > dpos) {
dw.writeByte(0, bis - dpos);
}
}

public void add(BoundImport bi) {
imports.add(bi);
}
Expand Down
29 changes: 29 additions & 0 deletions src/main/java/com/kichik/pecoff4j/CLRRuntimeHeader.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
package com.kichik.pecoff4j;

import com.kichik.pecoff4j.io.DataReader;
import com.kichik.pecoff4j.util.DataObject;

import java.io.IOException;

public class CLRRuntimeHeader extends DataObject {
private int headerSize;
private int majorRuntimeVersion;
Expand All @@ -23,6 +26,32 @@ public class CLRRuntimeHeader extends DataObject {
private int managedNativeHeaderAddress;
private int managedNativeHeaderSize;

public static CLRRuntimeHeader read(byte[] b) throws IOException {
DataReader dr = new DataReader(b);
CLRRuntimeHeader clrrh = new CLRRuntimeHeader();
clrrh.set(b);
clrrh.setHeaderSize(dr.readDoubleWord());
clrrh.setMajorRuntimeVersion(dr.readWord());
clrrh.setMinorRuntimeVersion(dr.readWord());
clrrh.setMetaDataDirectoryAddress(dr.readDoubleWord());
clrrh.setMetaDataDirectorySize(dr.readDoubleWord());
clrrh.setFlags(dr.readDoubleWord());
clrrh.setEntryPointToken(dr.readDoubleWord());
clrrh.setResourcesDirectoryAddress(dr.readDoubleWord());
clrrh.setResourcesDirectorySize(dr.readDoubleWord());
clrrh.setStrongNameSignatureAddress(dr.readDoubleWord());
clrrh.setStrongNameSignatureSize(dr.readDoubleWord());
clrrh.setCodeManagerTableAddress(dr.readDoubleWord());
clrrh.setCodeManagerTableSize(dr.readDoubleWord());
clrrh.setvTableFixupsAddress(dr.readDoubleWord());
clrrh.setvTableFixupsSize(dr.readDoubleWord());
clrrh.setExportAddressTableJumpsAddress(dr.readDoubleWord());
clrrh.setExportAddressTableJumpsSize(dr.readDoubleWord());
clrrh.setManagedNativeHeaderAddress(dr.readDoubleWord());
clrrh.setManagedNativeHeaderSize(dr.readDoubleWord());
return clrrh;
}

public int getHeaderSize() {
return headerSize;
}
Expand Down
27 changes: 27 additions & 0 deletions src/main/java/com/kichik/pecoff4j/COFFHeader.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,11 @@
*******************************************************************************/
package com.kichik.pecoff4j;

import com.kichik.pecoff4j.io.IDataReader;
import com.kichik.pecoff4j.io.IDataWriter;

import java.io.IOException;

public class COFFHeader {
private int machine;
private int numberOfSections;
Expand All @@ -18,6 +23,28 @@ public class COFFHeader {
private int sizeOfOptionalHeader;
private int characteristics;

public static COFFHeader read(IDataReader dr) throws IOException {
COFFHeader h = new COFFHeader();
h.setMachine(dr.readWord());
h.setNumberOfSections(dr.readWord());
h.setTimeDateStamp(dr.readDoubleWord());
h.setPointerToSymbolTable(dr.readDoubleWord());
h.setNumberOfSymbols(dr.readDoubleWord());
h.setSizeOfOptionalHeader(dr.readWord());
h.setCharacteristics(dr.readWord());
return h;
}

public void write(IDataWriter dw) throws IOException {
dw.writeWord(getMachine());
dw.writeWord(getNumberOfSections());
dw.writeDoubleWord(getTimeDateStamp());
dw.writeDoubleWord(getPointerToSymbolTable());
dw.writeDoubleWord(getNumberOfSymbols());
dw.writeWord(getSizeOfOptionalHeader());
dw.writeWord(getCharacteristics());
}

public int getMachine() {
return machine;
}
Expand Down
74 changes: 74 additions & 0 deletions src/main/java/com/kichik/pecoff4j/DOSHeader.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,11 @@
*******************************************************************************/
package com.kichik.pecoff4j;

import com.kichik.pecoff4j.io.IDataReader;
import com.kichik.pecoff4j.io.IDataWriter;

import java.io.IOException;

public class DOSHeader {
public static final int DOS_MAGIC = 0;

Expand All @@ -33,6 +38,75 @@ public class DOSHeader {
private int addressOfNewExeHeader;
private int stubSize;

public static DOSHeader read(IDataReader dr) throws IOException {
DOSHeader dh = new DOSHeader();
dh.setMagic(dr.readWord());
dh.setUsedBytesInLastPage(dr.readWord());
dh.setFileSizeInPages(dr.readWord());
dh.setNumRelocationItems(dr.readWord());
dh.setHeaderSizeInParagraphs(dr.readWord());
dh.setMinExtraParagraphs(dr.readWord());
dh.setMaxExtraParagraphs(dr.readWord());
dh.setInitialSS(dr.readWord());
dh.setInitialSP(dr.readWord());
dh.setChecksum(dr.readWord());
dh.setInitialIP(dr.readWord());
dh.setInitialRelativeCS(dr.readWord());
dh.setAddressOfRelocationTable(dr.readWord());
dh.setOverlayNumber(dr.readWord());
int[] reserved = new int[4];
for (int i = 0; i < reserved.length; i++) {
reserved[i] = dr.readWord();
}
dh.setReserved(reserved);
dh.setOemId(dr.readWord());
dh.setOemInfo(dr.readWord());
int[] reserved2 = new int[10];
for (int i = 0; i < reserved2.length; i++) {
reserved2[i] = dr.readWord();
}
dh.setReserved2(reserved2);
dh.setAddressOfNewExeHeader(dr.readDoubleWord());

// calc stub size
int stubSize = dh.getFileSizeInPages() * 512
- (512 - dh.getUsedBytesInLastPage());
if (stubSize > dh.getAddressOfNewExeHeader())
stubSize = dh.getAddressOfNewExeHeader();
stubSize -= dh.getHeaderSizeInParagraphs() * 16;
dh.setStubSize(stubSize);

return dh;
}

public void write(IDataWriter dw) throws IOException {
dw.writeWord(getMagic());
dw.writeWord(getUsedBytesInLastPage());
dw.writeWord(getFileSizeInPages());
dw.writeWord(getNumRelocationItems());
dw.writeWord(getHeaderSizeInParagraphs());
dw.writeWord(getMinExtraParagraphs());
dw.writeWord(getMaxExtraParagraphs());
dw.writeWord(getInitialSS());
dw.writeWord(getInitialSP());
dw.writeWord(getChecksum());
dw.writeWord(getInitialIP());
dw.writeWord(getInitialRelativeCS());
dw.writeWord(getAddressOfRelocationTable());
dw.writeWord(getOverlayNumber());
int[] res = getReserved();
for (int i = 0; i < res.length; i++) {
dw.writeWord(res[i]);
}
dw.writeWord(getOemId());
dw.writeWord(getOemInfo());
int[] res2 = getReserved2();
for (int i = 0; i < res2.length; i++) {
dw.writeWord(res2[i]);
}
dw.writeDoubleWord(getAddressOfNewExeHeader());
}

public int getMagic() {
return magic;
}
Expand Down
Loading