/// <inheritdoc />
		void IModuleWriterListener.OnWriterEvent(ModuleWriterBase writer, ModuleWriterEvent evt) {
			if (evt == ModuleWriterEvent.PESectionsCreated)
				NativeEraser.Erase(writer as NativeModuleWriter, writer.Module as ModuleDefMD);
			if (OnWriterEvent != null) {
				OnWriterEvent(writer, new ModuleWriterListenerEventArgs(evt));
			}
		}
		public void PrepareEncryptNativeMethods(ModuleWriterBase moduleWriter) {
			if (methodToNativeMethod.Count == 0)
				return;

			validNativeMethods = new List<MethodDef>(methodToNativeMethod.Count);
			int len = 12;
			foreach (var kv in methodToNativeMethod) {
				if (kv.Key.DeclaringType == null)
					continue;	// Method was removed
				if (kv.Key.DeclaringType.Module != module)
					continue;	// method.DeclaringType was removed
				validNativeMethods.Add(kv.Key);
				len += 3 * 4 + kv.Value.Length;
			}
			if (validNativeMethods.Count == 0)
				return;

			len = (len & ~15) + 16;
			encryptedResource.Resource.Data = MemoryImageStream.Create(new byte[len]);
		}
		public void EncryptNativeMethods(ModuleWriterBase moduleWriter) {
			if (validNativeMethods == null || validNativeMethods.Count == 0)
				return;

			Logger.v("Encrypting native methods");

			var stream = new MemoryStream();
			var writer = new BinaryWriter(stream);
			writer.Write((uint)0);	// patch count
			writer.Write((uint)0);	// mode
			writer.Write(validNativeMethods.Count);

			int index = 0;
			foreach (var method in validNativeMethods) {
				var code = methodToNativeMethod[method];

				var mb = moduleWriter.MetaData.GetMethodBody(method);
				if (mb == null) {
					Logger.e("Could not find method body for method {0} ({1:X8})", method, method.MDToken.Raw);
					continue;
				}

				uint codeRva = (uint)mb.RVA;
				if (mb.IsTiny)
					codeRva++;
				else
					codeRva += (uint)(4 * (mb.Code[1] >> 4));

				Logger.v("Native method {0:X8}, code RVA {1:X8}", new MDToken(Table.Method, moduleWriter.MetaData.GetRid(method)).Raw, codeRva);

				writer.Write(codeRva);
				writer.Write(0x70000000 + index++);
				writer.Write(code.Length);
				writer.Write(code);
			}

			if (index != 0)
				Logger.n("Re-encrypted {0}/{1} native methods", index, totalEncryptedNativeMethods);

			var resourceChunk = moduleWriter.MetaData.GetChunk(encryptedResource.Resource);
			var resourceData = resourceChunk.Data;

			var encrypted = stream.ToArray();
			XorEncrypt(encrypted);

			encrypted = encryptedResource.Encrypt(encrypted);
			if (encrypted.Length != resourceData.Length)
				Logger.e("Encrypted native methods array is not same size as original array");
			Array.Copy(encrypted, resourceData, resourceData.Length);
		}
		public override void OnWriterEvent(ModuleWriterBase writer, ModuleWriterEvent evt) {
			if (!options.DecryptMethods || !methodsDecrypter.HasNativeMethods)
				return;
			switch (evt) {
			case ModuleWriterEvent.Begin:
				// The decrypter assumes RVAs are unique so don't share any method bodies
				writer.TheOptions.ShareMethodBodies = false;
				break;

			case ModuleWriterEvent.MDBeginAddResources:
				methodsDecrypter.PrepareEncryptNativeMethods(writer);
				break;

			case ModuleWriterEvent.BeginWriteChunks:
				methodsDecrypter.EncryptNativeMethods(writer);
				break;
			}
		}
Example #5
0
		void IModuleWriterListener.OnWriterEvent(ModuleWriterBase writer, ModuleWriterEvent evt) {
			ThrowIfCanceled();
			((ModuleFileProgress)fileProgress).CurrentEventIndex = evt - ModuleWriterEvent.Begin;
			Debug.Assert(((ModuleFileProgress)fileProgress).CurrentEventIndex >= 0);
			NotifyProgressUpdated();
		}
