Skip to content

Commit

Permalink
Add backup tools
Browse files Browse the repository at this point in the history
Tools manipulate the configuration files produced by the backup service.
  • Loading branch information
nrdmn committed May 24, 2020
1 parent a467e3b commit d571f1b
Show file tree
Hide file tree
Showing 4 changed files with 392 additions and 0 deletions.
12 changes: 12 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
CFLAGS=-Wall -Wextra -O2
LFLAGS=-lcrypto -lssl

BINARIES=license backup_decrypt backup_encrypt backup_content_md5

all: $(BINARIES)

%: %.c
$(CC) $(CFLAGS) $< $(LFLAGS) -o $@

clean:
rm -f *.o $(BINARIES)
45 changes: 45 additions & 0 deletions backup_content_md5.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
// compile with -lcrypto

#include <stdio.h>
#include <openssl/md5.h>

int main(int argc, char **argv)
{
if (argc != 2) {
fprintf(stderr, "usage: %s <filename>\n", argv[0]);
return 1;
}

FILE *file;
if (!(file = fopen(argv[1], "r"))) {
fputs("Can't open file!\n", stderr);
return 2;
}

if (fseek(file, 0x90, SEEK_SET)) {
fputs("Can't seek to 0x90!\n", stderr);
return 3;
}

char buf[0x200];
for (int i = 0; i < 0x200; i++) {
buf[i] = i % 0x4d;
}

MD5_CTX ctx;
char result[16];
MD5_Init(&ctx);
MD5_Update(&ctx, buf, 0x200);

while (fread(buf, 1, 0x200, file) != 0) {
MD5_Update(&ctx, buf, 0x200);
}

MD5_Final(result, &ctx);

for (int i = 0; i < 16; i++) {
printf("%02hhx ", result[i]);
}
puts("");
return 0;
}
156 changes: 156 additions & 0 deletions backup_decrypt.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
// compile with -lcrypto -lssl

#include <assert.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdint.h>
#include <openssl/evp.h>
#include <openssl/rand.h>
#include <openssl/rsa.h>
#include <openssl/ssl.h>

static void callback(int a, int b, void *c)
{
putchar('.');
}

static bool myrand_seeded = false;
static uint32_t myrand_state[2] = {0, 0};

static void myrand_seed(const void *buf, int num)
{
int x = *(uint32_t *)buf;
myrand_seeded = true;
myrand_state[0] = x & 0xffff;
myrand_state[1] = (x << 1) >> 0x11;
}

static unsigned char myrand_get_byte_(uint32_t state[2])
{
// this function is probably wrong
uint32_t foo;
uint32_t bar;

foo = state[0] * 0x3aa8 + 0xf4627;
bar = state[1] * 0x3aa8 + (foo >> 0x10);
foo &= 0xffff;
while (bar > 0x78f0) {
if (foo < 0x10000) {
foo += 0x10000;
bar--;
}
foo -= 0xe079;
bar -= 0x78f0;
}
state[0] = foo;
state[1] = bar;
return foo >> 4;
}

static unsigned char myrand_get_byte()
{
if (!myrand_seeded) {
myrand_seeded = true;
myrand_state[0] = 1;
}
return myrand_get_byte_(myrand_state);
}

static int myrand_nopseudo_bytes(unsigned char *buf, int num)
{
for (int i = 0; i < num; i++) {
buf[i] = myrand_get_byte();
}
return 1;
}

static RAND_METHOD myrand = {
myrand_seed,
myrand_nopseudo_bytes,
NULL,
NULL,
NULL,
NULL,
};

