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 firstname.lastname@example.org: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.
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
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 was
Running the program and stopping at the cmp instructions, I observed the values against which my entered value was compared. The following was discovered:
It looks like I need to somehow pass a 4 byte value. The value that I need has
0x21 in the 4th byte position.
The value that I need has
0x12 in the 1st byte position.
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,
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
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.
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
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.