Why BCryptDeriveKeyPBKDF2 return STATUS_INVALID_PARAMETER? - c++

#include <iostream>
#include<Windows.h>
#include<bcrypt.h>
#include <ntstatus.h>
#include<string>
#include<vector>
#pragma comment(lib, "bcrypt.lib")
void test_status(NTSTATUS return_val)
{
switch (return_val)
{
case(STATUS_SUCCESS):
{
std::cout << "STATUS_SUCCESS\n";
break;
}
case(STATUS_BUFFER_TOO_SMALL):
{
std::cout << "STATUS_BUFFER_TOO_SMALL\n";
break;
}
case(STATUS_INVALID_HANDLE):
{
std::cout << "STATUS_INVALID_HANDLE\n";
break;
}
case(STATUS_INVALID_PARAMETER):
{
std::cout << "STATUS_INVALID_PARAMETER\n";
break;
}
case(STATUS_NOT_SUPPORTED):
{
std::cout << "STATUS_NOT_SUPPORTED\n";
break;
}
};
}
int main()
{
BCRYPT_ALG_HANDLE phAlgorithm = nullptr;
BCRYPT_HASH_HANDLE phHash = nullptr;
LPCWSTR pszAlgId = TEXT("XTS-AES");
LPCWSTR pszImplementation = TEXT("Advanced Encryption Standard");
PUCHAR pbHashObject = nullptr;
std::vector<BYTE> pbSalt = { 0x77, 0x1f, 0x5b, 0x30, 0x2c, 0xf7, 0xc5, 0x31,
0xa9, 0x86, 0x46, 0x52, 0xe2, 0xff, 0x4a, 0x17,
0xab, 0xd0, 0x02, 0xdd, 0x4f, 0xb0, 0x2f, 0x71,
0x0f, 0xe5, 0xa8, 0x1a, 0xfe, 0xe7, 0x9c, 0x6b }; // 771f5b302cf7c531a9864652e2ff4a17abd002dd4fb02f710fe5a81afee79c6b
NTSTATUS status = BCryptOpenAlgorithmProvider(
&phAlgorithm,
BCRYPT_PBKDF2_ALGORITHM,
NULL,
NULL
);
test_status(status);
PUCHAR pbOutput = nullptr;
ULONG pcbResult = NULL;
status = BCryptGetProperty(
phAlgorithm,
BCRYPT_OBJECT_LENGTH,
pbOutput,
sizeof(DWORD),
&pcbResult,
NULL
);
test_status(status);
PUCHAR DerivedKey = nullptr;
DWORD cbDerivedKey = NULL;
std::string pbPassword = "MySecretPass";
std::string DerivedKeyString;
status = BCryptDeriveKeyPBKDF2(
phAlgorithm,
(BYTE*)pbPassword.data(),
pbPassword.length(),
(BYTE*)pbSalt.data(),
sizeof(BYTE),
10000,
(PUCHAR)DerivedKeyString.c_str(),
64,
0);
test_status(status);
status = BCryptCloseAlgorithmProvider(
phAlgorithm,
NULL
);
test_status(status);
}
This code should get the key from the password, but at this stage of generating this key, I get an error STATUS_INVALID_PARAMETER. Why is this happening and how to fix it
-I tried to change the encryption algorithm and pass the parameters in a different way, but all this did not lead to success or gave the error STATUS_INVALID_PARAMETER.

There are two errors:
Firstly, you are performing hash computation, the BCryptOpenAlgorithmProvider function must use flags and identifiers for the hash function's behavior.
In the function BCryptOpenAlgorithmProvider, replace BCRYPT_PBKDF2_ALGORITHM with BCRYPT_SHA256_ALGORITHM, use BCRYPT_ALG_HANDLE_HMAC_FLAG in the fourth dwFlags parameter.
The documentation for these two parameters is as follows:
https://learn.microsoft.com/en-us/windows/win32/seccng/cng-algorithm-identifiers
https://learn.microsoft.com/en-us/windows/win32/api/bcrypt/nf-bcrypt-bcryptopenalgorithmprovider
Secondly, do not use string type of the parameter pbDerivedKey, or it will crash the memory.
Replace std::string DerivedKeyString with BYTE DerivedKeyString[64].
In the function BCryptDeriveKeyPBKDF2, replace (PUCHAR)DerivedKeyString.c_str() with DerivedKeyString.

