# 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. ![](https://i.imgur.com/jpj1wzE.png) 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. ![](https://i.imgur.com/89d2ARU.png) 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. ![](https://i.imgur.com/oh1M0fF.png) 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()) ``` ![](https://i.imgur.com/YChjian.png) we just pwned it again.