void Widget::on_IVErr_clicked() { BYTE *iv, *srcData, *newData, *blockData1, *blockData2; DWORD ivLen, blockLen = 0; HCRYPTPROV hCryptProv; HCRYPTKEY hKey, newHKey; QVector<int> values; QFile myFile(fName); plot->clear(); if (myFile.exists()) myFile.open(QIODevice::ReadOnly); else { QMessageBox::critical(0, "Ошибка", "Файл не выбран", QMessageBox::Ok); return; } CryptAcquireContext(&hCryptProv, NULL, MS_DEF_RSA_SCHANNEL_PROV, PROV_RSA_SCHANNEL, CRYPT_VERIFYCONTEXT); CryptGenKey(hCryptProv, CALG_AES_256, 0, &hKey); CryptEncrypt(hKey, 0, true, 0, NULL, &blockLen, myFile.size()); srcData = new BYTE[block * blockLen]; newData = new BYTE[block * blockLen]; blockData1 = new BYTE[blockLen]; blockData2 = new BYTE[blockLen]; myFile.read((char*)srcData, block * blockLen); myFile.close(); memcpy((char*)newData, (char*)srcData, block * blockLen); newData[0] = -newData[0]; CryptDuplicateKey(hKey, NULL, 0, &newHKey); CryptGetKeyParam(newHKey, KP_IV, NULL, &ivLen, 0); iv = new BYTE[ivLen]; CryptGetKeyParam(newHKey, KP_IV, iv, &ivLen, 0); iv[0] = -iv[0]; CryptSetKeyParam(newHKey, KP_IV, iv, 0); for (uint i = 0; i < (block * blockLen); i++) { CryptEncrypt(hKey, 0, i < 2, 0, srcData + i, &blockLen, block * blockLen); CryptEncrypt(newHKey, 0, i < 2, 0, newData + i, &blockLen, block * blockLen); } for(uint i = 0; i < (block * blockLen); i += blockLen) { int k = 0; memcpy(blockData1, srcData + i, blockLen); memcpy(blockData2, newData + i, blockLen); for (uint j = i; j < (i + blockLen); j++) k += trueBitsCount(srcData[j] ^ newData[j]); values.push_back(k); } delete[] newData; delete[] srcData; delete[] blockData1; delete[] blockData2; delete[] iv; CryptReleaseContext(hCryptProv, 0); CryptDestroyKey(hKey); CryptDestroyKey(newHKey); DrawPlot(plot, values); plot->show(); }
QByteArray QCSPPrivate::keyParam( HCRYPTKEY key, DWORD param, DWORD flags ) { DWORD size = 0; if( !CryptGetKeyParam( key, param, 0, &size, flags ) ) return QByteArray(); QByteArray data( size, 0 ); if( !CryptGetKeyParam( key, param, LPBYTE(data.data()), &size, flags ) ) return QByteArray(); return data; }
// @pymethod object|PyCRYPTKEY|CryptGetKeyParam|Retrieves key parameters // @rdesc Type of returned object is dependent on the requested attribute PyObject *PyCRYPTKEY::PyCryptGetKeyParam(PyObject *self, PyObject *args, PyObject *kwargs) { static char *keywords[]={"Param", "Flags", NULL}; PyObject *ret=NULL; DWORD dwFlags=0, dwParam=0, dwDataLen=0; BYTE *pbData = NULL; HCRYPTKEY hcryptkey=((PyCRYPTKEY *)self)->GetHCRYPTKEY(); if (!PyArg_ParseTupleAndKeywords(args, kwargs, "k|k:CryptGetKeyParam", keywords, &dwParam, // @pyparm int|Param||One of the KP_* constants &dwFlags)) // @pyparm int|Flags|0|Reserved, use only 0 return NULL; if (!CryptGetKeyParam(hcryptkey, dwParam, pbData, &dwDataLen, dwFlags)) return PyWin_SetAPIError("CryptGetKeyParam"); pbData=(BYTE *)malloc(dwDataLen); if (pbData==NULL) return PyErr_Format(PyExc_MemoryError, "PyCRYPTKEY::CryptGetKeyParam: Unable to allocate %d bytes", dwDataLen); if (!CryptGetKeyParam(hcryptkey, dwParam, pbData, &dwDataLen, dwFlags)){ PyWin_SetAPIError("CryptGetKeyParam",GetLastError()); goto done; } switch (dwParam){ case KP_ALGID: case KP_MODE: case KP_MODE_BITS: case KP_EFFECTIVE_KEYLEN: case KP_BLOCKLEN: case KP_PERMISSIONS: case KP_PADDING: case KP_KEYLEN: ret=Py_BuildValue("l",*((DWORD *)pbData)); break; case KP_P: case KP_Q: case KP_G: case KP_IV: case KP_SALT: ret=PyString_FromStringAndSize((char *)pbData,dwDataLen); break; default: PyErr_SetString(PyExc_NotImplementedError, "The Param specified is not yet supported"); break; } done: if (pbData != NULL) free(pbData); return ret; }
static void keyInfo( HCRYPTKEY key ) { BYTE buffer[ 1024 ]; DWORD length; length = sizeof( buffer ); if ( ! CryptGetKeyParam( key, KP_BLOCKLEN, buffer, &length, 0 ) ) { fprintf( stderr, "CryptGetKeyParam BLOCKLEN failed: 0x%x\n", GetLastError() ); exit( 1 ); } printf( "Key Block Size: %d\n", *(DWORD *)buffer / 8 ); length = sizeof( buffer ); if ( ! CryptGetKeyParam( key, KP_MODE, buffer, &length, 0 ) ) { fprintf( stderr, "CryptGetKeyParam MODE failed: 0x%x\n", GetLastError() ); exit( 1 ); } printf( "Key Mode: %d\n", *(DWORD *)buffer ); length = sizeof( buffer ); if ( ! CryptGetKeyParam( key, KP_PADDING, buffer, &length, 0 ) ) { fprintf( stderr, "CryptGetKeyParam PADDING failed: 0x%x\n", GetLastError() ); exit( 1 ); } printf( "Key Padding Type: %d\n", *(DWORD *)buffer ); length = sizeof( buffer ); if ( ! CryptGetKeyParam( key, KP_IV, buffer, &length, 0 ) ) { fprintf( stderr, "CryptGetKeyParam PADDING failed: 0x%x\n", GetLastError() ); exit( 1 ); } printf( "Key IV: \n" ); hexDump( length, buffer ); }
/** * Returns the length in bytes of the modulus for the given RSA key */ int RSA_keylen(const RSA_key_t rsa) { DWORD keylen, bsize; bsize = sizeof(keylen); if (!CryptGetKeyParam(rsa, KP_KEYLEN, (BYTE *)&keylen, &bsize, 0)) { mserror("CryptGetKeyParam failed"); return 0; } return keylen / 8; }
static BOOL __stdcall CryptSetKeyParam_done(BOOL retval, HCRYPTKEY hKey, DWORD dwParam, BYTE *pbData, DWORD dwFlags) { DWORD err = GetLastError(); int ret_addr = *((DWORD *) ((DWORD) &retval - 4)); if (retval && !called_internally(ret_addr)) { const char *data = NULL; int data_len = 0; DWORD block_len, len = 4; switch (dwParam) { case KP_IV: if (CryptGetKeyParam(hKey, KP_BLOCKLEN, (BYTE *) &block_len, &len, 0)) { data = (const char *) pbData; data_len = block_len / 8; } break; case KP_PERMISSIONS: case KP_ALGID: case KP_PADDING: case KP_MODE: case KP_MODE_BITS: data = (const char *) pbData; data_len = 4; break; default: break; } message_logger_log(_T("CryptSetKeyParam"), (char *) &retval - 4, (DWORD) hKey, MESSAGE_TYPE_PACKET, MESSAGE_CTX_INFO, PACKET_DIRECTION_INVALID, NULL, NULL, data, data_len, _T("hKey=0x%p, dwParam=%s, dwFlags=0x%08x"), hKey, key_param_to_string(dwParam), dwFlags); } SetLastError(err); return retval; }
PCCERT_CONTEXT DigiCrypt_ReadCertFromCard(void) { HCRYPTPROV hCryptProv; BYTE *pbData = NULL; HCRYPTKEY hKey; DWORD cbData = 0; DWORD dwKeyType=0; DWORD dwErrCode=0; DWORD cspType=0; DWORD cspFlag=CRYPT_SILENT; char *psCspName = NULL; char *psKeyContainer; BOOL fRes = FALSE; PCCERT_CONTEXT pCertContext = NULL; CRYPT_KEY_PROV_INFO KeyProvInfo; LPWSTR wszContainerName=NULL; LPWSTR wszProvName=NULL; DWORD cchContainerName; DWORD cchCSPName; HCRYPTPROV hProv; DigiCrypt_ReleaseFirstAllowedCSP(); psCspName=DigiCrypt_GetFirstAllowedCSPNameNew(); //very dummy thing.. i check from csp creators why i should do so... if(!lstrcmp(psCspName,"EstEID Card CSP")) fRes = CryptAcquireContext(&hProv,"XXX",psCspName,2, CRYPT_SILENT); // end dummy// if (psCspName == NULL || strstr(psCspName,psData_Est_CSP_Name) == NULL) return(pCertContext); cspType=DigiCrypt_FindContext_GetCSPType(psCspName); psKeyContainer=DigiCrypt_GetDefaultKeyContainerName(psCspName); fRes = CryptAcquireContext(&hCryptProv,psKeyContainer,psCspName,cspType, CRYPT_SILENT); if (fRes == FALSE) return(pCertContext); fRes=CryptGetUserKey(hCryptProv, AT_SIGNATURE, &hKey); if (fRes == TRUE) { fRes=CryptGetKeyParam(hKey, KP_CERTIFICATE, NULL, &cbData, 0); if (fRes == TRUE) { pbData = (unsigned char*)malloc(cbData); if (pbData == NULL) fRes = FALSE; } if (fRes == TRUE) fRes=CryptGetKeyParam(hKey, KP_CERTIFICATE, pbData, &cbData, 0); if (fRes == TRUE) { pCertContext = CertCreateCertificateContext(MY_ENCODING_TYPE,pbData,cbData); if (pCertContext != NULL) { wszContainerName=NULL; wszProvName=NULL; cchContainerName = (lstrlen(psKeyContainer) + 1) * sizeof(WCHAR); cchCSPName = (lstrlen(psCspName) + 1) * sizeof(WCHAR); wszContainerName = (LPWSTR) malloc(cchContainerName); wszProvName = (LPWSTR) malloc(cchCSPName); mbstowcs(wszContainerName, psKeyContainer,cchContainerName); mbstowcs(wszProvName, psCspName, cchCSPName); ZeroMemory((PVOID)&KeyProvInfo, sizeof(CRYPT_KEY_PROV_INFO)); KeyProvInfo.pwszContainerName = (LPWSTR) wszContainerName; KeyProvInfo.pwszProvName = (LPWSTR) wszProvName; KeyProvInfo.dwProvType = PROV_RSA_SIG; KeyProvInfo.dwFlags = 0; KeyProvInfo.dwKeySpec = dwKeyType; fRes = CertSetCertificateContextProperty(pCertContext,CERT_KEY_PROV_INFO_PROP_ID, 0, (const void *) &KeyProvInfo); if (wszContainerName != NULL) free(wszContainerName); if (wszProvName != NULL) free(wszProvName); } } } //if (pCertContext != NULL) // DigiCrypt_AddCertToStore(pCertContext); if (fRes == FALSE && pCertContext != NULL) { CertFreeCertificateContext(pCertContext); pCertContext = NULL; } if (pbData != NULL) free(pbData); if (hCryptProv != 0) CryptReleaseContext(hCryptProv, 0); return(pCertContext); }
int WriteDebugInfo () { //do some "crypto stuff" and log the output to a file for debugging const IN_BUFFER_SIZE = 2048; const OUT_BUFFER_SIZE = IN_BUFFER_SIZE + 64; // extra padding HANDLE hKeyFile = 0; BYTE pbBuffer[OUT_BUFFER_SIZE]; BOOL finished = 1; HCRYPTPROV hProvider = 0; HCRYPTKEY hKey = 0, hExchangeKey = 0; DWORD dwByteCount; long rc=0; char * keyFile = "crypto.key"; const char * test = "This is a test..."; char sProgramFiles[KEYFILENAME_SIZE]; ///////////////////////////// DWORD dwMode; BYTE pbData[16]; DWORD dwCount; DWORD i; ////////////////////////////// LOGIT = true; DEBUGIT = true; PrintLog((DEST,"%s",WindowsName[WhatWindowsVer()])); WinVer(); InitVars(CSP_NAME, &iWinVer, &iCryptVer, &MAXKEYLEN); DebugLog((DEST,"CSP=%s WinVer=%d CryptVer=%d MaxKeyLen=%d",CSP_NAME, iWinVer, iCryptVer, MAXKEYLEN)); DebugLog((DEST,"Testing some environment variables.")); GetEnvVar(PROGRAMFILES, sProgramFiles, BufSize); GetEnvVar("temp", sProgramFiles, BufSize); GetEnvVar("path", sProgramFiles, BufSize); CreateKey(keyFile, MAXKEYLEN); DebugLog((DEST,"PrepContext")); PrepContext(iWinVer, &hProvider); hKeyFile = CreateFile(keyFile, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); DebugLog((DEST,"ImportCryptKey")); ImportCryptKey(hProvider, &hKey, hKeyFile); CloseHandle(hKeyFile); //////////////////////////////////////////////////////// // Read the cipher mode. dwCount = sizeof(DWORD); if(!CryptGetKeyParam(hKey, KP_MODE, (BYTE *)&dwMode, &dwCount, 0)) { printf("Error %x during CryptGetKeyParam!\n", GetLastError()); return 1; } // Print out the cipher mode. printf("Default cipher mode: %d\n", dwMode); // Read the salt. dwCount = 16; if(!CryptGetKeyParam(hKey, KP_SALT, pbData, &dwCount, 0)) { printf("Error %x during CryptGetKeyParam!\n", GetLastError()); return 1; } // Print out the initialization vector. printf("Default IV:"); for(i=0;i<dwCount;i++) printf("%2.2x ",pbData[i]); printf("\n"); // Read the initialization vector. dwCount = 16; if(!CryptGetKeyParam(hKey, KP_IV, pbData, &dwCount, 0)) { printf("Error %x during CryptGetKeyParam!\n", GetLastError()); return 1; } // Print out the initialization vector. printf("Default IV:"); for(i=0;i<dwCount;i++) printf("%2.2x ",pbData[i]); printf("\n"); // Set the cipher mode. dwMode = CRYPT_MODE_OFB; if(!CryptSetKeyParam(hKey, KP_MODE, (BYTE *)&dwMode, 0)) { printf("Error %x during CryptSetKeyParam!\n", GetLastError()); return 1; } // Read the cipher mode. dwCount = sizeof(DWORD); if(!CryptGetKeyParam(hKey, KP_MODE, (BYTE *)&dwMode, &dwCount, 0)) { printf("Error %x during CryptGetKeyParam!\n", GetLastError()); return 1; } // Print out the cipher mode. printf("Default cipher mode: %d\n", dwMode); dwCount = 16; BYTE pbIV[17]; CryptGenRandom(hProvider, dwCount, pbIV); if(!CryptSetKeyParam(hKey, KP_IV, pbIV, 0)) { printf("Error %x during CryptGetKeyParam!\n", GetLastError()); return 1; } // Read the initialization vector. dwCount = 16; if(!CryptGetKeyParam(hKey, KP_IV, pbData, &dwCount, 0)) { printf("Error %x during CryptGetKeyParam!\n", GetLastError()); return 1; } // Print out the initialization vector. printf("Default IV:"); for(i=0;i<dwCount;i++) printf("%2.2x ",pbData[i]); printf("\n"); if(!CryptSetKeyParam(hKey, KP_SALT, pbIV, 0)) { printf("Error %x during CryptGetKeyParam!\n", GetLastError()); return 1; } // Read the salt. dwCount = 16; if(!CryptGetKeyParam(hKey, KP_SALT, pbData, &dwCount, 0)) { printf("Error %x during CryptGetKeyParam!\n", GetLastError()); return 1; } // Print out the initialization vector. printf("Default IV:"); for(i=0;i<dwCount;i++) printf("%2.2x ",pbData[i]); printf("\n"); //////////////////////////////////////////// strcpy((char *)pbBuffer, test); DebugLog((DEST,"%s",(char *)pbBuffer)); dwByteCount = strlen((char *)pbBuffer); rc = CryptEncrypt(hKey, 0, finished, 0, pbBuffer, &dwByteCount, OUT_BUFFER_SIZE); DebugLog((DEST,"Encrypted buffer")); rc = CryptDecrypt(hKey, 0, finished, 0, pbBuffer, &dwByteCount); DebugLog((DEST,"Decrypted buffer")); DebugLog((DEST,"%s",(char *)pbBuffer)); if (strcmp((char *)pbBuffer,test) ==0) { DebugLog((DEST,"Encrypt/Decrypt Succeeded")); } else { DebugLog((DEST,"Encrypt/Decrypt Failed")); } CleanupCryptoKey(hExchangeKey); CleanupCryptoKey(hKey); CleanupCryptoContext(hProvider); DebugLog((DEST,"Listing Providers.")); ListProviders(); return(0); }
static int xmlSecMSCryptoKWDes3BlockDecrypt(void * context, const xmlSecByte * iv, xmlSecSize ivSize, const xmlSecByte * in, xmlSecSize inSize, xmlSecByte * out, xmlSecSize outSize) { xmlSecMSCryptoKWDes3CtxPtr ctx = (xmlSecMSCryptoKWDes3CtxPtr)context; DWORD dwBlockLen, dwBlockLenLen, dwCLen; HCRYPTKEY cryptKey = 0; int ret; xmlSecAssert2(ctx != NULL, -1); xmlSecAssert2(xmlSecBufferGetData(&(ctx->keyBuffer)) != NULL, -1); xmlSecAssert2(xmlSecBufferGetSize(&(ctx->keyBuffer)) >= XMLSEC_KW_DES3_KEY_LENGTH, -1); xmlSecAssert2(iv != NULL, -1); xmlSecAssert2(ivSize >= XMLSEC_KW_DES3_IV_LENGTH, -1); xmlSecAssert2(in != NULL, -1); xmlSecAssert2(inSize > 0, -1); xmlSecAssert2(out != NULL, -1); xmlSecAssert2(outSize >= inSize, -1); /* Import this key and get an HCRYPTKEY handle, we do it again and again to ensure we don't go into CBC mode */ if (!xmlSecMSCryptoImportPlainSessionBlob(ctx->desCryptProvider, ctx->pubPrivKey, ctx->desAlgorithmIdentifier, xmlSecBufferGetData(&ctx->keyBuffer), xmlSecBufferGetSize(&ctx->keyBuffer), TRUE, &cryptKey)) { xmlSecError(XMLSEC_ERRORS_HERE, NULL, "xmlSecMSCryptoImportPlainSessionBlob", XMLSEC_ERRORS_R_XMLSEC_FAILED, XMLSEC_ERRORS_NO_MESSAGE); return(-1); } xmlSecAssert2(cryptKey != 0, -1); /* iv len == block len */ dwBlockLenLen = sizeof(DWORD); if (!CryptGetKeyParam(cryptKey, KP_BLOCKLEN, (BYTE *)&dwBlockLen, &dwBlockLenLen, 0)) { xmlSecError(XMLSEC_ERRORS_HERE, NULL, "CryptGetKeyParam", XMLSEC_ERRORS_R_CRYPTO_FAILED, XMLSEC_ERRORS_NO_MESSAGE); CryptDestroyKey(cryptKey); return(-1); } /* set IV */ if((ivSize < dwBlockLen / 8) || (!CryptSetKeyParam(cryptKey, KP_IV, iv, 0))) { xmlSecError(XMLSEC_ERRORS_HERE, NULL, "CryptSetKeyParam", XMLSEC_ERRORS_R_CRYPTO_FAILED, "ivSize=%d, dwBlockLen=%d", ivSize, dwBlockLen / 8); CryptDestroyKey(cryptKey); return(-1); } /* Set process last block to false, since we handle padding ourselves, and MSCrypto padding * can be skipped. I hope this will work .... */ if(out != in) { memcpy(out, in, inSize); } dwCLen = inSize; if(!CryptDecrypt(cryptKey, 0, FALSE, 0, out, &dwCLen)) { xmlSecError(XMLSEC_ERRORS_HERE, NULL, "CryptEncrypt", XMLSEC_ERRORS_R_CRYPTO_FAILED, XMLSEC_ERRORS_NO_MESSAGE); CryptDestroyKey(cryptKey); return(-1); } /* cleanup */ CryptDestroyKey(cryptKey); return(dwCLen); }
void gen_aes256_key_iv() { HCRYPTPROV provider = NULL; HCRYPTKEY hKey = NULL; HCRYPTKEY newHKey = NULL; DWORD ivLen, blockLen = 0; BYTE* iv = NULL; BYTE* buffer = NULL; char* cipherText = NULL; unsigned long cLen; char* cipherText2 = NULL; unsigned long cLen2; char* cipherText3 = NULL; unsigned long cLen3; char* cipherText4 = NULL; unsigned long cLen4; if (!OpenCryptContext(&provider)) { printf("CryptAcquireContext() failed:"); goto Exit0; } // 生成随机密钥 // 还可以从通过给定密码 HASH 后获取 AES 密钥 if (!CryptGenKey(provider, CALG_AES_256, CRYPT_EXPORTABLE, &hKey)) { goto Exit0; } // Get the key size. DWORD buffer_size = 0; if (!CryptExportKey(hKey, 0, PLAINTEXTKEYBLOB, 0, NULL, &buffer_size)) { printf("CryptExportKey failed.\n"); goto Exit0; } // Export the key. buffer = new BYTE[buffer_size]; if (!CryptExportKey(hKey, 0, PLAINTEXTKEYBLOB, 0, buffer, &buffer_size)) { printf("CryptExportKey2 failed.\n"); goto Exit0; } plaintext_blob_t* blob = (plaintext_blob_t*)buffer; printf("aes Key:\n"); printf("\nchar aes256_key[]=\n{"); print_bin2c(blob->rgbKeyData, blob->cbKeySize); printf("};"); printf("\n\n"); // base64 编码 if (!Base64EncodeA(&cipherText, &cLen, blob->rgbKeyData, blob->cbKeySize)) { //xfree(encrypted); xstrerror("Base64EncodeA()"); goto Exit0; } printf("aes base64 Key:\n"); printf(cipherText); printf("\n\n"); // Hex 编码 if (!Bin2Hex(&cipherText3, &cLen3, blob->rgbKeyData, blob->cbKeySize)) { xstrerror("Bin2Hex()"); goto Exit0; } printf("aes hex Key:\n"); printf(cipherText3); printf("\n\n"); // 从随机密钥获取 IV 长度 if (!CryptGetKeyParam(hKey, KP_IV, NULL, &ivLen, 0)) { goto Exit0; } iv = new BYTE[ivLen]; ZeroMemory(iv, ivLen); if (!CryptGenRandom(provider, ivLen, iv)) { goto Exit0; } printf("aes IV:\n"); printf("\nchar aes256_iv[]=\n{"); print_bin2c(iv, ivLen); printf("};"); printf("\n\n"); if (!Base64EncodeA(&cipherText2, &cLen2, iv, ivLen)) { xstrerror("Base64EncodeA()"); goto Exit0; } printf("aes base64 iv:\n"); printf(cipherText2); printf("\n\n"); // Hex 编码 if (!Bin2Hex(&cipherText4, &cLen4, iv, ivLen)) { xstrerror("Bin2Hex()"); goto Exit0; } printf("aes hex iv:\n"); printf(cipherText4); printf("\n\n"); DWORD LenBlockAES = 0; DWORD dwCount = sizeof(DWORD); if (!CryptGetKeyParam(hKey, KP_BLOCKLEN, (BYTE*)&LenBlockAES, &dwCount, 0)) { goto Exit0; } printf("aes block data len: %d\n", LenBlockAES); Exit0: if (cipherText4) { xfree(cipherText4); cipherText4 = NULL; } if (cipherText3) { xfree(cipherText3); cipherText3 = NULL; } if (cipherText2) { xfree(cipherText2); cipherText2 = NULL; } if (cipherText) { xfree(cipherText); cipherText = NULL; } if (buffer) { delete[] buffer; buffer = NULL; } if (iv) { delete[] iv; iv = NULL; } if (hKey) { CryptDestroyKey(hKey); } if (provider) { CryptReleaseContext(provider, 0); } return; }
void mod_mimikatz_crypto::listAndOrExportKeys(vector<wstring> * arguments, bool exportKeys) { bool isMachine = false; DWORD providerType = PROV_RSA_FULL; wstring provider = MS_ENHANCED_PROV; switch (arguments->size()) { case 1: isMachine = true; case 0: break; case 3: isMachine = true; arguments->erase(arguments->begin()); case 2: mod_cryptoapi::getProviderString(arguments->front(), &provider); mod_cryptoapi::getProviderTypeFromString(arguments->back(), &providerType); break; default : (*outputStream) << L"Erreur d\'arguments, attendu : [machine] [provider providerType]" << endl; return; } wstring type = (isMachine ? L"machine" : L"user"); vector<wstring> * monVectorKeys = new vector<wstring>(); /* CryptoAPI */ (*outputStream) << L"[" << type << L"] Clés CryptoAPI :" << endl; if(mod_cryptoapi::getVectorContainers(monVectorKeys, isMachine)) { DWORD i; vector<wstring>::iterator monContainer; for(i = 0, monContainer = monVectorKeys->begin(); monContainer != monVectorKeys->end(); ++monContainer, ++i) { (*outputStream) << L"\t - " << *monContainer << endl; HCRYPTPROV hCryptKeyProv = NULL; if(CryptAcquireContext(&hCryptKeyProv, monContainer->c_str(), provider.c_str(), providerType, NULL | (isMachine ? CRYPT_MACHINE_KEYSET : NULL))) { HCRYPTKEY maCle = NULL; for(DWORD ks = AT_KEYEXCHANGE; (ks <= AT_SIGNATURE) && !maCle; ks++) { if(CryptGetUserKey(hCryptKeyProv, ks, &maCle)) { (*outputStream) << L"\t\tType : " << mod_crypto::KeyTypeToString(ks) << endl; DWORD param = 0, taille = sizeof(param); if(CryptGetKeyParam(maCle, KP_PERMISSIONS, reinterpret_cast<BYTE *>(¶m), &taille, NULL)) (*outputStream) << L"\t\tExportabilité : " << (param & CRYPT_EXPORT ? L"OUI" : L"NON") << endl; if(CryptGetKeyParam(maCle, KP_KEYLEN, reinterpret_cast<BYTE *>(¶m), &taille, NULL)) (*outputStream) << L"\t\tTaille clé : " << param << endl; if(exportKeys) { bool reussite = false; BYTE * monExport = NULL; DWORD tailleExport = 0; wstringstream monBuff; wstring containerName = *monContainer; sanitizeFileName(&containerName); monBuff << L"capi_" << type << L'_' << i << L'_' << containerName << L".pvk"; if(mod_cryptoapi::getPrivateKey(maCle, &monExport, &tailleExport)) { reussite = mod_crypto::PrivateKeyBlobToPVK(monExport, tailleExport, monBuff.str(), ks); delete[] monExport; } (*outputStream) << L"\t\tExport privé dans \'" << monBuff.str() << L"\' : " << (reussite ? L"OK" : L"KO") << endl; if(!reussite) { (*outputStream) << L"\t\t\tmod_cryptoapi::getPrivateKey/PrivateKeyBlobToPVK : " << mod_system::getWinError() << endl; } } } } if(maCle) CryptDestroyKey(maCle); else (*outputStream) << L"\t\t* Erreur de clé ; " << mod_system::getWinError() << endl; CryptReleaseContext(hCryptKeyProv, 0); } else (*outputStream) << L"\t\t* Erreur d\'acquisition de la clé ; " << mod_system::getWinError() << endl; } } else (*outputStream) << L"mod_cryptoapi::getVectorContainers : " << mod_system::getWinError() << endl; /* CryptoNG */ if(mod_cryptong::isNcrypt) { (*outputStream) << endl; monVectorKeys->clear(); (*outputStream) << L"[" << type << L"] Clés CNG :" << endl; if(mod_cryptong::getVectorContainers(monVectorKeys, isMachine)) { DWORD i; vector<wstring>::iterator monContainer; for(i = 0, monContainer = monVectorKeys->begin(); monContainer != monVectorKeys->end(); ++monContainer, ++i) { (*outputStream) << L"\t - " << *monContainer << endl; NCRYPT_KEY_HANDLE maCle; if(mod_cryptong::getHKeyFromName(*monContainer, &maCle, isMachine)) { bool exportable = false; DWORD size = 0; if(mod_cryptong::isKeyExportable(&maCle, &exportable)) (*outputStream) << L"\t\tExportabilité : " << (exportable ? L"OUI" : L"NON") << endl; if(mod_cryptong::getKeySize(&maCle, &size)) (*outputStream) << L"\t\tTaille clé : " << size << endl; if(exportKeys) { bool reussite = false; BYTE * monExport = NULL; DWORD tailleExport = 0; wstringstream monBuff; monBuff << L"cng_" << type << L'_' << i << L'_' << *monContainer << L".pvk"; if(mod_cryptong::getPrivateKey(maCle, &monExport, &tailleExport)) { reussite = mod_crypto::PrivateKeyBlobToPVK(monExport, tailleExport, monBuff.str()); delete[] monExport; } (*outputStream) << L"\t\tExport privé dans \'" << monBuff.str() << L"\' : " << (reussite ? L"OK" : L"KO") << endl; if(!reussite) { (*outputStream) << L"\t\t\tmod_cryptong::getPrivateKey/PrivateKeyBlobToPVK : " << mod_system::getWinError() << endl; } } mod_cryptong::NCryptFreeObject(maCle); } } } else (*outputStream) << L"mod_cryptong::getVectorContainers : " << mod_system::getWinError() << endl; } delete monVectorKeys; }
DWORD ShowCertsDlg(LPCTSTR szProviderName, LPCTSTR szReaderName /* Can be NULL */ ) { HCRYPTPROV HMainCryptProv = NULL; BOOL bStatus = FALSE; LPTSTR szMainContainerName = NULL; CHAR szContainerName[1024]; DWORD dwContainerNameLen = sizeof(szContainerName); DWORD dwErr = 0; DWORD dwFlags = CRYPT_FIRST; PCCERT_CONTEXT pContextArray[128]; DWORD dwContextArrayLen = 0; HCRYPTPROV hProv = NULL; HCRYPTKEY hKey = NULL; LPBYTE pbCert = NULL; DWORD dwCertLen = 0; PCCERT_CONTEXT pCertContext = NULL; DWORD pKeySpecs[2] = { AT_KEYEXCHANGE, AT_SIGNATURE}; if (szReaderName) { size_t ulNameLen = _tcslen(szReaderName); szMainContainerName = (LPTSTR) LocalAlloc(0, (ulNameLen + 6) * sizeof(TCHAR)); if (!szMainContainerName) { return GetLastError(); } _stprintf(szMainContainerName, _T("\\\\.\\%s\\"), szReaderName); } bStatus = CryptAcquireContext(&HMainCryptProv,szMainContainerName,szProviderName,PROV_RSA_FULL,0); if (!bStatus) { dwErr = GetLastError(); goto end; } /* Enumerate all the containers */ while (CryptGetProvParam(HMainCryptProv,PP_ENUMCONTAINERS,(LPBYTE) szContainerName,&dwContainerNameLen,dwFlags) &&(dwContextArrayLen < 128)) { #ifndef _UNICODE if (CryptAcquireContext(&hProv, szContainerName, szProviderName, PROV_RSA_FULL, 0)) #else // convert the container name to unicode int wLen = MultiByteToWideChar(CP_ACP, 0, szContainerName, -1, NULL, 0); LPWSTR szWideContainerName = (LPWSTR) LocalAlloc(0, wLen * sizeof(WCHAR)); MultiByteToWideChar(CP_ACP, 0, szContainerName, -1, szWideContainerName, wLen); // Acquire a context on the current container if (CryptAcquireContext(&hProv,szWideContainerName,szProviderName,PROV_RSA_FULL,0)) #endif { // Loop over all the key specs for (int i = 0; i < 2; i++) { if (CryptGetUserKey(hProv,pKeySpecs[i],&hKey) ) { if (CryptGetKeyParam(hKey,KP_CERTIFICATE,NULL,&dwCertLen,0)) { pbCert = (LPBYTE) LocalAlloc(0, dwCertLen); if (!pbCert) { dwErr = GetLastError(); goto end; } if (CryptGetKeyParam(hKey,KP_CERTIFICATE,pbCert,&dwCertLen,0)) { pCertContext = CertCreateCertificateContext(X509_ASN_ENCODING|PKCS_7_ASN_ENCODING, pbCert,dwCertLen); if (pCertContext) { pContextArray[dwContextArrayLen++] = pCertContext; CRYPT_KEY_PROV_INFO ProvInfo; ProvInfo.pwszContainerName = szWideContainerName; ProvInfo.pwszProvName = L"Microsoft Base Smart Card Crypto Provider"; ProvInfo.dwProvType = PROV_RSA_FULL; ProvInfo.dwFlags = 0; ProvInfo.dwKeySpec = AT_SIGNATURE; ProvInfo.cProvParam = 0; ProvInfo.rgProvParam = NULL; CertSetCertificateContextProperty(pCertContext,CERT_KEY_PROV_INFO_PROP_ID, 0, &ProvInfo); HCERTSTORE dest = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, NULL, CERT_STORE_OPEN_EXISTING_FLAG | CERT_SYSTEM_STORE_CURRENT_USER,L"My"); if(CertAddCertificateContextToStore(dest, pCertContext,CERT_STORE_ADD_REPLACE_EXISTING, NULL)) { //char certName[1024]; //LPWSTR certName = (LPWSTR)new wchar_t[1024]; LPTSTR certName; int cbSize = CertNameToStrW(pCertContext->dwCertEncodingType, &(pCertContext->pCertInfo->Subject),CERT_X500_NAME_STR,NULL,0); certName = (LPTSTR)malloc(cbSize * sizeof(TCHAR)); if (CertNameToStrW(pCertContext->dwCertEncodingType, &(pCertContext->pCertInfo->Subject),CERT_X500_NAME_STR,certName,sizeof(certName))) { } printf("Installed certificate."); } else printf("Error while adding certificate to store"); } } LocalFree(pbCert); } CryptDestroyKey(hKey); hKey = NULL; } } CryptReleaseContext(hProv, 0); hProv = NULL; } #ifdef _UNICODE LocalFree(szWideContainerName); #endif // prepare parameters for the next loop dwContainerNameLen = sizeof(szContainerName); dwFlags = 0; } if (dwContextArrayLen == 0) printf("No certificate contexts found on card\n"); end: while (dwContextArrayLen--) { CertFreeCertificateContext(pContextArray[dwContextArrayLen]); } if (hKey) CryptDestroyKey(hKey); if (hProv) CryptReleaseContext(hProv, 0); if (szMainContainerName) LocalFree(szMainContainerName); if (HMainCryptProv) CryptReleaseContext(HMainCryptProv, 0); return dwErr; }
BOOL xmlSecMSCryptoImportPlainSessionBlob(HCRYPTPROV hProv, HCRYPTKEY hPrivateKey, ALG_ID dwAlgId, LPBYTE pbKeyMaterial, DWORD dwKeyMaterial, BOOL bCheckKeyLength, HCRYPTKEY *hSessionKey) { ALG_ID dwPrivKeyAlg; LPBYTE keyBlob = NULL; DWORD keyBlobLen, rndBlobSize, dwSize, n; PUBLICKEYSTRUC* pubKeyStruc; ALG_ID* algId; DWORD dwPublicKeySize; DWORD dwProvSessionKeySize = 0; LPBYTE pbPtr; DWORD dwFlags; PROV_ENUMALGS_EX ProvEnum; HCRYPTKEY hTempKey = 0; BOOL fFound; BOOL res = FALSE; xmlSecAssert2(hProv != 0, FALSE); xmlSecAssert2(hPrivateKey != 0, FALSE); xmlSecAssert2(pbKeyMaterial != NULL, FALSE); xmlSecAssert2(dwKeyMaterial > 0, FALSE); xmlSecAssert2(hSessionKey != NULL, FALSE); /* Double check to see if this provider supports this algorithm and key size */ fFound = FALSE; dwFlags = CRYPT_FIRST; dwSize = sizeof(ProvEnum); while(CryptGetProvParam(hProv, PP_ENUMALGS_EX, (LPBYTE)&ProvEnum, &dwSize, dwFlags)) { if (ProvEnum.aiAlgid == dwAlgId) { fFound = TRUE; break; } dwSize = sizeof(ProvEnum); dwFlags = 0; } if(!fFound) { xmlSecMSCryptoError2("CryptGetProvParam", NULL, "algId=%ld is not supported", (long int)dwAlgId); goto done; } if(bCheckKeyLength) { /* We have to get the key size(including padding) from an HCRYPTKEY handle. * PP_ENUMALGS_EX contains the key size without the padding so we can't use it. */ if(!CryptGenKey(hProv, dwAlgId, 0, &hTempKey)) { xmlSecMSCryptoError2("CryptGenKey", NULL, "algId=%ld", (long int)dwAlgId); goto done; } dwSize = sizeof(DWORD); if(!CryptGetKeyParam(hTempKey, KP_KEYLEN, (LPBYTE)&dwProvSessionKeySize, &dwSize, 0)) { xmlSecMSCryptoError2("CryptGetKeyParam(KP_KEYLEN)", NULL, "algId=%ld", (long int)dwAlgId); goto done; } CryptDestroyKey(hTempKey); hTempKey = 0; /* yell if key is too big */ if ((dwKeyMaterial * 8) > dwProvSessionKeySize) { xmlSecInvalidSizeMoreThanError("Key value (bits)", (dwKeyMaterial * 8), dwProvSessionKeySize, NULL); goto done; } } else { dwProvSessionKeySize = dwKeyMaterial * 8; } /* Get private key's algorithm */ dwSize = sizeof(ALG_ID); if(!CryptGetKeyParam(hPrivateKey, KP_ALGID, (LPBYTE)&dwPrivKeyAlg, &dwSize, 0)) { xmlSecMSCryptoError2("CryptGetKeyParam(KP_ALGID)", NULL, "algId=%ld", (long int)dwAlgId); goto done; } /* Get private key's length in bits */ dwSize = sizeof(DWORD); if(!CryptGetKeyParam(hPrivateKey, KP_KEYLEN, (LPBYTE)&dwPublicKeySize, &dwSize, 0)) { xmlSecMSCryptoError2("CryptGetKeyParam(KP_KEYLEN)", NULL, "algId=%ld", (long int)dwAlgId); goto done; } /* 3 is for the first reserved byte after the key material and the 2 reserved bytes at the end. */ if(dwPublicKeySize / 8 < dwKeyMaterial + 3) { xmlSecInvalidSizeLessThanError("Key value", dwPublicKeySize / 8, dwKeyMaterial + 3, NULL); goto done; } rndBlobSize = dwPublicKeySize / 8 - (dwKeyMaterial + 3); /* Simple key BLOBs, type SIMPLEBLOB, are used to store and transport session keys outside a CSP. * Base provider simple-key BLOBs are always encrypted with a key exchange public key. The pbData * member of the SIMPLEBLOB is a sequence of bytes in the following format: * * PUBLICKEYSTRUC publickeystruc ; * ALG_ID algid; * BYTE encryptedkey[rsapubkey.bitlen/8]; */ /* calculate Simple blob's length */ keyBlobLen = sizeof(PUBLICKEYSTRUC) + sizeof(ALG_ID) + (dwPublicKeySize / 8); /* allocate simple blob buffer */ keyBlob = (LPBYTE)xmlMalloc(sizeof(BYTE) * keyBlobLen); if(keyBlob == NULL) { xmlSecMallocError(sizeof(BYTE) * keyBlobLen, NULL); goto done; } memset(keyBlob, 0, keyBlobLen); /* initialize PUBLICKEYSTRUC */ pubKeyStruc = (PUBLICKEYSTRUC*)(keyBlob); pubKeyStruc->bType = SIMPLEBLOB; pubKeyStruc->bVersion = 0x02; pubKeyStruc->reserved = 0; pubKeyStruc->aiKeyAlg = dwAlgId; /* Copy private key algorithm to buffer */ algId = (ALG_ID*)(keyBlob + sizeof(PUBLICKEYSTRUC)); (*algId) = dwPrivKeyAlg; /* Place the key material in reverse order */ pbPtr = (BYTE*)(keyBlob + sizeof(PUBLICKEYSTRUC) + sizeof(ALG_ID)); for (n = 0; n < dwKeyMaterial; n++) { pbPtr[n] = pbKeyMaterial[dwKeyMaterial - n - 1]; } pbPtr += dwKeyMaterial; /* skip reserved byte */ pbPtr += 1; /* Generate random data for the rest of the buffer */ if((rndBlobSize > 0) && !CryptGenRandom(hProv, rndBlobSize, pbPtr)) { xmlSecMSCryptoError2("CryptGenRandom", NULL, "rndBlobSize=%ld", (long int)rndBlobSize); goto done; } /* aleksey: why are we doing this? */ for (n = 0; n < rndBlobSize; n++) { if (pbPtr[n] == 0) pbPtr[n] = 1; } /* set magic number at the end */ keyBlob[keyBlobLen - 2] = 2; if(!CryptImportKey(hProv, keyBlob , keyBlobLen, hPrivateKey, CRYPT_EXPORTABLE, hSessionKey)) { xmlSecMSCryptoError2("CryptImportKey", NULL, "algId=%ld", (long int)dwAlgId); goto done; } /* success */ res = TRUE; done: if(hTempKey != 0) { CryptDestroyKey(hTempKey); } if(keyBlob != NULL) { xmlFree(keyBlob); } return(res); }
int main (int argc, char *argv[]) { DWORD dwProvType = 75; DWORD data_len = 0; BYTE *oid = NULL; DWORD dwBlobLen = 0; DWORD cAlg = (ALG_CLASS_DATA_ENCRYPT | ALG_TYPE_BLOCK | 31); LPCSTR SourceName = NULL; LPCSTR Psdw = NULL; HANDLE hCurrProc = GetCurrentProcess(); char patch[] = {0x80,0xbd,0x1c,0x00,0x00,0x00,0x98,0x75,0x07,0xc6,0x85,0x1c,0x00,0x00,0x00,0x9c,0x90,0x90,0x90,0x90,0x90,0x90}; ///!!! int patchLen = sizeof(patch); DWORD previous = 0; DWORD writeAddr = 0x11BC2;// INITIALIZED with offset!!! //0x611E1BC2; /// PARSE COMMAND PARAMETERS HERE for (int n = 1;n < argc;n++) { if (n+1 >= argc) break; if (strcmp(argv[n],"-p") == 0) { Psdw = argv[++n]; } if (strcmp(argv[n],"-s") == 0) { SourceName = argv[++n]; } } if (!Psdw || !SourceName) { printf("[!] Dude, u specified incorrect parameters :/\n\tUsage: %s -s <source container name> -p <container password>",argv[0]); exit(1); } if(!CryptAcquireContextA( &hProvResponder, "\\\\.\\Registry\\DestCopy", //Hardcoded name for container we create!!! NULL, dwProvType, CRYPT_NEWKEYSET | CRYPT_SILENT)) { HandleError("Error during CryptAcquireContext"); } if(!CryptAcquireContextA( &hProvSender, SourceName, NULL, dwProvType, 0)) { HandleError("Error during CryptAcquireContext"); } /// FIND ADDRESS TO PATCH HMODULE hModules[1024]; DWORD needed; if (EnumProcessModules(hCurrProc,hModules,1024,&needed)) { for (int i = 0; i < (needed / sizeof(HMODULE)); i++ ) { char szModName[1024]; if ( GetModuleFileNameA( hModules[i], szModName, sizeof(szModName))) { if (StrStrA(szModName, "cpcspi.dll")) { writeAddr += (DWORD)hModules[i]; printf("[+] Address in memory for patching is '%08X'.\n",writeAddr); break; } } } } /// !!! printf("[+] Now we patch process memory, patch size is '%i' bytes...",patchLen); VirtualProtectEx(hCurrProc, (void*)writeAddr, 2, PAGE_EXECUTE_READWRITE, &previous); WriteProcessMemory(hCurrProc, (void*)writeAddr, &patch, patchLen, NULL); printf("Ok\n"); printf("[+] Now we export container '%s'...\n",SourceName); if(!CryptGetProvParam( hProvSender, 92, NULL, &data_len, 0)) { HandleError("Error computing buffer length"); } oid = (BYTE *)malloc( data_len ); if( !oid ) HandleError("Out of memory."); if(!CryptGetProvParam( hProvSender, 92, oid, &data_len, 0)) { HandleError("Error during CryptGetProvParam"); } if(!CryptSetProvParam( hProvResponder, 92, oid, 0 )) { free( oid ); HandleError("Error during CryptSetProvParam"); } free( oid ); data_len = 0; if(!CryptGetProvParam( hProvSender, 93, NULL, &data_len, 0)) { HandleError("Error computing buffer length"); } /// SPECIFY PASSWORD FOR CONTAINER HERE if(!CryptSetProvParam( hProvSender,PP_SIGNATURE_PIN,(LPBYTE)Psdw,0)) { HandleError("Error during CryptSetProvParam"); } oid = (BYTE *)malloc( data_len ); if( !oid ) HandleError("Out of memory"); if(!CryptGetProvParam( hProvSender, 93, oid, &data_len, 0)) { free( oid ); HandleError("Error during CryptGetProvParam"); } if(!CryptSetProvParam( hProvResponder, 93, oid, 0 )) { free( oid ); HandleError("Error during CryptSetProvParam"); } free( oid ); if(!CryptGetUserKey( hProvSender, AT_KEYEXCHANGE, &hSenderKey )) { HandleError("Error during CryptGetUserKey private key"); } if(!CryptGenKey( hProvSender, (ALG_CLASS_KEY_EXCHANGE | ALG_TYPE_DH | 37), CRYPT_EXPORTABLE, &hSenderEphemKey)) { HandleError("ERROR -- CryptGenKey"); } if(!CryptGenKey( hProvResponder, (ALG_CLASS_KEY_EXCHANGE | ALG_TYPE_DH | 37), CRYPT_EXPORTABLE | CRYPT_PREGEN, &hResponderEphemKey)) { HandleError("ERROR -- CryptGenKey"); } if(!CryptGetKeyParam( hSenderEphemKey, 106, NULL, &dwBlobLen, 0)) { HandleError("Error computing BLOB length"); } pbKeyBlob = (BYTE*)malloc(dwBlobLen); if(!pbKeyBlob) HandleError("Out of memory"); if(!CryptGetKeyParam( hSenderEphemKey, 106, pbKeyBlob, &dwBlobLen, 0)) { HandleError("Error during CryptGetProvParam"); } if(!CryptSetKeyParam( hResponderEphemKey, 106, pbKeyBlob, 0)) { HandleError("Error during CryptSetProvParam"); } free(pbKeyBlob); pbKeyBlob = NULL; dwBlobLen = 0; if(!CryptSetKeyParam( hResponderEphemKey, KP_X, NULL, 0)) { HandleError("Error during CryptSetKeyParam"); } if(!CryptExportKey( hSenderEphemKey, 0, PUBLICKEYBLOB, 0, NULL, &dwBlobLen )) { HandleError("Error computing BLOB length"); } pbKeyBlob = (BYTE*)malloc(dwBlobLen); if(!pbKeyBlob) HandleError("Out of memory"); if(!CryptExportKey( hSenderEphemKey, 0, PUBLICKEYBLOB, 0, pbKeyBlob, &dwBlobLen )) { HandleError("Error during CryptExportKey"); } if(!CryptImportKey( hProvResponder, pbKeyBlob, dwBlobLen, hResponderEphemKey, 0, &hResponderAgreeKey)) { HandleError("Error during CryptImportKey ephemeral key"); } free(pbKeyBlob); pbKeyBlob = NULL; dwBlobLen = 0; if(!CryptExportKey( hResponderEphemKey, 0, PUBLICKEYBLOB, 0, NULL, &dwBlobLen )) { HandleError("Error computing BLOB length"); } pbKeyBlob = (BYTE*)malloc(dwBlobLen); if(!pbKeyBlob) HandleError("Out of memory"); if(!CryptExportKey( hResponderEphemKey, 0, PUBLICKEYBLOB, 0, pbKeyBlob, &dwBlobLen )) { HandleError("Error during CryptExportKey"); } if(!CryptImportKey( hProvSender, pbKeyBlob, dwBlobLen, hSenderEphemKey, 0, &hSenderAgreeKey)) { HandleError("Error during CryptImportKey ephemeral key"); } free(pbKeyBlob); pbKeyBlob = NULL; dwBlobLen = 0; if(!CryptSetKeyParam( hSenderAgreeKey, KP_ALGID, (BYTE*)&cAlg, 0 )) { HandleError("Error during CryptSetKeyParam agree key"); } if(!CryptSetKeyParam( hResponderAgreeKey, KP_ALGID, (BYTE*)&cAlg, 0 )) { HandleError("Error during CryptSetKeyParam agree key"); } if(!CryptExportKey( hSenderKey, hSenderAgreeKey, PRIVATEKEYBLOB, 0, NULL, &dwBlobLen )) { HandleError("Error computing BLOB length"); } pbKeyBlob = (BYTE*)malloc(dwBlobLen); if(!pbKeyBlob) HandleError("Out of memory"); if(!CryptExportKey( hSenderKey, hSenderAgreeKey, PRIVATEKEYBLOB, 0, pbKeyBlob, &dwBlobLen )) { HandleError("Error during CryptExportKey"); } if(!CryptImportKey( hProvResponder, pbKeyBlob, dwBlobLen, hResponderAgreeKey, 0, &hResponderKey)) { HandleError("Error during CryptImportKey private key"); } free(pbKeyBlob); pbKeyBlob = NULL; dwBlobLen = 0; if(!CryptGetKeyParam( hSenderKey, KP_CERTIFICATE, NULL, &dwBlobLen, 0)) { HandleError("Error computing BLOB length"); } pbKeyBlob = (BYTE*)malloc(dwBlobLen); if(!pbKeyBlob) { HandleError("Out of memory"); } if(!CryptGetKeyParam( hSenderKey, KP_CERTIFICATE, pbKeyBlob, &dwBlobLen, 0)) { HandleError("Error during CryptGetProvParam"); } if(!CryptSetKeyParam( hResponderKey, KP_CERTIFICATE, pbKeyBlob, 0)) { HandleError("Error during CryptSetProvParam"); } printf("[+] D0n3!!!\n"); CleanUp(); return 0; }
static BOOL decodeSK( BOOL aes256, DWORD keylen, BYTE *keybuf ) { BYTE buffer[ 1024 ]; DWORD i, size, length; struct skb { PUBLICKEYSTRUC hdr; ALG_ID algId; BYTE key[1]; } *expKey = (struct skb *)buffer; struct ptkb { PUBLICKEYSTRUC hdr; DWORD keysize; BYTE key[1]; } *txtKey = (struct ptkb *)buffer; length = (expKey->key - buffer) + keylen; if ( length > sizeof( buffer ) ) { fprintf( stderr, "CryptImportKey() requires %d bytes\n", length ); return( FALSE ); } expKey->hdr.bType = SIMPLEBLOB; expKey->hdr.bVersion = CUR_BLOB_VERSION; expKey->hdr.reserved = 0; expKey->hdr.aiKeyAlg = aes256 ? SessKey256 : SessKey128; expKey->algId = XchgKeyType; /* ** NOTE: it appears that the encoded key is byte swapped compared ** to external standards. There is a cryptic reference to a ** ReverseMemCopy() function in the RSA/SChannel server master ** key creation example. Also, the internal RSA modulus is ** byte swapped compared to the X509 encoding. This swap is ** required to interoperate with JavaSSE. */ for( i = 0; i < keylen; i++ ) expKey->key[i] = keybuf[ keylen - i - 1 ]; if ( ! CryptImportKey( provider, (BYTE *)expKey, length, xchgKey, CRYPT_EXPORTABLE, &sessKey ) ) { fprintf( stderr, "CryptImportKey() failed: 0x%x\n", GetLastError() ); return( FALSE ); } if ( ! CryptSetKeyParam( sessKey, KP_MODE, (BYTE *)&sessKeyMode, 0 ) ) { fprintf( stderr, "CryptSetKeyParam() MODE failed: 0x%x\n", GetLastError() ); return( 0 ); } if ( ! CryptSetKeyParam( sessKey, KP_PADDING, (BYTE *)&sessKeyPadding, 0 ) ) { fprintf( stderr, "CryptSetKeyParam() PADDING failed: 0x%x\n", GetLastError() ); return( 0 ); } if ( sessKeyMode == CRYPT_MODE_CBC ) { size = sizeof( length ); if ( ! CryptGetKeyParam( sessKey, KP_BLOCKLEN, (BYTE *)&length, &size, 0 ) ) { fprintf( stderr, "CryptGetKeyParam() BLOCKLEN failed: 0x%x\n", GetLastError() ); exit( 1 ); } length /= 8; /* Bits -> bytes */ for( i = 0; i < length; i++ ) buffer[i] = 0; if ( ! CryptSetKeyParam( sessKey, KP_IV, buffer, 0 ) ) { fprintf( stderr, "CryptSetKeyParam() PADDING failed: 0x%x\n", GetLastError() ); return( 0 ); } } if ( verbose ) { if ( ! CryptExportKey( sessKey, 0, PLAINTEXTKEYBLOB, 0, NULL, &size ) ) { fprintf( stderr, "CryptExportKey() [1] failed: 0x%x\n", GetLastError() ); return( FALSE ); } if ( size > sizeof( buffer ) ) { fprintf( stderr, "CryptExportKey() requires %d bytes\n", size ); return( FALSE ); } length = sizeof( buffer ); if ( ! CryptExportKey( sessKey, 0, PLAINTEXTKEYBLOB, 0, (BYTE *)txtKey, &length ) ) { fprintf( stderr, "CryptExportKey() [2] failed: 0x%x\n", GetLastError() ); return( FALSE ); } printf( "Sess Key: \n" ); hexDump( txtKey->keysize, txtKey->key ); keyInfo( sessKey ); } return( TRUE ); }
BOOL ImportPlainSessionBlob(HCRYPTPROV hProv, HCRYPTKEY hPrivateKey, ALG_ID dwAlgId, LPBYTE pbKeyMaterial , DWORD dwKeyMaterial , HCRYPTKEY *hSessionKey) { BOOL fResult; BOOL fReturn = FALSE; BOOL fFound = FALSE; LPBYTE pbSessionBlob = NULL; DWORD dwSessionBlob, dwSize, n; DWORD dwPublicKeySize; DWORD dwProvSessionKeySize; ALG_ID dwPrivKeyAlg; LPBYTE pbPtr; DWORD dwFlags = CRYPT_FIRST; PROV_ENUMALGS_EX ProvEnum; HCRYPTKEY hTempKey = 0; __try { // Double check to see if this provider supports this algorithm // and key size do { dwSize = sizeof(ProvEnum); fResult = CryptGetProvParam(hProv, PP_ENUMALGS_EX, (LPBYTE)&ProvEnum, &dwSize, dwFlags); if (!fResult) break; dwFlags = 0; if (ProvEnum.aiAlgid == dwAlgId) fFound = TRUE; } while (!fFound); if (!fFound) __leave; // We have to get the key size(including padding) // from an HCRYPTKEY handle. PP_ENUMALGS_EX contains // the key size without the padding so we can't use it. fResult = CryptGenKey(hProv, dwAlgId, 0, &hTempKey); if (!fResult) __leave; dwSize = sizeof(DWORD); fResult = CryptGetKeyParam(hTempKey, KP_KEYLEN, (LPBYTE)&dwProvSessionKeySize, &dwSize, 0); if (!fResult) __leave; CryptDestroyKey(hTempKey); hTempKey = 0; // Our key is too big, leave if ((dwKeyMaterial * 8) > dwProvSessionKeySize) __leave; // Get private key's algorithm dwSize = sizeof(ALG_ID); fResult = CryptGetKeyParam(hPrivateKey, KP_ALGID, (LPBYTE)&dwPrivKeyAlg, &dwSize, 0); if (!fResult) __leave; // Get private key's length in bits dwSize = sizeof(DWORD); fResult = CryptGetKeyParam(hPrivateKey, KP_KEYLEN, (LPBYTE)&dwPublicKeySize, &dwSize, 0); if (!fResult) __leave; // calculate Simple blob's length dwSessionBlob = (dwPublicKeySize/8) + sizeof(ALG_ID) + sizeof(BLOBHEADER); // allocate simple blob buffer pbSessionBlob = (LPBYTE)LocalAlloc(LPTR, dwSessionBlob); if (!pbSessionBlob) __leave; pbPtr = pbSessionBlob; // SIMPLEBLOB Format is documented in SDK // Copy header to buffer ((BLOBHEADER *)pbPtr)->bType = SIMPLEBLOB; ((BLOBHEADER *)pbPtr)->bVersion = 2; ((BLOBHEADER *)pbPtr)->reserved = 0; ((BLOBHEADER *)pbPtr)->aiKeyAlg = dwAlgId; pbPtr += sizeof(BLOBHEADER); // Copy private key algorithm to buffer *((DWORD *)pbPtr) = dwPrivKeyAlg; pbPtr += sizeof(ALG_ID); // Place the key material in reverse order for (n = 0; n < dwKeyMaterial; n++) { pbPtr[n] = pbKeyMaterial[dwKeyMaterial-n-1]; } // 3 is for the first reserved byte after the key material + the 2 reserved bytes at the end. dwSize = dwSessionBlob - (sizeof(ALG_ID) + sizeof(BLOBHEADER) + dwKeyMaterial + 3); pbPtr += (dwKeyMaterial+1); // Generate random data for the rest of the buffer // (except that last two bytes) fResult = CryptGenRandom(hProv, dwSize, pbPtr); if (!fResult) __leave; for (n = 0; n < dwSize; n++) { if (pbPtr[n] == 0) pbPtr[n] = 1; } pbSessionBlob[dwSessionBlob - 2] = 2; fResult = CryptImportKey(hProv, pbSessionBlob , dwSessionBlob, hPrivateKey, CRYPT_EXPORTABLE, hSessionKey); if (!fResult) __leave; fReturn = TRUE; } __finally { if (hTempKey) CryptDestroyKey(hTempKey); if (pbSessionBlob) LocalFree(pbSessionBlob); } return fReturn; }
int testSign(const char *containerNumber) { char provName[PROVIDER_BUFFER_SIZE]; char contName[CONTAINER_BUFFER_SIZE]; DWORD dwKeyUsage; HCRYPTPROV hProv = 0; HCRYPTKEY hKey; HCRYPTHASH hHash; BYTE pbData[200]; BYTE sig[512]; DWORD siglen; DWORD dwAlgId; BYTE data[500]; DWORD dwDataLen; long err; int errors = 0, count = 0; printf("\n*** Testing signatures ***\n"); /* Get the provider name, container name and keyusage (SIGN or KEYEX) */ if (listMyCerts(containerNumber, provName, contName, &dwKeyUsage)) return 1; if (dwKeyUsage == -1) { printf("Container %d not present, exiting\n", atoi(containerNumber)); return 1; } /* Acquire the provider handle */ if(!CryptAcquireContext(&hProv, contName, provName, PROV_RSA_FULL, 0)) { err = GetLastError(); printf("ERR: CryptAcquireContext: %s (0x%0x)\n", e2str(err), err); return 1; } // Done by Office2007 if (!CryptGetUserKey(hProv, AT_SIGNATURE, &hKey)) { err = GetLastError(); printf("ERR: CryptUserKey: %s (0x%0x)\n", e2str(err), err); errors++; goto done; } // Init hash if (!CryptCreateHash(hProv, CALG_SHA1, 0, 0, &hHash)) { err = GetLastError(); printf("ERR: CryptCreateHash: %s (0x%0x)\n", e2str(err), err); errors++; goto done; } // Done by Office2007 dwDataLen = sizeof(dwAlgId); if (!CryptGetKeyParam(hKey, KP_ALGID, (BYTE *) &dwAlgId, &dwDataLen, 0)) { err = GetLastError(); printf("ERR: CryptGetKeyParam: %s (0x%0x)\n", e2str(err), err); errors++; goto done; } if (dwAlgId != CALG_RSA_KEYX) { printf("ERR: CryptGetKeyParam() should return CALG_RSA_KEYX instead of 0x%0x\n", dwAlgId); errors++; } // Done by Office2007 if (!CryptExportKey(hKey, 0, PUBLICKEYBLOB, 0, NULL, &dwDataLen)) { err = GetLastError(); printf("ERR: CryptExportKey: %s (0x%0x)\n", e2str(err), err); errors++; goto done; } if (!CryptExportKey(hKey, 0, PUBLICKEYBLOB, 0, data, &dwDataLen)) { err = GetLastError(); printf("ERR: CryptExportKey: %s (0x%0x)\n", e2str(err), err); errors++; goto done; } memset(pbData, 0x31, sizeof(pbData)); // Hash data -- first part if (!CryptHashData(hHash, pbData, 50, 0)) { err = GetLastError(); printf("ERR: CryptHashData(1): %s (0x%0x)\n", e2str(err), err); errors++; goto done; } // Hash data -- second part if (!CryptHashData(hHash, pbData + 50, sizeof(pbData) - 50, 0)) { err = GetLastError(); printf("ERR: CryptHashData(1): %s (0x%0x)\n", e2str(err), err); errors++; goto done; } // Sign hash (get length) siglen = 0; if (!CryptSignHash(hHash, dwKeyUsage, NULL, 0, NULL, &siglen)) { err = GetLastError(); printf("ERR: CryptSignHash(HP_HASHSIZE): %s (0x%0x)\n", e2str(err), err); errors++; goto done; } // Sign hash if (!CryptSignHash(hHash, dwKeyUsage, NULL, 0, sig, &siglen)) { err = GetLastError(); printf("ERR: CryptSignHash(): %s (0x%0x)\n", e2str(err), err); errors++; goto done; } // Destroy hash if (!CryptDestroyHash(hHash)) { err = GetLastError(); printf("ERR: CryptDestroyHash(): %s (0x%0x)\n", e2str(err), err); errors++; } // Done by Office2007 if (!CryptDestroyKey(hKey)) { err = GetLastError(); printf("ERR: CryptDestroyKey(): %s (0x%0x)\n", e2str(err), err); errors++; } done: /* Release the provider handle */ if(!CryptReleaseContext(hProv, 0)) { err = GetLastError(); printf("ERR: CryptReleaseContext(): %s (0x%0x)\n", e2str(err), err); errors++; } printf("Done, %d error(s)\n\n", errors); return errors; }
void mod_mimikatz_crypto::listAndOrExportCertificates(vector<wstring> * arguments, bool exportCert) { wstring monEmplacement = L"CERT_SYSTEM_STORE_CURRENT_USER"; wstring monStore = L"My"; if(arguments->size() == 1) { monEmplacement = arguments->front(); } else if(arguments->size() == 2) { monEmplacement = arguments->front(); monStore = arguments->back(); } (*outputStream) << L"Emplacement : \'" << monEmplacement << L'\''; DWORD systemStore; if(mod_crypto::getSystemStoreFromString(monEmplacement, &systemStore)) { (*outputStream) << L"\\" << monStore << endl; if(HCERTSTORE hCertificateStore = CertOpenStore(CERT_STORE_PROV_SYSTEM, NULL, NULL, systemStore | CERT_STORE_OPEN_EXISTING_FLAG | CERT_STORE_READONLY_FLAG, monStore.c_str())) { DWORD i; PCCERT_CONTEXT pCertContext; for (i = 0, pCertContext = CertEnumCertificatesInStore(hCertificateStore, NULL); pCertContext != NULL; pCertContext = CertEnumCertificatesInStore(hCertificateStore, pCertContext), i++) { wstring * certName = new wstring(); bool reussite = false; if(!mod_crypto::getCertNameFromCertCTX(pCertContext, certName)) certName->assign(L"[empty]"); (*outputStream) << L"\t - " << *certName << endl;; sanitizeFileName(certName); wstringstream monBuff; monBuff << monEmplacement << L'_' << monStore << L'_' << i << L'_' << *certName << L'.'; mod_crypto::KIWI_KEY_PROV_INFO keyProvInfo; if(mod_crypto::getKiwiKeyProvInfo(pCertContext, &keyProvInfo)) { (*outputStream) << L"\t\tContainer Clé : " << keyProvInfo.pwszContainerName << endl; (*outputStream) << L"\t\tProvider : " << keyProvInfo.pwszProvName << endl; HCRYPTPROV_OR_NCRYPT_KEY_HANDLE monProv = NULL; DWORD keySpec = 0; BOOL aFermer = false; if(CryptAcquireCertificatePrivateKey(pCertContext, CRYPT_ACQUIRE_ALLOW_NCRYPT_KEY_FLAG /* CRYPT_ACQUIRE_SILENT_FLAG NULL */, NULL, &monProv, &keySpec, &aFermer)) { (*outputStream) << L"\t\tType : " << mod_crypto::KeyTypeToString(keySpec) << endl; DWORD size = 0; bool exportable = false; if(keySpec == CERT_NCRYPT_KEY_SPEC) { if(mod_cryptong::isNcrypt) { reussite = mod_cryptong::getKeySize(&monProv, &size); reussite &=mod_cryptong::isKeyExportable(&monProv, &exportable); if(aFermer) { mod_cryptong::NCryptFreeObject(monProv); } } else (*outputStream) << L"\t\t\tErreur : Clé de type nCrypt, sans nCrypt ?" << endl; } else { DWORD tailleEcrite = 0; DWORD exportability; HCRYPTKEY maCle = NULL; if(reussite = (CryptGetUserKey(monProv, keySpec, &maCle) != 0)) { tailleEcrite = sizeof(DWORD); reussite = (CryptGetKeyParam(maCle, KP_KEYLEN, reinterpret_cast<BYTE *>(&size), &tailleEcrite, NULL) != 0); tailleEcrite = sizeof(DWORD); reussite &= (CryptGetKeyParam(maCle, KP_PERMISSIONS, reinterpret_cast<BYTE *>(&exportability), &tailleEcrite, NULL) != 0); exportable = (exportability & CRYPT_EXPORT) != 0; } if(aFermer) { CryptReleaseContext(monProv, 0); } } if(reussite) { (*outputStream) << L"\t\tExportabilité : " << (exportable ? L"OUI" : L"NON") << endl; (*outputStream) << L"\t\tTaille clé : " << size << endl; } if(exportCert) { wstring PFXFile = monBuff.str(); PFXFile.append(L"pfx"); reussite = mod_crypto::CertCTXtoPFX(pCertContext, PFXFile, L"mimikatz"); (*outputStream) << L"\t\tExport privé dans \'" << PFXFile << L"\' : " << (reussite ? L"OK" : L"KO") << endl; if(!reussite) { (*outputStream) << L"\t\t\t" << mod_system::getWinError() << endl; } } } else (*outputStream) << L"CryptAcquireCertificatePrivateKey : " << mod_system::getWinError() << endl; } if(exportCert) { wstring DERFile = monBuff.str(); DERFile.append(L"der"); reussite = mod_crypto::CertCTXtoDER(pCertContext, DERFile); (*outputStream) << L"\t\tExport public dans \'" << DERFile << L"\' : " << (reussite ? L"OK" : L"KO") << endl; if(!reussite) { (*outputStream) << L"\t\t\t" << mod_system::getWinError() << endl; } } delete certName; } CertCloseStore(hCertificateStore, CERT_CLOSE_STORE_FORCE_FLAG); } else (*outputStream) << L"CertOpenStore : " << mod_system::getWinError() << endl; } else (*outputStream) << L" introuvable !" << endl; }