protected override CallResult createCallResult(IMethod method, MethodSpec gim, Block block, int callInstrIndex)
 {
     int methodId;
     if (!methodTokenToId.TryGetValue(method.MDToken.ToInt32(), out methodId))
         return null;
     return new MyCallResult(block, callInstrIndex, methodId, gim);
 }
        protected override bool Deobfuscate(Block block)
        {
            bool modified = false;

            constantsReader = null;
            var instrs = block.Instructions;
            for (int i = 0; i < instrs.Count; i++) {
                bool ch = Deobfuscate1(block, i);
                if (ch) {
                    modified = true;
                    continue;
                }

                ch = Deobfuscate2(block, i);
                if (ch) {
                    modified = true;
                    continue;
                }

                ch = Deobfuscate3(block, i);
                if (ch) {
                    modified = true;
                    continue;
                }
            }

            return modified;
        }
Example #3
0
 protected override CallResult createCallResult(MethodReference method, Block block, int callInstrIndex)
 {
     int methodId;
     if (!methodTokenToId.TryGetValue(method.MetadataToken.ToInt32(), out methodId))
         return null;
     return new MyCallResult(block, callInstrIndex, methodId);
 }
		public void AddInitializeArrayCode(Block block, int start, int numToRemove, ITypeDefOrRef elementType, byte[] data) {
			int index = start;
			block.Replace(index++, numToRemove, Instruction.CreateLdcI4(data.Length / elementType.ToTypeSig().ElementType.GetPrimitiveSize()));
			block.Insert(index++, OpCodes.Newarr.ToInstruction(elementType));
			block.Insert(index++, OpCodes.Dup.ToInstruction());
			block.Insert(index++, OpCodes.Ldtoken.ToInstruction((IField)Create(data)));
			block.Insert(index++, OpCodes.Call.ToInstruction((IMethod)InitializeArrayMethod));
		}
Example #5
0
 public void addInitializeArrayCode(Block block, int start, int numToRemove, TypeReference elementType, byte[] data)
 {
     int index = start;
     block.replace(index++, numToRemove, DotNetUtils.createLdci4(data.Length / elementType.PrimitiveSize));
     block.insert(index++, Instruction.Create(OpCodes.Newarr, elementType));
     block.insert(index++, Instruction.Create(OpCodes.Dup));
     block.insert(index++, Instruction.Create(OpCodes.Ldtoken, create(data)));
     block.insert(index++, Instruction.Create(OpCodes.Call, InitializeArrayMethod));
 }