Related

Can Microsoft Cryptographic API allow creation of ECDSA keys from a stream of bytes?

So I am pondering which cryptographic C++ library to use (I already figured out how to do equivalent in C#) for the verification of a licence file signed hash.
Reading the Microsoft documentation for CNG it seems that it is not possible to generate an ECDSA key in code from a stream of bytes despite this being possible for a RSA key (I think, not 100% sure).
Because I wanted in code byte stream generation, I looked at crypto++ and I managed to get the test suite compiled but cryptolib.lib is an outsize 90 megabytes and I am facing a slew of link errors simply trying to do something basic. So I am less keen in crypto++ now.
So I want to turn back to using something shipped by Microsoft in its desktop Windows OS but I am back to my original problem of no in code bytestream generated keys.
Can an expert confirm that this really isn't possible? Also, can they suggest alternative, I am happy to fall back to RSA with a long (2048?) key.
The following code compiles and runs for me. It can be found at the MSDN article -
Signing Data with CNG. I was wondering if it could be adapted. Does this code (a) create an ECDSA key on the fly (b) sign a hash (c) save key to a certificate store (d) retrieve the key and verify signed hash. If so then I guess it's demo code. What I would need is an example of a hard coded ECDSA key not one created on the fly.
// CngECDSA.cpp : Defines the entry point for the console application.
// Based on https://msdn.microsoft.com/en-us/library/windows/desktop/aa376304(v=vs.85).aspx
#include "stdafx.h"
#include <Windows.h>
#include <stdint.h>
#include <Bcrypt.h>
#include <ncrypt.h>
#pragma comment(lib, "bcrypt")
#pragma comment(lib, "ncrypt")
#define NT_SUCCESS(Status) (((NTSTATUS)(Status)) >= 0)
#define STATUS_UNSUCCESSFUL ((NTSTATUS)0xC0000001L)
static const BYTE rgbMsg[] =
{
0x04, 0x87, 0xec, 0x66, 0xa8, 0xbf, 0x17, 0xa6,
0xe3, 0x62, 0x6f, 0x1a, 0x55, 0xe2, 0xaf, 0x5e,
0xbc, 0x54, 0xa4, 0xdc, 0x68, 0x19, 0x3e, 0x94,
};
BYTE value[] =
{ 0x02,0x00,0x00,0x00 };
void __cdecl wmain(
int argc,
__in_ecount(argc) LPWSTR *wargv)
{
NCRYPT_PROV_HANDLE hProv = NULL;
NCRYPT_KEY_HANDLE hKey = NULL;
BCRYPT_KEY_HANDLE hTmpKey = NULL;
SECURITY_STATUS secStatus = ERROR_SUCCESS;
BCRYPT_ALG_HANDLE hHashAlg = NULL,
hSignAlg = NULL;
BCRYPT_HASH_HANDLE hHash = NULL;
NTSTATUS status = STATUS_UNSUCCESSFUL;
DWORD cbData = 0,
cbHash = 0,
cbBlob = 0,
cbSignature = 0,
cbHashObject = 0;
PBYTE pbHashObject = NULL;
PBYTE pbHash = NULL,
pbBlob = NULL,
pbSignature = NULL;
UNREFERENCED_PARAMETER(argc);
UNREFERENCED_PARAMETER(wargv);
//open an algorithm handle
if (!NT_SUCCESS(status = BCryptOpenAlgorithmProvider(
&hHashAlg,
BCRYPT_SHA1_ALGORITHM,
NULL,
0)))
{
wprintf(L"**** Error 0x%x returned by BCryptOpenAlgorithmProvider\n", status);
goto Cleanup;
}
if (!NT_SUCCESS(status = BCryptOpenAlgorithmProvider(
&hSignAlg,
BCRYPT_ECDSA_P256_ALGORITHM,
NULL,
0)))
{
wprintf(L"**** Error 0x%x returned by BCryptOpenAlgorithmProvider\n", status);
goto Cleanup;
}
//calculate the size of the buffer to hold the hash object
if (!NT_SUCCESS(status = BCryptGetProperty(
hHashAlg,
BCRYPT_OBJECT_LENGTH,
(PBYTE)&cbHashObject,
sizeof(DWORD),
&cbData,
0)))
{
wprintf(L"**** Error 0x%x returned by BCryptGetProperty\n", status);
goto Cleanup;
}
//allocate the hash object on the heap
pbHashObject = (PBYTE)HeapAlloc(GetProcessHeap(), 0, cbHashObject);
if (NULL == pbHashObject)
{
wprintf(L"**** memory allocation failed\n");
goto Cleanup;
}
//calculate the length of the hash
if (!NT_SUCCESS(status = BCryptGetProperty(
hHashAlg,
BCRYPT_HASH_LENGTH,
(PBYTE)&cbHash,
sizeof(DWORD),
&cbData,
0)))
{
wprintf(L"**** Error 0x%x returned by BCryptGetProperty\n", status);
goto Cleanup;
}
//allocate the hash buffer on the heap
pbHash = (PBYTE)HeapAlloc(GetProcessHeap(), 0, cbHash);
if (NULL == pbHash)
{
wprintf(L"**** memory allocation failed\n");
goto Cleanup;
}
//create a hash
if (!NT_SUCCESS(status = BCryptCreateHash(
hHashAlg,
&hHash,
pbHashObject,
cbHashObject,
NULL,
0,
0)))
{
wprintf(L"**** Error 0x%x returned by BCryptCreateHash\n", status);
goto Cleanup;
}
//hash some data
if (!NT_SUCCESS(status = BCryptHashData(
hHash,
(PBYTE)rgbMsg,
sizeof(rgbMsg),
0)))
{
wprintf(L"**** Error 0x%x returned by BCryptHashData\n", status);
goto Cleanup;
}
//close the hash
if (!NT_SUCCESS(status = BCryptFinishHash(
hHash,
pbHash,
cbHash,
0)))
{
wprintf(L"**** Error 0x%x returned by BCryptFinishHash\n", status);
goto Cleanup;
}
//open handle to KSP
if (FAILED(secStatus = NCryptOpenStorageProvider(
&hProv,
MS_KEY_STORAGE_PROVIDER,
0)))
{
wprintf(L"**** Error 0x%x returned by NCryptOpenStorageProvider\n", secStatus);
goto Cleanup;
}
//create a persisted key
if (FAILED(secStatus = NCryptCreatePersistedKey(
hProv,
&hKey,
NCRYPT_ECDSA_P256_ALGORITHM,
L"my ecc key",
0,
0)))
{
wprintf(L"**** Error 0x%x returned by NCryptCreatePersistedKey\n", secStatus);
goto Cleanup;
}
//create key on disk
if (FAILED(secStatus = NCryptFinalizeKey(hKey, 0)))
{
wprintf(L"**** Error 0x%x returned by NCryptFinalizeKey\n", secStatus);
goto Cleanup;
}
//sign the hash
if (FAILED(secStatus = NCryptSignHash(
hKey,
NULL,
pbHash,
cbHash,
NULL,
0,
&cbSignature,
0)))
{
wprintf(L"**** Error 0x%x returned by NCryptSignHash\n", secStatus);
goto Cleanup;
}
//allocate the signature buffer
pbSignature = (PBYTE)HeapAlloc(GetProcessHeap(), 0, cbSignature);
if (NULL == pbSignature)
{
wprintf(L"**** memory allocation failed\n");
goto Cleanup;
}
if (FAILED(secStatus = NCryptSignHash(
hKey,
NULL,
pbHash,
cbHash,
pbSignature,
cbSignature,
&cbSignature,
0)))
{
wprintf(L"**** Error 0x%x returned by NCryptSignHash\n", secStatus);
goto Cleanup;
}
if (FAILED(secStatus = NCryptExportKey(
hKey,
NULL,
BCRYPT_ECCPUBLIC_BLOB,
NULL,
NULL,
0,
&cbBlob,
0)))
{
wprintf(L"**** Error 0x%x returned by NCryptExportKey\n", secStatus);
goto Cleanup;
}
pbBlob = (PBYTE)HeapAlloc(GetProcessHeap(), 0, cbBlob);
if (NULL == pbBlob)
{
wprintf(L"**** memory allocation failed\n");
goto Cleanup;
}
if (FAILED(secStatus = NCryptExportKey(
hKey,
NULL,
BCRYPT_ECCPUBLIC_BLOB,
NULL,
pbBlob,
cbBlob,
&cbBlob,
0)))
{
wprintf(L"**** Error 0x%x returned by NCryptExportKey\n", secStatus);
goto Cleanup;
}
if (!NT_SUCCESS(status = BCryptImportKeyPair(
hSignAlg,
NULL,
BCRYPT_ECCPUBLIC_BLOB,
&hTmpKey,
pbBlob,
cbBlob,
0)))
{
wprintf(L"**** Error 0x%x returned by BCryptImportKeyPair\n", status);
goto Cleanup;
}
if (!NT_SUCCESS(status = BCryptVerifySignature(
hTmpKey,
NULL,
pbHash,
cbHash,
pbSignature,
cbSignature,
0)))
{
wprintf(L"**** Error 0x%x returned by BCryptVerifySignature\n", status);
goto Cleanup;
}
wprintf(L"Success!\n");
Cleanup:
if (hHashAlg)
{
BCryptCloseAlgorithmProvider(hHashAlg, 0);
}
if (hSignAlg)
{
BCryptCloseAlgorithmProvider(hSignAlg, 0);
}
if (hHash)
{
BCryptDestroyHash(hHash);
}
if (pbHashObject)
{
HeapFree(GetProcessHeap(), 0, pbHashObject);
}
if (pbHash)
{
HeapFree(GetProcessHeap(), 0, pbHash);
}
if (pbSignature)
{
HeapFree(GetProcessHeap(), 0, pbSignature);
}
if (pbBlob)
{
HeapFree(GetProcessHeap(), 0, pbBlob);
}
if (hTmpKey)
{
BCryptDestroyKey(hTmpKey);
}
if (hKey)
{
NCryptDeleteKey(hKey, 0);
}
if (hProv)
{
NCryptFreeObject(hProv);
}
}
Just to be clear, I aiming at 384 bit and for compatibility with OpenSsl and C# curvename is NIST recommended curve secp384r1 – {1.3.132.0.34} And I will be using SHA256 hash twice (just like BitCoin).
Does this code (a) create an ECDSA key on the fly (b) sign a hash (c) save key to a certificate store (d) retrieve the key and verify signed hash. If so then I guess it's demo code.
A) Yes.
B) Yes.
C) Yes. It saves the key as a persisted object named "my ec key". But since it never asked for it by name again, nullptr/NULL could have been passed to make it be an ephemeral key. (And it saved it to the "key store", not a "certificate store".
D) Yes to verify, no to retrieve.
Getting your publicKey data (this is the output of openssl ec -in eckey.pem -pubout -outform der | xxd -g1 translated into the C array) and signature (in the IEEE P1363 format) is an exercise left to the reader.
static const BYTE data[] =
{
'1', '2', '3', '4',
};
static const BYTE publicKey[] =
{
0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2a, 0x86,
0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x08, 0x2a,
0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, 0x03,
0x42, 0x00, 0x04, 0x23, 0x63, 0xdd, 0x13, 0x1d,
0xa6, 0x5e, 0x89, 0x9a, 0x2e, 0x63, 0xe9, 0xe0,
0x5e, 0x50, 0xc8, 0x30, 0xd4, 0x99, 0x46, 0x62,
0xff, 0xe8, 0x83, 0xdb, 0x2b, 0x9a, 0x76, 0x7d,
0xcc, 0xab, 0xa2, 0xf0, 0x70, 0x81, 0xb5, 0x71,
0x1b, 0xe1, 0xde, 0xe9, 0x0d, 0xfc, 0x8d, 0xe1,
0x79, 0x70, 0xc2, 0xd9, 0x37, 0xa1, 0x6c, 0xd3,
0x45, 0x81, 0xf5, 0x2b, 0x8d, 0x59, 0xc9, 0xe9,
0x53, 0x2d, 0x13,
};
static const BYTE signature[] =
{
// r
0xc6, 0x4c, 0x14, 0x55, 0xfe, 0xc0, 0x2f, 0xe7,
0x4a, 0x25, 0x87, 0xe7, 0x0c, 0x10, 0x4e, 0x73,
0xf0, 0x28, 0x86, 0x18, 0x28, 0xae, 0xef, 0x4f,
0xe5, 0xa0, 0xcc, 0x7a, 0xa8, 0xe4, 0x1f, 0xbf,
// s
0x35, 0x9f, 0x23, 0xfd, 0xc3, 0xd6, 0x33, 0xfb,
0x52, 0x47, 0x9b, 0xef, 0x2b, 0x2a, 0x48, 0xa8,
0x6f, 0x37, 0x04, 0xd0, 0x8c, 0xc3, 0x49, 0x04,
0x21, 0x53, 0xb8, 0x3c, 0x9d, 0x8c, 0x6c, 0xf5,
};
#define NT_SUCCESS(Status) (((NTSTATUS)(Status)) >= 0)
int main()
{
NTSTATUS status = NTE_BAD_DATA;
int exitCode = ERROR_INVALID_FUNCTION;
BCRYPT_KEY_HANDLE importedPublicKey = nullptr;
PCERT_PUBLIC_KEY_INFO subjectPublicKeyInfo = (PCERT_PUBLIC_KEY_INFO)LocalAlloc(0, 2048);
BCRYPT_ALG_HANDLE sha256 = nullptr;
BCRYPT_HASH_HANDLE hHash = nullptr;
BYTE dataHash[256 >> 3];
DWORD structSize = 2048;
if (!CryptDecodeObject(
X509_ASN_ENCODING,
X509_PUBLIC_KEY_INFO,
publicKey,
sizeof(publicKey),
0,
subjectPublicKeyInfo,
&structSize))
{
wprintf(L"**** Error 0x%x returned by CryptDecodeObject\n", GetLastError());
goto Cleanup;
}
if (!CryptImportPublicKeyInfoEx2(
X509_ASN_ENCODING,
subjectPublicKeyInfo,
0,
nullptr,
&importedPublicKey))
{
wprintf(L"**** Error 0x%x returned by CryptImportPublicKeyInfoEx2\n", GetLastError());
goto Cleanup;
}
if (!NT_SUCCESS(status = BCryptOpenAlgorithmProvider(&sha256, BCRYPT_SHA256_ALGORITHM, nullptr, 0)))
{
wprintf(L"**** Error 0x%x returned by BCryptOpenAlgorithmProvider\n", status);
goto Cleanup;
}
if (!NT_SUCCESS(status = BCryptCreateHash(sha256, &hHash, nullptr, 0, nullptr, 0, 0)))
{
wprintf(L"**** Error 0x%x returned by BCryptCreateHash\n", status);
goto Cleanup;
}
if (!NT_SUCCESS(status = BCryptHashData(hHash, (PUCHAR)data, sizeof(data), 0)))
{
wprintf(L"**** Error 0x%x returned by BCryptHashData\n", status);
goto Cleanup;
}
if (!NT_SUCCESS(status = BCryptFinishHash(hHash, (PUCHAR)dataHash, sizeof(dataHash), 0)))
{
wprintf(L"**** Error 0x%x returned by BCryptFinishHash\n", status);
goto Cleanup;
}
status = BCryptVerifySignature(
importedPublicKey,
nullptr,
(PUCHAR)dataHash,
sizeof(dataHash),
(PUCHAR)signature,
sizeof(signature),
0);
switch (status)
{
case STATUS_SUCCESS:
wprintf(L"Signature verified successfully\n");
exitCode = ERROR_SUCCESS;
break;
case STATUS_INVALID_SIGNATURE:
wprintf(L"Signature did not verify\n");
exitCode = ERROR_INVALID_DATA;
break;
default:
wprintf(L"**** Error 0x%x returned by BCryptVerifySignature\n", status);
goto Cleanup;
}
Cleanup:
if (hHash != nullptr)
BCryptDestroyHash(hHash);
if (sha256 != nullptr)
BCryptCloseAlgorithmProvider(sha256, 0);
if (importedPublicKey != nullptr)
BCryptDestroyKey(importedPublicKey);
LocalFree(subjectPublicKeyInfo);
return exitCode;
}

