mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-03 17:59:46 +02:00
Better protections for overlapping input analysis
This commit is contained in:
parent
b17957b176
commit
5319b9703c
3 changed files with 24 additions and 18 deletions
|
@ -482,7 +482,7 @@ int4 ParamListStandard::characterizeAsParam(const Address &loc,int4 size) const
|
||||||
const ParamEntry *testEntry = (*iterpair.first).getParamEntry();
|
const ParamEntry *testEntry = (*iterpair.first).getParamEntry();
|
||||||
if (testEntry->getMinSize() <= size && testEntry->justifiedContain(loc, size)==0)
|
if (testEntry->getMinSize() <= size && testEntry->justifiedContain(loc, size)==0)
|
||||||
return 1;
|
return 1;
|
||||||
if (testEntry->containedBy(loc, size))
|
if (testEntry->isExclusion() && testEntry->containedBy(loc, size))
|
||||||
res = 2;
|
res = 2;
|
||||||
++iterpair.first;
|
++iterpair.first;
|
||||||
}
|
}
|
||||||
|
@ -490,7 +490,7 @@ int4 ParamListStandard::characterizeAsParam(const Address &loc,int4 size) const
|
||||||
iterpair.second = resolver->find_end(loc.getOffset() + (size-1));
|
iterpair.second = resolver->find_end(loc.getOffset() + (size-1));
|
||||||
while(iterpair.first != iterpair.second) {
|
while(iterpair.first != iterpair.second) {
|
||||||
const ParamEntry *testEntry = (*iterpair.first).getParamEntry();
|
const ParamEntry *testEntry = (*iterpair.first).getParamEntry();
|
||||||
if (testEntry->containedBy(loc, size)) {
|
if (testEntry->isExclusion() && testEntry->containedBy(loc, size)) {
|
||||||
res = 2;
|
res = 2;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -953,9 +953,12 @@ bool ParamListStandard::getBiggestContainedParam(const Address &loc,int4 size,Va
|
||||||
ParamEntryResolver *resolver = resolverMap[index];
|
ParamEntryResolver *resolver = resolverMap[index];
|
||||||
if (resolver == (ParamEntryResolver *)0)
|
if (resolver == (ParamEntryResolver *)0)
|
||||||
return false;
|
return false;
|
||||||
|
Address endLoc = loc + (size-1);
|
||||||
|
if (endLoc.getOffset() < loc.getOffset())
|
||||||
|
return false; // Assume there is no parameter if we see wrapping
|
||||||
const ParamEntry *maxEntry = (const ParamEntry *)0;
|
const ParamEntry *maxEntry = (const ParamEntry *)0;
|
||||||
ParamEntryResolver::const_iterator iter = resolver->find_begin(loc.getOffset());
|
ParamEntryResolver::const_iterator iter = resolver->find_begin(loc.getOffset());
|
||||||
ParamEntryResolver::const_iterator enditer = resolver->find_end(loc.getOffset() + (size-1));
|
ParamEntryResolver::const_iterator enditer = resolver->find_end(endLoc.getOffset());
|
||||||
while(iter != enditer) {
|
while(iter != enditer) {
|
||||||
const ParamEntry *testEntry = (*iter).getParamEntry();
|
const ParamEntry *testEntry = (*iter).getParamEntry();
|
||||||
++iter;
|
++iter;
|
||||||
|
@ -966,9 +969,9 @@ bool ParamListStandard::getBiggestContainedParam(const Address &loc,int4 size,Va
|
||||||
maxEntry = testEntry;
|
maxEntry = testEntry;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!maxEntry->isExclusion())
|
|
||||||
return false;
|
|
||||||
if (maxEntry != (const ParamEntry *)0) {
|
if (maxEntry != (const ParamEntry *)0) {
|
||||||
|
if (!maxEntry->isExclusion())
|
||||||
|
return false;
|
||||||
res.space = maxEntry->getSpace();
|
res.space = maxEntry->getSpace();
|
||||||
res.offset = maxEntry->getBase();
|
res.offset = maxEntry->getBase();
|
||||||
res.size = maxEntry->getSize();
|
res.size = maxEntry->getSize();
|
||||||
|
|
|
@ -1043,17 +1043,20 @@ void Heritage::guard(const Address &addr,int4 size,vector<Varnode *> &read,vecto
|
||||||
/// pulls out the potential parameter.
|
/// pulls out the potential parameter.
|
||||||
/// \param fc is the call site potentially taking a parameter
|
/// \param fc is the call site potentially taking a parameter
|
||||||
/// \param addr is the starting address of the range
|
/// \param addr is the starting address of the range
|
||||||
|
/// \param transAddr is the start of the same range from the callee's stack perspective
|
||||||
/// \param size is the size of the range in bytes
|
/// \param size is the size of the range in bytes
|
||||||
void Heritage::guardCallOverlappingInput(FuncCallSpecs *fc,const Address &addr,int4 size)
|
void Heritage::guardCallOverlappingInput(FuncCallSpecs *fc,const Address &addr,const Address &transAddr,int4 size)
|
||||||
|
|
||||||
{
|
{
|
||||||
VarnodeData vData;
|
VarnodeData vData;
|
||||||
|
|
||||||
if (fc->getBiggestContainedInputParam(addr, size, vData)) {
|
if (fc->getBiggestContainedInputParam(transAddr, size, vData)) {
|
||||||
ParamActive *active = fc->getActiveInput();
|
ParamActive *active = fc->getActiveInput();
|
||||||
Address taddr(vData.space,vData.offset);
|
Address truncAddr(vData.space,vData.offset);
|
||||||
if (active->whichTrial(taddr, size) < 0) { // If not already a trial
|
if (active->whichTrial(truncAddr, size) < 0) { // If not already a trial
|
||||||
int4 truncateAmount = addr.justifiedContain(size, taddr, vData.size, false);
|
int4 truncateAmount = transAddr.justifiedContain(size, truncAddr, vData.size, false);
|
||||||
|
int4 diff = (int4)(truncAddr.getOffset() - transAddr.getOffset());
|
||||||
|
truncAddr = addr + diff; // Convert truncated Address to caller's perspective
|
||||||
PcodeOp *op = fc->getOp();
|
PcodeOp *op = fc->getOp();
|
||||||
PcodeOp *subpieceOp = fd->newOp(2,op->getAddr());
|
PcodeOp *subpieceOp = fd->newOp(2,op->getAddr());
|
||||||
fd->opSetOpcode(subpieceOp, CPUI_SUBPIECE);
|
fd->opSetOpcode(subpieceOp, CPUI_SUBPIECE);
|
||||||
|
@ -1061,9 +1064,9 @@ void Heritage::guardCallOverlappingInput(FuncCallSpecs *fc,const Address &addr,i
|
||||||
wholeVn->setActiveHeritage();
|
wholeVn->setActiveHeritage();
|
||||||
fd->opSetInput(subpieceOp,wholeVn,0);
|
fd->opSetInput(subpieceOp,wholeVn,0);
|
||||||
fd->opSetInput(subpieceOp,fd->newConstant(4,truncateAmount),1);
|
fd->opSetInput(subpieceOp,fd->newConstant(4,truncateAmount),1);
|
||||||
Varnode *vn = fd->newVarnodeOut(vData.size, taddr, subpieceOp);
|
Varnode *vn = fd->newVarnodeOut(vData.size, truncAddr, subpieceOp);
|
||||||
fd->opInsertBefore(subpieceOp,op);
|
fd->opInsertBefore(subpieceOp,op);
|
||||||
active->registerTrial(taddr, vData.size);
|
active->registerTrial(truncAddr, vData.size);
|
||||||
fd->opInsertInput(op, vn, op->numInput());
|
fd->opInsertInput(op, vn, op->numInput());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1121,21 +1124,21 @@ void Heritage::guardCalls(uint4 flags,const Address &addr,int4 size,vector<Varno
|
||||||
tryregister = false;
|
tryregister = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Address taddr(spc,off);
|
Address transAddr(spc,off); // Address relative to callee's stack
|
||||||
if (tryregister) {
|
if (tryregister) {
|
||||||
int4 inputCharacter = fc->characterizeAsInputParam(taddr,size);
|
int4 inputCharacter = fc->characterizeAsInputParam(transAddr,size);
|
||||||
if (inputCharacter == 1) { // Call could be using this range as an input parameter
|
if (inputCharacter == 1) { // Call could be using this range as an input parameter
|
||||||
ParamActive *active = fc->getActiveInput();
|
ParamActive *active = fc->getActiveInput();
|
||||||
if (active->whichTrial(taddr,size)<0) { // If not already a trial
|
if (active->whichTrial(transAddr,size)<0) { // If not already a trial
|
||||||
PcodeOp *op = fc->getOp();
|
PcodeOp *op = fc->getOp();
|
||||||
active->registerTrial(taddr,size);
|
active->registerTrial(transAddr,size);
|
||||||
Varnode *vn = fd->newVarnode(size,addr);
|
Varnode *vn = fd->newVarnode(size,addr);
|
||||||
vn->setActiveHeritage();
|
vn->setActiveHeritage();
|
||||||
fd->opInsertInput(op,vn,op->numInput());
|
fd->opInsertInput(op,vn,op->numInput());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (inputCharacter == 2) // Call may be using part of this range as an input parameter
|
else if (inputCharacter == 2) // Call may be using part of this range as an input parameter
|
||||||
guardCallOverlappingInput(fc, addr, size);
|
guardCallOverlappingInput(fc, addr, transAddr, size);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// We do not guard the call if the effect is "unaffected" or "reload"
|
// We do not guard the call if the effect is "unaffected" or "reload"
|
||||||
|
|
|
@ -246,7 +246,7 @@ class Heritage {
|
||||||
void reprocessFreeStores(AddrSpace *spc,vector<PcodeOp *> &freeStores);
|
void reprocessFreeStores(AddrSpace *spc,vector<PcodeOp *> &freeStores);
|
||||||
void guard(const Address &addr,int4 size,vector<Varnode *> &read,vector<Varnode *> &write,vector<Varnode *> &inputvars);
|
void guard(const Address &addr,int4 size,vector<Varnode *> &read,vector<Varnode *> &write,vector<Varnode *> &inputvars);
|
||||||
void guardInput(const Address &addr,int4 size,vector<Varnode *> &input);
|
void guardInput(const Address &addr,int4 size,vector<Varnode *> &input);
|
||||||
void guardCallOverlappingInput(FuncCallSpecs *fc,const Address &addr,int4 size);
|
void guardCallOverlappingInput(FuncCallSpecs *fc,const Address &addr,const Address &transAddr,int4 size);
|
||||||
void guardCalls(uint4 flags,const Address &addr,int4 size,vector<Varnode *> &write);
|
void guardCalls(uint4 flags,const Address &addr,int4 size,vector<Varnode *> &write);
|
||||||
void guardStores(const Address &addr,int4 size,vector<Varnode *> &write);
|
void guardStores(const Address &addr,int4 size,vector<Varnode *> &write);
|
||||||
void guardLoads(uint4 flags,const Address &addr,int4 size,vector<Varnode *> &write);
|
void guardLoads(uint4 flags,const Address &addr,int4 size,vector<Varnode *> &write);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue