Jump to content

Windows CryptoAPI: Difference between revisions

From Haidhi Wiki
 
Line 250: Line 250:
g++ .\main.cpp -o main -lcrypt32
g++ .\main.cpp -o main -lcrypt32
main.exe
main.exe
</syntaxhightlight>
</syntaxhighlight>


= Catatan Akhir =
= Catatan Akhir =

Latest revision as of 06:18, 10 April 2025

Windows menyediakan berbagai API untuk kriptografi yang bisa digunakan secara legal oleh aplikasi, tapi juga disalahgunakan oleh malware. API tersebut berasal dari Advapi32.dll dan mencakup:

  • CryptAcquireContext
  • CryptCreateHash
  • CryptHashData
  • CryptDeriveKey
  • CryptEncrypt
  • CryptDecrypt
  • CryptImportKey
  • CryptDestroyKey
  • CryptDestroyHash
  • CryptReleaseContext


Step-by-Step Malware Menggunakan Crypto API

Note: Dalam konteks malware, CryptoAPI digunakan untuk mengenkripsi payload, C2 config, atau file hasil exfiltration agar susah di-reverse engineer atau dideteksi oleh antivirus.

Step 1: Acquire Cryptographic Context

Malware memanggil CryptAcquireContext buat mendapatkan handle ke CSP yang akan dipakai buat semua operasi kriptografi selanjutnya.

HCRYPTPROV hProv = NULL;
CryptAcquireContext(&hProv, NULL, MS_ENH_RSA_AES_PROV, PROV_RSA_AES, CRYPT_VERIFYCONTEXT);

Code C++ di atas memakai Windows CryptoAPI. Fokus utama code ini adalah untuk mengambil cryptographic context memakai CryptAcquireContext

Lalu apa itu Cryptographic Context? Di Windows sebelum kita melakukan operasi cryptography, maka kita harus memiliki yang namanya Cryptographic Context. Cryptographic Context sendiri mirip dengan environment atau objek yang menyimpan informasi penting soal provider yang dipakai seperti algoritma dan key container. Berikut adalah penjelasan code sebelumnya

// Digunakan untuk menyimpan cryptographic context
HCRYPTPROV hProv = NULL;
CryptAcquireContext(
  &hProv,                 // tempat menyimpan hasil context
  NULL,                   // nama key container (NULL = default)
  MS_ENH_RSA_AES_PROV,    // nama provider (di sini pakai Enhanced RSA AES)
  PROV_RSA_AES,           // tipe provider (RSA + AES)
  CRYPT_VERIFYCONTEXT     // flag: tidak menyimpan key secara permanen
)

Step 2: Menyiapkan Key

Ada dua cara untuk menyiapkan key yaitu:

  • Hash & Derive
  • Memakai KEYBLOB


Hash & Derive

Derive = menurunkan atau membentuk sesuatu dari sesuatu yang lain. dalam konteks cryptography derive adalah membuat kunci kriptografi (AES, DES, dll) dari data lain yang belum berbentuk kunci, misalnya password, string rahasia, atau hash. Misal kita punya key yaitu mykey, nah si mykey ini gak bisa langsung dipakai untuk enkripsi AES karena masih berbentuk string mentah dan panjangnya belum sesuai syarat. Oleh karena itu kita derive menjadi key yang valid.

Jadi kira-kira gini alurnya:

  • kita punya key string biasa: mykey
  • tapi kita butuh kunci AES valid sepanjang 16-byte dengan type BYTE, bukan string

Maka prosesnya:

  • mykey -> dihash dulu (misal MD5)
  • hasil hash -> AES key
HCRYPTHASH hHash;
HCRYPTKEY hKey;

BYTE *secret = (BYTE *)"mykey";
DWORD secret_len = strlen((char *)secret);

// Buat hash (misal MD5)
CryptCreateHash(hProv, CALG_MD5, 0, 0, &hHash);
CryptHashData(hHash, secret, secret_len, 0);

// Derive jadi session key (misal AES)
CryptDeriveKey(hProv, CALG_AES_128, hHash, 0, &hKey);


KEYBLOB

Keyblob adalah struktur biner yang berisi informasi lengkap soal key yang mau kita import, seperti:

  • Jenis blob-nya (plaintext, public, private, dsb)
  • Algoritma yang dipakai (DES, AES, dll)
  • Ukuran key-nya
  • isi key itu sendiri

teknik keyblob digunakan untuk inject key ke Crypto API tanpa perlu hash atau derive apapun. Windows CryptoAPI dapat menerima keyblob via CryptImportKey() dan hasilnya langsung dapat HCRYPTKEY yang siap pakai untuk enkripsi/dekripsi.

Contoh struktur keyblob:

 
BYTE AesKeyBlob[] = {
  0x08,0x02,0x00,0x00, 0x0E,0x66,0x00,0x00, // Header (8 byte)
  0x10,0x00,0x00,0x00, // Key length 16 byte (4 byte)
  0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88, // key (sesuaikan dengan key length)
  0x99,0xaa,0xbb,0xcc,0xdd,0xee,0xff,0x00
};

Keyblob punya tiga yaitu header, key length, dan key

  • header

header memberi informasi tentang key dan jenis algoritmanya. Header memiliki ukuran 8 Bytes dan memiliki struktur sebagai berikut:

