CryptImportKey Windows 8.1 Using AES_256 PLAINTEXTKEYBLOB - c++

context->last_error = NULL;
const BYTE key[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,// BLOBHEADER
0x00, 0x00, 0x00, 0x00,// Key size
0x23, 0x31, 0xb1, 0x24, 0x7b, 0x15, 0xdf, 0xb0,// AES KEY
0xc9, 0x92, 0xaa, 0xc4, 0x2e, 0x02, 0x9b, 0x07,
0xdf, 0x21, 0x12, 0x53, 0xba, 0x28, 0x77, 0xd2,
0x99, 0x74, 0x96, 0xa4, 0x54, 0x54, 0x0d, 0xf1 };
BLOBHEADER* hdr = (BLOBHEADER*)key;
hdr->aiKeyAlg = CALG_AES_256;
hdr->bType = PLAINTEXTKEYBLOB;
hdr->bVersion = CUR_BLOB_VERSION;//default value
hdr->reserved = NULL;//reserved, default value
LPDWORD key_size = (LPDWORD)&key[sizeof(BLOBHEADER)];
//*(DWORD *)(key + 0x14) = 0;
*key_size = AES_KEY_SIZE_;
if (!CryptImportKey(context->context, key, 32, 0, CRYPT_EXPORTABLE, &context->aes_hKey))
{
return context->last_error = GetLastError();
}
return context->last_error;
Works with Windows 7, this is not an exported key, but Fails on windows 8.1
If anyone has found a solution to this, it would help the entire internet.

dwDataLen param for CryptImportKey was set to 32, should be the total size of the byte array.
The issue is this works on windows 7 :\
sorry guys

Related

How can I create a bitmap from bytes array of png image in C++

Tried using the below code but it does not seem to work. The value of bm is null
BYTE imageData[] =
{
0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00,
0x10, 0x00, 0x00, 0x00, 0x0f, 0x04, 0x03, 0x00, 0x00, 0x00, 0x1f, 0x5d, 0x52, 0x1c, 0x00, 0x00, 0x00, 0x0f, 0x50,
0x4c, 0x54, 0x45, 0x7a, 0xdf, 0xfd, 0xfd, 0xff, 0xfc, 0x39, 0x4d, 0x52, 0x19, 0x16, 0x15, 0xc3, 0x8d, 0x76, 0xc7,
0x36, 0x2c, 0xf5, 0x00, 0x00, 0x00, 0x40, 0x49, 0x44, 0x41, 0x54, 0x08, 0xd7, 0x95, 0xc9, 0xd1, 0x0d, 0xc0, 0x20,
0x0c, 0x03, 0xd1, 0x23, 0x5d, 0xa0, 0x49, 0x17, 0x20, 0x4c, 0xc0, 0x10, 0xec, 0x3f, 0x53, 0x8d, 0xc2, 0x02, 0x9c,
0xfc, 0xf1, 0x24, 0xe3, 0x31, 0x54, 0x3a, 0xd1, 0x51, 0x96, 0x74, 0x1c, 0xcd, 0x18, 0xed, 0x9b, 0x9a, 0x11, 0x85,
0x24, 0xea, 0xda, 0xe0, 0x99, 0x14, 0xd6, 0x3a, 0x68, 0x6f, 0x41, 0xdd, 0xe2, 0x07, 0xdb, 0xb5, 0x05, 0xca, 0xdb,
0xb2, 0x9a, 0xdd, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82
};
HGLOBAL hMem = ::GlobalAlloc(GMEM_MOVEABLE, sizeof(imageData));
LPVOID pImage = ::GlobalLock(hMem);
memcpy(pImage, imageData, sizeof(imageData));
IStream* pStream = NULL;
::CreateStreamOnHGlobal(hMem, FALSE, &pStream);
Gdiplus::Bitmap* bm = Gdiplus::Bitmap::FromStream(pStream, true);
I can suggest 2 ways to convert PNG to BMP.
You can use third-party libraries. In case of opencv it will be something like that:
Mat image = imread("image.png", -1);
Mat image_bmp;
image.convertTo(image_bmp, CV_8UC3);
imwrite("image.bmp", image_bmp);
In VS you can use GDI+. The following code is runnable in my VS2019.
#include <windows.h>
#include <gdiplus.h>
#include <stdio.h>
#pragma comment (lib,"Gdiplus.lib")
using namespace Gdiplus;
INT GetEncoderClsid(const WCHAR* format, CLSID* pClsid); // helper function
INT main()
{
// Initialize GDI+.
GdiplusStartupInput gdiplusStartupInput;
ULONG_PTR gdiplusToken;
GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
CLSID encoderClsid;
Status stat;
Image* image = new Image(L"image.png");
// Get the CLSID of the encoder.
GetEncoderClsid(L"image/bmp", &encoderClsid);
stat = image->Save(L"image.bmp", &encoderClsid, NULL);
if (stat == Ok)
printf("Image was saved successfully\n");
else
printf("Failure: stat = %d\n", stat);
delete image;
GdiplusShutdown(gdiplusToken);
return 0;
}
int GetEncoderClsid(const WCHAR* format, CLSID* pClsid)
{
UINT num = 0; // number of image encoders
UINT size = 0; // size of the image encoder array in bytes
ImageCodecInfo* pImageCodecInfo = NULL;
GetImageEncodersSize(&num, &size);
if (size == 0)
return -1; // Failure
pImageCodecInfo = (ImageCodecInfo*)(malloc(size));
if (pImageCodecInfo == NULL)
return -1; // Failure
GetImageEncoders(num, size, pImageCodecInfo);
for (UINT j = 0; j < num; ++j)
{
if (wcscmp(pImageCodecInfo[j].MimeType, format) == 0)
{
*pClsid = pImageCodecInfo[j].Clsid;
free(pImageCodecInfo);
return j; // Success
}
}
free(pImageCodecInfo);
return -1; // Failure
}

