Sheet 5
PABE Exercise Sheet 5
General Information
All solutions must be Python 3 scripts 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. Feel free to post other resources to the mailing list to help your fellow PABE students.
Please keep in mind that you should:
-
read the task description carefully
-
push
all your changes to the GitLab repository (master
branch) before the deadline. Make also sure that the file permissions are set correctly! If you are new to Git check out this site! -
Make sure that your solution (also) runs in the CI environment (and not just your local machine); this also means that you must install all additional packages yourself from within the
solution
script (see our blog post for details how to do that). -
Make sure that the solution is an executable python3 script named
solution
(chmod +x ./solution
) with a working shebang line at the top (i.e.#!/usr/bin/env python3
) so that it can be executed like this:./solution
(do not name your scriptsolution.py
,Solution
,solution.sh
, … justsolution
) -
The final solution string, and only that, must be written to
stdout
and could be a number, a string, a string with the formatFLAG{some letters and digits here}
, depending on the specific task. -
Describe what you are doing using detailed comments for all your solution scripts! For example, use Docstrings (link) or inline comments:
1 2 3 4 5 6 7 8
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) # the final check happens here 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. Please do not leave any commented code (i.e., code that is not needed to solve the task) in your
solution
files! -
Make sure that your
solution
executes within 10 seconds (this is a hard timeout on our server). -
Violating any of the points above might lead to reduced final points for the specific task!
The deadline for this sheet is Tuesday, 2022-01-11 23:59:59 CET
Task 21 – Notebook App (4 Points)
We got a new app that allows you to take notes. There are two kinds of notes: simple ones and printable ones. The app is still work in progress so there might still be some bugs.
Find the bug and exploit it to print the flag. As always, describe what you are doing with technical details in comments so that we see that you fully understood the vulnerability and the exploit.
Once again, edit the provided solution
template and explain your approach with meaningful comments!
Hints:
- What happens if you set the printing function to
puts()
and then have heap allocation with the same size before that? - Have a closer look at the struct
printable_note
Your solution should execute like this:
|
|
Task 22 – Heap Visualization (4 Points)
Write a GDB script that visualizes parts of the heap by showing all free chunks (fast bin, small bin, unsorted bin, large bin chunks). Your solution must not use pwntools/pwndbg.
In more detail:
In GDB you can use libc’s debugging symbols to get information about the main_arena
like this:
|
|
There you can see the fastbinsY
, bins
, the top
chunk and so on.
Implement a gdb.Command
(https://sourceware.org/gdb/onlinedocs/gdb/Commands-In-Python.html#Commands-In-Python) that can be used with freeheapchunks
in GDB and shows all free chunks (fast bin, small bin, unsorted bin, large bin chunks) like this:
|
|
The ???
should contain the correct values in hexadecimal notation.
Also note:
- First, some of the values make no sense for specific chunk types (e.g., fastbins do not have a
bk
pointer) so set them ton/a
for not available. - Second, some bins hold linked lists with specific sizes (e.g., chunks of size 0x20, 0x30, …), so print all the free chunks in every bin of any size.
The data
field (which is not part of a libc heap chunk) should give a “preview” of the data that is still inside the chunk’s malloc()
ed memory even if the chunk has been free()
d by the user.
If the data is printable then print it, if it is not printable render a dot (.) like in xxd
.
Please use the code in malloc_and_free.c
as a reference and invoke your custom command freeheapchunks
at the lines where the comments tell you to do so (set the breakpoints accordingly). Also use the provided binary malloc_and_free
. Here is a snippet of the code:
|
|
Use pure GDB (not pwntools/pwndbg) to solve this task! You may ignore the tcache bins.
Once again, edit the provided solution
template and explain your approach with meaningful comments!
This solution template expects a gdb_heap_vis.py file which is your GDB script.
Task 23 – ROP ROP ROP ROP ROP (8 Points, individual Task)
This time there are two binaries: vuln
and execute_me_with_rop
.
There is a simple vulnerability in vuln
.
Your task is to build a ROP chain that executes execute_me_with_rop
so that it prints the flag.
Use the execve
system call and prepare all necessary arguments accordingly.
You must not use pwntools' pwnlib.shellcraft
for this exercise!
You must also not just execve("/bin/sh -c './execute_me_with_rop arg1 arg2'")
for the execution of execute_me_with_rop
!
Once again, edit the provided solution
template and explain your approach with meaningful comments!
Hints:
- Try to write a C program first which executes
execute_me_with_rop
, to find out how to build your ROP chain:
|
|
-
Have a look at the Hello-World ROP chain in order to build your ROP chain
-
Remember how to set
argv**
Leaking the address
-
Try to leak the address of
__libc_csu_init
from the stack and calculate thefile_base_addr
-
Next, use the
file_base_addr
to build a small ROP-chain from the./vuln
which invokesputs-PLT
and as anputs-GOT
entry as its parameter and finally start the program again through the ROP-chain in oder to leakputs@GLIBC
.
Task 24 – Bad Characters And A Non-Executable Stack (16 Points)
Task Description
Your task is to exploit a simple bug in exploitme
.
But there is a problem: not all characters of your shellcode can be used!
Also, the stack is not executable, so you have to get around that as well.
Your task is to:
- Write a file
shellcode.s
in assembler that uses theopen
,read
andwrite
system calls to print the content offlag.txt
to stdout, - create machine code of your
shellcode.s
file withnasm
and copy out only the machine code (you cannot inject an ELF file) andobjcopy
magic orasm
from pwntools,
- use the
mprotect
system call to make the input buffer executable again to run your shellcode, - find out what the bad characters in your shellcode are (see next section),
- use
msfvenom
[1] from Metasploit (which is installed on your VMs) to get rid of the bad characters or craft your shellcode by hand so that it does not contain any of those bad characters (please note: you can only usemsfvenom
on the shellcode… not themprotect
ROP chain!), and finally - inject your bad-character-free payload into
exploitme
so that it will be executed and print the flag!
Your input should look like this:
|
|
Finding Bad Characters
Use the exploitme
binary and try to input data that contains all possible bytes:
|
|
Debug the program and see if the complete input ends up in the input buffer.
Spoiler alert: \x00
terminates a string so nothing ends up in the input buffer.
So, remove that byte and try again with \x01\x02\x03\x04...\xfe\xff
… maybe this time you see that all bytes up until \x0a
(a newline character) end up in the buffer.
Again, remove that byte and continue with \x01\x01\x02\x03\x04...\x09\x0b...\xfe\xff
. When you reach \xff
you just collect all bytes that somehow destroyed your shellcode during the injection (e.g., \x00, \x0a
).
Those bytes are your bad characters.
Solution
Once again, edit the provided solution
template and explain your approach with meaningful comments!
Your solution should execute like this:
|
|
As always, comment all of your code! You do not have to automate the step of finding the bad characters. Just describe what you did and upload your helper scripts if you created any.
Hints:
- When building our ROP chain it might helpful in the case of
mprotect()
to jump at an offset where some registers gets set for us. - Remember that the
read()
function is not putting a NULL-byte at the end of the string. - Do not forget to submit your
shellcode.s
file along with the solution!
[1] https://www.offensive-security.com/metasploit-unleashed/msfvenom/
Task 25 – C++ and vtables (8 Points)
In this task you have to exploit a vulnerability that leads to a vtable pointer overwrite.
Although it is also possible to overwrite the return address of main()
, you must not use this approach.
What you should do:
- Find the bug(s)
- Understand how vtables work in C++ (e.g., https://en.wikipedia.org/wiki/Virtual_method_table, https://godbolt.org/z/les9Bx)
- Exploit the bug to get the flag from
flag.txt
by manipulating the vtable (pointer)
Once again, edit the provided solution
template and explain your approach with meaningful comments!
Your solution should execute like this:
|
|
Hints:
- Are there any useful functions in the binary?
- How can you manipulate the control flow without overwriting the return address?
Ask yourself the following questions:
- How is
PabeUser::set_username(std::string)
invoked at assembly level? - What if you change the pointer from
set_username(std::string)
to a function which invokessystem
to get the flag printed?