#include "stdafx.h"
#include "Crypter.h"
CCrypter::CCrypter()
{
}
CCrypter::~CCrypter()
{
}
int CCrypter::Encrypt(BYTE *pbIn, int iInOffset, int iInLen, BYTE *pbKey, BYTE *pbRet, int iRetLen) const
{
int iPos = (iInLen + 0x0A) % 8;
if( iPos != 0 )
iPos = 8 - iPos;
int iOutLen = iInLen + iPos + 10;
if( iRetLen < iOutLen )
return -1;
BYTE* pbPlain = (BYTE*)malloc(8);
BYTE* pbPrePlain = (BYTE*)malloc(8);
int iCrypt = 0;
int iPreCrypt = 0;
BYTE* pbOut = (BYTE*)malloc(iOutLen);
pbPlain[0] = (BYTE)((rand() & 0xF8) | iPos);
for( int i = 1; i <= iPos; i++ )
pbPlain[i] = (BYTE)(rand() & 0xFF);
iPos++;
for( i = 0; i < 8; i++ )
pbPrePlain[i] = 0x0;
bool bHeader = true;
int iPadding = 1;
while( iPadding <= 2 )
{
if( iPos < 8 )
{
pbPlain[iPos++] = (BYTE)(rand() & 0xFF);
iPadding++;
}
if( iPos == 8 )
{
Encrypt8Bytes(bHeader, pbPlain, pbPrePlain, pbKey, iCrypt, iPreCrypt, pbOut);
iPos = 0;
bHeader = false;
}
}
i = iInOffset;
while( iInLen > 0 )
{
if( iPos < 8 )
{
pbPlain[iPos++] = pbIn[i++];
iInLen--;
}
if( iPos == 8 )
{
Encrypt8Bytes(bHeader, pbPlain, pbPrePlain, pbKey, iCrypt, iPreCrypt, pbOut);
iPos = 0;
bHeader = false;
}
}
iPadding = 1;
while( iPadding <= 7 )
{
if( iPos < 8 )
{
pbPlain[iPos++] = 0x0;
iPadding++;
}
if( iPos == 8 )
{
Encrypt8Bytes(bHeader, pbPlain, pbPrePlain, pbKey, iCrypt, iPreCrypt, pbOut);
iPos = 0;
bHeader = false;
}
}
memcpy(pbRet, pbOut, iOutLen);
free(pbOut);
free(pbPrePlain);
free(pbPlain);
return iOutLen;
}
int CCrypter::Decrypt(BYTE *pbIn, int iInOffset, int iInLen, BYTE *pbKey, BYTE *pbRet, int iRetLen) const
{
if( (iInLen % 8 != 0) || (iInLen < 16) )
return -1;
BYTE* pbPrePlain = (BYTE*)malloc(8);
int iCrypt = 0;
int iPreCrypt = 0;
int iCount;
int iPos;
Decipher(pbIn, iInOffset, pbKey, pbPrePlain);
iPos = pbPrePlain[0] & 0x7;
iCount = iInLen - iPos - 10;
if( iCount < 0 )
{
free(pbPrePlain);
return -1;
}
int iOutLen = iCount;
if( iRetLen < iCount )
{
free(pbPrePlain);
return -1;
}
BYTE* pbOut = (BYTE*)malloc(iOutLen);
BYTE* pbM = (BYTE*)malloc(iInOffset + 8);
for( int i = 0; i < 8; i++ )
pbM[iInOffset + i] = 0;
iPreCrypt = 0;
iCrypt = 8;
int iContextStart = 8;
iPos++;
int iPadding = 1;
while( iPadding <= 2 )
{
if( iPos < 8 )
{
iPos++;
iPadding++;
}
if( iPos == 8 )
{
free(pbM);
pbM = (BYTE*)malloc(iInLen);
memcpy(pbM, pbIn, iInLen);
Decrypt8Bytes(pbPrePlain, pbKey, iContextStart, iCrypt, iPreCrypt, pbIn, iInOffset, iInLen);
iPos = 0;
}
}
i = 0;
while( iCount != 0 )
{
if( iPos < 8 )
{
pbOut[i] = (BYTE)(pbM[iInOffset + iPreCrypt + iPos] ^ pbPrePlain[iPos]);
i++;
iCount--;
iPos++;
}
if( iPos == 8 )
{
free(pbM);
pbM = (BYTE*)malloc(iInLen);
memcpy(pbM, pbIn, iInLen);
iPreCrypt = iCrypt - 8;
Decrypt8Bytes(pbPrePlain, pbKey, iContextStart, iCrypt, iPreCrypt, pbIn, iInOffset, iInLen);
iPos = 0;
}
}
for( iPadding = 1; iPadding < 8; iPadding++ )
{
if( iPos < 8 )
{
if( (pbM[iInOffset + iPreCrypt + iPos] ^ pbPrePlain[iPos]) != 0 )
{
free(pbOut);
free(pbPrePlain);
free(pbM);
return -1;
}
iPos++;
}
if( iPos == 8 )
{
free(pbM);
pbM = (BYTE*)malloc(iInLen);
memcpy(pbM, pbIn, iInLen);
iPreCrypt = iCrypt;
Decrypt8Bytes(pbPrePlain, pbKey, iContextStart, iCrypt, iPreCrypt, pbIn, iInOffset, iInLen);
iPos = 0;
}
}
memcpy(pbRet, pbOut, iOutLen);
free(pbOut);
free(pbM);
free(pbPrePlain);
return iOutLen;
}
void CCrypter::Encrypt8Bytes(bool bHeader, BYTE *pbPlain, BYTE *pbPrePlain, BYTE *pbKey, int &iCrypt, int &iPreCrypt, BYTE *pbOut) const
{
for( int iPos = 0; iPos < 8; iPos++ )
{
if( bHeader )
pbPlain[iPos] ^= pbPrePlain[iPos];
else
pbPlain[iPos] ^= pbOut[iPreCrypt + iPos];
}
BYTE* pbCrypted = (BYTE*)malloc(8);
Encipher(pbPlain, pbKey, pbCrypted);
memcpy(pbOut + iCrypt, pbCrypted, 8);
free(pbCrypted);
for( iPos = 0; iPos < 8; iPos++ )
pbOut[iCrypt + iPos] ^= pbPrePlain[iPos];
memcpy(pbPrePlain, pbPlain, 8);
iPreCrypt = iCrypt;
iCrypt += 8;
}
void CCrypter::Decrypt8Bytes(BYTE *pbPrePlain, BYTE *pbKey, int &iContextStart, int &iCrypt, int &iPreCrypt, BYTE *pbIn, int iInOffset, int iInLen) const
{
for( int iPos = 0; iPos < 8; iPos++ )
{
if( iContextStart + iPos >= iInLen )
return;
pbPrePlain[iPos] ^= pbIn[iInOffset + iCrypt + iPos];
}
BYTE* pbDecrypted = (BYTE*)malloc(8);
Decipher(pbPrePlain, 0, pbKey, pbDecrypted);
memcpy(pbPrePlain, pbDecrypted, 8);
free(pbDecrypted);
iContextStart += 8;
iCrypt += 8;
}
void CCrypter::Encipher(BYTE *pbIn, BYTE *pbKey, BYTE *pbRet) const
{
unsigned long y, z;
unsigned long a, b, c, d;
CRYPTER_GET_DWORD(pbIn, y);
CRYPTER_GET_DWORD(pbIn, z);
CRYPTER_GET_DWORD(pbKey, a);
CRYPTER_GET_DWORD(pbKey, b);
CRYPTER_GET_DWORD(pbKey, c);
CRYPTER_GET_DWORD(pbKey, d);
unsigned __int64 ui64Sum = 0;
unsigned long ulDelta = 0x9E3779B9;
ulDelta &= 0xFFFFFFFF;
int iLoop = 0x10;
while( iLoop-- > 0 )
{
ui64Sum += ulDelta;
ui64Sum &= 0xFFFFFFFFF;
unsigned __int64 y1, y2, y3, z1, z2, z3;
y1 = (z << 4) + a;
y2 = z + ui64Sum;
y3 = (z / 32) + b;
y += y1 ^ y2 ^ y3;
y &= 0xFFFFFFFF;
z1 = (y << 4) + c;
z2 = y + ui64Sum;
z3 = (y / 32) + d;
z += z1 ^ z2 ^ z3;
z &= 0xFFFFFFFF;
}
CRYPTER_PUT_DWORD(pbRet, (int)y);
CRYPTER_PUT_DWORD(pbRet, (int)z);
}
void CCrypter::Decipher(BYTE *pbIn, int iInOffset, BYTE *pbKey, BYTE *pbRet) const
{
pbIn += iInOffset;
unsigned long y, z;
unsigned long a, b, c, d;
CRYPTER_GET_DWORD(pbIn, y);
CRYPTER_GET_DWORD(pbIn, z);
CRYPTER_GET_DWORD(pbKey, a);
CRYPTER_GET_DWORD(pbKey, b);
CRYPTER_GET_DWORD(pbKey, c);
CRYPTER_GET_DWORD(pbKey, d);
unsigned __int64 ui64Sum = 0xE3779B90;
unsigned long ulDelta = 0x9E3779B9;
ui64Sum &= 0xFFFFFFFF;
ulDelta &= 0xFFFFFFFF;
int iLoop = 0x10;
while( iLoop-- > 0 )
{
unsigned __int64 y1, y2, y3, z1, z2, z3;
z1 = (y << 4) + c;
z2 = y + ui64Sum;
z3 = (y / 32) + d;
z -= z1 ^ z2 ^ z3;
z &= 0xFFFFFFFF;
y1 = (z << 4) + a;
y2 = z + ui64Sum;
y3 = (z / 32) + b;
y -= y1 ^ y2 ^ y3;
y &= 0xFFFFFFFF;
ui64Sum -= ulDelta;
ui64Sum &= 0xFFFFFFFF;
}
CRYPTER_PUT_DWORD(pbRet, (int)y);
CRYPTER_PUT_DWORD(pbRet, (int)z);
}