Ejemplo n.º 1
0
        bool isStLdlocBranch(Block switchBlock, bool isSwitch)
        {
            int numInstrs = 2 + (isSwitch ? 1 : 0);

            return(switchBlock.Instructions.Count == numInstrs &&
                   switchBlock.Instructions[0].isStloc() &&
                   switchBlock.Instructions[1].isLdloc() &&
                   Instr.getLocalVar(blocks.Locals, switchBlock.Instructions[0]) == Instr.getLocalVar(blocks.Locals, switchBlock.Instructions[1]));
        }
Ejemplo n.º 2
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);
 }
Ejemplo n.º 3
0
 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);
 }
Ejemplo n.º 4
0
        void findLoadStores()
        {
            foreach (var block in allBlocks)
            {
                foreach (var instr in block.Instructions)
                {
                    VariableDefinition local;
                    AccessFlags        flags;
                    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:
                        local = Instr.getLocalVar(blocks.Locals, instr);
                        flags = AccessFlags.Read;
                        break;

                    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(blocks.Locals, instr);
                        flags = AccessFlags.Write;
                        break;

                    case Code.Ldloca_S:
                    case Code.Ldloca:
                        local = instr.Operand as VariableDefinition;
                        flags = AccessFlags.Read | AccessFlags.Write;
                        break;

                    default:
                        local = null;
                        flags = AccessFlags.None;
                        break;
                    }

                    if (local == null)
                    {
                        continue;
                    }
                    localFlags[local.Index] |= flags;
                }
            }
        }
Ejemplo n.º 5
0
        protected override bool deobfuscate(Block block)
        {
            bool changed      = false;
            var  instructions = block.Instructions;

            for (int i = 0; i < instructions.Count; i++)
            {
                var instr = instructions[i];
                switch (instr.OpCode.Code)
                {
                // Xenocode generates stloc + ldloc (bool). Replace it with dup + stloc. It will eventually
                // become dup + pop and be removed.
                case Code.Stloc:
                case Code.Stloc_S:
                case Code.Stloc_0:
                case Code.Stloc_1:
                case Code.Stloc_2:
                case Code.Stloc_3:
                    if (i + 1 >= instructions.Count)
                    {
                        break;
                    }
                    if (!instructions[i + 1].isLdloc())
                    {
                        break;
                    }
                    var local = Instr.getLocalVar(locals, instr);
                    if (local.Type.ElementType != ElementType.Boolean)
                    {
                        continue;
                    }
                    if (local != Instr.getLocalVar(locals, instructions[i + 1]))
                    {
                        break;
                    }
                    instructions[i]     = new Instr(OpCodes.Dup.ToInstruction());
                    instructions[i + 1] = instr;
                    changed             = true;
                    break;

                default:
                    break;
                }
            }

            return(changed);
        }
Ejemplo n.º 6
0
        bool fix(Block block)
        {
            bool changed      = false;
            var  instructions = block.Instructions;

            for (int i = 0; i < instructions.Count; i++)
            {
                var instr = instructions[i];
                switch (instr.OpCode.Code)
                {
                // Xenocode generates stloc + ldloc (bool). Replace it with dup + stloc. It will eventually
                // become dup + pop and be removed.
                case Code.Stloc:
                case Code.Stloc_S:
                case Code.Stloc_0:
                case Code.Stloc_1:
                case Code.Stloc_2:
                case Code.Stloc_3:
                    if (i + 1 >= instructions.Count)
                    {
                        break;
                    }
                    if (!instructions[i + 1].isLdloc())
                    {
                        break;
                    }
                    var local = Instr.getLocalVar(locals, instr);
                    if (local.VariableType.FullName != "System.Boolean")
                    {
                        continue;
                    }
                    if (local != Instr.getLocalVar(locals, instructions[i + 1]))
                    {
                        break;
                    }
                    instructions[i]     = new Instr(Instruction.Create(OpCodes.Dup));
                    instructions[i + 1] = instr;
                    changed             = true;
                    break;

                default:
                    break;
                }
            }

            return(changed);
        }