How to decrypt AES cipherText with NCryptDecrypt on Windows

I'm trying to use Ncrypt.lib to encrypt plain text with AES and then decrypt it.
I use Ncrypt.lib because I want to use a persistent symetric key.
My problem is that the decryption works partially. Indeed, I don't have my first 16 bytes decrypted correctly.
#include <stdio.h>
#include <tchar.h>
#include <Windows.h>
#include <ncrypt.h>
#include <bcrypt.h>
void PrintBytes(
IN BYTE *pbPrintData,
IN DWORD cbDataLen) {
DWORD dwCount = 0;
for (dwCount = 0; dwCount < cbDataLen; dwCount++) {
printf("0x%02x, ", pbPrintData[dwCount]);
if (0 == (dwCount + 1) % 10) putchar('\n');
}
}
int main() {
BYTE plaintext[] =
{
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F
};
static const int plainTextLen = 48;
printf("PlainText:\n");
PrintBytes(plaintext, plainTextLen);
printf("\n");
LPCWSTR keyName = L"NCryptTest";
SECURITY_STATUS status;
NCRYPT_PROV_HANDLE hProvider;
NCRYPT_KEY_HANDLE hKey;
// Open storage provider
status = NCryptOpenStorageProvider(&hProvider, NULL, 0);
// Get stored key
status = NCryptOpenKey(hProvider, &hKey, keyName, 0, 0);
if (status == NTE_BAD_KEYSET) {
// Create key if it doesn't exist
status = NCryptCreatePersistedKey(hProvider, &hKey, BCRYPT_AES_ALGORITHM, keyName, 0, 0);
status = NCryptFinalizeKey(hKey, 0);
}
// Set the chaining mode to cipher feedback
LPCWSTR chainMode = BCRYPT_CHAIN_MODE_CFB;
status = NCryptSetProperty(hKey, NCRYPT_CHAINING_MODE_PROPERTY,
(PBYTE)chainMode, wcslen(chainMode) * 2 + 2, 0);
// Random iv but here, it's fixed
//char* iv = "0123456789abcdef";
//status = NCryptSetProperty(hKey, BCRYPT_INITIALIZATION_VECTOR,
//(PBYTE)iv, 16, 0);
// Get size of the cipher text
DWORD cbCipherText = 0;
status = NCryptEncrypt(hKey, plaintext, plainTextLen, NULL, NULL, 0,
&cbCipherText, 0);
PBYTE pbCipherText = NULL;
pbCipherText = (PBYTE)HeapAlloc(GetProcessHeap(), 0, cbCipherText);
if (pbCipherText == NULL) {
printf("Error! memory allocation failed\n");
}
// Encrypt
DWORD outlen = -1;
status = NCryptEncrypt(hKey, plaintext, plainTextLen, NULL, pbCipherText,
cbCipherText, &outlen, 0);
printf("CipherText:\n");
PrintBytes(pbCipherText, cbCipherText);
printf("\n");
// Get size of the plain text
DWORD cbPlainText = 0;
status = NCryptDecrypt(hKey, pbCipherText, cbCipherText, NULL, NULL, 0,
&cbPlainText, 0);
PBYTE pbPlainText = NULL;
pbPlainText = (PBYTE)HeapAlloc(GetProcessHeap(), 0, cbPlainText);
if (pbPlainText == NULL) {
printf("Error! memory allocation failed\n");
}
// Decrypt
outlen = -1;
status = NCryptDecrypt(hKey, pbCipherText, cbCipherText, NULL,
pbPlainText, cbPlainText, &outlen, 0);
printf("PlainText:\n");
PrintBytes(pbPlainText, cbPlainText);
printf("\n");
// Cleanup
NCryptFreeObject(hKey);
NCryptFreeObject(hProvider);
getchar();
return 0;
}
And the result is :
PlainText:
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09,
0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, 0x01, 0x02, 0x03,
0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d,
0x0e, 0x0f, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
CipherText:
0xc5, 0xdc, 0x7e, 0xde, 0x83, 0x35, 0xbc, 0x34, 0x27, 0x4b,
0xf9, 0xde, 0x40, 0x36, 0xeb, 0x6d, 0xaf, 0x51, 0x8c, 0x48,
0x69, 0xa0, 0x16, 0xfb, 0x6d, 0x80, 0x44, 0xea, 0x5c, 0x74,
0x27, 0x38, 0xf1, 0x20, 0xa3, 0x87, 0x65, 0xc3, 0xcf, 0x62,
0x94, 0x84, 0xc9, 0xcd, 0x55, 0x4c, 0x7b, 0x48,
PlainText:
0x1d, 0x52, 0x88, 0x1b, 0x0c, 0x01, 0x13, 0xed, 0xe0, 0x39,
0x1e, 0x96, 0x67, 0x39, 0x72, 0x38, 0x00, 0x01, 0x02, 0x03,
0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d,
0x0e, 0x0f, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
I suspect a initialisation vector problem but I don't know how to use it, simply with BCRYPT_INITIALIZATION_VECTOR ? or I must place the random iv in front of the plain text ?
Thanks for your help.
Answer in comment:
this is because every success call NCryptEncrypt or NCryptDecrypt change state of the hKey. so you can not use the same key. after you encrypt - you need again obtaining key for decrypt – RbMm
Thank you #RbMm !

