Skip to content

Reference: Dumping Memory background on relocations

ktwo/ShaneK2 edited this page Jul 23, 2017 · 1 revision

Volatile memory forensic investigation

A complicated and tedious process that currently involves significant manual tasking and far too often, major assumptions. It often amazes me that when one of the most beneficial tactics of an attacker is misdirection, that we accept massive known vulnerabilities in accepted best practices.

These are not the bytes you are looking for...

Secure hash verification is the hallmark of file based integrity validation and attestation (known what your looking at is really what you think it is.). Major companies are build on the premise of this, perhaps the original tripwire is famously known even today as a considerably powerful defense when used comprehensively. Times changed and as it stands, in-memory-only attacks are here to stay. There will be not tripwire event or alert to help isolate what's going on during a compromise.

A secondary aspect of the in-memory attack is that (at least on Windows) it is typical for a binary to be modified by the PE loader between disk and it's in-memory representation. This was originally done to benefit run-time performance over load time, these modifications were a sort of glue to make references more efficient known as "Relocations". Due to the historical nature of when relocations were devised, they were determined not to be needed after loading (correctly so) and a waste of memory so, they are unloaded immediately after any binary loads. This makes things a real pain to then figure out if a given memory block originated from your disk or if it's the result of a compromise. So much so that I believe it's an intractable problem that if you think you have a solution, you're probably wrong.

Straddling

No not Texas Hold’em straddling, even though the effect of page straddling instructions raises the steaks against our efforts. Some pages may be out of memory (i.e. in the page file, not "paged-in" to memory), which will (almost without exception) result in an instruction which straddles two pages to be the target of a relocation.

Address Bytes Instructions
7778f000 44 e6 80 out 80h,al
7778f003 77 ff ja 7778f004
7778f005 55 push rbp
7778f006 f4 hlt

Unfortunately, when presented with the above bytes as code. Any possible disassembly based auto-analysis is significantly disadvantaged so greatly that I believe it should not be done. The potential for abuse, poisoning of analysis and failures that would result should not be taken lightly in the belief that there’s an automated way to statically determine what to do in this (and infinite other) cases. The net result is that due to instruction page straddling.

At a page boundary any byte may be any value for a significant range (the max instruction size).

The offending instruction is highlighted below; this is what we should expect to see for an exact match.


Address Bytes Instructions
7778effc 8b c8 mov ecx,eax
7778effe ff 15 44 e6 80 77 call qword ptr [00000000`eef9d648]
7778f004 ff55f4 call qword ptr [rbp-0Ch]

Given the sort of issues we have to deal with completely out of our control, i.e. the Intel/AMD ABI allow's for arbitrary length instructions and there will be no hint or ability to calculate what those bytes should of been due to the fact that they represent the target of a call, which can be anywhere.

Since any given neighboring memory page may not be resident, the options are endless for an attacker to insert mal-code into such a memory location that can defy any manual analysis.

Now What? (back to basics)

To have confidence in your forensic process, it is required to delocate the code pages. Without doing so directly means that the level of confidence and any statements as to what took place during a compromise or any given given incident is marginal at best.

Try @K2/Reloc (cross platform delocation tool)

To resolve this sort of ambiguity and hopefully instill a confidence into the statements made by those charged with doing the impossible (e.g. Hey there, take a look at a few dozen GB of code over the next couple of days and provide me an understanding of what happened!). Lacking the sort of file based integrity mechanisms to perform this sort of a task is a nightmare that usually means a lot of statements like "The review was time limited so we did enough to catch a modestly sophisticated persistent threat".

This seems fairly understandable and the sort of pain point that allows sneaky (flame and others) malicious code to remain undetected for far too long periods of time.

At a macro scale, were being attacked by such a deluge of random attacks, whenever something written by the A+ team comes along, it slips under the radar due to institutional inertia.

Oh yeah, back to basics

All we need to do is dump and delocate memory and then visualize it (it's coming) in a way that when you look to the screen and see "Everything's Fine", you can have some confidence your not simply doing a strings based analysis and hoping you see the "l33+ S|gn4|ur3" of a well known, expected to find bad-guy.

Status

You can use inVtero.net to extract memory in an OS/micro-architecture independent way to extract memory (minimal and working towards ZERO dependencies on logical/flawed (under the control of an attacker) inputs). Delocate and then simply use a hash database similar to the NIST NSRL or other (IOActive BlockWatch, Microsoft Page Hash's).

The result is a road map of where to start a manual review. This isn't the solution, or end result, it's a process/procedure/technique/method to ensure your not wasting your time and looking at what's really important.

Typically pre Win10 can be baked down to 1/2 of 1% (so if you have 1GB of resident code in all of the processes and kernel combined, we hope to eliminate 995MB of it from anything you would care to look at). 5MB is not much in comparison but it is still significant, however using either differential analysis or recovering firmware/BIOS inputs and refining your hash databases you can improve this number.

Win10?

It should be noted that Win10+ kernels can be attested to at a 100% rate. So that makes life a bit easier right?