Try   HackMD

[zer0pts CTF 2020] Locked KitKat

tags: zer0pts CTF forensics

Overview

We're given an Android disk image. Our goal is to find the pattern lock.
Since this is an old version of Android (KitKat), we can recover the pattern from /data/system/gesture.key.

Solution

gesture.key uses SHA1 hash.
You can write a simple brute-force script.

#include <stdio.h>
#include <string.h>
#include <openssl/sha.h>
#define MAX_LENGTH 9

void sha1(unsigned char *data, unsigned char *hash, int len) {
  SHA_CTX c;
  SHA1_Init(&c);
  SHA1_Update(&c, data, len);
  SHA1_Final(hash, &c);
}

long crack(unsigned char *target, int len, int depth, unsigned long code) {
  int i;
  long result;
  unsigned long c = code;
  unsigned char hash[SHA_DIGEST_LENGTH];
  unsigned char data[MAX_LENGTH];

  if (depth == len) {
    for (i = 0; i < len; i++) {
      data[i] = c % 10;
      c /= 10;
    }
    sha1(data, hash, len);
    if (strncmp(target, hash, SHA_DIGEST_LENGTH) == 0) {
      return code;
    } else {
      return -1;
    }
  } else {
    for (i = 0; i < 10; i++) {
      result = crack(target, len, depth + 1, code * 10 + i);
      if (result != -1) break;
    }
  }

  return result;
}

int main(void) {
  int l, i;
  unsigned char target[SHA_DIGEST_LENGTH];
  long result;
  FILE *fp = fopen("./gesture.key", "rb");
  if (fp == NULL) {
    perror("gesture.key");
    return 1;
  }

  l = fread(target, SHA_DIGEST_LENGTH, 1, fp);

  for(l = 1; l <= MAX_LENGTH; l++) {
    result = crack(target, l, 0, 0);
    if (result == -1) {
      printf("[-] Failed: len=%d\n", l);
    } else {
      printf("Code: ");
      for(i = 0; i < l; i++) {
        printf("%c", (char)(0x30 + (result % 10)));
        result /= 10;
      }
      putchar('\n');
      fclose(fp);
      return 0;
    }
  }

  puts("Solution not found :(");
  fclose(fp);
  return 1;
}