|
Thoughts on "Using dual-mappings to evade automated unpackers"
Uninformed 10 was released recently. On it Skape brings about a simple, yet beautiful and powerful idea. The paper itself is short and concise but a quick summary would be along the lines of: some generic unpackers use, either as their main technique or as an heuristic, the tracking of memory writes and whenever the execution flow hits those written areas an assumption is made that unpacked (or self-modifying code) has been reached. This is an over-simplification because of multi-staged unpackers and other details, but will suffice for the sake of the discussion. Skape basically introduces a technique by which hes able to write into a range of virtual addresses an execute from another range, both pointing to the same real data. This is a well supported technique and nothing strange of itself. It is its use what is creative and rather amusing as it breaks the assumption mentioned earlier. Given that no writes are seen in the area of memory that will be executed. The technique relies on the possibility of having several virtual addresses refer the same physical memory. The Memory Management Unit (MMU) allows pages of virtual memory to map to common physical locations in order to avoid, for instance, the need of having multiple copies of shared components between different processes. Some of the tools having trouble with this trick cant really do much about it but other tools he mentions in the paper should have no issue handling it in some way or another. Ive been working with Bochs for a few years. The technique should be (and is) easily defeatable by tools providing a birds eye perspective like Bochs or by tools running in kernel mode. Analyzing the generally one-to-one mapping of virtual-to-physical memory to find a one-to-many relationship is not all that difficult, and the case where a set of virtually mapped pages receive writes and not much more and another set pointing to the same physical ranges is only (or mostly just) executed should be easy to determine. Thatd be a simple heuristic but attempting to defeat it by writing to the execute-only mapping would break down the whole idea... Its definitely a beatiful idea but its easy to detect if youre on the right spot. One can take a quick look at it if you have Windbg lying around. Just connect to your test machine running a test process that implements the code that Skape outlines. Do a quick process listing to find it by issuing: !process 0 0 Then, take a look at the Cid of the process of interest and get its details with: !process <Cid> In that listing the page directory base DirBase will be given. With that we can tell Windbg to do the mapping of a virtual address using the virtual-to-physical mapping of that process by pasing the directory base to the !vtop command. In my case the DirBase of my process was f5a and Ill instruct Windbg to give me the corresponding physical address to which the virtual addresses 0x419000 and 0x519000 are mapped (those addresses are specific to the example code I wrote implementing skapes idea) lkd> !vtop f5a 0x419000 Pdi 1 Pti 19 00419000 14a79000 pfn(14a79) lkd> !vtop f5a 0x519000 Pdi 1 Pti 119 00519000 14a79000 pfn(14a79) As you can see both lead to the same physical location 14a79000. So its easy to see this from kernel mode by walking the page directory of a process under surveillance. If you want to see all physical-virtual mappings the following command provides that: !ptov f5a Ive also implemented detection of this trick in some Python scripts Ive developed for my Python-weaponized Bochs environment. On that front. I have an up-to-date patch for Bochs (improved from what I introduced at HitB in Dubai). While I hope to be able to eventually work with the Bochs developers to merge it anyone that wants to give it a shot it welcome to shoot me an email... Ill be talking on packers and their techniques on the forthcoming Hack in the Box in Kuala Lumpur. Ill be there next week and later in November at Power Of Community in Korea. |