Example #6
0
        protected override bool deobfuscate(Block block)
        {
            bool changed = false;

            instructionEmulator.init(blocks);
            var instrs = block.Instructions;
            for (int i = 0; i < instrs.Count; i++) {
                var instr = instrs[i];

                switch (instr.OpCode.Code) {
                case Code.Ldarg:
                case Code.Ldarg_0:
                case Code.Ldarg_1:
                case Code.Ldarg_2:
                case Code.Ldarg_3:
                case Code.Ldarg_S:
                    changed |= fixLoadInstruction(block, i, instructionEmulator.getArg(DotNetUtils.getParameter(args, instr.Instruction)));
                    break;

                case Code.Ldloc:
                case Code.Ldloc_0:
                case Code.Ldloc_1:
                case Code.Ldloc_2:
                case Code.Ldloc_3:
                case Code.Ldloc_S:
                    changed |= fixLoadInstruction(block, i, instructionEmulator.getLocal(DotNetUtils.getLocalVar(blocks.Locals, instr.Instruction)));
                    break;

                case Code.Ldarga:
                case Code.Ldarga_S:
                    instructionEmulator.makeArgUnknown((ParameterDefinition)instr.Operand);
                    break;

                case Code.Ldloca:
                case Code.Ldloca_S:
                    instructionEmulator.makeLocalUnknown((VariableDefinition)instr.Operand);
                    break;
                }

                try {
                    instructionEmulator.emulate(instr.Instruction);
                }
                catch (NullReferenceException) {
                    // Here if eg. invalid metadata token in a call instruction (operand is null)
                    break;
                }
            }

            return changed;
        }
		protected override bool Deobfuscate(Block block) {
			bool modified = false;

			instructionEmulator.Initialize(blocks, allBlocks[0] == block);
			var instrs = block.Instructions;
			for (int i = 0; i < instrs.Count; i++) {
				var instr = instrs[i];

				switch (instr.OpCode.Code) {
				case Code.Ldarg:
				case Code.Ldarg_0:
				case Code.Ldarg_1:
				case Code.Ldarg_2:
				case Code.Ldarg_3:
				case Code.Ldarg_S:
					modified |= FixLoadInstruction(block, i, instructionEmulator.GetArg(instr.Instruction.GetParameter(args)));
					break;

				case Code.Ldloc:
				case Code.Ldloc_0:
				case Code.Ldloc_1:
				case Code.Ldloc_2:
				case Code.Ldloc_3:
				case Code.Ldloc_S:
					modified |= FixLoadInstruction(block, i, instructionEmulator.GetLocal(instr.Instruction.GetLocal(blocks.Locals)));
					break;

				case Code.Ldarga:
				case Code.Ldarga_S:
					instructionEmulator.MakeArgUnknown((Parameter)instr.Operand);
					break;

				case Code.Ldloca:
				case Code.Ldloca_S:
					instructionEmulator.MakeLocalUnknown((Local)instr.Operand);
					break;
				}

				try {
					instructionEmulator.Emulate(instr.Instruction);
				}
				catch (NullReferenceException) {
					// Here if eg. invalid metadata token in a call instruction (operand is null)
					break;
				}
			}

			return modified;
		}
        static int findCallMethod(Block block, int index, bool keepLooking, Func<IMethod, bool> func)
        {
            var instrs = block.Instructions;
            for (int i = index; i < instrs.Count; i++) {
                var instr = instrs[i];
                if (instr.OpCode.Code != Code.Call && instr.OpCode.Code != Code.Callvirt)
                    continue;

                var calledMethod = instr.Operand as IMethod;
                if (calledMethod != null && func(calledMethod))
                    return i;
                if (!keepLooking)
                    return -1;
            }
            return -1;
        }
 void add(Dictionary<Block, List<RemoveInfo>> removeInfos, Block block, int index, DelegateInfo di)
 {
     List<RemoveInfo> list;
     if (!removeInfos.TryGetValue(block, out list))
         removeInfos[block] = list = new List<RemoveInfo>();
     list.Add(new RemoveInfo {
         Index = index,
         DelegateInfo = di,
     });
 }
 public MyCallResult(Block block, int callEndIndex, IMethod method, MethodSpec gim)
     : base(block, callEndIndex)
 {
     this.IMethod = method;
     this.gim = gim;
 }
 protected override CallResult createCallResult(IMethod method, MethodSpec gim, Block block, int callInstrIndex)
 {
     if (stringDecrypters.find(method) == null)
         return null;
     return new MyCallResult(block, callInstrIndex, method, gim);
 }
 void removeDeadBlock(Block block)
 {
     var parent = block.Parent;
     if (parent != null)	// null if already dead
         parent.removeDeadBlock(block);
 }
