summaryrefslogtreecommitdiff
path: root/arch/mips
diff options
context:
space:
mode:
authorJosh Ferrell <josh@vector35.com>2024-04-25 13:08:34 -0400
committerJosh Ferrell <josh@vector35.com>2024-04-25 13:08:34 -0400
commit13c41bc582fa037e03cbc5343a1401ea4c6cf8e7 (patch)
treed93b4f8294dd8bf8543529d344a106f5536575ef /arch/mips
parent4db391cdfdb53c3ac18fa5f0c15f2976fde12791 (diff)
Recognize uClibc MIPS ELF PLT entries
Diffstat (limited to 'arch/mips')
-rw-r--r--arch/mips/arch_mips.cpp118
1 files changed, 118 insertions, 0 deletions
diff --git a/arch/mips/arch_mips.cpp b/arch/mips/arch_mips.cpp
index 77de378f..6a3d80e4 100644
--- a/arch/mips/arch_mips.cpp
+++ b/arch/mips/arch_mips.cpp
@@ -1829,6 +1829,121 @@ private:
return false;
}
+
+ bool RecognizeELFPLTEntries2(BinaryView* data, Function* func, LowLevelILFunction* il)
+ {
+ // Look for the following code pattern:
+ // $t7 = addr_past_got_end
+ // $t9 = [$t7 - backward_offset_into_got].d
+ // $t8 = $t7 + (-backward_offset_into_got)
+ // OPTIONAL: $t7 = addr_past_got_end
+ // tailcall($t9)
+ if (il->GetInstructionCount() < 4)
+ return false;
+ if (il->GetInstructionCount() > 5)
+ return false;
+
+ LowLevelILInstruction lui = il->GetInstruction(0);
+ if (lui.operation != LLIL_SET_REG)
+ return false;
+ LowLevelILInstruction luiOperand = lui.GetSourceExpr<LLIL_SET_REG>();
+ if (!LowLevelILFunction::IsConstantType(luiOperand.operation))
+ return false;
+ if (luiOperand.size != func->GetArchitecture()->GetAddressSize())
+ return false;
+ uint64_t addrPastGot = luiOperand.GetConstant();
+ uint32_t pltReg = lui.GetDestRegister<LLIL_SET_REG>();
+
+ LowLevelILInstruction ld = il->GetInstruction(1);
+ if (ld.operation != LLIL_SET_REG)
+ return false;
+ uint32_t targetReg = ld.GetDestRegister<LLIL_SET_REG>();
+ LowLevelILInstruction ldOperand = ld.GetSourceExpr<LLIL_SET_REG>();
+ if (ldOperand.operation != LLIL_LOAD)
+ return false;
+ if (ldOperand.size != func->GetArchitecture()->GetAddressSize())
+ return false;
+ LowLevelILInstruction ldAddrOperand = ldOperand.GetSourceExpr<LLIL_LOAD>();
+ uint64_t entry = addrPastGot;
+ int64_t ldAddrRightOperandValue = 0;
+
+ if ((ldAddrOperand.operation == LLIL_ADD) || (ldAddrOperand.operation == LLIL_SUB))
+ {
+ LowLevelILInstruction ldAddrLeftOperand = ldAddrOperand.GetRawOperandAsExpr(0);
+ LowLevelILInstruction ldAddrRightOperand = ldAddrOperand.GetRawOperandAsExpr(1);
+ if (ldAddrLeftOperand.operation != LLIL_REG)
+ return false;
+ if (ldAddrLeftOperand.GetSourceRegister<LLIL_REG>() != pltReg)
+ return false;
+ if (!LowLevelILFunction::IsConstantType(ldAddrRightOperand.operation))
+ return false;
+ ldAddrRightOperandValue = ldAddrRightOperand.GetConstant();
+ if (ldAddrOperand.operation == LLIL_SUB)
+ ldAddrRightOperandValue = -ldAddrRightOperandValue;
+ entry = addrPastGot + ldAddrRightOperandValue;
+ }
+ else if (ldAddrOperand.operation != LLIL_REG) //If theres no constant
+ return false;
+
+ Ref<Symbol> sym = data->GetSymbolByAddress(entry);
+ if (!sym)
+ return false;
+ if (sym->GetType() != ImportAddressSymbol)
+ return false;
+
+ LowLevelILInstruction add = il->GetInstruction(2);
+ if (add.operation != LLIL_SET_REG)
+ return false;
+ LowLevelILInstruction addOperand = add.GetSourceExpr<LLIL_SET_REG>();
+
+ if (addOperand.operation == LLIL_ADD)
+ {
+ LowLevelILInstruction addLeftOperand = addOperand.GetLeftExpr<LLIL_ADD>();
+ LowLevelILInstruction addRightOperand = addOperand.GetRightExpr<LLIL_ADD>();
+ if (addLeftOperand.operation != LLIL_REG)
+ return false;
+ if (addLeftOperand.GetSourceRegister<LLIL_REG>() != pltReg)
+ return false;
+ if (!LowLevelILFunction::IsConstantType(addRightOperand.operation))
+ return false;
+ if (addRightOperand.GetConstant() != ldAddrRightOperandValue)
+ return false;
+ }
+ else if ((addOperand.operation != LLIL_REG) || (addOperand.GetSourceRegister<LLIL_REG>() != pltReg)) //Simple assignment
+ return false;
+
+ LowLevelILInstruction jump = il->GetInstruction(3);
+ if (jump.operation == LLIL_SET_REG)
+ {
+ if (il->GetInstructionCount() != 5)
+ return false;
+ if (jump.GetDestRegister<LLIL_SET_REG>() != pltReg)
+ return false;
+ LowLevelILInstruction luiOperand = jump.GetSourceExpr<LLIL_SET_REG>();
+ if (!LowLevelILFunction::IsConstantType(luiOperand.operation))
+ return false;
+ if (luiOperand.size != func->GetArchitecture()->GetAddressSize())
+ return false;
+ if (((uint64_t) luiOperand.GetConstant()) != addrPastGot)
+ return false;
+ jump = il->GetInstruction(4);
+ }
+
+ if ((jump.operation != LLIL_JUMP) && (jump.operation != LLIL_TAILCALL))
+ return false;
+ LowLevelILInstruction jumpOperand = (jump.operation == LLIL_JUMP) ? jump.GetDestExpr<LLIL_JUMP>() : jump.GetDestExpr<LLIL_TAILCALL>();
+ if (jumpOperand.operation != LLIL_REG)
+ return false;
+ if (jumpOperand.GetSourceRegister<LLIL_REG>() != targetReg)
+ return false;
+
+ Ref<Symbol> funcSym = Symbol::ImportedFunctionFromImportAddressSymbol(sym, func->GetStart());
+ data->DefineAutoSymbol(funcSym);
+ func->ApplyImportedTypes(funcSym);
+ return true;
+ }
+
+
public:
virtual bool RecognizeLowLevelIL(BinaryView* data, Function* func, LowLevelILFunction* il) override
{
@@ -1838,6 +1953,9 @@ public:
if (RecognizeELFPLTEntries1(data, func, il))
return true;
+ if (RecognizeELFPLTEntries2(data, func, il))
+ return true;
+
return false;
}
};