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