Hacking Tutorials

Challenge #0: fd

Challenge #0: fd


"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://www.youtube.com/watch?v=blAxTfcW9VU

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

Without further ado, let's continue!
When we ssh into the box, we are immediately presented with 3 files:

Screen Shot 2017-10-03 at 9.28.38 AM.png
  1. fd
  2. fd.c
  3. flag


Following convention, we know the flag is the item of desire. (If you are new to CTFs or CTF-style of hacking, the obtaining the flag, which is usually a string of some sort, is the main goal). If we attempt to concatenate the file, we are presented with insufficient permissions. If it was that easy, this really wouldn't be much of a challenge. So let's take a look at the permissions.


It appears that only rood and fd_pwn have permissions to read the flag. By running the $ groups command, we discover that we are only in the fd group. What I didn't notice at first, is that the binary fd has the owner of fd_pwn and the group fd. It ALSO has a "s" which stands for SUID (Set owner User ID up on execution). 

Normally in Linux/Unix when a program runs, it inherits access permissions from the logged in user. SUID is defined as giving temporary permissions to a user to run a program/file with the permissions of the file owner rather that the user who runs it.

The reason this is important, is that as soon as the program runs, we have the permissions of fd_pwn, which is a user that can read the flag file. Calling a function like system("/bin/cat flag") will get us access to read the flag. Very cool!

Okay, let's take a look at the other two files starting with fd.c.


Let's start with what we know first, and learn what we are confused about or more simply don't know about. We are importing 3 libraries, creating a 32-byte buffer, and accepts 2 arguments (but looks like it only calls one), conditional compares two strings, which will lead us to a system() to read the flag if the strings match. If we fail, it will print a nice hint. Sweet!

Now let's go over what we don't know/are not as familiar with. I know very little about the function call atoi(), and would like to know more about the read(), strcmp(), and system().

First up, the atoi() function. According to tutorialpoints, it converts a string type variable that is numerical into an int type. If it doesn't understand it, it defaults to 0. 

 I suppose in python, this would be the same as type casting.

I suppose in python, this would be the same as type casting.

The read() function does, as it's name implies, reads from one input and outputs it to a buffer. The function takes 3 arguments:

  1. The file descriptor of the file
  2. The buffer where the read data is to be stored
  3. The number of bytes to read from the file.

In our program, we have read(fd, buf, 32).
LESSON: The file descriptor (fd) has 3 main standard streams.

- 0: Standard Input
- 1: Standard Output
- 2: Standard Error

To set the read to read from the command prompt, we must get the fd to equal 0. fd = 0;
Let's take a look back at our code.

Screen Shot 2017-10-03 at 12.06.32 PM.png

In order to get the file descriptor (fd) to be set to 0, we must make the solution of argv[1] - 0x1234 equal to 0. We can convert 0x1234 from hex to decimal by using the following python command.

Screen Shot 2017-10-03 at 12.12.08 PM.png

Let's see what happens when you use 4660 as argv[1].

Screen Shot 2017-10-03 at 12.15.12 PM.png

It looks like the program is waiting for input! Perfect! Let's continue.

Okay, next is strcmp(). After some more research, it appears that it compares two strings, and provides an output depending on the condition of the comparison. "strcmp returns 0 when the strings are equal, a negative integer when s1 is less than s2, or a positive integer if s1is greater than s2, according to the lexicographical order." This is interesting. One attack vector we could do, is reverse engineer the binary, find the location where it returns the comparison, and set that variable to 0. Glad that we have 1 type of attack under our belt. Let's keep diving in. 

The system() functions appears to run a command on the system, given a string that is a command.

The C library function int system(const char *command) passes the command name or program name specified by command to the host environment to be executed by the command processor and returns after the command has been completed.

Now that we have all the functions down, let's try the string that's in our program, "LETMEWIN".

Screen Shot 2017-10-03 at 12.17.21 PM.png

WE DID IT! We completed the challenge and learned more about file descriptors! Congrats!!

Chris Magistrado