Exemple #1
0
        bool DecryptImage_v14_r58004(MyPEImage peImage, byte[] fileData)
        {
            var reader = new BinaryReader(new MemoryStream(methodsData));

            reader.ReadInt16();                 // sig
            var writer   = new BinaryWriter(new MemoryStream(fileData));
            int numInfos = reader.ReadInt32();

            for (int i = 0; i < numInfos; i++)
            {
                uint offs = reader.ReadUInt32() ^ key4;
                if (offs == 0)
                {
                    continue;
                }
                uint rva = reader.ReadUInt32() ^ key4;
                if (peImage.RvaToOffset(rva) != offs)
                {
                    throw new ApplicationException("Invalid offs & rva");
                }
                writer.BaseStream.Position = peImage.RvaToOffset(rva);
                writer.Write(reader.ReadBytes(reader.ReadInt32()));
            }

            return(true);
        }
			public MethodInfos(ModuleDef module, MainType mainType, MyPEImage peImage, PeHeader peHeader, McKey mcKey) {
				this.module = module;
				this.mainType = mainType;
				this.peImage = peImage;
				this.peHeader = peHeader;
				this.mcKey = mcKey;

				structSize = GetStructSize(mcKey);

				uint methodInfosRva = peHeader.GetRva(0x0FF8, mcKey.ReadUInt32(0x005A));
				uint encryptedDataRva = peHeader.GetRva(0x0FF0, mcKey.ReadUInt32(0x0046));

				methodInfosOffset = peImage.RvaToOffset(methodInfosRva);
				encryptedDataOffset = peImage.RvaToOffset(encryptedDataRva);
			}
Exemple #3
0
		public bool Decrypt(MyPEImage peImage, ref DumpedMethods dumpedMethods) {
			dumpedMethods = new DumpedMethods();

			bool decrypted = false;

			var methodDef = peImage.MetaData.TablesStream.MethodTable;
			for (uint rid = 1; rid <= methodDef.Rows; rid++) {
				var dm = new DumpedMethod();
				peImage.ReadMethodTableRowTo(dm, rid);

				if (dm.mdRVA == 0)
					continue;
				uint bodyOffset = peImage.RvaToOffset(dm.mdRVA);

				peImage.Reader.Position = bodyOffset;
				var mbHeader = MethodBodyParser.ParseMethodBody(peImage.Reader, out dm.code, out dm.extraSections);
				peImage.UpdateMethodHeaderInfo(dm, mbHeader);

				if (dm.code.Length < 6 || dm.code[0] != 0x2A || dm.code[1] != 0x2A)
					continue;

				int seed = BitConverter.ToInt32(dm.code, 2);
				Array.Copy(newCodeHeader, dm.code, newCodeHeader.Length);
				if (seed == 0)
					Decrypt(dm.code);
				else
					Decrypt(dm.code, seed);

				dumpedMethods.Add(dm);
				decrypted = true;
			}

			return decrypted;
		}
Exemple #4
0
            public MethodInfos(ModuleDef module, MainType mainType, MyPEImage peImage, PeHeader peHeader, McKey mcKey)
            {
                this.module   = module;
                this.mainType = mainType;
                this.peImage  = peImage;
                this.peHeader = peHeader;
                this.mcKey    = mcKey;

                structSize = GetStructSize(mcKey);

                uint methodInfosRva   = peHeader.GetRva(0x0FF8, mcKey.ReadUInt32(0x005A));
                uint encryptedDataRva = peHeader.GetRva(0x0FF0, mcKey.ReadUInt32(0x0046));

                methodInfosOffset   = peImage.RvaToOffset(methodInfosRva);
                encryptedDataOffset = peImage.RvaToOffset(encryptedDataRva);
            }
Exemple #5
0
        public uint Emulate(uint rva, uint[] args)
        {
            Initialize(args);

            reader.Position = peImage.RvaToOffset(rva);
            byte[] prolog, epilog;
            if (IsBytes(prolog1))
            {
                prolog = prolog1;
                epilog = epilog1;
            }
            else if (IsBytes(prolog2))
            {
                prolog = prolog2;
                epilog = epilog2;
            }
            else
            {
                throw new ApplicationException(string.Format("Missing prolog @ RVA {0:X8}", rva));
            }
            reader.Position += prolog.Length;

            while (!IsBytes(epilog))
            {
                Emulate();
            }

            return(regs[0]);
        }
Exemple #6
0
        bool DecryptImage_v16_r71742(MyPEImage peImage, byte[] fileData)
        {
            var reader = new BinaryReader(new MemoryStream(methodsData));

            reader.ReadInt16();                 // sig
            int numInfos = reader.ReadInt32();

            for (int i = 0; i < numInfos; i++)
            {
                uint offs = reader.ReadUInt32() ^ key4;
                if (offs == 0)
                {
                    continue;
                }
                uint rva = reader.ReadUInt32() ^ key5;
                if (peImage.RvaToOffset(rva) != offs)
                {
                    throw new ApplicationException("Invalid offs & rva");
                }
                int len = reader.ReadInt32();
                for (int j = 0; j < len; j++)
                {
                    fileData[offs + j] = reader.ReadByte();
                }
            }
            return(true);
        }
Exemple #7
0
            public DecrypterBase(MyPEImage peImage, CodeHeader codeHeader)
            {
                this.peImage    = peImage;
                this.codeHeader = codeHeader;
                var mdDir = peImage.Cor20Header.MetaData;

                endOfMetadata = peImage.RvaToOffset((uint)mdDir.VirtualAddress + mdDir.Size);
            }
        DumpedMethods CreateDumpedMethods(MyPEImage peImage, byte[] fileData, byte[] methodsData)
        {
            var dumpedMethods = new DumpedMethods();

            var methodsDataReader = MemoryImageStream.Create(methodsData);
            var fileDataReader    = MemoryImageStream.Create(fileData);

            var methodDef = peImage.MetaData.TablesStream.MethodTable;

            for (uint rid = 1; rid <= methodDef.Rows; rid++)
            {
                var dm = new DumpedMethod();

                peImage.ReadMethodTableRowTo(dm, rid);
                if (dm.mdRVA == 0)
                {
                    continue;
                }
                uint bodyOffset = peImage.RvaToOffset(dm.mdRVA);

                byte b = peImage.OffsetReadByte(bodyOffset);
                uint codeOffset;
                if ((b & 3) == 2)
                {
                    if (b != 2)
                    {
                        continue;                               // not zero byte code size
                    }
                    dm.mhFlags          = 2;
                    dm.mhMaxStack       = 8;
                    dm.mhLocalVarSigTok = 0;
                    codeOffset          = bodyOffset + 1;
                }
                else
                {
                    if (peImage.OffsetReadUInt32(bodyOffset + 4) != 0)
                    {
                        continue;                               // not zero byte code size
                    }
                    dm.mhFlags          = peImage.OffsetReadUInt16(bodyOffset);
                    dm.mhMaxStack       = peImage.OffsetReadUInt16(bodyOffset + 2);
                    dm.mhLocalVarSigTok = peImage.OffsetReadUInt32(bodyOffset + 8);
                    codeOffset          = bodyOffset + (uint)(dm.mhFlags >> 12) * 4;
                }
                fileDataReader.Position = codeOffset;

                if (!decrypter.Decrypt(fileDataReader, dm))
                {
                    continue;
                }

                dumpedMethods.Add(dm);
            }

            return(dumpedMethods);
        }
Exemple #9
0
        static uint GetOldCodeHeaderOffset(MyPEImage peImage)
        {
            var sect = GetLastOf(peImage, sections);

            if (sect == null || sect.VirtualSize < 0x100)
            {
                return(0);
            }
            return(peImage.RvaToOffset((uint)sect.VirtualAddress + sect.VirtualSize - 0x100));
        }
        int GetStartOffset(MyPEImage peImage)
        {
            int minOffset = int.MaxValue;

            foreach (var rva in mainType.Rvas)
            {
                int rvaOffs = (int)peImage.RvaToOffset((uint)rva);
                if (rvaOffs < minOffset)
                {
                    minOffset = rvaOffs;
                }
            }
            return(minOffset == int.MaxValue ? 0 : minOffset);
        }
Exemple #11
0
        public bool Decrypt(MyPEImage peImage, ref DumpedMethods dumpedMethods)
        {
            dumpedMethods = new DumpedMethods();

            bool decrypted = false;

            var methodDef = peImage.DotNetFile.MetaData.TablesStream.MethodTable;

            for (uint rid = 1; rid <= methodDef.Rows; rid++)
            {
                var dm = new DumpedMethod();
                peImage.ReadMethodTableRowTo(dm, rid);

                if (dm.mdRVA == 0)
                {
                    continue;
                }
                uint bodyOffset = peImage.RvaToOffset(dm.mdRVA);

                peImage.Reader.Position = bodyOffset;
                var mbHeader = MethodBodyParser.ParseMethodBody(peImage.Reader, out dm.code, out dm.extraSections);
                peImage.UpdateMethodHeaderInfo(dm, mbHeader);

                if (dm.code.Length < 6 || dm.code[0] != 0x2A || dm.code[1] != 0x2A)
                {
                    continue;
                }

                int seed = BitConverter.ToInt32(dm.code, 2);
                Array.Copy(newCodeHeader, dm.code, newCodeHeader.Length);
                if (seed == 0)
                {
                    Decrypt(dm.code);
                }
                else
                {
                    Decrypt(dm.code, seed);
                }

                dumpedMethods.Add(dm);
                decrypted = true;
            }

            return(decrypted);
        }
