From 8538f30102dd9faec2ba4f606405c2e1c6051ff0 Mon Sep 17 00:00:00 2001 From: Domingo Dirutigliano Date: Sun, 2 Jul 2023 21:32:18 +0200 Subject: [PATCH 1/3] Changed info --- content/about/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content/about/index.md b/content/about/index.md index 9203b56..17dd1d6 100644 --- a/content/about/index.md +++ b/content/about/index.md @@ -17,7 +17,7 @@ Our team was born during the national competition of [CyberChallenge](https://cy Here you can find some information about the participants of the team: {{< cardbox >}} -{{< card img="imgs/domysh.jpg" title="Domingo Dirutigliano" github="https://github.com/domysh" website="https://domysh.com" email="me@domysh.com">}} +{{< card img="imgs/domysh.jpg" title="Domingo Dirutigliano" github="https://github.com/domysh" website="https://domy.sh" email="me@domy.sh">}} {{< card img="imgs/panic.jpg" title="Nicola Pace" github="https://github.com/nicolapace">}} {{< card img="imgs/nicolag.png" title="Nicola Guerrera" github="https://github.com/nik012003" website="https://catboy.it" >}} {{< card img="imgs/oscar.jpg" title="Oscar Urselli" github="https://github.com/oscar0urselli">}} From 29f14180f79eac8b11c10e4e3a605a539c8c603e Mon Sep 17 00:00:00 2001 From: Domingo Dirutigliano Date: Sun, 16 Jul 2023 07:25:09 +0200 Subject: [PATCH 2/3] Add files via upload --- content/posts/aush.md | 143 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 143 insertions(+) create mode 100644 content/posts/aush.md diff --git a/content/posts/aush.md b/content/posts/aush.md new file mode 100644 index 0000000..a5bd211 --- /dev/null +++ b/content/posts/aush.md @@ -0,0 +1,143 @@ ++++ +title = "zer0pts 2023: Aush (pwn, easy)" +author = "Domingo Dirutigliano" +tags = ["pwn"] +date = "2023-07-15" ++++ +## Aush (pwn, easy) + +>I will give you the shell, but after you authenticated yourself. + +I spent a lot of time on this challenge because I typically focus on static analysis and don't execute the program until I understand how it works. Initially, I solved it without fully understanding the exploit, but after further analysis, I finally grasped its mechanism and wrote this write-up. + +## Overview + +The challenge provides us with the binary (also running on a remote server) and its C source code. + +The program initially reads some bytes from `/dev/urandom`, which serve as the username and password. We need to input the correct values to obtain a shell. + +One noteworthy aspect is that the binary uses cowsay to print messages (through `execve`). + +```c +#include +#include +#include +#include +#define LEN_USER 0x10 +#define LEN_PASS 0x20 + +int setup(char *passbuf, size_t passlen, char *userbuf, size_t userlen) { + int ret, fd; + + // TODO: change it to password/username file + if ((fd = open("/dev/urandom", O_RDONLY)) == -1) + return 1; + ret = read(fd, passbuf, passlen) != passlen; + ret |= read(fd, userbuf, userlen) != userlen; + close(fd); + return ret; +} + +int main(int argc, char **argv, char **envp) { + char *args[3]; + char inpuser[LEN_USER+1] = { 0 }; + char inppass[LEN_PASS+1] = { 0 }; + char username[LEN_USER] = { 0 }; + char password[LEN_PASS] = { 0 }; + + if (system("/usr/games/cowsay Welcome to AUSH: AUthenticated SHell!") != 0) { + write(STDOUT_FILENO, "cowsay not found\n", 17); + return 1; + } + + /* Load password and username file */ + if (setup(password, LEN_PASS, username, LEN_USER)) + return 1; + + /* Check username */ + write(STDOUT_FILENO, "Username: ", 10); + if (read(STDIN_FILENO, inpuser, 0x200) <= 0) + return 1; + + if (memcmp(username, inpuser, LEN_USER) != 0) { + args[0] = "/usr/games/cowsay"; + args[1] = "Invalid username"; + args[2] = NULL; + execve(args[0], args, envp); + } + + /* Check password */ + write(STDOUT_FILENO, "Password: ", 10); + if (read(STDIN_FILENO, inppass, 0x200) <= 0) + return 1; + + if (memcmp(password, inppass, LEN_PASS) != 0) { + args[0] = "/usr/games/cowsay"; + args[1] = "Invalid password"; + args[2] = NULL; + execve(args[0], args, envp); + } + + /* Grant access */ + args[0] = "/bin/sh"; + args[1] = NULL; + execve(args[0], args, envp); + return 0; +} +``` + +## My first doubts + +There is a buffer overflow on the user input, but: + +- The binary has PIE enabled, and there's no way to leak addresses. +- The binary has NX enabled, and there's no way to execute shellcode. +- The variable holding the random username is located below the user input buffer, which means we can't overwrite it using the buffer overflow. + +So, The challenge is impossible? + +However, it's labeled as an easy challenge. So, after overthinking it, I tried executing it by inputting a different size of "A" characters. + +With 411 "A" characters as the username, it resulted in the correct username... What? How is it possible? + +However, when I entered the overwritten password containing "A" characters, it seemed to pass the equality check, but no shell was spawned, and a stack smash was triggered. + +## The brutal solution + +After some debugging, I noticed that the `execve` for the shell was executed, but the pointer to the environment variables (`envp`) was partially overwritten, making it an invalid pointer. I tried overwriting it with zeros in the first input, but it didn't work. However, when I did the same using the second input, it worked! I got a shell! + +```python +from pwn import * +p = process("./aush") +p.sendline(b"A"*411) +p.sendline(b"A"0x20+b"\x00"*400) +p.iteractive() +``` + +## Why it works? + +The fact that it worked triggered my obsessive side for static analysis, so I tried to understand why it worked. + +Using gdb and inserting the input `"A"*411`, I observed that the `memcmp` function was executed and returned `0xffffffff`, which is different from 0. Thus, the `execve` was executed... or was it? + +And that's the point! The `execve` was executed, but it failed. + +Thanks to our overflow, we reached the `envp` pointer on the stack and overwrote it, making it an invalid address. + +While `execve` was indeed executed, the `envp` pointer was invalid, causing `execve` to fail. However, the program continued its execution without being interrupted by the `"error"` because the `cowsay binary` was used to close the main program. This is because it calls `exit_group` at the end, which kills the main program as well. + +The first step of the exploit is to overwrite the `envp` pointer with an invalid value, so `execve` will be skipped. Additionally, we overwrite the generated password with a password of our choice. + +Now we can pass the next check by inserting the chosen password. But there's a problem: at this point, `execve` is used to spawn our shell, but the `envp` pointer is still invalid, causing `execve` to fail, and no shell is spawned. D: + +Now we need to enable again the execution of `execve`, and one way to do that is by using a `null pointer` instead of the `envp` pointer (execve accepts a null pointer as valid for environment). + +So, we can insert the correct password chosen by us, but also overwrite the `envp` pointer with a null pointer. This way, cowsay will be skipped because the password is deemed correct, and execve will be able to spawn the shell normally. + +--- + +## TL; DR + +The challenge was easy to solve but tricky to understand. + +I understood also that: `dynamic analysis >>> static analysis` :D \ No newline at end of file From 424d1ba442f26372557bddb11208c8bb337c4e83 Mon Sep 17 00:00:00 2001 From: Domingo Dirutigliano Date: Tue, 15 Aug 2023 18:18:16 +0200 Subject: [PATCH 3/3] Update hugo.toml --- hugo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hugo.toml b/hugo.toml index 946e703..20ef719 100644 --- a/hugo.toml +++ b/hugo.toml @@ -16,7 +16,7 @@ theme = 'paper' twitter = 'https://twitter.com/pwnzer0tt1' github = 'https://github.com/pwnzer0tt1' #instagram = 'https://instagram.com/pwnzer0tt1' - discord = 'https://discord.gg/79NNVJBK5Z' + discord = 'https://discord.gg/NWyJydmRSg' # home page profile avatar = 'https://pwnzer0tt1.it/icon.png' name = 'Pwnzer0tt1'