164 lines
5.0 KiB
C
164 lines
5.0 KiB
C
|
// crossfire: distributed brute force infrastructure
|
||
|
//
|
||
|
// Copyright (C) 2020 haskal
|
||
|
//
|
||
|
// This program is free software: you can redistribute it and/or modify
|
||
|
// it under the terms of the GNU Affero General Public License as published by
|
||
|
// the Free Software Foundation, either version 3 of the License, or
|
||
|
// (at your option) any later version.
|
||
|
//
|
||
|
// This program is distributed in the hope that it will be useful,
|
||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
|
// GNU Affero General Public License for more details.
|
||
|
//
|
||
|
// You should have received a copy of the GNU Affero General Public License
|
||
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||
|
|
||
|
#include "crossfire-embedding.h"
|
||
|
#include "find-section.h"
|
||
|
|
||
|
#include <stdio.h>
|
||
|
#include <stdarg.h>
|
||
|
#include <time.h>
|
||
|
#include <unistd.h>
|
||
|
|
||
|
#include <chezscheme.h>
|
||
|
#include <racketcs.h>
|
||
|
#include <monocypher.h>
|
||
|
|
||
|
#define error() \
|
||
|
fprintf(stderr, "[WRAPPER] fatal boot error... corrupted binary?\n"); \
|
||
|
return -1;
|
||
|
|
||
|
static const ffi_ent ffi_table[] = {
|
||
|
FFI_ENT(crypto_sign_public_key),
|
||
|
FFI_ENT(crypto_sign),
|
||
|
FFI_ENT(crypto_check),
|
||
|
FFI_ENT(crypto_key_exchange_public_key),
|
||
|
FFI_ENT(crypto_key_exchange),
|
||
|
FFI_ENT(crypto_lock),
|
||
|
FFI_ENT(crypto_unlock),
|
||
|
FFI_ENT(crypto_wipe),
|
||
|
FFI_ENT(crypto_blake2b_init),
|
||
|
FFI_ENT(crypto_blake2b_update),
|
||
|
FFI_ENT(crypto_blake2b_final),
|
||
|
|
||
|
FFI_ENT(clock_gettime),
|
||
|
FFI_ENT(gethostname),
|
||
|
FFI_ENT(fsync)
|
||
|
};
|
||
|
static const size_t ffi_table_size = sizeof(ffi_table)/sizeof(ffi_ent);
|
||
|
|
||
|
// yeet
|
||
|
// chez people don't yell at me pls
|
||
|
static ptr scheme_list(int count, ...) {
|
||
|
va_list ap;
|
||
|
va_start(ap, count);
|
||
|
ptr vals[count];
|
||
|
for (int i = 0; i < count; i++) {
|
||
|
ptr arg = va_arg(ap, ptr);
|
||
|
vals[i] = arg;
|
||
|
}
|
||
|
va_end(ap);
|
||
|
ptr val = Snil;
|
||
|
for (int i = 0; i < count; i++) {
|
||
|
val = Scons(vals[count - i - 1], val);
|
||
|
}
|
||
|
return val;
|
||
|
}
|
||
|
|
||
|
static void cs_setup_ffi_table() {
|
||
|
// this is pain
|
||
|
// chez scheme is pain
|
||
|
// why is it like this
|
||
|
// gimme my scheme_primitive_module holy shit pls,,,,
|
||
|
racket_namespace_require(Sstring_to_symbol("racket/base"));
|
||
|
|
||
|
// also since this is '#%kernel level code, technically it's all UB
|
||
|
// which is fun
|
||
|
ptr module = Sstring_to_symbol("module");
|
||
|
ptr __module_begin = Sstring_to_symbol("#%module-begin");
|
||
|
ptr quote = Sstring_to_symbol("quote");
|
||
|
ptr __kernel = Sstring_to_symbol("#%kernel");
|
||
|
ptr __provide = Sstring_to_symbol("#%provide");
|
||
|
ptr define_values = Sstring_to_symbol("define-values");
|
||
|
|
||
|
ptr __static_ffi = Sstring_to_symbol("#%static-ffi");
|
||
|
ptr table_n = Sstring_to_symbol("table");
|
||
|
ptr table_size_n = Sstring_to_symbol("table-size");
|
||
|
ptr arch_n = Sstring_to_symbol("arch");
|
||
|
|
||
|
ptr table_e = scheme_list(2, quote, Sunsigned64((uint64_t) &ffi_table[0]));
|
||
|
ptr table_size_e = scheme_list(2, quote, Sunsigned64(ffi_table_size));
|
||
|
ptr arch_e = scheme_list(2, quote, Sstring(APP_ARCH));
|
||
|
|
||
|
ptr table_d = scheme_list(3, define_values, scheme_list(1, table_n), table_e);
|
||
|
ptr table_size_d = scheme_list(3, define_values, scheme_list(1, table_size_n), table_size_e);
|
||
|
ptr arch_d = scheme_list(3, define_values, scheme_list(1, arch_n), arch_e);
|
||
|
|
||
|
ptr e = scheme_list(4,
|
||
|
module,
|
||
|
__static_ffi,
|
||
|
scheme_list(2, quote, __kernel),
|
||
|
scheme_list(5,
|
||
|
__module_begin,
|
||
|
scheme_list(4, __provide, table_n, table_size_n, arch_n),
|
||
|
table_d,
|
||
|
table_size_d,
|
||
|
arch_d));
|
||
|
|
||
|
// evaling this magically registers it in the default namespace
|
||
|
// it's magic
|
||
|
// don't ask questions
|
||
|
racket_eval(e);
|
||
|
}
|
||
|
|
||
|
int main(int argc, char* argv[]) {
|
||
|
printf("[WRAPPER] booting racket CS\n");
|
||
|
boot_ctx ctx;
|
||
|
if (init_boot_ctx(&ctx) < 0) {
|
||
|
error();
|
||
|
}
|
||
|
|
||
|
racket_boot_arguments_t args;
|
||
|
memset(&args, 0, sizeof(args));
|
||
|
|
||
|
args.boot1_path = ctx.self_name;
|
||
|
args.boot2_path = ctx.self_name;
|
||
|
args.boot3_path = ctx.self_name;
|
||
|
|
||
|
boot_lookup boot1 = boot_ctx_lookup(&ctx, ".csboot1");
|
||
|
boot_lookup boot2 = boot_ctx_lookup(&ctx, ".csboot2");
|
||
|
boot_lookup boot3 = boot_ctx_lookup(&ctx, ".csboot3");
|
||
|
|
||
|
if (boot1.offset == (off_t) -1 ||
|
||
|
boot2.offset == (off_t) -1 ||
|
||
|
boot3.offset == (off_t) -1) {
|
||
|
error();
|
||
|
}
|
||
|
|
||
|
args.boot1_offset = boot1.offset;
|
||
|
args.boot2_offset = boot2.offset;
|
||
|
args.boot3_offset = boot3.offset;
|
||
|
|
||
|
args.exec_file = argv[0];
|
||
|
|
||
|
racket_boot(&args);
|
||
|
|
||
|
boot_lookup app_offset = boot_ctx_lookup(&ctx, ".boot");
|
||
|
if (app_offset.offset == (off_t) -1) {
|
||
|
error();
|
||
|
}
|
||
|
racket_embedded_load_bytes(((uint8_t*) ctx.self_mm) + app_offset.offset,
|
||
|
app_offset.size, false);
|
||
|
|
||
|
unload_boot_ctx(&ctx);
|
||
|
|
||
|
cs_setup_ffi_table();
|
||
|
ptr mod = Scons(Sstring_to_symbol("quote"), Scons(Sstring_to_symbol(APP_NAME), Snil));
|
||
|
racket_dynamic_require(mod, Sfalse);
|
||
|
|
||
|
return 0;
|
||
|
}
|