Example #6
0
		void EncryptSection(ModuleWriterBase writer) {
			Stream stream = writer.DestinationStream;
			var reader = new BinaryReader(writer.DestinationStream);
			stream.Position = 0x3C;
			stream.Position = reader.ReadUInt32();

			stream.Position += 6;
			ushort sections = reader.ReadUInt16();
			stream.Position += 0xc;
			ushort optSize = reader.ReadUInt16();
			stream.Position += 2 + optSize;

			uint encLoc = 0, encSize = 0;
			int origSects = -1;
			if (writer is NativeModuleWriter && writer.Module is ModuleDefMD)
				origSects = ((ModuleDefMD)writer.Module).MetaData.PEImage.ImageSectionHeaders.Count;
			for (int i = 0; i < sections; i++) {
				uint nameHash;
				if (origSects > 0) {
					origSects--;
					stream.Write(new byte[8], 0, 8);
					nameHash = 0;
				}
				else
					nameHash = reader.ReadUInt32() * reader.ReadUInt32();
				stream.Position += 8;
				if (nameHash == name1 * name2) {
					encSize = reader.ReadUInt32();
					encLoc = reader.ReadUInt32();
				}
				else if (nameHash != 0) {
					uint sectSize = reader.ReadUInt32();
					uint sectLoc = reader.ReadUInt32();
					Hash(stream, reader, sectLoc, sectSize);
				}
				else
					stream.Position += 8;
				stream.Position += 16;
			}

			uint[] key = DeriveKey();
			encSize >>= 2;
			stream.Position = encLoc;
			var result = new uint[encSize];
			for (uint i = 0; i < encSize; i++) {
				uint data = reader.ReadUInt32();
				result[i] = data ^ key[i & 0xf];
				key[i & 0xf] = (key[i & 0xf] ^ data) + 0x3dbb2819;
			}
			var byteResult = new byte[encSize << 2];
			Buffer.BlockCopy(result, 0, byteResult, 0, byteResult.Length);
			stream.Position = encLoc;
			stream.Write(byteResult, 0, byteResult.Length);
		}
Example #7
0
 void IModuleWriterListener.OnWriterEvent(ModuleWriterBase writer, ModuleWriterEvent evt)
 {
     ThrowIfCanceled();
     currentEventIndex = evt - ModuleWriterEvent.Begin;
     Debug.Assert(currentEventIndex >= 0);
     if (OnProgressUpdated != null)
         OnProgressUpdated(this, EventArgs.Empty);
 }
Example #8
0
		void CreateSection(ModuleWriterBase writer) {
			// move some PE parts to separate section to prevent it from being hashed
			var peSection = new PESection("", 0x60000020);
			bool moved = false;
			uint alignment;
			if (writer.StrongNameSignature != null) {
				alignment = writer.TextSection.Remove(writer.StrongNameSignature).Value;
				peSection.Add(writer.StrongNameSignature, alignment);
				moved = true;
			}
			var managedWriter = writer as ModuleWriter;
			if (managedWriter != null) {
				if (managedWriter.ImportAddressTable != null) {
					alignment = writer.TextSection.Remove(managedWriter.ImportAddressTable).Value;
					peSection.Add(managedWriter.ImportAddressTable, alignment);
					moved = true;
				}
				if (managedWriter.StartupStub != null) {
					alignment = writer.TextSection.Remove(managedWriter.StartupStub).Value;
					peSection.Add(managedWriter.StartupStub, alignment);
					moved = true;
				}
			}
			if (moved)
				writer.Sections.Add(peSection);

			// create section
			var nameBuffer = new byte[8];
			nameBuffer[0] = (byte)(name1 >> 0);
			nameBuffer[1] = (byte)(name1 >> 8);
			nameBuffer[2] = (byte)(name1 >> 16);
			nameBuffer[3] = (byte)(name1 >> 24);
			nameBuffer[4] = (byte)(name2 >> 0);
			nameBuffer[5] = (byte)(name2 >> 8);
			nameBuffer[6] = (byte)(name2 >> 16);
			nameBuffer[7] = (byte)(name2 >> 24);
			var newSection = new PESection(Encoding.ASCII.GetString(nameBuffer), 0xE0000040);
			writer.Sections.Insert(random.NextInt32(writer.Sections.Count), newSection);

			// random padding at beginning to prevent revealing hash key
			newSection.Add(new ByteArrayChunk(random.NextBytes(0x10)), 0x10);

			// create index
			var bodyIndex = new JITBodyIndex(methods.Select(method => writer.MetaData.GetToken(method).Raw));
			newSection.Add(bodyIndex, 0x10);

			// save methods
			foreach (MethodDef method in methods.WithProgress(context.Logger)) {
				if (!method.HasBody)
					continue;

				MDToken token = writer.MetaData.GetToken(method);

				var jitBody = new JITMethodBody();
				var bodyWriter = new JITMethodBodyWriter(writer.MetaData, method.Body, jitBody, random.NextUInt32(), writer.MetaData.KeepOldMaxStack || method.Body.KeepOldMaxStack);
				bodyWriter.Write();
				jitBody.Serialize(token.Raw, key, fieldLayout);
				bodyIndex.Add(token.Raw, jitBody);

				method.Body = NopBody;
				writer.MetaData.TablesHeap.MethodTable[token.Rid].ImplFlags |= (ushort)MethodImplAttributes.NoInlining;
				context.CheckCancellation();
			}
			bodyIndex.PopulateSection(newSection);

			// padding to prevent bad size due to shift division
			newSection.Add(new ByteArrayChunk(new byte[4]), 4);
		}
