Pwnium CTF – Kernel land write-up

So.. My first CTF writeup! I participated with a few others in the Pwnium capture-the-flag. One of the challenges I looked at was the Reverse Engineering challenge “Kernel Land”. The challenge gave a link to a binary with the tip: “The third Tick gives you the answer ;)”. After a first peek it appeared to be a linux binary:

root@kalipwn:~/Downloads# file kernel
kernel: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), statically linked, not stripped

And a first run:

root@kalipwn:~/Downloads# ./kernel
Segmentation fault

After further examination with IDA this doesn’t appear to be a generic linux executable but (as the challenge name suggests) a custom written linux kernel! Let’s inspect the main function:

main-func

It appears to:

  • clear the screen (monitor_clear)
  • Print “Booting…”
  • Print some addresses (dump_mboot)
  • GDT initialization (Global Description Table)
  • IDT initialization (Interrupt Description Table)
  • IRQ initialization (Interrupt Request)
  • Timer initialization!

Hmm.. Timer initialization? “The third Tick gives you the answer ;)”.

timer-init

This function calls irq_install_handler to install a custom IRQ handler for IRQ0 (system clock). Let’s have a look at this IRQ handler, timer_tick!

timer-callback

This looks interesting! We see a variable called “flag” (dead giveaway..) and a suspicious looking string which get’s modified every tick. Time to debug this and see what “flag” contains after the third thick.

flag-debugging

We use  QEMU to run and debug the kernel. We can connect to it using GDB and step though the timer_tick callbacks, reviewing what is in the flag variable. And there it is.. After three thicks we have the flag!

But there is another way! Another team member came up with a different approach. timer_tick basically does a xor operation on the flag operation with a key:


++*(_DWORD *)&idt[128];
printf("%d Tick..\n");
key = idt[128];
result = 0;
do{
    flag[result] = (flag[result] ^ key) + 1;
    ++result;
}while ( result != 40 );

So he wrote a little python script to bruteforce the flag which was also quite effective:


#!/usr/bin/python
import sys
 
d = bytearray('Itofrjxb2`..c.2.6031]g6b1gg0^)b11cb^^-]z')
for i in range(256):
    for ii in range(40):
        d[ii] = ((d[ii] ^ i+1) + 1) & 0xFF
        print 'key %d: %s' % ( i, str(d) )

Output:

key 0: Ivohtlzd4b00c0408231]g8d1gg2`)d11cd``-]|
key 1: Lunkwoyg7a33b373;124`f;g4ff1c,g44bgcc0`⌂
key 2: Pwnium{e5c11b1519328df9e8ff3a0e88beaa4d}
key 3: UtknrjÇb2h66g626>87=ac>b=cc8f5b==gbff1az
key 4: Qrolxpåh8n44c484<>39egd1h99chdd5eÇ
key 5: Xujk⌂wüo?i33f3?3;96@db;o@bb9c8o@@focc4dç
key 6: `snmyqçi9o55b595=?2Hdf=iHff?e@iHHbiee4dü
key 7: i|gfrzÉb2h>>k>2>68;Amo6bAoo8nIbAAkbnn=mè
key 8: avop|tÜl<b88c8<8@23Ieg@lIgg2hAlIIclhh5eä
key 9: l}f{w⌂æg7i33j373K9:DpnKgDnn9cLgDDjgcc@pÅ
key 10: hwnq}uøm=c99b9=9A32P|fAmPff3iHmPPbmiiL|à
key 11: e|c~rzÿb2p66o626N@?]qkNb]kk@fEb]]obffAqè
key 12: irotÇxûp@~<<c<@<DN3Q}gDpQggNlIpQQcpllM}ê key 13: h}b{ÅwÖ⌂Oq33n3O3KA>`tjK⌂`jjAcH⌂``n⌂ccDtç
.....snip.....