CRC16 checksum calculation: which one is correct?

Currently I'm working on Modbus protocol, which requires a CRC checksum. I implemented three functions, generating different results:
CRC16_table: implemented based on modbus manual above page 114, this's a look-up-table way, but I didn't verify the table provided in the manual.
CRC16_modbus: implemented based on modbus manual page 112, this's a naive way
CRC16_origin: implemented based on this article and have the same result with this calculator at least.
My code is as follow:
#include <iostream>
#include <iomanip>
using namespace std;
static unsigned char auchCRCHi[] = {
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81,
0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01,
0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81,
0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01,
0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81,
0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01,
0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81,
0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01,
0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81,
0x40
};
static char auchCRCLo[] = {
0x00, 0xC0, 0xC1, 0x01, 0xC3, 0x03, 0x02, 0xC2, 0xC6, 0x06, 0x07, 0xC7, 0x05, 0xC5, 0xC4,
0x04, 0xCC, 0x0C, 0x0D, 0xCD, 0x0F, 0xCF, 0xCE, 0x0E, 0x0A, 0xCA, 0xCB, 0x0B, 0xC9, 0x09,
0x08, 0xC8, 0xD8, 0x18, 0x19, 0xD9, 0x1B, 0xDB, 0xDA, 0x1A, 0x1E, 0xDE, 0xDF, 0x1F, 0xDD,
0x1D, 0x1C, 0xDC, 0x14, 0xD4, 0xD5, 0x15, 0xD7, 0x17, 0x16, 0xD6, 0xD2, 0x12, 0x13, 0xD3,
0x11, 0xD1, 0xD0, 0x10, 0xF0, 0x30, 0x31, 0xF1, 0x33, 0xF3, 0xF2, 0x32, 0x36, 0xF6, 0xF7,
0x37, 0xF5, 0x35, 0x34, 0xF4, 0x3C, 0xFC, 0xFD, 0x3D, 0xFF, 0x3F, 0x3E, 0xFE, 0xFA, 0x3A,
0x3B, 0xFB, 0x39, 0xF9, 0xF8, 0x38, 0x28, 0xE8, 0xE9, 0x29, 0xEB, 0x2B, 0x2A, 0xEA, 0xEE,
0x2E, 0x2F, 0xEF, 0x2D, 0xED, 0xEC, 0x2C, 0xE4, 0x24, 0x25, 0xE5, 0x27, 0xE7, 0xE6, 0x26,
0x22, 0xE2, 0xE3, 0x23, 0xE1, 0x21, 0x20, 0xE0, 0xA0, 0x60, 0x61, 0xA1, 0x63, 0xA3, 0xA2,
0x62, 0x66, 0xA6, 0xA7, 0x67, 0xA5, 0x65, 0x64, 0xA4, 0x6C, 0xAC, 0xAD, 0x6D, 0xAF, 0x6F,
0x6E, 0xAE, 0xAA, 0x6A, 0x6B, 0xAB, 0x69, 0xA9, 0xA8, 0x68, 0x78, 0xB8, 0xB9, 0x79, 0xBB,
0x7B, 0x7A, 0xBA, 0xBE, 0x7E, 0x7F, 0xBF, 0x7D, 0xBD, 0xBC, 0x7C, 0xB4, 0x74, 0x75, 0xB5,
0x77, 0xB7, 0xB6, 0x76, 0x72, 0xB2, 0xB3, 0x73, 0xB1, 0x71, 0x70, 0xB0, 0x50, 0x90, 0x91,
0x51, 0x93, 0x53, 0x52, 0x92, 0x96, 0x56, 0x57, 0x97, 0x55, 0x95, 0x94, 0x54, 0x9C, 0x5C,
0x5D, 0x9D, 0x5F, 0x9F, 0x9E, 0x5E, 0x5A, 0x9A, 0x9B, 0x5B, 0x99, 0x59, 0x58, 0x98, 0x88,
0x48, 0x49, 0x89, 0x4B, 0x8B, 0x8A, 0x4A, 0x4E, 0x8E, 0x8F, 0x4F, 0x8D, 0x4D, 0x4C, 0x8C,
0x44, 0x84, 0x85, 0x45, 0x87, 0x47, 0x46, 0x86, 0x82, 0x42, 0x43, 0x83, 0x41, 0x81, 0x80,
0x40
};
unsigned short CRC16_table(char* message, int len)
{
unsigned char uchCRCHi = 0xFF;
unsigned char uchCRCLo = 0xFF;
unsigned uIndex;
while(len--)
{
uIndex = uchCRCHi ^ *message++;
uchCRCHi = uchCRCLo ^ auchCRCHi[uIndex];
uchCRCLo = auchCRCLo[uIndex];
}
return (((unsigned short)uchCRCHi << 8) | (unsigned short)uchCRCLo);
}
unsigned short CRC16_origin(char* message, int len)
{
const unsigned short generator = 0xA001;
unsigned short crc = 0;
for(int i = 0; i < len; ++i)
{
crc ^= (unsigned short)(message[i] << 8);
for(int b = 0; b < 8; ++b)
{
if((crc & 0x8000) != 0)
{
crc <<= 1;
crc ^= generator;
}
else
crc <<= 1;
}
}
return crc;
}
unsigned short CRC16_modbus(char* message, int len)
{
const unsigned short generator = 0xA001;
unsigned short crc = 0xFFFF;
for(int i = 0; i < len; ++i)
{
crc ^= (unsigned short)message[i];
for(int b = 0; b < 8; ++b)
{
if((crc & 1) != 0)
{
crc >>= 1;
crc ^= generator;
}
else
crc >>= 1;
}
}
return crc;
}
int main()
{
char message[] = {0x01, 0x06,0x00, 0x63, 0x04, 0x00};
int len = 6;
unsigned short temp1 = CRC16_table(message, len);
unsigned short temp2 = CRC16_origin(message, len);
unsigned short temp3 = CRC16_modbus(message, len);
cout<<hex<<temp1<<endl;
cout<<hex<<temp2<<endl;
cout<<hex<<temp3<<endl;
return 0;
}
Could anyone help me point out which one is correct? Based on what I read, I believe CRC16_origin is most likely right, but I'm still not sure because the other two are from an official manual; I'm stuck on this for almost a week, let me know if you have any advice, thanks!
Modbus uses an initial value of 0xffff.
Your third example uses an initial value of zero, poorly enforced in their illiterate example.
They aren't going to deliver the same results. Stick with the Modbus code.
Of the three approaches:
CRC16_table is correct, but only on a big endian CPU. In the old days a table-based approach would be the fastest approach, but it does not port between processors well.
CRC16_origin uses the wrong seed value. It computes a CRC for something, but not modbus.
CRC16_modbus is correct and portable.
With a modern processor the performance difference between the CRC16_table and CRC16_modbus approaches may not be worth the portability issues. Profile it and find out. On my PC they run neck-and-neck, which say go with the simplest and most portable. On an ARM or MSP430, who can say?
Experimental hack code:
#include <stdint.h>
#include <iostream>
#include <chrono>
uint16_t sizeeffect; // hack global to force execution of loops
static unsigned char auchCRCHi[] = {
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81,
0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01,
0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81,
0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01,
0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81,
0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01,
0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81,
0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01,
0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81,
0x40
};
static unsigned char auchCRCLo[] = {
0x00, 0xC0, 0xC1, 0x01, 0xC3, 0x03, 0x02, 0xC2, 0xC6, 0x06, 0x07, 0xC7, 0x05, 0xC5, 0xC4,
0x04, 0xCC, 0x0C, 0x0D, 0xCD, 0x0F, 0xCF, 0xCE, 0x0E, 0x0A, 0xCA, 0xCB, 0x0B, 0xC9, 0x09,
0x08, 0xC8, 0xD8, 0x18, 0x19, 0xD9, 0x1B, 0xDB, 0xDA, 0x1A, 0x1E, 0xDE, 0xDF, 0x1F, 0xDD,
0x1D, 0x1C, 0xDC, 0x14, 0xD4, 0xD5, 0x15, 0xD7, 0x17, 0x16, 0xD6, 0xD2, 0x12, 0x13, 0xD3,
0x11, 0xD1, 0xD0, 0x10, 0xF0, 0x30, 0x31, 0xF1, 0x33, 0xF3, 0xF2, 0x32, 0x36, 0xF6, 0xF7,
0x37, 0xF5, 0x35, 0x34, 0xF4, 0x3C, 0xFC, 0xFD, 0x3D, 0xFF, 0x3F, 0x3E, 0xFE, 0xFA, 0x3A,
0x3B, 0xFB, 0x39, 0xF9, 0xF8, 0x38, 0x28, 0xE8, 0xE9, 0x29, 0xEB, 0x2B, 0x2A, 0xEA, 0xEE,
0x2E, 0x2F, 0xEF, 0x2D, 0xED, 0xEC, 0x2C, 0xE4, 0x24, 0x25, 0xE5, 0x27, 0xE7, 0xE6, 0x26,
0x22, 0xE2, 0xE3, 0x23, 0xE1, 0x21, 0x20, 0xE0, 0xA0, 0x60, 0x61, 0xA1, 0x63, 0xA3, 0xA2,
0x62, 0x66, 0xA6, 0xA7, 0x67, 0xA5, 0x65, 0x64, 0xA4, 0x6C, 0xAC, 0xAD, 0x6D, 0xAF, 0x6F,
0x6E, 0xAE, 0xAA, 0x6A, 0x6B, 0xAB, 0x69, 0xA9, 0xA8, 0x68, 0x78, 0xB8, 0xB9, 0x79, 0xBB,
0x7B, 0x7A, 0xBA, 0xBE, 0x7E, 0x7F, 0xBF, 0x7D, 0xBD, 0xBC, 0x7C, 0xB4, 0x74, 0x75, 0xB5,
0x77, 0xB7, 0xB6, 0x76, 0x72, 0xB2, 0xB3, 0x73, 0xB1, 0x71, 0x70, 0xB0, 0x50, 0x90, 0x91,
0x51, 0x93, 0x53, 0x52, 0x92, 0x96, 0x56, 0x57, 0x97, 0x55, 0x95, 0x94, 0x54, 0x9C, 0x5C,
0x5D, 0x9D, 0x5F, 0x9F, 0x9E, 0x5E, 0x5A, 0x9A, 0x9B, 0x5B, 0x99, 0x59, 0x58, 0x98, 0x88,
0x48, 0x49, 0x89, 0x4B, 0x8B, 0x8A, 0x4A, 0x4E, 0x8E, 0x8F, 0x4F, 0x8D, 0x4D, 0x4C, 0x8C,
0x44, 0x84, 0x85, 0x45, 0x87, 0x47, 0x46, 0x86, 0x82, 0x42, 0x43, 0x83, 0x41, 0x81, 0x80,
0x40
};
unsigned short CRC16_table(char* message, int len)
{
unsigned char uchCRCHi = 0xFF;
unsigned char uchCRCLo = 0xFF;
unsigned uIndex;
while(len--)
{
uIndex = uchCRCHi ^ *message++;
uchCRCHi = uchCRCLo ^ auchCRCHi[uIndex];
uchCRCLo = auchCRCLo[uIndex];
}
return (((unsigned short)uchCRCHi << 8) | (unsigned short)uchCRCLo);
}
// CRC table I'm using for Wintell and PC linux
static const uint16_t lCRCTable[] =
{
0x0000, 0xC0C1, 0xC181, 0x0140, 0xC301, 0x03C0, 0x0280, 0xC241,
0xC601, 0x06C0, 0x0780, 0xC741, 0x0500, 0xC5C1, 0xC481, 0x0440,
0xCC01, 0x0CC0, 0x0D80, 0xCD41, 0x0F00, 0xCFC1, 0xCE81, 0x0E40,
0x0A00, 0xCAC1, 0xCB81, 0x0B40, 0xC901, 0x09C0, 0x0880, 0xC841,
0xD801, 0x18C0, 0x1980, 0xD941, 0x1B00, 0xDBC1, 0xDA81, 0x1A40,
0x1E00, 0xDEC1, 0xDF81, 0x1F40, 0xDD01, 0x1DC0, 0x1C80, 0xDC41,
0x1400, 0xD4C1, 0xD581, 0x1540, 0xD701, 0x17C0, 0x1680, 0xD641,
0xD201, 0x12C0, 0x1380, 0xD341, 0x1100, 0xD1C1, 0xD081, 0x1040,
0xF001, 0x30C0, 0x3180, 0xF141, 0x3300, 0xF3C1, 0xF281, 0x3240,
0x3600, 0xF6C1, 0xF781, 0x3740, 0xF501, 0x35C0, 0x3480, 0xF441,
0x3C00, 0xFCC1, 0xFD81, 0x3D40, 0xFF01, 0x3FC0, 0x3E80, 0xFE41,
0xFA01, 0x3AC0, 0x3B80, 0xFB41, 0x3900, 0xF9C1, 0xF881, 0x3840,
0x2800, 0xE8C1, 0xE981, 0x2940, 0xEB01, 0x2BC0, 0x2A80, 0xEA41,
0xEE01, 0x2EC0, 0x2F80, 0xEF41, 0x2D00, 0xEDC1, 0xEC81, 0x2C40,
0xE401, 0x24C0, 0x2580, 0xE541, 0x2700, 0xE7C1, 0xE681, 0x2640,
0x2200, 0xE2C1, 0xE381, 0x2340, 0xE101, 0x21C0, 0x2080, 0xE041,
0xA001, 0x60C0, 0x6180, 0xA141, 0x6300, 0xA3C1, 0xA281, 0x6240,
0x6600, 0xA6C1, 0xA781, 0x6740, 0xA501, 0x65C0, 0x6480, 0xA441,
0x6C00, 0xACC1, 0xAD81, 0x6D40, 0xAF01, 0x6FC0, 0x6E80, 0xAE41,
0xAA01, 0x6AC0, 0x6B80, 0xAB41, 0x6900, 0xA9C1, 0xA881, 0x6840,
0x7800, 0xB8C1, 0xB981, 0x7940, 0xBB01, 0x7BC0, 0x7A80, 0xBA41,
0xBE01, 0x7EC0, 0x7F80, 0xBF41, 0x7D00, 0xBDC1, 0xBC81, 0x7C40,
0xB401, 0x74C0, 0x7580, 0xB541, 0x7700, 0xB7C1, 0xB681, 0x7640,
0x7200, 0xB2C1, 0xB381, 0x7340, 0xB101, 0x71C0, 0x7080, 0xB041,
0x5000, 0x90C1, 0x9181, 0x5140, 0x9301, 0x53C0, 0x5280, 0x9241,
0x9601, 0x56C0, 0x5780, 0x9741, 0x5500, 0x95C1, 0x9481, 0x5440,
0x9C01, 0x5CC0, 0x5D80, 0x9D41, 0x5F00, 0x9FC1, 0x9E81, 0x5E40,
0x5A00, 0x9AC1, 0x9B81, 0x5B40, 0x9901, 0x59C0, 0x5880, 0x9841,
0x8801, 0x48C0, 0x4980, 0x8941, 0x4B00, 0x8BC1, 0x8A81, 0x4A40,
0x4E00, 0x8EC1, 0x8F81, 0x4F40, 0x8D01, 0x4DC0, 0x4C80, 0x8C41,
0x4400, 0x84C1, 0x8581, 0x4540, 0x8701, 0x47C0, 0x4680, 0x8641,
0x8201, 0x42C0, 0x4380, 0x8341, 0x4100, 0x81C1, 0x8081, 0x4040
};
// CRC table I'm using for Wintell and PC linux
uint16_t CRC16 (const uint8_t *datap, size_t len)
{
uint8_t loc;
uint16_t crc = 0xFFFF;
while (len--)
{
loc = *datap++ ^ crc;
crc >>= 8;
crc ^= lCRCTable[loc];
}
return crc;
}
unsigned short CRC16_modbus(const char* message, int len)
{
const unsigned short generator = 0xA001;
unsigned short crc = 0xFFFF;
for(int i = 0; i < len; ++i)
{
crc ^= (unsigned short)message[i];
for(int b = 0; b < 8; ++b)
{
if((crc & 1) != 0)
{
crc >>= 1;
crc ^= generator;
}
else
crc >>= 1;
}
}
return crc;
}
int main()
{
char message[] = "I am the very model of a modern major general.";
uint16_t a = CRC16((uint8_t *)message, sizeof(message));
uint16_t b = CRC16_modbus(message, sizeof(message));
uint16_t c = CRC16_table(message, sizeof(message));
if (a == b)
{
std::cout << "A-B Match"<< std::endl;
}
else
{
std::cout << a << std::endl;
std::cout << b << std::endl;
}
if (a == c)
{
std::cout << "A-C Match"<< std::endl;
}
else
{
std::cout << a << std::endl;
std::cout << c << std::endl;
}
int count = 10000000;
std::chrono::time_point<std::chrono::high_resolution_clock> start, end;
start = std::chrono::high_resolution_clock::now();
while (count--)
{
sizeeffect = CRC16((uint8_t *)message, sizeof(message));
}
end = std::chrono::high_resolution_clock::now();
std::cout << "Table took " << std::chrono::duration_cast<std::chrono::microseconds>(end-start).count() << "\n";
count = 10000000;
start = std::chrono::high_resolution_clock::now();
while (count--)
{
sizeeffect = CRC16((uint8_t *)message, sizeof(message));
}
end = std::chrono::high_resolution_clock::now();
std::cout << "Calc took " << std::chrono::duration_cast<std::chrono::microseconds>(end-start).count() << "\n";
}
Typical output:
A-B Match
5874
61974
Table took 900167
Calc took 892935
Besides other answer, I should use unsigned char* as the first parameter instead of char* in my functions because when I convert it to unsigned short, if it's char * and MSB is 1, it will add ff for the high byte, which is obviously wrong!
Thanks everyone here! Solved!

