Memory buffers for… initiated, part 2 – Frida(y) edition

In my last post I boasted about my tool that could dump memory blocks that included plain vanilla perl, or .bat code obfuscated using a number of ‘2exe’ converters. Boasting is fun, but what about trying to share the actual tool instead?

While I can’t share the tool, I can do better — in this short post I will prototype 2 Frida handlers to do the job for me and since their code is available you can not only adjust it to your needs, but also copy the ideas presented and use it to hook & dump buffers of other APIs.

I am not very well versed in modern JavaScript, I used to code in it for a living at some stage in my past, but things changed so much since that I am basically a JavaScript noob. Secondly, I am also a Frida noob. Hence, the code I am going to present you is not top notch. Still, better some than none 🙂

In my original tool I was injecting a code into a monitored process; that code would then hook RtlFreeHeap function and the hook would make a call to RtlSizeHeap at the time of memory freeing. I needed the latter to obtain the size of the memory dump I wanted to save to a file.

With Frida, I took a simpler approach. I hook RtlAllocateHeap and anytime it is called I store the returned memory address and its requested size in an internal buffer. When RtlFreeHeap is called, I simply do a lookup in a table and obtain the size from there. If the size is larger than 1MB I just truncate the buffer to 1MB. Simple, and seems to work. Note that resizing of memory blocks is not supported and will break things.

That’s it really. All you have to do is to drop these 2 handlers in __handlers__\NtDll.dll\ and run:

frida-trace -i RtlFreeHeap -i RtlAllocateHeap -f <exe>

The heap buffers will be stored in a heap_buffers.bin file.

Since I referred to rfc.exe in my previous article, let’s have a look how the tool works with this .exe — reviewing the content of heap_buffers.bin we can see:

Not bad.

The code of both handlers is here.

See part 3 here.

Memory buffers for… initiated

Early Visual Basic program crackers knew that if you put a breakpoint in a right place, you can intercept strings entered into a text/input box. Once you do that, finding the key verification routine is easy as it will refer the memory buffer we can track after data is copied to it.

Around 13 years ago I was asked by an analyst on my team to help him with a WinBatch-compiled malicious sample. At that time there were not many options for analyzing these types of programs and of course, reading producers’ web site one would be discouraged to reverse engineer such executables as they are ‘close to impossible to crack’. After poking around I realized that the code of the ‘compiled’ batch file was actually available in plain text during run-time! It was decrypted and then stored in a memory block on a heap.

I was experimenting a lot with API hooking at that time and this particular experience led me to write a tool that was intercepting calls to a RtlFreeHeap function (HeapFree was forwarded to it), then dumping the content of a memory block the API referenced to a file before releasing the memory. You see, if you are a coder that is taught to free memory buffers after use, it’s only natural you will call these APIs. Even if you don’t really need to, because after process is killed these memory buffer will be killed anyway…

That tool I wrote back in 2008 was essential in handling many ‘script hidden by obfuscation more than anything else’ – it dealt with executables created by perl2exe, winbatch, and many bat2exe converters, and alike. It would literally take seconds to run a suspicious sample through that tool, review the data file it created, and cherry-pick the content that was of interest.

Because of that tool I was probably one of the first analysts being able to systematically dump code of many perl2exe samples targeting POS as well as forensic tools shared by prominent forensic experts e.g. compare rfc.exe vs. its source code, where the dump from my tool shows this (raw data + formatted):

Over next few years I started building a more robust sandbox and I added handling for buffers freed by many memory functions including VirtualFree, RtlFreeHeap, GlobalFree/LocalFree, free, NtFreeVirtualMemory and a few others that I knew contained buffers worth looking at.

Software analysis progressed really a lot since then and we have a gamut of decompilers, sandboxes, emulators, debuggers, plug-ins and both dynamic and static-oriented analysis tools now. It’s a treat.

Yet.

One thing remains constant – tricks are here to stay.

If you can cut reversing corners – you definitely should.

Check the second part of this series.