Post

CSAW 2019 - beleaf

by CSAW

Tree sounds are best listened to by https://binary.ninja/demo or ghidra.

Attachments: beleaf

Solution

This challenge was my introduction into reverse engineering. Utilizing Ghidra, I was able to decompile the binary and view the main function:

Screenshot 2023-07-24 at 7 01 00 PM

This function takes in an input with a length greater than 33 bytes (0x21), then iterates through the input. With each iteration, the current index position character is passed into the transformFunc function:

Screenshot 2023-07-24 at 7 03 11 PM

This function takes in a single character and returns the index with which it lies within the &lookup table. Here’s a sample of what our &lookup table looks like:

Screenshot 2023-07-24 at 7 04 41 PM

Lets go back to our main function:

Screenshot 2023-07-24 at 7 06 15 PM

Once the function is “transformed” (the index of that character is found), that returned value is compared with our desired output table. Here is a sample of that table:

Screenshot 2023-07-24 at 7 07 47 PM

This table has values that are offset to every 8 bytes. If the transformedValue and the ExpectedOutput index value do not match up, the challenge will fail. So we need values at: 01, 09, 11, 27, 02, 00, 12, 03, 08, 12, 09, 12, 11, 01, 03, 13, 04, 03, 05, 15, 2e, 0a, 12, 03, 01, 2e, 16, 2e, 12, 06

Lets go back to the transformedFunc:

Screenshot 2023-07-24 at 7 16 41 PM

Let’s plug in a value and walk through this:

1
2
3
4
5
input = f
transformFunc(char f){
  long i;
  i = 0
  while((i != -1 && ((int)f != *(int*)(&lookup +i * 4)))

So, (int)f is converting our char to ASCII (102) The reference to &lookup is referring to the first index in our table:

Screenshot 2023-07-24 at 7 22 14 PM

so this value (&lookup + i * 4) is equivalent to: 0x301020 + 0 * 4 => 0x301020 OR 0x77 (119) Let’s clean it up

1
2
3
while((i != -1 && (102 != 119)){
  if (102 < 119){
    i = i * 2 + 1

i now equals 1, new iteration

1
  while((i != -1 && (119 != (0x301020 + 1 * 4))){

(0x301020 + 1 * 4) => 0x301024 OR 0x66 (102)

1
2
3
4
5
6
while((i != -1 && (102 != 102)){
  if (102 < 119){
    i = i * 2 + 1;
  ...
  ...
  return i;

Screenshot 2023-07-24 at 7 40 47 PM

The condition passes as we have found the index with which our value of “f” passes. This index (i) is 1 and that index is returned to the main function

Screenshot 2023-07-24 at 7 42 39 PM

1
if (1 != 01 + 0 * 8)

Here we have returned the value of 1, which, when compared with our desiredOutput, happens to match the index of our current desiredOutput table

Screenshot 2023-07-24 at 7 33 24 PM

We can follow the same logic with all of the other values inside of our lookup table. Once done, we should receive the flag:

1
flag{we_beleaf_in_your_re_future}

This was my first reverse engineering challenge that I was able to fully grasp. Hopefully this helps you understand these types of problems.

This post is licensed under CC BY 4.0 by the author.