Windows: How to control the adaptive brightness?

I want to control(On/Off) the adaptive brightness like the Power Options
Enable adaptive brightness:
by API in Win 10. I guess the API is included in the Power Management Functions: https://msdn.microsoft.com/en-us/library/windows/desktop/aa373163(v=vs.85).aspx
But I cannot find the function... May someone provide me some suggestions or directions. Thanks a lot!
I found the solution by myself, and I share the way to everyone who needs!
GUID *guidScheme;
bool bResult = false;
byte enableFunction= 0x1; //Set 0x0 to disable
bResult = PowerGetActiveScheme(NULL, &guidScheme);
if (bResult != ERROR_SUCCESS){
//error message
}
GUID guidSubVideo = { 0x7516b95f, 0xf776, 0x4464, 0x8c, 0x53, 0x06, 0x16, 0x7f, 0x40, 0xcc, 0x99 };
GUID guidAdaptBright = { 0xfbd9aa66, 0x9553, 0x4097, 0xba, 0x44, 0xed, 0x6e, 0x9d, 0x65, 0xea, 0xb8 };
bResult = PowerWriteDCValueIndex(NULL, guidScheme, &guidSubVideo, &guidAdaptBright, enableFunction);
if (bResult != ERROR_SUCCESS){
//error message
}

