Skip to content

Commit 385c888

Browse files
authored
Merge branch 'dev' into simpl-arch
2 parents 3296f79 + 87b1470 commit 385c888

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

57 files changed

+1926
-445
lines changed

arch/mips/arch_mips.cpp

Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1829,6 +1829,121 @@ class MipsImportedFunctionRecognizer: public FunctionRecognizer
18291829
return false;
18301830
}
18311831

1832+
1833+
bool RecognizeELFPLTEntries2(BinaryView* data, Function* func, LowLevelILFunction* il)
1834+
{
1835+
// Look for the following code pattern:
1836+
// $t7 = addr_past_got_end
1837+
// $t9 = [$t7 - backward_offset_into_got].d
1838+
// $t8 = $t7 + (-backward_offset_into_got)
1839+
// OPTIONAL: $t7 = addr_past_got_end
1840+
// tailcall($t9)
1841+
if (il->GetInstructionCount() < 4)
1842+
return false;
1843+
if (il->GetInstructionCount() > 5)
1844+
return false;
1845+
1846+
LowLevelILInstruction lui = il->GetInstruction(0);
1847+
if (lui.operation != LLIL_SET_REG)
1848+
return false;
1849+
LowLevelILInstruction luiOperand = lui.GetSourceExpr<LLIL_SET_REG>();
1850+
if (!LowLevelILFunction::IsConstantType(luiOperand.operation))
1851+
return false;
1852+
if (luiOperand.size != func->GetArchitecture()->GetAddressSize())
1853+
return false;
1854+
uint64_t addrPastGot = luiOperand.GetConstant();
1855+
uint32_t pltReg = lui.GetDestRegister<LLIL_SET_REG>();
1856+
1857+
LowLevelILInstruction ld = il->GetInstruction(1);
1858+
if (ld.operation != LLIL_SET_REG)
1859+
return false;
1860+
uint32_t targetReg = ld.GetDestRegister<LLIL_SET_REG>();
1861+
LowLevelILInstruction ldOperand = ld.GetSourceExpr<LLIL_SET_REG>();
1862+
if (ldOperand.operation != LLIL_LOAD)
1863+
return false;
1864+
if (ldOperand.size != func->GetArchitecture()->GetAddressSize())
1865+
return false;
1866+
LowLevelILInstruction ldAddrOperand = ldOperand.GetSourceExpr<LLIL_LOAD>();
1867+
uint64_t entry = addrPastGot;
1868+
int64_t ldAddrRightOperandValue = 0;
1869+
1870+
if ((ldAddrOperand.operation == LLIL_ADD) || (ldAddrOperand.operation == LLIL_SUB))
1871+
{
1872+
LowLevelILInstruction ldAddrLeftOperand = ldAddrOperand.GetRawOperandAsExpr(0);
1873+
LowLevelILInstruction ldAddrRightOperand = ldAddrOperand.GetRawOperandAsExpr(1);
1874+
if (ldAddrLeftOperand.operation != LLIL_REG)
1875+
return false;
1876+
if (ldAddrLeftOperand.GetSourceRegister<LLIL_REG>() != pltReg)
1877+
return false;
1878+
if (!LowLevelILFunction::IsConstantType(ldAddrRightOperand.operation))
1879+
return false;
1880+
ldAddrRightOperandValue = ldAddrRightOperand.GetConstant();
1881+
if (ldAddrOperand.operation == LLIL_SUB)
1882+
ldAddrRightOperandValue = -ldAddrRightOperandValue;
1883+
entry = addrPastGot + ldAddrRightOperandValue;
1884+
}
1885+
else if (ldAddrOperand.operation != LLIL_REG) //If theres no constant
1886+
return false;
1887+
1888+
Ref<Symbol> sym = data->GetSymbolByAddress(entry);
1889+
if (!sym)
1890+
return false;
1891+
if (sym->GetType() != ImportAddressSymbol)
1892+
return false;
1893+
1894+
LowLevelILInstruction add = il->GetInstruction(2);
1895+
if (add.operation != LLIL_SET_REG)
1896+
return false;
1897+
LowLevelILInstruction addOperand = add.GetSourceExpr<LLIL_SET_REG>();
1898+
1899+
if (addOperand.operation == LLIL_ADD)
1900+
{
1901+
LowLevelILInstruction addLeftOperand = addOperand.GetLeftExpr<LLIL_ADD>();
1902+
LowLevelILInstruction addRightOperand = addOperand.GetRightExpr<LLIL_ADD>();
1903+
if (addLeftOperand.operation != LLIL_REG)
1904+
return false;
1905+
if (addLeftOperand.GetSourceRegister<LLIL_REG>() != pltReg)
1906+
return false;
1907+
if (!LowLevelILFunction::IsConstantType(addRightOperand.operation))
1908+
return false;
1909+
if (addRightOperand.GetConstant() != ldAddrRightOperandValue)
1910+
return false;
1911+
}
1912+
else if ((addOperand.operation != LLIL_REG) || (addOperand.GetSourceRegister<LLIL_REG>() != pltReg)) //Simple assignment
1913+
return false;
1914+
1915+
LowLevelILInstruction jump = il->GetInstruction(3);
1916+
if (jump.operation == LLIL_SET_REG)
1917+
{
1918+
if (il->GetInstructionCount() != 5)
1919+
return false;
1920+
if (jump.GetDestRegister<LLIL_SET_REG>() != pltReg)
1921+
return false;
1922+
LowLevelILInstruction luiOperand = jump.GetSourceExpr<LLIL_SET_REG>();
1923+
if (!LowLevelILFunction::IsConstantType(luiOperand.operation))
1924+
return false;
1925+
if (luiOperand.size != func->GetArchitecture()->GetAddressSize())
1926+
return false;
1927+
if (((uint64_t) luiOperand.GetConstant()) != addrPastGot)
1928+
return false;
1929+
jump = il->GetInstruction(4);
1930+
}
1931+
1932+
if ((jump.operation != LLIL_JUMP) && (jump.operation != LLIL_TAILCALL))
1933+
return false;
1934+
LowLevelILInstruction jumpOperand = (jump.operation == LLIL_JUMP) ? jump.GetDestExpr<LLIL_JUMP>() : jump.GetDestExpr<LLIL_TAILCALL>();
1935+
if (jumpOperand.operation != LLIL_REG)
1936+
return false;
1937+
if (jumpOperand.GetSourceRegister<LLIL_REG>() != targetReg)
1938+
return false;
1939+
1940+
Ref<Symbol> funcSym = Symbol::ImportedFunctionFromImportAddressSymbol(sym, func->GetStart());
1941+
data->DefineAutoSymbol(funcSym);
1942+
func->ApplyImportedTypes(funcSym);
1943+
return true;
1944+
}
1945+
1946+
18321947
public:
18331948
virtual bool RecognizeLowLevelIL(BinaryView* data, Function* func, LowLevelILFunction* il) override
18341949
{
@@ -1838,6 +1953,9 @@ class MipsImportedFunctionRecognizer: public FunctionRecognizer
18381953
if (RecognizeELFPLTEntries1(data, func, il))
18391954
return true;
18401955

1956+
if (RecognizeELFPLTEntries2(data, func, il))
1957+
return true;
1958+
18411959
return false;
18421960
}
18431961
};

arch/riscv/src/lib.rs

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -508,23 +508,23 @@ impl<D: RiscVDisassembler> architecture::Intrinsic for RiscVIntrinsic<D> {
508508
}
509509
}
510510

511-
fn inputs(&self) -> Vec<NameAndType<String>> {
511+
fn inputs(&self) -> Vec<Ref<NameAndType>> {
512512
match self.id {
513513
Intrinsic::Uret | Intrinsic::Sret | Intrinsic::Mret | Intrinsic::Wfi => {
514514
vec![]
515515
}
516516
Intrinsic::Csrrd => {
517517
vec![NameAndType::new(
518-
"csr".into(),
518+
"csr",
519519
&Type::int(4, false),
520520
max_confidence(),
521521
)]
522522
}
523523
Intrinsic::Csrrw | Intrinsic::Csrwr | Intrinsic::Csrrs | Intrinsic::Csrrc => {
524524
vec![
525-
NameAndType::new("csr".into(), &Type::int(4, false), max_confidence()),
525+
NameAndType::new("csr", &Type::int(4, false), max_confidence()),
526526
NameAndType::new(
527-
"value".into(),
527+
"value",
528528
&Type::int(<D::RegFile as RegFile>::Int::width(), false),
529529
min_confidence(),
530530
),
@@ -540,8 +540,8 @@ impl<D: RiscVDisassembler> architecture::Intrinsic for RiscVIntrinsic<D> {
540540
| Intrinsic::Fmin(size)
541541
| Intrinsic::Fmax(size) => {
542542
vec![
543-
NameAndType::new("".into(), &Type::float(size as usize), max_confidence()),
544-
NameAndType::new("".into(), &Type::float(size as usize), max_confidence()),
543+
NameAndType::new("", &Type::float(size as usize), max_confidence()),
544+
NameAndType::new("", &Type::float(size as usize), max_confidence()),
545545
]
546546
}
547547
Intrinsic::Fsqrt(size, _)
@@ -550,28 +550,28 @@ impl<D: RiscVDisassembler> architecture::Intrinsic for RiscVIntrinsic<D> {
550550
| Intrinsic::FcvtFToI(size, _, _)
551551
| Intrinsic::FcvtFToU(size, _, _) => {
552552
vec![NameAndType::new(
553-
"".into(),
553+
"",
554554
&Type::float(size as usize),
555555
max_confidence(),
556556
)]
557557
}
558558
Intrinsic::FcvtIToF(size, _, _) => {
559559
vec![NameAndType::new(
560-
"".into(),
560+
"",
561561
&Type::int(size as usize, true),
562562
max_confidence(),
563563
)]
564564
}
565565
Intrinsic::FcvtUToF(size, _, _) => {
566566
vec![NameAndType::new(
567-
"".into(),
567+
"",
568568
&Type::int(size as usize, false),
569569
max_confidence(),
570570
)]
571571
}
572572
Intrinsic::Fence => {
573573
vec![NameAndType::new(
574-
"".into(),
574+
"",
575575
&Type::int(4, false),
576576
min_confidence(),
577577
)]
@@ -2428,10 +2428,9 @@ impl<D: 'static + RiscVDisassembler + Send + Sync> RelocationHandler
24282428
.iter()
24292429
.find(|r| r.info().native_type == Self::R_RISCV_PCREL_HI20)
24302430
{
2431-
Some(target) => target,
2431+
Some(target) => target.target().wrapping_add(target.info().addend as u64),
24322432
None => return false,
24332433
};
2434-
let target = target.target().wrapping_add(target.info().addend as u64);
24352434

24362435
let offset = target.wrapping_sub(reloc.target()) as u32;
24372436
let low_offset = offset & 0xfff;

basedetection.cpp

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
// Copyright (c) 2015-2024 Vector 35 Inc
2+
//
3+
// Permission is hereby granted, free of charge, to any person obtaining a copy
4+
// of this software and associated documentation files (the "Software"), to
5+
// deal in the Software without restriction, including without limitation the
6+
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
7+
// sell copies of the Software, and to permit persons to whom the Software is
8+
// furnished to do so, subject to the following conditions:
9+
//
10+
// The above copyright notice and this permission notice shall be included in
11+
// all copies or substantial portions of the Software.
12+
//
13+
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14+
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15+
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16+
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17+
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
18+
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
19+
// IN THE SOFTWARE.
20+
21+
#include "binaryninjaapi.h"
22+
23+
using namespace BinaryNinja;
24+
25+
26+
BaseAddressDetection::BaseAddressDetection(Ref<BinaryView> bv)
27+
{
28+
m_object = BNCreateBaseAddressDetection(bv->GetObject());
29+
}
30+
31+
32+
BaseAddressDetection::~BaseAddressDetection()
33+
{
34+
BNFreeBaseAddressDetection(m_object);
35+
}
36+
37+
38+
bool BaseAddressDetection::DetectBaseAddress(BaseAddressDetectionSettings& settings)
39+
{
40+
BNBaseAddressDetectionSettings bnSettings = {
41+
settings.Architecture.c_str(),
42+
settings.Analysis.c_str(),
43+
settings.MinStrlen,
44+
settings.Alignment,
45+
settings.LowerBoundary,
46+
settings.UpperBoundary,
47+
settings.POIAnalysis,
48+
settings.MaxPointersPerCluster,
49+
};
50+
51+
return BNDetectBaseAddress(m_object, bnSettings);
52+
}
53+
54+
55+
void BaseAddressDetection::Abort()
56+
{
57+
return BNAbortBaseAddressDetection(m_object);
58+
}
59+
60+
61+
bool BaseAddressDetection::IsAborted()
62+
{
63+
return BNIsBaseAddressDetectionAborted(m_object);
64+
}
65+
66+
67+
std::set<std::pair<size_t, uint64_t>> BaseAddressDetection::GetScores(BNBaseAddressDetectionConfidence* confidence,
68+
uint64_t *lastTestedBaseAddress)
69+
{
70+
std::set<std::pair<size_t, uint64_t>> result;
71+
BNBaseAddressDetectionScore scores[10];
72+
size_t numCandidates = BNGetBaseAddressDetectionScores(m_object, scores, 10, confidence, lastTestedBaseAddress);
73+
for (size_t i = 0; i < numCandidates; i++)
74+
result.insert(std::make_pair(scores[i].Score, scores[i].BaseAddress));
75+
return result;
76+
}
77+
78+
79+
std::vector<BNBaseAddressDetectionReason> BaseAddressDetection::GetReasonsForBaseAddress(uint64_t baseAddress)
80+
{
81+
std::vector<BNBaseAddressDetectionReason> result;
82+
size_t count;
83+
BNBaseAddressDetectionReason *reasons = BNGetBaseAddressDetectionReasons(m_object, baseAddress, &count);
84+
if (!reasons)
85+
return result;
86+
87+
for (size_t i = 0; i < count; i++)
88+
result.push_back(reasons[i]);
89+
90+
BNFreeBaseAddressDetectionReasons(reasons);
91+
return result;
92+
}

binaryninjaapi.h

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17378,6 +17378,62 @@ namespace BinaryNinja {
1737817378
const std::function<void(Symbol*, Type*)>& add);
1737917379
void Process();
1738017380
};
17381+
17382+
struct BaseAddressDetectionSettings
17383+
{
17384+
std::string Architecture;
17385+
std::string Analysis;
17386+
uint32_t MinStrlen;
17387+
uint32_t Alignment;
17388+
uint64_t LowerBoundary;
17389+
uint64_t UpperBoundary;
17390+
BNBaseAddressDetectionPOISetting POIAnalysis;
17391+
uint32_t MaxPointersPerCluster;
17392+
};
17393+
17394+
/*!
17395+
\ingroup baseaddressdetection
17396+
*/
17397+
class BaseAddressDetection
17398+
{
17399+
BNBaseAddressDetection* m_object;
17400+
17401+
public:
17402+
BaseAddressDetection(Ref<BinaryView> view);
17403+
~BaseAddressDetection();
17404+
17405+
/*! Analyze program, identify pointers and points-of-interest, and detect candidate base addresses
17406+
17407+
\param settings Base address detection settings
17408+
\return true on success, false otherwise
17409+
*/
17410+
bool DetectBaseAddress(BaseAddressDetectionSettings& settings);
17411+
17412+
/*! Get the top 10 candidate base addresses and thier scores
17413+
17414+
\param confidence Confidence level that indicates the likelihood the top base address candidate is correct
17415+
\param lastTestedBaseAddress Last base address tested before analysis was aborted or completed
17416+
\return Set of pairs containing candidate base addresses and their scores
17417+
*/
17418+
std::set<std::pair<size_t, uint64_t>> GetScores(BNBaseAddressDetectionConfidence* confidence, uint64_t *lastTestedBaseAddress);
17419+
17420+
/*! Get a vector of BNBaseAddressDetectionReasons containing information that indicates why a base address was reported as a candidate
17421+
17422+
\param baseAddress Base address to query reasons for
17423+
\return Vector of reason structures containing information about why a base address was reported as a candidate
17424+
*/
17425+
std::vector<BNBaseAddressDetectionReason> GetReasonsForBaseAddress(uint64_t baseAddress);
17426+
17427+
/*! Abort base address detection
17428+
*/
17429+
void Abort();
17430+
17431+
/*! Determine if base address detection is aborted
17432+
17433+
\return true if aborted by user, false otherwise
17434+
*/
17435+
bool IsAborted();
17436+
};
1738117437
} // namespace BinaryNinja
1738217438

1738317439

0 commit comments

Comments
 (0)