Example #9
0
		void CreateSections(ModuleWriterBase writer) {
			var nameBuffer = new byte[8];
			nameBuffer[0] = (byte)(name1 >> 0);
			nameBuffer[1] = (byte)(name1 >> 8);
			nameBuffer[2] = (byte)(name1 >> 16);
			nameBuffer[3] = (byte)(name1 >> 24);
			nameBuffer[4] = (byte)(name2 >> 0);
			nameBuffer[5] = (byte)(name2 >> 8);
			nameBuffer[6] = (byte)(name2 >> 16);
			nameBuffer[7] = (byte)(name2 >> 24);
			var newSection = new PESection(Encoding.ASCII.GetString(nameBuffer), 0xE0000040);
			writer.Sections.Insert(0, newSection); // insert first to ensure proper RVA

			uint alignment;

			alignment = writer.TextSection.Remove(writer.MetaData).Value;
			writer.TextSection.Add(writer.MetaData, alignment);

			alignment = writer.TextSection.Remove(writer.NetResources).Value;
			writer.TextSection.Add(writer.NetResources, alignment);

			alignment = writer.TextSection.Remove(writer.Constants).Value;
			newSection.Add(writer.Constants, alignment);

			// move some PE parts to separate section to prevent it from being hashed
			var peSection = new PESection("", 0x60000020);
			bool moved = false;
			if (writer.StrongNameSignature != null) {
				alignment = writer.TextSection.Remove(writer.StrongNameSignature).Value;
				peSection.Add(writer.StrongNameSignature, alignment);
				moved = true;
			}
			var managedWriter = writer as ModuleWriter;
			if (managedWriter != null) {
				if (managedWriter.ImportAddressTable != null) {
					alignment = writer.TextSection.Remove(managedWriter.ImportAddressTable).Value;
					peSection.Add(managedWriter.ImportAddressTable, alignment);
					moved = true;
				}
				if (managedWriter.StartupStub != null) {
					alignment = writer.TextSection.Remove(managedWriter.StartupStub).Value;
					peSection.Add(managedWriter.StartupStub, alignment);
					moved = true;
				}
			}
			if (moved)
				writer.Sections.Add(peSection);

			// move encrypted methods
			var encryptedChunk = new MethodBodyChunks(writer.TheOptions.ShareMethodBodies);
			newSection.Add(encryptedChunk, 4);
			foreach (MethodDef method in methods) {
				if (!method.HasBody)
					continue;
				MethodBody body = writer.MetaData.GetMethodBody(method);
				bool ok = writer.MethodBodies.Remove(body);
				encryptedChunk.Add(body);
			}

			// padding to prevent bad size due to shift division
			newSection.Add(new ByteArrayChunk(new byte[4]), 4);
		}
Example #10
0
            public void OnWriterEvent(ModuleWriterBase writer, ModuleWriterEvent evt)
            {
                if (evt == ModuleWriterEvent.MDBeginCreateTables) {
                    // Add key signature
                    uint sigBlob = writer.MetaData.BlobHeap.Add(ctx.KeySig);
                    uint sigRid = writer.MetaData.TablesHeap.StandAloneSigTable.Add(new RawStandAloneSigRow(sigBlob));
                    Debug.Assert(sigRid == 1);
                    uint sigToken = 0x11000000 | sigRid;
                    ctx.KeyToken = sigToken;
                    MutationHelper.InjectKey(writer.Module.EntryPoint, 2, (int)sigToken);
                }
                else if (evt == ModuleWriterEvent.MDBeginAddResources) {
                    // Compute hash
                    byte[] hash = SHA1.Create().ComputeHash(ctx.OriginModule);
                    uint hashBlob = writer.MetaData.BlobHeap.Add(hash);

                    MDTable<RawFileRow> fileTbl = writer.MetaData.TablesHeap.FileTable;
                    uint fileRid = fileTbl.Add(new RawFileRow(
                                                   (uint)FileAttributes.ContainsMetaData,
                                                   writer.MetaData.StringsHeap.Add("koi"),
                                                   hashBlob));
                    uint impl = CodedToken.Implementation.Encode(new MDToken(Table.File, fileRid));

                    // Add resources
                    MDTable<RawManifestResourceRow> resTbl = writer.MetaData.TablesHeap.ManifestResourceTable;
                    foreach (var resource in ctx.ManifestResources)
                        resTbl.Add(new RawManifestResourceRow(resource.Item1, resource.Item2, writer.MetaData.StringsHeap.Add(resource.Item3), impl));

                    // Add exported types
                    var exTbl = writer.MetaData.TablesHeap.ExportedTypeTable;
                    foreach (var type in ctx.OriginModuleDef.GetTypes()) {
                        if (!type.IsVisibleOutside())
                            continue;
                        exTbl.Add(new RawExportedTypeRow((uint)type.Attributes, 0,
                                                         writer.MetaData.StringsHeap.Add(type.Name),
                                                         writer.MetaData.StringsHeap.Add(type.Namespace), impl));
                    }
                }
            }
 /// <inheritdoc />
 void IModuleWriterListener.OnWriterEvent(ModuleWriterBase writer, ModuleWriterEvent evt)
 {
     if (OnWriterEvent != null) {
         OnWriterEvent(writer, new ModuleWriterListenerEventArgs(evt));
     }
 }
