Пример #1
0
 internal bool getLdcValue(Instr instr, out int value)
 {
     if (Code.Ldc_I4_0 <= instr.OpCode.Code && instr.OpCode.Code <= Code.Ldc_I4_8)
     {
         value = instr.OpCode.Code - Code.Ldc_I4_0;
     }
     else if (instr.OpCode.Code == Code.Ldc_I4)
     {
         value = (int)instr.Operand;
     }
     else if (instr.OpCode.Code == Code.Ldc_I4_S)
     {
         value = (sbyte)instr.Operand;
     }
     else if (instr.OpCode.Code == Code.Ldc_I4_M1)
     {
         value = -1;
     }
     else
     {
         value = 0;
         return(false);
     }
     return(true);
 }
Пример #2
0
        // Returns the variable or null if it's not a ldloc/stloc instruction
        public static VariableDefinition getLocalVar(IList<VariableDefinition> locals, Instr instr)
        {
            switch (instr.OpCode.Code) {
            case Code.Ldloc:
            case Code.Ldloc_S:
            case Code.Stloc:
            case Code.Stloc_S:
                return (VariableDefinition)instr.Operand;

            case Code.Ldloc_0:
            case Code.Ldloc_1:
            case Code.Ldloc_2:
            case Code.Ldloc_3:
                return locals[instr.OpCode.Code - Code.Ldloc_0];

            case Code.Stloc_0:
            case Code.Stloc_1:
            case Code.Stloc_2:
            case Code.Stloc_3:
                return locals[instr.OpCode.Code - Code.Stloc_0];

            default:
                return null;
            }
        }
Пример #3
0
 static bool checkStloc(IList<VariableDefinition> locals, Instr instr, VariableDefinition local)
 {
     if (!instr.isStloc())
         return false;
     if (Instr.getLocalVar(locals, instr) != local)
         return false;
     return true;
 }
 static bool checkStloc(IList<Local> locals, Instr instr, Local local)
 {
     if (!instr.isStloc())
         return false;
     if (Instr.getLocalVar(locals, instr) != local)
         return false;
     return true;
 }
Пример #5
0
 public bool CanAppend(Block other)
 {
     if (other == null || other == this || GetOnlyTarget() != other)
     {
         return(false);
     }
     // If it's eg. a leave, then don't merge them since it clears the stack.
     return(LastInstr.IsBr() || Instr.IsFallThrough(LastInstr.OpCode));
 }
 static bool checkCall(Instr instr, string returnType, string parameters)
 {
     if (instr.OpCode.Code != Code.Call && instr.OpCode.Code != Code.Callvirt)
         return false;
     var calledMethod = instr.Operand as IMethod;
     if (calledMethod == null)
         return false;
     return DotNetUtils.isMethod(calledMethod, returnType, parameters);
 }
 static bool checkCall(Instr instr, string methodFullname)
 {
     if (instr.OpCode.Code != Code.Call && instr.OpCode.Code != Code.Callvirt)
         return false;
     var calledMethod = instr.Operand as IMethod;
     if (calledMethod == null)
         return false;
     return calledMethod.ToString() == methodFullname;
 }
Пример #8
0
		public void Deobfuscate(Blocks blocks) {
			foreach (var block in blocks.MethodBlocks.GetAllBlocks()) {
				var instrs = block.Instructions;
				for (int i = 0; i < instrs.Count - 1; i++) {
					var first = instrs[i];
					var second = instrs[i + 1];
					if (first.OpCode.Code == Code.Not && second.OpCode.Code == Code.Neg) {
						// It's increment
						instrs[i] = new Instr(OpCodes.Ldc_I4_1.ToInstruction());
						instrs[i + 1] = new Instr(OpCodes.Add.ToInstruction());
					}
					else if (first.OpCode.Code == Code.Neg && second.OpCode.Code == Code.Not) {
						// It's decrement
						instrs[i] = new Instr(OpCodes.Ldc_I4_1.ToInstruction());
						instrs[i + 1] = new Instr(OpCodes.Sub.ToInstruction());
					}
				}
			}
		}