Exemple #12
0
        byte[] DecryptMethodsData_v14_r57884(MyPEImage peImage, bool hasStrongNameInfo)
        {
            var reader = peImage.Reader;

            reader.Position = 0;
            var md5SumData = reader.ReadBytes((int)peImage.OptionalHeader.CheckSum ^ (int)key0);

            int csOffs = (int)peImage.OptionalHeader.StartOffset + 0x40;

            Array.Clear(md5SumData, csOffs, 4);
            /*var md5Sum =*/ DeobUtils.Md5Sum(md5SumData);
            ulong checkSum = reader.ReadUInt64() ^ lkey0;

            if (hasStrongNameInfo)
            {
                int sn    = reader.ReadInt32();
                int snLen = reader.ReadInt32();
                if (sn != 0)
                {
                    if (peImage.RvaToOffset((uint)peImage.Cor20Header.StrongNameSignature.VirtualAddress) != sn ||
                        peImage.Cor20Header.StrongNameSignature.Size != snLen)
                    {
                        throw new ApplicationException("Invalid sn and snLen");
                    }
                    Array.Clear(md5SumData, sn, snLen);
                }
            }
            if (checkSum != CalcChecksum(md5SumData))
            {
                throw new ApplicationException("Invalid checksum. File has been modified.");
            }
            var iv        = reader.ReadBytes(reader.ReadInt32() ^ (int)key2);
            var encrypted = reader.ReadBytes(reader.ReadInt32() ^ (int)key3);
            var decrypted = Decrypt(encrypted, iv, md5SumData);

            if (BitConverter.ToInt16(decrypted, 0) != 0x6FD6)
            {
                throw new ApplicationException("Invalid magic");
            }
            return(decrypted);
        }
        DumpedMethods Decrypt_v17_r73404(MyPEImage peImage, byte[] fileData)
        {
            var dumpedMethods = new DumpedMethods();

            var methodDef = peImage.Metadata.TablesStream.MethodTable;

            for (uint rid = 1; rid <= methodDef.Rows; rid++)
            {
                var dm = new DumpedMethod();
                peImage.ReadMethodTableRowTo(dm, rid);

                if (dm.mdRVA == 0)
                {
                    continue;
                }
                uint bodyOffset = peImage.RvaToOffset(dm.mdRVA);

                if (!IsEncryptedMethod(fileData, (int)bodyOffset))
                {
                    continue;
                }

                int key      = BitConverter.ToInt32(fileData, (int)bodyOffset + 6);
                int mdOffs   = BitConverter.ToInt32(fileData, (int)bodyOffset + 2) ^ key;
                int len      = BitConverter.ToInt32(fileData, (int)bodyOffset + 11) ^ ~key;
                var codeData = DecryptMethodData_v17_r73404(methodsData, mdOffs + 2, (uint)key, len);

                var reader   = ByteArrayDataReaderFactory.CreateReader(codeData);
                var mbHeader = MethodBodyParser.ParseMethodBody(ref reader, out dm.code, out dm.extraSections);
                if (reader.Position != reader.Length)
                {
                    throw new ApplicationException("Invalid method data");
                }

                peImage.UpdateMethodHeaderInfo(dm, mbHeader);

                dumpedMethods.Add(dm);
            }

            return(dumpedMethods);
        }