Ejemplo n.º 7
0
        //		ldloc N
        //		br swblk
        // or
        //		stloc N
        //		ldloc N
        //		br swblk
        bool deobfuscateTos_Ldloc(IList <Block> switchTargets, Block switchFallThrough, Block block)
        {
            if (isLdlocBranch(block, false))
            {
                var switchVariable = Instr.getLocalVar(blocks.Locals, block.Instructions[0]);
                if (switchVariable == null)
                {
                    return(false);
                }
                return(deobfuscateLdloc(switchTargets, switchFallThrough, block, switchVariable));
            }
            else if (isStLdlocBranch(block, false))
            {
                return(deobfuscateStLdloc(switchTargets, switchFallThrough, block));
            }

            return(false);
        }
Ejemplo n.º 8
0
        bool isSwitchType2(Block switchBlock)
        {
            Local 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);
        }
Ejemplo n.º 9
0
        Dictionary <Local, int> getBccLocalConstants(Block block)
        {
            var dict   = new Dictionary <Local, 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 Local;
                    if (local != null)
                    {
                        dict.Remove(local);
                    }
                }
            }
            return(dict);
        }
Ejemplo n.º 10
0
        bool removeDeadStores()
        {
            bool changed = false;

            foreach (var block in allBlocks)
            {
                var instructions = block.Instructions;
                for (int i = 0; i < instructions.Count; i++)
                {
                    var instr = instructions[i];
                    VariableDefinition local;
                    switch (instr.OpCode.Code)
                    {
                    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(blocks.Locals, instr);
                        break;

                    default:
                        continue;
                    }

                    if (local == null)
                    {
                        continue;
                    }
                    if (!deadLocals[local.Index])
                    {
                        continue;
                    }
                    instructions[i] = new Instr(Instruction.Create(OpCodes.Pop));
                    changed         = true;
                }
            }

            return(changed);
        }
Ejemplo n.º 11
0
        bool deobfuscateStLdloc(Block switchBlock)
        {
            bool changed = false;

            var switchVariable = Instr.getLocalVar(blocks.Locals, switchBlock.Instructions[0]);

            if (switchVariable == null)
            {
                return(changed);
            }

            if (switchBlock.Targets == null)
            {
                return(changed);
            }
            var targets = new List <Block>(switchBlock.Targets);

            changed |= deobfuscateStLdloc(targets, switchBlock.FallThrough, switchBlock);

            return(changed);
        }
Ejemplo n.º 12
0
        void init()
        {
            foreach (var variable in locals)
            {
                variableToValue[variable] = new Variable();
            }

            foreach (var block in allBlocks)
            {
                for (int i = 0; i < block.Instructions.Count; i++)
                {
                    var instr = block.Instructions[i];

                    switch (instr.OpCode.Code)
                    {
                    case Code.Stloc:
                    case Code.Stloc_S:
                    case Code.Stloc_0:
                    case Code.Stloc_1:
                    case Code.Stloc_2:
                    case Code.Stloc_3:
                        var variable = Instr.getLocalVar(locals, instr);
                        var val      = variableToValue[variable];
                        val.addWrite();
                        object obj;
                        if (!getValue(block, i, out obj))
                        {
                            val.setUnknown();
                        }
                        val.Value = obj;
                        break;

                    default:
                        break;
                    }
                }
            }
        }
