ProfileScan - Volatility plugin to guess profiles
Let’s do some forensics analysis, shall we ?
I recently found myself playing with CTF challenges featuring memory dumps to play a little bit with Volatility. For those who are new to this project, Volatility is an open-source framework written in Python2 which first goal is data and informations extraction from memory dumps. It lays on a system of plugins, which are loaded at runtime and can perform different actions, and profiles, which represent the system of the memory dump.
One of the first obstacle you usually encounter when faced with a dump,
especially in CTF, is recovering where it comes from and what it was running
before being dumped (for Volatility, the
profile). Indeed, Volatility’s plugins
are often OS dependant and some really useful (like
imageinfo, which gives you
the almost exact OS version of a Windows dump) are not available for every
There are multiple techniques to guess the operating system. One can grep for strings in the binary and try to recognize some patterns, manually or with a little bit of programming:
You can also try blindly to run
mac_get_profile, praying for
one to work. But you may waste time waiting for an output that may never come,
in the worst case.
So right, I decided to give it a try, and look for some ways to get informations
about the underlying operating system. My first try was as script
based on the previous
grep command, but a little bit more sophisticated, and OS
independant (python). It works pretty well for Linux and Windows, even if it is
waaaaay slower than grep, but fails with OSX. Why ? Because grepping for
“windows” might look clever, but since a ‘window’ is actually an object that
can represent any GUI component, you will see that every OS with any sense of
graphical interface will magically turn into Windows.
So right, let’s try to think of any other interesting keyword. I went on looking
vmlinuz for Linux kernels, but didn’t find anything for OSX. Plus, this
still was to slow to execute and too innaccurate.
So, what will almost everytime differentiate two different systems, such that we
can guess their profiles ?
Well, their executables will. Unix runs
ELFs, Windows runs
PEs/EXEs and OSX
Mach-Os. This could be a good indicator!
So the plan was to look for these formats’ signatures in the dump. Let’s do
things properly, and make a Volatility plugin out of it. So I took the
baseclass, and created one that would look for magic numbers in the dump, and
count them. This worked pretty well at first sight, but a magic number is rarely
more than 4 bytes, and even 2 for the PE format. I thus quickly saw PEs spawning
everywhere, and decided to restrict things a bit.
Problem is, a file header may change regarding the versions, size, etc. So I
needed something that would only look for the bytes that never changed. First,
let’s try to determine these bytes. For that, I took the naive way: a set of
each executable format, and
(The output was cropped so that it fits smoothly here.)
^ indicates a byte that never changes. To be able to verify only these bytes,
we will apply a mask on the bytes sequence that we want to compare to our
signature, and check if both are equal. The bytes we don’t care about are
0xff in the signature and the mask, and the interesting ones are
0x00 in the mask:
Translated in python, it gave this:
With strong signatures like this there were far less false positive and the
result was quite good, but very slow. Indeed, I had to read each byte sequence
X times (X being the number of signatures, of different length for some) and
check, which was way to long. So I looked for ways to reduce computations. My
first thought was to try to read the executable header and skip the size
registered in it. But Gaby reminded me that executables were always loaded at
the beginning of a memory page. Thus, instead of reading each byte, I read each
page’s first byte, and thus multiplied the speed by
So now, the plugin determines quite accurately the OS in less than a minute (which is still quite long, I still look for ways to speed it up), and is available on Github. I also found a way to get the linux distribution from a magic string in linux kernels; right now it seems quite accurate, but I only tested it on the sample set I was given.
Here is an output example: