Set locals = 0 when emulating from first instruction

This commit is contained in:
de4dot 2013-11-12 17:11:54 +01:00
parent 4fcb332ddf
commit 682b0df04a
4 changed files with 40 additions and 13 deletions

View File

@ -35,7 +35,7 @@ namespace de4dot.blocks.cflow {
this.block = block;
if (!block.LastInstr.IsConditionalBranch() && block.LastInstr.OpCode.Code != Code.Switch)
return false;
instructionEmulator.Initialize(blocks);
instructionEmulator.Initialize(blocks, allBlocks[0] == block);
var instructions = block.Instructions;
if (instructions.Count == 0)

View File

@ -37,7 +37,7 @@ namespace de4dot.blocks.cflow {
protected override bool Deobfuscate(Block block) {
bool modified = false;
instructionEmulator.Initialize(blocks);
instructionEmulator.Initialize(blocks, allBlocks[0] == block);
var instrs = block.Instructions;
for (int i = 0; i < instrs.Count; i++) {
var instr = instrs[i];

View File

@ -34,19 +34,24 @@ namespace de4dot.blocks.cflow {
MethodDef prev_method;
List<Value> cached_args = new List<Value>();
List<Value> cached_locals = new List<Value>();
List<Value> cached_zeroed_locals = new List<Value>();
public InstructionEmulator() {
}
public InstructionEmulator(MethodDef method) {
Initialize(method);
Initialize(method, false);
}
public void Initialize(Blocks blocks) {
Initialize(blocks.Method);
public void Initialize(Blocks blocks, bool emulateFromFirstInstruction) {
Initialize(blocks.Method, emulateFromFirstInstruction);
}
public void Initialize(MethodDef method) {
Initialize(method, false);
}
public void Initialize(MethodDef method, bool emulateFromFirstInstruction) {
this.parameterDefs = method.Parameters;
this.localDefs = method.Body.Variables;
valueStack.Initialize();
@ -60,14 +65,17 @@ namespace de4dot.blocks.cflow {
cached_args.Add(GetUnknownValue(parameterDefs[i].Type));
cached_locals.Clear();
for (int i = 0; i < localDefs.Count; i++)
cached_zeroed_locals.Clear();
for (int i = 0; i < localDefs.Count; i++) {
cached_locals.Add(GetUnknownValue(localDefs[i].Type));
cached_zeroed_locals.Add(GetDefaultValue(localDefs[i].Type));
}
}
args.Clear();
args.AddRange(cached_args);
locals.Clear();
locals.AddRange(cached_locals);
locals.AddRange(method.Body.InitLocals && emulateFromFirstInstruction ? cached_zeroed_locals : cached_locals);
}
public void SetProtected(Value value) {
@ -95,6 +103,25 @@ namespace de4dot.blocks.cflow {
return new UnknownValue();
}
static Value GetDefaultValue(TypeSig type) {
if (type == null)
return new UnknownValue();
switch (type.ElementType) {
case ElementType.Boolean:
case ElementType.I1:
case ElementType.U1:
case ElementType.I2:
case ElementType.U2:
case ElementType.I4:
case ElementType.U4:
return Int32Value.zero;
case ElementType.I8:
case ElementType.U8:
return Int64Value.zero;
}
return new UnknownValue();
}
Value TruncateValue(Value value, TypeSig type) {
if (type == null)
return value;

View File

@ -158,7 +158,7 @@ namespace de4dot.blocks.cflow {
foreach (var source in new List<Block>(block.Sources)) {
if (!isBranchBlock(source))
continue;
instructionEmulator.Initialize(blocks);
instructionEmulator.Initialize(blocks, allBlocks[0] == source);
instructionEmulator.Emulate(source.Instructions);
var target = GetSwitchTarget(switchTargets, switchFallThrough, instructionEmulator.Pop());
@ -183,7 +183,7 @@ namespace de4dot.blocks.cflow {
bool modified = false;
foreach (var source in new List<Block>(block.Sources)) {
if (isBranchBlock(source)) {
instructionEmulator.Initialize(blocks);
instructionEmulator.Initialize(blocks, allBlocks[0] == source);
instructionEmulator.Emulate(source.Instructions);
var target = GetSwitchTarget(switchTargets, switchFallThrough, instructionEmulator.GetLocal(switchVariable));
@ -193,7 +193,7 @@ namespace de4dot.blocks.cflow {
modified = true;
}
else if (IsBccBlock(source)) {
instructionEmulator.Initialize(blocks);
instructionEmulator.Initialize(blocks, allBlocks[0] == source);
instructionEmulator.Emulate(source.Instructions);
var target = GetSwitchTarget(switchTargets, switchFallThrough, instructionEmulator.GetLocal(switchVariable));
@ -223,7 +223,7 @@ namespace de4dot.blocks.cflow {
foreach (var source in new List<Block>(block.Sources)) {
if (!isBranchBlock(source))
continue;
instructionEmulator.Initialize(blocks);
instructionEmulator.Initialize(blocks, allBlocks[0] == source);
instructionEmulator.Emulate(source.Instructions);
var target = GetSwitchTarget(switchTargets, switchFallThrough, instructionEmulator.Pop());
@ -407,7 +407,7 @@ namespace de4dot.blocks.cflow {
}
bool EmulateGetTarget(Block switchBlock, out Block target) {
instructionEmulator.Initialize(blocks);
instructionEmulator.Initialize(blocks, allBlocks[0] == switchBlock);
try {
instructionEmulator.Emulate(switchBlock.Instructions, 0, switchBlock.Instructions.Count - 1);
}
@ -421,7 +421,7 @@ namespace de4dot.blocks.cflow {
}
bool WillHaveKnownTarget(Block switchBlock, Block source) {
instructionEmulator.Initialize(blocks);
instructionEmulator.Initialize(blocks, allBlocks[0] == source);
try {
instructionEmulator.Emulate(source.Instructions);
instructionEmulator.Emulate(switchBlock.Instructions, 0, switchBlock.Instructions.Count - 1);