Exemple #14
0
        bool Decrypt_v14_r57884(MyPEImage peImage, byte[] fileData)
        {
            methodsData = DecryptMethodsData_v14_r57884(peImage, false);

            var reader = new BinaryReader(new MemoryStream(methodsData));

            reader.ReadInt16();                 // sig
            var writer   = new BinaryWriter(new MemoryStream(fileData));
            int numInfos = reader.ReadInt32();

            for (int i = 0; i < numInfos; i++)
            {
                uint rva = reader.ReadUInt32();
                if (rva == 0)
                {
                    continue;
                }
                writer.BaseStream.Position = peImage.RvaToOffset(rva);
                writer.Write(reader.ReadBytes(reader.ReadInt32()));
            }

            return(true);
        }
		DumpedMethods Decrypt(MyPEImage peImage, byte[] fileData, DecryptMethodData decrypter) {
			var dumpedMethods = new DumpedMethods();

			var methodDef = peImage.MetaData.TablesStream.MethodTable;
			for (uint rid = 1; rid <= methodDef.Rows; rid++) {
				var dm = new DumpedMethod();
				peImage.ReadMethodTableRowTo(dm, rid);

				if (dm.mdRVA == 0)
					continue;
				uint bodyOffset = peImage.RvaToOffset(dm.mdRVA);

				if (!IsEncryptedMethod(fileData, (int)bodyOffset))
					continue;

				int key = BitConverter.ToInt32(fileData, (int)bodyOffset + 6);
				int mdOffs = BitConverter.ToInt32(fileData, (int)bodyOffset + 2) ^ key;
				int len = BitConverter.ToInt32(fileData, (int)bodyOffset + 11) ^ ~key;
				int methodDataOffset = mdOffs + 2;
				uint[] methodData;
				byte[] codeData;
				decrypter.Decrypt(methodsData, methodDataOffset, (uint)key, len, out methodData, out codeData);

				dm.mhFlags = 0x03;
				int maxStack = (int)methodData[methodDataIndexes.maxStack];
				dm.mhMaxStack = (ushort)maxStack;
				dm.mhLocalVarSigTok = methodData[methodDataIndexes.localVarSigTok];
				if (dm.mhLocalVarSigTok != 0 && (dm.mhLocalVarSigTok >> 24) != 0x11)
					throw new ApplicationException("Invalid local var sig token");
				int numExceptions = (int)methodData[methodDataIndexes.ehs];
				uint options = methodData[methodDataIndexes.options];
				int codeSize = (int)methodData[methodDataIndexes.codeSize];

				var codeDataReader = MemoryImageStream.Create(codeData);
				if (decrypter.IsCodeFollowedByExtraSections(options)) {
					dm.code = codeDataReader.ReadBytes(codeSize);
					dm.extraSections = ReadExceptionHandlers(codeDataReader, numExceptions);
				}
				else {
					dm.extraSections = ReadExceptionHandlers(codeDataReader, numExceptions);
					dm.code = codeDataReader.ReadBytes(codeSize);
				}
				if (codeDataReader.Position != codeDataReader.Length)
					throw new ApplicationException("Invalid method data");
				if (dm.extraSections != null)
					dm.mhFlags |= 8;
				dm.mhCodeSize = (uint)dm.code.Length;

				// Figure out if the original method was tiny or not.
				bool isTiny = dm.code.Length <= 0x3F &&
							dm.mhLocalVarSigTok == 0 &&
							dm.extraSections == null &&
							dm.mhMaxStack == 8;
				if (isTiny)
					dm.mhFlags |= 0x10;	// Set 'init locals'
				dm.mhFlags |= (ushort)(options & 0x10);	// copy 'init locals' bit

				dumpedMethods.Add(dm);
			}

			return dumpedMethods;
		}
			public DecrypterBase(MyPEImage peImage, CodeHeader codeHeader) {
				this.peImage = peImage;
				this.codeHeader = codeHeader;
				var mdDir = peImage.Cor20Header.MetaData;
				endOfMetadata = peImage.RvaToOffset((uint)mdDir.VirtualAddress + mdDir.Size);
			}
		bool Decrypt_v14_r57884(MyPEImage peImage, byte[] fileData) {
			methodsData = DecryptMethodsData_v14_r57884(peImage, false);

			var reader = new BinaryReader(new MemoryStream(methodsData));
			reader.ReadInt16();	// sig
			var writer = new BinaryWriter(new MemoryStream(fileData));
			int numInfos = reader.ReadInt32();
			for (int i = 0; i < numInfos; i++) {
				uint rva = reader.ReadUInt32();
				if (rva == 0)
					continue;
				writer.BaseStream.Position = peImage.RvaToOffset(rva);
				writer.Write(reader.ReadBytes(reader.ReadInt32()));
			}

			return true;
		}
		byte[] DecryptMethodsData_v14_r57884(MyPEImage peImage, bool hasStrongNameInfo) {
			var reader = peImage.Reader;
			reader.Position = 0;
			var md5SumData = reader.ReadBytes((int)peImage.OptionalHeader.CheckSum ^ (int)key0);

			int csOffs = (int)peImage.OptionalHeader.StartOffset + 0x40;
			Array.Clear(md5SumData, csOffs, 4);
			var md5Sum = DeobUtils.Md5Sum(md5SumData);
			ulong checkSum = reader.ReadUInt64() ^ lkey0;
			if (hasStrongNameInfo) {
				int sn = reader.ReadInt32();
				int snLen = reader.ReadInt32();
				if (sn != 0) {
					if (peImage.RvaToOffset((uint)peImage.Cor20Header.StrongNameSignature.VirtualAddress) != sn ||
						peImage.Cor20Header.StrongNameSignature.Size != snLen)
						throw new ApplicationException("Invalid sn and snLen");
					Array.Clear(md5SumData, sn, snLen);
				}
			}
			if (checkSum != CalcChecksum(md5SumData))
				throw new ApplicationException("Invalid checksum. File has been modified.");
			var iv = reader.ReadBytes(reader.ReadInt32() ^ (int)key2);
			var encrypted = reader.ReadBytes(reader.ReadInt32() ^ (int)key3);
			var decrypted = Decrypt(encrypted, iv, md5SumData);
			if (BitConverter.ToInt16(decrypted, 0) != 0x6FD6)
				throw new ApplicationException("Invalid magic");
			return decrypted;
		}
		public bool Decrypt(MyPEImage peImage, ISimpleDeobfuscator simpleDeobfuscator, ref DumpedMethods dumpedMethods, Dictionary<uint, byte[]> tokenToNativeCode, bool unpackedNativeFile) {
			if (encryptedResource.Method == null)
				return false;

			encryptedResource.Initialize(simpleDeobfuscator);
			if (!encryptedResource.FoundResource)
				return false;
			var methodsData = encryptedResource.Decrypt();

			bool hooksJitter = FindDnrCompileMethod(encryptedResource.Method.DeclaringType) != null;

			xorKey = GetXorKey();
			XorEncrypt(methodsData);

			var methodsDataReader = MemoryImageStream.Create(methodsData);
			int patchCount = methodsDataReader.ReadInt32();
			int mode = methodsDataReader.ReadInt32();

			int tmp = methodsDataReader.ReadInt32();
			methodsDataReader.Position -= 4;
			if ((tmp & 0xFF000000) == 0x06000000) {
				// It's method token + rva. DNR 3.7.0.3 (and earlier?) - 3.9.0.1
				methodsDataReader.Position += 8L * patchCount;
				patchCount = methodsDataReader.ReadInt32();
				mode = methodsDataReader.ReadInt32();

				PatchDwords(peImage, methodsDataReader, patchCount);
				while (methodsDataReader.Position < methodsData.Length - 1) {
					uint token = methodsDataReader.ReadUInt32();
					int numDwords = methodsDataReader.ReadInt32();
					PatchDwords(peImage, methodsDataReader, numDwords / 2);
				}
			}
			else if (!hooksJitter || mode == 1) {
				// DNR 3.9.8.0, 4.0+

				PatchDwords(peImage, methodsDataReader, patchCount);
				bool oldCode = !IsNewer45Decryption(encryptedResource.Method);
				while (methodsDataReader.Position < methodsData.Length - 1) {
					uint rva = methodsDataReader.ReadUInt32();
					int size;
					if (oldCode) {
						methodsDataReader.ReadUInt32();	// token, unknown, or index
						size = methodsDataReader.ReadInt32();
					}
					else
						size = methodsDataReader.ReadInt32() * 4;

					var newData = methodsDataReader.ReadBytes(size);
					if (unpackedNativeFile)
						peImage.DotNetSafeWriteOffset(rva, newData);
					else
						peImage.DotNetSafeWrite(rva, newData);
				}
			}
			else {
				// DNR 4.0+ (jitter is hooked)

				var methodDef = peImage.MetaData.TablesStream.MethodTable;
				var rvaToIndex = new Dictionary<uint, int>((int)methodDef.Rows);
				uint offset = (uint)methodDef.StartOffset;
				for (int i = 0; i < methodDef.Rows; i++) {
					uint rva = peImage.OffsetReadUInt32(offset);
					offset += methodDef.RowSize;
					if (rva == 0)
						continue;

					if ((peImage.ReadByte(rva) & 3) == 2)
						rva++;
					else
						rva += (uint)(4 * (peImage.ReadByte(rva + 1) >> 4));
					rvaToIndex[rva] = i;
				}

				PatchDwords(peImage, methodsDataReader, patchCount);
				int count = methodsDataReader.ReadInt32();
				dumpedMethods = new DumpedMethods();
				while (methodsDataReader.Position < methodsData.Length - 1) {
					uint rva = methodsDataReader.ReadUInt32();
					uint index = methodsDataReader.ReadUInt32();
					bool isNativeCode = index >= 0x70000000;
					int size = methodsDataReader.ReadInt32();
					var methodData = methodsDataReader.ReadBytes(size);

					int methodIndex;
					if (!rvaToIndex.TryGetValue(rva, out methodIndex)) {
						Logger.w("Could not find method having code RVA {0:X8}", rva);
						continue;
					}

					uint methodToken = 0x06000001 + (uint)methodIndex;

					if (isNativeCode) {
						totalEncryptedNativeMethods++;
						if (tokenToNativeCode != null)
							tokenToNativeCode[methodToken] = methodData;

						// Convert return true / false methods. The others are converted to
						// throw 0xDEADCODE.
						if (DeobUtils.IsCode(nativeLdci4, methodData)) {
							uint val = BitConverter.ToUInt32(methodData, 4);
							// ldc.i4 XXXXXXXXh / ret
							methodData = new byte[] { 0x20, 0, 0, 0, 0, 0x2A };
							methodData[1] = (byte)val;
							methodData[2] = (byte)(val >> 8);
							methodData[3] = (byte)(val >> 16);
							methodData[4] = (byte)(val >> 24);
						}
						else if (DeobUtils.IsCode(nativeLdci4_0, methodData)) {
							// ldc.i4.0 / ret
							methodData = new byte[] { 0x16, 0x2A };
						}
						else {
							tokenToNativeMethod[methodToken] = methodData;

							// ldc.i4 0xDEADCODE / conv.u4 / throw
							methodData = new byte[] { 0x20, 0xDE, 0xC0, 0xAD, 0xDE, 0x6D, 0x7A };
						}
					}

					var dm = new DumpedMethod();
					peImage.ReadMethodTableRowTo(dm, MDToken.ToRID(methodToken));
					dm.code = methodData;

					var codeReader = peImage.Reader;
					codeReader.Position = peImage.RvaToOffset(dm.mdRVA);
					byte[] code;
					var mbHeader = MethodBodyParser.ParseMethodBody(codeReader, out code, out dm.extraSections);
					peImage.UpdateMethodHeaderInfo(dm, mbHeader);

					dumpedMethods.Add(dm);
				}
			}

			return true;
		}
		bool DecryptImage_v14_r58004(MyPEImage peImage, byte[] fileData) {
			var reader = new BinaryReader(new MemoryStream(methodsData));
			reader.ReadInt16();	// sig
			var writer = new BinaryWriter(new MemoryStream(fileData));
			int numInfos = reader.ReadInt32();
			for (int i = 0; i < numInfos; i++) {
				uint offs = reader.ReadUInt32() ^ key4;
				if (offs == 0)
					continue;
				uint rva = reader.ReadUInt32() ^ key4;
				if (peImage.RvaToOffset(rva) != offs)
					throw new ApplicationException("Invalid offs & rva");
				writer.BaseStream.Position = peImage.RvaToOffset(rva);
				writer.Write(reader.ReadBytes(reader.ReadInt32()));
			}

			return true;
		}
		int GetStartOffset(MyPEImage peImage) {
			int minOffset = int.MaxValue;
			foreach (var rva in mainType.Rvas) {
				int rvaOffs = (int)peImage.RvaToOffset((uint)rva);
				if (rvaOffs < minOffset)
					minOffset = rvaOffs;
			}
			return minOffset == int.MaxValue ? 0 : minOffset;
		}
		static uint GetOldCodeHeaderOffset(MyPEImage peImage) {
			var sect = GetLastOf(peImage, sections);
			if (sect == null || sect.VirtualSize < 0x100)
				return 0;
			return peImage.RvaToOffset((uint)sect.VirtualAddress + sect.VirtualSize - 0x100);
		}