Ejemplo n.º 13
0
        public void deobfuscate(Blocks blocks)
        {
            var instrsToRemove = new List <int>();

            foreach (var block in blocks.MethodBlocks.getAllBlocks())
            {
                instrsToRemove.Clear();
                var instrs = block.Instructions;
                for (int i = 0; i < instrs.Count; i++)
                {
                    var                instr = instrs[i];
                    int                indexToRemove;
                    TypeReference      type;
                    VariableDefinition local = null;

                    if (instr.OpCode.Code == Code.Newobj)
                    {
                        if (i + 1 >= instrs.Count)
                        {
                            continue;
                        }
                        var ctor = instr.Operand as MethodReference;
                        if (ctor == null || ctor.DeclaringType == null)
                        {
                            continue;
                        }
                        if (ctor.Name != ".ctor")
                        {
                            continue;
                        }

                        var next = instrs[i + 1];
                        if (!next.isStloc() && !next.isLeave() && next.OpCode.Code != Code.Pop)
                        {
                            continue;
                        }

                        indexToRemove = i;
                        type          = ctor.DeclaringType;
                        if (next.isStloc())
                        {
                            local = Instr.getLocalVar(blocks.Locals, next);
                        }
                    }
                    else if (instr.OpCode.Code == Code.Ldfld)
                    {
                        if (i == 0)
                        {
                            continue;
                        }
                        var ldloc = instrs[i - 1];
                        if (!ldloc.isLdloc())
                        {
                            continue;
                        }

                        var field = instr.Operand as FieldReference;
                        if (field == null || field.DeclaringType == null)
                        {
                            continue;
                        }

                        indexToRemove = i;
                        type          = field.DeclaringType;
                        local         = Instr.getLocalVar(blocks.Locals, ldloc);
                    }
                    else
                    {
                        continue;
                    }

                    if (type == null)
                    {
                        continue;
                    }
                    var info = typeToInfo.find(type);
                    if (info == null)
                    {
                        continue;
                    }

                    info.referenced = true;
                    instrsToRemove.Add(indexToRemove);
                    if (local != null)
                    {
                        local.VariableType = info.localType;
                    }
                }
                block.remove(instrsToRemove);
            }
        }
Ejemplo n.º 14
0
        bool findFirstBlocks(Block block, TamperBlocks tamperBlocks, IList <Block> allBlocks, IList <VariableDefinition> locals)
        {
            if (!block.LastInstr.isBrfalse())
            {
                return(false);
            }

            /*
             * ldc.i4.0
             * stloc X
             * call GetExecutingAssembly()
             * stloc Y
             * ldloc Y
             * callvirt Location
             * ldc.i4.1
             * ldloca X
             * call StrongNameSignatureVerificationEx
             * pop / brfalse bad_code
             * ldloc X
             * brfalse bad_code
             * ldloc Y
             * callvirt FullName()
             * ldstr "......"
             * callvirt EndsWith(string)
             * brfalse bad_code / brtrue good_code
             */

            var             instrs = block.Instructions;
            int             end    = instrs.Count - 1;
            Instr           instr;
            MethodReference method;

            tamperBlocks.type = Type.V1;

            int index = 0;

            int start = findCallMethod(block, index, true, (calledMethod) => calledMethod.ToString() == "System.Reflection.Assembly System.Reflection.Assembly::GetExecutingAssembly()");

            if (start < 0)
            {
                return(false);
            }
            index = start + 1;
            instr = instrs[--start];
            if (!instr.isStloc())
            {
                return(false);
            }
            var loc0 = Instr.getLocalVar(locals, instr);

            instr = instrs[--start];
            if (!instr.isLdcI4())
            {
                return(false);
            }

            index = findCallMethod(block, index, false, (calledMethod) => calledMethod.ToString() == "System.String System.Reflection.Assembly::get_Location()");
            if (index < 0)
            {
                return(false);
            }
            index++;

            index = findCallMethod(block, index, false, (calledMethod) => {
                tamperBlocks.pinvokeMethod = DotNetUtils.getMethod(module, calledMethod);
                return(DotNetUtils.isPinvokeMethod(tamperBlocks.pinvokeMethod, "mscorwks", "StrongNameSignatureVerificationEx"));
            });
            if (index < 0)
            {
                return(false);
            }
            index++;

            if (!instrs[index].isBrfalse())
            {
                if (instrs[index].OpCode.Code != Code.Pop)
                {
                    return(false);
                }
                instr = instrs[index + 1];
                if (!instr.isLdloc() || Instr.getLocalVar(locals, instr) != loc0)
                {
                    return(false);
                }
                if (!instrs[index + 2].isBrfalse())
                {
                    return(false);
                }

                tamperBlocks.type  = Type.V1;
                tamperBlocks.first = new BlockInfo {
                    Block = block,
                    Start = start,
                    End   = end,
                };
            }
            else
            {
                tamperBlocks.type  = Type.V2;
                tamperBlocks.first = new BlockInfo {
                    Block = block,
                    Start = start,
                    End   = end,
                };

                block = block.FallThrough;
                if (block == null)
                {
                    return(false);
                }
                instrs = block.Instructions;
                index  = 0;
                instr  = instrs[index];
                if (!instr.isLdloc() || Instr.getLocalVar(locals, instr) != loc0)
                {
                    return(false);
                }
                if (!instrs[index + 1].isBrfalse())
                {
                    return(false);
                }
            }

            block  = block.FallThrough;
            instrs = block.Instructions;
            start  = end = 0;

            instr = instrs[end++];
            if (!instr.isLdloc())
            {
                return(false);
            }

            instr = instrs[end++];
            if (instr.OpCode != OpCodes.Callvirt)
            {
                return(false);
            }
            method = (MethodReference)instr.Operand;
            if (method.ToString() != "System.String System.Reflection.Assembly::get_FullName()")
            {
                return(false);
            }

            instr = instrs[end++];
            if (instr.OpCode != OpCodes.Ldstr)
            {
                return(false);
            }

            instr = instrs[end++];
            if (instr.OpCode != OpCodes.Callvirt)
            {
                return(false);
            }
            method = (MethodReference)instr.Operand;
            if (method.ToString() != "System.Boolean System.String::EndsWith(System.String)")
            {
                return(false);
            }

            instr = instrs[end++];
            if (!instr.isBrfalse() && !instr.isBrtrue())
            {
                return(false);
            }

            end--;
            tamperBlocks.second = new BlockInfo {
                Block = block,
                Start = start,
                End   = end,
            };

            return(true);
        }
