private static void WriteUTF16Z(ByteBuffer bb, string str) { foreach (char c in str) { bb.Write((short)c); } bb.Write((short)0); }
private void WriteEntry(ByteBuffer bb, ref int offset, Dictionary <string, int> strings, ref int stringTableOffset, ByteBuffer stringTable) { WriteNameOrOrdinal(bb, OrdinalOrName, strings, ref stringTableOffset, stringTable); if (Data == null) { bb.Write(0x80000000U | (uint)offset); } else { bb.Write(offset); } offset += 16 + entries.Count * 8; }
private static void WriteString(ByteBuffer bb, string name, string value) { value = value ?? " "; int pos = bb.Position; bb.Write((short)0); // wLength (placeholder) bb.Write((short)(value.Length + 1)); // wValueLength bb.Write((short)1); // wType WriteUTF16Z(bb, name); bb.Align(4); WriteUTF16Z(bb, value); bb.Align(4); int savedPos = bb.Position; bb.Position = pos; bb.Write((short)(savedPos - pos)); bb.Position = savedPos; }
internal void Write(MetadataWriter mw, uint rva) { foreach (int offset in linkOffsets) { bb.Position = offset; bb.Write(bb.GetInt32AtCurrentPosition() + (int)rva); } mw.Write(bb); }
private void WriteResourceDataEntries(ByteBuffer bb, List <int> linkOffsets, ref int offset) { foreach (ResourceDirectoryEntry entry in entries) { if (entry.Data != null) { linkOffsets.Add(bb.Position); bb.Write(offset); bb.Write(entry.Data.Length); bb.Write(0); // code page bb.Write(0); // reserved offset += (entry.Data.Length + 3) & ~3; } else { entry.WriteResourceDataEntries(bb, linkOffsets, ref offset); } } }
private void SetDataAndRvaImpl(byte[] data, ByteBuffer bb, int readonlyMarker) { attribs |= FieldAttributes.HasFieldRVA; FieldRVATable.Record rec = new FieldRVATable.Record(); bb.Align(8); rec.RVA = bb.Position + readonlyMarker; rec.Field = pseudoToken; typeBuilder.ModuleBuilder.FieldRVA.AddRecord(rec); bb.Write(data); }
private static void StrongName(Stream stream, StrongNameKeyPair keyPair, uint headerLength, uint textSectionFileOffset, uint strongNameSignatureFileOffset, uint strongNameSignatureLength) { SHA1Managed hash = new SHA1Managed(); using (CryptoStream cs = new CryptoStream(Stream.Null, hash, CryptoStreamMode.Write)) { stream.Seek(0, SeekOrigin.Begin); byte[] buf = new byte[8192]; HashChunk(stream, cs, buf, (int)headerLength); stream.Seek(textSectionFileOffset, SeekOrigin.Begin); HashChunk(stream, cs, buf, (int)(strongNameSignatureFileOffset - textSectionFileOffset)); stream.Seek(strongNameSignatureLength, SeekOrigin.Current); HashChunk(stream, cs, buf, (int)(stream.Length - (strongNameSignatureFileOffset + strongNameSignatureLength))); } using (RSA rsa = CryptoHack.CreateRSA(keyPair)) { RSAPKCS1SignatureFormatter sign = new RSAPKCS1SignatureFormatter(rsa); byte[] signature = sign.CreateSignature(hash); Array.Reverse(signature); if (signature.Length != strongNameSignatureLength) { throw new InvalidOperationException("Signature length mismatch"); } stream.Seek(strongNameSignatureFileOffset, SeekOrigin.Begin); stream.Write(signature, 0, signature.Length); } // compute the PE checksum stream.Seek(0, SeekOrigin.Begin); int count = (int)stream.Length / 4; BinaryReader br = new BinaryReader(stream); long sum = 0; for (int i = 0; i < count; i++) { sum += br.ReadUInt32(); int carry = (int)(sum >> 32); sum &= 0xFFFFFFFFU; sum += carry; } while ((sum >> 16) != 0) { sum = (sum & 0xFFFF) + (sum >> 16); } sum += stream.Length; // write the PE checksum, note that it is always at offset 0xD8 in the file ByteBuffer bb = new ByteBuffer(4); bb.Write((int)sum); stream.Seek(0xD8, SeekOrigin.Begin); bb.WriteTo(stream); }
private void Write(ByteBuffer bb, int writeDepth, int currentDepth, ref int offset, Dictionary <string, int> strings, ref int stringTableOffset, ByteBuffer stringTable) { if (currentDepth == writeDepth) { // directory header bb.Write(0); // Characteristics bb.Write(0); // Time/Date Stamp bb.Write(0); // Version (Major / Minor) bb.Write((ushort)namedEntries); bb.Write((ushort)(entries.Count - namedEntries)); } foreach (ResourceDirectoryEntry entry in entries) { if (currentDepth == writeDepth) { entry.WriteEntry(bb, ref offset, strings, ref stringTableOffset, stringTable); } else { entry.Write(bb, writeDepth, currentDepth + 1, ref offset, strings, ref stringTableOffset, stringTable); } } }
private static void WriteNameOrOrdinal(ByteBuffer bb, OrdinalOrName id, Dictionary <string, int> strings, ref int stringTableOffset, ByteBuffer stringTable) { if (id.Name == null) { bb.Write((int)id.Ordinal); } else { int stringOffset; if (!strings.TryGetValue(id.Name, out stringOffset)) { stringOffset = stringTableOffset; strings.Add(id.Name, stringOffset); stringTableOffset += id.Name.Length * 2 + 2; stringTable.Write((ushort)id.Name.Length); foreach (char c in id.Name) { stringTable.Write((short)c); } } bb.Write(0x80000000U | (uint)stringOffset); } }
private void WriteData(ByteBuffer bb) { foreach (ResourceDirectoryEntry entry in entries) { if (entry.Data != null) { bb.Write(entry.Data); bb.Align(4); } else { entry.WriteData(bb); } } }
private static void StrongName(Stream stream, StrongNameKeyPair keyPair, uint headerLength, uint textSectionFileOffset, uint strongNameSignatureFileOffset, uint strongNameSignatureLength) { byte[] hash; using (SHA1 sha1 = SHA1.Create()) { stream.Seek(0, SeekOrigin.Begin); Stream skipStream = new SkipStream(stream, strongNameSignatureFileOffset, strongNameSignatureLength); skipStream = new SkipStream(skipStream, headerLength, textSectionFileOffset - headerLength); hash = sha1.ComputeHash(skipStream); } using (RSACryptoServiceProvider rsa = keyPair.CreateRSA()) { byte[] signature = rsa.SignHash(hash, "1.3.14.3.2.26"); Array.Reverse(signature); if (signature.Length != strongNameSignatureLength) { throw new InvalidOperationException("Signature length mismatch"); } stream.Seek(strongNameSignatureFileOffset, SeekOrigin.Begin); stream.Write(signature, 0, signature.Length); } // compute the PE checksum stream.Seek(0, SeekOrigin.Begin); int count = (int)stream.Length / 4; BinaryReader br = new BinaryReader(stream); long sum = 0; for (int i = 0; i < count; i++) { sum += br.ReadUInt32(); int carry = (int)(sum >> 32); sum &= 0xFFFFFFFFU; sum += carry; } while ((sum >> 16) != 0) { sum = (sum & 0xFFFF) + (sum >> 16); } sum += stream.Length; // write the PE checksum, note that it is always at offset 0xD8 in the file ByteBuffer bb = new ByteBuffer(4); bb.Write((int)sum); stream.Seek(0xD8, SeekOrigin.Begin); bb.WriteTo(stream); }
internal void Write(ByteBuffer bb, List <int> linkOffsets) { if (entries.Count != 0) { int stringTableOffset = this.DirectoryLength; Dictionary <string, int> strings = new Dictionary <string, int>(); ByteBuffer stringTable = new ByteBuffer(16); int offset = 16 + entries.Count * 8; for (int pass = 0; pass < 3; pass++) { Write(bb, pass, 0, ref offset, strings, ref stringTableOffset, stringTable); } // the pecoff spec says that the string table is between the directory entries and the data entries, // but the windows linker puts them after the data entries, so we do too. stringTable.Align(4); offset += stringTable.Length; WriteResourceDataEntries(bb, linkOffsets, ref offset); bb.Write(stringTable); WriteData(bb); } }
private void WriteSigImpl(ModuleBuilder module, ByteBuffer bb, int parameterCount) { byte first; if ((callingConvention & CallingConventions.Any) == CallingConventions.VarArgs) { Debug.Assert(genericParamCount == 0); first = VARARG; } else if (genericParamCount > 0) { first = GENERIC; } else { first = DEFAULT; } if ((callingConvention & CallingConventions.HasThis) != 0) { first |= HASTHIS; } if ((callingConvention & CallingConventions.ExplicitThis) != 0) { first |= EXPLICITTHIS; } bb.Write(first); if (genericParamCount > 0) { bb.WriteCompressedInt(genericParamCount); } bb.WriteCompressedInt(parameterCount); // RetType if (modifiers != null && modifiers[0] != null) { WriteCustomModifiers(module, bb, ELEMENT_TYPE_CMOD_OPT, modifiers[0][0]); WriteCustomModifiers(module, bb, ELEMENT_TYPE_CMOD_REQD, modifiers[0][1]); } WriteType(module, bb, returnType); // Param for (int i = 0; i < parameterTypes.Length; i++) { if (modifiers != null && modifiers[i + 1] != null) { WriteCustomModifiers(module, bb, ELEMENT_TYPE_CMOD_OPT, modifiers[i + 1][0]); WriteCustomModifiers(module, bb, ELEMENT_TYPE_CMOD_REQD, modifiers[i + 1][1]); } WriteType(module, bb, parameterTypes[i]); } }
private static void WriteString(ByteBuffer bb, string str) { byte[] buf = Encoding.UTF8.GetBytes(str); bb.WriteCompressedUInt(buf.Length); bb.Write(buf); }
private static void WriteNameOrOrdinal(ByteBuffer bb, OrdinalOrName id, Dictionary<string, int> strings, ref int stringTableOffset, ByteBuffer stringTable) { if (id.Name == null) { bb.Write((int)id.Ordinal); } else { int stringOffset; if (!strings.TryGetValue(id.Name, out stringOffset)) { stringOffset = stringTableOffset; strings.Add(id.Name, stringOffset); stringTableOffset += id.Name.Length * 2 + 2; stringTable.Write((ushort)id.Name.Length); foreach (char c in id.Name) { stringTable.Write((short)c); } } bb.Write(0x80000000U | (uint)stringOffset); } }
private void Write(ByteBuffer bb, int writeDepth, int currentDepth, ref int offset, Dictionary<string, int> strings, ref int stringTableOffset, ByteBuffer stringTable) { if (currentDepth == writeDepth) { // directory header bb.Write(0); // Characteristics bb.Write(0); // Time/Date Stamp bb.Write(0); // Version (Major / Minor) bb.Write((ushort)namedEntries); bb.Write((ushort)(entries.Count - namedEntries)); } foreach (ResourceDirectoryEntry entry in entries) { if (currentDepth == writeDepth) { entry.WriteEntry(bb, ref offset, strings, ref stringTableOffset, stringTable); } else { entry.Write(bb, writeDepth, currentDepth + 1, ref offset, strings, ref stringTableOffset, stringTable); } } }
private void WriteResourceDataEntries(ByteBuffer bb, List<int> linkOffsets, ref int offset) { foreach (ResourceDirectoryEntry entry in entries) { if (entry.Data != null) { linkOffsets.Add(bb.Position); bb.Write(offset); bb.Write(entry.Data.Length); bb.Write(0); // code page bb.Write(0); // reserved offset += (entry.Data.Length + 3) & ~3; } else { entry.WriteResourceDataEntries(bb, linkOffsets, ref offset); } } }
internal BlobHeap() { buf.Write((byte)0); }
internal static void WriteMethodSpec(ModuleBuilder module, ByteBuffer bb, Type[] genArgs) { bb.Write(GENERICINST); bb.WriteCompressedUInt(genArgs.Length); foreach (Type arg in genArgs) { WriteType(module, bb, arg); } }
protected static void WriteType(ModuleBuilder module, ByteBuffer bb, Type type) { while (type.HasElementType) { if (type.__IsVector) { bb.Write(ELEMENT_TYPE_SZARRAY); } else if (type.IsArray) { int rank = type.GetArrayRank(); bb.Write(ELEMENT_TYPE_ARRAY); // LAMESPEC the Type production (23.2.12) doesn't include CustomMod* for arrays, but the verifier allows it and ildasm also supports it WriteCustomModifiers(module, bb, ELEMENT_TYPE_CMOD_REQD, type.__GetRequiredCustomModifiers()); WriteCustomModifiers(module, bb, ELEMENT_TYPE_CMOD_OPT, type.__GetOptionalCustomModifiers()); WriteType(module, bb, type.GetElementType()); bb.WriteCompressedInt(rank); // since a Type doesn't contain the lower/upper bounds // (they act like a custom modifier, so they are part of the signature, but not of the Type), // we set them to the C# compatible values and hope for the best bb.WriteCompressedInt(0); // boundsCount bb.WriteCompressedInt(rank); // loCount for (int i = 0; i < rank; i++) { bb.WriteCompressedInt(0); } return; } else if (type.IsByRef) { bb.Write(ELEMENT_TYPE_BYREF); } else if (type.IsPointer) { bb.Write(ELEMENT_TYPE_PTR); } WriteCustomModifiers(module, bb, ELEMENT_TYPE_CMOD_REQD, type.__GetRequiredCustomModifiers()); WriteCustomModifiers(module, bb, ELEMENT_TYPE_CMOD_OPT, type.__GetOptionalCustomModifiers()); type = type.GetElementType(); } Universe u = module.universe; if (type == u.System_Void) { bb.Write(ELEMENT_TYPE_VOID); } else if (type == u.System_Int32) { bb.Write(ELEMENT_TYPE_I4); } else if (type == u.System_Boolean) { bb.Write(ELEMENT_TYPE_BOOLEAN); } else if (type == u.System_String) { bb.Write(ELEMENT_TYPE_STRING); } else if (type == u.System_Char) { bb.Write(ELEMENT_TYPE_CHAR); } else if (type == u.System_SByte) { bb.Write(ELEMENT_TYPE_I1); } else if (type == u.System_Byte) { bb.Write(ELEMENT_TYPE_U1); } else if (type == u.System_Int16) { bb.Write(ELEMENT_TYPE_I2); } else if (type == u.System_UInt16) { bb.Write(ELEMENT_TYPE_U2); } else if (type == u.System_UInt32) { bb.Write(ELEMENT_TYPE_U4); } else if (type == u.System_Int64) { bb.Write(ELEMENT_TYPE_I8); } else if (type == u.System_UInt64) { bb.Write(ELEMENT_TYPE_U8); } else if (type == u.System_Single) { bb.Write(ELEMENT_TYPE_R4); } else if (type == u.System_Double) { bb.Write(ELEMENT_TYPE_R8); } else if (type == u.System_IntPtr) { bb.Write(ELEMENT_TYPE_I); } else if (type == u.System_UIntPtr) { bb.Write(ELEMENT_TYPE_U); } else if (type == u.System_TypedReference) { bb.Write(ELEMENT_TYPE_TYPEDBYREF); } else if (type == u.System_Object) { bb.Write(ELEMENT_TYPE_OBJECT); } else if (type.IsGenericParameter) { if (type is UnboundGenericMethodParameter || type.DeclaringMethod != null) { bb.Write(ELEMENT_TYPE_MVAR); } else { bb.Write(ELEMENT_TYPE_VAR); } bb.WriteCompressedInt(type.GenericParameterPosition); } else if (type.IsGenericType) { WriteGenericSignature(module, bb, type); } else { if (type.IsValueType) { bb.Write(ELEMENT_TYPE_VALUETYPE); } else { bb.Write(ELEMENT_TYPE_CLASS); } bb.WriteTypeDefOrRefEncoded(module.GetTypeToken(type).Token); } }
protected static void WriteCustomModifiers(ModuleBuilder module, ByteBuffer bb, byte mod, Type[] modifiers) { if (modifiers != null) { foreach (Type type in modifiers) { bb.Write(mod); bb.WriteTypeDefOrRefEncoded(module.GetTypeTokenForMemberRef(type)); } } }
// unmanaged calling convention internal static void WriteStandAloneMethodSig(ModuleBuilder module, ByteBuffer bb, CallingConvention callingConvention, Type returnType, Type[] parameterTypes) { switch (callingConvention) { case CallingConvention.Cdecl: bb.Write((byte)0x01); // C break; case CallingConvention.StdCall: case CallingConvention.Winapi: bb.Write((byte)0x02); // STDCALL break; case CallingConvention.ThisCall: bb.Write((byte)0x03); // THISCALL break; case CallingConvention.FastCall: bb.Write((byte)0x04); // FASTCALL break; default: throw new ArgumentOutOfRangeException("callingConvention"); } bb.WriteCompressedInt(parameterTypes.Length); WriteType(module, bb, returnType); foreach (Type t in parameterTypes) { WriteType(module, bb, t); } }
// managed calling convention internal static void WriteStandAloneMethodSig(ModuleBuilder module, ByteBuffer bb, CallingConventions callingConvention, Type returnType, Type[] parameterTypes, Type[] optionalParameterTypes) { byte flags = 0; if ((callingConvention & CallingConventions.HasThis) != 0) { flags |= HASTHIS; } if ((callingConvention & CallingConventions.ExplicitThis) != 0) { flags |= EXPLICITTHIS; } if ((callingConvention & CallingConventions.VarArgs) != 0) { flags |= VARARG; } bb.Write(flags); bb.WriteCompressedInt(parameterTypes.Length + optionalParameterTypes.Length); WriteType(module, bb, returnType); foreach (Type t in parameterTypes) { WriteType(module, bb, t); } if (optionalParameterTypes.Length > 0) { bb.Write(SENTINEL); foreach (Type t in optionalParameterTypes) { WriteType(module, bb, t); } } }
internal static void WriteLocalVarSig(ModuleBuilder module, ByteBuffer bb, IList<LocalBuilder> locals) { bb.Write(LOCAL_SIG); bb.WriteCompressedInt(locals.Count); foreach (LocalBuilder local in locals) { if (local.IsPinned) { bb.Write(ELEMENT_TYPE_PINNED); } WriteType(module, bb, local.LocalType); } }
internal static void WritePropertySig(ModuleBuilder module, ByteBuffer bb, CallingConventions callingConvention, Type returnType, Type[] returnTypeRequiredCustomModifiers, Type[] returnTypeOptionalCustomModifiers, Type[] parameterTypes, Type[][] parameterTypeRequiredCustomModifiers, Type[][] parameterTypeOptionalCustomModifiers) { byte flags = PROPERTY; if ((callingConvention & CallingConventions.HasThis) != 0) { flags |= HASTHIS; } if ((callingConvention & CallingConventions.ExplicitThis) != 0) { flags |= EXPLICITTHIS; } if ((callingConvention & CallingConventions.VarArgs) != 0) { flags |= VARARG; } bb.Write(flags); bb.WriteCompressedInt(parameterTypes == null ? 0 : parameterTypes.Length); WriteCustomModifiers(module, bb, ELEMENT_TYPE_CMOD_REQD, returnTypeRequiredCustomModifiers); WriteCustomModifiers(module, bb, ELEMENT_TYPE_CMOD_OPT, returnTypeOptionalCustomModifiers); WriteType(module, bb, returnType); if (parameterTypes != null) { for (int i = 0; i < parameterTypes.Length; i++) { if (parameterTypeRequiredCustomModifiers != null) { WriteCustomModifiers(module, bb, ELEMENT_TYPE_CMOD_REQD, parameterTypeRequiredCustomModifiers[i]); } if (parameterTypeOptionalCustomModifiers != null) { WriteCustomModifiers(module, bb, ELEMENT_TYPE_CMOD_OPT, parameterTypeOptionalCustomModifiers[i]); } WriteType(module, bb, parameterTypes[i]); } } }
internal void AddIcon(byte[] iconFile) { BinaryReader br = new BinaryReader(new MemoryStream(iconFile)); ushort idReserved = br.ReadUInt16(); ushort idType = br.ReadUInt16(); ushort idCount = br.ReadUInt16(); if (idReserved != 0 || idType != 1) { throw new ArgumentException("The supplied byte array is not a valid .ico file."); } ByteBuffer group = new ByteBuffer(6 + 14 * idCount); group.Write(idReserved); group.Write(idType); group.Write(idCount); for (int i = 0; i < idCount; i++) { byte bWidth = br.ReadByte(); byte bHeight = br.ReadByte(); byte bColorCount = br.ReadByte(); byte bReserved = br.ReadByte(); ushort wPlanes = br.ReadUInt16(); ushort wBitCount = br.ReadUInt16(); uint dwBytesInRes = br.ReadUInt32(); uint dwImageOffset = br.ReadUInt32(); // we start the icon IDs at 2 ushort id = (ushort)(2 + i); group.Write(bWidth); group.Write(bHeight); group.Write(bColorCount); group.Write(bReserved); group.Write(wPlanes); group.Write(wBitCount); group.Write(dwBytesInRes); group.Write(id); byte[] icon = new byte[dwBytesInRes]; Buffer.BlockCopy(iconFile, (int)dwImageOffset, icon, 0, icon.Length); root[new OrdinalOrName(RT_ICON)][new OrdinalOrName(id)][new OrdinalOrName(0)].Data = ByteBuffer.Wrap(icon); } root[new OrdinalOrName(RT_GROUP_ICON)][new OrdinalOrName(32512)][new OrdinalOrName(0)].Data = group; }
internal static void WriteStandAloneMethodSig(ModuleBuilder module, ByteBuffer bb, __StandAloneMethodSig sig) { if (sig.IsUnmanaged) { switch (sig.UnmanagedCallingConvention) { case CallingConvention.Cdecl: bb.Write((byte)0x01); // C break; case CallingConvention.StdCall: case CallingConvention.Winapi: bb.Write((byte)0x02); // STDCALL break; case CallingConvention.ThisCall: bb.Write((byte)0x03); // THISCALL break; case CallingConvention.FastCall: bb.Write((byte)0x04); // FASTCALL break; default: throw new ArgumentOutOfRangeException("callingConvention"); } } else { CallingConventions callingConvention = sig.CallingConvention; byte flags = 0; if ((callingConvention & CallingConventions.HasThis) != 0) { flags |= HASTHIS; } if ((callingConvention & CallingConventions.ExplicitThis) != 0) { flags |= EXPLICITTHIS; } if ((callingConvention & CallingConventions.VarArgs) != 0) { flags |= VARARG; } bb.Write(flags); } Type[] parameterTypes = sig.ParameterTypes; Type[] optionalParameterTypes = sig.OptionalParameterTypes; bb.WriteCompressedUInt(parameterTypes.Length + optionalParameterTypes.Length); WriteCustomModifiers(module, bb, sig.GetReturnTypeCustomModifiers()); WriteType(module, bb, sig.ReturnType); int index = 0; foreach (Type t in parameterTypes) { WriteCustomModifiers(module, bb, sig.GetParameterCustomModifiers(index++)); WriteType(module, bb, t); } // note that optional parameters are only allowed for managed signatures (but we don't enforce that) if (optionalParameterTypes.Length > 0) { bb.Write(SENTINEL); foreach (Type t in optionalParameterTypes) { WriteCustomModifiers(module, bb, sig.GetParameterCustomModifiers(index++)); WriteType(module, bb, t); } } }
internal static void WriteSignatureHelper(ModuleBuilder module, ByteBuffer bb, byte flags, ushort paramCount, List<Type> args) { bb.Write(flags); if (flags != FIELD) { bb.WriteCompressedUInt(paramCount); } foreach (Type type in args) { if (type == null) { bb.Write(ELEMENT_TYPE_VOID); } else if (type is MarkerType) { bb.Write(type.SigElementType); } else { WriteType(module, bb, type); } } }
private static void StrongName(FileStream fs, StrongNameKeyPair keyPair, uint headerLength, uint textSectionFileOffset, uint strongNameSignatureFileOffset, uint strongNameSignatureLength) { SHA1Managed hash = new SHA1Managed(); using (CryptoStream cs = new CryptoStream(Stream.Null, hash, CryptoStreamMode.Write)) { fs.Seek(0, SeekOrigin.Begin); byte[] buf = new byte[8192]; HashChunk(fs, cs, buf, (int)headerLength); fs.Seek(textSectionFileOffset, SeekOrigin.Begin); HashChunk(fs, cs, buf, (int)(strongNameSignatureFileOffset - textSectionFileOffset)); fs.Seek(strongNameSignatureLength, SeekOrigin.Current); HashChunk(fs, cs, buf, (int)(fs.Length - (strongNameSignatureFileOffset + strongNameSignatureLength))); } using (RSA rsa = CryptoHack.CreateRSA(keyPair)) { RSAPKCS1SignatureFormatter sign = new RSAPKCS1SignatureFormatter(rsa); sign.SetHashAlgorithm("SHA1"); byte[] signature = sign.CreateSignature(hash.Hash); Array.Reverse(signature); Debug.Assert(signature.Length == strongNameSignatureLength); fs.Seek(strongNameSignatureFileOffset, SeekOrigin.Begin); fs.Write(signature, 0, signature.Length); } // compute the PE checksum fs.Seek(0, SeekOrigin.Begin); int count = (int)fs.Length / 4; BinaryReader br = new BinaryReader(fs); long sum = 0; for (int i = 0; i < count; i++) { sum += br.ReadUInt32(); int carry = (int)(sum >> 32); sum &= 0xFFFFFFFFU; sum += carry; } while ((sum >> 16) != 0) { sum = (sum & 0xFFFF) + (sum >> 16); } sum += fs.Length; // write the PE checksum, note that it is always at offset 0xD8 in the file ByteBuffer bb = new ByteBuffer(4); bb.Write((int)sum); fs.Seek(0xD8, SeekOrigin.Begin); bb.WriteTo(fs); }
internal void Write(ByteBuffer bb, List<int> linkOffsets) { if (entries.Count != 0) { int stringTableOffset = this.DirectoryLength; Dictionary<string, int> strings = new Dictionary<string, int>(); ByteBuffer stringTable = new ByteBuffer(16); int offset = 16 + entries.Count * 8; for (int pass = 0; pass < 3; pass++) { Write(bb, pass, 0, ref offset, strings, ref stringTableOffset, stringTable); } // the pecoff spec says that the string table is between the directory entries and the data entries, // but the windows linker puts them after the data entries, so we do too. stringTable.Align(4); offset += stringTable.Length; WriteResourceDataEntries(bb, linkOffsets, ref offset); bb.Write(stringTable); WriteData(bb); } }
internal override void WriteSig(ModuleBuilder module, ByteBuffer bb) { byte flags = PROPERTY; if ((callingConvention & CallingConventions.HasThis) != 0) { flags |= HASTHIS; } if ((callingConvention & CallingConventions.ExplicitThis) != 0) { flags |= EXPLICITTHIS; } if ((callingConvention & CallingConventions.VarArgs) != 0) { flags |= VARARG; } bb.Write(flags); bb.WriteCompressedInt(parameterTypes == null ? 0 : parameterTypes.Length); WriteCustomModifiers(module, bb, customModifiers.GetReturnTypeCustomModifiers()); WriteType(module, bb, propertyType); if (parameterTypes != null) { for (int i = 0; i < parameterTypes.Length; i++) { WriteCustomModifiers(module, bb, customModifiers.GetParameterCustomModifiers(i)); WriteType(module, bb, parameterTypes[i]); } } }
internal void WriteMethodRefSig(ModuleBuilder module, ByteBuffer bb, Type[] optionalParameterTypes, CustomModifiers[] customModifiers) { WriteSigImpl(module, bb, parameterTypes.Length + optionalParameterTypes.Length); if (optionalParameterTypes.Length > 0) { bb.Write(SENTINEL); for (int i = 0; i < optionalParameterTypes.Length; i++) { WriteCustomModifiers(module, bb, Util.NullSafeElementAt(customModifiers, i)); WriteType(module, bb, optionalParameterTypes[i]); } } }
private void WriteEntry(ByteBuffer bb, ref int offset, Dictionary<string, int> strings, ref int stringTableOffset, ByteBuffer stringTable) { WriteNameOrOrdinal(bb, OrdinalOrName, strings, ref stringTableOffset, stringTable); if (Data == null) { bb.Write(0x80000000U | (uint)offset); } else { bb.Write(offset); } offset += 16 + entries.Count * 8; }
protected static void WriteType(ModuleBuilder module, ByteBuffer bb, Type type) { while (type.HasElementType) { byte sigElementType = type.SigElementType; bb.Write(sigElementType); if (sigElementType == ELEMENT_TYPE_ARRAY) { // LAMESPEC the Type production (23.2.12) doesn't include CustomMod* for arrays, but the verifier allows it and ildasm also supports it WriteCustomModifiers(module, bb, type.__GetCustomModifiers()); WriteType(module, bb, type.GetElementType()); bb.WriteCompressedUInt(type.GetArrayRank()); int[] sizes = type.__GetArraySizes(); bb.WriteCompressedUInt(sizes.Length); for (int i = 0; i < sizes.Length; i++) { bb.WriteCompressedUInt(sizes[i]); } int[] lobounds = type.__GetArrayLowerBounds(); bb.WriteCompressedUInt(lobounds.Length); for (int i = 0; i < lobounds.Length; i++) { bb.WriteCompressedInt(lobounds[i]); } return; } WriteCustomModifiers(module, bb, type.__GetCustomModifiers()); type = type.GetElementType(); } if (type.__IsBuiltIn) { bb.Write(type.SigElementType); } else if (type.IsGenericParameter) { bb.Write(type.SigElementType); bb.WriteCompressedUInt(type.GenericParameterPosition); } else if (!type.__IsMissing && type.IsGenericType) { WriteGenericSignature(module, bb, type); } else if (type.__IsFunctionPointer) { bb.Write(ELEMENT_TYPE_FNPTR); WriteStandAloneMethodSig(module, bb, type.__MethodSignature); } else { if (type.IsValueType) { bb.Write(ELEMENT_TYPE_VALUETYPE); } else { bb.Write(ELEMENT_TYPE_CLASS); } bb.WriteTypeDefOrRefEncoded(module.GetTypeToken(type).Token); } }
private static void WriteGenericSignature(ModuleBuilder module, ByteBuffer bb, Type type) { Type[] typeArguments = type.GetGenericArguments(); CustomModifiers[] customModifiers = type.__GetGenericArgumentsCustomModifiers(); if (!type.IsGenericTypeDefinition) { type = type.GetGenericTypeDefinition(); } bb.Write(ELEMENT_TYPE_GENERICINST); if (type.IsValueType) { bb.Write(ELEMENT_TYPE_VALUETYPE); } else { bb.Write(ELEMENT_TYPE_CLASS); } bb.WriteTypeDefOrRefEncoded(module.GetTypeToken(type).Token); bb.WriteCompressedUInt(typeArguments.Length); for (int i = 0; i < typeArguments.Length; i++) { WriteCustomModifiers(module, bb, customModifiers[i]); WriteType(module, bb, typeArguments[i]); } }
internal void WriteMethodRefSig(ModuleBuilder module, ByteBuffer bb, Type[] optionalParameterTypes) { WriteSigImpl(module, bb, parameterTypes.Length + optionalParameterTypes.Length); if (optionalParameterTypes.Length > 0) { bb.Write(SENTINEL); foreach (Type type in optionalParameterTypes) { WriteType(module, bb, type); } } }
protected static void WriteCustomModifiers(ModuleBuilder module, ByteBuffer bb, CustomModifiers modifiers) { foreach (CustomModifiers.Entry entry in modifiers) { bb.Write(entry.IsRequired ? ELEMENT_TYPE_CMOD_REQD : ELEMENT_TYPE_CMOD_OPT); bb.WriteTypeDefOrRefEncoded(module.GetTypeTokenForMemberRef(entry.Type)); } }
private static void WriteString(ByteBuffer bb, string name, string value) { value = value ?? " "; int pos = bb.Position; bb.Write((short)0); // wLength (placeholder) bb.Write((short)(value.Length + 1));// wValueLength bb.Write((short)1); // wType WriteUTF16Z(bb, name); bb.Align(4); WriteUTF16Z(bb, value); bb.Align(4); int savedPos = bb.Position; bb.Position = pos; bb.Write((short)(savedPos - pos)); bb.Position = savedPos; }
private static void StrongName(Stream stream, StrongNameKeyPair keyPair, uint headerLength, uint textSectionFileOffset, uint strongNameSignatureFileOffset, uint strongNameSignatureLength) { SHA1Managed hash = new SHA1Managed(); using (CryptoStream cs = new CryptoStream(Stream.Null, hash, CryptoStreamMode.Write)) { stream.Seek(0, SeekOrigin.Begin); byte[] buf = new byte[8192]; HashChunk(stream, cs, buf, (int)headerLength); stream.Seek(textSectionFileOffset, SeekOrigin.Begin); HashChunk(stream, cs, buf, (int)(strongNameSignatureFileOffset - textSectionFileOffset)); stream.Seek(strongNameSignatureLength, SeekOrigin.Current); HashChunk(stream, cs, buf, (int)(stream.Length - (strongNameSignatureFileOffset + strongNameSignatureLength))); } using (RSA rsa = keyPair.CreateRSA()) { RSAPKCS1SignatureFormatter sign = new RSAPKCS1SignatureFormatter(rsa); byte[] signature = sign.CreateSignature(hash); Array.Reverse(signature); if (signature.Length != strongNameSignatureLength) { throw new InvalidOperationException("Signature length mismatch"); } stream.Seek(strongNameSignatureFileOffset, SeekOrigin.Begin); stream.Write(signature, 0, signature.Length); } // compute the PE checksum stream.Seek(0, SeekOrigin.Begin); int count = (int)stream.Length / 4; BinaryReader br = new BinaryReader(stream); long sum = 0; for (int i = 0; i < count; i++) { sum += br.ReadUInt32(); int carry = (int)(sum >> 32); sum &= 0xFFFFFFFFU; sum += carry; } while ((sum >> 16) != 0) { sum = (sum & 0xFFFF) + (sum >> 16); } sum += stream.Length; // write the PE checksum, note that it is always at offset 0xD8 in the file ByteBuffer bb = new ByteBuffer(4); bb.Write((int)sum); stream.Seek(0xD8, SeekOrigin.Begin); bb.WriteTo(stream); }
internal void Write(ByteBuffer bb) { if (fileVersion == null) { if (name.Version != null) { fileVersion = name.Version.ToString(); } else { fileVersion = "0.0.0.0"; } } int codepage = 1200; // Unicode codepage int lcid = 0x7f; if (name.CultureInfo != null) { lcid = name.CultureInfo.LCID; } if (culture != null) { lcid = new CultureInfo(culture).LCID; } Version filever = ParseVersionRobust(fileVersion); int fileVersionMajor = filever.Major; int fileVersionMinor = filever.Minor; int fileVersionBuild = filever.Build; int fileVersionRevision = filever.Revision; int productVersionMajor = fileVersionMajor; int productVersionMinor = fileVersionMinor; int productVersionBuild = fileVersionBuild; int productVersionRevision = fileVersionRevision; if (informationalVersion != null) { Version productver = ParseVersionRobust(informationalVersion); productVersionMajor = productver.Major; productVersionMinor = productver.Minor; productVersionBuild = productver.Build; productVersionRevision = productver.Revision; } ByteBuffer stringTable = new ByteBuffer(512); stringTable.Write((short)0); // wLength (placeholder) stringTable.Write((short)0); // wValueLength stringTable.Write((short)1); // wType WriteUTF16Z(stringTable, string.Format("{0:x4}{1:x4}", lcid, codepage)); stringTable.Align(4); WriteString(stringTable, "Comments", description); WriteString(stringTable, "CompanyName", company); WriteString(stringTable, "FileDescription", title); WriteString(stringTable, "FileVersion", fileVersion); WriteString(stringTable, "InternalName", name.Name); WriteString(stringTable, "LegalCopyright", copyright); WriteString(stringTable, "LegalTrademarks", trademark); WriteString(stringTable, "OriginalFilename", fileName); WriteString(stringTable, "ProductName", product); WriteString(stringTable, "ProductVersion", informationalVersion); stringTable.Position = 0; stringTable.Write((short)stringTable.Length); ByteBuffer stringFileInfo = new ByteBuffer(512); stringFileInfo.Write((short)0); // wLength (placeholder) stringFileInfo.Write((short)0); // wValueLength stringFileInfo.Write((short)1); // wType WriteUTF16Z(stringFileInfo, "StringFileInfo"); stringFileInfo.Align(4); stringFileInfo.Write(stringTable); stringFileInfo.Position = 0; stringFileInfo.Write((short)stringFileInfo.Length); byte[] preamble1 = new byte[] { // VS_VERSIONINFO (platform SDK) 0x34, 0x00, // wValueLength 0x00, 0x00, // wType 0x56, 0x00, 0x53, 0x00, 0x5F, 0x00, 0x56, 0x00, 0x45, 0x00, 0x52, 0x00, 0x53, 0x00, 0x49, 0x00, 0x4F, 0x00, 0x4E, 0x00, 0x5F, 0x00, 0x49, 0x00, 0x4E, 0x00, 0x46, 0x00, 0x4F, 0x00, 0x00, 0x00, // "VS_VERSION_INFO\0" 0x00, 0x00, // Padding1 (32 bit alignment) // VS_FIXEDFILEINFO starts 0xBD, 0x04, 0xEF, 0xFE, // dwSignature (0xFEEF04BD) 0x00, 0x00, 0x01, 0x00, // dwStrucVersion }; byte[] preamble2 = new byte[] { 0x3F, 0x00, 0x00, 0x00, // dwFileFlagsMask (??) 0x00, 0x00, 0x00, 0x00, // dwFileFlags (??) 0x04, 0x00, 0x00, 0x00, // dwFileOS 0x02, 0x00, 0x00, 0x00, // dwFileType 0x00, 0x00, 0x00, 0x00, // dwFileSubtype 0x00, 0x00, 0x00, 0x00, // dwFileDateMS 0x00, 0x00, 0x00, 0x00, // dwFileDateLS // Padding2 (32 bit alignment) // VarFileInfo 0x44, 0x00, // wLength 0x00, 0x00, // wValueLength 0x01, 0x00, // wType 0x56, 0x00, 0x61, 0x00, 0x72, 0x00, 0x46, 0x00, 0x69, 0x00, 0x6C, 0x00, 0x65, 0x00, 0x49, 0x00, 0x6E, 0x00, 0x66, 0x00, 0x6F, 0x00, 0x00, 0x00, // "VarFileInfo\0" 0x00, 0x00, // Padding // Var 0x24, 0x00, // wLength 0x04, 0x00, // wValueLength 0x00, 0x00, // wType 0x54, 0x00, 0x72, 0x00, 0x61, 0x00, 0x6E, 0x00, 0x73, 0x00, 0x6C, 0x00, 0x61, 0x00, 0x74, 0x00, 0x69, 0x00, 0x6F, 0x00, 0x6E, 0x00, 0x00, 0x00, // "Translation\0" 0x00, 0x00, // Padding (32 bit alignment) }; bb.Write((short)(2 + preamble1.Length + 8 + 8 + preamble2.Length + 4 + stringFileInfo.Length)); bb.Write(preamble1); bb.Write((short)fileVersionMinor); bb.Write((short)fileVersionMajor); bb.Write((short)fileVersionRevision); bb.Write((short)fileVersionBuild); bb.Write((short)productVersionMinor); bb.Write((short)productVersionMajor); bb.Write((short)productVersionRevision); bb.Write((short)productVersionBuild); bb.Write(preamble2); bb.Write((short)lcid); bb.Write((short)codepage); bb.Write(stringFileInfo); }
internal void Write(ByteBuffer bb) { if (fileVersion == null) { if (name.Version != null) { fileVersion = name.Version.ToString(); } else { fileVersion = "0.0.0.0"; } } int codepage = 1200; // Unicode codepage int lcid = 0x7f; try { if (name.CultureInfo != null) { lcid = name.CultureInfo.LCID; } } catch (ArgumentException) { // AssemblyName.CultureInfo throws an ArgumentException if AssemblyBuilder.__SetAssemblyCulture() was used to specify a non-existing culture } Version filever = ParseVersionRobust(fileVersion); int fileVersionMajor = filever.Major; int fileVersionMinor = filever.Minor; int fileVersionBuild = filever.Build; int fileVersionRevision = filever.Revision; int productVersionMajor = fileVersionMajor; int productVersionMinor = fileVersionMinor; int productVersionBuild = fileVersionBuild; int productVersionRevision = fileVersionRevision; if (informationalVersion != null) { Version productver = ParseVersionRobust(informationalVersion); productVersionMajor = productver.Major; productVersionMinor = productver.Minor; productVersionBuild = productver.Build; productVersionRevision = productver.Revision; } ByteBuffer stringTable = new ByteBuffer(512); stringTable.Write((short)0); // wLength (placeholder) stringTable.Write((short)0); // wValueLength stringTable.Write((short)1); // wType WriteUTF16Z(stringTable, string.Format("{0:x4}{1:x4}", lcid, codepage)); stringTable.Align(4); WriteString(stringTable, "Comments", description); WriteString(stringTable, "CompanyName", company); WriteString(stringTable, "FileDescription", title); WriteString(stringTable, "FileVersion", fileVersion); WriteString(stringTable, "InternalName", name.Name); WriteString(stringTable, "LegalCopyright", copyright); WriteString(stringTable, "LegalTrademarks", trademark); WriteString(stringTable, "OriginalFilename", fileName); WriteString(stringTable, "ProductName", product); WriteString(stringTable, "ProductVersion", informationalVersion); stringTable.Position = 0; stringTable.Write((short)stringTable.Length); ByteBuffer stringFileInfo = new ByteBuffer(512); stringFileInfo.Write((short)0); // wLength (placeholder) stringFileInfo.Write((short)0); // wValueLength stringFileInfo.Write((short)1); // wType WriteUTF16Z(stringFileInfo, "StringFileInfo"); stringFileInfo.Align(4); stringFileInfo.Write(stringTable); stringFileInfo.Position = 0; stringFileInfo.Write((short)stringFileInfo.Length); byte[] preamble1 = new byte[] { // VS_VERSIONINFO (platform SDK) 0x34, 0x00, // wValueLength 0x00, 0x00, // wType 0x56, 0x00, 0x53, 0x00, 0x5F, 0x00, 0x56, 0x00, 0x45, 0x00, 0x52, 0x00, 0x53, 0x00, 0x49, 0x00, 0x4F, 0x00, 0x4E, 0x00, 0x5F, 0x00, 0x49, 0x00, 0x4E, 0x00, 0x46, 0x00, 0x4F, 0x00, 0x00, 0x00, // "VS_VERSION_INFO\0" 0x00, 0x00, // Padding1 (32 bit alignment) // VS_FIXEDFILEINFO starts 0xBD, 0x04, 0xEF, 0xFE, // dwSignature (0xFEEF04BD) 0x00, 0x00, 0x01, 0x00, // dwStrucVersion }; byte[] preamble2 = new byte[] { 0x3F, 0x00, 0x00, 0x00, // dwFileFlagsMask (??) 0x00, 0x00, 0x00, 0x00, // dwFileFlags (??) 0x04, 0x00, 0x00, 0x00, // dwFileOS 0x02, 0x00, 0x00, 0x00, // dwFileType 0x00, 0x00, 0x00, 0x00, // dwFileSubtype 0x00, 0x00, 0x00, 0x00, // dwFileDateMS 0x00, 0x00, 0x00, 0x00, // dwFileDateLS // Padding2 (32 bit alignment) // VarFileInfo 0x44, 0x00, // wLength 0x00, 0x00, // wValueLength 0x01, 0x00, // wType 0x56, 0x00, 0x61, 0x00, 0x72, 0x00, 0x46, 0x00, 0x69, 0x00, 0x6C, 0x00, 0x65, 0x00, 0x49, 0x00, 0x6E, 0x00, 0x66, 0x00, 0x6F, 0x00, 0x00, 0x00, // "VarFileInfo\0" 0x00, 0x00, // Padding // Var 0x24, 0x00, // wLength 0x04, 0x00, // wValueLength 0x00, 0x00, // wType 0x54, 0x00, 0x72, 0x00, 0x61, 0x00, 0x6E, 0x00, 0x73, 0x00, 0x6C, 0x00, 0x61, 0x00, 0x74, 0x00, 0x69, 0x00, 0x6F, 0x00, 0x6E, 0x00, 0x00, 0x00, // "Translation\0" 0x00, 0x00, // Padding (32 bit alignment) }; bb.Write((short)(2 + preamble1.Length + 8 + 8 + preamble2.Length + 4 + stringFileInfo.Length)); bb.Write(preamble1); bb.Write((short)fileVersionMinor); bb.Write((short)fileVersionMajor); bb.Write((short)fileVersionRevision); bb.Write((short)fileVersionBuild); bb.Write((short)productVersionMinor); bb.Write((short)productVersionMajor); bb.Write((short)productVersionRevision); bb.Write((short)productVersionBuild); bb.Write(preamble2); bb.Write((short)lcid); bb.Write((short)codepage); bb.Write(stringFileInfo); }