Пример #9
0
        // Fix all branches so they now point to a Block, and not an Instruction. The
        // block's Targets field is updated, not the Instruction's Operand field.
        // Also update Block.FallThrough with next Block if last instr falls through.
        void fixBranchTargets(List <Block> instrToBlock, List <Block> allBlocks)
        {
            for (var i = 0; i < allBlocks.Count; i++)
            {
                var block     = allBlocks[i];
                var lastInstr = block.LastInstr;

                switch (lastInstr.OpCode.OperandType)
                {
                case OperandType.ShortInlineBrTarget:
                case OperandType.InlineBrTarget:
                    var targetInstr = lastInstr.Operand as Instruction;
                    if (targetInstr != null)
                    {
                        block.Targets = new List <Block> {
                            instrToBlock[instrToIndex[targetInstr]]
                        }
                    }
                    ;
                    break;

                case OperandType.InlineSwitch:
                    var switchTargets    = (Instruction[])lastInstr.Operand;
                    var newSwitchTargets = new List <Block>();
                    block.Targets = newSwitchTargets;
                    foreach (var target in switchTargets)
                    {
                        if (target != null)
                        {
                            newSwitchTargets.Add(instrToBlock[instrToIndex[target]]);
                        }
                    }
                    break;
                }

                if (i + 1 < allBlocks.Count && Instr.isFallThrough(lastInstr.OpCode))
                {
                    block.FallThrough = allBlocks[i + 1];
                }
            }
        }
Пример #10
0
 // Returns the variable or null if it's not a ldloc/stloc instruction. It does not return
 // a local variable if it's a ldloca/ldloca.s instruction.
 public static VariableDefinition getLocalVar(IList<VariableDefinition> locals, Instr instr)
 {
     return DotNetUtils.getLocalVar(locals, instr.Instruction);
 }
Пример #11
0
 // Returns the variable or null if it's not a ldloc/stloc instruction. It does not return
 // a local variable if it's a ldloca/ldloca.s instruction.
 public static VariableDefinition getLocalVar(IList <VariableDefinition> locals, Instr instr)
 {
     return(DotNetUtils.getLocalVar(locals, instr.Instruction));
 }
Пример #12
0
        public void deobfuscate(Blocks blocks)
        {
            foreach (var block in blocks.MethodBlocks.getAllBlocks()) {
                var instrs = block.Instructions;
                for (int i = 0; i < instrs.Count; i++) {
                    var instr = instrs[i];

                    if (instr.OpCode.Code != Code.Ldsfld)
                        continue;

                    var field = instr.Operand as FieldReference;
                    if (field == null)
                        continue;
                    var info = stringInfos.find(field);
                    if (info == null)
                        continue;
                    var decrypted = decrypt(info);

                    instrs[i] = new Instr(Instruction.Create(OpCodes.Ldstr, decrypted));
                    Log.v("Decrypted string: {0}", Utils.toCsharpString(decrypted));
                }
            }
        }
Пример #13
0
		static bool CheckCall(Instr instr, IMethod expectedMethod) {
			if (instr.OpCode.Code != Code.Call && instr.OpCode.Code != Code.Callvirt)
				return false;
			var calledMethod = instr.Operand as IMethod;
			if (calledMethod == null)
				return false;
			return MethodEqualityComparer.CompareDeclaringTypes.Equals(calledMethod, expectedMethod);
		}
Пример #14
0
        public int OptimizeLocals()
        {
            if (locals.Count == 0)
            {
                return(0);
            }

            var usedLocals = new Dictionary <Local, List <LocalVariableInfo> >();

            foreach (var block in methodBlocks.GetAllBlocks())
            {
                for (int i = 0; i < block.Instructions.Count; i++)
                {
                    var   instr = block.Instructions[i];
                    Local local;
                    switch (instr.OpCode.Code)
                    {
                    case Code.Ldloc:
                    case Code.Ldloc_S:
                    case Code.Ldloc_0:
                    case Code.Ldloc_1:
                    case Code.Ldloc_2:
                    case Code.Ldloc_3:
                    case Code.Stloc:
                    case Code.Stloc_S:
                    case Code.Stloc_0:
                    case Code.Stloc_1:
                    case Code.Stloc_2:
                    case Code.Stloc_3:
                        local = Instr.GetLocalVar(locals, instr);
                        break;

                    case Code.Ldloca_S:
                    case Code.Ldloca:
                        local = (Local)instr.Operand;
                        break;

                    default:
                        local = null;
                        break;
                    }
                    if (local == null)
                    {
                        continue;
                    }

                    List <LocalVariableInfo> list;
                    if (!usedLocals.TryGetValue(local, out list))
                    {
                        usedLocals[local] = list = new List <LocalVariableInfo>();
                    }
                    list.Add(new LocalVariableInfo(block, i));
                    if (usedLocals.Count == locals.Count)
                    {
                        return(0);
                    }
                }
            }

            int newIndex      = -1;
            var newLocals     = new List <Local>(usedLocals.Count);
            var newLocalsDict = new Dictionary <Local, bool>(usedLocals.Count);

            foreach (var local in usedLocals.Keys)
            {
                newIndex++;
                newLocals.Add(local);
                newLocalsDict[local] = true;
                foreach (var info in usedLocals[local])
                {
                    info.block.Instructions[info.index] = new Instr(OptimizeLocalInstr(info.block.Instructions[info.index], local, (uint)newIndex));
                }
            }

            // We can't remove all locals. Locals that reference another assembly will
            // cause the CLR to load that assembly before the method is executed if it
            // hasn't been loaded yet. This is a side effect the program may depend on.
            // At least one program has this dependency and will crash if we remove the
            // unused local. This took a while to figure out...
            var keptAssemblies = new Dictionary <string, bool>(StringComparer.Ordinal);

            foreach (var local in locals)
            {
                if (newLocalsDict.ContainsKey(local))
                {
                    continue;
                }
                var defAsm = local.Type.DefinitionAssembly;
                if (defAsm == null)
                {
                    continue;                           // eg. fnptr
                }
                if (defAsm == method.DeclaringType.Module.Assembly)
                {
                    continue;                           // this assembly is always loaded
                }
                if (defAsm.IsCorLib())
                {
                    continue;                           // mscorlib is always loaded
                }
                var asmName = defAsm.FullName;
                if (keptAssemblies.ContainsKey(asmName))
                {
                    continue;
                }
                keptAssemblies[asmName] = true;
                newLocals.Add(local);
            }

            int numRemoved = locals.Count - newLocals.Count;

            locals.Clear();
            foreach (var local in newLocals)
            {
                locals.Add(local);
            }
            return(numRemoved);
        }
