Solving reverse_cipher from picoCTF

Hello everyone! Today we’re looking at reverse_cipher from picoCTF. It is under the category of Reverse engineering in the picoGym. picoCTF has some really great challenges and best of all…it’s free to join! Lets get started!

First Run

You start this challenge with 2 files: a binary/ELF and a text file. Running the binary gives you an error and the text file, rev_this, just contains something that looks like a flag. Lets load our binary into Ghidra and see what we can find out.

String Search to get to the useful code

Lets create a new project, jump into the Code Browser, let Ghidra analyze the binary and see what we come up with. To get to the important code quickly, do a Strings search (Search -> For Strings), accept the default search parameters, and your results should look like the above picture. Double click the highlighted selection in the picture above and double click the reference or “XREF” and you should end up in the main function.

Main function!

Now that we’re in the main function, we can begin to understand the working of this program. First it appears that it is trying to open a file named “flag.txt” in read mode as seen in the decompiler on the right(line 15) and in the assembly instructions on the left(00101194 and 0010119b). Problem is…we don’t have a “flag.txt” file so lets create one. Copy the contents of “rev_this” into “flag.txt” and lets run our program again with “ ./rev flag.txt”.

Creating flag.txt and running again

Looking back at the the decompiler we see another “fopen” command(line 16) but this time with the append mode set. It looks like it’s appending some data to our “rev_this” file and in fact, that’s exactly what it’s doing. Looks like it appended another flag…huh…interesting! Lets keep analyzing.

Renamed Variables

I went ahead and renamed the variables(rightclick the variable in the decompiler -> select rename) to make it easier to understand. Looks like our program is now reading from the file “flag.txt” and saving the characters to an array named “flag_chars_array” which is what I renamed the variable to. A quick check is done to make sure that “fread” returned some data and if not “exit(0)” is called.

First Loop

Now we encounter our first loop! Notice again I changed some variable names. This loop isn’t doing very much. In fact it’s simply copying the first 8 letters from “flag_chars_array” into our “rev_this” file. This will give us the 8 chars of “picoCTF{”. Lets get to the next loop!

Our Second Loop

Alright so we have another while loop, with another counter value this time initialized to 8(line 39). Looks like this will run until “flag_counter” is no longer less than 0x17(which is hex for 23). Right off the bat we encounter an “if” statement with the bitwise operator “&”. This is checking to see if “flag_counter & 1” is equal to zero and if it is, a value of 5 is added to the character in the “flag_chars_array” at the index of “flag_chars_array[flag_counter]”. If “flag_counter & 1” is not equal to zero, we subtract 2 from the current position. We then put this char in the “rev_this” file and increment our counter.

Check values where ( i & 1 ) will equal 0

A quick check with python as to the values that evaluate to zero is seen on the left. Now we can really start to see all the details in this program. Lets run some more checks.

Showing ‘w’ as five chars away from |

Our test flag had a couple of w’s(at index 8 and 12) in it which became pipe characters (|) which are 5 away from each other in the ASCII table.

Showing 1 is 2 chars away from /

Our test flag also had a couple of 1’s(at index 9 and 11) in it which became backslashes(/), two away on the ASCII table.

Rolling with this logic we can deduce that in order to get a flag that produces our original flag in originally downloaded “rev_this” file, we must reverse action and subtract 5 when our “if” statement evaluates to true and add 2 when it evaluates to false. I wrote a little python script that did this for me as seen below.

Python Script to product flag
Result from our python script

So were we correct?

diff to compare

‘diff’ couldn’t tell the difference between the two which is a great sign!

Got Another one!!

Looks like we got it!! Hurray!! I had solved this problem previously, had a good time doing it, and decided to do a writeup, hence the “…correctly again.” part. This challenge is great fun and is something of a substitution cipher/simple substitution. I hope you’ll give it a shot as well!

Hello there! You’ll find some programming problems and Capture the Flags here. Who doesn’t love a good puzzle?