Skip to content
Jenn Janesko edited this page Apr 5, 2019 · 12 revisions

The problem was described in the following way:

"Rufus, down dog!" commands Captain Crypto. But, Rufus the fun-loving dog wants a pet.

"All right, Rufus, I told you three times. That's enough! Now you're going into your crate..."

He's a cute little dog; don't worry, he won't byte. :-)

Your mini-mission: free Rufus!

SSH to challenges.ctfd.io on port 30060 Login with username rufus and password rufus

After ssh-ing to the server, I found an executable file and a file which I could not access due to file permissions. My assumption is that the flag was in the inaccessible file and that running the executable successfully would give access to the flag. Using scp, I copied the executable to my local computer.

scp -P 30060 rufus@challenges.ctfd.io:rufus ./

Running the executable locally, I observed that I needed to provide input when prompted.

Entering "3" resulted in failure. So, using gdb enhanced with PEDA, I opened the executable in the debugger. Before starting, I changed the display of the disassembler to intel.

Then I disassembled main as a starting point. There I saw some very interesting function calls.

  • compareLowerByte
  • compareHigherByte
  • comparesMiddleByte
  • winnerWinnerChickenDinner

My assumption is that winnerWinnerChickenDinner was the function that was called when the correct value is provided. The other 3 functions looked suspiciously like functions that performed the checks on the entered value. I disassembled each of the compare... functions and added a breakpoint at the only cmp statements in those functions. I wanted to inspect the values that were being compared. Each of the functions had a similar cmp call. This is an example from compareLowerByte.

As can be seen, there is a comparison between the value that was stored in register eax and the DWORD at the address stored in the rbp register minus the value 0xc (in all cases, the resulting address was0x7fffffffdb74).

Running the program and stopping at the cmp instructions, I observed the values against which my entered value was compared. The following was discovered:

compareLowerByte

It looks like I need to somehow pass a 4 byte value. The value that I need has 0x21 in the 4th byte position.

compareHigherByte

The value that I need has 0x12 in the 1st byte position.

compareMiddleBytes

The values that I need to pass has 0x3443 in the 2nd and 3rd byte positions.

Put together, this value is 0x12344321. Somehow I needed to get this value into the program. As ASCII, this value has unprintable values. I took a quick look at the program to see if I needed to write a python script to pass the non-printable values to the program, and I noticed a very interesting function call, atoi.

According to https://www.tutorialspoint.com/c_standard_library/c_function_atoi.htm, atoi converts a number represented as a string into the integer represented by the string. So, string '255' would become the integer value 255 and would be stored as 0xFF in memory. So, I tried entering the value 305414945 (integer value of 0x12344321) into the program. This resulted in a failure.

I stepped through the program, and I noticed that my value that I entered was modified at some point. After the atoi function, eax register contained 0x12344321. But, one instruction later, there is an xor operation.

0x555555554a50 <main+98>: xor eax,0x84ff

This xor operation modifies my inputted value to something slightly different and stores it in eax.

EAX: 0x1234c7de

This eax value remained the constant value that was used for comparison through the rest of that program. Since xor is a two way function, I prepared my value by xor-ing the compare value 0x12344321 by 0x84ff and then converted to an integer. The result was:

0x12344321 ^ 0x84ff

305448926

Passing the integer value to the program on the server resulted in the successful running of the program and access to the flag file contents.

Yay!