From 8eed8cde29960ace2ea1b2ceb61962be6f258364 Mon Sep 17 00:00:00 2001 From: David Timber Date: Mon, 7 Sep 2020 21:54:51 +0930 Subject: * Impl: proone-pack * Impl: host_cred (base64) --- src/proone-pack.c | 430 ++++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 334 insertions(+), 96 deletions(-) (limited to 'src/proone-pack.c') 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 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 [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; } -- cgit