int main(int argc, char **argv)
{
SSL_library_init();
RAND_cleanup();
RAND_set_rand_method(&myrand);

if (argc != 4) {
fprintf(stderr, "usage: %s <chip id> <input file> <output file>\n", argv[0]);
fprintf(stderr, "chip id must be 16 lower case hex digits\n");
return 1;
}

FILE *in_file = fopen(argv[2], "r");
assert(in_file);
fseek(in_file, 0x90, SEEK_SET);
FILE *out_file = fopen(argv[3], "w");
assert(out_file);


puts("reading salt from file");
char salt[0x40];
fread(salt, 0x40, 1, in_file);


puts("read ek length from file");
int ek_len;
fread(&ek_len, 4, 1, in_file);
// flip endianness
ek_len = ek_len << 0x18 | (ek_len >> 8 & 0xff) << 0x10 | (ek_len >> 0x10 & 0xff) << 8 | ek_len >> 0x18;
assert(ek_len == 256);


puts("read ek from file");
char ek[256];
fread(ek, ek_len, 1, in_file);


puts("read iv from file");
int iv_len = EVP_CIPHER_iv_length(EVP_aes_256_cbc());
assert(iv_len == 16);

char iv[16];
fread(iv, iv_len, 1, in_file);


puts("seed rng");
char pbkdf2_result[0x80];
assert(strlen(argv[1]) == 16);
PKCS5_PBKDF2_HMAC(argv[1], 16, salt, 0x40, 0x2f59, EVP_sha384(), 0x80, pbkdf2_result);
//RAND_seed(pbkdf2_result, 0x80);
RAND_seed(pbkdf2_result, 4); // lol entropy


puts("generate rsa key");
RSA *key = RSA_generate_key(0x800, 0x10001, callback, NULL);
assert(key);
puts("done");


EVP_PKEY *pkey = EVP_PKEY_new();
assert(pkey);
EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new();
assert(ctx);
assert(EVP_PKEY_set1_RSA(pkey, key));
assert(EVP_PKEY_size(pkey) == ek_len);
EVP_OpenInit(ctx, EVP_aes_256_cbc(), ek, ek_len, iv, pkey);

fseek(in_file, 0x90 + 0x154*5, SEEK_SET);
char buf[0x2000];
char out[0x2000];
int out_len;
size_t read_len;
while (read_len = fread(buf, 1, 0x1000, in_file)) {
assert(EVP_OpenUpdate(ctx, out, &out_len, buf, read_len));
fwrite(out, out_len, 1, out_file);
}
EVP_OpenFinal(ctx, out, &out_len);
fwrite(out, out_len, 1, out_file);

return 0;
}
179 changes: 179 additions & 0 deletions backup_encrypt.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,179 @@
// compile with -lcrypto -lssl
// THIS PROGRAM DOES NOT SEEM TO WORK CORRECTLY

#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <openssl/evp.h>
#include <openssl/md5.h>
#include <openssl/rand.h>
#include <openssl/rsa.h>
#include <openssl/ssl.h>

static void callback(int a, int b, void *c)
{
putchar('.');
}

static bool myrand_seeded = false;
static uint32_t myrand_state[2] = {0, 0};

static void myrand_seed(const void *buf, int num)
{
int x = *(uint32_t *)buf;
myrand_seeded = true;
myrand_state[0] = x & 0xffff;
myrand_state[1] = (x << 1) >> 0x11;
}

static unsigned char myrand_get_byte_(uint32_t state[2])
{
// this function is probably wrong
uint32_t foo;
uint32_t bar;

foo = state[0] * 0x3aa8 + 0xf4627;
bar = state[1] * 0x3aa8 + (foo >> 0x10);
foo &= 0xffff;
while (bar > 0x78f0) {
if (foo < 0x10000) {
foo += 0x10000;
bar--;
}
foo -= 0xe079;
bar -= 0x78f0;
}
state[0] = foo;
state[1] = bar;
return foo >> 4;
}

static unsigned char myrand_get_byte()
{
if (!myrand_seeded) {
myrand_seeded = true;
myrand_state[0] = 1;
}
return myrand_get_byte_(myrand_state);
}

static int myrand_nopseudo_bytes(unsigned char *buf, int num)
{
for (int i = 0; i < num; i++) {
buf[i] = myrand_get_byte();
}
return 1;
}

