mirror of
https://github.com/NationalSecurityAgency/ghidra
synced 2024-10-13 05:33:02 +00:00
Merge remote-tracking branch 'origin/GP-64_ghizard_Partial_Clang_Windows_Support'
This commit is contained in:
commit
85073f4c46
|
@ -182,7 +182,8 @@ public class PeLoader extends AbstractPeDebugLoader {
|
|||
}
|
||||
|
||||
@Override
|
||||
public String validateOptions(ByteProvider provider, LoadSpec loadSpec, List<Option> options, Program program) {
|
||||
public String validateOptions(ByteProvider provider, LoadSpec loadSpec, List<Option> options,
|
||||
Program program) {
|
||||
if (options != null) {
|
||||
for (Option option : options) {
|
||||
String name = option.getName();
|
||||
|
@ -797,16 +798,20 @@ public class PeLoader extends AbstractPeDebugLoader {
|
|||
"This program must be run under Win32\r\n$".toCharArray();
|
||||
static final char[] errString_GCC_VS =
|
||||
"This program cannot be run in DOS mode.\r\r\n$".toCharArray();
|
||||
static final char[] errString_Clang =
|
||||
"This program cannot be run in DOS mode.$".toCharArray();
|
||||
static final int[] asm16_Borland = { 0xBA, 0x10, 0x00, 0x0E, 0x1F, 0xB4, 0x09, 0xCD, 0x21,
|
||||
0xB8, 0x01, 0x4C, 0xCD, 0x21, 0x90, 0x90 };
|
||||
static final int[] asm16_GCC_VS =
|
||||
static final int[] asm16_GCC_VS_Clang =
|
||||
{ 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd, 0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21 };
|
||||
|
||||
public enum CompilerEnum {
|
||||
|
||||
VisualStudio("visualstudio:unknown"),
|
||||
GCC("gcc:unknown"),
|
||||
Clang("clang:unknown"),
|
||||
GCC_VS("visualstudiogcc"),
|
||||
GCC_VS_Clang("visualstudiogccclang"),
|
||||
BorlandPascal("borland:pascal"),
|
||||
BorlandCpp("borland:c++"),
|
||||
BorlandUnk("borland:unknown"),
|
||||
|
@ -892,6 +897,9 @@ public class PeLoader extends AbstractPeDebugLoader {
|
|||
if (dh.e_lfanew() == 0x80) {
|
||||
offsetChoice = CompilerEnum.GCC_VS;
|
||||
}
|
||||
else if (dh.e_lfanew() == 0x78) {
|
||||
offsetChoice = CompilerEnum.Clang;
|
||||
}
|
||||
else if (dh.e_lfanew() < 0x80) {
|
||||
offsetChoice = CompilerEnum.Unknown;
|
||||
}
|
||||
|
@ -931,13 +939,13 @@ public class PeLoader extends AbstractPeDebugLoader {
|
|||
asmChoice = CompilerEnum.BorlandUnk;
|
||||
}
|
||||
else {
|
||||
for (counter = 0; counter < asm16_GCC_VS.length; counter++) {
|
||||
if ((asm[counter] & 0xff) != (asm16_GCC_VS[counter] & 0xff)) {
|
||||
for (counter = 0; counter < asm16_GCC_VS_Clang.length; counter++) {
|
||||
if ((asm[counter] & 0xff) != (asm16_GCC_VS_Clang[counter] & 0xff)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (counter == asm16_GCC_VS.length) {
|
||||
asmChoice = CompilerEnum.GCC_VS;
|
||||
if (counter == asm16_GCC_VS_Clang.length) {
|
||||
asmChoice = CompilerEnum.GCC_VS_Clang;
|
||||
}
|
||||
else {
|
||||
asmChoice = CompilerEnum.Unknown;
|
||||
|
@ -948,6 +956,7 @@ public class PeLoader extends AbstractPeDebugLoader {
|
|||
for (int i = 10; i < asm.length - 3; i++) {
|
||||
if (asm[i] == 'T' && asm[i + 1] == 'h' && asm[i + 2] == 'i' && asm[i + 3] == 's') {
|
||||
errStringOffset = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -966,13 +975,16 @@ public class PeLoader extends AbstractPeDebugLoader {
|
|||
else if (compareBytesToChars(asm, errStringOffset, errString_GCC_VS)) {
|
||||
errStringChoice = CompilerEnum.GCC_VS;
|
||||
}
|
||||
else if (compareBytesToChars(asm, errStringOffset, errString_Clang)) {
|
||||
errStringChoice = CompilerEnum.Clang;
|
||||
}
|
||||
else {
|
||||
errStringChoice = CompilerEnum.Unknown;
|
||||
}
|
||||
}
|
||||
|
||||
// Check for AddressOfStart and PointerToSymbol
|
||||
if (errStringChoice == CompilerEnum.GCC_VS && asmChoice == CompilerEnum.GCC_VS &&
|
||||
if (errStringChoice == CompilerEnum.GCC_VS && asmChoice == CompilerEnum.GCC_VS_Clang &&
|
||||
dh.e_lfanew() == 0x80) {
|
||||
// Trying to determine if we have gcc or old VS
|
||||
|
||||
|
@ -997,6 +1009,11 @@ public class PeLoader extends AbstractPeDebugLoader {
|
|||
return compilerType;
|
||||
}
|
||||
}
|
||||
else if ((offsetChoice == CompilerEnum.Clang ||
|
||||
errStringChoice == CompilerEnum.Clang) && asmChoice == CompilerEnum.GCC_VS_Clang) {
|
||||
compilerType = CompilerEnum.Clang;
|
||||
return compilerType;
|
||||
}
|
||||
else if (errStringChoice == CompilerEnum.Unknown || asmChoice == CompilerEnum.Unknown) {
|
||||
compilerType = CompilerEnum.Unknown;
|
||||
return compilerType;
|
||||
|
|
|
@ -119,9 +119,12 @@ public abstract class AbstractCreateDataTypeModel {
|
|||
*/
|
||||
final protected boolean isWindows() {
|
||||
CompilerSpecID compilerSpecID = program.getCompilerSpec().getCompilerSpecID();
|
||||
return compilerSpecID.getIdAsString().equals("windows") &&
|
||||
String compilerIdString = compilerSpecID.getIdAsString();
|
||||
String compilerString = program.getCompiler();
|
||||
return ("windows".equals(compilerIdString) || "clangwindows".equals(compilerIdString)) &&
|
||||
program.getExecutableFormat().equals(PeLoader.PE_NAME) &&
|
||||
program.getCompiler().equals(CompilerEnum.VisualStudio.toString());
|
||||
(compilerString.equals(CompilerEnum.VisualStudio.toString()) ||
|
||||
compilerString.equals(CompilerEnum.Clang.toString()));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -24,12 +24,9 @@ import ghidra.app.services.*;
|
|||
import ghidra.app.util.datatype.microsoft.DataApplyOptions;
|
||||
import ghidra.app.util.datatype.microsoft.DataValidationOptions;
|
||||
import ghidra.app.util.importer.MessageLog;
|
||||
import ghidra.app.util.opinion.PeLoader;
|
||||
import ghidra.app.util.opinion.PeLoader.CompilerOpinion.CompilerEnum;
|
||||
import ghidra.framework.cmd.Command;
|
||||
import ghidra.program.model.address.*;
|
||||
import ghidra.program.model.data.InvalidDataTypeException;
|
||||
import ghidra.program.model.lang.CompilerSpecID;
|
||||
import ghidra.program.model.listing.Program;
|
||||
import ghidra.program.model.mem.MemoryBlock;
|
||||
import ghidra.program.util.ProgramMemoryUtil;
|
||||
|
@ -64,10 +61,7 @@ public class PEExceptionAnalyzer extends AbstractAnalyzer {
|
|||
|
||||
@Override
|
||||
public boolean canAnalyze(Program program) {
|
||||
CompilerSpecID compilerSpecID = program.getCompilerSpec().getCompilerSpecID();
|
||||
return compilerSpecID.getIdAsString().equals("windows") &&
|
||||
program.getExecutableFormat().equals(PeLoader.PE_NAME) &&
|
||||
program.getCompiler().equals(CompilerEnum.VisualStudio.toString());
|
||||
return PEUtil.isVisualStudioOrClangPe(program);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -87,8 +81,8 @@ public class PEExceptionAnalyzer extends AbstractAnalyzer {
|
|||
"[\\x20,\\x21,\\x22]\\x05\\x93[\\x19,\\x39,\\x59,\\x79,\\x99,\\xb9,\\xd9,\\xf9]";
|
||||
String bePattern =
|
||||
"[\\x19,\\x39,\\x59,\\x79,\\x99,\\xb9,\\xd9,\\xf9]\\x93\\x05[\\x20,\\x21,\\x22]";
|
||||
RegExSearchData regExSearchData = RegExSearchData
|
||||
.createRegExSearchData(program.getLanguage().isBigEndian() ? bePattern : lePattern);
|
||||
RegExSearchData regExSearchData = RegExSearchData.createRegExSearchData(
|
||||
program.getLanguage().isBigEndian() ? bePattern : lePattern);
|
||||
int alignment = 4;
|
||||
SearchInfo searchInfo = new SearchInfo(regExSearchData, MATCH_LIMIT, false, true, alignment,
|
||||
false, new CodeUnitSearchInfo(false, true, true), null);
|
||||
|
|
|
@ -26,6 +26,7 @@ import ghidra.app.util.datatype.microsoft.GuidInfo;
|
|||
import ghidra.app.util.datatype.microsoft.GuidUtil;
|
||||
import ghidra.app.util.opinion.BinaryLoader;
|
||||
import ghidra.app.util.opinion.PeLoader;
|
||||
import ghidra.app.util.opinion.PeLoader.CompilerOpinion.CompilerEnum;
|
||||
import ghidra.program.model.address.*;
|
||||
import ghidra.program.model.data.DataType;
|
||||
import ghidra.program.model.data.TypeDef;
|
||||
|
@ -42,12 +43,11 @@ public class PEUtil {
|
|||
return true;
|
||||
}
|
||||
if (format.equals(BinaryLoader.BINARY_NAME)) {
|
||||
MemoryByteProvider mbp =
|
||||
new MemoryByteProvider(program.getMemory(),
|
||||
program.getAddressFactory().getDefaultAddressSpace());
|
||||
MemoryByteProvider mbp = new MemoryByteProvider(program.getMemory(),
|
||||
program.getAddressFactory().getDefaultAddressSpace());
|
||||
try {
|
||||
FactoryBundledWithBinaryReader reader =
|
||||
new FactoryBundledWithBinaryReader(RethrowContinuesFactory.INSTANCE, mbp, true/*LittleEndian*/);
|
||||
FactoryBundledWithBinaryReader reader = new FactoryBundledWithBinaryReader(
|
||||
RethrowContinuesFactory.INSTANCE, mbp, true/*LittleEndian*/);
|
||||
DOSHeader dosHeader = DOSHeader.createDOSHeader(reader);
|
||||
if (dosHeader.e_magic() == DOSHeader.IMAGE_DOS_SIGNATURE) {
|
||||
int peHeaderStartIndex = dosHeader.e_lfanew();
|
||||
|
@ -63,6 +63,12 @@ public class PEUtil {
|
|||
return false;
|
||||
}
|
||||
|
||||
static public boolean isVisualStudioOrClangPe(Program program) {
|
||||
return program.getExecutableFormat().equals(PeLoader.PE_NAME) &&
|
||||
(program.getCompiler().equals(CompilerEnum.VisualStudio.toString()) ||
|
||||
program.getCompiler().equals(CompilerEnum.Clang.toString()));
|
||||
}
|
||||
|
||||
static DataType getActualType(DataType dataType) {
|
||||
if (dataType instanceof TypeDef) {
|
||||
return getActualType(((TypeDef) dataType).getDataType());
|
||||
|
@ -76,8 +82,7 @@ public class PEUtil {
|
|||
AddressSpace defaultSpace = addressFactory.getDefaultAddressSpace();
|
||||
try {
|
||||
int addrAsInt = memory.getInt(addr);
|
||||
Address pointedToAddr =
|
||||
addressFactory.getAddress(defaultSpace.getSpaceID(), addrAsInt);
|
||||
Address pointedToAddr = addressFactory.getAddress(defaultSpace.getSpaceID(), addrAsInt);
|
||||
return memory.contains(pointedToAddr);
|
||||
}
|
||||
catch (MemoryAccessException e) {
|
||||
|
@ -91,8 +96,7 @@ public class PEUtil {
|
|||
AddressSpace defaultSpace = addressFactory.getDefaultAddressSpace();
|
||||
try {
|
||||
int addrAsInt = memory.getInt(addr);
|
||||
Address pointedToAddr =
|
||||
addressFactory.getAddress(defaultSpace.getSpaceID(), addrAsInt);
|
||||
Address pointedToAddr = addressFactory.getAddress(defaultSpace.getSpaceID(), addrAsInt);
|
||||
if (memory.contains(pointedToAddr)) {
|
||||
GuidInfo guidInfo = GuidUtil.getKnownGuid(program, pointedToAddr);
|
||||
if (guidInfo != null) {
|
||||
|
|
|
@ -69,7 +69,7 @@ public class RttiAnalyzer extends AbstractAnalyzer {
|
|||
|
||||
@Override
|
||||
public boolean canAnalyze(Program program) {
|
||||
return PEUtil.canAnalyze(program);
|
||||
return PEUtil.isVisualStudioOrClangPe(program);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -134,7 +134,7 @@ public class RttiAnalyzer extends AbstractAnalyzer {
|
|||
monitor.setMaximum(possibleRtti0Addresses.size());
|
||||
monitor.setMessage("Creating RTTI Data...");
|
||||
|
||||
ArrayList<Address> rtti0Locations = new ArrayList<Address>();
|
||||
ArrayList<Address> rtti0Locations = new ArrayList<>();
|
||||
int count = 0;
|
||||
for (Address rtti0Address : possibleRtti0Addresses) {
|
||||
monitor.checkCanceled();
|
||||
|
@ -277,7 +277,7 @@ public class RttiAnalyzer extends AbstractAnalyzer {
|
|||
}
|
||||
|
||||
// Each time a match for this byte pattern validate as an RTTI4 and add to list
|
||||
GenericMatchAction<Address> action = new GenericMatchAction<Address>(rtti0Address) {
|
||||
GenericMatchAction<Address> action = new GenericMatchAction<>(rtti0Address) {
|
||||
@Override
|
||||
public void apply(Program prog, Address addr, Match match) {
|
||||
Address possibleRtti4Address;
|
||||
|
@ -311,7 +311,7 @@ public class RttiAnalyzer extends AbstractAnalyzer {
|
|||
|
||||
// create a Pattern of the bytes and the MatchAction to perform upon a match
|
||||
GenericByteSequencePattern<Address> genericByteMatchPattern =
|
||||
new GenericByteSequencePattern<Address>(bytes, action);
|
||||
new GenericByteSequencePattern<>(bytes, action);
|
||||
|
||||
searcher.addPattern(genericByteMatchPattern);
|
||||
}
|
||||
|
|
|
@ -161,6 +161,24 @@ public class AbstractCreateDataTypeModelTest extends AbstractGenericTest {
|
|||
return builder;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a 64 bit program builder that can be used for testing.
|
||||
* @return the program builder for a 64 bit VisualStudio x86 PE program.
|
||||
* @throws Exception if it fails to create the ProgramBuilder
|
||||
*/
|
||||
protected ProgramBuilder build64BitX86Clang() throws Exception {
|
||||
ProgramBuilder builder =
|
||||
new ProgramBuilder("test64BitX86", ProgramBuilder._X64, "clangwindows", null);
|
||||
setExecFormatAndCompiler(builder, PeLoader.PE_NAME, "clang:unknown");
|
||||
setImageBase(builder, 0x101000000L);
|
||||
builder.createMemory(".text", "0x101001000", 0x2000);
|
||||
builder.createMemory(".rdata", "0x101003000", 0x2000);
|
||||
builder.createMemory(".data", "0x101005000", 0x2000);
|
||||
setupDTMService(builder.getProgram());
|
||||
builder.setBytes("0x101005010", RttiAnalyzer.TYPE_INFO_STRING.getBytes());
|
||||
return builder;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a 64 bit program builder that can be used for testing.
|
||||
* @return the program builder for a 64 bit non-VisualStudio x86 PE program.
|
||||
|
@ -168,7 +186,7 @@ public class AbstractCreateDataTypeModelTest extends AbstractGenericTest {
|
|||
*/
|
||||
protected ProgramBuilder build64BitX86NonVS() throws Exception {
|
||||
ProgramBuilder builder =
|
||||
new ProgramBuilder("test64BitX86", ProgramBuilder._X64, "windows", null);
|
||||
new ProgramBuilder("test64BitX86Unknown", ProgramBuilder._X64, "windows", null);
|
||||
setExecFormatAndCompiler(builder, PeLoader.PE_NAME, null);
|
||||
setImageBase(builder, 0x101000000L);
|
||||
builder.createMemory(".text", "0x101001000", 0x2000);
|
||||
|
|
|
@ -511,23 +511,6 @@ public class RttiModelTest extends AbstractRttiTest {
|
|||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInvalidRtti4_64NonVS() throws Exception {
|
||||
ProgramBuilder builder = build64BitX86NonVS();
|
||||
ProgramDB program = builder.getProgram();
|
||||
setupRtti4_32(builder, 0x101001340L, 0, 0, 0, "0x00005364", "0x0000137c");
|
||||
Address address = builder.addr(0x101001340L);
|
||||
Rtti4Model model = new Rtti4Model(program, address, defaultValidationOptions);
|
||||
try {
|
||||
model.validate();
|
||||
}
|
||||
catch (InvalidDataTypeException e) {
|
||||
assertEquals(
|
||||
"RTTICompleteObjectLocator data type model is only valid for Visual Studio windows PE.",
|
||||
e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testValidRtti4Model_64NoFollowFlow() throws Exception {
|
||||
|
||||
|
|
|
@ -0,0 +1,53 @@
|
|||
/* ###
|
||||
* IP: GHIDRA
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package ghidra.app.plugin.prototype.MicrosoftCodeAnalyzerPlugin;
|
||||
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import ghidra.app.cmd.data.AbstractCreateDataTypeModelTest;
|
||||
import ghidra.program.database.ProgramBuilder;
|
||||
import ghidra.program.database.ProgramDB;
|
||||
|
||||
public class PEUtilTest extends AbstractCreateDataTypeModelTest {
|
||||
|
||||
@Test
|
||||
public void testIsVisualStudioOrClangPeGivenVisualStudioPe() throws Exception {
|
||||
ProgramBuilder builder = build64BitX86();
|
||||
ProgramDB program = builder.getProgram();
|
||||
boolean result = PEUtil.isVisualStudioOrClangPe(program);
|
||||
assertTrue(result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsVisualStudioOrClangPeGivenClangPe() throws Exception {
|
||||
ProgramBuilder builder = build64BitX86Clang();
|
||||
ProgramDB program = builder.getProgram();
|
||||
boolean result = PEUtil.isVisualStudioOrClangPe(program);
|
||||
assertTrue(result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsVisualStudioOrClangPeGivenNotVisualStudioOrClangPe() throws Exception {
|
||||
ProgramBuilder builder = build64BitX86NonVS();
|
||||
ProgramDB program = builder.getProgram();
|
||||
boolean result = PEUtil.isVisualStudioOrClangPe(program);
|
||||
assertFalse(result);
|
||||
}
|
||||
|
||||
}
|
|
@ -12,6 +12,7 @@
|
|||
id="x86:LE:32:default">
|
||||
<description>Intel/AMD 32-bit x86</description>
|
||||
<compiler name="Visual Studio" spec="x86win.cspec" id="windows"/>
|
||||
<compiler name="clang" spec="x86win.cspec" id="clangwindows"/>
|
||||
<compiler name="gcc" spec="x86gcc.cspec" id="gcc"/>
|
||||
<compiler name="Borland C++" spec="x86borland.cspec" id="borlandcpp"/>
|
||||
<compiler name="Delphi" spec="x86delphi.cspec" id="borlanddelphi"/>
|
||||
|
@ -83,6 +84,7 @@
|
|||
id="x86:LE:64:default">
|
||||
<description>Intel/AMD 64-bit x86</description>
|
||||
<compiler name="Visual Studio" spec="x86-64-win.cspec" id="windows"/>
|
||||
<compiler name="clang" spec="x86-64-win.cspec" id="clangwindows"/>
|
||||
<compiler name="gcc" spec="x86-64-gcc.cspec" id="gcc"/>
|
||||
<external_name tool="gnu" name="i386:x86-64:intel"/>
|
||||
<external_name tool="IDA-PRO" name="metapc"/>
|
||||
|
|
|
@ -6,6 +6,12 @@
|
|||
<constraint primary="334" processor="x86" endian="little" size="32" />
|
||||
<constraint primary="34404" processor="x86" endian="little" size="64" />
|
||||
</constraint>
|
||||
<constraint compilerSpecID="clangwindows">
|
||||
<constraint primary="332" secondary="clang" processor="x86" endian="little" size="32" />
|
||||
<constraint primary="333" secondary="clang" processor="x86" endian="little" size="32" />
|
||||
<constraint primary="334" secondary="clang" processor="x86" endian="little" size="32" />
|
||||
<constraint primary="34404" secondary="clang" processor="x86" endian="little" size="64" />
|
||||
</constraint>
|
||||
<constraint compilerSpecID="borlandcpp">
|
||||
<constraint primary="332" secondary="borlandcpp" processor="x86" endian="little" size="32" />
|
||||
<constraint primary="333" secondary="borlandcpp" processor="x86" endian="little" size="32" />
|
||||
|
|
Loading…
Reference in a new issue