angry (rev)

As the challenge name suggests, we should be using angr to solve the challenge. The main code is as follows:

undefined8 main(void)
{
  int iVar1;
  void *input;
  
  input = malloc(1);
  process(input,"Give me a password : ",0x28);
  iVar1 = check1(input); // I renamed this function
  if (iVar1 == 0) {
    puts("Bruh : (");
  }
  else {
    iVar1 = check2(input); // I renamed this function
    if (iVar1 == 0) {
      puts("Bruh : (");
    }
    else {
      puts("Congratulations !");
    }
  }
  return 0;
}

process() essentially prompts for the input and saves it into the address of input.

Then, the input is encrypted using check1. check1 is given below.

undefined8 check1(byte *input)
{
  int 0x25;
  size_t n;
  undefined8 uVar1;
  
  n = strlen((char *)input);
  0x25 = FUN_001011fe(); // this function just returns 0x25
  if (((((((((n == (long)0x25) &&
            ((int)(char)input[15] * (int)(char)input[5] - (int)(char)input[7] == 0x12ec)) &&
           (input[6] == 'n')) &&
          (((int)(char)input[7] * (int)(char)input[7] == 0x2971 && (input[8] != 0)))) &&
         ((input[9] != 0 && ((((int)(char)input[10] & 0x3fffffffU) == L'4' && (input[11] == '_')) )))
         ) && (input[12] == 'l')) &&
       ((((((int)(char)(input[2] ^ input[13] ^ *input ^ input[1]) != (uint)(input[3] == 0x44) &&
           ((int)(char)input[17] +
            (int)(char)input[14] + (int)(char)input[15] + (int)(char)input[16] == 0x15c)) &&
          ((int)(char)(input[1] ^ input[15]) != (uint)(input[2] == 0x41))) &&
         (((((int)(char)input[16] + (int)(char)input[21]) - (int)(char)input[25] == 0x55 &&
           ((int)(char)input[33] + ((int)(char)input[17] - (int)(char)input[32]) == 156)) &&
          ((input[18] == '0' && ((input[19] == 'n' && (input[20] == 't')))))))) &&
        (((input[17] ^ input[21]) == 0x3b &&
         (((input[22] == 'd' && ((int)(char)input[0x17] != (uint)(input[21] == 10))) &&
          (input[24] == '_')))))))) &&
      (((((int)(char)input[25] - (int)(char)input[5] == 8 && (input[26] != 1)) &&
        (((input[27] == '_' &&
          ((((int)(char)input[28] + (int)(char)input[21]) - (int)(char)input[25] == 99 &&
           ((int)(char)input[29] != (uint)((int)(char)input[28] + (int)(char)input[31] == 246)))) )
         && (input[30] == 'n')))) &&
       (((((int)(char)input[0x1f] != (uint)(input[13] == 100) &&
          ((int)(char)input[31] + (int)(char)input[34] == 193)) &&
         ((int)(char)input[33] + (int)(char)input[32] == 160)) &&
        ((input[33] == 'l' && ((int)(char)input[33] - (int)(char)input[1] == 57)))))))) &&
     ((input[34] == 'l' && ((input[35] == 'y' && (input[36] == 0x7d)))))) {
    uVar1 = 1;
  }
  else {
    uVar1 = 0;
  }
  return uVar1;
}

It verifies that the input length is 37 and performs a series of checks on the characters of the input. If we pass these checks we move on to enc2:

undefined8 check2(long param_1)
{
  undefined8 uVar1;
  
  if ((((*(char *)(param_1 + 8) == 'r') && (*(char *)(param_1 + 9) == '_')) &&
      (*(char *)(param_1 + 23) == 'o')) &&
     ((*(char *)(param_1 + 29) == '4' && ((char)(*(byte *)(param_1 + 10) & 0xcf) < '\n')))) {
    uVar1 = 1;
  }
  else {
    uVar1 = 0;
  }
  return uVar1;
}

Again, we are performing more (albeit straightforward) checks on the input.

Using claripy, we specify our flag to be a bitvector with 37 characters. Using angr, we specify the base address of the binary to be 0, and we want to find the address 0x1286 which is the address of puts("Congratulations !"), and we avoid the addresses 0x1848 and 0x1837 which are the addresses of puts("Bruh : ( "). We then get the simulation manager to explore the program and find the flag.

import angr
import sys
import claripy

input_file_path='./angry_patched_skill_issues'
flag_length=37
known_string='L3AK{'
FIND_ADDR=0x1826
AVOID_ADDR=[0x1848, 0x1837]


proj=angr.Project(input_file_path,main_opts={'base_addr':0x00})
known_chars=[claripy.BVV((known_string[i])) for i in range(len(known_string))]
flag_chars=[claripy.BVS(f"flag_{i}",8) for i in range(flag_length-len(known_string))]
flag=claripy.Concat(*known_chars+flag_chars + [claripy.BVV(b'\n')])
state = proj.factory.entry_state(args=[input_file_path], stdin=flag)
# state=proj.factory.full_init_state(args=[input_file_path,flag])
# state = proj.factory.full_init_state(stdin=flag)
sim_manager=proj.factory.simulation_manager(state)
sim_manager.explore(find=FIND_ADDR,avoid=AVOID_ADDR)

if(len(sim_manager.found)>0):
	print(sim_manager.found[0].solver.eval(flag,cast_to=bytes))

# L3AK{angr_4_l1f3_d0nt_do_it_m4nU4lly}

Last updated