Check out the new web development bootcamp! learn more

It has already been one month since I first created this blog! I am trying to improve it. Do you have any ideas? leave a feedback

home > NCL Exploitation Root Cause Write Up

NCL Exploitation Root Cause Write Up

Noah Tongate · April 20, 2020 · 7 min read

ctfexploitationreverseengineering

0

0 leave some love!

This was my first time competing in an event like the competition hosted by the National Cyber League (NCL) and I had a lot of fun going through each of the categories from Wifi Pentesting, Network Analysis, Exploitation, Web App Security and many more.

There were many tricky challenges that ranged from Easy to Hard, but the category that I found most interesting is the “Enumeration and Exploitation” category. The challenges in this category involved reverse engineering software/malware or retrieving files from a machine.

There was a challenge in the Spring 2020 Preseason that I really enjoyed solving called “Root Cause”. During the preseason I noticed that there was around ten players that managed to solve the Root Cause problem in the beginning unlike many of the other challenges where there were many people with a 100% completion in different categories. I saw this as a challenge and began to solve it and become one of the top players.

You are given the option between downloading either a x32 or x64 binary file to solve the problem. So my first instinct was to open the debugger of my choice and at the time I used Ghidra a tool that was developed by the NSA.

You can also follow along with binary file to download here

Once you open Ghidra you want to start a new project and import the binary file into you project.

Screenshot1

Now that the file is added to the project we want to open the CodeBrowser which is represented as a dragon in the tool chest panel. Then open the project and import file in the CodeBrowser..

Screenshot2

Now that we have imported the file we want to analyze it

Screenshot3

In the next window we want to make sure we have “Decompile Parameter ID” checked

Screenshot4

To jump to the start of the program we can go to the symbol tree window on the left side and under the dropdown of the functions folder we want to click “entry” this is where the C program begins.

Screenshot5

In the decompile window we can see the entry point and that it calls another function which is our “main”. The decompiler renamed this to FUN_00400b0b. If we double click on it we can jump to the main of the C program.

Screenshot6

Once we have stepped into the main of the C program we can see on line 2 there is an int and undefined datatype as the parameters. From experience with C we can assume that this is int argc, char *argv and user input is passed to the binary. Also it is important to note the TID that we were given by the NCL competition is only argument that is ran when the binary is executed in the terminal. You can also see proof of that on line 17.

Screenshot7

So we can go ahead and rename these by right clicking and changing the variable name and type to its respective value. At this point we can begin to follow the decompiled code and understand what is going on. We can also see that the program requires the user to run a root or a user that has a UID of 0

 uid = geteuid();
 if (uid != 0) {
   fwrite("You don\'t have permission to run this program!\n",1,0x2f,stderr);
                   /* WARNING: Subroutine does not return */
   exit(1);
 }

So I went ahead and renamed a few variables to help me follow the program.

Screenshot8

We can see that there is a another function previously called FUN_00400906 that we renamed to CalculateFlag that passes an argument of argv[1] which should be the TID value that we passed into the program. Now if we double click on the CalculateFlag function we can just to its decompiled code and right off the bat I noticed that there were variables that had hex values set.

Screenshot9

If we convert those hex values to ascii we should get something that starts with SKY- which is a piece of a flag since all the NCL flags start with NCL- or SKY-. We cant assume that this is the flag because the program does something with the TID and those values.

As we go through the program we notice is that the AUTH linux environment variable is retrieved and saved to a variable in the program and is later used.

  __s = getenv("AUTH");
   if (__s != (char *)0x0) {
    sVar1 = strlen(__s);
    if (sVar1 == 0xd) {
      local_68 = 0;
      local_70 = 0;
      while( true ) {
        sVar1 = strlen(tid);
        if (sVar1 <= (ulong)(long)local_70) break;
        local_68 = local_68 + tid[local_70];
        local_70 = local_70 + 1;
      }
      local_6c = 0;

I assume this AUTH environment variable is set on the NCL linux server and has a flag stored to check the user input the right flag. We can see that the program checks to make sure the user input flag is 13 (0xd) characters long and begins to take the TID value we passed in and adding the decimal value of each char to local_68 which is later used in the program.

Unfortunately I don’t have the TID that was given to me, but the value of local_68 turned out to be 2487.

Then immediately after we can see that local_6c is set to 0 which which is the index of the program.

        if (index < 4) {
          if ((int)flag_value[index] != local_58[index]) {
            uVar2 = 0;
            goto LAB_00400adf;
          }
        }

Now the code begins to come a little more clear. The code above shows that the AUTH environment variable which we assumed as the flag value is compared with the values we found at the beginning of the program as shown below. This values should be equivalent to SKY-.

  local_58[0] = 0x53;
  local_58[1] = 0x4b;
  local_58[2] = 0x59;
  local_58[3] = 0x2d;
  local_48 = 0x50;
  local_44 = 0x51;
  local_40 = 0x4e;
  local_3c = 0x4f;
  local_38 = 0xc;
  local_34 = 0x31;
  local_30 = 0x30;
  local_2c = 0x30;
  local_28 = 0x31;

‘0x50’, ‘0x51’, ‘0x4e’, ‘0x4f’, ‘0xc’, ‘0x31’, ‘0x30’, ‘0x30’, ‘0x31’

Now that we know the flag begins with SKY- we can begin to solve the rest. Now that we are looking for the 4 index value of the flag we can follow the code below.

        else {
          if (index == 8) {
            if (flag_value[8] != flag_value[3]) {
              uVar2 = 0;
              goto LAB_00400adf;
            }
          }
          else {
            if (((long)flag_value[index] ^ tid_value % 10) != (long)local_58[index]) {
              uVar2 = 0;
              goto LAB_00400adf;
            }
          }
        }
        index = index + 1;

As we said earlier we can assume that local48, local44, local40, local3c, local38, local34, local30, local2c, and local28 is the remaining values of the local58 array which is the obfuscated flag stored in the program. Since we are looking for the 4 index we will start at line 9 and it we can see that the flag value we input has a bitwise XOR to the value 2487 (tidvalue) and is modulus by 10 and is compared to the local58 flag character stored in the program. So in order to reverse the value we can use a little bit of python.

chr(int("0x50" ,16) ^ 2487 % 10)

The output returns a ‘W’

So we can do this for all of the hex values.

a = ['0x50', '0x51', '0x4e', '0x4f', '0xc', '0x31', '0x30', '0x30', '0x31']
  for hex in a:
    print chr(int(hex ,16) ^ 2487 % 10),

The output gives us:

W V I H 6 7 7 6

Now all we have to do is piece it together and we have the flag.

Just to note for the future. The TID will always be different so this flag wont always be the same.


Noah Tongate -I’m currently a student at the University of Louisville double majoring in Computer Science and Computer Engineering. I’m passionate about the field of Cyber Security, but more specifically the offensive security.
Archive