Pwnable.kr - fd


After feeling a big need to improve my knowledge of pwnable category, I decided to check out pwnable.kr and start from the beginning.

Here comes the Toddler’s Bottle and the first challenge - fd.

Mommy! what is a file descriptor in Linux?

In order to view the challenge, we have to connect via ssh with password guest.

[email protected] ~ % ssh [email protected] -p2222
[email protected] password:
 ____  __    __  ____    ____  ____   _        ___      __  _  ____  
|    \|  |__|  ||    \  /    ||    \ | |      /  _]    |  |/ ]|    \
|  o  )  |  |  ||  _  ||  o  ||  o  )| |     /  [_     |  ' / |  D  )
|   _/|  |  |  ||  |  ||     ||     || |___ |    _]    |    \ |    /
|  |  |  `  '  ||  |  ||  _  ||  O  ||     ||   [_  __ |     \|    \
|  |   \      / |  |  ||  |  ||     ||     ||     ||  ||  .  ||  .  \
|__|    \_/\_/  |__|__||__|__||_____||_____||_____||__||__|\_||__|\_|

- Site admin : [email protected]
- IRC : irc.netgarage.org:6667 / #pwnable.kr
- Simply type "irssi" command to join IRC now
- files under /tmp can be erased anytime. make your directory under /tmp
- to use peda, issue `source /usr/share/peda/peda.py` in gdb terminal
Last login: Thu Nov 23 11:25:25 2017 from 131.202.114.32
[email protected]:~$ ls -la
total 40
drwxr-x---  5 root   fd   4096 Oct 26  2016 .
drwxr-xr-x 80 root   root 4096 Jan 11  2017 ..
d---------  2 root   root 4096 Jun 12  2014 .bash_history
-r-sr-x---  1 fd_pwn fd   7322 Jun 11  2014 fd
-rw-r--r--  1 root   root  418 Jun 11  2014 fd.c
-r--r-----  1 fd_pwn root   50 Jun 11  2014 flag
-rw-------  1 root   root  128 Oct 26  2016 .gdb_history
dr-xr-xr-x  2 root   root 4096 Dec 19  2016 .irssi
drwxr-xr-x  2 root   root 4096 Oct 23  2016 .pwntools-cache

In this directory we have the challenge files - source code and binary. Firstly, let’s view the source to understand what’s going on.

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

}

By reading it, we get that firstly atoi( argv[1] ) will convert the argument into the integer, then it will substract from it 0x1234. After converting it into decimal we get number 4660.

>>> 0x1234
4660

After that read(fd, buf, 32) syscall is executed. First argument of this function fd is the file descriptor of where to read the input. Then buf is the character array where the read content will be stored and 32 is the number of bytes to read before truncating the data. The last step compares the content of buf with a string LETMEWIN\n.

How can we enter this string to make the condition true? Firstly, we can learn that file descriptor is simply an integer that is used to access a file, or IO resource. Read more at Wikipedia

Each Unix process should have three standard POSIX file descriptors. With respective integers 0 is stdin, 1 is stdout and 2 is stderr. In our attack we’re going to use stdin, since it’s going to allow us to enter characters from the keyboard.

To make the fd equall to 0, we’re going to make the atoi( argv[1] ) equall to the 4660. Then substraction will result in 0, and the read function will read the characters that we enter.

[email protected]:~$ ./fd 4660
LETMEWIN
good job :)
mommy! I think I know what a file descriptor is!!

Here goes the flag!

Keep learning and stay safe! ~ W3ndige