Example #13
0
		static Block GetNopBlockTarget(Dictionary<Block, bool> nopBlocks, Block source, Block nopBlock) {
			if (nopBlock == null || !nopBlocks.ContainsKey(nopBlock) || source == nopBlock.FallThrough)
				return null;
			if (nopBlock.Parent.BaseBlocks[0] == nopBlock)
				return null;
			var target = nopBlock.FallThrough;
			if (nopBlock.Parent != target.Parent)
				return null;
			return target;
		}
		bool GetArg(IMethod 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).
					Logger.w("Could not find all arguments to method {0} ({1:X8})",
								Utils.RemoveNewlines(method),
								method.MDToken.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.Instruction.GetLocal(theMethod.Body.Variables), out arg);
					break;

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

				default:
					int pushes, pops;
					instr.Instruction.CalculateStackUsage(false, out pushes, out pops);
					if (!useUnknownArgs || pushes != 1) {
						Logger.w("Could not find all arguments to method {0} ({1:X8}), instr: {2}",
									Utils.RemoveNewlines(method),
									method.MDToken.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;
		}
		// Returns null if method is not a method we should inline
		protected abstract CallResult CreateCallResult(IMethod method, MethodSpec gim, Block block, int callInstrIndex);
Example #16
0
 public MyCallResult(Block block, int callEndIndex, MethodReference method)
     : base(block, callEndIndex)
 {
     this.methodKey = new MethodReferenceAndDeclaringTypeKey(method);
 }
Example #17
0
 protected override CallResult createCallResult(MethodReference method, Block block, int callInstrIndex)
 {
     if (!stringDecrypters.ContainsKey(new MethodReferenceAndDeclaringTypeKey(method)))
         return null;
     return new MyCallResult(block, callInstrIndex, method);
 }
Example #18
0
 public MyCallResult(Block block, int callEndIndex, int methodId)
     : base(block, callEndIndex)
 {
     this.methodId = methodId;
 }
        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;
        }
        BlockInfo findBadBlock(Block last)
        {
            /*
             * ldstr "........."
             * newobj	System.Security.SecurityException(string)
             * throw
             */

            var instrs = last.Instructions;
            if (instrs.Count != 3)
                return null;

            Instr instr;
            int start = 0;
            int end = 0;

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

            instr = instrs[end++];
            if (instr.OpCode != OpCodes.Newobj)
                return null;
            var method = instr.Operand as IMethod;
            if (method == null || method.ToString() != "System.Void System.Security.SecurityException::.ctor(System.String)")
                return null;

            instr = instrs[end++];
            if (instr.OpCode != OpCodes.Throw)
                return null;

            end--;
            return new BlockInfo {
                Block = last,
                Start = start,
                End = end,
            };
        }
		void FindBlocks(List<Block> instrToBlock, List<Block> allBlocks) {
			Block block = null;
			for (var i = 0; i < instructions.Count; i++) {
				List<int> branchSources;
				if (branches.TryGetValue(i, out branchSources) || block == null) {
					block = new Block();
					allBlocks.Add(block);
				}

				block.Add(new Instr(this.instructions[i]));
				instrToBlock.Add(block);
			}
		}
        BlockInstr findProxyCall(DelegateInfo di, Block block, int index, Dictionary<Block, bool> visited, int stack)
        {
            if (visited.ContainsKey(block))
                return null;
            if (index <= 0)
                visited[block] = true;

            var instrs = block.Instructions;
            for (int i = index + 1; i < instrs.Count; i++) {
                if (stack <= 0)
                    return null;
                var instr = instrs[i];
                DotNetUtils.updateStack(instr.Instruction, ref stack, false);
                if (stack < 0)
                    return null;

                if (instr.OpCode != OpCodes.Call && instr.OpCode != OpCodes.Callvirt)
                    continue;
                var method = DotNetUtils.getMethod(module, instr.Operand as MethodReference);
                if (method == null)
                    continue;
                if (stack != (DotNetUtils.hasReturnValue(method) ? 1 : 0))
                    continue;
                if (method.DeclaringType != di.field.DeclaringType)
                    continue;

                return new BlockInstr {
                    Block = block,
                    Index = i,
                };
            }
            if (stack <= 0)
                return null;

            foreach (var target in block.getTargets()) {
                var info = findProxyCall(di, target, -1, visited, stack);
                if (info != null)
                    return info;
            }

            return null;
        }
			public CallResult(Block block, int callEndIndex) {
				this.block = block;
				this.callEndIndex = callEndIndex;
			}