I have got data from Wireshark, in C array form, and now i m getting trouble to decode it in normal form

Below is the data i've got from wireshark and not able to crack it.
char peer0_13[] = {
0x02, 0xb6, 0x8d, 0x7c, 0x7a, 0x56, 0x2f, 0x06,
0xde, 0x6c, 0xd9, 0x55, 0x78, 0xd3, 0x12, 0xf9,
0xe5, 0x4a, 0x57, 0x02, 0xdc, 0xb7, 0x1c, 0x75,
0x5b, 0x9c, 0x51, 0x51, 0x3e, 0x2a, 0x3a, 0x9a,
0xca, 0x50, 0xeb, 0x40, 0x28, 0x05, 0x00, 0xa0,
0x14, 0x02, 0x80, 0x50, 0x0a, 0x01, 0x40, 0x28,
0x05, 0x00, 0xa0, 0x14, 0x02, 0x80, 0x50, 0x0a,
0x01, 0x40, 0x28, 0x05, 0x00, 0xa0, 0x14, 0x02,
0x80, 0x50, 0x0a, 0x01, 0x40, 0x28, 0x05, 0x00,
0xa0, 0x14, 0x02, 0x80, 0x50, 0x0a, 0x01, 0x40,
0x28, 0x05, 0x00, 0xa0, 0x14, 0x02, 0x80, 0x50,
0x0a, 0x01, 0x40, 0x28, 0x05, 0x00, 0xa0, 0x14,
0x02, 0x80, 0x50, 0x0a, 0x01, 0x40, 0x28, 0x05,
0x00, 0xa0, 0x14, 0x02, 0x80, 0x50, 0x0a, 0x01,
0x40, 0x28, 0x05, 0x00, 0xa0, 0x14, 0x02, 0x80,
0x50, 0x0a, 0x01, 0x40, 0x28, 0x05, 0x00, 0xa0,
0x14, 0x02, 0x80, 0x50, 0x0a, 0x01, 0x40, 0x28,
0x05, 0x00, 0xa0, 0x14, 0x02, 0x80, 0x50, 0x0a,
0x01, 0x40, 0x28, 0x05, 0x00, 0xa0, 0x14, 0x02,
0x80, 0x50, 0x0a, 0x01, 0x40, 0x28, 0x05, 0x00,
0xa0, 0x3f, 0xff, 0xd9 };
I am not getting that how to convert this data into plain text / string so that it is easy to read.
Here are some manual tricks i've applied to get in plain text.
(First solution is not working properly, as it gives me garbage values).
#1.
for (int i = 0; i <= sizeof (peer0_13); i++)
{
printf ("%c",peer0_13[i]);
}
#2.
cout << peer0_13 << endl ;
#3.
printf ("%s\n", peer0_13);
Please help to convert this data into normal string.
Any help would be grateful. :)
You can not convert the above char vector into String since I see 0x00 at the end of the line before the last. char[] is a String but if you need to copy its data into a normal string then you have to copy all of the chars to an empty string one by one using a loop, but the 0x00 value will truncate the string.
Note that in your first loop you need to change the condition to i < sizeof (peer0_13) and eleminate the equal sign which raises an index out of bound error.
If you meant to read the char array as a String that a human could understand and you need to just print it out, You have to exclude the null characters (0x00) while copying it into a String or erase null character from your array and simply use %s with a printf.