CM_Get_Device_Interface_List returns CR_INVALID_POINTER

So, I have little problem with CM_Get_Device_Interface_List function. Function returns with error code 3, which is CR_INVALID_POINTER. But when I call CM_Get_Device_Interface_List_Size function, it returns success.
ULONG lenght = 0;
PWSTR DevicePath = NULL;
CONFIGRET cr = CR_SUCCESS;
cr = CM_Get_Device_Interface_List_Size(&lenght, (LPGUID)&HWN_DEVINTERFACE_NLED, NULL, CM_GET_DEVICE_INTERFACE_LIST_PRESENT);// success
if (cr != CR_SUCCESS)
{
// error handling
}
cr = CM_Get_Device_Interface_List((LPGUID)&HWN_DEVINTERFACE_NLED, NULL, DevicePath, lenght, CM_GET_DEVICE_INTERFACE_LIST_PRESENT); // error
if (cr != CR_SUCCESS)
{
// error handling
}
DEFINE_GUID(HWN_DEVINTERFACE_NLED,
0x6b2a25e2, 0xaaf5, 0x482c, 0x99, 0xa5, 0x62, 0x05, 0xcd, 0xcc, 0x17, 0x6a); // GUID Declaration
So, why the pointer is invalid?
A bit late, probably figured this out but in case someone else comes across this I believe the reason you are getting the invalid pointer is because you are passing in a null pointer as the buffer (DevicePath), it must be allocated with the size returned from your first call.
Example (cleaned up a bit):
ULONG bufferSize = 0;
if (CM_Get_Device_Interface_List_Size(&bufferSize, (LPGUID)&HWN_DEVINTERFACE_NLED, NULL, CM_GET_DEVICE_INTERFACE_LIST_PRESENT) == CR_SUCCESS)
{
PWSTR buffer = (PWSTR)malloc(bufferSize);
if (CM_Get_Device_Interface_List((LPGUID)&HWN_DEVINTERFACE_NLED, NULL, buffer, bufferSize, CM_GET_DEVICE_INTERFACE_LIST_PRESENT) == CR_SUCCESS)
{
// buffer should now contain a list of NULL-terminated unicode strings
}
if (buffer)
{
free(buffer);
}
}
DEFINE_GUID(HWN_DEVINTERFACE_NLED,
0x6b2a25e2, 0xaaf5, 0x482c, 0x99, 0xa5, 0x62, 0x05, 0xcd, 0xcc, 0x17, 0x6a); // GUID Declaration
Alternate Example (no malloc):
#define BUFFER_SIZE 4096 // 4k buffer should be plenty
WCHAR buffer[BUFFER_SIZE];
if (CM_Get_Device_Interface_List((LPGUID)&HWN_DEVINTERFACE_NLED, NULL, buffer, BUFFER_SIZE, CM_GET_DEVICE_INTERFACE_LIST_PRESENT) == CR_SUCCESS)
{
// buffer should now contain a list of NULL-terminated unicode strings
}
DEFINE_GUID(HWN_DEVINTERFACE_NLED,
0x6b2a25e2, 0xaaf5, 0x482c, 0x99, 0xa5, 0x62, 0x05, 0xcd, 0xcc, 0x17, 0x6a); // GUID Declaration

SizeOfImage member causing program crash

Im trying to look for BYTE patterns in programs but for some reason when i assign the value to from MINFO.SizeOfImage to ModuleSize it causes the program i injected the DLL into to crash.
DWORD FindPattern(const BYTE* Pattern,SIZE_T PatternSize)
{
DWORD ModuleBase = (DWORD)GetModuleHandle(NULL);
DWORD ModuleSize = 0;
MODULEINFO MINFO;
HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS,0,GetCurrentProcessId());
if(hProcess)
{
GetModuleInformation(hProcess,GetModuleHandle(NULL),&MINFO,sizeof(MODULEINFO));
CloseHandle(hProcess);
ModuleSize = MINFO.SizeOfImage;
}
else
return 0;
for(int i = 0;i < ModuleSize;i++)
{
if(memcmp((void*)(ModuleBase + i),Pattern,PatternSize) == 0)
return ModuleBase + i;
}
return 0;
}
You code worked just fine when i compiled it and injected. I even tested it against the current FindPattern i am using. I didnt get any errors. Heres my code & yours
bool Compare(const BYTE* pData, const BYTE* bMask, const char* szMask)
{
for(;*szMask;++szMask,++pData,++bMask)
if(*szMask=='x' && *pData!=*bMask) return 0;
return (*szMask) == NULL;
}
DWORD FindPattern(DWORD dwAddress, DWORD dwLen, BYTE *bMask, char * szMask)
{
for(DWORD i=0; i<dwLen; i++)
if (Compare((BYTE*)(dwAddress+i),bMask,szMask)) return (DWORD)(dwAddress+i);
return 0;
}
And then when i run this through it
uint8 DecryptNeedle[] = {0x56, 0x8B, 0x74, 0x24, 0x08, 0x89, 0x71, 0x10,
0x0F, 0xB6, 0x16, 0x0F, 0xB6, 0x46, 0x01, 0x03,
0xC2, 0x8B, 0x51, 0x28, 0x25, 0xFF, 0x00, 0x00,
0x00, 0x89, 0x41, 0x04, 0x0F, 0xB6, 0x04, 0x10};
char DecryptMask[] = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
DWORD addrDecrypt = FindPattern(dwModuleStartAddr, 0xA000, DecryptNeedle, DecryptMask);
DWORD decrypt2 = YourFindPattern(DecryptNeedle, 32);
output is identical in both.
I would double check your injection code, and check whatelse could be causing the error. Also, do a quick error check
if(hProcess)
{
if(!GetModuleInformation(hProcess,GetModuleHandle(NULL),&MINFO,sizeof(MODULEINFO)));
{
//error
}
CloseHandle(hProcess);
ModuleSize = MINFO.SizeOfImage;
}