Example #12
0
		// Gets notified during module writing
		public void OnWriterEvent(ModuleWriterBase writer, ModuleWriterEvent evt) {
			switch (evt) {
			case ModuleWriterEvent.PESectionsCreated:
				// Add a PE section
				var sect1 = new PESection(".dummy", 0x40000040);
				writer.Sections.Add(sect1);
				// Let's add data
				sect1.Add(new ByteArrayChunk(new byte[123]), 4);
				sect1.Add(new ByteArrayChunk(new byte[10]), 4);
				break;

			case ModuleWriterEvent.MDEndCreateTables:
				// All types, methods etc have gotten their new RIDs. Let's print the new values
				Console.WriteLine("Old -> new type and method tokens");
				foreach (var type in writer.Module.GetTypes()) {
					Console.WriteLine("TYPE: {0:X8} -> {1:X8} {2}",
						type.MDToken.Raw,
						new MDToken(Table.TypeDef, writer.MetaData.GetRid(type)).Raw,
						type.FullName);
					foreach (var method in type.Methods)
						Console.WriteLine("  METH: {0:X8} -> {1:X8} {2}",
							method.MDToken.Raw,
							new MDToken(Table.Method, writer.MetaData.GetRid(method)).Raw,
							method.FullName);
				}
				break;

			default:
				break;
			}
		}
Example #13
0
		void PrintTokens(ModuleWriterBase writer) {
			if (Logger.Instance.IgnoresEvent(LoggerEvent.Verbose))
				return;

			var md = writer.MetaData;

			Logger.v("Old -> new tokens: Assembly: {0} (module: {1})", module.Assembly, module.Location);
			Logger.Instance.Indent();
			foreach (var type in module.GetTypes()) {
				uint newRid;

				newRid = md.GetRid(type);
				if (newRid == 0)
					continue;
				Logger.v("{0:X8} -> {1:X8} Type: {2}",
						type.MDToken.ToUInt32(),
						new MDToken(Table.TypeDef, newRid).ToUInt32(),
						Utils.RemoveNewlines(type));

				Logger.Instance.Indent();

				foreach (var method in type.Methods) {
					newRid = md.GetRid(method);
					if (newRid == 0)
						continue;
					Logger.v("{0:X8} -> {1:X8} Method: {2}",
							method.MDToken.ToUInt32(),
							new MDToken(Table.Method, newRid).ToUInt32(),
							Utils.RemoveNewlines(method));
				}

				foreach (var field in type.Fields) {
					newRid = md.GetRid(field);
					if (newRid == 0)
						continue;
					Logger.v("{0:X8} -> {1:X8} Field: {2}",
							field.MDToken.ToUInt32(),
							new MDToken(Table.Field, newRid).ToUInt32(),
							Utils.RemoveNewlines(field));
				}

				foreach (var prop in type.Properties) {
					newRid = md.GetRid(prop);
					if (newRid == 0)
						continue;
					Logger.v("{0:X8} -> {1:X8} Property: {2}",
							prop.MDToken.ToUInt32(),
							new MDToken(Table.Property, newRid).ToUInt32(),
							Utils.RemoveNewlines(prop));
				}

				foreach (var evt in type.Events) {
					newRid = md.GetRid(evt);
					if (newRid == 0)
						continue;
					Logger.v("{0:X8} -> {1:X8} Event: {2}",
							evt.MDToken.ToUInt32(),
							new MDToken(Table.Event, newRid).ToUInt32(),
							Utils.RemoveNewlines(evt));
				}

				Logger.Instance.DeIndent();
			}
			Logger.Instance.DeIndent();
		}
Example #14
0
		public void OnWriterEvent(ModuleWriterBase writer, ModuleWriterEvent evt) {
			if (otherListener != null)
				otherListener.OnWriterEvent(writer, evt);
			if (evt == ModuleWriterEvent.End)
				PrintTokens(writer);
		}