Search This Blog

Monday, April 25, 2022

fd - pwnable.kr (file descriptors & read() function) | pwn



CHALLENGE DESCRIPTION:

Mommy! what is a file descriptor in Linux?

* try to play the wargame your self but if you are ABSOLUTE beginner, follow this tutorial link:
https://youtu.be/971eZhMHQQw

ssh fd@pwnable.kr -p2222 (pw:guest)

This is my writeup for an easy pwn challenge that has to do with file descriptors and the read() function. using the SSH creds given, we log onto the server and we list the files in the current directory to see an executable file, the source code to the executable as well as the flag, owned by root, which stops us from cheating. The challenge needs to be complete to read the flag. Let's see the files provided to complete the challenge. play the wargame here.

fd@pwnable:~$ ls
fd  fd.c  flag

Let's see more about the fd executable file....

fd@pwnable:~$ file fd
fd: setuid ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux.so.2,
for GNU/Linux 2.6.24 BuildID[sha1]=c5ecc1690866b3bb085d59e87aad26a1e386aaeb, not stripped

Turns out the challenge is a 32bit ELF file, dynamically linked, meaning that it has libc libraries it refers to when executing built-in C functions like printf() and system() functions and its not stripped, which makes it easy to reverse engineer if it ever comes to that. Let's open the fd.c file to see how the program is written to analyze the code.

fd@pwnable:~$ cat fd.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;

}

The goal is for the system("/bin/cat flag") to be executed to complete the challenge. For this to happen, we have to do some analysis on the code prior to this in order to see how we can achieve this. the source reveals a main() function which firstly checks if the command line arguments are two. if not it prints "pass argv[1] a number". If the arguments are two, it then goes forward to take the command line argument and passes it into the atoi() function which turns an ascii character to an integer. The next two lines show the 'len' variable contain zero. The next line pretty much shows the read() function at play. Looking into the manpages, we see the description of the function of the read() function

"The read() function shall attempt to read nbyte bytes from the file associated with the open file descriptor, 
fildes, into the buffer pointed to by buf"

Linux File descriptors are as follows:

0: stdin
1: stdout
2: stderr

This indicates that if we can get the fd = 0, the program will take input from stdin, then we can go on and input 'LETMEWIN' since there is a strcmp() function which compares the input places in buf with the string 'LETMEWIN'. The fd variable will take our command line argument and subtract it by 0x1234, which is 4660 in ascii text. To exploit this, we simply execute the fd binary and insert 4660 as a command line argument and after input the 'LETMEWIN' string in order for the strcmp() function check to evaluate to "True" (meaning the program must see that the string we put in and the string our input is compared to by the program evaluates to true so that the system() function executes the "/bin/cat flag" gets executed for the flag to be captured.

fd@pwnable:~$ ./fd 4660
LETMEWIN
good job :)
mommy! I think I know what a file descriptor is!!

Challenge completed! 

Flag: mommy! I think I know what a file descriptor is!!

No comments:

Post a Comment