Invalid Algorithm Specified CryptoAPI

I am trying to decrypt something using 128BIT AES Decryption. When i attempt to calling CryptDecrypt i get an Error stating "Invalid Algorithm Specified". I get the same problem when using the library posted here: http://www.codeproject.com/KB/security/WinAES.aspx
What can cause this error?
I am using CryptoAPI along on vista64bit with visual studio 2008. I checked in the registry and the AES library is there...
EDIT
BYTE*& encryptedData /* get data length */
HCRYPTPROV cryptoHandle = NULL;
HCRYPTKEY aesKeyHandle = NULL;
hr = InitWinCrypt(cryptoHandle);
if(FAILED(hr))
{
return hr;
}
AesKeyOffering aesKey = { {PLAINTEXTKEYBLOB, CUR_BLOB_VERSION, 0, CALG_AES_128}, 16, { 0xFF, 0x00, 0xFF, 0x1C, 0x1D, 0x1E, 0x03, 0x04, 0x05, 0x0F, 0x20, 0x21, 0xAD, 0xAF, 0xA4, 0x04 }};
if(CryptImportKey(cryptoHandle, (CONST BYTE*)&aesKey, sizeof(AesKeyOffering), NULL, 0, &aesKeyHandle) == FALSE)
{
// DO error
return HRESULT_FROM_WIN32(GetLastError());
}
if(CryptSetKeyParam(aesKeyHandle, KP_IV, { 0xFF, 0x00, 0xFF, 0x1C, 0x1D, 0x1E, 0x03, 0x04, 0x05, 0x0F, 0x20, 0x21, 0xAD, 0xAF, 0xA4, 0x04 } , 0) == FALSE)
{
return HRESULT_FROM_WIN32(GetLastError());
}
BYTE blah2 = CRYPT_MODE_CBC;
// set block mode
if(CryptSetKeyParam(aesKeyHandle, KP_MODE, &blah2, 0) == FALSE)
{
//
return HRESULT_FROM_WIN32(GetLastError());
}
DWORD lol = dataLength / 16 + 1;
DWORD lol2 = lol * 16;
if(CryptDecrypt(aesKeyHandle, 0, TRUE, 0, encryptedData, &lol2) == FALSE)
{
return HRESULT_FROM_WIN32(GetLastError());
}
InitWinCrypt function
if(!CryptAcquireContextW(&cryptoHandle, NULL, L"Microsoft Enhanced RSA and AES Cryptographic Provider", PROV_RSA_AES, CRYPT_VERIFYCONTEXT))
{
if(!CryptAcquireContextW(&cryptoHandle, NULL, L"Microsoft Enhanced RSA and AES Cryptographic Provider", PROV_RSA_AES, 0))
{
return HRESULT_FROM_WIN32(GetLastError());
}
else
{
return S_OK;
}
}
return S_OK;
AesOffering struct:
struct AesKeyOffering
{
BLOBHEADER m_Header;
DWORD m_KeyLength;
BYTE Key[16];
};
EDIT2
After rebooting my computer, and remvoing the CBC chunk. I am now getting Bad Data Errors. The data decrypts fine in C#. But i need to do this using wincrypt.
Are you passing cryptoHandle by reference to InitWithCrypt? If not, your code
if(!CryptAcquireContextW(&cryptoHandle, ...
would only modify InitWinCrypt's copy of cryptoHandle.
EDIT: Given that it does, try getting rid of the CryptSetKeyParam call which sets CRYPT_MODE_CBC