mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-05 19:42:36 +02:00
GP-3687 fixed potential replacement of goto reference with data
reference in x86 PIC CALL to fallthru address
This commit is contained in:
parent
c32b6d6bdb
commit
c0c04ff789
2 changed files with 61 additions and 4 deletions
|
@ -15,13 +15,11 @@
|
||||||
*/
|
*/
|
||||||
package ghidra.program.util;
|
package ghidra.program.util;
|
||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.*;
|
||||||
import static org.junit.Assert.assertNotNull;
|
|
||||||
import static org.junit.Assert.assertTrue;
|
|
||||||
|
|
||||||
import java.math.BigInteger;
|
import java.math.BigInteger;
|
||||||
|
|
||||||
import org.junit.*;
|
import org.junit.Test;
|
||||||
|
|
||||||
import generic.test.AbstractGenericTest;
|
import generic.test.AbstractGenericTest;
|
||||||
import ghidra.app.plugin.core.analysis.ConstantPropagationAnalyzer;
|
import ghidra.app.plugin.core.analysis.ConstantPropagationAnalyzer;
|
||||||
|
@ -34,6 +32,7 @@ import ghidra.program.model.lang.RegisterValue;
|
||||||
import ghidra.program.model.listing.*;
|
import ghidra.program.model.listing.*;
|
||||||
import ghidra.program.model.pcode.Varnode;
|
import ghidra.program.model.pcode.Varnode;
|
||||||
import ghidra.program.model.symbol.Reference;
|
import ghidra.program.model.symbol.Reference;
|
||||||
|
import ghidra.program.model.symbol.ReferenceIterator;
|
||||||
import ghidra.program.util.SymbolicPropogator.Value;
|
import ghidra.program.util.SymbolicPropogator.Value;
|
||||||
import ghidra.util.exception.NotFoundException;
|
import ghidra.util.exception.NotFoundException;
|
||||||
import ghidra.util.task.TaskMonitor;
|
import ghidra.util.task.TaskMonitor;
|
||||||
|
@ -308,6 +307,53 @@ public class ConstantPropogationReferenceTest extends AbstractGenericTest {
|
||||||
assertOperandReferenceTo(1, instr, addr("0x00040100"));
|
assertOperandReferenceTo(1, instr, addr("0x00040100"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testPIC_Call_X86_64() throws Exception {
|
||||||
|
|
||||||
|
builder = new ProgramBuilder("PICCode", ProgramBuilder._X64, "gcc", this);
|
||||||
|
|
||||||
|
// entry
|
||||||
|
// 48 83 ec 28 SUB RSP,0x28
|
||||||
|
// e8 00 00 00 00 CALL LAB_140020119
|
||||||
|
// LAB_140020119
|
||||||
|
// 8f c3 POP RBX
|
||||||
|
// 48 8d 43 e0 LEA RAX,[RBX + -0x20]
|
||||||
|
// ff d0 CALL RAX
|
||||||
|
// 48 83 c4 28 ADD RSP,0x28
|
||||||
|
// c3 RET
|
||||||
|
|
||||||
|
builder.setBytes("0x140020110",
|
||||||
|
"48 83 ec 28 e8 00 00 00 00 8f c3 48 8d 43 e0 ff d0 48 83 c4 28 c3");
|
||||||
|
|
||||||
|
builder.setBytes("0x1400200f9",
|
||||||
|
"15 02 2f 00 00 89 05 e8 b9 00 00 48 83 c4 38");
|
||||||
|
|
||||||
|
builder.disassemble("0x140020110", 21);
|
||||||
|
|
||||||
|
analyzer = new ConstantPropagationAnalyzer();
|
||||||
|
|
||||||
|
program = builder.getProgram();
|
||||||
|
program.startTransaction("Test");
|
||||||
|
|
||||||
|
Address codeStart = addr("140020110");
|
||||||
|
Listing listing = program.getListing();
|
||||||
|
assertNotNull("Bad instruction disassembly", listing.getInstructionAt(codeStart));
|
||||||
|
|
||||||
|
AddressSet addressSet = new AddressSet(codeStart, codeStart.add(21));
|
||||||
|
analyze(addressSet);
|
||||||
|
|
||||||
|
Instruction instr = listing.getInstructionAt(addr("0x140020114"));
|
||||||
|
assertOperandReferenceTo(0, instr, addr("0x140020119"));
|
||||||
|
instr = listing.getInstructionAt(addr("0x140020119"));
|
||||||
|
ReferenceIterator referenceIteratorTo = instr.getReferenceIteratorTo();
|
||||||
|
Reference ref = referenceIteratorTo.next();
|
||||||
|
assertTrue(ref.getReferenceType().isJump());
|
||||||
|
instr = listing.getInstructionAt(addr("0x14002011f"));
|
||||||
|
Reference[] referencesFrom = instr.getReferencesFrom();
|
||||||
|
assertTrue(referencesFrom[0].getReferenceType().isFlow());
|
||||||
|
assertEquals("1400200f9", referencesFrom[0].getToAddress().toString());
|
||||||
|
}
|
||||||
|
|
||||||
private void assertNoOperandReference(int opIndex, Instruction instr) {
|
private void assertNoOperandReference(int opIndex, Instruction instr) {
|
||||||
Reference[] refs = instr.getOperandReferences(opIndex);
|
Reference[] refs = instr.getOperandReferences(opIndex);
|
||||||
assertEquals("No reference on operand " + opIndex, 0, refs.length);
|
assertEquals("No reference on operand " + opIndex, 0, refs.length);
|
||||||
|
|
|
@ -303,6 +303,17 @@ public class ReferenceDBManager implements ReferenceManager, ManagerDB, ErrorHan
|
||||||
* @return combined reference type, or the newType if unable to combine
|
* @return combined reference type, or the newType if unable to combine
|
||||||
*/
|
*/
|
||||||
private RefType combineReferenceType(RefType newType, RefType oldType) {
|
private RefType combineReferenceType(RefType newType, RefType oldType) {
|
||||||
|
// check if types are the same, if same no use doing work replacing reference
|
||||||
|
if (newType == oldType) {
|
||||||
|
return oldType;
|
||||||
|
}
|
||||||
|
// any flow reference should be used over the existing ref to the same location
|
||||||
|
if (newType.isFlow()) {
|
||||||
|
return newType; // allow any new flow ref to replace old type
|
||||||
|
}
|
||||||
|
if (oldType.isFlow()) {
|
||||||
|
return oldType; // always keep flow over new data ref
|
||||||
|
}
|
||||||
if (newType == RefType.DATA) {
|
if (newType == RefType.DATA) {
|
||||||
if (oldType.isData()) {
|
if (oldType.isData()) {
|
||||||
return oldType;
|
return oldType;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue