Blowfish算法逆向分析

Blowfish算法逆向分析

Blowfish算法简介

Blowfish 算法是一种对称加密算法,该算法由两大部分组成,分别是密钥预处理数据加密。而数据加密的过程则依赖于预处理后的两个密钥盒,这两个密钥盒分别是:

  • unsigned long key_pbox[18]
  • unsigned long key_sbox[4][256]

数据加解密过程分析

因为Blowfish 算法是对称加密算法,所以无论是加密还是解密过程,它所用到的密钥盒(即key_pbox和key_sbox)为相同的密钥盒。而这两个密钥盒,我们可以在密钥预处理函数执行结束后从内存中dump下来。对于我们的输入(长度为64位),Blowfish 首先将其分为长度相等的两部分,分别是高32位(记作XL)和低32位(记作XR)。在Blowfish加解密过程中,还涉及到了一个函数(记作F),该函数接收两个参数,一个参数为 key_sbox的起始地址,另一个参数则为XL和key_pbox的子密钥异或的结果。F函数在程序中的伪代码如下所示:

//首先将a2分成4个长度为8位的a、b、c、d,之后再将 (((KEY_SBOX[0][a]+KEY_SBOX[1][b])^KEY_SBOX[2][c])+KEY_SBOX[3][d] 的值返回。
//注:KEY_SBOX的起始地址即为KEY_PBOX的起始地址加上0x48。

int __cdecl F(int a1, unsigned int a2)
{
  return *(_DWORD *)(a1 + 4 * (unsigned __int8)a2 + 3144)
         + (*(_DWORD *)(a1 + 4 * BYTE1(a2) + 2120) ^ (*(_DWORD *)(a1 + 4 * ((a2 >> 16) & 0xFF) 
         + 1096) + *(_DWORD *)(a1 + 4 * (a2 >> 24) + 72)));
}

Blowfish算法解密过程的伪代码如下所示:

int *__cdecl decrypt(_DWORD *key_pbox, int *higher4bytes, int *lower4bytes)
{
  int XL; // eax
  int XR; // esi
  _DWORD *v5; // edi
  _DWORD *v6; // ebx
  int v7; // ebp
  bool v8; // zf
  int v9; // ecx
  int *result; // eax
  signed int index; // [esp+14h] [ebp+4h]

  XL = *higher4bytes;                           // 将所输入的密文的前32位赋值给XL。
  XR = *lower4bytes;                            // 将所输入的密文的后32位赋值给XR。
  v5 = key_pbox;                                // 将key_pbox的起始地址赋值给v5。
  index = 16;                                   // 解密过程需要对密文进行16次迭代。
  v6 = v5 + 17;                                 // v6的初始值为&key_pbox[17]。
  do
  {
    v7 = *v6 ^ XL;                              // 将key_pbox[index+1]与XL进行异或。
    XL = XR ^ F((int)v5, v7);                   // 将函数sub_401000的返回值与XR的值进行异或后赋给XL。
    --v6;                                       // 使v6指向key_pbox[index]。
    v8 = index == 1;
    XR = v7;
    --index;                                    // 迭代次数减1。
  }
  while ( !v8 );
  v9 = XL ^ v5[1];                              // v9的值即为迭代16轮后的XL的值与key_pbox[1]异或的结果。
  result = higher4bytes;                        
  *higher4bytes = v7 ^ *v5;                     // 最后所得明文的高32位为迭代16轮后XR的值与key_pbox[0]异或的结果。
  *lower4bytes = v9;
  return result;
}

Blowfish算法的加密过程则只需将key_pbox进行逆序即可。