fd from Pwnable.kr

Category : Toddler’s Bottle

This blog post will be part of the binary exploitation series. I am new to this kind of stuff and will be posting about them as I learn. In this series we will be hacking pwnable.kr challenges. I heard that is a great resource to learn from.

Toddler’s Bottle

So the first category is Toddler’s Bottle. They are supposed to be easy beginner level binary exploitation challenges. Thus we will be starting from there.

fd

The first challenge name is fd and it talks about Linux file descriptors in the challenge prompt.

Lets login into the server and check the binary. We ssh into the server with a password guest.

ssh -p2222 fd@pwnable.kr

There are 3 files fd, fd.c and the flag file. Copy the file to our box and begin the analysis.

Note: for debugging create a file names flag in your directory as if our exploit works the program will read that file and we will know the exploit worked.

I created a flag file with contents “this works bruh”.

scp -P 2222 fd@pwnable.kr:/home/fd/fd* .

We run the fd binary and see, it asks for an argument.

./fd
pass argv[1] a number

So we run it with a random number such 69 to see what happens.

./fd 69
learn about Linux file IO

In Linux a file descriptor is an abstract indicator (handle) used to access a file or other input/output resource, such as a pipe or network socket. They go as follows:

0 -> stdin
1 -> stdout
2 -> stderr

so lets now examine the source code that was given with the file.

#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;

}

Here the noteworthy thing here is the read function used. The read function C takes 3 arguments normally.

Thus the use to read 32 bytes from the stdin into the buffer looks like.

read(0,buff,32);

Now to make binary output the flag and we need to pass the if statement.

if(!strcmp("LETMEWIN\n", buf)){
        printf("good job :)\n");
        system("/bin/cat flag");
        exit(0);
    }

For that the buf must contain the string “LETMEWIN”. Thus in order to exploit all we need to do is make the read() call the stdin and then enter the required string. Simple enough.

Since we control the fd value that is passed to the read function, all we need to do is make that 0 in order to call the stdin.

In code we that the argument passed via CLI is subtracted by 0x1234 then passed to fd.

int fd = atoi( argv[1] ) - 0x1234;

0x1234 that is 4660 in decimal (can be converted with python interactive prompt as below.)

Thus if we pass 4660 as argument, the fd gets the value zero and the program reads the stdin. So lets do it.

./fd 4660
LETMEIN
good job :)
this works bruh

The payload works and we get the contents of the dummy flag file that we created. Thus lets do this on the server now.