Sheet 2

General Information

The solutions should be created mainly with Python but it is also allowed to use a little bit of shell/Bash magic for your solution file. If you are new to Python have a look online… there are many good resources to get started such as this course and this slide deck. Feel free to post other resources to the mailing list to help other PABE students.

Please keep in mind that you should:

  • push all your changes to the GitLab repository (master branch) before the deadline. Make also sure that the file permissions are set correctly!
  • make sure that your solution (also) runs on the virtual machine (and not just your local machine)
  • make sure that the solution is an executable script named solution with a working shebang line at the top (e.g., #!/usr/bin/env python2) so that it can be executed like this: ./solution
  • the final solution string (and only that) must be written to stdout and could be a number, a string, a string with the format FLAG{some letters and digits here}, depending on the specific task
  • read the task description carefully, for example, if we ask you to write a Python script do not submit a Bash script or something else

Describe what you are doing using comments for all your solution scripts regardless of programming language (Bash, Python, C, …). You could use, for example, Python Docstrings (link) for you Python programs:

1
2
3
4
5
6
def check_input_length(input_string):
    """
    The input string must have a length greater than 42 and must also be even.
    """
    length = len(input_string)
    return (length > 42) and (length % 2 == 0)

This helps us to find out if you really understood the task and you are not just brute-forcing some solutions.

The deadline for this sheet is Tuesday, 2019-11-19 23:59:59

Task 6 – Key Checker

The program check_key needs a valid key as an input. Find out how to provide the key to the program and how the key checking algorithm works (use a disassembler such as IDA Pro 7, radare2, binary ninja or use a debugger, such as gdb). The final task is to write a Python script as solution that is able to generate valid keys and print 500 of them to stdout (unique keys).

Your solution could, for example, look like this:

1
2
3
4
5
6
./solution
key1
key2
key3
...
key20

where keyX is a valid key.

Note: Do not brute-force all solutions by executing the binary check_key and checking its output. It’s a Reverse Engineering Task ;-)

Task 7 – In-memory decryption

Have a look at the binary xor. When you run the binary it seems that nothing happens… If you have a look at the disassembly (e.g. with objdump or any other disassembler) you can see that there is a string within the binary that gets decrypted during runtime. The decrypted string only exists during the execution but will not be printed to stdout.

Your task is to write a gdb script in Python (link) that sets a breakpoint at the correct address (when the string is finally decrypted), runs the program and outputs the string to stdout. This time your solution can be a Bash script that calls gdb with the Python script as an argument (gdb --command=<your Python script>) . Make sure that only the decrypted string is printed to the final stdout (e.g., Bash’s stdout).

Your solution could, for example, look like:

1
2
$ ./solution
abcdefg

Task 8 – Broken Header

Oh no! Our binary broken is causing segmentation faults. What is happening here? There could be something wrong with the header…

Your task is to write a Python script that patches and executes the binary broken.

Your solution could, for example, look like:

1
2
$ ./solution
FLAG{some letters and digits here}

Hint: You should check the header of a working binary (e.g. /bin/ls) and compare it to the broken binary.

Task 9 – Broken Code

Oh no again! Another binary also called broken is not printing the flag. I think the evil wizard of three-mistakes has corrupted it. Can you help us? Before this incident the binary printed a flag and exited with return code 42!

Your task is to write a Python script that patches the binary broken so that it runs as expected.

Your solution could, for example, look like:

1
2
$ ./solution
FLAG{some letters and digits here}

Hints:

  • The broken code can be found in the function _start.
  • You can use the pwntools command line tool asm to get the opcodes for a specific assembler instruction:
    1
    2
    
    $ asm "mov eax, 0x1"
    b801000000
    
    1
    
    
    

Task 10 – Unicorn Engine

Unicorn Engine is a CPU emulator that supports many different architectures (link) CPU emulator means that you won’t have any support from the operating system and have to work very low level. This is especially true for memory mapping.

We provided you a solution file with some Python code. When you run the code (i.e. ./solution) you will notice that you get an error ERROR: Invalid memory read (UC_ERR_READ_UNMAPPED).

Your task is to:

  • understand the Python and assembly code
  • find out why the error messages occur
  • fix the Python code so that the emulation runs correctly

If I remember correctly the value 0x1337 was stored at the address 0x31337 (mov eax, [0x31337])

With the code tracing hook in place engine.hook_add(UC_HOOK_CODE, hook_code) you will also see the currently executed instruction via stdout.

Your final solution could, for example, look like:

1
2
3
4
5
6
$ ./solution
...
eax = 0x1234
ebx = 0x1234
ecx = 0x1234
edx = 0x1234

We will check the last 4 lines to see if the results are correct. Do not modify the simple_asm code.

Hints:

  • How can you catch illegal memory accesses?
  • Must the memory you map be aligned somehow?