Example #24
0
 bool FixLoadInstruction(Block block, int index, Value value)
 {
     if (value.IsInt32()) {
         var intValue = (Int32Value)value;
         if (!intValue.AllBitsValid())
             return false;
         block.Instructions[index] = new Instr(Instruction.CreateLdcI4(intValue.Value));
         return true;
     }
     else if (value.IsInt64()) {
         var intValue = (Int64Value)value;
         if (!intValue.AllBitsValid())
             return false;
         block.Instructions[index] = new Instr(OpCodes.Ldc_I8.ToInstruction(intValue.Value));
         return true;
     }
     return false;
 }
		void FindCallResults(Block block) {
			for (int i = 0; i < block.Instructions.Count; i++) {
				var instr = block.Instructions[i];
				if (instr.OpCode != OpCodes.Call)
					continue;
				var method = instr.Operand as IMethod;
				if (method == null)
					continue;

				IMethod elementMethod = method;
				var gim = method as MethodSpec;
				if (gim != null)
					elementMethod = gim.Method;
				var callResult = CreateCallResult(elementMethod, gim, block, i);
				if (callResult == null)
					continue;

				if (FindArgs(callResult))
					callResults.Add(callResult);
			}
		}
Example #26
0
        protected override bool Deobfuscate(Block block)
        {
            bool modified = false;

            instructionEmulator.Initialize(Blocks, AllBlocks[0] == block);
            var instrs = block.Instructions;
            for (int i = 0; i < instrs.Count; i++) {
                var instr = instrs[i];

                switch (instr.OpCode.Code) {
                case Code.Ldarg:
                case Code.Ldarg_0:
                case Code.Ldarg_1:
                case Code.Ldarg_2:
                case Code.Ldarg_3:
                case Code.Ldarg_S:
                    modified |= FixLoadInstruction(block, i, instructionEmulator.GetArg(instr.Instruction.GetParameter(args)));
                    break;

                case Code.Ldloc:
                case Code.Ldloc_0:
                case Code.Ldloc_1:
                case Code.Ldloc_2:
                case Code.Ldloc_3:
                case Code.Ldloc_S:
                    modified |= FixLoadInstruction(block, i, instructionEmulator.GetLocal(instr.Instruction.GetLocal(Blocks.Locals)));
                    break;

                case Code.Ldarga:
                case Code.Ldarga_S:
                    instructionEmulator.MakeArgUnknown((Parameter)instr.Operand);
                    break;

                case Code.Ldloca:
                case Code.Ldloca_S:
                    instructionEmulator.MakeLocalUnknown((Local)instr.Operand);
                    break;

                case Code.Add:
                case Code.Add_Ovf:
                case Code.Add_Ovf_Un:
                case Code.And:
                case Code.Ceq:
                case Code.Cgt:
                case Code.Cgt_Un:
                case Code.Clt:
                case Code.Clt_Un:
                case Code.Conv_I:
                case Code.Conv_I1:
                case Code.Conv_I2:
                case Code.Conv_I4:
                case Code.Conv_I8:
                case Code.Conv_Ovf_I:
                case Code.Conv_Ovf_I_Un:
                case Code.Conv_Ovf_I1:
                case Code.Conv_Ovf_I1_Un:
                case Code.Conv_Ovf_I2:
                case Code.Conv_Ovf_I2_Un:
                case Code.Conv_Ovf_I4:
                case Code.Conv_Ovf_I4_Un:
                case Code.Conv_Ovf_I8:
                case Code.Conv_Ovf_I8_Un:
                case Code.Conv_Ovf_U:
                case Code.Conv_Ovf_U_Un:
                case Code.Conv_Ovf_U1:
                case Code.Conv_Ovf_U1_Un:
                case Code.Conv_Ovf_U2:
                case Code.Conv_Ovf_U2_Un:
                case Code.Conv_Ovf_U4:
                case Code.Conv_Ovf_U4_Un:
                case Code.Conv_Ovf_U8:
                case Code.Conv_Ovf_U8_Un:
                case Code.Conv_R_Un:
                case Code.Conv_R4:
                case Code.Conv_R8:
                case Code.Conv_U:
                case Code.Conv_U1:
                case Code.Conv_U2:
                case Code.Conv_U4:
                case Code.Conv_U8:
                case Code.Div:
                case Code.Div_Un:
                case Code.Dup:
                case Code.Mul:
                case Code.Mul_Ovf:
                case Code.Mul_Ovf_Un:
                case Code.Neg:
                case Code.Not:
                case Code.Or:
                case Code.Rem:
                case Code.Rem_Un:
                case Code.Shl:
                case Code.Shr:
                case Code.Shr_Un:
                case Code.Sub:
                case Code.Sub_Ovf:
                case Code.Sub_Ovf_Un:
                case Code.Xor:
                    if (DisableNewCode)
                        break;
                    if (i + 1 < instrs.Count && instrs[i + 1].OpCode.Code == Code.Pop)
                        break;
                    if (!VerifyValidArgs(instr.Instruction))
                        break;
                    instructionEmulator.Emulate(instr.Instruction);
                    var tos = instructionEmulator.Peek();
                    Instruction newInstr = null;
                    if (tos.IsInt32()) {
                        var val = (Int32Value)tos;
                        if (val.AllBitsValid())
                            newInstr = Instruction.CreateLdcI4(val.Value);
                    }
                    else if (tos.IsInt64()) {
                        var val = (Int64Value)tos;
                        if (val.AllBitsValid())
                            newInstr = OpCodes.Ldc_I8.ToInstruction(val.Value);
                    }
                    else if (tos.IsReal8()) {
                        var val = (Real8Value)tos;
                        if (val.IsValid)
                            newInstr = GetLoadRealInstruction(val.Value);
                    }
                    if (newInstr != null) {
                        block.Insert(i + 1, Instruction.Create(OpCodes.Pop));
                        block.Insert(i + 2, newInstr);
                        i += 2;
                        modified = true;
                    }
                    continue;
                }

                try {
                    instructionEmulator.Emulate(instr.Instruction);
                }
                catch (NullReferenceException) {
                    // Here if eg. invalid metadata token in a call instruction (operand is null)
                    break;
                }
            }

            return modified;
        }
		bool GetValue(Block block, int index, out object obj) {
			while (true) {
				if (index <= 0) {
					obj = null;
					return false;
				}
				var instr = block.Instructions[--index];
				if (instr.OpCode == OpCodes.Nop)
					continue;

				switch (instr.OpCode.Code) {
				case Code.Ldc_I4:
				case Code.Ldc_I8:
				case Code.Ldc_R4:
				case Code.Ldc_R8:
				case Code.Ldstr:
					obj = instr.Operand;
					return true;
				case Code.Ldc_I4_S:
					obj = (int)(sbyte)instr.Operand;
					return true;

				case Code.Ldc_I4_0: obj = 0; return true;
				case Code.Ldc_I4_1: obj = 1; return true;
				case Code.Ldc_I4_2: obj = 2; return true;
				case Code.Ldc_I4_3: obj = 3; return true;
				case Code.Ldc_I4_4: obj = 4; return true;
				case Code.Ldc_I4_5: obj = 5; return true;
				case Code.Ldc_I4_6: obj = 6; return true;
				case Code.Ldc_I4_7: obj = 7; return true;
				case Code.Ldc_I4_8: obj = 8; return true;
				case Code.Ldc_I4_M1:obj = -1; return true;
				case Code.Ldnull:	obj = null; return true;

				default:
					obj = null;
					return false;
				}
			}
		}
Example #28
0
 bool fixLoadInstruction(Block block, int index, Value value)
 {
     if (value.isInt32()) {
         var intValue = (Int32Value)value;
         if (!intValue.allBitsValid())
             return false;
         block.Instructions[index] = new Instr(DotNetUtils.createLdci4(intValue.value));
         return true;
     }
     else if (value.isInt64()) {
         var intValue = (Int64Value)value;
         if (!intValue.allBitsValid())
             return false;
         block.Instructions[index] = new Instr(Instruction.Create(OpCodes.Ldc_I8, intValue.value));
         return true;
     }
     return false;
 }
Example #29
0
			public LocalVariableInfo(Block block, int index) {
				this.block = block;
				this.index = index;
			}
        bool findFirstBlocks(Block block, TamperBlocks tamperBlocks, IList<Block> allBlocks, IList<Local> 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;
            IMethod 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 = instr.Operand as IMethod;
            if (method == null || 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 = instr.Operand as IMethod;
            if (method == null || 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;
        }