Home

/

CTFs

/

BSides Mumbai

/

Warmup

Warmup

Reverse engineering a simple LLVM IR.

REVERSE

~2 minutes

M58

Due to a certain lack of time at the moment, I only focused on the first challenge of Reverse.

We were given access to a simple .txt file

When we display it in our terminal, we realize that we have a LLVM (LowLevelVirtualMachine) IR (Intermediate Representation) file.

We can quickly understand the structure of the program and the few strings it contains. ('The flag is (in)correct').

We can also observe constants that are initialized in the initial program as follows:

190: ; preds = %185
  %191 = getelementptr inbounds [100 x i8], [100 x i8]* %2, i64 0, i64 4
  %192 = load i8, i8* %191, align 4
  %193 = sext i8 %192 to i32
  %194 = icmp eq i32 %193, 49
  br i1 %194, label %195, label %207

195: ; preds = %190
  %196 = getelementptr inbounds [100 x i8], [100 x i8]* %2, i64 0, i64 5
  %197 = load i8, i8* %196, align 1
  %198 = sext i8 %197 to i32
  %199 = icmp eq i32 %198, 95
  br i1 %199, label %200, label %20

Method 1 : We get the ASCII values of each call (here '49' and '95' respectively).

Method 2 : You can use a tool available under Linux (clang(1)). It allows to compile C++ and Objective C.

We quickly rename the file to warmup.ll then we run the command :

mv warmup warmup.ll && clang warmup.ll -o WriteUp && ~/idafree-8.1/ida64 WriteUp

We end up with an ELFx86 that we can import under IDA.

int __cdecl main(int argc, const char **argv, const char **envp)
{
  char s[108]; // [rsp+0h] [rbp-70h] BYREF
  int v5; // [rsp+6Ch] [rbp-4h]

  v5 = 0;
  printf("Enter a string: ");
  scanf("%s", s);
  if ( strlen(s) != 39 )
    exit(0);
  if ( s[28] == 55
    && s[30] == 110
    && s[29] == 49
    && s[36] == 53
    && s[13] == 121
    && s[18] == 95
    && s[2] == 77
    && s[15] == 51
    && s[34] == 48
    && s[7] == 48
    && s[24] == 102
    && s[17] == 102
    && s[26] == 48
    && s[25] == 49
    && s[10] == 100
    && s[27] == 52
    && s[3] == 123
    && s[23] == 95
    && s[19] == 49
    && s[21] == 95
    && s[31] == 57
    && s[8] == 117
    && s[37] == 51
    && s[11] == 95
    && s[33] == 104
    && s[1] == 83
    && s[0] == 66
    && s[22] == 52
    && s[32] == 95
    && s[16] == 49
    && s[12] == 109
    && s[38] == 125
    && s[35] == 117
    && s[6] == 102
    && s[9] == 110
    && s[14] == 53
    && s[4] == 49
    && s[5] == 95
    && s[20] == 110 )
  {
    printf("The flag is correct!\n");
  }
  else
  {
    printf("The flag is incorrect.\n");
  }
  return 0;
}

We can see that the main is really simple, just checks of the [i] of the input in the disorder. We put it all together and find the flag.