Handle more switch cases
This commit is contained in:
parent
8aff8b22b1
commit
5fdd91ae05
|
@ -290,5 +290,12 @@ namespace de4dot.blocks {
|
||||||
throw new ApplicationException("Could not remove dead block");
|
throw new ApplicationException("Could not remove dead block");
|
||||||
block.removeGuaranteedDeadBlock();
|
block.removeGuaranteedDeadBlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void add(Block block) {
|
||||||
|
if (block.Parent != null)
|
||||||
|
throw new ApplicationException("Block already has a parent");
|
||||||
|
baseBlocks.Add(block);
|
||||||
|
block.Parent = this;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,6 +41,9 @@ namespace de4dot.blocks.cflow {
|
||||||
if (isSwitchType1(switchBlock) && deobfuscateType1(switchBlock))
|
if (isSwitchType1(switchBlock) && deobfuscateType1(switchBlock))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
if (isSwitchType2(switchBlock) && deobfuscateType2(switchBlock))
|
||||||
|
return true;
|
||||||
|
|
||||||
if (switchBlock.FirstInstr.isLdloc() && fixSwitchBranch(switchBlock))
|
if (switchBlock.FirstInstr.isLdloc() && fixSwitchBranch(switchBlock))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
@ -60,6 +63,36 @@ namespace de4dot.blocks.cflow {
|
||||||
return switchBlock.FirstInstr.isLdloc();
|
return switchBlock.FirstInstr.isLdloc();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool isSwitchType2(Block switchBlock) {
|
||||||
|
VariableDefinition local = null;
|
||||||
|
foreach (var instr in switchBlock.Instructions) {
|
||||||
|
if (!instr.isLdloc())
|
||||||
|
continue;
|
||||||
|
local = Instr.getLocalVar(blocks.Locals, instr);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (local == null)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
foreach (var source in switchBlock.Sources) {
|
||||||
|
var instrs = source.Instructions;
|
||||||
|
for (int i = 1; i < instrs.Count; i++) {
|
||||||
|
var ldci4 = instrs[i - 1];
|
||||||
|
if (!ldci4.isLdcI4())
|
||||||
|
continue;
|
||||||
|
var stloc = instrs[i];
|
||||||
|
if (!stloc.isStloc())
|
||||||
|
continue;
|
||||||
|
if (Instr.getLocalVar(blocks.Locals, stloc) != local)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
bool isStLdlocBranch(Block switchBlock, bool isSwitch) {
|
bool isStLdlocBranch(Block switchBlock, bool isSwitch) {
|
||||||
int numInstrs = 2 + (isSwitch ? 1 : 0);
|
int numInstrs = 2 + (isSwitch ? 1 : 0);
|
||||||
return switchBlock.Instructions.Count == numInstrs &&
|
return switchBlock.Instructions.Count == numInstrs &&
|
||||||
|
@ -295,6 +328,83 @@ namespace de4dot.blocks.cflow {
|
||||||
return changed;
|
return changed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool deobfuscateType2(Block switchBlock) {
|
||||||
|
bool changed = false;
|
||||||
|
|
||||||
|
var bccSources = new List<Block>();
|
||||||
|
foreach (var source in new List<Block>(switchBlock.Sources)) {
|
||||||
|
if (source.LastInstr.isConditionalBranch()) {
|
||||||
|
bccSources.Add(source);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (!source.canAppend(switchBlock))
|
||||||
|
continue;
|
||||||
|
if (!willHaveKnownTarget(switchBlock, source))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
source.append(switchBlock);
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var bccSource in bccSources) {
|
||||||
|
if (!willHaveKnownTarget(switchBlock, bccSource))
|
||||||
|
continue;
|
||||||
|
var consts = getBccLocalConstants(bccSource);
|
||||||
|
if (consts.Count == 0)
|
||||||
|
continue;
|
||||||
|
var newFallThrough = createBlock(consts, bccSource.FallThrough);
|
||||||
|
var newTarget = createBlock(consts, bccSource.Targets[0]);
|
||||||
|
var oldFallThrough = bccSource.FallThrough;
|
||||||
|
var oldTarget = bccSource.Targets[0];
|
||||||
|
bccSource.setNewFallThrough(newFallThrough);
|
||||||
|
bccSource.setNewTarget(0, newTarget);
|
||||||
|
newFallThrough.setNewFallThrough(oldFallThrough);
|
||||||
|
newTarget.setNewFallThrough(oldTarget);
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return changed;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Block createBlock(Dictionary<VariableDefinition, int> consts, Block fallThrough) {
|
||||||
|
var block = new Block();
|
||||||
|
foreach (var kv in consts) {
|
||||||
|
block.Instructions.Add(new Instr(DotNetUtils.createLdci4(kv.Value)));
|
||||||
|
block.Instructions.Add(new Instr(Instruction.Create(OpCodes.Stloc, kv.Key)));
|
||||||
|
}
|
||||||
|
fallThrough.Parent.add(block);
|
||||||
|
return block;
|
||||||
|
}
|
||||||
|
|
||||||
|
Dictionary<VariableDefinition, int> getBccLocalConstants(Block block) {
|
||||||
|
var dict = new Dictionary<VariableDefinition, int>();
|
||||||
|
var instrs = block.Instructions;
|
||||||
|
for (int i = 0; i < instrs.Count; i++) {
|
||||||
|
var instr = instrs[i];
|
||||||
|
if (instr.isStloc()) {
|
||||||
|
var local = Instr.getLocalVar(blocks.Locals, instr);
|
||||||
|
if (local == null)
|
||||||
|
continue;
|
||||||
|
var ldci4 = i == 0 ? null : instrs[i - 1];
|
||||||
|
if (ldci4 == null || !ldci4.isLdcI4())
|
||||||
|
dict.Remove(local);
|
||||||
|
else
|
||||||
|
dict[local] = ldci4.getLdcI4Value();
|
||||||
|
}
|
||||||
|
else if (instr.isLdloc()) {
|
||||||
|
var local = Instr.getLocalVar(blocks.Locals, instr);
|
||||||
|
if (local != null)
|
||||||
|
dict.Remove(local);
|
||||||
|
}
|
||||||
|
else if (instr.OpCode.Code == Code.Ldloca || instr.OpCode.Code == Code.Ldloca_S) {
|
||||||
|
var local = instr.Operand as VariableDefinition;
|
||||||
|
if (local != null)
|
||||||
|
dict.Remove(local);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return dict;
|
||||||
|
}
|
||||||
|
|
||||||
bool emulateGetTarget(Block switchBlock, out Block target) {
|
bool emulateGetTarget(Block switchBlock, out Block target) {
|
||||||
instructionEmulator.init(blocks);
|
instructionEmulator.init(blocks);
|
||||||
try {
|
try {
|
||||||
|
|
Loading…
Reference in New Issue
Block a user