Freebsd kernel remote debugging. Part1

As Freebsd is an active and maintained operating system. It's offer some debugger software for programmer working on it. There is a user space and kernel space  debugger. We'll mostly working on the later one.

But before  let's resume in one image the final goal we want to achieve.

To do a source level, step by step debugging. We need to setup a remote debugging environment consisting mainly of two Freebsd operating system.
I'm using Oracle virtualbox as it allow us to setup things easily than using real physical machine which need a serial cable. And you know, modern laptop at least don't support this at all apart from using some usb converter.
And in virtualbox we can create a virtual serial connexion between the 2 Freebsd VM.

Naming convention:
- Target VM: The VM which will be the target of the attack and need to be
  debugged from another remote VM.
- DEBUG VM: The VM used to perform a source level debugging against
  the target VM.

Without further words let's get straight to the actual step needed for this.
- First download an AMD64 Freebsd iso image from the official site.
- Of course you need to install virtualbox.
- Install the Freebsd iso with source codes options enabled.
- Now an important step, we need to rebuild the freebsd kernel with debugging symbol so we can enable source level debugging later on.
 - cd into /usr/src/sys/amd64/conf
 - create a copy of the original config file : cp GENERIC GENERIC_DBG
 - Edit the newly copied GENERIC_DBG file by adding some new options
   options DDB and options GDB.
 - cd  /usr/src
 - make buildkernel KERNCONF=GENERIC_DBG
 - make installkernel KERNCONF=GENERIC_DBG

- Once this step is done and you confirmed that new kernel has been installed by
  running the uname command, clone this VM and name the cloned VM
  differently.
- Another important step, we need to setup a virtual serial connection between
  the two VM. But first power off the two VM.
  
  - Target VM:
    - Click on the VM setting->Serial Ports->Port1
    - Enable Serial Port option.
     - Choose COM1 as port number.
     - Port mode: Host Pipe
     - Leave the option connect to existing pipe/socket unchecked.
     - Choose a path for the pipe. (Mine: /home/michael/Exploit/pipe)
       This will create a pipe socket when VM is powered on.
   - DEBUG VM:
    - Click on the VM setting->Serial Ports->Port1
    - Enable Serial Port option.
     - Choose COM1 as port number.
     - Port mode: Host Pipe
     - Enable the option connect to existing pipe/socket
     - Choose the same path like the Target VM.
- Now, we need to enable some uart flag on the Target VM. Power on the VM
  and edit or add hint.uart.0.flags="0xC0" in /boot/device.hints
  reboot it.
- After rebooting the Target VM, start the DEBUG VM.
- On Target VM, enter ddb mode: sysctl debug.kdb.enter=1
  and type gdb it will now wait the DEBUG VM for command.
- On the DEBUG VM side, type:  
   kgdb -r /dev/cuau0 /usr/obj/usr/src/sys/GENERIC_DBG/kernel.debug
It will enter a gdb mode, and we can begin to do a source level debugging from now. Type continue to let the TARGET VM continue it's execution.

We'll begin to debug a ICMP hook modules as use case.
- nethook.c: The actual icmp kernel hook modules in C.
- Makefile: Makefile for nethook.c


We'll use this C modules through this series, It's an example of a reachable 
vulnerable networking code from a remote a remote attacker. 
There is a stack based overflow vulnerability in the process_icmp function.

What this code does is just replacing  the original icmp_input function inside freebsd kernel networking code which used to process an icmp packet from the IP layer. So all ICMP packet will be intercepted by our function instead of the original.

Now, copying these two file   nethook.c and Makefile into each VM.
I've been using ssh and scp that connect into these VM doing this.
 
On Target VM:
- make DEBUG_FLAGS='-g -O0' 
- kldload ./nethook.ko 
- sysctl debug.kdb.enter=1 
- Type gdb in ddb.

On DEBUG VM:
- make DEBUG_FLAGS='-g -O0' 
- cd /usr/obj/usr/src/sys/GENERIC_DBG/
- kgdb -r /dev/cuau0 ./kernel.debug
  (kgdb) add-kld pathto_nethook.ko
  (kgdb) break process_icmp
  (kgdb) c

You can ping the Target VM from your HOST(ex:Linux) and you we'll see that the DEBUG VM cathed the breakpoint against process_icmp function.
This is because ping tools use ICMP protocol.



                                           Figure 1: DEBUG VM: Setting breakpoint



                                          Figure 2: DEBUG VM: Breakpoint catched.

We can inspect all variable, structure, registers, like normal user space
debugging
 


                                           Figure 3: DEBUG VM: Back trace
                       


                                         Figure 4: DEBUG VM: Info reg




We've done the debugging environment now. In the next part we'll use all of these for exploring deep and deep into the FreeBSD kernel.
Thanks for reading.

http://freebsd.org/
https://www.freebsd.org/doc/en/books/handbook/kernelconfig-building.html
https://www.freebsd.org/doc/en_US.ISO8859-1/books/developers-handbook/kerneldebug-online-gdb.html


Comments