Exemple #23
0
        DumpedMethods Decrypt(MyPEImage peImage, byte[] fileData, DecryptMethodData decrypter)
        {
            var dumpedMethods = new DumpedMethods();

            var methodDef = peImage.MetaData.TablesStream.MethodTable;

            for (uint rid = 1; rid <= methodDef.Rows; rid++)
            {
                var dm = new DumpedMethod();
                peImage.ReadMethodTableRowTo(dm, rid);

                if (dm.mdRVA == 0)
                {
                    continue;
                }
                uint bodyOffset = peImage.RvaToOffset(dm.mdRVA);

                if (!IsEncryptedMethod(fileData, (int)bodyOffset))
                {
                    continue;
                }

                int    key              = BitConverter.ToInt32(fileData, (int)bodyOffset + 6);
                int    mdOffs           = BitConverter.ToInt32(fileData, (int)bodyOffset + 2) ^ key;
                int    len              = BitConverter.ToInt32(fileData, (int)bodyOffset + 11) ^ ~key;
                int    methodDataOffset = mdOffs + 2;
                uint[] methodData;
                byte[] codeData;
                decrypter.Decrypt(methodsData, methodDataOffset, (uint)key, len, out methodData, out codeData);

                dm.mhFlags = 0x03;
                int maxStack = (int)methodData[methodDataIndexes.maxStack];
                dm.mhMaxStack       = (ushort)maxStack;
                dm.mhLocalVarSigTok = methodData[methodDataIndexes.localVarSigTok];
                if (dm.mhLocalVarSigTok != 0 && dm.mhLocalVarSigTok >> 24 != 0x11)
                {
                    throw new ApplicationException("Invalid local var sig token");
                }
                int  numExceptions = (int)methodData[methodDataIndexes.ehs];
                uint options       = methodData[methodDataIndexes.options];
                int  codeSize      = (int)methodData[methodDataIndexes.codeSize];

                var codeDataReader = MemoryImageStream.Create(codeData);
                if (decrypter.IsCodeFollowedByExtraSections(options))
                {
                    dm.code          = codeDataReader.ReadBytes(codeSize);
                    dm.extraSections = ReadExceptionHandlers(codeDataReader, numExceptions);
                }
                else
                {
                    dm.extraSections = ReadExceptionHandlers(codeDataReader, numExceptions);
                    dm.code          = codeDataReader.ReadBytes(codeSize);
                }
                if (codeDataReader.Position != codeDataReader.Length)
                {
                    throw new ApplicationException("Invalid method data");
                }
                if (dm.extraSections != null)
                {
                    dm.mhFlags |= 8;
                }
                dm.mhCodeSize = (uint)dm.code.Length;

                // Figure out if the original method was tiny or not.
                bool isTiny = dm.code.Length <= 0x3F &&
                              dm.mhLocalVarSigTok == 0 &&
                              dm.extraSections == null &&
                              dm.mhMaxStack == 8;
                if (isTiny)
                {
                    dm.mhFlags |= 0x10;                         // Set 'init locals'
                }
                dm.mhFlags |= (ushort)(options & 0x10);         // copy 'init locals' bit

                dumpedMethods.Add(dm);
            }

            return(dumpedMethods);
        }
		bool DecryptImage_v16_r71742(MyPEImage peImage, byte[] fileData) {
			var reader = new BinaryReader(new MemoryStream(methodsData));
			reader.ReadInt16();	// sig
			int numInfos = reader.ReadInt32();
			for (int i = 0; i < numInfos; i++) {
				uint offs = reader.ReadUInt32() ^ key4;
				if (offs == 0)
					continue;
				uint rva = reader.ReadUInt32() ^ key5;
				if (peImage.RvaToOffset(rva) != offs)
					throw new ApplicationException("Invalid offs & rva");
				int len = reader.ReadInt32();
				for (int j = 0; j < len; j++)
					fileData[offs + j] = reader.ReadByte();
			}
			return true;
		}