Пример #15
0
        void layOutInstructions(out IList<Instruction> allInstructions, out IList<ExceptionHandler> allExceptionHandlers)
        {
            allInstructions = new List<Instruction>();
            allExceptionHandlers = new List<ExceptionHandler>();

            var blockInfos = new List<BlockInfo>();
            for (int i = 0; i < blocks.Count; i++) {
                var block = blocks[i];

                int startIndex = allInstructions.Count;
                for (int j = 0; j < block.Instructions.Count - 1; j++)
                    allInstructions.Add(block.Instructions[j].Instruction);

                if (block.Targets != null) {
                    var targets = new List<Instr>();
                    foreach (var target in block.Targets)
                        targets.Add(target.FirstInstr);
                    block.LastInstr.updateTargets(targets);
                }
                allInstructions.Add(block.LastInstr.Instruction);

                var next = i + 1 < blocks.Count ? blocks[i + 1] : null;

                // If eg. ble next, then change it to bgt XYZ and fall through to next.
                if (block.Targets != null && block.canFlipConditionalBranch() && block.Targets[0] == next) {
                    block.flipConditionalBranch();
                    block.LastInstr.updateTargets(new List<Instr> { block.Targets[0].FirstInstr });
                }
                else if (block.FallThrough != null && block.FallThrough != next) {
                    var instr = new Instr(Instruction.Create(OpCodes.Br, block.FallThrough.FirstInstr.Instruction));
                    instr.updateTargets(new List<Instr> { block.FallThrough.FirstInstr });
                    allInstructions.Add(instr.Instruction);
                }

                int endIndex = allInstructions.Count - 1;

                blockInfos.Add(new BlockInfo(startIndex, endIndex));
            }

            foreach (var ex in exceptions) {
                var tryStart = blockInfos[ex.tryStart].start;
                var tryEnd = blockInfos[ex.tryEnd].end;
                var filterStart = ex.filterStart == -1 ? -1 : blockInfos[ex.filterStart].start;
                var handlerStart = blockInfos[ex.handlerStart].start;
                var handlerEnd = blockInfos[ex.handlerEnd].end;

                var eh = new ExceptionHandler(ex.handlerType);
                eh.CatchType = ex.catchType;
                eh.TryStart = getInstruction(allInstructions, tryStart);
                eh.TryEnd = getInstruction(allInstructions, tryEnd + 1);
                eh.FilterStart = filterStart == -1 ? null : getInstruction(allInstructions, filterStart);
                eh.HandlerStart = getInstruction(allInstructions, handlerStart);
                eh.HandlerEnd = getInstruction(allInstructions, handlerEnd + 1);

                allExceptionHandlers.Add(eh);
            }
        }
Пример #16
0
        bool Deobfuscate1(Block block, int i)
        {
            var instrs = block.Instructions;
            if (i >= instrs.Count - 2)
                return false;

            var ldloc = instrs[i];
            if (!ldloc.IsLdloc())
                return false;
            var local = ldloc.Instruction.GetLocal(Blocks.Locals);
            if (local == null)
                return false;
            ArrayBlockState.FieldInfo info;
            if (!localToInfo.TryGetValue(local, out info))
                return false;

            var ldci4 = instrs[i + 1];
            if (!ldci4.IsLdcI4())
                return false;

            var ldelem = instrs[i + 2];
            if (!IsLdelem(info, ldelem.OpCode.Code))
                return false;

            block.Remove(i, 3 - 1);
            instrs[i] = new Instr(Instruction.CreateLdcI4((int)info.ReadArrayElement(ldci4.GetLdcI4Value())));
            return true;
        }
