Link Search Menu Expand Document

Polaris (Launched 1998)

  • Password: tolearn
  • (20 points)
Table of contents
  1. Starter files
  2. Your task
  3. The interact API
  4. Debugging
  5. Tips
  6. Deliverables
The Spica logs seem to be definitive proof of EvanBot’s existence, but without
further clues, you seem to have hit a dead end. Luckily, some time later, CSA
assigns you to deorbit Polaris, a former Gobian spy satellite.

As the space race became more competitive, newer Gobian Union satellites like
Polaris introduced stack canaries to protect top-secret information from enemy spies.
Although stack canaries were considered state-of-the-art defense at the time, we now
know that they can be defeated.

Hack into Polaris to see what intelligence it contains, and don’t forget to deorbit it
afterwards

For this question, stack canaries are enabled. The stack canary in this question is 4 random bytes (no null byte) that change each time you run the program. We recommend trying Q1 on HW2 before attempting this question.

Note: be careful that the canary doesn’t contain a NULL byte, unlike how it was taught in lecture.


Starter files

The vulnerable dehexify program takes an input and converts it so that its hexadecimal escapes are decoded into the corresponding ASCII characters. Any non-hexadecimal escapes are outputted as-is. For example:

$ ./dehexify
\x41\x42   # outputs AB
XYZ        # outputs XYZ
# Control-D ends input

Note that we are not inputting the byte \x41 here. Instead, we are inputting a literal backslash and the literal characters x, 4, and 1.

Also note that you can decode multiple inputs within a single execution of a program.


Your task

Your exploit for this question will go in an interact script instead of a egg script. To get started, copy over the starter code and make it writable by running:

cp interact.scaffold interact
chmod +w interact

The exploit script simply runs your interact script three times in a row (since your solution might have a small chance of failure.)


The interact API

The interact script lets you send multiple inputs and read multiple outputs from a program. In particular, you have access to the following variables and functions:

  1. SHELLCODE: This variable contains the shellcode that you should execute. Rather than opening a shell, it prints the README file, which contains the password. Note that this is different from the shellcode in the previous two questions.

  2. p.send(s): This function sends a string s to the C program. You must include a newline \n at the end your input string s (this is like pushing “Enter” when manually typing input). The newline is not sent to the C program.

  3. p.recv(n): This function reads n bytes from the C program’s output.

As an example, we can write the session from before using this API.

p.send('\\x41\\x42' + '\n')  # newline not sent to C program
assert p.recv(3) == 'BC\n'   # newline printed by C program
p.send('XYZ' + '\n')
foo = p.recv(4)              # save C program output in a variable
assert foo == 'XYZ\n'

Note that in Python, to send a literal backslash character, you must escape it as \\.


Debugging

Input and output redirection does not work in this question, because it involves multiple inputs and outputs. Instead, you will need to type your desired input into gdb directly:

  1. Run ./debug-exploit to start gdb.

  2. Set appropriate breakpoints and layout split if desired.

  3. Start the program without any arguments (run or r).

  4. When you step over the call to gets, gdb will wait for your input. Type in your input and hit enter.

Note that you cannot type special byte characters directly into gdb. For example, if you type \x12, gdb will input a literal backslash and the literal characters x, 1, and 2.

Additionally, you can use print statements in your interact script for debugging. These will be directly printed to the terminal (and not sent to the program). For example, the following line prints out the Python variable foo as hex characters:

print(" ".join("{:02x}".format(ord(c)) for c in foo))

Tips

  • Important: In this question, gets appends two null bytes after your input, not one. This will affect your exploit slightly.

  • You might want to save some C program output and input part of it back into the C program. No hex decoding or little-endian reversing is necessary to do this. For example:

        foo = p.recv(12)  # receive 12 bytes of output
        bar = foo[4:8]    # slice the second word of the output
        p.send(bar)       # send the second word back to the C program
  • Keep in mind that the function does not return immediately after the buffer overflow takes place (it might help to look at what codes are executed next and think about what it does to the stack), so you will need to account for any extra behavior so that the stack is set up correctly when the function returns.

Deliverables

A script interact and a writeup. Make sure the script works by running ./exploit.

Note: It may be difficult to show GDB output for this question. For this question only, it’s sufficient to show the GDB output after your first input to the program, along with a stack diagram showing how any future inputs would conceptually change the stack.


frontier