樣本中的CryptAPI
0x00 CryptAPI的概述
一個CSP是實現加密操作的獨立模塊,要實現加密,至少需要一個CSP。每個CSP對CryptAPI的實現是不同的,使用的算法不同,有些包含了對硬件的支持
- CryptAcquireContext 獲得指定CSP的密鑰容器的句柄
- CryptReleaseContext釋放得到的句柄
在此前提下相關的函數如下
- CryptDeriveKey 從一個密碼中派生一個密鑰
- CryptDestoryKey 銷毀密鑰
- CryptDuplicateKey 制作一個密鑰和密鑰狀態的精確復制
- CryptGenKey 創建一個隨機密鑰
- CryptImportKey 把一個密鑰BLOB傳送到CSP中
用來加解密數據,需要指定一個密鑰,這個密鑰可以是由CryptGenKey、CryptDuplicateKey、CryptImportKey產生。
- CryptEncrypt 使用指定加密密鑰來加密一段信息
- CryptDecrypt 使用指定加密密鑰來解密一段密文
完整的解密過程如下
#include #include #pragma comment (lib, "advapi32")int main(){ HCRYPTPROV hCryptProv; HCRYPTHASH hCryptHash; HCRYPTKEY hCryptKey;
CryptAcquireContext(&hCryptProv, // CSP句柄的指針 NULL, // 密鑰容器名稱 MS_DEF_PROV, // CSP名稱(如果為NULL,就使用默認的CSP) PROV_RSA_FULL, // CSP類型 CRYPT_VERIFYCONTEXT); // 此選項指出應用程序不需要使用公鑰/私鑰對
CryptCreateHash(hCryptProv, // CSP句柄 CALG_MD5, // Hash算法的標識符 0, // 如果哈希算法是密鑰哈希,如HMAC或MAC算法,就用此密鑰句柄傳遞密鑰 0, // 保留,必須為0 &hCryptHash); // 哈希對象的句柄指針
static char szPassword[] = "FSD@#fds23"; // 加密密碼 DWORD dwLen = strlen(szPassword);
// 計算密碼的Hash值 CryptHashData(hCryptHash, (BYTE*)szPassword, dwLen, 0);
// 根據密碼的Hash值派生一個密鑰 CryptDeriveKey(hCryptProv, // CSP句柄 CALG_RC4, // 要產生密鑰的對稱加密算法 hCryptHash, // 哈希對象的句柄 0, // 密鑰類型 &hCryptKey); // 輸出密鑰句柄指針
// 待加密數據 static char szData[] = "important data";
DWORD dwLenIn = strlen(szData); DWORD dwLenOut = dwLenIn;
CryptEncrypt(hCryptKey, // 密鑰句柄 0, // 如果在加密的同時需要計算Hash值,傳入一個Hash對象句柄 TRUE, // 標識是否是最后一次加密操作 0, // 保留,必須為0 (BYTE*)szData, // 要被加密的數據 &dwLenOut, // [in/out] 傳入需要加密的數據長度,傳出已經加密的數據長度 dwLenIn); // 指出szData的Buffer長度
CryptDecrypt(hCryptKey, // 秘鑰句柄 0, // 如果在加密的同時需要計算Hash值,傳入一個Hash對象句柄 TRUE, // 標識是否是最后一個解密操作 0, // 保留,必須為0 (BYTE*)szData, // [in/out] 需要解密數據的地址 &dwLenOut); // [in/out] 傳入需要解密的數據長度,傳出已經解密的數據長度
// 清理工作 CryptDestroyKey(hCryptKey); CryptDestroyHash(hCryptHash); CryptReleaseContext(hCryptProv, NULL);
0x01 樣本中的使用情況
該樣本是某組織使用的最新的shellcode,該shellcode先獲取計算機名,然后通過計算機名來獲得IP地址,最后通過IP來計算hash和秘鑰并對下一階段的shellcode進行解密
具體過程如下
shellcode通過getComputerNamew和GetAddrInfow來獲取IP信息,通過遍歷addrinfoW鏈表來獲取IP(打碼部分為16進制IP地址),經過一次and操作后存入內存,待后續計算hash使用




計算并提取hash的過程如下
- 創建hash對象CryptCreateHash
- 通過上面的16進制IP計算hash CryptHashData
- 查詢hash長度CryptGetHashParam(HPHASHSIZE)
- 查詢hash值CryptGetHashParam(HPHASHVAL)

其他獲取CSP和destroy hash以及釋放CSP的常規操作就不多說了
然后用IP的hash值進行拼接,復制到內存中(棧中)組合成key blob.通過CryptImportKey將其導入CSP中,設置以初始向量模式進行解密,將舊shellcode中待解密的部分復制到新內存中,用CryptDecrypt解密





最后還會對解密后的下一階段shellcode再算一次hash

把這個算出的hash和舊shellcode中存的hash做比較,相同就創建線程去執行下一階段shellcode



0x02 參考
https://nixwang.com/2013/04/18/windows-cryptoapi/
初始向量模式 https://blog.csdn.net/Vieri32/article/details/48345023)https://blog.csdn.net/weixin45303938/article/details/109012292