Crack TQueen using GDB

Home

NIT Durgapur’s GLUG conducted a CTF event spanning less than a week in which there was a reverse engineering question named TQueen having the highest bounty.

I had already encountered this type of question in another CTF conducted by the same team. It took a real amount of effort using GDB to traverse the program bit by bit for the first time. Glad I found out ways to make GDB more interactive.

I have also used graphical debuggers like CodeBlocks, Kdbg, DDD and Emacs GUD. Also came to know about radare2 from @realsdx and IDA from @iamalsaher. But there was a learning curve which I had planned to cover up later.

Introduction to using a debugger

A debugger is a very powerful tool used for detecting bugs by controlling the execution of a process/program.

Setting breakpoints at specific locations in code, pauses the execution of the program before that location so that we can examine the values of variables or set more breakpoints then optionally we can do either of the following things:

  • Execute the next statement or instruction then pause for further actions
  • Step into execution of a function or module then pause for further actions
  • Resume the execution of a program or function until the end or until it hits a breakpoint

There are various commands to control the execution of the program and examine the data in it. It is recommended that you go through the basic commands in GDB to get the feel of what we will be dealing with in this post.

Interactive GDB

gdb -tui ./tqueen.ctf

This will open a curses window split into two halves, one for showing the source code while the other for running the gdb commands. Pressing C-x 2 splits the first split into two halves showing assembly instructions along with the source code. Pressing C-x 2 again replaces the souce code window with CPU register values.

Screenshot: Multiple splits in GDB

Lets start debugging

Then do some nexti or ni until you reach a jump instruction which might look like the following assembly instruction:

0x55555555505d <main+234>       jle    0x555555555025 <main+178>

Now what you need to do is to analyze the location where it jumps to. You can analyse the jump location using up and down keys. Some of these jump instructions represent normal for loops which might be frustating to go through. So, I would recommend putting a breakpoint at the line just outside the loop.

(gdb) b *main+236  # Add a breakpoint
(gdb) c            # Resumes the execution

If a statement looks suspicious like

0x555555555077 <main+260>       callq  0x555555554ed6 <flagHelper>

We need to step into the execution of the function using stepi or si. In this function is a jump instruction which happens to exit the flagHelper function. Below are some statements of flagHelper function:

0x555555554ed6 <flagHelper>     push   %rbp
0x555555554ed7 <flagHelper+1>   mov    %rsp,%rbp
0x555555554eda <flagHelper+4>   sub    $0x30,%rsp
0x555555554ede <flagHelper+8>   mov    %rdi,-0x28(%rbp)
0x555555554ee2 <flagHelper+12>  movl   $0x4,-0x10(%rbp)
0x555555554ee9 <flagHelper+19>  movl   $0x10,-0xc(%rbp)
0x555555554ef0 <flagHelper+26>  cmpl   $0x45,-0x10(%rbp)
0x555555554ef4 <flagHelper+30>  jle    0x555555554f6c <flagHelper+150>
0x555555554ef6 <flagHelper+32>  cmpl   $0x41,-0xc(%rbp)
0x555555554efa <flagHelper+36>  jle    0x555555554f6c <flagHelper+150>
0x555555554efc <flagHelper+38>  movl   $0x0,-0x14(%rbp)
0x555555554f03 <flagHelper+45>  jmp    0x555555554f1a <flagHelper+68>

Analysis of instructions around flagHelper+150 shows that it is used for returning from the function while flagHelper+68 does some work I am not bothered about.

We can just can change the instruction pointer to execute the unexecuted statements to possibly uncover the flag. The instruction used is:

(gdb) set $rip=*flagHelper+38
(gdb) c

This will spawn up a process(possibly a browser) which needs to be closed or detached in order to obtain the flag.

There are many other ways to obtain the flag without actually executing the whole program but that is left as a homework. The thing you might need in this situation is x/s, a GDB command which prints a string given a base address.

If you have any feedback or suggestions you can Email me at [ comproprasad at gmail dot com ].