Пример #17
0
        public int optimizeLocals()
        {
            if (locals.Count == 0)
            {
                return(0);
            }

            var usedLocals = new Dictionary <VariableDefinition, List <LocalVariableInfo> >();

            foreach (var block in methodBlocks.getAllBlocks())
            {
                for (int i = 0; i < block.Instructions.Count; i++)
                {
                    var instr = block.Instructions[i];
                    VariableDefinition local;
                    switch (instr.OpCode.Code)
                    {
                    case Code.Ldloc:
                    case Code.Ldloc_S:
                    case Code.Ldloc_0:
                    case Code.Ldloc_1:
                    case Code.Ldloc_2:
                    case Code.Ldloc_3:
                    case Code.Stloc:
                    case Code.Stloc_S:
                    case Code.Stloc_0:
                    case Code.Stloc_1:
                    case Code.Stloc_2:
                    case Code.Stloc_3:
                        local = Instr.getLocalVar(locals, instr);
                        break;

                    case Code.Ldloca_S:
                    case Code.Ldloca:
                        local = (VariableDefinition)instr.Operand;
                        break;

                    default:
                        local = null;
                        break;
                    }
                    if (local == null)
                    {
                        continue;
                    }

                    List <LocalVariableInfo> list;
                    if (!usedLocals.TryGetValue(local, out list))
                    {
                        usedLocals[local] = list = new List <LocalVariableInfo>();
                    }
                    list.Add(new LocalVariableInfo(block, i));
                    if (usedLocals.Count == locals.Count)
                    {
                        return(0);
                    }
                }
            }

            int newIndex  = -1;
            var newLocals = new List <VariableDefinition>(usedLocals.Count);

            foreach (var local in usedLocals.Keys)
            {
                newIndex++;
                newLocals.Add(local);
                foreach (var info in usedLocals[local])
                {
                    info.block.Instructions[info.index] = new Instr(optimizeLocalInstr(info.block.Instructions[info.index], local, (uint)newIndex));
                }
            }

            int numRemoved = locals.Count - newLocals.Count;

            locals.Clear();
            foreach (var local in newLocals)
            {
                locals.Add(local);
            }
            return(numRemoved);
        }
Пример #18
0
		public void Deobfuscate(Blocks blocks) {
			foreach (var block in blocks.MethodBlocks.GetAllBlocks()) {
				var instrs = block.Instructions;
				for (int i = 0; i < instrs.Count; i++) {
					var instr = instrs[i];

					if (instr.OpCode.Code == Code.Call || instr.OpCode.Code == Code.Callvirt) {
						if (blocks.Method.DeclaringType == decrypterType)
							continue;
						var calledMethod = instr.Operand as IMethod;
						if (calledMethod != null && calledMethod.DeclaringType == decrypterType)
							canRemoveType = false;
					}
					else if (instr.OpCode.Code == Code.Ldsfld) {
						if (instr.OpCode.Code != Code.Ldsfld)
							continue;
						var field = instr.Operand as IField;
						if (field == null)
							continue;
						var decrypted = fieldToDecryptedString.Find(field);
						if (decrypted == null)
							continue;

						instrs[i] = new Instr(OpCodes.Ldstr.ToInstruction(decrypted));
						Logger.v("Decrypted string: {0}", Utils.ToCsharpString(decrypted));
					}
				}
			}
		}
