Rating: 4.0

Califrobnication (83 solves)

It's the edge of the world and all of western civilization.

The sun may rise in the East at least it's settled in a final location. It's understood that Hollywood sells Califrobnication.

You get source for this one. Find the flag at /problems/2020/califrobnication on the shell server.

Author: kmh11

In this challenge we have to find flag based on anagram from strfry function.

Since we know current time and pid of process, we can reverse strfry and get original message.

Source:

#include <stdio.h>
#include <string.h>

int main() {
    FILE *f;
    char flag[50];
    f = fopen("flag.txt", "r");
    fread(flag, 50, 1, f);
    strtok(flag, "\n");
    memfrob(&flag, strlen(flag));
    strfry(&flag);
    printf("Here's your encrypted flag: %s\n", &flag);
}

The memfrob() function encrypts the first n bytes of the memory area s by exclusive-ORing each character with the number 42. The effect can be reversed by using memfrob() on the encrypted memory area.

The strfry() function randomizes the contents of string by using rand to randomly swap characters in the string. The result is an anagram of string.

strfry source code:

#include <string.h>
#include <stdlib.h>
#include <time.h>
#include <unistd.h>
char *
strfry (char *string)
{
  static int init;
  static struct random_data rdata;
  if (!init)
    {
      static char state[32];
      rdata.state = NULL;
      __initstate_r (time ((time_t *) NULL) ^ getpid (),
                     state, sizeof (state), &rdata);
      init = 1;
    }
  size_t len = strlen (string);
  if (len > 0)
    for (size_t i = 0; i < len - 1; ++i)
      {
        int32_t j;
        __random_r (&rdata, &j);
        j = j % (len - i) + i;
        char c = string[i];
        string[i] = string[j];
        string[j] = c;
      }
  return string;
}

And here is where we can cheat:

__initstate_r (time ((time_t *) NULL) ^ getpid (), state, sizeof (state), &rdata);

The seed, that passed to __random_r is based on current time xor pid.

Solution:

Since we can determine current time and average pid number range, we can find right rand sequence that was generated by the program.

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>
#include <unistd.h>
#include <stdint.h>

// out initial values
const int32_t finish_time = 1584522034;
const int32_t start_time  = 1584522000;
const int32_t startpid    = 2100;
const int32_t finishpid   = 2200;
const char flag[] =  "9dcm0doda2er_aic46aa5fftb1lc_84nfcn1rf{_5otoi}ia";

// reversed strfry
char *strfry_rev(char *string, const int *seq) {
    size_t len = strlen(string);

    for (size_t i = len - 2; i >= 0; i--) {
        char c = string[i];
        string[i] = string[seq[i]];
        string[seq[i]] = c;
    }
    return string;
}


void brute() {
    for (int32_t t = start_time; t <= finish_time; t++) {
        for (int32_t pid = startpid; pid <= finishpid; pid++) {
            printf("trying %d %d: ", t, pid);
            
            int seq[50] = { 0 };
            char placeholder[50] = { 0 };
            
            // taken from strfry.c source
            static struct random_data rdata;
            static char state[32];
            rdata.state = NULL;

            // generate seq of random ints based on seed
            initstate_r (t ^ pid, state, sizeof (state), &rdata);
            // len(flag) == 48
            int len = 48; 
            for (int i = 0; i < len - 1; i++) {
                int32_t j;
                random_r (&rdata, &j);
                j = j % (len - i) + i;
                seq[i] = j;
            }

            // reverse strfry
            strcpy(placeholder, flag);
            strfry_rev(placeholder, seq);
            printf("%s\n", placeholder);
        }

    }
}

int main(int argc, char const *argv[])
{
    brute();
    return 0;
}
$ ./a.out | grep actf
trying 1584522016 2101: actf{dream_of_califrobnication_1f6d458091cad254}
trying 1584522017 2100: actf{dream_of_califrobnication_1f6d458091cad254}
trying 1584522018 2103: actf{dream_of_califrobnication_1f6d458091cad254}
trying 1584522019 2102: actf{dream_of_califrobnication_1f6d458091cad254}
trying 1584522024 2109: actf{dream_of_califrobnication_1f6d458091cad254}
trying 1584522025 2108: actf{dream_of_califrobnication_1f6d458091cad254}
trying 1584522026 2111: actf{dream_of_califrobnication_1f6d458091cad254}
trying 1584522027 2110: actf{dream_of_califrobnication_1f6d458091cad254}
trying 1584522028 2105: actf{dream_of_califrobnication_1f6d458091cad254}
trying 1584522029 2104: actf{dream_of_califrobnication_1f6d458091cad254}
trying 1584522030 2107: actf{dream_of_califrobnication_1f6d458091cad254}
trying 1584522031 2106: actf{dream_of_califrobnication_1f6d458091cad254}
Original writeup (https://github.com/archercreat/CTF-Writeups/blob/master/angstromctf/rev/Califrobnication/README.md).