Just wanted to drop a quick note regarding eEye's recently released bin-diffing tool:
For those of you who are interested, Ero and I are giving a 2-day course in Vegas at Blackhat on Reverse Engineering on Windows. While the class will have a malware centric focus, the main purpose of the course is to glean general reversing knowledge and techniques. In the process PaiMei will certainly be covered, explored and experimented with. With that shameless self plug said and done, onto the main reason behind this posting.
hooks = utils.hook_container()
Next resolve and add hooks for your target functions. In our case, we will need to hook RtlAllocateHeap, RtlFreeHeap and RtlReAllocateHeap. All located within NTDLL.DLL:
a = dbg.func_resolve("ntdll", "RtlAllocateHeap")
f = dbg.func_resolve("ntdll", "RtlFreeHeap")
r = dbg.func_resolve("ntdll", "RtlReAllocateHeap")
hooks.add(dbg, a, 3, None, RtlAllocateHeap)
hooks.add(dbg, f, 3, None, RtlFreeHeap)
hooks.add(dbg, r, 4, None, RtlReAllocateHeap)
The first argument to the hook container object is an instance of PyDbg, the second is the address of the API to hook, followed by the number of arguments the API supports, a callback function for when the API is entered and finally a callback function for when the API exits. The entry-point callback provides you with the argument list, allowing you to instrument the arguments prior to passing control back to the API. The exit-point callback provides you with the argument list and return value, allowing you to instrument the return value prior to passing control back to the caller.
With that out of the way it's fairly trivial to generate and dynamically maintain a pgraph structure as well as display the results in real time through uDraw. Whenever RtlAllocateHeap is called, we'll create an orange node containing the address of the calling instruction, a blue node containing the allocation size and we'll connect the two nodes together. This is sufficient for a demo, but as we are hooking the lowest user-mode level heap manipulation routines the calling instruction address will likely lie within a Windows DLL and is not all that interesting. To improve this we could examine dbg.stack_unwind() and utilize the first address that lies within a non Microsoft DLL. Whenever RtlFreeHeap is called we will examine the arguments and remove the buffer address from the graph. Finally, whenever RtlReAllocateHeap is called, we'll resize the target buffer and paint the node yellow. We can then easily tie it to uDraw through the udraw_connector. All said and done, here is a flash excerpt from the code in action: http://pedram.redhive.com/PaiMei/heap_trace/ You can grab the code behind this application from heap_trace.py. As an experiment I tossed in some to disk rendering once the graph node count reaches 1000. It's all pretty simple. One of the nice things about this class is that it (I think / hope) transparently takes care of various thread-related race conditions that make pairing arguments and return values more tricky than trivial.
Just publicly released an advisory affecting the Microsoft Windows kernel: Microsoft SRV.SYS Mailslot Ring0 Memory Corruption Vulnerability. I worked with H D Moore (who you most recently heard of from his Browser Fun blog) in discovering this bug. This is a great example of the benefits of having a custom SMB stack, many thanks to HD for sacrificing his Sunday afternoon with me on this.
push 0 ; lpSecurityAttributes
push 0 ; lReadTimeout
push 0 ; nMaxMessageSize
push slot_name ; "\\\\.\\mailslot\\mailslot_name"
call CreateMailslotA
The nMaxMessageSize argument is key as it specifies the maximum size of a single message that can be written to the Mailslot in bytes, a value of zero allows for any arbitrary size (this is what you want). So the big question is, what else is exposed? I know of at least one 3rd party application, details of which will be released when a patch is available. A combination of Googling and examinaton of a number of targets tells me that Mailslot usage is pretty rare (fortunate or unfortunate depending on your point of view), but I'm curious to see what the masses discover.
As promised, to those of you at my RECON talk, the initial release of PaiMei is available for download from:
It took a few days of (interspersed) debugging but I finally got memory breakpoints implemented in the Python Win32 debugging engine I wrote last weekend. It's built on the Python ctypes module, which I'm very fond of. Many thanks to the people I leaned on at various times while pulling my hair out trying to figure out what was wrong (hoglund, spoon, skape, drew ...). I'll make it available at some point, it's currently way too ugly but very functional:
def attach:
def bp_del:
def bp_del_mem:
def bp_is_ours:
def bp_is_ours_mem:
def bp_set:
def bp_set_mem:
def cleanup:
def debug_event_loop:
def detach:
def disasm:
def dump_context:
def enumerate_threads:
def exception_handler_breakpoint:
def exception_handler_guard_page:
def exception_handler_single_step:
def func_resolve:
def get_thread_context:
def hex_dump:
def hide_debugger:
def is_address_on_stack:
def is_printable_ascii:
def is_printable_unicode:
def little_endian:
def load:
def process_restore:
def process_snapshot:
def read_process_memory:
def resume_thread:
def set_callback:
def set_register:
def set_thread_context:
def single_step:
def smart_dereference:
def stack_range:
def suspend_thread:
def terminate_process:
def virtual_protect:
def virtual_query:
def write_process_memory:
It's interesting being able to quickly prototype various debugging based ideas in Python:
pydbg = pydbg()
pydbg.set_callback(EXCEPTION_BREAKPOINT, h_bp)
pydbg.set_callback(EXCEPTION_ACCESS_VIOLATION, h_av)
try:
pydbg.attach(pid)
recv = pydbg.func_resolve("ws2_32", "recv")
recvfrom = pydbg.func_resolve("ws2_32", "recvfrom")
pydbg.bp_set(recv)
pydbg.bp_set(recvfrom)
pydbg.debug_event_loop()
except pdx, x:
sys.stderr.write(x.__str__() + "\n")
There is still an oustanding question of how exactly Windows deals with guard pages. I put that question up in the forums so people can respond to it:
http://www.openrce.org/forums/posts/110 |