Exemple #25
0
        List <CsHeaderVersion> GetCsHeaderVersions(uint codeHeaderOffset, MDTable methodDefTable)
        {
            if (sigType == SigType.Old)
            {
                return new List <CsHeaderVersion> {
                           CsHeaderVersion.V10
                }
            }
            ;
            if (!IsOldHeader(methodDefTable))
            {
                return new List <CsHeaderVersion> {
                           CsHeaderVersion.V52
                }
            }
            ;
            if (csRtType.IsAtLeastVersion50())
            {
                return new List <CsHeaderVersion> {
                           CsHeaderVersion.V50
                }
            }
            ;
            if (IsCsHeader40(codeHeaderOffset))
            {
                return(new List <CsHeaderVersion> {
                    CsHeaderVersion.V40,
                    CsHeaderVersion.V30,
                });
            }
            return(new List <CsHeaderVersion> {
                CsHeaderVersion.V45,
                CsHeaderVersion.V50,
            });
        }

        bool IsCsHeader40(uint codeHeaderOffset)
        {
            try {
                uint offset       = codeHeaderOffset + codeHeader.totalCodeSize + 0x28;
                uint prevCodeOffs = 0;
                for (int i = 0; i < (int)codeHeader.numMethods; i++, offset += 4)
                {
                    uint codeOffs = peImage.OffsetReadUInt32(offset);
                    if (prevCodeOffs != 0 && codeOffs != 0 && codeOffs < prevCodeOffs)
                    {
                        return(false);
                    }
                    if (codeOffs != 0)
                    {
                        prevCodeOffs = codeOffs;
                    }
                }

                return(true);
            }
            catch (IOException) {
                return(false);
            }
        }

        bool IsOldHeader(MDTable methodDefTable)
        {
            if (methodDefTable.RowSize != codeHeader.methodDefElemSize)
            {
                return(true);
            }
            if ((uint)methodDefTable.StartOffset - peImage.RvaToOffset((uint)peImage.Cor20Header.MetaData.VirtualAddress) != codeHeader.methodDefTableOffset)
            {
                return(true);
            }

            return(false);
        }

        ICsHeader CreateCsHeader(CsHeaderVersion version)
        {
            switch (version)
            {
            case CsHeaderVersion.V30: return(new CsHeader30(this));

            case CsHeaderVersion.V40: return(new CsHeader40(this));

            case CsHeaderVersion.V45: return(new CsHeader45(this));

            case CsHeaderVersion.V50: return(new CsHeader5(this, 0x28));

            case CsHeaderVersion.V52: return(new CsHeader5(this, 0x30));

            default: throw new ApplicationException("Unknown CS header");
            }
        }
