class
VmpStackEvaluator
{
public:
bool
EvaluateStackOffset(Funcdata& data,Varnode
*
vn,
int
& outOffset);
private:
uintb traceVarnodeStack(Varnode
*
vn);
uintb tracePcodeStack(PcodeOp
*
op);
uintb
eval
(PcodeOp
*
op);
private:
bool
bContainEsp
=
false;
bool
bError
=
false;
VarnodeData espLoc;
};
uintb VmpStackEvaluator::
eval
(PcodeOp
*
op)
{
if
(bError) {
return
0x0
;
}
uintb val1
=
traceVarnodeStack(op
-
>getIn(
0
));
uintb val2
=
traceVarnodeStack(op
-
>getIn(
1
));
uintb calVal
=
op
-
>getOpcode()
-
>evaluateBinary(op
-
>getOut()
-
>getSize(), op
-
>getIn(
0
)
-
>getSize(), val1, val2);
return
calVal;
}
uintb VmpStackEvaluator::tracePcodeStack(PcodeOp
*
op)
{
if
(bError) {
return
0x0
;
}
OpCode code
=
op
-
>code();
switch (code) {
case CPUI_INT_ADD:
case CPUI_INT_SUB:
case CPUI_PIECE:
case CPUI_SUBPIECE:
return
eval
(op);
case CPUI_COPY:
return
traceVarnodeStack(op
-
>getIn(
0
));
default:
bError
=
true;
break
;
}
return
0x0
;
}
uintb VmpStackEvaluator::traceVarnodeStack(Varnode
*
vn)
{
if
(bError) {
return
0x0
;
}
if
(vn
-
>isConstant()) {
return
vn
-
>getOffset();
}
if
(vn
-
>isInput()) {
if
(vn
-
>getSpace()
=
=
espLoc.space && vn
-
>getOffset()
=
=
espLoc.offset) {
bContainEsp
=
true;
}
else
{
bError
=
true;
}
return
0x0
;
}
PcodeOp
*
defOp
=
vn
-
>getDef();
if
(!defOp) {
bError
=
true;
return
0x0
;
}
return
tracePcodeStack(defOp);
}
bool
VmpStackEvaluator::EvaluateStackOffset(Funcdata& data, Varnode
*
vn,
int
& outOffset)
{
espLoc
=
data.getArch()
-
>translate
-
>getRegister(
"ESP"
);
if
(!vn
-
>isWritten()) {
return
false;
}
PcodeOp
*
defOp
=
vn
-
>getDef();
if
(defOp
-
>code() !
=
CPUI_INT_ADD && defOp
-
>code() !
=
CPUI_INT_SUB) {
return
false;
}
outOffset
=
tracePcodeStack(defOp);
if
(bError) {
return
false;
}
return
bContainEsp;
}