typedef struct _BLOBHEADER {
  BYTE  bType;     // Jenis blob: PLAINTEXT, PUBLICKEY, PRIVATEKEY, dsb.
  BYTE  bVersion;  // Versi (biasanya 0x02)
  WORD  reserved;  // Reserved, harus 0
  ALG_ID aiKeyAlg; // Algoritma yang dipakai (misal CALG_DES, CALG_AES_128)
} BLOBHEADER;
Penjelasan Field
Field Ukuran Contoh Value Keterangan
bType 1 byte 0x08 Tipe blob: PLAINTEXTKEYBLOB = 0x08, PUBLICKEYBLOB = 0x06, dll
bVersion 1 byte 0x02 Versi struktur. Biasanya 2 (0x02) untuk key blob modern
reserved 2 byte 0x0000 Harus 0
aiKeyAlg 4 byte 0x0000660E Algoritma yang digunakan. Contoh: CALG_DES, CALG_AES_128, dll
  • Key length

memberi informasi key length. Ukuran 4 bytes

// contoh 1: kalo mau bikin key dengan panjang 8 byte
BYTE AesKeyBlob[] = {
  0x08,0x02,0x00,0x00, 0x0E,0x66,0x00,0x00, // Header 
  0x08,0x00,0x00,0x00, // Key length 8 byte 
  0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88, // key (sesuaikan dengan key length)
};

// contoh 2: kalo mau bikin key dengan panjang 16 byte
BYTE AesKeyBlob[] = {
  0x08,0x02,0x00,0x00, 0x0E,0x66,0x00,0x00, // Header 
  0x10,0x00,0x00,0x00, // Key length 8 byte 
  0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88, // key (sesuaikan dengan key length)
  0x99,0xaa,0xbb,0xcc,0xdd,0xee,0xff,0x00 
};
  • Key

Isi bebas, sesuaikan panjangnya dengan key length


Contoh lengkap:

HCRYPTKEY hKey;
BYTE DesKeyBlob[] = {
        0x08,0x02,0x00,0x00, 0x0E,0x66,0x00,0x00, // Header (8 byte)
        0x10,0x00,0x00,0x00, // Key length 16 byte (4 byte)
        0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88, // key (sesuaikan dengan key length)
        0x99,0xaa,0xbb,0xcc,0xdd,0xee,0xff,0x00
      };
CryptImportKey(hProv, DesKeyBlob, sizeof(DesKeyBlob), 0, 0, &hKey);

Step 3: Enkripsi dan Dekripsi Data

Data yang sudah siap akan dienkripsi atau didekripsi dengan CryptEncrypt / CryptDecrypt

    // encrypt
    BYTE buffer[128] = "Hello, I'm encrypted malware!";
    DWORD buffer_len = strlen((char *)buffer);
    DWORD buffer_total = sizeof(buffer);
    CryptEncrypt(hKey, 0, TRUE, 0, buffer, &buffer_len, buffer_total);
    // Print Chiper text
    for (DWORD i = 0; i < buffer_len; ++i) {
        printf("%02X ", buffer[i]);
    }
    printf("\n");
    
    // Decrypt
    CryptDecrypt(hKey, 0, TRUE, 0, buffer, &buffer_len);
    printf("Decrypted: %s\n", buffer);

Step 4: Freeing Memory

Bersihkan Jejak

CryptDestroyKey(hKey);
// CryptDestroyHash(hHash); // jika pakai hash & derive
CryptReleaseContext(hProv, 0);

Code Lengkap

#include <windows.h>
#include <wincrypt.h>
#include <iostream>

#pragma comment (lib, "advapi32.lib") 

int main(){
    HCRYPTPROV hProv = NULL;
    CryptAcquireContext(&hProv, NULL, MS_ENH_RSA_AES_PROV, PROV_RSA_AES, CRYPT_VERIFYCONTEXT);

    // HCRYPTHASH hHash; // jika pakai hash & derive
    HCRYPTKEY hKey;

    // BYTE *secret = (BYTE *)"malwarekey";
    // DWORD secret_len = strlen((char *)secret);

    // // Buat hash (misal MD5)
    // CryptCreateHash(hProv, CALG_MD5, 0, 0, &hHash);
    // CryptHashData(hHash, secret, secret_len, 0);

    // // Derive jadi session key (misal AES)
    // CryptDeriveKey(hProv, CALG_AES_128, hHash, 0, &hKey);

    BYTE DesKeyBlob[] = {
        0x08,0x02,0x00,0x00, 0x0E,0x66,0x00,0x00, // Header (8 byte)
        0x10,0x00,0x00,0x00, // Key length 16 byte (4 byte)
        0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88, // key (sesuaikan dengan key length)
        0x99,0xaa,0xbb,0xcc,0xdd,0xee,0xff,0x00
      };
      
    CryptImportKey(hProv, DesKeyBlob, sizeof(DesKeyBlob), 0, 0, &hKey);

    BYTE buffer[128] = "Hello, I'm encrypted malware!";
    DWORD buffer_len = strlen((char *)buffer);
    DWORD buffer_total = sizeof(buffer);
    CryptEncrypt(hKey, 0, TRUE, 0, buffer, &buffer_len, buffer_total);
    
    // Print Chiper text
    for (DWORD i = 0; i < buffer_len; ++i) {
        printf("%02X ", buffer[i]);
    }
    printf("\n");
    

    CryptDecrypt(hKey, 0, TRUE, 0, buffer, &buffer_len);
    printf("Decrypted: %s\n", buffer);

    CryptDestroyKey(hKey);
    // CryptDestroyHash(hHash); // jika pakai hash & derive
    CryptReleaseContext(hProv, 0);

    return 0;
}

Compile & run

g++ .\main.cpp -o main -lcrypt32
main.exe

Catatan Akhir

Windows CryptoAPI sering disalahgunakan oleh malware untuk:

  • Menyimpan konfigurasi secara terenkripsi.
  • Menyembunyikan komunikasi command and control (C2).
  • Menghindari deteksi signature-based oleh antivirus.

Penting untuk threat researcher memahami cara kerja API ini agar bisa mendeteksi atau bahkan mendekripsi payload dari malware saat proses analisis forensik atau reverse engineering.