Exemple #26
0
 static uint GetCodeHeaderOffset(MyPEImage peImage)
 {
     return(peImage.RvaToOffset((uint)peImage.Cor20Header.MetaData.VirtualAddress + peImage.Cor20Header.MetaData.Size));
 }
        public bool Decrypt(MyPEImage peImage, ISimpleDeobfuscator simpleDeobfuscator, ref DumpedMethods dumpedMethods, Dictionary <uint, byte[]> tokenToNativeCode, bool unpackedNativeFile)
        {
            if (encryptedResource.Method == null)
            {
                return(false);
            }

            encryptedResource.Initialize(simpleDeobfuscator);
            if (!encryptedResource.FoundResource)
            {
                return(false);
            }
            var methodsData = encryptedResource.Decrypt();

            bool hooksJitter = FindDnrCompileMethod(encryptedResource.Method.DeclaringType) != null;

            xorKey = GetXorKey();
            XorEncrypt(methodsData);

            var methodsDataReader = MemoryImageStream.Create(methodsData);
            int patchCount        = methodsDataReader.ReadInt32();
            int mode = methodsDataReader.ReadInt32();

            int tmp = methodsDataReader.ReadInt32();

            methodsDataReader.Position -= 4;
            if ((tmp & 0xFF000000) == 0x06000000)
            {
                // It's method token + rva. DNR 3.7.0.3 (and earlier?) - 3.9.0.1
                methodsDataReader.Position += 8L * patchCount;
                patchCount = methodsDataReader.ReadInt32();
                mode       = methodsDataReader.ReadInt32();

                PatchDwords(peImage, methodsDataReader, patchCount);
                while (methodsDataReader.Position < methodsData.Length - 1)
                {
                    uint token     = methodsDataReader.ReadUInt32();
                    int  numDwords = methodsDataReader.ReadInt32();
                    PatchDwords(peImage, methodsDataReader, numDwords / 2);
                }
            }
            else if (!hooksJitter || mode == 1)
            {
                // DNR 3.9.8.0, 4.0+

                PatchDwords(peImage, methodsDataReader, patchCount);
                bool oldCode = !IsNewer45Decryption(encryptedResource.Method);
                while (methodsDataReader.Position < methodsData.Length - 1)
                {
                    uint rva = methodsDataReader.ReadUInt32();
                    int  size;
                    if (oldCode)
                    {
                        methodsDataReader.ReadUInt32();                         // token, unknown, or index
                        size = methodsDataReader.ReadInt32();
                    }
                    else
                    {
                        size = methodsDataReader.ReadInt32() * 4;
                    }

                    var newData = methodsDataReader.ReadBytes(size);
                    if (unpackedNativeFile)
                    {
                        peImage.DotNetSafeWriteOffset(rva, newData);
                    }
                    else
                    {
                        peImage.DotNetSafeWrite(rva, newData);
                    }
                }
            }
            else
            {
                // DNR 4.0+ (jitter is hooked)

                var  methodDef  = peImage.MetaData.TablesStream.MethodTable;
                var  rvaToIndex = new Dictionary <uint, int>((int)methodDef.Rows);
                uint offset     = (uint)methodDef.StartOffset;
                for (int i = 0; i < methodDef.Rows; i++)
                {
                    uint rva = peImage.OffsetReadUInt32(offset);
                    offset += methodDef.RowSize;
                    if (rva == 0)
                    {
                        continue;
                    }

                    if ((peImage.ReadByte(rva) & 3) == 2)
                    {
                        rva++;
                    }
                    else
                    {
                        rva += (uint)(4 * (peImage.ReadByte(rva + 1) >> 4));
                    }
                    rvaToIndex[rva] = i;
                }

                PatchDwords(peImage, methodsDataReader, patchCount);
                int count = methodsDataReader.ReadInt32();
                dumpedMethods = new DumpedMethods();
                while (methodsDataReader.Position < methodsData.Length - 1)
                {
                    uint rva          = methodsDataReader.ReadUInt32();
                    uint index        = methodsDataReader.ReadUInt32();
                    bool isNativeCode = index >= 0x70000000;
                    int  size         = methodsDataReader.ReadInt32();
                    var  methodData   = methodsDataReader.ReadBytes(size);

                    int methodIndex;
                    if (!rvaToIndex.TryGetValue(rva, out methodIndex))
                    {
                        Logger.w("Could not find method having code RVA {0:X8}", rva);
                        continue;
                    }

                    uint methodToken = 0x06000001 + (uint)methodIndex;

                    if (isNativeCode)
                    {
                        totalEncryptedNativeMethods++;
                        if (tokenToNativeCode != null)
                        {
                            tokenToNativeCode[methodToken] = methodData;
                        }

                        // Convert return true / false methods. The others are converted to
                        // throw 0xDEADCODE.
                        if (DeobUtils.IsCode(nativeLdci4, methodData))
                        {
                            uint val = BitConverter.ToUInt32(methodData, 4);
                            // ldc.i4 XXXXXXXXh / ret
                            methodData    = new byte[] { 0x20, 0, 0, 0, 0, 0x2A };
                            methodData[1] = (byte)val;
                            methodData[2] = (byte)(val >> 8);
                            methodData[3] = (byte)(val >> 16);
                            methodData[4] = (byte)(val >> 24);
                        }
                        else if (DeobUtils.IsCode(nativeLdci4_0, methodData))
                        {
                            // ldc.i4.0 / ret
                            methodData = new byte[] { 0x16, 0x2A };
                        }
                        else
                        {
                            tokenToNativeMethod[methodToken] = methodData;

                            // ldc.i4 0xDEADCODE / conv.u4 / throw
                            methodData = new byte[] { 0x20, 0xDE, 0xC0, 0xAD, 0xDE, 0x6D, 0x7A };
                        }
                    }

                    var dm = new DumpedMethod();
                    peImage.ReadMethodTableRowTo(dm, MDToken.ToRID(methodToken));
                    dm.code = methodData;

                    var codeReader = peImage.Reader;
                    codeReader.Position = peImage.RvaToOffset(dm.mdRVA);
                    byte[] code;
                    var    mbHeader = MethodBodyParser.ParseMethodBody(codeReader, out code, out dm.extraSections);
                    peImage.UpdateMethodHeaderInfo(dm, mbHeader);

                    dumpedMethods.Add(dm);
                }
            }

            return(true);
        }
		DumpedMethods CreateDumpedMethods(MyPEImage peImage, byte[] fileData, byte[] methodsData) {
			var dumpedMethods = new DumpedMethods();

			var methodsDataReader = MemoryImageStream.Create(methodsData);
			var fileDataReader = MemoryImageStream.Create(fileData);

			var methodDef = peImage.MetaData.TablesStream.MethodTable;
			for (uint rid = 1; rid <= methodDef.Rows; rid++) {
				var dm = new DumpedMethod();

				peImage.ReadMethodTableRowTo(dm, rid);
				if (dm.mdRVA == 0)
					continue;
				uint bodyOffset = peImage.RvaToOffset(dm.mdRVA);

				byte b = peImage.OffsetReadByte(bodyOffset);
				uint codeOffset;
				if ((b & 3) == 2) {
					if (b != 2)
						continue;	// not zero byte code size

					dm.mhFlags = 2;
					dm.mhMaxStack = 8;
					dm.mhLocalVarSigTok = 0;
					codeOffset = bodyOffset + 1;
				}
				else {
					if (peImage.OffsetReadUInt32(bodyOffset + 4) != 0)
						continue;	// not zero byte code size

					dm.mhFlags = peImage.OffsetReadUInt16(bodyOffset);
					dm.mhMaxStack = peImage.OffsetReadUInt16(bodyOffset + 2);
					dm.mhLocalVarSigTok = peImage.OffsetReadUInt32(bodyOffset + 8);
					codeOffset = bodyOffset + (uint)(dm.mhFlags >> 12) * 4;
				}
				fileDataReader.Position = codeOffset;

				if (!decrypter.Decrypt(fileDataReader, dm))
					continue;

				dumpedMethods.Add(dm);
			}

			return dumpedMethods;
		}
		DumpedMethods Decrypt_v17_r73404(MyPEImage peImage, byte[] fileData) {
			var dumpedMethods = new DumpedMethods();

			var methodDef = peImage.MetaData.TablesStream.MethodTable;
			for (uint rid = 1; rid <= methodDef.Rows; rid++) {
				var dm = new DumpedMethod();
				peImage.ReadMethodTableRowTo(dm, rid);

				if (dm.mdRVA == 0)
					continue;
				uint bodyOffset = peImage.RvaToOffset(dm.mdRVA);

				if (!IsEncryptedMethod(fileData, (int)bodyOffset))
					continue;

				int key = BitConverter.ToInt32(fileData, (int)bodyOffset + 6);
				int mdOffs = BitConverter.ToInt32(fileData, (int)bodyOffset + 2) ^ key;
				int len = BitConverter.ToInt32(fileData, (int)bodyOffset + 11) ^ ~key;
				var codeData = DecryptMethodData_v17_r73404(methodsData, mdOffs + 2, (uint)key, len);

				var reader = MemoryImageStream.Create(codeData);
				var mbHeader = MethodBodyParser.ParseMethodBody(reader, out dm.code, out dm.extraSections);
				if (reader.Position != reader.Length)
					throw new ApplicationException("Invalid method data");

				peImage.UpdateMethodHeaderInfo(dm, mbHeader);

				dumpedMethods.Add(dm);
			}

			return dumpedMethods;
		}
		static uint GetCodeHeaderOffset(MyPEImage peImage) {
			return peImage.RvaToOffset((uint)peImage.Cor20Header.MetaData.VirtualAddress + peImage.Cor20Header.MetaData.Size);
		}