Skip to content

Latest commit

 

History

History

solution

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 

Writeup

The challenge is based on two components:

  1. VectorBlox: You can view the manual here!
  2. simon: A lightweight block cipher.

The code was not stripped to help with understanding and checking the manual.

Here is the source code:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <stdint.h>
#include <assert.h>
#include <sys/ptrace.h>
#include "vbx.h"
#include "utils.h"

const int N = 8;
const uint8_t secret[] = {0x1e, 0xcb, 0x87, 0xc1, 0xb4, 0x76, 0x70, 0xb9, 0x99, 0xad, 0xdf, 0x84, 0x1e, 0x62, 0x25, 0x66, 0x38, 0x50, 0x72, 0xe3, 0xf1, 0x5f, 0x6c, 0x00, 0x0c, 0xef, 0xaf, 0x94, 0xc6, 0x03, 0xc4, 0xb1, 0x7f, 0x96, 0x18, 0xb3, 0x7f, 0x94, 0x54, 0x0a, 0xc7, 0xf8, 0xc2, 0xf1, 0x19, 0xe5, 0xda, 0xbf, 0xd7, 0x8f, 0xce, 0xbb, 0x0e, 0x7d, 0xe8, 0xdd, 0xc2, 0xca, 0x29, 0xcb, 0xc1, 0x23, 0x03, 0x66};

struct RNG {
    unsigned int seed;
};

unsigned int gen(struct RNG* rng) {
    rng->seed = rng->seed * 110515245 + 114514;
    return (unsigned int)(rng->seed/65536) % 32768;
}

uint8_t* init(int N, char* key) {
    uint8_t *arr = (uint8_t*) malloc((N*N) * sizeof(uint8_t));
    for(int i = 0; i < N*N; i++) {
        arr[i] = (uint8_t) key[i];
    }
    return arr;
}

int manipulate(vbx_ubyte_t *v_dst, vbx_ubyte_t *v_src, const int N) {
	vbx_set_vl(1, N, N);
	vbx_set_2D(N * sizeof(vbx_ubyte_t), sizeof(vbx_ubyte_t), 0);
	vbx_set_3D(sizeof(vbx_ubyte_t), N * sizeof(vbx_ubyte_t), 0);
    vbx(VVBU, VMOV, v_dst, v_src, 0);
	return 1;
}

int enc(uint8_t *keys, uint8_t* input) {
    for (int i = 0; i < N; i++) {
        uint8_t *pt = input + i * N;
        enc2(pt, keys);
        // pt should match secret[i*N:i*N+N]
        if (memcmp(pt, secret + i * N, N) != 0) {
            return 0;
        }
    }
    return 1;
}


int main() {

	printf("+------+.    \n");
	printf("|`.    | `.  \n");
	printf("|  `+--+---+ \n");
	printf("|   |  |   | \n");
	printf("+---+--+.  | \n");
	printf(" `. |    `.| \n");
	printf("   `+------+ \n");

#if VBX_SIMULATOR==1
	vbxsim_init(512, 16384, 256, 6, 5, 4, 0, 0);
#endif
    if (ptrace(PTRACE_TRACEME, 0, 0, 0) == -1) exit(1);
	char command[65];
	printf("Enter the command to unlock the Matrix...\n> ");
	scanf("%64s", command);

	if (strlen(command) != 0x40 || strncmp(command, "SEKAI{", 6) != 0 || command[63] != '}') {
		printf("Incorrect command format. You cannot unlock the Matrix. :(\n");
		exit(1);
	}

	uint8_t *A = init(N, command);
	static const int num_elements = N * N;

	// Allocate vectors in scratchpad
	vbx_ubyte_t* v_A = vbx_sp_malloc(num_elements * sizeof(vbx_ubyte_t));
	vbx_ubyte_t* v_B = vbx_sp_malloc(num_elements * sizeof(vbx_ubyte_t));
	vbx_ubyte_t* v_C = vbx_sp_malloc(num_elements * sizeof(vbx_ubyte_t));
    vbx_ubyte_t* v_D = vbx_sp_malloc(num_elements * sizeof(vbx_ubyte_t));
	vbx_ubyte_t* v_O = vbx_sp_malloc(num_elements * sizeof(vbx_ubyte_t));

	if (v_A == NULL || v_B == NULL || v_C == NULL || v_D == NULL || v_O == NULL) {
		printf("Unknown error while launching the Matrix.\n");
		exit(1);
	}

	vbx_dma_to_vector(v_A, A, num_elements * sizeof(vbx_ubyte_t));
	vbx_sync();

	vbx_set_vl(num_elements);

	vbx(VSBU, VXOR, v_A, v_A, 0x13);

	vbx(SVBU, VMOV, v_B, 2, 0);

    vbx(VSBU, VSLT, v_D, v_A, 97);

    vbx(VVBU, VSUB, v_B, v_B, v_D);

	vbx(VVBU, VMUL, v_C, v_A, v_B);

	manipulate(v_O, v_C, N);

	uint8_t* output = (uint8_t*) malloc(num_elements * sizeof(uint8_t));
	vbx_dma_to_host(output, v_O, num_elements * sizeof(vbx_ubyte_t));
    vbx_sync();

	printf("Command accepted. Generating your Single-use Key...\n");
	printf("Using RNG to make it completely random.");
	sleep(2);
	struct RNG rng = {0xdeadbeef};
	uint8_t key[16];
	for (int i = 0; i < 16; i++) {
		while (1) {
			key[i] = (uint8_t) gen(&rng) % 256;
			if (key[i] >= 33 && key[i] <= 126) {
				break;
			}
		}
	}

    uint8_t keys[SEKAI_BLOCK_SIZE/16*SEKAI_R2];
    ks2(key, keys);

	printf("\nVerifying your identity...\n");
	if (enc(keys, output)) {
		printf("Access granted. Enjoy the Matrix Flag.\n");
	} else {
		printf("Access denied. You cannot unlock the Matrix. :(\n");
	}

    vbx_sp_free();
	return 0;
}

Flag: SEKAI{y4y_u_p4ss3d_ScR4TcHp4D_t35t_w1th_V3ct0rB10x_4nd_51M0N_xD}