首页
社区
课程
招聘
[讨论]高手能认出这是什么加密算法吗?(有源码)
发表于: 2012-6-14 02:08 5805

[讨论]高手能认出这是什么加密算法吗?(有源码)

2012-6-14 02:08
5805
本着学习的目的逆向了一个程序,大家看看这是什么加密算法?
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期)

收藏
免费 0
支持
分享
最新回复 (2)
雪    币: 139
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
这个太难了,没看懂啊
2012-6-14 13:44
0
雪    币: 260
活跃值: (15)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
知道是RSA1024了,安全性很强啊。
2012-6-14 14:24
0
游客
登录 | 注册 方可回帖
返回
//