dotnet / runtime

.NET is a cross-platform runtime for cloud, mobile, desktop, and IoT apps.
https://docs.microsoft.com/dotnet/core/
MIT License
15.04k stars 4.68k forks source link

More offsets in MetadataReader #14540

Closed krwq closed 4 years ago

krwq commented 9 years ago

I believe MetadataReader should have more APIs which tell me about offsets.

I. e.: Let's say I'm writing strong name signer, there are few steps required (assuming that assembly is already delayed signed):

to calculate hash you need to skip some parts of the PE file like:

so I need to have offsets and sizes for each of those. For blobs there are already APIs: i.e.:

peReader.PEHeaders.CorHeader.StrongNameSignatureDirectory.Size
peReader.PEHeaders.CorHeader.StrongNameSignatureDirectory.RelativeVirtualAddress
peReader.PEHeaders.PEHeader.CertificateTableDirectory.Size
peReader.PEHeaders.PEHeader.CertificateTableDirectory.RelativeVirtualAddress

what is missing is:

for blob headers we can do simple change in System.Reflection.PortableExecutable.DirectoryEntry which is:

    public struct DirectoryEntry
    {
//...
+       public readonly int HeaderOffset;
//...
        internal DirectoryEntry(ref PEBinaryReader reader)
        {
+           HeaderOffset = reader.CurrentOffset;
            RelativeVirtualAddress = reader.ReadInt32();
            Size = reader.ReadInt32();
        }
//...
    }

For stuff like CheckSum offset we need something like this:

    public sealed class PEHeader
    {
//...
+       public int BaseOffset; // this might be always 0 so const would be fine too
//...
+       public const int CheckSumOffset;
+       public const int CheckSumSize;
+       //etc. for other fields
}

cc: @nguerrera @tmat

What are your thoughts? With good modifications we could probably reuse some of those types when writing MetadataWriter (assuming we are planning to do that)

krwq commented 9 years ago

Also what I found useful is size of: DOS Header + PeHeader + PEOptionalHeader + DataDirectory headers (after this point there is padding and then sections) as the padding is not being hashed when calculating hash for the strong name signing.

tmat commented 7 years ago

We exposed more APIs, perhaps not sufficient yet, but I think close. See TestChecksumAndAuthenticodeSignature test in https://source.dot.net/#System.Reflection.Metadata.Tests/PortableExecutable/PEBuilderTests.cs,663

krwq commented 7 years ago

Nice! Thanks @tmat!

karelz commented 7 years ago

We need to find out if the scenario of signing built binary has good enough API. Maybe we do not need any API at all.

scott-xu commented 4 years ago

Looking forward about signing API (sign/verify) for PE/COFF formats. The SignTool.exe is windows only and has no switch to turn off revocation check.

ericstj commented 4 years ago

This library does not implement signing, the discussion was about exposing enough API so that one could implement strong name signing on top of this API. This issue remains only about exposing offsets. Note that strong-name signing is different from Authenticode signing, which is what signtool does. We aren't discussing authenticode at all in this issue.

I took a look at what was exposed and it looks like it covers @krwq's suggestion.

checksum offset (and optionally a size)

https://github.com/dotnet/runtime/blob/110282c71b3f7e1f91ea339953f4a0eba362a62c/src/libraries/System.Reflection.Metadata/tests/PortableExecutable/PEBuilderTests.cs#L723-L725

blob headers

peHeaders.PEHeaderStartOffset