This may be due to a corruption of the heap, which indicates a bug in testcrypto.exe or any of the DLLs it has loaded

#pragma once
#include <string>
#include <vector>
#include <stdint.h>
class PasswordCrypt
{
public:
PasswordCrypt(std::vector<uint8_t> buffer);
~PasswordCrypt(void);
void PassCrypto(std::vector<uint8_t> buffer);
const std::vector<uint8_t>& Encrypt(const std::vector<uint8_t>& buffer);
const std::vector<uint8_t>& Decrypt(std::vector<uint8_t>& buffer);
private:
uint8_t* key;
};
--------------------------------------------------------------------------------------
#include "PasswordCrypt.h"
PasswordCrypt::PasswordCrypt(std::vector<uint8_t> buffer)
{
this->key = new uint8_t[200];
int sum = 0;
for (int i = 0 ; i< buffer.size() ;i++)
sum += buffer[i];
srand(sum);
uint8_t hash[0x10];
for (int i = 0; i < 0x10; i++)
hash[i] =(uint8_t)rand();
for (int i = 1; i < 0x100; i++)
{
key[i * 2] = (uint8_t)i;
key[(i * 2) + 1] = (uint8_t)(i ^ hash[i & 0x0F]);
}
for (int i = 1; i < 0x100; i++)
for (int j = 1 + i; j < 0x100; j++)
if (key[(i * 2) + 1] < key[(j * 2) + 1])
{
key[i * 2] ^= key[j * 2];
key[j * 2] ^= key[i * 2];
key[i * 2] ^= key[j * 2];
key[(i * 2) + 1] ^= key[(j * 2) + 1];
key[(j * 2) + 1] ^= key[(i * 2) + 1];
key[(i * 2) + 1] ^= key[(j * 2) + 1];
}
}
PasswordCrypt::~PasswordCrypt(void)
{
delete[] this->key;
}
const uint8_t scanCodeToVirtualKeyMap[] =
{
0x00, 0x1B, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0xBD, 0xBB, 0x08, 0x09,
0x51, 0x57, 0x45, 0x52, 0x54, 0x59, 0x55, 0x49, 0x4F, 0x50, 0xDB, 0xDD, 0x0D, 0x11, 0x41, 0x53,
0x44, 0x46, 0x47, 0x48, 0x4A, 0x4B, 0x4C, 0xBA, 0xC0, 0xDF, 0x10, 0xDE, 0x5A, 0x58, 0x43, 0x56,
0x42, 0x4E, 0x4D, 0xBC, 0xBE, 0xBF, 0x10, 0x6A, 0x12, 0x20, 0x14, 0x70, 0x71, 0x72, 0x73, 0x74,
0x75, 0x76, 0x77, 0x78, 0x79, 0x90, 0x91, 0x24, 0x26, 0x21, 0x6D, 0x25, 0x0C, 0x27, 0x6B, 0x23,
0x28, 0x22, 0x2D, 0x2E, 0x2C, 0x00, 0xDC, 0x7A, 0x7B, 0x0C, 0xEE, 0xF1, 0xEA, 0xF9, 0xF5, 0xF3,
0x00, 0x00, 0xFB, 0x2F, 0x7C, 0x7D, 0x7E, 0x7F, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0xED,
0x00, 0xE9, 0x00, 0xC1, 0x00, 0x00, 0x87, 0x00, 0x00, 0x00, 0x00, 0xEB, 0x09, 0x00, 0xC2, 0x00,
};
const uint8_t virtualKeyToScanCodeMap[] =
{
0x00, 0x00, 0x00, 0x46, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x0F, 0x00, 0x00, 0x4C, 0x1C, 0x00, 0x00,
0x2A, 0x1D, 0x38, 0x00, 0x3A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
0x39, 0x49, 0x51, 0x4F, 0x47, 0x4B, 0x48, 0x4D, 0x50, 0x00, 0x00, 0x00, 0x54, 0x52, 0x53, 0x63,
0x0B, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x1E, 0x30, 0x2E, 0x20, 0x12, 0x21, 0x22, 0x23, 0x17, 0x24, 0x25, 0x26, 0x32, 0x31, 0x18,
0x19, 0x10, 0x13, 0x1F, 0x14, 0x16, 0x2F, 0x11, 0x2D, 0x15, 0x2C, 0x5B, 0x5C, 0x5D, 0x00, 0x5F,
0x52, 0x4F, 0x50, 0x51, 0x4B, 0x4C, 0x4D, 0x47, 0x48, 0x49, 0x37, 0x4E, 0x00, 0x4A, 0x53, 0x35,
0x3B, 0x3C, 0x3D, 0x3E, 0x3F, 0x40, 0x41, 0x42, 0x43, 0x44, 0x57, 0x58, 0x64, 0x65, 0x66, 0x67,
0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x45, 0x46, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x2A, 0x36, 0x1D, 0x1D, 0x38, 0x38, 0x6A, 0x69, 0x67, 0x68, 0x65, 0x66, 0x32, 0x20, 0x2E, 0x30,
0x19, 0x10, 0x24, 0x22, 0x6C, 0x6D, 0x6B, 0x21, 0x00, 0x00, 0x27, 0x0D, 0x33, 0x0C, 0x34, 0x35,
0x28, 0x73, 0x7E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1A, 0x56, 0x1B, 0x2B, 0x29,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x71, 0x5C, 0x7B, 0x00, 0x6F, 0x5A, 0x00,
0x00, 0x5B, 0x00, 0x5F, 0x00, 0x5E, 0x00, 0x00, 0x00, 0x5D, 0x00, 0x62, 0x00, 0x00, 0x00, 0x00
};
const std::vector<uint8_t>& PasswordCrypt::Encrypt(const std::vector<uint8_t>& buffer)
{
std::vector<uint8_t> result(buffer.size());
for (int i = 0; i < buffer.size(); i++)
{
bool upper = false;
if (buffer[i] == 0) break;
else
{
uint8_t b =this->key[buffer[i] * 2];
if (b > 0x80)
{
b = (uint8_t)(this->key[buffer[i] * 2] - 0x80);
upper = true;
}
result[i] += scanCodeToVirtualKeyMap[b];
}
if (!upper && result[i] >= 'A' && result[i] <= 'Z') result[i] += 'a' - 'A';
}
return result;
}
const std::vector<uint8_t>& PasswordCrypt::Decrypt(std::vector<uint8_t>& buffer)
{
std::vector<uint8_t> result(buffer.size(), 0);
for (int j = 0; j < buffer.size(); j++)
{
uint8_t c = buffer[j];
if (buffer[j] >= 'a' && buffer[j] <= 'z')
buffer[j] -= 'a' - 'A';
uint8_t d = virtualKeyToScanCodeMap[buffer[j]];
if (c >= 'A' && c <= 'Z')
d += 0x80;
for (uint8_t i = 0; i <= 255; i++)
{
uint8_t b = (uint8_t)this->key[i * 2];
if (b == d)
{
result[j] = i;
break;
}
}
}
return result;
}
---------------------------------------------------------------------------------------
#include <iostream>
#include <Windows.h>
#include <string>
#include <stdint.h>
#include "PasswordCrypt.h"
#include <iomanip>
using namespace std;
void output_hex(std::ostream& out, std::vector<uint8_t>& data) {
for (std::vector<uint8_t>::iterator i=data.begin();i<data.end();i++)
out << std::hex
<< std::setw(2)
<< std::setfill('0')
<< static_cast<int>(data[*i])
<< " ";
out << endl;
}
int main()
{
std::string test="Hellow World!";
std::vector<uint8_t> buf(test.begin(), test.end());
PasswordCrypt dec(buf);
//output_hex(cout, buf);
std::vector<uint8_t> enced = dec.Encrypt(buf);
//output_hex(cout, enced);
std::vector<uint8_t> deced = dec.Decrypt(enced);
//output_hex(cout, deced);
system("pause");
return 0;
}
Error:
Windows has triggered a breakpoint in
testcrypto.exe.
This may be due to a corruption of the
heap, which indicates a bug in
testcrypto.exe or any of the DLLs it
has loaded.
This may also be due to the user
pressing F12 while testcrypto.exe has
focus.
You have a classic buffer overrun. Here you allocate 200 bytes for key:
this->key = new uint8_t[200];
Here, however:
for (int i = 1; i < 0x100; i++)
{
key[i * 2] = (uint8_t)i;
You (attempt to) write to k[2] through key[2 * 0x100]. 2 * 0x100 is 0x200, which is 512 in decimal. It would appear that where you allocate the buffer, you should really allocate 0x200 elements.
Some of the other code looks like it tries to access key[0x200] -- to make that work, you'd want/need to allocate 0x201 elements (0x200 elements will run from key[0] through key[0x1ff] inclusive).
Edit: doing a bit more looking, it gets even worse. Perhaps putting these three lines next to each other will make the next problem more obvious:
const std::vector<uint8_t>& PasswordCrypt::Encrypt(const std::vector<uint8_t>& buffer)
{
std::vector<uint8_t> result(buffer.size());
[ ...]
return result;
You're returning a reference to a local variable, so the caller receives a dangling reference.
j < 0x100;
0x100 is not the same as 100. It's 256. And your key array is only 200 elements long.
You then go off and try to access key[j * 2], which is way off the end of the array, trampling all over random bits of memory. That's your problem.
Your other problem is using xor-swapping instead of something more readable - while you might think it's a "neat trick", it really isn't. It makes things much less legible and doesn't provide any meaningful performance benefit.