Skip to content

MemPE v0.2.0

Choose a tag to compare

@techlinn techlinn released this 31 Jul 06:33
· 21 commits to main since this release

Import recovery got a lot better. mempe reads the delay-load directory now, and
it understands the register-load form of an import reference instead of only
call and jmp. Dumping kernel32 recovers 1274 of the 1292 imports the file
actually has. The packed test binaries each picked up around 205.

The checksum has been wrong this whole time. mempe copied the header block out
of memory and never updated the field, so every file it wrote claimed a checksum
that described completely different bytes. It is recomputed now and agrees with
what Windows calculates for the same file.

Two things got added to the summary that describe what mempe saw rather than
what it did. It reports whether the entry point sits inside surviving unwind
data, which ordinary compiler output almost always has and hand-written stubs
usually do not. It also counts sections that were writable and executable at the
same moment. Neither one is a judgement about the target.

There is a new warning for executable sections that are high-entropy but were
never written after the image was mapped. That combination usually means the
section was still encrypted when the snapshot happened, so what mempe wrote is
not real code. The warning is about mempe's own output, not about the program.

Dumps of a stomped module used to be fabricated: if the headers in memory were
unreadable, mempe read the original file off disk and spliced its headers onto
whatever was there. It now checks the memory is still backed by that file first.

Carving looks at non-image memory, which is where a .NET assembly loaded from a
byte array lives. New --raw-regions flag writes executable memory that held no
complete PE, for headerless payloads. Off by default, it can produce a lot of
files.

Test count went from 40 to 56, and each new test was checked by deliberately
breaking the code it covers to confirm it fails.

Worth knowing: the wider instruction decoding picks up two entries on kernel32
that are runtime function pointers rather than genuine imports, 2 out of 1276.
Both point at real APIs, they are just not load-time dependencies.