Пример #19
0
        static Instruction optimizeLocalInstr(Instr instr, VariableDefinition local, uint newIndex)
        {
            switch (instr.OpCode.Code)
            {
            case Code.Ldloc:
            case Code.Ldloc_S:
            case Code.Ldloc_0:
            case Code.Ldloc_1:
            case Code.Ldloc_2:
            case Code.Ldloc_3:
                if (newIndex == 0)
                {
                    return(Instruction.Create(OpCodes.Ldloc_0));
                }
                if (newIndex == 1)
                {
                    return(Instruction.Create(OpCodes.Ldloc_1));
                }
                if (newIndex == 2)
                {
                    return(Instruction.Create(OpCodes.Ldloc_2));
                }
                if (newIndex == 3)
                {
                    return(Instruction.Create(OpCodes.Ldloc_3));
                }
                if (newIndex <= 0xFF)
                {
                    return(Instruction.Create(OpCodes.Ldloc_S, local));
                }
                return(Instruction.Create(OpCodes.Ldloc, local));

            case Code.Stloc:
            case Code.Stloc_S:
            case Code.Stloc_0:
            case Code.Stloc_1:
            case Code.Stloc_2:
            case Code.Stloc_3:
                if (newIndex == 0)
                {
                    return(Instruction.Create(OpCodes.Stloc_0));
                }
                if (newIndex == 1)
                {
                    return(Instruction.Create(OpCodes.Stloc_1));
                }
                if (newIndex == 2)
                {
                    return(Instruction.Create(OpCodes.Stloc_2));
                }
                if (newIndex == 3)
                {
                    return(Instruction.Create(OpCodes.Stloc_3));
                }
                if (newIndex <= 0xFF)
                {
                    return(Instruction.Create(OpCodes.Stloc_S, local));
                }
                return(Instruction.Create(OpCodes.Stloc, local));

            case Code.Ldloca_S:
            case Code.Ldloca:
                if (newIndex <= 0xFF)
                {
                    return(Instruction.Create(OpCodes.Ldloca_S, local));
                }
                return(Instruction.Create(OpCodes.Ldloca, local));

            default:
                throw new ApplicationException("Invalid ld/st local instruction");
            }
        }
        public void deobfuscate(Blocks blocks)
        {
            foreach (var block in blocks.MethodBlocks.getAllBlocks()) {
                var instrs = block.Instructions;
                for (int i = 0; i < instrs.Count; i++) {
                    var call = instrs[i];
                    if (call.OpCode.Code != Code.Call)
                        continue;
                    var calledMethod = call.Operand as MethodDefinition;
                    if (calledMethod == null)
                        continue;

                    MethodReference newMethod = null;
                    if (calledMethod == getManifestResourceStream1Method)
                        newMethod = Assembly_GetManifestResourceStream1;
                    else if (calledMethod == getManifestResourceStream2Method)
                        newMethod = Assembly_GetManifestResourceStream2;
                    else if (calledMethod == getManifestResourceNamesMethod)
                        newMethod = Assembly_GetManifestResourceNames;
                    if (newMethod == null)
                        continue;

                    instrs[i] = new Instr(Instruction.Create(OpCodes.Callvirt, newMethod));
                }
            }
        }
Пример #21
0
 public void add(Instr instr)
 {
     instructions.Add(instr);
 }
		public void Deobfuscate(Blocks blocks) {
			if (type == null)
				return;

			foreach (var block in blocks.MethodBlocks.GetAllBlocks()) {
				var instrs = block.Instructions;
				for (int i = 0; i < instrs.Count - 1; i++) {
					var instr = instrs[i];
					if (instr.OpCode.Code != Code.Ldc_I4)
						continue;
					var call = instrs[i + 1];
					if (call.OpCode.Code != Code.Call)
						continue;
					var method = call.Operand as IMethod;
					if (method == null)
						continue;
					if (!new SigComparer().Equals(type, method.DeclaringType))
						continue;
					var methodDef = DotNetUtils.GetMethod(module, method);
					if (methodDef == null)
						continue;
					if (methodDef != typeMethod && methodDef != fieldMethod)
						continue;

					uint token = (uint)(int)instrs[i].Operand;
					instrs[i] = new Instr(OpCodes.Nop.ToInstruction());
					instrs[i + 1] = new Instr(new Instruction(OpCodes.Ldtoken, module.ResolveToken(token) as ITokenOperand));
				}
			}
		}
Пример #23
0
        bool Deobfuscate2(Block block, int i)
        {
            var instrs = block.Instructions;
            if (i >= instrs.Count - 2)
                return false;

            var ldsfld = instrs[i];
            if (ldsfld.OpCode.Code != Code.Ldsfld)
                return false;
            var info = arrayBlockState.GetFieldInfo(ldsfld.Operand as IField);
            if (info == null)
                return false;

            var ldci4 = instrs[i + 1];
            if (!ldci4.IsLdcI4())
                return false;

            var ldelem = instrs[i + 2];
            if (!IsLdelem(info, ldelem.OpCode.Code))
                return false;

            block.Remove(i, 3 - 1);
            instrs[i] = new Instr(Instruction.CreateLdcI4((int)info.ReadArrayElement(ldci4.GetLdcI4Value())));
            return true;
        }
Пример #24
0
 // Returns the variable or null if it's not a ldloc/stloc instruction. It does not return
 // a local variable if it's a ldloca/ldloca.s instruction.
 public static Local GetLocalVar(IList <Local> locals, Instr instr)
 {
     return(instr.Instruction.GetLocal(locals));
 }
Пример #25
0
		// Returns the variable or null if it's not a ldloc/stloc instruction. It does not return
		// a local variable if it's a ldloca/ldloca.s instruction.
		public static Local GetLocalVar(IList<Local> locals, Instr instr) {
			return instr.Instruction.GetLocal(locals);
		}
		public void Deobfuscate(Blocks blocks) {
			if (decrypter == null)
				return;
			foreach (var block in blocks.MethodBlocks.GetAllBlocks()) {
				var instrs = block.Instructions;
				for (int i = 0; i < instrs.Count; i++) {
					var instr = instrs[i];

					if (instr.OpCode.Code != Code.Ldsfld)
						continue;

					var field = instr.Operand as IField;
					if (field == null)
						continue;
					var info = stringInfos.Find(field);
					if (info == null)
						continue;
					var decrypted = Decrypt(info);

					instrs[i] = new Instr(OpCodes.Ldstr.ToInstruction(decrypted));
					Logger.v("Decrypted string: {0}", Utils.ToCsharpString(decrypted));
				}
			}
		}
