Exercise Requirements and Grading Guidelines
This document contains the information and requirements you need to know in order to work on our exercise sheets.
Structure of the Exercises
There are 6 exercise sheets (0…5) in total.
Sheet 0 is highly recommended (while technically optional) as we will guide you through the necessary infrastructure to solve the tasks and refresh some knowledge required for this lecture. Also, it will contain some bonus points.
Grouping
Each sheet will contain some group tasks and one individual task. To be admitted to the exam, you will need to reach 50% over all group tasks and 50% over all individual tasks.
Information about group assignment and registration for exercises is given in the first lecture.
Technical Requirements
Git
The exercises are carried out in our GitLab instance. For each task, a repository will be created for you which will contain the necessary files. We expect you to push your solution to this repository before the deadline. Please note that we always check out the main branch for the final submission and check the last commit before the deadline.
If you are new to Git, check out this guide!
Solution Script
Each solution must be a single Python 3 script named solution if not stated otherwise.
If you are new to Python 3, have a look online, there are many good resources to get started such as
this intro course, this advanced course,
this blog post,
and this slide deck.
The first line of solution must be a shebang line: #!/usr/bin/env python3
The solution script must be named solution.
It must not be named solution.sh or solution.py or… anything else, really.
The solution script must be executable.
You can make it executable by executing chmod +x solution.
You can check if your script is executable by running ls -l:
Good:
|
|
Not good:
|
|
Your solution script must execute in our CI within at most 60 seconds. Check the CI-Pipeline status and output for any errors. If the Pipeline is green and the output looks right, your solution should be correct.
Dependencies
Your script solution must be executable in our container. Install all additional packages that are not available in the container we provide!
|
|
In order to avoid losing points, always check if your script executes properly in the provided container!
Files
If you need to patch a binary, push the binary to the repository as well!
|
|
Python Version
In the provided container:
|
|
You cannot use language features from newer Python versions or from Python 2!
Content Requirements
This section will describe the structure we expect from your solution file.
Each task may contain additional requirements.
Solution template
We often provide a template for your solution called solution which will already properly start the binary and set some convenience variables.
The template will usually be based on pwntools, a popular library for binary exploitation.
Most of the times, you can also start it inside a tmux session with ./solution GDB to start it and automagically connect GDB to it.
Refer to this cheatsheet for hints on how to control the tmux environment.
Your task will generally be to add your exploit code in this script at the appropriate location.
Feel free to add your own functions outside of main to make your code more readable and concise.
Comments and Code Style
We would like to know whether you understand what you are doing.
For this reason, a detailed description is an essential aspect of your solutions.
Use meaningful code comments as well as appropriate variable and function names in your solution script to make the strategy and intent of your code clear to the reader.
For all tasks dealing with exploiting a program, your solution must include the following:
- A block comment at the beginning of the
solutionfile describing the vulnerability (including relevant addresses or instructions) and your general plan how to exploit it. Think of this as a small writeup. - Comments throughout your exploit code what exactly you are doing and why.
- If you did not succeed in exploiting the program, you can still get partial points by sharing your thoughts with us in a comment: Where were you stuck? What happened at this point? Do you have an idea or a guess why it didn’t work? Feel free to include e.g. some output of GDB.
Unused Code
While detailed comments that describe your ideas and thoughts are valuable to us, bloating up the code by commented or unused code, unused functions etc. makes it hard for us to understand what you are doing.
Therefore, please only leave code in your submission which is actually used.
Output
If not stated otherwise, we require you to print the flag and ONLY the flag to stdout:
|
|
You may need to suppress additional GDB or pwntools output in your script.
Gaining information
In all tasks that require exploiting a binary to print a flag, the flag and all required runtime metadata such as ASLR address offsets must be obtained by exploiting the binary. That is, your exploit should generally also work for a remote system where you can only send inputs to and read outputs from the binary. You may assume the same configuration as in our isolation container for this remote system (libc, installed tools, …). Further, you may use any addresses and information from the binaries we shared with you.
Grading Guidelines
These are the guidelines that we follow when grading your submissions.
Whenever you feel that we have treated your submission unfairly and have not followed our own rules, you are encouraged to write an email to placeholder@example.com.
Please remember that we always check out the main branch for the final submission and check the last commit before the deadline.
Make sure that this commit reflects your final submission.
Each task has a number of achievable points assigned to it.
- You gain points by solving the task (see below).
- You lose points for mistakes and rule violations (see further below).
- You cannot get negative points for a task.
We will internally split up the task into required general steps to solve it and assign one or more points to each step, depending on the complexity of the step. If the step has been solved successfully, you will be awarded the point(s) for it. If it is solved wrongly or not at all, you will receive 0 points for it. If it is solved partially or with minor errors, you may receive a part of the points. As described above, sufficiently detailed descriptions are essential for full points.
In case you find an unforeseen solution which works but does not adhere to the intended steps, you will of course also receive full points for a perfect solution, or partial points for correct parts.
Further, in case of formal issues, points will be deducted as follows:
1. General issues
- If there is no solution at all for a task, you will be awarded 0 points for that task.
- If we detect that a solution for a task has been plagiarised, all involved groups will get 0 points for the whole sheet.
2. Technical issues
-
If the solution logic is not written in pure Python 3, you will be awarded 0 points for that task.
Examples:1 2 3 4#!/usr/bin/env python3 import subprocess subprocess.check_output('./i_like_bash_better.sh')☝️ Something like this will result in 0 points, because the solution logic is written in bash.
1 2 3# the shellcode was created by running nasm -f elf -o shellcode shellcode.asm shellcode = open('./shellcode', 'rb').read() exploit_binary('./exploitme', shellcode)☝️ This is ok, if the
shellcode.asmsource file and the shellcode binary file have been committed as well, because it is just data for the application logic inexploit_binary()(not pictured). -
If the solution is not executable, 1 point will be deducted.
-
If the solution is not properly named (e.g. it is not called
solution), 1 point will be deducted. -
If the solution crashes with an error (Python Exception, Segmentation Fault, …), 1 point will be deducted.
-
If there is more output on stdout than what is required (usually just the result
FLAG{…}or a number), 1 point will be deducted. Usually, this refers to additional GDB / pwntools output. -
If the solution does not respect the timeout of 60 seconds, 1 point will be deducted.
-
If the solution contains lots of unused code (commented out, not called, …), 1 point will be deducted.
3. Content related issues
-
If the solution violates constraints or requirements from the task description or from the general requirements, you will be awarded 0 points for the respective steps.
Examples:-
Task: “Exploit the binary and print the flag!"
1 2# I found the flag with Ghidra print("FLAG{abcdef}")☝️ This is considered cheating because the printed result looks right, but no exploitation is being done by the solution. 0 points.
-
Task: “Exploit the binary and print the flag!"
1print(open("./flag", "r").read())☝️ This is considered cheating because the printed result looks right, but no exploitation is being done by the solution. 0 points.
-
Task: “Exploit the binary and print the flag!"
1 2io.sendline(... + open("./flag", "rb").read() + ...) print(io.readline().decode().split()[0])☝️ This is considered cheating because, even though the binary may print the flag, it was obtained locally without exploiting the binary. 0 points.
-
Task: “Calculate (some key with some properties). Hint: Use
z3to solve the constraints!"1 2key = calculate_key_but_do_not_use_z3_at_all() print(key)☝️ It is not forbidden to make life harder for yourself. You may also ignore hints. If the solution is correct, you get points for this one.
-
Task: “Calculate (some key with some properties). You must use
z3to solve the constraints!"1 2key = calculate_key_but_do_not_use_z3_at_all() print(key)☝️ In this case the use of the
z3library was required, so this solution would yield 0 points. -
Task: “Exploit (something). Do not use pwntools'
pwnlib.shellcraftfor this exercise!"1 2 3 4 5from pwnlib import shellcraft … l = listen(fam='ipv6', timeout=5) assembly = shellcraft.i386.linux.connect('::1', l.lport, 'ipv6') …☝️ Whoops! This solution violates a constraint from the task description, so it would yield 0 points.
-
Task: “Exploit (something).
1 2 3 4 5 6 7 8 9from pwn import * … io = process('./vulnerable_binary') libc = ELF('/lib/x86_64-linux-gnu/libc.so.6') libc.address = io.libc.address # OR with open('/proc/self/maps', 'r') as f: maps = f.read() …☝️ This solution violates a constraint from the general requirements, since you obtained runtime metadata without exploiting the binary. 0 points.
-
-
If comments are not sufficiently detailed for us to understand a step but it works, 1 point will be deducted for the step.
-
If your solution does not work at all and your comments are not sufficiently detailed for us to understand your exploit idea and the problem, the task will be graded with 0 points. On the other hand, a non-working but sufficiently commented solution will receive points for correct ideas and parts.
Finally, here’s an illustrative example:
Task: Use a buffer overflow in a given binary to open a shell and print the flag! (4 Points)
solutionis not executable (technical issue, 1 point deducted)- found vulnerability and wrote a comment explaining the vulnerability and the attack plan (1/1 point for correct step)
- injected shellcode with invalid characters - which would otherwise open a shell, but good comment about what went wrong (1/2 points for partially correct step)
- overwrote return address with incorrect value (0/1 points for incorrect step)
- 👉 1/4 points.