Skip to content

Instantly share code, notes, and snippets.

@nguerrera
Last active August 17, 2017 23:18
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save nguerrera/6864d2a907cb07d869be5a2afed8d764 to your computer and use it in GitHub Desktop.
Save nguerrera/6864d2a907cb07d869be5a2afed8d764 to your computer and use it in GitHub Desktop.
static void OpenEmbeddedResources(string path)
{
using (var peStream = File.OpenRead(path))
using (var peReader = new PEReader(peStream))
{
var mdReader = peReader.GetMetadataReader();
foreach (var resourceHandle in mdReader.ManifestResources)
{
var resource = mdReader.GetManifestResource(resourceHandle);
if (!resource.Implementation.IsNil)
{
continue; // resource is not embedded.
}
using (var resourceStream = peReader.GetEmbeddedResourceStream(resource))
{
// profit!
}
}
}
}
/// <summary>
/// Get the bytes in an embedded resource as a Stream.
/// WARNING: It is incorrect to read from this stream after the PEReader has been disposed.
/// </summary>
static unsafe Stream GetEmbeddedResourceStream(this PEReader peReader, ManifestResource resource)
{
if (!resource.Implementation.IsNil)
{
throw new ArgumentException("Resource is not embedded in the PE file.", "resource");
}
checked // arithmetic overflow here could cause AV
{
// Locate start and end of PE image in unmanaged memory.
var block = peReader.GetEntireImage();
Debug.Assert(block.Pointer != null && block.Length > 0);
byte* peImageStart = block.Pointer;
byte* peImageEnd = peImageStart + block.Length;
// Locate offset to resources within PE image.
int offsetToResources;
if (!peReader.PEHeaders.TryGetDirectoryOffset(peReader.PEHeaders.CorHeader.ResourcesDirectory, out offsetToResources))
{
throw new InvalidDataException("Failed to get offset to resources in PE file.");
}
Debug.Assert(offsetToResources > 0);
byte* resourceStart = peImageStart + offsetToResources + resource.Offset;
// Get the length of the the resource from the first 4 bytes.
if (resourceStart >= peImageEnd - sizeof(int))
{
throw new InvalidDataException("resource offset out of bounds.");
}
int resourceLength = new BlobReader(resourceStart, sizeof(int)).ReadInt32();
resourceStart += sizeof(int);
if (resourceLength < 0 || resourceStart >= peImageEnd - resourceLength)
{
throw new InvalidDataException("resource offset or length out of bounds.");
}
return new UnmanagedMemoryStream(resourceStart, resourceLength);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment