May 1, 2026

Pwnable 1 - File Descriptor

"Introduction to Linux file descriptor"

After sshing into ther server

#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");
                setregid(getegid(), getegid());
                system("/bin/cat flag");
                exit(0);
        }
        printf("learn about Linux file IO\n");
        return 0;

}

Let us analyze it, First check is argc, that is argument count, which must be greater than 2. That means while running the fd binary, we must provide an argument with it. Next

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

So fd is initialized with the first argument - 0x1234 But what does atoi does.

Now, that clear and out of the way. Next

        int len = 0;
        len = read(fd, buf, 32);

A variable len is initialized. Then read function is used to read input to buffer of exactly 32 bytes. But whats fd doing here ? Lets look at the manual page of read

So basically fd says from which File Descriptor should the read function take input from

fd = 0 means Standard Input fd = 1 means Standard Output fd = 2 means Standard Error

Next,

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

Then strcmp compares the input stored at buf with “LETMEWIN\n”, So if we want to give input by standard input, we must set fd = 0, For that,

0x1234 is hex form, converting it to decimal gives 4660. And that gives the flag.