优化 MethodControlFlowCalculator生成的指令有可能违反IL控制流规则的问题

main
walon 2025-08-01 10:57:53 +08:00
parent ddb144eac8
commit c596b58d3e
1 changed files with 30 additions and 9 deletions

View File

@ -330,7 +330,8 @@ namespace Obfuz.ObfusPasses.ControlFlowObfus
group.basicBlocks.Insert(group.basicBlocks.IndexOf(to), saveLocalBasicBlock); group.basicBlocks.Insert(group.basicBlocks.IndexOf(to), saveLocalBasicBlock);
group.switchMachineCases.Add(new SwitchMachineCase { index = -1, prepareBlock = saveLocalBasicBlock, targetBlock = to}); group.switchMachineCases.Add(new SwitchMachineCase { index = -1, prepareBlock = saveLocalBasicBlock, targetBlock = to});
saveLocalBasicBlock.instructions.Add(Instruction.Create(OpCodes.Ldsfld, (FieldDef)null)); saveLocalBasicBlock.instructions.Add(Instruction.Create(OpCodes.Ldsfld, (FieldDef)null));
saveLocalBasicBlock.instructions.Add(Instruction.Create(OpCodes.Br, group.switchMachineInst)); saveLocalBasicBlock.instructions.Add(Instruction.Create(OpCodes.Stloc, GlobalSwitchIndexLocal));
saveLocalBasicBlock.instructions.Add(Instruction.Create(OpCodes.Br, group.switchMachineEntryInst));
return saveLocalBasicBlock; return saveLocalBasicBlock;
@ -426,6 +427,21 @@ namespace Obfuz.ObfusPasses.ControlFlowObfus
//} //}
} }
private Local _globalSwitchIndexLocal;
Local GlobalSwitchIndexLocal
{
get
{
if (_globalSwitchIndexLocal == null)
{
_globalSwitchIndexLocal = new Local(_method.Module.CorLibTypes.Int32);
_method.Body.Variables.Add(_globalSwitchIndexLocal);
}
return _globalSwitchIndexLocal;
}
}
private void InsertSwitchMachineBasicBlockForGroup(BlockGroup group, Dictionary<Instruction, BasicBlockInfo> inst2bb) private void InsertSwitchMachineBasicBlockForGroup(BlockGroup group, Dictionary<Instruction, BasicBlockInfo> inst2bb)
{ {
if (group.subGroups != null && group.subGroups.Count > 0) if (group.subGroups != null && group.subGroups.Count > 0)
@ -449,6 +465,8 @@ namespace Obfuz.ObfusPasses.ControlFlowObfus
var instructions = new List<Instruction>() var instructions = new List<Instruction>()
{ {
Instruction.Create(OpCodes.Ldsfld, (FieldDef)null), Instruction.Create(OpCodes.Ldsfld, (FieldDef)null),
Instruction.Create(OpCodes.Stloc, GlobalSwitchIndexLocal),
group.switchMachineEntryInst,
group.switchMachineInst, group.switchMachineInst,
Instruction.Create(OpCodes.Br, firstCase.targetBlock.FirstInstruction), Instruction.Create(OpCodes.Br, firstCase.targetBlock.FirstInstruction),
}; };
@ -480,7 +498,7 @@ namespace Obfuz.ObfusPasses.ControlFlowObfus
switchMachineCase.index = i; switchMachineCase.index = i;
List<Instruction> prepareBlockInstructions = switchMachineCase.prepareBlock.instructions; List<Instruction> prepareBlockInstructions = switchMachineCase.prepareBlock.instructions;
Instruction setBranchIndexInst = prepareBlockInstructions[prepareBlockInstructions.Count - 2]; Instruction setBranchIndexInst = prepareBlockInstructions[prepareBlockInstructions.Count - 3];
Assert.AreEqual(setBranchIndexInst.OpCode, OpCodes.Ldsfld, "first instruction of prepareBlock should be Ldsfld"); Assert.AreEqual(setBranchIndexInst.OpCode, OpCodes.Ldsfld, "first instruction of prepareBlock should be Ldsfld");
//setBranchIndexInst.Operand = i; //setBranchIndexInst.Operand = i;
var indexField = _constFieldAllocator.Allocate(i); var indexField = _constFieldAllocator.Allocate(i);
@ -489,9 +507,10 @@ namespace Obfuz.ObfusPasses.ControlFlowObfus
} }
// after shuffle // after shuffle
Assert.IsTrue(instructions.Count == 3 || instructions.Count == 4, "Switch machine basic block should contain 3 or 4 instructions"); //Assert.IsTrue(instructions.Count == 4 || instructions.Count == 5, "Switch machine basic block should contain 4 or 5 instructions");
Assert.AreEqual(Code.Ldsfld, instructions[instructions.Count - 3].OpCode.Code, "First instruction should be Ldsfld"); Instruction loadFirstIndex = instructions[instructions.Count - 5];
instructions[instructions.Count - 3].Operand = _constFieldAllocator.Allocate(firstCase.index); Assert.AreEqual(Code.Ldsfld, loadFirstIndex.OpCode.Code, "First instruction should be Ldsfld");
loadFirstIndex.Operand = _constFieldAllocator.Allocate(firstCase.index);
} }
} }
@ -553,6 +572,7 @@ namespace Obfuz.ObfusPasses.ControlFlowObfus
public List<BasicBlockInfo> basicBlocks; public List<BasicBlockInfo> basicBlocks;
public Instruction switchMachineEntryInst;
public Instruction switchMachineInst; public Instruction switchMachineInst;
public List<SwitchMachineCase> switchMachineCases; public List<SwitchMachineCase> switchMachineCases;
@ -663,7 +683,7 @@ namespace Obfuz.ObfusPasses.ControlFlowObfus
this.subGroups = finalGroupList; this.subGroups = finalGroupList;
} }
public void ComputeBasicBlocks(Dictionary<Instruction, BasicBlockInfo> inst2bb) public void ComputeBasicBlocks(Dictionary<Instruction, BasicBlockInfo> inst2bb, Func<Local> switchIndexLocalGetter)
{ {
if (subGroups == null || subGroups.Count == 0) if (subGroups == null || subGroups.Count == 0)
{ {
@ -684,13 +704,14 @@ namespace Obfuz.ObfusPasses.ControlFlowObfus
basicBlocks.Add(block); basicBlocks.Add(block);
} }
} }
switchMachineEntryInst = Instruction.Create(OpCodes.Ldloc, switchIndexLocalGetter());
switchMachineInst = Instruction.Create(OpCodes.Switch, new List<Instruction>()); switchMachineInst = Instruction.Create(OpCodes.Switch, new List<Instruction>());
switchMachineCases = new List<SwitchMachineCase>(); switchMachineCases = new List<SwitchMachineCase>();
return; return;
} }
foreach (var subGroup in subGroups) foreach (var subGroup in subGroups)
{ {
subGroup.ComputeBasicBlocks(inst2bb); subGroup.ComputeBasicBlocks(inst2bb, switchIndexLocalGetter);
} }
} }
} }
@ -799,7 +820,7 @@ namespace Obfuz.ObfusPasses.ControlFlowObfus
var rootGroup = new BlockGroup(new List<Instruction>(instructions), inst2blockGroup); var rootGroup = new BlockGroup(new List<Instruction>(instructions), inst2blockGroup);
rootGroup.SplitInstructionsNotInAnySubGroupsToIndividualGroups(inst2blockGroup); rootGroup.SplitInstructionsNotInAnySubGroupsToIndividualGroups(inst2blockGroup);
rootGroup.ComputeBasicBlocks(BuildInstructionToBasicBlockInfoDic()); rootGroup.ComputeBasicBlocks(BuildInstructionToBasicBlockInfoDic(), () => GlobalSwitchIndexLocal);
return rootGroup; return rootGroup;
} }