Пример #27
0
        static Instruction optimizeLocalInstr(Instr instr, VariableDefinition local, uint newIndex)
        {
            switch (instr.OpCode.Code) {
            case Code.Ldloc:
            case Code.Ldloc_S:
            case Code.Ldloc_0:
            case Code.Ldloc_1:
            case Code.Ldloc_2:
            case Code.Ldloc_3:
                if (newIndex == 0)
                    return Instruction.Create(OpCodes.Ldloc_0);
                if (newIndex == 1)
                    return Instruction.Create(OpCodes.Ldloc_1);
                if (newIndex == 2)
                    return Instruction.Create(OpCodes.Ldloc_2);
                if (newIndex == 3)
                    return Instruction.Create(OpCodes.Ldloc_3);
                if (newIndex <= 0xFF)
                    return Instruction.Create(OpCodes.Ldloc_S, local);
                return Instruction.Create(OpCodes.Ldloc, local);

            case Code.Stloc:
            case Code.Stloc_S:
            case Code.Stloc_0:
            case Code.Stloc_1:
            case Code.Stloc_2:
            case Code.Stloc_3:
                if (newIndex == 0)
                    return Instruction.Create(OpCodes.Stloc_0);
                if (newIndex == 1)
                    return Instruction.Create(OpCodes.Stloc_1);
                if (newIndex == 2)
                    return Instruction.Create(OpCodes.Stloc_2);
                if (newIndex == 3)
                    return Instruction.Create(OpCodes.Stloc_3);
                if (newIndex <= 0xFF)
                    return Instruction.Create(OpCodes.Stloc_S, local);
                return Instruction.Create(OpCodes.Stloc, local);

            case Code.Ldloca_S:
            case Code.Ldloca:
                if (newIndex <= 0xFF)
                    return Instruction.Create(OpCodes.Ldloca_S, local);
                return Instruction.Create(OpCodes.Ldloca, local);

            default:
                throw new ApplicationException("Invalid ld/st local instruction");
            }
        }
Пример #28
0
 public void Add(Instr instr)
 {
     instructions.Add(instr);
 }
Пример #29
0
		static bool CheckLdloc(IList<Local> locals, Instr instr, Local local) {
			if (!instr.IsLdloc())
				return false;
			if (Instr.GetLocalVar(locals, instr) != local)
				return false;
			return true;
		}
Пример #30
0
        public void deobfuscate(Blocks blocks)
        {
            if (type == null)
                return;

            foreach (var block in blocks.MethodBlocks.getAllBlocks()) {
                var instrs = block.Instructions;
                for (int i = 0; i < instrs.Count - 1; i++) {
                    var instr = instrs[i];
                    if (instr.OpCode.Code != Code.Ldc_I4)
                        continue;
                    var call = instrs[i + 1];
                    if (call.OpCode.Code != Code.Call)
                        continue;
                    var method = call.Operand as MethodReference;
                    if (method == null)
                        continue;
                    if (!MemberReferenceHelper.compareTypes(type, method.DeclaringType))
                        continue;
                    var methodDef = DotNetUtils.getMethod(module, method);
                    if (methodDef == null)
                        continue;
                    if (methodDef != typeMethod && methodDef != fieldMethod)
                        continue;

                    int token = (int)instrs[i].Operand;
                    instrs[i] = new Instr(Instruction.Create(OpCodes.Nop));
                    instrs[i + 1] = new Instr(new Instruction(OpCodes.Ldtoken, module.LookupToken(token) as MemberReference));
                }
            }
        }
Пример #31
0
 static bool checkCall(Instr instr, string methodFullName)
 {
     if (instr.OpCode.Code != Code.Call && instr.OpCode.Code != Code.Callvirt)
         return false;
     var calledMethod = instr.Operand as MethodReference;
     if (calledMethod == null)
         return false;
     return calledMethod.FullName == methodFullName;
 }
Пример #32
0
        void fixTypeofDecrypterInstructions(Blocks blocks)
        {
            var type = getDecrypterType();
            if (type == null)
                return;

            foreach (var block in blocks.MethodBlocks.getAllBlocks()) {
                var instructions = block.Instructions;
                for (int i = 0; i < instructions.Count; i++) {
                    var instr = instructions[i];
                    if (instr.OpCode.Code != Code.Ldtoken)
                        continue;
                    if (!MemberReferenceHelper.compareTypes(type, instr.Operand as TypeReference))
                        continue;
                    instructions[i] = new Instr(Instruction.Create(OpCodes.Ldtoken, blocks.Method.DeclaringType));
                }
            }
        }
