feat: implement encryption
This commit is contained in:
3
.gitmodules
vendored
3
.gitmodules
vendored
@@ -1,3 +1,6 @@
|
||||
[submodule "tinyriscv"]
|
||||
path = tinyriscv
|
||||
url = ssh://git@ssh.git.xn--k-0fa.se:222/sas2026/tinyriscv.git
|
||||
[submodule "tiny-AES-c"]
|
||||
path = tiny-AES-c
|
||||
url = git@github.com:kokke/tiny-AES-c.git
|
||||
|
||||
36
Makefile
36
Makefile
@@ -16,10 +16,14 @@ HOST_LDFLAGS ?= -Wl,-s
|
||||
EMU_SRC_FILES := $(wildcard src/emulated/*.c)
|
||||
EMU_OBJ_FILES := $(EMU_SRC_FILES:src/emulated/%.c=build/%.riscv.o)
|
||||
EMU_OBJ := build/emulated.riscv.elf
|
||||
EMU_OBJ_LICENSE := build/license
|
||||
|
||||
GENERATED := build/include/generated.h
|
||||
|
||||
HOST_SRC := src/main.c src/elf.c
|
||||
HOST_SRC_EXTRA := src/elf.c src/hwinfo.c src/util.c tiny-AES-c/aes.c
|
||||
HOST_SRC := src/main.c $(HOST_SRC_EXTRA)
|
||||
HOST_SRC_ENCRYPTOR := src/encryptor.c $(HOST_SRC_EXTRA)
|
||||
HOST_INCLUDE := -I src -I tinyriscv/src -I tiny-AES-c
|
||||
|
||||
ifeq ($(OS),Windows_NT)
|
||||
HOST_EXE := build/main.exe
|
||||
@@ -27,6 +31,13 @@ else
|
||||
HOST_EXE := build/main
|
||||
endif
|
||||
|
||||
ifeq ($(OS),Windows_NT)
|
||||
HOST_EXE_ENCRYPTOR := build/encryptor.exe
|
||||
else
|
||||
HOST_EXE_ENCRYPTOR := build/encryptor
|
||||
endif
|
||||
|
||||
|
||||
# Disassembly
|
||||
RISCV_OBJDUMP ?= $(patsubst %-gcc,%-objdump,$(RISCV_CC))
|
||||
_DISAS_TARGETS := $(filter disas-%,$(MAKECMDGOALS))
|
||||
@@ -36,18 +47,29 @@ _DISAS_FILES := $(if $(_DISAS_TARGETS),$(filter %.elf %.o,$(MAKECMDGOALS)))
|
||||
|
||||
.PHONY: all emulated-riscv host clean disas-risc
|
||||
|
||||
all: $(HOST_EXE) $(EMU_OBJ)
|
||||
all: $(HOST_EXE) $(EMU_OBJ_LICENSE) $(HOST_EXE_ENCRYPTOR)
|
||||
|
||||
emulated-riscv: $(EMU_OBJ)
|
||||
emulated-riscv: $(EMU_OBJ_LICENSE)
|
||||
|
||||
host: $(HOST_EXE)
|
||||
host: $(HOST_EXE) $(HOST_EXE_ENCRYPTOR)
|
||||
|
||||
$(HOST_EXE): $(HOST_SRC) tinyriscv/src/tinyriscv.h src/config.h src/elf.h | build
|
||||
$(HOST_CC) $(HOST_CFLAGS) $(HOST_LDFLAGS) -I src -I tinyriscv/src $(HOST_SRC) -o $@
|
||||
$(HOST_EXE): $(HOST_SRC) | build
|
||||
$(HOST_CC) $(HOST_CFLAGS) $(HOST_LDFLAGS) $(HOST_INCLUDE) $(HOST_SRC) -o $@
|
||||
|
||||
build/%.riscv.o: src/emulated/%.c $(GENERATED) | build
|
||||
$(HOST_EXE_ENCRYPTOR): $(HOST_SRC_ENCRYPTOR) | build
|
||||
$(HOST_CC) $(HOST_CFLAGS) $(HOST_LDFLAGS) $(HOST_INCLUDE) $(HOST_SRC_ENCRYPTOR) -o $@
|
||||
|
||||
build/%.riscv.o: src/emulated/%.c $(GENERATED) $(HOST_EXE_ENCRYPTOR) | build
|
||||
$(RISCV_CC) $(RISCV_ARCH_FLAGS) -I $(dir $(GENERATED)) -I src/emulated -c $< -o $@
|
||||
|
||||
|
||||
EMU_OBJ_LICENSE_IF_EXISTS := $(wildcard $(EMU_OBJ_LICENSE))
|
||||
$(EMU_OBJ_LICENSE): $(EMU_OBJ) | build
|
||||
ifneq ($(EMU_OBJ_LICENSE_IF_EXISTS),)
|
||||
rm $(EMU_OBJ_LICENSE_IF_EXISTS)
|
||||
endif
|
||||
$(HOST_EXE_ENCRYPTOR) $(EMU_OBJ) $@
|
||||
|
||||
$(EMU_OBJ): $(EMU_OBJ_FILES) | build
|
||||
$(RISCV_CC) $(RISCV_ARCH_FLAGS) -nostdlib -Wl,-e,entry -Wl,-Ttext=0 -Wl,--emit-relocs $(EMU_OBJ_FILES) -o $@
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#define EMU_MEM_SIZE 16384u
|
||||
#define EMU_PROGRAM_PATH "build/emulated.riscv.elf"
|
||||
#define EMU_PROGRAM_PATH "build/license"
|
||||
#define EMU_ENTRY_SYMBOL "entry"
|
||||
|
||||
#define STACK_SIZE 1024
|
||||
|
||||
38
src/elf.c
38
src/elf.c
@@ -8,45 +8,41 @@
|
||||
#include <stdlib.h>
|
||||
|
||||
|
||||
static int read_file_bytes(const char* path, uint8_t** out_buf, size_t* out_size) {
|
||||
FILE* f = fopen(path, "rb");
|
||||
static int read_file_bytes(FILE* f, uint8_t** out_buf, size_t* out_size) {
|
||||
if (!f) {
|
||||
fprintf(stderr, "Failed to open object file: %s (%s)\n", path, strerror(errno));
|
||||
fprintf(stderr, "Failed to open object file: (%s)\n", strerror(errno));
|
||||
return LOAD_ERR_OPEN;
|
||||
}
|
||||
|
||||
rewind(f);
|
||||
|
||||
if (fseek(f, 0, SEEK_END) != 0) {
|
||||
fclose(f);
|
||||
fprintf(stderr, "Failed to seek object file: %s\n", path);
|
||||
fprintf(stderr, "Failed to seek object file\n");
|
||||
return LOAD_ERR_SMALL_FILE;
|
||||
}
|
||||
|
||||
long file_size = ftell(f);
|
||||
if (file_size < 0) {
|
||||
fclose(f);
|
||||
fprintf(stderr, "Failed to read object file size: %s\n", path);
|
||||
fprintf(stderr, "Failed to read object file size\n");
|
||||
return LOAD_ERR_SMALL_FILE;
|
||||
}
|
||||
|
||||
if (fseek(f, 0, SEEK_SET) != 0) {
|
||||
fclose(f);
|
||||
fprintf(stderr, "Failed to rewind object file: %s\n", path);
|
||||
fprintf(stderr, "Failed to rewind object file\n");
|
||||
return LOAD_ERR_SMALL_FILE;
|
||||
}
|
||||
|
||||
uint8_t* file_buf = (uint8_t*)malloc((size_t)file_size);
|
||||
if (!file_buf) {
|
||||
fclose(f);
|
||||
fprintf(stderr, "Failed to allocate %ld bytes for object file\n", file_size);
|
||||
return LOAD_ERR_OOM;
|
||||
}
|
||||
|
||||
size_t read_count = fread(file_buf, 1, (size_t)file_size, f);
|
||||
fclose(f);
|
||||
|
||||
if (read_count != (size_t)file_size) {
|
||||
free(file_buf);
|
||||
fprintf(stderr, "Object file too small or unreadable: %s\n", path);
|
||||
fprintf(stderr, "Object file too small or unreadable\n");
|
||||
return LOAD_ERR_SMALL_FILE;
|
||||
}
|
||||
|
||||
@@ -267,29 +263,29 @@ static int apply_relocations(const uint8_t* file_buf, size_t bytes, uint8_t* mem
|
||||
return LOAD_OK;
|
||||
}
|
||||
|
||||
int load_elf_object_sections(const char* path, uint8_t* memory, uint32_t mem_size) {
|
||||
int load_elf_object_sections(FILE* f, uint8_t* memory, uint32_t mem_size) {
|
||||
uint8_t* file_buf = NULL;
|
||||
size_t bytes = 0u;
|
||||
int file_status = read_file_bytes(path, &file_buf, &bytes);
|
||||
int file_status = read_file_bytes(f, &file_buf, &bytes);
|
||||
if (file_status != LOAD_OK) {
|
||||
return file_status;
|
||||
}
|
||||
|
||||
if (bytes < 52u) {
|
||||
fprintf(stderr, "Object file too small or unreadable: %s\n", path);
|
||||
fprintf(stderr, "Object file too small or unreadable\n");
|
||||
free(file_buf);
|
||||
return LOAD_ERR_SMALL_FILE;
|
||||
}
|
||||
|
||||
if (file_buf[0] != ELF_MAGIC_0 || file_buf[1] != ELF_MAGIC_1
|
||||
|| file_buf[2] != ELF_MAGIC_2 || file_buf[3] != ELF_MAGIC_3) {
|
||||
fprintf(stderr, "Not an ELF file: %s\n", path);
|
||||
fprintf(stderr, "Not an ELF file\n");
|
||||
free(file_buf);
|
||||
return LOAD_ERR_NOT_ELF;
|
||||
}
|
||||
|
||||
if (file_buf[4] != ELFCLASS32 || file_buf[5] != ELFDATA2LSB) {
|
||||
fprintf(stderr, "Unsupported ELF format in %s (need 32-bit little-endian)\n", path);
|
||||
fprintf(stderr, "Unsupported ELF format (need 32-bit little-endian)\n");
|
||||
free(file_buf);
|
||||
return LOAD_ERR_UNSUPPORTED_FORMAT;
|
||||
}
|
||||
@@ -299,13 +295,13 @@ int load_elf_object_sections(const char* path, uint8_t* memory, uint32_t mem_siz
|
||||
uint16_t e_shnum = read_u16_le(file_buf + 48);
|
||||
|
||||
if (e_shoff >= bytes || e_shentsize == 0u) {
|
||||
fprintf(stderr, "Invalid section header table in %s\n", path);
|
||||
fprintf(stderr, "Invalid section header table\n");
|
||||
free(file_buf);
|
||||
return LOAD_ERR_INVALID_SHT;
|
||||
}
|
||||
|
||||
if ((uint32_t)e_shoff + (uint32_t)e_shentsize * (uint32_t)e_shnum > bytes) {
|
||||
fprintf(stderr, "Section headers out of file bounds in %s\n", path);
|
||||
fprintf(stderr, "Section headers out of file bounds\n");
|
||||
free(file_buf);
|
||||
return LOAD_ERR_SHT_OUT_OF_BOUNDS;
|
||||
}
|
||||
@@ -389,11 +385,11 @@ int load_elf_object_sections(const char* path, uint8_t* memory, uint32_t mem_siz
|
||||
return reloc_status;
|
||||
}
|
||||
|
||||
int resolve_elf_symbol_memory_offset(const char* path, const char* symbol_name,
|
||||
int resolve_elf_symbol_memory_offset(FILE* f, const char* symbol_name,
|
||||
uint32_t mem_size, uint32_t* out_offset) {
|
||||
uint8_t* file_buf = NULL;
|
||||
size_t bytes = 0u;
|
||||
int file_status = read_file_bytes(path, &file_buf, &bytes);
|
||||
int file_status = read_file_bytes(f, &file_buf, &bytes);
|
||||
if (file_status != LOAD_OK) {
|
||||
return file_status;
|
||||
}
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
#define R_RISCV_RELAX 51u
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
|
||||
enum {
|
||||
LOAD_OK = 1,
|
||||
@@ -48,7 +49,7 @@ enum {
|
||||
uint16_t read_u16_le(const uint8_t* data);
|
||||
uint32_t read_u32_le(const uint8_t* data);
|
||||
uint32_t align_up(uint32_t value, uint32_t align);
|
||||
int load_elf_object_sections(const char* path, uint8_t* memory, uint32_t mem_size);
|
||||
int resolve_elf_symbol_memory_offset(const char* path, const char* symbol_name,
|
||||
int load_elf_object_sections(FILE* f, uint8_t* memory, uint32_t mem_size);
|
||||
int resolve_elf_symbol_memory_offset(FILE* f, const char* symbol_name,
|
||||
uint32_t mem_size, uint32_t* out_offset);
|
||||
|
||||
|
||||
61
src/encryptor.c
Normal file
61
src/encryptor.c
Normal file
@@ -0,0 +1,61 @@
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <aes.h>
|
||||
|
||||
#include "hwinfo.h"
|
||||
#include "util.h"
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
if (argc != 3) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
char* input = argv[1];
|
||||
char* output = argv[2];
|
||||
|
||||
hw_info_t hwinfo = {0};
|
||||
if(get_hw_info(&hwinfo) != 0){
|
||||
return 1;
|
||||
}
|
||||
|
||||
uint8_t* key = hwinfo_to_key(hwinfo);
|
||||
|
||||
if(key == NULL) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
fprintf(stderr, "HWINFO: %s\n", hw_info_flatten(hwinfo));
|
||||
|
||||
fprintf(stderr, "Key: ");
|
||||
for (int i = 0; i < 16; i++)
|
||||
fprintf(stderr, "%02X", key[i]);
|
||||
fprintf(stderr, "\n");
|
||||
|
||||
struct AES_ctx ctx;
|
||||
uint8_t nonce[16] = {0};
|
||||
|
||||
FILE* license = fopen(input, "rb");
|
||||
long data_start = ftell(license);
|
||||
fseek(license, 0, SEEK_END);
|
||||
int license_size = ftell(license) - data_start;
|
||||
fseek(license, data_start, SEEK_SET);
|
||||
uint8_t* buf = malloc(license_size);
|
||||
fread(buf, 1, license_size, license);
|
||||
|
||||
|
||||
AES_init_ctx(&ctx, key);
|
||||
AES_init_ctx_iv(&ctx, key, nonce);
|
||||
AES_CTR_xcrypt_buffer(&ctx, buf, license_size);
|
||||
|
||||
FILE* encrypted_license = fopen(output, "wb+");
|
||||
fwrite(&nonce, 1, sizeof(nonce), encrypted_license);
|
||||
fwrite(buf, 1, license_size, encrypted_license);
|
||||
|
||||
fclose(license);
|
||||
fclose(encrypted_license);
|
||||
|
||||
fprintf(stderr, "Wrote encrypted license file to %s\n", output);
|
||||
|
||||
return 0;
|
||||
}
|
||||
77
src/hwinfo.c
Normal file
77
src/hwinfo.c
Normal file
@@ -0,0 +1,77 @@
|
||||
#include "hwinfo.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
char* hw_info_flatten(hw_info_t hwinfo) {
|
||||
int bufsize = strlen(hwinfo.vendor_id) +
|
||||
strlen(hwinfo.model_name) +
|
||||
strlen(hwinfo.os_version) +
|
||||
strlen(hwinfo.mem_total) +
|
||||
1;
|
||||
|
||||
char* hw_info_flat = malloc(bufsize);
|
||||
|
||||
if(hw_info_flat == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
memset(hw_info_flat, 0, bufsize);
|
||||
|
||||
strcat(hw_info_flat, hwinfo.vendor_id);
|
||||
strcat(hw_info_flat, hwinfo.model_name);
|
||||
strcat(hw_info_flat, hwinfo.os_version);
|
||||
strcat(hw_info_flat, hwinfo.mem_total);
|
||||
|
||||
return hw_info_flat;
|
||||
}
|
||||
|
||||
|
||||
void read_cpu_info(FILE* file, hw_info_t* hwinfo) {
|
||||
char line[256];
|
||||
while(fgets(line, sizeof(line), file)) {
|
||||
if (strncmp(line, "vendor_id", 9) == 0) {
|
||||
hwinfo->vendor_id = strdup(strchr(line, ':') + 2);
|
||||
hwinfo->vendor_id[strcspn(hwinfo->vendor_id, "\r\n")] = 0; // Remove newline
|
||||
} else if (strncmp(line, "model name", 10) == 0) {
|
||||
hwinfo->model_name = strdup(strchr(line, ':') + 2);
|
||||
hwinfo->model_name[strcspn(hwinfo->model_name, "\r\n")] = 0; // Remove newline
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void read_os_version(FILE* file, hw_info_t* hwinfo) {
|
||||
char line[256];
|
||||
if(!fgets(line, sizeof(line), file)){
|
||||
return;
|
||||
}
|
||||
hwinfo->os_version = strdup(strchr(strchr(line, ' ') + 1, ' ') + 1);
|
||||
hwinfo->os_version[strcspn(hwinfo->os_version, " \r\n")] = 0;
|
||||
}
|
||||
|
||||
void read_mem_info(FILE* file, hw_info_t* hwinfo) {
|
||||
char line[256];
|
||||
while(fgets(line, sizeof(line), file)) {
|
||||
if(strncmp(line, "MemTotal", 8) == 0) {
|
||||
hwinfo->mem_total = strchr(line, ':') + 1;
|
||||
hwinfo->mem_total = strdup(hwinfo->mem_total + strspn(hwinfo->mem_total, " "));
|
||||
*strrchr(hwinfo->mem_total, ' ') = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int get_hw_info(hw_info_t* hwinfo) {
|
||||
FILE* f_cpuinfo = fopen("/proc/cpuinfo", "rb");
|
||||
FILE* f_osversion = fopen("/proc/version", "rb");
|
||||
FILE* f_meminfo = fopen("/proc/meminfo", "rb");
|
||||
|
||||
|
||||
if(!f_cpuinfo || !f_osversion || !f_meminfo) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
read_cpu_info(f_cpuinfo, hwinfo);
|
||||
read_os_version(f_osversion, hwinfo);
|
||||
read_mem_info(f_meminfo, hwinfo);
|
||||
|
||||
return 0;
|
||||
}
|
||||
19
src/hwinfo.h
Normal file
19
src/hwinfo.h
Normal file
@@ -0,0 +1,19 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
typedef struct HWInfo {
|
||||
char* vendor_id;
|
||||
char* model_name;
|
||||
char* os_version;
|
||||
char* mem_total;
|
||||
} hw_info_t;
|
||||
|
||||
char* hw_info_flatten(hw_info_t hwinfo);
|
||||
|
||||
void read_cpu_info(FILE* file, hw_info_t* hwinfo);
|
||||
void read_os_version(FILE* file, hw_info_t* hwinfo);
|
||||
void read_mem_info(FILE* file, hw_info_t* hwinfo);
|
||||
|
||||
int get_hw_info(hw_info_t* hwinfo);
|
||||
72
src/main.c
72
src/main.c
@@ -1,18 +1,78 @@
|
||||
#define TINYRISCV_M
|
||||
|
||||
#include "tinyriscv.h"
|
||||
#include "elf.h"
|
||||
#include "hwinfo.h"
|
||||
#include "util.h"
|
||||
|
||||
#include "aes.h"
|
||||
#include "tinyriscv.h"
|
||||
#include "config.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
|
||||
|
||||
#define MAX_STEPS 1024u
|
||||
|
||||
|
||||
int main(){
|
||||
hw_info_t hwinfo = {0};
|
||||
if(get_hw_info(&hwinfo) != 0){
|
||||
return 1;
|
||||
}
|
||||
|
||||
uint8_t* key = hwinfo_to_key(hwinfo);
|
||||
|
||||
if(key == NULL) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
fprintf(stderr, "HWINFO: %s\n", hw_info_flatten(hwinfo));
|
||||
|
||||
fprintf(stderr, "Key: ");
|
||||
for (int i = 0; i < 16; i++)
|
||||
fprintf(stderr, "%02X", key[i]);
|
||||
fprintf(stderr, "\n");
|
||||
|
||||
|
||||
|
||||
struct AES_ctx ctx;
|
||||
uint8_t nonce[16] = {0};
|
||||
|
||||
FILE* license = fopen(EMU_PROGRAM_PATH, "rb");
|
||||
fread(nonce, 16, 1, license);
|
||||
long data_start = ftell(license);
|
||||
fseek(license, 0, SEEK_END);
|
||||
int license_size = ftell(license) - data_start;
|
||||
fseek(license, data_start, SEEK_SET);
|
||||
uint8_t* buf = malloc(license_size);
|
||||
fread(buf, 1, license_size, license);
|
||||
|
||||
|
||||
// void AES_init_ctx(struct AES_ctx* ctx, const uint8_t* key);
|
||||
// void AES_init_ctx_iv(struct AES_ctx* ctx, const uint8_t* key, const uint8_t* iv);
|
||||
// void AES_CTR_xcrypt_buffer(struct AES_ctx* ctx, uint8_t* buf, size_t length);
|
||||
|
||||
AES_init_ctx(&ctx, key);
|
||||
AES_init_ctx_iv(&ctx, key, nonce);
|
||||
AES_CTR_xcrypt_buffer(&ctx, buf, license_size);
|
||||
|
||||
FILE* decrypted_license = tmpfile();
|
||||
fwrite(buf, 1, license_size, decrypted_license);
|
||||
rewind(decrypted_license);
|
||||
|
||||
char begin[8] = {0};
|
||||
char expected[] = {0x7F, 'E', 'L', 'F', 1, 1, 1, 0};
|
||||
fread(begin, 1, sizeof(begin), decrypted_license);
|
||||
if(memcmp(begin, expected, sizeof(begin)) != 0) {
|
||||
// This happens when decryption fails
|
||||
printf("You are not authorized to use this software!\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
const int maxninput = 255;
|
||||
printf("Please enter the flag: ");
|
||||
fflush(stdout);
|
||||
@@ -34,9 +94,9 @@ int main(){
|
||||
memcpy(memory + SECTION_USERDATA + 1, userinput, real_len);
|
||||
|
||||
// Load elf, keep 512 bytes as safe buffer
|
||||
int load_status = load_elf_object_sections(EMU_PROGRAM_PATH, memory, cpu.mem_size - SIZE_USERDATA);
|
||||
int load_status = load_elf_object_sections(decrypted_license, memory, cpu.mem_size - SIZE_USERDATA);
|
||||
if (load_status != LOAD_OK) {
|
||||
fprintf(stderr, "ELF load failed with code %d for '%s'\n", load_status, EMU_PROGRAM_PATH);
|
||||
fprintf(stderr, "ELF load failed with code %d for decrypted license\n", load_status);
|
||||
fflush(stderr);
|
||||
printf("ELF load failed with code %d\n", load_status);
|
||||
fflush(stdout);
|
||||
@@ -45,7 +105,7 @@ int main(){
|
||||
|
||||
uint32_t entry_offset = 0u;
|
||||
int symbol_status = resolve_elf_symbol_memory_offset(
|
||||
EMU_PROGRAM_PATH, EMU_ENTRY_SYMBOL, cpu.mem_size, &entry_offset);
|
||||
decrypted_license, EMU_ENTRY_SYMBOL, cpu.mem_size, &entry_offset);
|
||||
if (symbol_status != LOAD_OK) {
|
||||
fprintf(stderr, "Entry symbol '%s' resolve failed with code %d for '%s'\n",
|
||||
EMU_ENTRY_SYMBOL, symbol_status, EMU_PROGRAM_PATH);
|
||||
@@ -72,9 +132,9 @@ int main(){
|
||||
uint32_t result = (uint32_t)cpu.x[10];
|
||||
|
||||
if(result == 1) {
|
||||
printf("Congrats! That's the flag!");
|
||||
printf("Congrats! That's the flag!\n");
|
||||
} else {
|
||||
printf("Nope, sorry, that's incorrect!");
|
||||
printf("Nope, sorry, that's incorrect!\n");
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
44
src/util.c
Normal file
44
src/util.c
Normal file
@@ -0,0 +1,44 @@
|
||||
#include "util.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
/*
|
||||
We do the following algorithm twice
|
||||
|
||||
algorithm fnv-1a is
|
||||
hash := FNV_offset_basis
|
||||
|
||||
for each byte_of_data to be hashed do
|
||||
hash := hash XOR byte_of_data
|
||||
hash := hash × FNV_prime
|
||||
|
||||
return hash
|
||||
*/
|
||||
void dual_fnv_hash(char* input, uint8_t key[16]) {
|
||||
uint64_t lower = 0xcbf29ce484222325;
|
||||
uint64_t upper = 0xcbf29ce484222325 + 0xC0010FF5E7; // add a made-up constant
|
||||
|
||||
while(*input != 0) {
|
||||
lower = (lower ^ *input) * FNV_PRIME;
|
||||
upper = (upper ^ *input) * FNV_PRIME;
|
||||
|
||||
input += 1;
|
||||
}
|
||||
|
||||
memcpy(key, &lower, 8);
|
||||
memcpy(key + 8, &upper, 8);
|
||||
}
|
||||
|
||||
|
||||
uint8_t* hwinfo_to_key(hw_info_t hwinfo) {
|
||||
char* hw_info_flat = hw_info_flatten(hwinfo);
|
||||
|
||||
if (hw_info_flat == NULL){
|
||||
return NULL;
|
||||
}
|
||||
|
||||
uint8_t* key = malloc(16);
|
||||
dual_fnv_hash(hw_info_flat, key);
|
||||
|
||||
return key;
|
||||
}
|
||||
15
src/util.h
Normal file
15
src/util.h
Normal file
@@ -0,0 +1,15 @@
|
||||
#pragma once
|
||||
|
||||
#include "hwinfo.h"
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#define FNV_PRIME 0x00000100000001b3
|
||||
|
||||
// Generate an aes key by hashing the input
|
||||
// This hash is not safe in any way
|
||||
// But it is fast and easy to implement!
|
||||
// https://en.wikipedia.org/wiki/Fowler%E2%80%93Noll%E2%80%93Vo_hash_function
|
||||
void dual_fnv_hash(char* input, uint8_t key[16]);
|
||||
|
||||
uint8_t* hwinfo_to_key(hw_info_t hwinfo);
|
||||
1
tiny-AES-c
Submodule
1
tiny-AES-c
Submodule
Submodule tiny-AES-c added at 23856752fb
Reference in New Issue
Block a user