Skip to content

Debugging

magrazia edited this page May 24, 2016 · 1 revision

Many times during the development of the framework we needed to assess our results. Fortunately, we have the source code of our test-case (Chuck - the kernel ROP rootkit), and the VM to execute it (provided by the Chuck's author).

In this page I show you how we used GDB, extended with a set of Python3 plugins to extract information about the running rootkit and compare them with the results of our framework. Keep in mind that the assessment framework is working on the live virtual machine while ROPMEMU is working on a memory dump.

Chasing the dispatcher chain

The scenario is the following. We log in the VM. We attach GDB and we run the rootkit. We want to skip the copy chain and directly go to the dispatcher chain.

First step, we have to attach to the running VM.

      > gdb -q -ex "set disassembly-flavor intel" -ex "set architecture i386:x86-64:intel" -ex "target remote:1234"
	The target architecture is assumed to be i386:x86-64:intel
	Remote debugging using :1234
	0xffffffff81043fa6 in ?? ()

Second, we need the pointer to the copy chain and we use the GDB Python script chuckgetcopyptr. In the guest OS, this pointer changes at every reboot. Of course in the VM we have to run the rootkit :-)

	(gdb) source chuckgetcopyptr.py 
	--[ ROPMEMU framework - GDB utils ]--

	[+] Patching...
	[+] Setting the breakpoint...
	Breakpoint 1 at 0xffffffff810039a0
	[+] Back to the VM
	[+] Reading RAX...
	[+] Copy Chain initial ptr: ffff880024400000 
	-----
	0xffff880024400000:     0xffffffff8100a4de      0xffff880024800000
	0xffff880024400010:     0xffffffff8115c832      0xffffffff8100a4de
	0xffff880024400020:     0xffff880024800008      0xffffffff81060147
	0xffff880024400030:     0xffffffff8115c832      0xffffffff810051ae
	0xffff880024400040:     0xffffffff816a9434      0xffffffff812ce029
	-----

	Breakpoint 1, 0xffffffff810039a0 in ?? ()

Then we set a breakpoint on POP RSP; RET, the switching sequence. We want to detect the switching to a new chain.

	(gdb) b *0xffffffff81423f82
	Breakpoint 2 at 0xffffffff81423f82
	(gdb) c
	Continuing.
	Breakpoint 2, 0xffffffff81423f82 in ?? ()

We load boundary to detect a new chain by monitoring the SP deltas.

	(gdb) source boundary.py
	(gdb) boundary System.map-3.8.0-19-generic
	--[ ROPMEMU framework - GDB utils ]--

	[+] Chasing the dispatcher chain...
	1) 0xffff88002461b770 - 0xffff88002461b770
	0xffffffff81423f83 in ?? ()
	2) 0xffff880028382000 - 0xffff88002461b770
	[+] last_sp: 0xffff88002461b770 - current_sp: 0xffff880028382000
	[+] 2 instructions executed!

We use unropandroll to generate traces and compare the assembly instructions and the CPU context.

	(gdb) source unropandroll.py 
	(gdb) unrop 
	--[ ROPMEMU framework - GDB utils ]--

	+-------------------------------------------------------------------------------------
	| Usage: unrop <num_of_instrs> <output_file> <System.map> <mode> <multipath>
	| Mode: 0 Normal txt trace - 1: JSON output with registers
	| Multipath: NULL, default:0, default:1 - sp1:zf,sp2:zf - Pushf based
	+-------------------------------------------------------------------------------------
	(gdb) unrop 300 /tmp/gdb_dispatacher_300_0.json System.map-3.8.0-19-generic 1 default:0

spmonitor

Another interesting script is spmonitor. This script monitors the evolution of the stack pointer, in this way it is possible to figure out possible mistakes during the stack emulation. We run it from GDB:

            (gdb) source spmonitor.py 
	(gdb) spmonitor 
	--[ ROPMEMU framework - GDB utils ]--

	+--------------------------------------------------------------------+
	| Usage: spmonitor <num_of_instrs> <output_file> <System.map>        |
	+--------------------------------------------------------------------+
	(gdb) spmonitor 10 /tmp/spmonitor_10.log System.map-3.8.0-19-generic

it generates /tmp/spmonitor_10.log that it looks like:

            pop rax | 0xffff880024c00008 | 0xffff880024c00010 | 0x8
	ret | 0xffff880024c00010 | 0xffff880024c00018 | 0x8
	mov [rax], rdx | 0xffff880024c00018 | 0xffff880024c00018 | 0x0
	ret | 0xffff880024c00018 | 0xffff880024c00020 | 0x8
Clone this wiki locally