Пример #33
0
 static bool checkCall(Instr instr, MethodReference expectedMethod)
 {
     if (instr.OpCode.Code != Code.Call && instr.OpCode.Code != Code.Callvirt)
         return false;
     var calledMethod = instr.Operand as MethodReference;
     if (calledMethod == null)
         return false;
     return MemberReferenceHelper.compareMethodReferenceAndDeclaringType(calledMethod, expectedMethod);
 }
Пример #34
0
        void layOutInstructions(out IList <Instruction> allInstructions, out IList <ExceptionHandler> allExceptionHandlers)
        {
            allInstructions      = new List <Instruction>();
            allExceptionHandlers = new List <ExceptionHandler>();

            var blockInfos = new List <BlockInfo>();

            for (int i = 0; i < blocks.Count; i++)
            {
                var block = blocks[i];

                int startIndex = allInstructions.Count;
                for (int j = 0; j < block.Instructions.Count - 1; j++)
                {
                    allInstructions.Add(block.Instructions[j].Instruction);
                }

                if (block.Targets != null)
                {
                    var targets = new List <Instr>();
                    foreach (var target in block.Targets)
                    {
                        targets.Add(target.FirstInstr);
                    }
                    block.LastInstr.updateTargets(targets);
                }
                allInstructions.Add(block.LastInstr.Instruction);

                var next = i + 1 < blocks.Count ? blocks[i + 1] : null;

                // If eg. ble next, then change it to bgt XYZ and fall through to next.
                if (block.Targets != null && block.canFlipConditionalBranch() && block.Targets[0] == next)
                {
                    block.flipConditionalBranch();
                    block.LastInstr.updateTargets(new List <Instr> {
                        block.Targets[0].FirstInstr
                    });
                }
                else if (block.FallThrough != null && block.FallThrough != next)
                {
                    var instr = new Instr(OpCodes.Br.ToInstruction(block.FallThrough.FirstInstr.Instruction));
                    instr.updateTargets(new List <Instr> {
                        block.FallThrough.FirstInstr
                    });
                    allInstructions.Add(instr.Instruction);
                }

                int endIndex = allInstructions.Count - 1;

                blockInfos.Add(new BlockInfo(startIndex, endIndex));
            }

            foreach (var ex in exceptions)
            {
                var tryStart     = getBlockInfo(blockInfos, ex.tryStart).start;
                var tryEnd       = getBlockInfo(blockInfos, ex.tryEnd).end;
                var filterStart  = ex.filterStart == -1 ? -1 : getBlockInfo(blockInfos, ex.filterStart).start;
                var handlerStart = getBlockInfo(blockInfos, ex.handlerStart).start;
                var handlerEnd   = getBlockInfo(blockInfos, ex.handlerEnd).end;

                var eh = new ExceptionHandler(ex.handlerType);
                eh.CatchType    = ex.catchType;
                eh.TryStart     = getInstruction(allInstructions, tryStart);
                eh.TryEnd       = getInstruction(allInstructions, tryEnd + 1);
                eh.FilterStart  = filterStart == -1 ? null : getInstruction(allInstructions, filterStart);
                eh.HandlerStart = getInstruction(allInstructions, handlerStart);
                eh.HandlerEnd   = getInstruction(allInstructions, handlerEnd + 1);

                allExceptionHandlers.Add(eh);
            }
        }
Пример #35
0
		void FixTypeofDecrypterInstructions(Blocks blocks) {
			var type = GetDecrypterType();
			if (type == null)
				return;

			foreach (var block in blocks.MethodBlocks.GetAllBlocks()) {
				var instructions = block.Instructions;
				for (int i = 0; i < instructions.Count; i++) {
					var instr = instructions[i];
					if (instr.OpCode.Code != Code.Ldtoken)
						continue;
					if (!new SigComparer().Equals(type, instr.Operand as ITypeDefOrRef))
						continue;
					instructions[i] = new Instr(OpCodes.Ldtoken.ToInstruction(blocks.Method.DeclaringType));
				}
			}
		}