static RAND_METHOD myrand = {
myrand_seed,
myrand_nopseudo_bytes,
NULL,
NULL,
NULL,
NULL,
};

struct header {
char magic1[8];
uint64_t size;
unsigned char content_md5[16];
char magic2[16];
char version[32];
char type[32];
unsigned char password_md5[16];
char zeros[16];
};

static const char magic1[8] = {0x49, 0x4c, 0xfa, 0x42, 0x01, 0x01, 0x00, 0x00};

int main(int argc, char **argv)
{
SSL_library_init();
RAND_cleanup();
RAND_set_rand_method(&myrand);

if (argc != 4) {
fprintf(stderr, "usage: %s <chip id> <input file> <output file>\n", argv[0]);
fprintf(stderr, "chip id must be 16 lower case hex digits\n");
return 1;
}

FILE *in_file = fopen(argv[2], "r");
FILE *out_file = fopen(argv[3], "w+");

// high security crypto happens here
char key_length[4] = {0, 0, 1, 0};
char key[0x100];
char iv[0x10];
memset(iv, 0, 0x10);
char salt[0x40];
memset(salt, 0, 0x40);
// seed rng
char pbkdf2_result[0x80];
PKCS5_PBKDF2_HMAC(argv[1], 16, salt, 0x40, 0x2f59, EVP_sha384(), 0x80, pbkdf2_result);
RAND_seed(pbkdf2_result, 4);

// generate key
RSA *rsakey = RSA_generate_key(0x800, 0x10001, callback, NULL);
EVP_PKEY *pkey = EVP_PKEY_new();
EVP_PKEY_set1_RSA(pkey, rsakey);
EVP_CIPHER_CTX *cipher_ctx = EVP_CIPHER_CTX_new();
unsigned char *key_ptr = key;
int ekl;
EVP_SealInit(cipher_ctx, EVP_aes_256_cbc(), &key_ptr, &ekl, iv, &pkey, 1);

// write key info
fseek(out_file, sizeof(struct header), SEEK_SET);
// just write the same key 5 times
for (int i = 0; i < 5; i++) {
fwrite(salt, 0x40, 1, out_file);
fwrite(key_length, 4, 1, out_file);
fwrite(key, 0x100, 1, out_file);
fwrite(iv, 0x10, 1, out_file);
}

char buf[0x2000];
char out[0x2000];
size_t read_len;
int out_len;
while (read_len = fread(buf, 1, 0x1000, in_file)) {
EVP_SealUpdate(cipher_ctx, out, &out_len, buf, read_len);
fwrite(out, out_len, 1, out_file);
}
EVP_SealFinal(cipher_ctx, out, &out_len);
fwrite(out, out_len, 1, out_file);

struct header header;
memset(&header, 0, sizeof(struct header));
memcpy(&header.magic1, &magic1, 8);
header.size = ftell(out_file);
header.magic2[0] = 1;
memcpy(&header.version, "1.40", 4);
memcpy(&header.type, "iLO 5 Backup file", 17);

char md5buf[0x200];
for (int i = 0; i < 0x200; i++) {
md5buf[i] = i % 0x4d;
}
MD5_CTX md5_ctx;
MD5_Init(&md5_ctx);
MD5_Update(&md5_ctx, md5buf, 0x200);
fseek(out_file, 0x90, SEEK_SET);
while (fread(md5buf, 1, 0x200, out_file) != 0) {
MD5_Update(&md5_ctx, md5buf, 0x200);
}

/* write content hash */
MD5_Final(&header.content_md5, &md5_ctx);

/* write empty password hash */
MD5_Init(&md5_ctx);
MD5_Final(&header.password_md5, &md5_ctx);

rewind(out_file);
fwrite(&header, sizeof(struct header), 1, out_file);

return 0;
}

0 comments on commit d571f1b

Please sign in to comment.