Windows CryptoAPI: Difference between revisions
| (3 intermediate revisions by the same user not shown) | |||
| Line 49: | Line 49: | ||
*Hash & Derive | *Hash & Derive | ||
*Memakai KEYBLOB | *Memakai KEYBLOB | ||
=== Hash & Derive === | === Hash & Derive === | ||
| Line 63: | Line 64: | ||
* ''mykey'' -> dihash dulu (misal MD5) | * ''mykey'' -> dihash dulu (misal MD5) | ||
* hasil hash -> AES key | * hasil hash -> AES key | ||
<syntaxhighlight lang=cpp> | <syntaxhighlight lang=cpp> | ||
| Line 79: | Line 79: | ||
CryptDeriveKey(hProv, CALG_AES_128, hHash, 0, &hKey); | CryptDeriveKey(hProv, CALG_AES_128, hHash, 0, &hKey); | ||
</syntaxhighlight> | </syntaxhighlight> | ||
=== KEYBLOB === | === KEYBLOB === | ||
| Line 159: | Line 160: | ||
}; | }; | ||
CryptImportKey(hProv, DesKeyBlob, sizeof(DesKeyBlob), 0, 0, &hKey); | CryptImportKey(hProv, DesKeyBlob, sizeof(DesKeyBlob), 0, 0, &hKey); | ||
</syntaxhighlight> | </syntaxhighlight> | ||
== Step 3: Enkripsi dan Dekripsi Data == | == Step 3: Enkripsi dan Dekripsi Data == | ||
| Line 243: | Line 244: | ||
return 0; | return 0; | ||
} | } | ||
</syntaxhighlight> | |||
Compile & run | |||
<syntaxhighlight lang="powershell"> | |||
g++ .\main.cpp -o main -lcrypt32 | |||
main.exe | |||
</syntaxhighlight> | </syntaxhighlight> | ||
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;
| 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.