Ejemplo n.º 15
0
        bool getArg(MethodReference method, Block block, ref object arg, ref int instrIndex)
        {
            while (true)
            {
                if (instrIndex < 0)
                {
                    // We're here if there were no cflow deobfuscation, or if there are two or
                    // more blocks branching to the decrypter method, or the two blocks can't be
                    // merged because one is outside the exception handler (eg. buggy obfuscator).
                    Log.w("Could not find all arguments to method {0} ({1:X8})",
                          Utils.removeNewlines(method),
                          method.MetadataToken.ToInt32());
                    errors++;
                    return(false);
                }

                var instr = block.Instructions[instrIndex--];
                switch (instr.OpCode.Code)
                {
                case Code.Ldc_I4:
                case Code.Ldc_I8:
                case Code.Ldc_R4:
                case Code.Ldc_R8:
                case Code.Ldstr:
                    arg = instr.Operand;
                    break;

                case Code.Ldc_I4_S:
                    arg = (int)(sbyte)instr.Operand;
                    break;

                case Code.Ldc_I4_0: arg = 0; break;

                case Code.Ldc_I4_1: arg = 1; break;

                case Code.Ldc_I4_2: arg = 2; break;

                case Code.Ldc_I4_3: arg = 3; break;

                case Code.Ldc_I4_4: arg = 4; break;

                case Code.Ldc_I4_5: arg = 5; break;

                case Code.Ldc_I4_6: arg = 6; break;

                case Code.Ldc_I4_7: arg = 7; break;

                case Code.Ldc_I4_8: arg = 8; break;

                case Code.Ldc_I4_M1: arg = -1; break;

                case Code.Ldnull:       arg = null; break;

                case Code.Nop:
                    continue;

                case Code.Ldloc:
                case Code.Ldloc_S:
                case Code.Ldloc_0:
                case Code.Ldloc_1:
                case Code.Ldloc_2:
                case Code.Ldloc_3:
                    getLocalVariableValue(Instr.getLocalVar(theMethod.Body.Variables, instr), out arg);
                    break;

                case Code.Ldfld:
                case Code.Ldsfld:
                    arg = instr.Operand;
                    break;

                default:
                    int pushes, pops;
                    DotNetUtils.calculateStackUsage(instr.Instruction, false, out pushes, out pops);
                    if (!useUnknownArgs || pushes != 1)
                    {
                        Log.w("Could not find all arguments to method {0} ({1:X8}), instr: {2}",
                              Utils.removeNewlines(method),
                              method.MetadataToken.ToInt32(),
                              instr);
                        errors++;
                        return(false);
                    }

                    for (int i = 0; i < pops; i++)
                    {
                        if (!getArg(method, block, ref arg, ref instrIndex))
                        {
                            return(false);
                        }
                    }
                    arg = null;
                    break;
                }
                break;
            }

            return(true);
        }
