Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Parsing PE file in memory #48

Closed
aelth opened this issue Mar 14, 2018 · 5 comments
Closed

Parsing PE file in memory #48

aelth opened this issue Mar 14, 2018 · 5 comments

Comments

@aelth
Copy link

aelth commented Mar 14, 2018

Hi,

first of all thanks for PeNet, it is a great library!
I have one feature request - the ability to parse PE file directly from memory, without the need to copy the contents to another buffer.
I tried to implement this myself using Streams, but I got stuck since the byte array usage is used in every parser and it seems to me that switch to memory streams would be very consuming (although I might be wrong).

Thanks,
aelth

@secana
Copy link
Owner

secana commented Mar 15, 2018

Hi @aelth,
first, thanks! Good to hear that you like it.

I'm not sure if I understand your use case correctly. There is the function public PeFile(byte[] buff) to create a PeFile from a existing buffer. The buffer is used by reference, so no new copy is made.

Could you elaborate a bit more what you need?

Regards,
secana

@aelth
Copy link
Author

aelth commented Mar 15, 2018

Hi,

I'm sorry, I asked a question in a hurry without throughly thinking about it:(

What I'm trying to do is to traverse the list of active processes and obtain the PE structure of the mapped file (process image) or any loaded DLL without reading the file from the disk.
The main problem is that I'm dealing with remote memory (i.e. memory of another process), so I must first map (i.e. read) that memory into memory space of my process.
So I was thinking about the stream-like interface, where I would pass my custom stream to PeNet and when PeNet tries to read from the stream, the stream would actually read remote process memory.
The same thing could be done by copying the memory to byte array and passing the array to PeNet constructor.

But, I was actually trying to avoid reading/copying/mapping the entire PE structure and tried to just parse the structures that I'm interested in (for example NT headers and section headers).
My question should have rather been "Is it possible to parse parts of the PE structure without parsing entire file?". And I see this could be very easily implemented by just initializing NativeStructureParsers - in my modified version of PeNet I added additional constructor parameter that just initializes "native structures" and it perfectly suits my needs.

Sorry again for my misleading question.

Cheers,
aelth

@secana
Copy link
Owner

secana commented Mar 15, 2018

Very interesting use case. I didn't have that in mind when I wrote PeNet. So you solved your problem by using the NativeStructureParsers? If you have some changes, that you would to see in the official lib, just give me a pull request, or tell me what you need.

@aelth
Copy link
Author

aelth commented Mar 19, 2018

At the end NativeStructureParsers were not fully adequate for my task, because I don't know the size of my "native" headers in advance (the offset of NT headers, sections, etc.).

I solved my problem by reading the structures directly, taking fixed lengths into account and parsing sizes when needed. It looks something like this:

byte[] rawHeader = process.ReadMemory<byte[]>(baseAddress, sizeOfDOSHeader);
IMAGE_DOS_HEADER dosHeader = new IMAGE_DOS_HEADER(rawHeader, 0);

// some error checking here

IntPtr pNtHeaders = (IntPtr)(baseAddress.ToInt64() + dosHeader.e_lfanew);

// take signature into account (+4)!
byte[] fileHeaderRaw = process.ReadMemory<byte[]>(pNtHeaders, sizeOfFileHeader + 4);

// check NT signature
if(fileHeaderRaw[0] != 0x50 || fileHeaderRaw[1] != 0x45)
{
   // error handling here
}

IMAGE_FILE_HEADER fileHeader = new IMAGE_FILE_HEADER(fileHeaderRaw, 4);

// some more checks here

byte[] optionalHeaderRaw = process.ReadMemory<byte[]>((IntPtr)(pNtHeaders.ToInt64() + 4 + sizeOfFileHeader), fileHeader.SizeOfOptionalHeader);

IMAGE_OPTIONAL_HEADER optionalHeader = new IMAGE_OPTIONAL_HEADER(optionalHeaderRaw, 0, fileHeader.Machine == (ushort)Constants.FileHeaderMachine.IMAGE_FILE_MACHINE_AMD64);

...

It is a bit hacky and I'm using PeNet structures directly, but it works:)
This is in no way issue with PeNet - I'm just trying to extend it usage to "in-memory" files.
In my program, I'm also using it in the standard (intended) way and it works very well!

Regarding the pull request, I don't think I have one, I just used the structures as described...

Thanks again for your help!

aelth

@secana
Copy link
Owner

secana commented Mar 20, 2018

Alright, good to hear that you found a solution. I'll close the issue. Whenever you have another question or idea feel free to create a new one.
Cheers!

@secana secana closed this as completed Mar 20, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants