private static void InsertBlockBefore(ControlFlowGraph graph, BasicBlock oldblock , BasicBlock newblock) { List <BasicBlock> lstTemp = new List <BasicBlock>(); Sharpen.Collections.AddAll(lstTemp, oldblock.GetPreds()); Sharpen.Collections.AddAll(lstTemp, oldblock.GetPredExceptions()); // replace predecessors foreach (BasicBlock pred in lstTemp) { pred.ReplaceSuccessor(oldblock, newblock); } // copy exception edges and extend protected ranges foreach (BasicBlock hd in oldblock.GetSuccExceptions()) { newblock.AddSuccessorException(hd); ExceptionRangeCFG range = graph.GetExceptionRange(hd, oldblock); range.GetProtectedRange().Add(newblock); } // replace handler foreach (ExceptionRangeCFG range in graph.GetExceptions()) { if (range.GetHandler() == oldblock) { range.SetHandler(newblock); } } newblock.AddSuccessor(oldblock); graph.GetBlocks().AddWithKey(newblock, newblock.id); if (graph.GetFirst() == oldblock) { graph.SetFirst(newblock); } }
public static void InsertDummyExceptionHandlerBlocks(ControlFlowGraph graph, int bytecode_version) { Dictionary <BasicBlock, HashSet <ExceptionRangeCFG> > mapRanges = new Dictionary <BasicBlock , HashSet <ExceptionRangeCFG> >(); foreach (ExceptionRangeCFG range in graph.GetExceptions()) { mapRanges.ComputeIfAbsent(range.GetHandler(), (BasicBlock k) => new HashSet <ExceptionRangeCFG >()).Add(range); } foreach (KeyValuePair <BasicBlock, HashSet <ExceptionRangeCFG> > ent in mapRanges) { BasicBlock handler = ent.Key; HashSet <ExceptionRangeCFG> ranges = ent.Value; if (ranges.Count == 1) { continue; } foreach (ExceptionRangeCFG range in ranges) { // add some dummy instructions to prevent optimizing away the empty block SimpleInstructionSequence seq = new SimpleInstructionSequence(); seq.AddInstruction(Instruction.Create(ICodeConstants.opc_bipush, false, ICodeConstants .Group_General, bytecode_version, new int[] { 0 }), -1); seq.AddInstruction(Instruction.Create(ICodeConstants.opc_pop, false, ICodeConstants .Group_General, bytecode_version, null), -1); BasicBlock dummyBlock = new BasicBlock(++graph.last_id); dummyBlock.SetSeq(seq); graph.GetBlocks().AddWithKey(dummyBlock, dummyBlock.id); // only exception predecessors from this range considered List <BasicBlock> lstPredExceptions = new List <BasicBlock>(handler.GetPredExceptions ()); lstPredExceptions = lstPredExceptions.Intersect(range.GetProtectedRange()).ToList(); // replace predecessors foreach (BasicBlock pred in lstPredExceptions) { pred.ReplaceSuccessor(handler, dummyBlock); } // replace handler range.SetHandler(dummyBlock); // add common exception edges HashSet <BasicBlock> commonHandlers = new HashSet <BasicBlock>(handler.GetSuccExceptions ()); foreach (BasicBlock pred in lstPredExceptions) { commonHandlers.IntersectWith(pred.GetSuccExceptions()); } // TODO: more sanity checks? foreach (BasicBlock commonHandler in commonHandlers) { ExceptionRangeCFG commonRange = graph.GetExceptionRange(commonHandler, handler); dummyBlock.AddSuccessorException(commonHandler); commonRange.GetProtectedRange().Add(dummyBlock); } dummyBlock.AddSuccessor(handler); } } }
public static void InsertEmptyExceptionHandlerBlocks(ControlFlowGraph graph) { HashSet <BasicBlock> setVisited = new HashSet <BasicBlock>(); foreach (ExceptionRangeCFG range in graph.GetExceptions()) { BasicBlock handler = range.GetHandler(); if (setVisited.Contains(handler)) { continue; } setVisited.Add(handler); BasicBlock emptyblock = new BasicBlock(++graph.last_id); graph.GetBlocks().AddWithKey(emptyblock, emptyblock.id); // only exception predecessors considered List <BasicBlock> lstTemp = new List <BasicBlock>(handler.GetPredExceptions()); // replace predecessors foreach (BasicBlock pred in lstTemp) { pred.ReplaceSuccessor(handler, emptyblock); } // replace handler foreach (ExceptionRangeCFG range_ext in graph.GetExceptions()) { if (range_ext.GetHandler() == handler) { range_ext.SetHandler(emptyblock); } else if (range_ext.GetProtectedRange().Contains(handler)) { emptyblock.AddSuccessorException(range_ext.GetHandler()); range_ext.GetProtectedRange().Add(emptyblock); } } emptyblock.AddSuccessor(handler); if (graph.GetFirst() == handler) { graph.SetFirst(emptyblock); } } }
public static void RestorePopRanges(ControlFlowGraph graph) { List <ExceptionDeobfuscator.Range> lstRanges = new List <ExceptionDeobfuscator.Range >(); // aggregate ranges foreach (ExceptionRangeCFG range in graph.GetExceptions()) { bool found = false; foreach (ExceptionDeobfuscator.Range arr in lstRanges) { if (arr.handler == range.GetHandler() && InterpreterUtil.EqualObjects(range.GetUniqueExceptionsString (), arr.uniqueStr)) { Sharpen.Collections.AddAll(arr.protectedRange, range.GetProtectedRange()); found = true; break; } } if (!found) { // doesn't matter, which range chosen lstRanges.Add(new ExceptionDeobfuscator.Range(range.GetHandler(), range.GetUniqueExceptionsString (), new HashSet <BasicBlock>(range.GetProtectedRange()), range)); } } // process aggregated ranges foreach (ExceptionDeobfuscator.Range range in lstRanges) { if (range.uniqueStr != null) { BasicBlock handler = range.handler; InstructionSequence seq = handler.GetSeq(); Instruction firstinstr; if (seq.Length() > 0) { firstinstr = seq.GetInstr(0); if (firstinstr.opcode == ICodeConstants.opc_pop || firstinstr.opcode == ICodeConstants .opc_astore) { HashSet <BasicBlock> setrange = new HashSet <BasicBlock>(range.protectedRange); foreach (ExceptionDeobfuscator.Range range_super in lstRanges) { // finally or strict superset if (range != range_super) { HashSet <BasicBlock> setrange_super = new HashSet <BasicBlock>(range_super.protectedRange ); if (!setrange.Contains(range_super.handler) && !setrange_super.Contains(handler) && (range_super.uniqueStr == null || setrange.All(setrange_super.Contains))) { if (range_super.uniqueStr == null) { setrange_super.IntersectWith(setrange); } else { setrange_super.ExceptWith(setrange); } if (!(setrange_super.Count == 0)) { BasicBlock newblock = handler; // split the handler if (seq.Length() > 1) { newblock = new BasicBlock(++graph.last_id); InstructionSequence newseq = new SimpleInstructionSequence(); newseq.AddInstruction(firstinstr.Clone(), -1); newblock.SetSeq(newseq); graph.GetBlocks().AddWithKey(newblock, newblock.id); List <BasicBlock> lstTemp = new List <BasicBlock>(); Sharpen.Collections.AddAll(lstTemp, handler.GetPreds()); Sharpen.Collections.AddAll(lstTemp, handler.GetPredExceptions()); // replace predecessors foreach (BasicBlock pred in lstTemp) { pred.ReplaceSuccessor(handler, newblock); } // replace handler foreach (ExceptionRangeCFG range_ext in graph.GetExceptions()) { if (range_ext.GetHandler() == handler) { range_ext.SetHandler(newblock); } else if (range_ext.GetProtectedRange().Contains(handler)) { newblock.AddSuccessorException(range_ext.GetHandler()); range_ext.GetProtectedRange().Add(newblock); } } newblock.AddSuccessor(handler); if (graph.GetFirst() == handler) { graph.SetFirst(newblock); } // remove the first pop in the handler seq.RemoveInstruction(0); } newblock.AddSuccessorException(range_super.handler); range_super.rangeCFG.GetProtectedRange().Add(newblock); handler = range.rangeCFG.GetHandler(); seq = handler.GetSeq(); } } } } } } } } }
private static void DeleteArea(ControlFlowGraph graph, FinallyProcessor.Area area ) { BasicBlock start = area.start; BasicBlock next = area.next; if (start == next) { return; } if (next == null) { // dummy exit block next = graph.GetLast(); } // collect common exception ranges of predecessors and successors HashSet <BasicBlock> setCommonExceptionHandlers = new HashSet <BasicBlock>(next.GetSuccExceptions ()); foreach (BasicBlock pred in start.GetPreds()) { setCommonExceptionHandlers.RetainAll(pred.GetSuccExceptions()); } bool is_outside_range = false; HashSet <BasicBlock> setPredecessors = new HashSet <BasicBlock>(start.GetPreds()); // replace start with next foreach (BasicBlock pred in setPredecessors) { pred.ReplaceSuccessor(start, next); } HashSet <BasicBlock> setBlocks = area.sample; HashSet <ExceptionRangeCFG> setCommonRemovedExceptionRanges = null; // remove all the blocks inbetween foreach (BasicBlock block in setBlocks) { // artificial basic blocks (those resulted from splitting) // can belong to more than one area if (graph.GetBlocks().ContainsKey(block.id)) { if (!block.GetSuccExceptions().ContainsAll(setCommonExceptionHandlers)) { is_outside_range = true; } HashSet <ExceptionRangeCFG> setRemovedExceptionRanges = new HashSet <ExceptionRangeCFG >(); foreach (BasicBlock handler in block.GetSuccExceptions()) { setRemovedExceptionRanges.Add(graph.GetExceptionRange(handler, block)); } if (setCommonRemovedExceptionRanges == null) { setCommonRemovedExceptionRanges = setRemovedExceptionRanges; } else { setCommonRemovedExceptionRanges.RetainAll(setRemovedExceptionRanges); } // shift extern edges on splitted blocks if (block.GetSeq().IsEmpty() && block.GetSuccs().Count == 1) { BasicBlock succs = block.GetSuccs()[0]; foreach (BasicBlock pred in new List <BasicBlock>(block.GetPreds())) { if (!setBlocks.Contains(pred)) { pred.ReplaceSuccessor(block, succs); } } if (graph.GetFirst() == block) { graph.SetFirst(succs); } } graph.RemoveBlock(block); } } if (is_outside_range) { // new empty block BasicBlock emptyblock = new BasicBlock(++graph.last_id); graph.GetBlocks().AddWithKey(emptyblock, emptyblock.id); // add to ranges if necessary foreach (ExceptionRangeCFG range in setCommonRemovedExceptionRanges) { emptyblock.AddSuccessorException(range.GetHandler()); range.GetProtectedRange().Add(emptyblock); } // insert between predecessors and next emptyblock.AddSuccessor(next); foreach (BasicBlock pred in setPredecessors) { pred.ReplaceSuccessor(next, emptyblock); } } }
private bool CompareBasicBlocksEx(ControlFlowGraph graph, BasicBlock pattern, BasicBlock sample, int type, int finallytype, List <int[]> lstStoreVars) { InstructionSequence seqPattern = pattern.GetSeq(); InstructionSequence seqSample = sample.GetSeq(); if (type != 0) { seqPattern = seqPattern.Clone(); if ((type & 1) > 0) { // first if (finallytype > 0) { seqPattern.RemoveInstruction(0); } } if ((type & 2) > 0) { // last if (finallytype == 0 || finallytype == 2) { seqPattern.RemoveLast(); } if (finallytype == 2) { seqPattern.RemoveLast(); } } } if (seqPattern.Length() > seqSample.Length()) { return(false); } for (int i = 0; i < seqPattern.Length(); i++) { Instruction instrPattern = seqPattern.GetInstr(i); Instruction instrSample = seqSample.GetInstr(i); // compare instructions with respect to jumps if (!EqualInstructions(instrPattern, instrSample, lstStoreVars)) { return(false); } } if (seqPattern.Length() < seqSample.Length()) { // split in two blocks SimpleInstructionSequence seq = new SimpleInstructionSequence(); LinkedList <int> oldOffsets = new LinkedList <int>(); for (int i = seqSample.Length() - 1; i >= seqPattern.Length(); i--) { seq.AddInstruction(0, seqSample.GetInstr(i), -1); oldOffsets.AddFirst(sample.GetOldOffset(i)); seqSample.RemoveInstruction(i); } BasicBlock newblock = new BasicBlock(++graph.last_id); newblock.SetSeq(seq); Sharpen.Collections.AddAll(newblock.GetInstrOldOffsets(), oldOffsets); List <BasicBlock> lstTemp = new List <BasicBlock>(sample.GetSuccs()); // move successors foreach (BasicBlock suc in lstTemp) { sample.RemoveSuccessor(suc); newblock.AddSuccessor(suc); } sample.AddSuccessor(newblock); graph.GetBlocks().AddWithKey(newblock, newblock.id); HashSet <BasicBlock> setFinallyExits = graph.GetFinallyExits(); if (setFinallyExits.Contains(sample)) { setFinallyExits.Remove(sample); setFinallyExits.Add(newblock); } // copy exception edges and extend protected ranges for (int j = 0; j < sample.GetSuccExceptions().Count; j++) { BasicBlock hd = sample.GetSuccExceptions()[j]; newblock.AddSuccessorException(hd); ExceptionRangeCFG range = graph.GetExceptionRange(hd, sample); range.GetProtectedRange().Add(newblock); } } return(true); }
private static void InsertSemaphore(ControlFlowGraph graph, HashSet <BasicBlock> setTry , BasicBlock head, BasicBlock handler, int var, FinallyProcessor.Record information , int bytecode_version) { HashSet <BasicBlock> setCopy = new HashSet <BasicBlock>(setTry); int finallytype = information.firstCode; Dictionary <BasicBlock, bool> mapLast = information.mapLast; // first and last statements RemoveExceptionInstructionsEx(handler, 1, finallytype); foreach (KeyValuePair <BasicBlock, bool> entry in mapLast) { BasicBlock last = entry.Key; if (entry.Value) { RemoveExceptionInstructionsEx(last, 2, finallytype); graph.GetFinallyExits().Add(last); } } // disable semaphore at statement exit points foreach (BasicBlock block in setTry) { List <BasicBlock> lstSucc = block.GetSuccs(); foreach (BasicBlock dest in lstSucc) { // break out if (dest != graph.GetLast() && !setCopy.Contains(dest)) { // disable semaphore SimpleInstructionSequence seq = new SimpleInstructionSequence(); seq.AddInstruction(Instruction.Create(ICodeConstants.opc_bipush, false, ICodeConstants .Group_General, bytecode_version, new int[] { 0 }), -1); seq.AddInstruction(Instruction.Create(ICodeConstants.opc_istore, false, ICodeConstants .Group_General, bytecode_version, new int[] { var }), -1); // build a separate block BasicBlock newblock = new BasicBlock(++graph.last_id); newblock.SetSeq(seq); // insert between block and dest block.ReplaceSuccessor(dest, newblock); newblock.AddSuccessor(dest); setCopy.Add(newblock); graph.GetBlocks().AddWithKey(newblock, newblock.id); // exception ranges // FIXME: special case synchronized // copy exception edges and extend protected ranges for (int j = 0; j < block.GetSuccExceptions().Count; j++) { BasicBlock hd = block.GetSuccExceptions()[j]; newblock.AddSuccessorException(hd); ExceptionRangeCFG range = graph.GetExceptionRange(hd, block); range.GetProtectedRange().Add(newblock); } } } } // enable semaphore at the statement entrance SimpleInstructionSequence seq_1 = new SimpleInstructionSequence(); seq_1.AddInstruction(Instruction.Create(ICodeConstants.opc_bipush, false, ICodeConstants .Group_General, bytecode_version, new int[] { 1 }), -1); seq_1.AddInstruction(Instruction.Create(ICodeConstants.opc_istore, false, ICodeConstants .Group_General, bytecode_version, new int[] { var }), -1); BasicBlock newhead = new BasicBlock(++graph.last_id); newhead.SetSeq(seq_1); InsertBlockBefore(graph, head, newhead); // initialize semaphor with false seq_1 = new SimpleInstructionSequence(); seq_1.AddInstruction(Instruction.Create(ICodeConstants.opc_bipush, false, ICodeConstants .Group_General, bytecode_version, new int[] { 0 }), -1); seq_1.AddInstruction(Instruction.Create(ICodeConstants.opc_istore, false, ICodeConstants .Group_General, bytecode_version, new int[] { var }), -1); BasicBlock newheadinit = new BasicBlock(++graph.last_id); newheadinit.SetSeq(seq_1); InsertBlockBefore(graph, newhead, newheadinit); setCopy.Add(newhead); setCopy.Add(newheadinit); foreach (BasicBlock hd in new HashSet <BasicBlock>(newheadinit.GetSuccExceptions() )) { ExceptionRangeCFG range = graph.GetExceptionRange(hd, newheadinit); if (setCopy.ContainsAll(range.GetProtectedRange())) { newheadinit.RemoveSuccessorException(hd); range.GetProtectedRange().Remove(newheadinit); } } }