Ejemplo n.º 16
0
        bool remove(Blocks blocks, Block block)
        {
            var       instrs            = block.Instructions;
            const int numInstrsToRemove = 11;

            if (instrs.Count < numInstrsToRemove)
            {
                return(false);
            }
            int startIndex = instrs.Count - numInstrsToRemove;
            int index      = startIndex;

            if (instrs[index++].OpCode.Code != Code.Ldtoken)
            {
                return(false);
            }
            if (!checkCall(instrs[index++], "System.Type System.Type::GetTypeFromHandle(System.RuntimeTypeHandle)"))
            {
                return(false);
            }
            if (!checkCall(instrs[index++], "System.Reflection.Assembly System.Type::get_Assembly()"))
            {
                return(false);
            }
            if (!checkCall(instrs[index++], "System.Reflection.AssemblyName System.Reflection.Assembly::GetName()"))
            {
                return(false);
            }
            if (!checkCall(instrs[index++], "System.Byte[] System.Reflection.AssemblyName::GetPublicKeyToken()"))
            {
                return(false);
            }
            if (!checkCall(instrs[index++], "System.String System.Convert::ToBase64String(System.Byte[])"))
            {
                return(false);
            }
            if (instrs[index++].OpCode.Code != Code.Ldstr)
            {
                return(false);
            }
            if (!checkCall(instrs[index++], "System.String", "(System.String,System.String)"))
            {
                return(false);
            }
            if (instrs[index++].OpCode.Code != Code.Ldstr)
            {
                return(false);
            }
            if (!checkCall(instrs[index++], "System.Boolean System.String::op_Inequality(System.String,System.String)"))
            {
                return(false);
            }
            if (!instrs[index++].isBrfalse())
            {
                return(false);
            }

            var badBlock  = block.FallThrough;
            var goodblock = block.Targets[0];

            if (badBlock == null)
            {
                return(false);
            }

            if (badBlock == goodblock)
            {
                // All of the bad block was removed by the cflow deobfuscator. It was just a useless
                // calculation (div by zero).
                block.replaceLastInstrsWithBranch(numInstrsToRemove, goodblock);
            }
            else if (badBlock.Sources.Count == 1)
            {
                instrs = badBlock.Instructions;
                if (instrs.Count != 12)
                {
                    return(false);
                }
                index = 0;
                if (!instrs[index++].isLdcI4())
                {
                    return(false);
                }
                if (!instrs[index].isStloc())
                {
                    return(false);
                }
                var local = Instr.getLocalVar(blocks.Locals, instrs[index++]);
                if (local == null)
                {
                    return(false);
                }
                if (!checkLdloc(blocks.Locals, instrs[index++], local))
                {
                    return(false);
                }
                if (!checkLdloc(blocks.Locals, instrs[index++], local))
                {
                    return(false);
                }
                if (instrs[index++].OpCode.Code != Code.Sub)
                {
                    return(false);
                }
                if (instrs[index++].OpCode.Code != Code.Conv_U1)
                {
                    return(false);
                }
                if (!checkStloc(blocks.Locals, instrs[index++], local))
                {
                    return(false);
                }
                if (!checkLdloc(blocks.Locals, instrs[index++], local))
                {
                    return(false);
                }
                if (!checkLdloc(blocks.Locals, instrs[index++], local))
                {
                    return(false);
                }
                if (instrs[index++].OpCode.Code != Code.Div)
                {
                    return(false);
                }
                if (instrs[index++].OpCode.Code != Code.Conv_U1)
                {
                    return(false);
                }
                if (!checkStloc(blocks.Locals, instrs[index++], local))
                {
                    return(false);
                }

                block.replaceLastInstrsWithBranch(numInstrsToRemove, goodblock);
                badBlock.Parent.removeDeadBlock(badBlock);
            }
            else
            {
                return(false);
            }

            return(true);
        }