# Echo Chamber Hello there! Welcome to the write-up for **Echo Chamber**. This is a classic "pwn" challenge that demonstrates a very common but powerful vulnerability: the **Format String Vulnerability**. In this challenge, we are given a compiled binary. When we don't have the original source code, we use tools like **Ghidra** to decompile the binary and see what the program is doing "under the hood." --- ## 1. Initial Reconnaissance When we run the program, it asks for some input and "echoes" it back: ```text Welcome to the Echo Chamber! Give me a phrase, and I will shout it back: Hello! You said: Hello! ``` The developer's description gives us a hint: > "The developer claims it's perfectly secure because 'it doesn't execute any code, it just prints text.'" This is a classic "famous last words" situation in security! Let's look at the decompiled code to see why. ## 2. Analyzing the Decompiled Code (Ghidra) Opening the binary in Ghidra, we find the `vuln()` function. Here is the pseudo-code it gives us: ```c void vuln(void) { char acStack_a0 [64]; // Our input buffer char local_60 [72]; // Where the flag is stored FILE *local_18; local_18 = fopen64("flag.txt","r"); if (local_18 == (FILE *)0x0) { puts("Flag file is missing!"); exit(0); } // 1. The flag is read into local_60 fgets(local_60,0x40,local_18); fclose(local_18); puts("Welcome to the Echo Chamber!"); printf("Give me a phrase, and I will shout it back: "); // 2. Our input is read into acStack_a0 fgets(acStack_a0,0x40,(FILE *)stdin); printf("You said: "); // 3. VULNERABILITY: Our input is passed directly to printf! printf(acStack_a0); putchar(10); return; } ``` Do you see that line `printf(acStack_a0);`? This is our "Golden Ticket." ## 3. The Vulnerability: Format Strings In C, `printf` expects its first argument to be a **format string** (like `"%s"` or `"Hello %s"`). If a developer passes user input directly to `printf`, the user can provide their own format specifiers. When `printf` sees a specifier like `%p` (print pointer) or `%x` (print hex), it looks for the next argument on the **stack**. If we don't provide any arguments, `printf` will just start leaking whatever is already on the stack! ### Where is the flag? Looking at the Ghidra output, notice that both `acStack_a0` (our input) and `local_60` (the flag) are **local variables**. This means they are both stored on the stack right next to each other. ## 4. Exploiting the "Echo" If we send a string of format specifiers like `%p %p %p %p %p %p...`, we can trick `printf` into printing the contents of the stack. Since the flag is sitting on the stack, it will eventually be printed! Try providing this as input: `%p %p %p %p %p %p %p %p %p %p %p %p %p %p %p %p` The program will respond with a series of hex addresses. Some of these values will actually be the ASCII characters of our flag. ### Little Endianness When you see the hex values, remember that modern systems use **Little Endian** byte ordering. This means the bytes are stored in reverse order. For example, if you see `0x7b67616c66`, and you convert those bytes from hex to ASCII: - `66` = `f` - `6c` = `l` - `61` = `a` - `67` = `g` - `7b` = `{` The value `0x7b67616c66` represents `flag{` in reverse! ## 5. Putting it all Together To solve the challenge: 1. Connect to the service. 2. Send many `%p` specifiers to leak the stack. 3. Identify the hex values that look like printable text (starting with `0x...` and containing ASCII values). 4. Reverse the bytes (Endianness) and convert them to characters. 5. Combine the parts to find the flag! ## Lessons Learned Even if a program "just prints text," it's not safe if it uses `printf` incorrectly. The fix is simple: always use `printf("%s", buffer);`. This ensures the input is treated as a literal string, not as code or instructions for the function. Happy Hacking!