Skip to content

Latest commit

 

History

History
110 lines (91 loc) · 2.91 KB

File metadata and controls

110 lines (91 loc) · 2.91 KB

Dysfunctional

My "functional programming in C" library finally works! Although, now that I realize it, it seems more... dysfunctional. Either way, I've used it for my cutting edge flag encryption algorithm along with this file - here's the encrypted flag.

Attachments:

Solution

Decompiling the binary in IDA and renaming/retyping variables we get...

Main Function

int __cdecl main(int argc, const char **argv, const char **envp)
{
  unsigned int rand_flag[64];
  char flag[72];

  FILE *stream; = fopen("flag", "r");
  fgets(flag, 64, stream);
  FILE *not_flag; = fopen("not_flag", "r");
  lookup = malloc(0x20000uLL);
  fread(lookup, 0x20000uLL, 1uLL, not_flag);
  int flag_len = strlen(flag);
  FILE *random = fopen("/dev/urandom", "r");
  for (int i = 0; i < flag_len; ++i )
  {
    int v6 = 0;
    for (int j = 0; j <= 2; ++j )
      v6 = (fgetc(random) + v6) << 8;
    rand_flag[i] = v6 + flag[i];
  }
  long *closure_1 = closure(0xDEADuLL, 0xBEEF, 0xFEEDLL, lookup);
  long *closure_2 = closure(0x1337uLL, 0xCAFE, 0x1234LL, lookup);
  long *comp_1 = compose(closure_1, closure_2);
  long *comp_2 = compose(closure_2, closure_1);
  unsigned int *some_data = map(comp_1, rand_flag, flag_len);
  unsigned int *output_flag = map(comp_2, some_data, flag_len);
  for (int k = 0; k < flag_len; ++k )
    printf("%x ", output_flag[k]);
  puts("is the encrypted flag. Good luck!");
  free(lookup);
  return 0;
}

The flag is read and converted to a int array of higher bits as random data. Then it reads some data from not_flag and does something in closure

map

unsigned int *__fastcall map(long *func, unsigned int *data, int len)
{
  unsigned int *result;

  result = (unsigned int *)malloc(4LL * len);
  for (int i = 0; i < len; ++i )
    result[i] = func(data[i]);
  return result;
}

The data returned after closure and compose are some functions. So I used dynamic analysis to understand those functions... the results are:

comp_1 Function

unsigned int comp1(unsigned int input)
{
	unsigned int tmp = stack_func_1(input);
	unsigned int result = stack_func_2(tmp);
	return result;
}

comp_2 Function

unsigned int comp2(unsigned int input)
{
	unsigned int tmp = stack_func_2(input);
	unsigned int result = stack_func_1(tmp);
	return result;
}

stack_func_1

unsigned int stack_func_1(unsigned int inp)
{
  return 0xDEAD ^ (SBox[(inp & 0xFFFF) ^ 0xBEEF] + SBox[(inp >> 16) ^ 0xBEEF] << 16);
}

stack_func_2

unsigned int stack_func_2(unsigned int inp)
{
  return 0x1337 ^ (SBox[(inp & 0xFFFF) ^ 0xCAFE] + SBox[(inp >> 16) ^ 0xCAFE] << 16);
}

I dumped the Sbox data with gdb(dump binary memory SBox 0x00007ffff7fa5010 0x7ffff7fc5010).

So I just xored the encypted flag data and inversed Sbox to get the flag.

Solve script here

Flag

actf{but_wh4t_4b0ut_0bj3ct_d1s0r13nt3d}