Пример #36
0
        static Instruction OptimizeLocalInstr(Instr instr, Local local, uint newIndex)
        {
            switch (instr.OpCode.Code)
            {
            case Code.Ldloc:
            case Code.Ldloc_S:
            case Code.Ldloc_0:
            case Code.Ldloc_1:
            case Code.Ldloc_2:
            case Code.Ldloc_3:
                if (newIndex == 0)
                {
                    return(OpCodes.Ldloc_0.ToInstruction());
                }
                if (newIndex == 1)
                {
                    return(OpCodes.Ldloc_1.ToInstruction());
                }
                if (newIndex == 2)
                {
                    return(OpCodes.Ldloc_2.ToInstruction());
                }
                if (newIndex == 3)
                {
                    return(OpCodes.Ldloc_3.ToInstruction());
                }
                if (newIndex <= 0xFF)
                {
                    return(OpCodes.Ldloc_S.ToInstruction(local));
                }
                return(OpCodes.Ldloc.ToInstruction(local));

            case Code.Stloc:
            case Code.Stloc_S:
            case Code.Stloc_0:
            case Code.Stloc_1:
            case Code.Stloc_2:
            case Code.Stloc_3:
                if (newIndex == 0)
                {
                    return(OpCodes.Stloc_0.ToInstruction());
                }
                if (newIndex == 1)
                {
                    return(OpCodes.Stloc_1.ToInstruction());
                }
                if (newIndex == 2)
                {
                    return(OpCodes.Stloc_2.ToInstruction());
                }
                if (newIndex == 3)
                {
                    return(OpCodes.Stloc_3.ToInstruction());
                }
                if (newIndex <= 0xFF)
                {
                    return(OpCodes.Stloc_S.ToInstruction(local));
                }
                return(OpCodes.Stloc.ToInstruction(local));

            case Code.Ldloca_S:
            case Code.Ldloca:
                if (newIndex <= 0xFF)
                {
                    return(OpCodes.Ldloca_S.ToInstruction(local));
                }
                return(OpCodes.Ldloca.ToInstruction(local));

            default:
                throw new ApplicationException("Invalid ld/st local instruction");
            }
        }
		static bool IsCast(Instr instr) {
			return instr.OpCode.Code == Code.Castclass || instr.OpCode.Code == Code.Isinst;
		}
Пример #38
0
		public void Deobfuscate(Blocks blocks) {
			if (oldToNewMethod.Count == 0)
				return;
			foreach (var block in blocks.MethodBlocks.GetAllBlocks()) {
				var instrs = block.Instructions;
				for (int i = 0; i < instrs.Count; i++) {
					var call = instrs[i];
					if (call.OpCode.Code != Code.Call)
						continue;
					var calledMethod = call.Operand as MethodDef;
					if (calledMethod == null)
						continue;

					var newMethodInfo = oldToNewMethod.Find(calledMethod);
					if (newMethodInfo == null)
						continue;

					instrs[i] = new Instr(Instruction.Create(newMethodInfo.opCode, newMethodInfo.method));
				}
			}
		}
		static ITypeDefOrRef GetCastType(Instr instr) {
			if (!IsCast(instr))
				return null;
			return instr.Operand as ITypeDefOrRef;
		}
Пример #40
0
		static Instruction OptimizeLocalInstr(Instr instr, Local local, uint newIndex) {
			switch (instr.OpCode.Code) {
			case Code.Ldloc:
			case Code.Ldloc_S:
			case Code.Ldloc_0:
			case Code.Ldloc_1:
			case Code.Ldloc_2:
			case Code.Ldloc_3:
				if (newIndex == 0)
					return OpCodes.Ldloc_0.ToInstruction();
				if (newIndex == 1)
					return OpCodes.Ldloc_1.ToInstruction();
				if (newIndex == 2)
					return OpCodes.Ldloc_2.ToInstruction();
				if (newIndex == 3)
					return OpCodes.Ldloc_3.ToInstruction();
				if (newIndex <= 0xFF)
					return OpCodes.Ldloc_S.ToInstruction(local);
				return OpCodes.Ldloc.ToInstruction(local);

			case Code.Stloc:
			case Code.Stloc_S:
			case Code.Stloc_0:
			case Code.Stloc_1:
			case Code.Stloc_2:
			case Code.Stloc_3:
				if (newIndex == 0)
					return OpCodes.Stloc_0.ToInstruction();
				if (newIndex == 1)
					return OpCodes.Stloc_1.ToInstruction();
				if (newIndex == 2)
					return OpCodes.Stloc_2.ToInstruction();
				if (newIndex == 3)
					return OpCodes.Stloc_3.ToInstruction();
				if (newIndex <= 0xFF)
					return OpCodes.Stloc_S.ToInstruction(local);
				return OpCodes.Stloc.ToInstruction(local);

			case Code.Ldloca_S:
			case Code.Ldloca:
				if (newIndex <= 0xFF)
					return OpCodes.Ldloca_S.ToInstruction(local);
				return OpCodes.Ldloca.ToInstruction(local);

			default:
				throw new ApplicationException("Invalid ld/st local instruction");
			}
		}
Пример #41
0
 VariableDefinition getLocalVar(Instr instr)
 {
     return Instr.getLocalVar(blocks.Locals, instr);
 }