Skip to content

Instantly share code, notes, and snippets.

@hexploitable
Last active August 23, 2020 14:56
Show Gist options
  • Save hexploitable/25e1805b832fa3e2c25ba4875ffce2dd to your computer and use it in GitHub Desktop.
Save hexploitable/25e1805b832fa3e2c25ba4875ffce2dd to your computer and use it in GitHub Desktop.
r2con2020 CTF cyberlock
/*
r2con2020 CTF - Cyber Lock
@hexploitable
flag: r2con{StopL0ckPickingY0urNos3}
Challenge description:
1. Only accept input at the third minute of every hour. - expected to patch this
2. Input via file the code below, it will then say how many pins are correct.
3. If all pins are correct, use the input to derive key to decrypt flag
*/
// Imports
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <time.h>
#include <string.h>
#include <glib.h>
#include <glib-object.h>
#include <glib/gstdio.h>
#include <openssl/evp.h>
#include <openssl/aes.h>
#include <stdint.h>
#include <assert.h>
/* defines */
#define kRED "\x1B[31m"
#define kGRN "\x1B[32m"
#define kRST "\033[0m"
#define AES_256_KEY_LENGTH 32
#define AES_256_KEY_LENGTH_BITS 256
#define AES_256_IVEC_LENGTH 12
#define AES_256_GCM_TAG_LENGTH 16
/*
sample input
2 sha256 "pins", each a single ASCII character.
without quotes: "are you real".
*/
const char *code = "\
2E7D2C03A9507AE265ECF5B5356885A53393A2029D241394997265A1A25AEFC6\
454349E422F05297191EAD13E21D3DB520E5ABEF52055E4964B82FB213F593A1";
static void printLock () {
printf("[i] R2conCTF 2020 - CyberLock 1.3.3.7-alpha\n");
printf("\n");
printf(" .--------. \n");
printf(" / .------. \\\n");
printf(" / / \\ \\\n");
printf(" | | | | \n");
printf(" _| |________| |_ \n");
printf(".' |_| |_| '. \n");
printf("'._____ ____ _____.' \n");
printf("| .'____'. | \n");
printf("'.__.'.' '.'.__.' \n");
printf("'.__ |!R2Con| __.' \n");
printf("| '.'.____.'.' | \n");
printf("'.____'.____.'____.' \n");
printf("'.________________.' \n");
printf("\n");
printf("[i] The r2con Cyberlock is the world's only quantum, military-grade, agile, blockchain backed, hardened, bullet-proof 12-pin digital cryptographic cyber lock.\n");
printf("[i] Hackers will never make it past the first pin!!!!\n\n");
}
/*
input is crafted as: {sha256 of pin}_{minute (3)}_{r2con2020}.
input is hashed using sha512 and compared with the {hashes} array per the correct pin index.
pin1: c ... generated str: 2E7D2C03A9507AE265ECF5B5356885A53393A2029D241394997265A1A25AEFC6_3_r2con2020
pin2: h ... generated str: AAA9402664F1A41F40EBBC52C9993EB66AEB366602958FDFAA283B71E64DB123_3_r2con2020
pin3: a ... generated str: CA978112CA1BBDCAFAC231B39A23DC4DA786EFF8147C4E72B9807785AFEE48BB_3_r2con2020
pin4: o ... generated str: 65C74C15A686187BB6BBF9958F494FC6B80068034A659A9AD44991B08C58F2D2_3_r2con2020
pin5: s ... generated str: 043A718774C572BD8A25ADBEB1BFCD5C0256AE11CECF9F9C3F925D0E52BEAF89_3_r2con2020
pin6: M ... generated str: 08F271887CE94707DA822D5263BAE19D5519CB3614E0DAEDC4C7CE5DAB7473F1_3_r2con2020
pin7: o ... generated str: 65C74C15A686187BB6BBF9958F494FC6B80068034A659A9AD44991B08C58F2D2_3_r2con2020
pin8: N ... generated str: 8CE86A6AE65D3692E7305E2C58AC62EEBD97D3D943E093F577DA25C36988246B_3_r2con2020
pin9: K ... generated str: 86BE9A55762D316A3026C2836D044F5FC76E34DA10E1B45FEEE5F18BE7EDB177_3_r2con2020
pin10: e ... generated str: 3F79BB7B435B05321651DAEFD374CDC681DC06FAA65E374E38337B88CA046DEA_3_r2con2020
pin11: y ... generated str: A1FCE4363854FF888CFF4B8E7875D600C2682390412A8CF79B37D0B11148B0FA_3_r2con2020
pin12: s ... generated str: 043A718774C572BD8A25ADBEB1BFCD5C0256AE11CECF9F9C3F925D0E52BEAF89_3_r2con2020
*/
const char *salt = "r2con2020";
const char *hashes[12] =
{
"D9259A378FC0EA75C1828369059854DEF76F91CABD01B56EF548C7ABA6441D59DD2DB9E51BD70C457179A123D53138F88132B29C691A9671F6C80E41E7D682A4",
"3F675784DABBC1330806CB4D5FE67860C25E103B75EB7B22821B2D75264B60C4D2E042A1726E1B85E3936A2A95E835E92FEFAC2C2E34A249109D98AED3962C71",
"BD605F0A10170EC1F7610BCF696C518AAB31C235CCF47866A71C332368BFE8B7E9FE4E3907B3CD37F111B40EEFFE89287C25033A41369A3236751474AD522537",
"B8CA8A22501EAB44AD44E6EB2F87791CA69955BFFC025988418866BDD8A1EAABA97F630A705D68B26370E49DAD9DE65AB478117C4289FFC240A8C85308D116A1",
"0694F2776E101C72092994B2F125973CBD3A608B3BA17CF8795DDDEEDE6773E0DE8D832EAE4EE3FF8C748FD6BDBC1BF843081CC6AEEFB09B1C908AD484382884",
"F9B4F710E8ADC5D4A32779A865396B019A630E2B1DB475F0F1656BC195ED2E0171932C9629DE5417F5C2D96FECC4B89107C9E28477513F98D5147391DF374C3C",
"B8CA8A22501EAB44AD44E6EB2F87791CA69955BFFC025988418866BDD8A1EAABA97F630A705D68B26370E49DAD9DE65AB478117C4289FFC240A8C85308D116A1",
"7280E46538FE2158921FA20E7A835E9F4900E8AFDA73E1D1EE03472E0B34D59AC28ABE964652B6EC8DF1B44D3F1B90A7684D470A191BB446FB2149918E69DE38",
"F08DF5E5DFDACE8892F03B4475263D72D6999DCC499C741028935D7D167222086F5FB63C793C20BA02E56AB74E901B1E66D178206E91B469F6055E63EE824D7F",
"9D9A2B793485D2ADF818DB5DF1D97CD1072F826845940780ECA50B623F8D931DC9533AF77DF2B811645B8B852670188A17736E8A536F672D5639EA40F2D1FC40",
"4AC1807EC58C1BD56D177E3F409FBD0FBCDE7D97F9F8A71469FD92817BB866B4D71A0DF10EB501AF6CE4439861E46B89473555B08874CEBA33312AD3495E84F2",
"0694F2776E101C72092994B2F125973CBD3A608B3BA17CF8795DDDEEDE6773E0DE8D832EAE4EE3FF8C748FD6BDBC1BF843081CC6AEEFB09B1C908AD484382884"
};
// unsigned char *encrypt(unsigned char *key)
// {
// const unsigned char *plaintext = "r2con{StopL0ckPickingY0urNos3}";
// int status = 0;
// const unsigned char ivec[13] = "000000000000";
// gchar *md5;
// md5 = g_compute_checksum_for_string(G_CHECKSUM_MD5, key, strlen(key));
// GString *computedHash = g_string_ascii_up(g_string_new(md5));
// g_free(md5);
// printf("Encrypt Key: %s\n", computedHash->str);
// // printf("encrypting: %s\n", plaintext);
// // set up to Encrypt AES 256 GCM
// int numberOfBytes = 0;
// EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new();
// EVP_EncryptInit_ex (ctx, EVP_aes_256_gcm(), NULL, NULL, NULL);
// // set the key and ivec
// EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_IVLEN, AES_256_IVEC_LENGTH, NULL);
// EVP_EncryptInit_ex (ctx, NULL, NULL, computedHash->str, ivec);
// unsigned char *ciphertext = malloc(4096);
// EVP_EncryptUpdate (ctx, ciphertext, &numberOfBytes, plaintext, strlen((const char *)plaintext));
// status = EVP_EncryptFinal_ex (ctx, ciphertext+numberOfBytes, &numberOfBytes);
// // EVP_CIPHER_CTX_free(ctx);
// int i;
// unsigned char *p = (unsigned char *)ciphertext;
// for (i=0;i<128;i++) {
// printf("0x%02x ", p[i]);
// if ((i%16==0) && i)
// printf("\n");
// }
// // printf("Ciphertext: %s\n", ciphertext);
// return ciphertext;
// }
unsigned char *decrypt(unsigned char *ciphertext, unsigned char *key)
{
int status = 0;
const unsigned char ivec[13] = "000000000000";
// printf("Decrypt Key: %s\n", key);
// printf("decrypting: %s\n", ciphertext);
// set up to Encrypt AES 256 GCM
int numberOfBytes = 0;
EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new();
EVP_EncryptInit_ex (ctx, EVP_aes_256_gcm(), NULL, NULL, NULL);
// set the key and ivec
EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_IVLEN, AES_256_IVEC_LENGTH, NULL);
EVP_DecryptInit_ex (ctx, NULL, NULL, key, ivec);
unsigned char *plaintext = malloc(1024);
EVP_DecryptUpdate (ctx, plaintext, &numberOfBytes, ciphertext, strlen((const char *)ciphertext));
status = EVP_DecryptFinal_ex (ctx, plaintext+numberOfBytes, &numberOfBytes);
EVP_CIPHER_CTX_free(ctx);
plaintext[30] = '\0';
return plaintext;
}
void decryptFlag(const char *key) {
unsigned char flag[] = {
0xd7, 0x8a, 0xf3, 0xb8, 0x98, 0x46, 0x37, 0x06,
0x89, 0x71, 0x20, 0x08, 0x58, 0x8c, 0xdd, 0x69,
0xce, 0x7d, 0xf2, 0xa6, 0x53, 0x5e, 0xd9, 0xaf,
0x47, 0x4f, 0xe3, 0x2e, 0x54, 0x3a, 0x00, 0x00
};
gchar *md5;
md5 = g_compute_checksum_for_string(G_CHECKSUM_MD5, key, strlen(key));
GString *derivedKey = g_string_ascii_up(g_string_new(md5));
g_free(md5);
const unsigned char *plaintext = decrypt(flag, (unsigned char *)derivedKey->str);
printf("\n[i] Flag: %s%s%s\n", kGRN, plaintext, kRST);
return;
}
void checkPins (const char *s, int minute)
{
const size_t N = 64;
char pin[N + 1];
int count = 1;
size_t i = 0;
int correctCount = 0;
char masterKey[1537] = {};
for (; *s; ++s)
{
if (count > 12) {
printf("[!] stack-based pin overflow!!!\n");
break;
}
if (!isspace((unsigned char)*s)) {
pin[i++] = *s;
if (i == N) {
pin[i] = '\0';
i = 0;
char pinInput[128];
strcpy(pinInput, pin);
strcat(pinInput, "_");
char min[3] = {};
sprintf(min, "%d", minute);
strcat(pinInput, min);
strcat(pinInput, "_");
strcat(pinInput, salt);
// printf("[i] Constructed pin: %s\n", pinInput);
gchar *sha512;
sha512 = g_compute_checksum_for_string(G_CHECKSUM_SHA512, pinInput, strlen(pinInput));
GString *computedHash = g_string_ascii_up(g_string_new(sha512));
// printf("[i] SHA512 hash: %s\n", computedHash->str);
// g_free(sha512);
// printf("[i] Comparing with %s (hash %d)\n", hashes[count-1], count-1);
int result = strncmp(hashes[count-1], computedHash->str, 128);
if (result == 0) {
printf("[i] Pin %d:\t%s - %sBINGO!!!%s\n", count++, pin, kGRN, kRST);
strcat(masterKey, pin);
correctCount++;
if (correctCount == 12) {
break;
}
} else {
printf("[i] Pin %d:\t%s - %sWRONG!!!%s\n", count++, pin, kRED, kRST);
printf("[i] %sWARNING - This unlock attempt has been logged and @pancake has been notified!!!%s\n", kRED, kRST);
break;
}
}
}
}
if (correctCount == 12) {
printf("\n[i] %s12%s/12 pins correct.\n", kGRN, kRST);
printf("[i] Welcome back %s@pancake%s, using your master key: %s\n", kGRN, kRST, masterKey);
decryptFlag(masterKey);
} else {
printf("\n[i] %s%d%s/12 pins correct.\n", kRED, correctCount, kRST);
}
}
static int getCurrentMinute () {
time_t rawtime;
struct tm *timeinfo;
time(&rawtime);
timeinfo = localtime(&rawtime);
int minute = timeinfo->tm_min;
return minute;
}
int main () {
printLock();
// if minute 3...
int currentMinute = getCurrentMinute();
if (currentMinute == 3) { //TODO - change back to ==
GError *err = NULL;
const char *fname = "/tmp/masterkey.in";
FILE *file = g_fopen (fname, "r");
if (file) {
gchar *pinCodes;
gboolean didRead = g_file_get_contents(fname, &pinCodes, NULL, &err);
if (didRead) {
printf("[i] Procesing input code...\n");
checkPins(pinCodes, currentMinute);
}
} else {
//use the internal code variable to give them a clue, they can then copy this to the file
checkPins(code, currentMinute);
}
} else {
printf("[!] Oh... we forgot to tell you that this secure lock can only be unlocked once per hour - ha ha ha! Come back at 3 minutes past the hour.\nExiting...\n");
}
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment