本着学习的目的逆向了一个程序,大家看看这是什么加密算法?
int __stdcall GetLastNotZero(LPDWORD lpData, DWORD nMax)
{
int iIndex;
iIndex = nMax;
while(iIndex--)
{
if (lpData[iIndex])
break;
}
return iIndex+1;
}
void memcpy_reverse(LPBYTE lpDest,LPBYTE lpSrc,DWORD dwSize)
{
for(DWORD i=0;i<dwSize;i++)
lpDest[i]=lpSrc[dwSize-i-1];
}
#define KEYSIZE 128
#define KEYCOUNT 32
int CalcJiaocha(DWORD Dword1, DWORD Dword2, LPDWORD Out1, LPDWORD Out2)
{
unsigned int sumjiaocha; // eax@1
unsigned int v5; // esi@1
unsigned int high2; // esi@1
int high2xlow1; // ecx@1
unsigned int sumHighWord; // eax@3
DWORD v9; // ecx@3
int result; // eax@5
high2 = Dword2 >> 16;
high2xlow1 = high2 * (WORD)Dword1;
*Out1 = (unsigned __int16)Dword2 * (unsigned __int16)Dword1;// 两个dword的低16位相乘
sumjiaocha = high2xlow1 + (unsigned __int16)(Dword1 >> 16) * (unsigned __int16)Dword2;// 两个dword高低16位交叉相乘并相加
*Out2 = high2 * (unsigned __int16)(Dword1 >> 16);// 两个dword的高16位相乘
v5 = 0x10000u;
if ( sumjiaocha >= high2xlow1 )
v5 = 0; // 如果加high2low1时没有溢出,则置v5=0;反之溢出则相当于高16位+1
v9 = sumjiaocha << 16;
*Out1 += sumjiaocha << 16; // out1加上"交叉乘积和"的低16位
sumHighWord = sumjiaocha >> 16;
if ( *Out1 < v9 )
++v5; // 溢出则+1
result = v5 + sumHighWord;
*Out2 += result; // Out2加上交叉乘积的高16位,再加一个可能为0、1、0x10000、0x10001的变量
return result;
}
int CalcBufferByNumAndKey(LPDWORD Key, LPDWORD lpBuf1End, DWORD KeyCount, DWORD dwValue)
{
DWORD v7; // edx@5
int v9; // ebx@5
DWORD CalcValue2; // [sp+4h] [bp-14h]@5
DWORD CalcValue1; // [sp+8h] [bp-10h]@5
int v18= 0;
if ( dwValue )
{
for(DWORD i=0;i<KeyCount;i++)
{
CalcJiaocha(dwValue,Key[i],&CalcValue1,&CalcValue2);
v9=lpBuf1End[i]-v18;
lpBuf1End[i]=v9-CalcValue1;
/*if(i==0x1e && dwValue==0x3fab1de4)
{
__asm int 3;
}*/
printf("\t CalcValue1=%8x CalcValue2=%8x\n",CalcValue1,CalcValue2);
v7 = -1 - v18 < (DWORD)v9;
if ( lpBuf1End[i]> (0xffffffff - (DWORD)CalcValue1) )
++v7;
v18 = CalcValue2 + v7;
}
}
return v18;
}
signed int __stdcall CalcsubBuffer(LPDWORD Buf1End, LPDWORD Key, int KeyCount)
{
signed int result=0; // eax@1
DWORD dwBufValue; // ecx@3
int Value; // ecx@4
for(DWORD i=0;i<KeyCount;i++)
{
dwBufValue = Buf1End[i] - result;
if ( dwBufValue == (DWORD)-1 )
{
Value = -1 - Key[i];
}
else
{
Value = dwBufValue - Key[i];
result = 0;
if ( Value > (DWORD)-1 - Key[i] )
result = 1;
}
Buf1End[i] = Value;
}
return result;
}
signed int __stdcall CompareDwordArr_MustLessZero(LPDWORD DataBuf, LPDWORD KeyBuf, int Count)
{
signed int result=0; // eax@6
while(Count--)
{
if(DataBuf[Count]>KeyBuf[Count])
return 1;
if(DataBuf[Count]<KeyBuf[Count])
return -1;
}
return result;
}
void CombineBuffer(LPDWORD BigBuf,LPDWORD SrcBuf1,LPDWORD SrcBuf2,DWORD dwKeyCount)
{
DWORD ThisBuf[66]={0};
DWORD dwBuf1Count=GetLastNotZero(SrcBuf1,dwKeyCount);
DWORD dwBuf2Count=GetLastNotZero(SrcBuf2,dwKeyCount);
for(DWORD i=0;i<dwBuf1Count;i++)
{
DWORD dwLastValue=0;
if(SrcBuf1[i])
{
DWORD v20,v17,v12;
for(DWORD j=0;j<dwBuf2Count;j++)
{ // 指向lpdwTmpBuf的dword依次和data的每个dword计算,
// 每计算一次,ThisBufferLoop1指向的dword加上一次结果
// 外层循环lpdwTmpBuf加1,每一次外层循环ThisBuffer1都被改变
CalcJiaocha(SrcBuf1[i], SrcBuf2[j],&v20, (LPDWORD)&v17);
v12=0;
ThisBuf[i+j] += dwLastValue;
if(ThisBuf[i+j]<dwLastValue)
v12++;
ThisBuf[i+j] += v20;
if ( ThisBuf[i+j] < v20 )
++v12;
dwLastValue = v17 + v12;
}
}
ThisBuf[i+dwBuf2Count]+=dwLastValue;
}
memcpy(BigBuf,ThisBuf,dwKeyCount*2*4);
}
void DecryptOnce(LPBYTE OutBuf,LPBYTE SrcBuf1,LPBYTE SrcBuf2,LPDWORD Key,DWORD dwKeyCount)
{
DWORD BigBuf[66]={0};
DWORD KeyHighNotZeroBit=32;//应该由Key中的cf3892e1计算得来
DWORD FromHighZerobit=0;
DWORD dwSeedValue;
DWORD KeyConvertLastValue=((LPDWORD)Key)[dwKeyCount-1];//调试一下,应该是cf3892e1
DWORD KeyConvertLastValuePlus1=KeyConvertLastValue+1;
DWORD KeyLastValuePlus1HighWord=KeyConvertLastValuePlus1>>16;
LPDWORD lpBuf1End,lpBuf2End;
lpBuf1End=BigBuf+dwKeyCount;
lpBuf2End=BigBuf+dwKeyCount*2;
CombineBuffer(BigBuf,(LPDWORD)SrcBuf1,(LPDWORD)SrcBuf2,dwKeyCount);
for(DWORD LoopCount=0;LoopCount<=dwKeyCount;LoopCount++)
{
DWORD dwConvertBuf2Value=*lpBuf2End;
DWORD dwVar19;
//CalcJiaocha(dwConvertBuf2Value,KeyConvertLastValuePlus1,&dwTestOut1,&dwTestOut2);
//printf("Test1=%8x Test2=%8x\n",dwTestOut1,dwTestOut2);
if(KeyLastValuePlus1HighWord==0xffff)
{//cf38 这个条件应该不走
dwVar19=dwConvertBuf2Value>>16;
}else
{
dwVar19=dwConvertBuf2Value/(KeyLastValuePlus1HighWord+1);
}
dwVar19 &= 0xffff;//也许是不必要的
DWORD dwVar22,dwVar23;
dwVar23=(dwVar19*(WORD)KeyConvertLastValuePlus1)<<16;
dwVar22=*(lpBuf2End-1)-dwVar23;
if(dwVar22>(((DWORD)-1)-dwVar23))
dwConvertBuf2Value--;
dwConvertBuf2Value-=dwVar19*KeyLastValuePlus1HighWord + ((dwVar19*(WORD)KeyConvertLastValuePlus1)>>16);
while( dwConvertBuf2Value > KeyLastValuePlus1HighWord
|| dwConvertBuf2Value ==KeyLastValuePlus1HighWord
&& dwVar22>=(KeyConvertLastValuePlus1<<16))
{
dwVar22-=(KeyConvertLastValuePlus1<<16);
if ( dwVar22 > (DWORD)(-1) - (KeyConvertLastValuePlus1 << 16) )
--dwConvertBuf2Value;
dwConvertBuf2Value -= KeyLastValuePlus1HighWord;
++dwVar19;
}
DWORD v24,v25,v26,v27,v28,v29;
if (KeyLastValuePlus1HighWord == 0xffff )
v24 = dwConvertBuf2Value;
else
v24 = ((dwConvertBuf2Value << 16) + (dwVar22 >> 16))
/ ((unsigned int)(WORD)KeyLastValuePlus1HighWord + 1);
v27 = (unsigned __int16)v24 * (unsigned __int16)KeyConvertLastValuePlus1;
v25 = (unsigned __int16)KeyLastValuePlus1HighWord * (unsigned __int16)v24;
v26 = dwVar22 - v27;
if ( v26 > ((DWORD)-1 - v27) )
--dwConvertBuf2Value;
v28 = v26 - (v25 << 16);
if ( v28 > -1 - (v25 << 16) )
--dwConvertBuf2Value;
v29 = dwConvertBuf2Value - (v25 >> 16);
while ( v29 || v28 >= KeyConvertLastValuePlus1 )
{
v28 -= KeyConvertLastValuePlus1;
if ( v28 > -1 - KeyConvertLastValuePlus1 )
--v29;
++v24;
}
//这个数计算得来之不易啊
dwSeedValue = (unsigned __int16)v24 + ((unsigned __int16)dwVar19 << 16);
for (DWORD i = CalcBufferByNumAndKey(Key,lpBuf1End,dwKeyCount,dwSeedValue);
;i = CalcsubBuffer(lpBuf1End, Key, dwKeyCount) )// 大概是内存与key内存值相减
{ // CalcsubBuffer返回0或1
printf("%02d. Seed=%8x i=%-8x [%08x %08x ~ %08x] %8x\n",LoopCount,dwSeedValue,i,
lpBuf1End[0],lpBuf1End[1],lpBuf1End[dwKeyCount-1],lpBuf1End[dwKeyCount]);
*lpBuf2End -= i;//返回的i之所以和这个数相等或小1,是因为dwSeedValue是由*lpBuf2End与key最后一个值计算的
if (*lpBuf2End==0) // 第一个函数返回的i减后一般就是0了,有时走155A8,走完返回0或1,目标也是0或1,减完就是0了
{ // 应该比较的就是为0的这个值和Key最后一个值,应该会小于0
if ( CompareDwordArr_MustLessZero(lpBuf1End, Key, dwKeyCount) < 0 )
break;
}
++dwSeedValue;
}
lpBuf1End--;
lpBuf2End--;
}
memcpy(OutBuf,BigBuf,dwKeyCount*4);
}
unsigned int DecryptData(LPBYTE Out, DWORD* Outsize, LPBYTE Data, unsigned int DataSize, LPBYTE key)
{
BYTE TmpOut[132]={0};
LPBYTE lpNewData=new BYTE[DataSize];
DWORD lpNewKey[32];
memcpy_reverse(lpNewData,Data,DataSize);
memcpy_reverse((LPBYTE)lpNewKey,key,128);
DWORD dwLoopCount=9;
DWORD dwKey2Value=0x40004000;
*(LPDWORD)TmpOut=1;
do
{
DecryptOnce(TmpOut,TmpOut,TmpOut,lpNewKey,KEYCOUNT);
DecryptOnce(TmpOut,TmpOut,TmpOut,lpNewKey,KEYCOUNT);//因为一开始为0,最开始的两次这个操作没影响
if(dwKey2Value>>30)
{//第一次就是将data复制过来
DecryptOnce(TmpOut,TmpOut,lpNewData,lpNewKey,KEYCOUNT);
//printf("Equal:%d\n",!memcmp(TmpOut,lpNewData,KEYSIZE));
}
dwKey2Value<<=2;
} while (dwLoopCount--!=1);
memcpy_reverse(Out,TmpOut,16);
return 0;
}
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)