好象就是一种简单的分组加密吧,很容易求逆的。好象QQ在某个地方用到类似的算法。算法的迭代采用的是类似Feistel网络的东西。
这个算法是16轮迭代。假定第k轮迭代时,分组的高32-bit为H[k], 低32-bit为L[k]。
进入循环之前的ecx/edx就是算法的输入值,即明文H[0]/L[0];
退出循环之后的ecx/edx就是算法的输出值,即密文H[16]/L[16];
密钥可以认为是128-bit的,暂存在[ebp+08]/[ebp+10]/[ebp-04]/[ebp-08]中,分别称为key1, key2, key3, key4;
根据上面的16轮迭代过程可以得到H[k]/L[k]和H[k+1]/L[k+1]之间的递推关系,这个递推关系是两个等式。
根据上面的汇编代码得到的是从H[k]/L[k]推出H[k+1]/L[k+1]的等式,即正向算法,但根据这两个等式也很容易恒等变换出从H[k+1]/L[k+1]推出H[k]/L[k]的等式,即逆算法。
注意:
在上述算法中,常数esi的值从0每轮递减61C88647,共16轮,得到一个最终值。在逆算法中,这个过程也要反过来变成从终值每轮递加61C88647至0。
下面是我以前分析某个软件得到的类似的算法的代码,32轮的。
#define F_FUNCTION(x, k1, k2, c) ((((x) >> 5) + (k1)) ^ (((x) << 4) + (k2)) ^ ((c) +(x)))
//软件里面的解密运算过程
//注意:编译器会将有符号数的右移翻译成SAR指令,而我们需要的是SHR指令,所以必须定义成无符号数
void Decrypt(unsigned int &edx, unsigned int &ebx)
{
static const unsigned int Key1 = 0x13579BDF;
static const unsigned int Key2 = 0x02468ACE;
static const unsigned int Key3 = 0x90ABCDEF;
static const unsigned int Key4 = 0x12345678;
int C1 = 0xC6EF3720;
for(int k = 0 ; k < 32; k++)
{
ebx -= F_FUNCTION(edx, Key1, Key2, C1);
edx -= F_FUNCTION(ebx, Key3, Key4, C1);
C1 += 0x61C88647;
}
}
//上面的函数的逆
void Encrypt(unsigned int &edx, unsigned int &ebx)
{
static const unsigned int Key1 = 0x13579BDF;
static const unsigned int Key2 = 0x02468ACE;
static const unsigned int Key3 = 0x90ABCDEF;
static const unsigned int Key4 = 0x12345678;
int C1 = 0x00000000;
for(int k = 0 ; k < 32; k++)
{
C1 -= 0x61C88647;
edx += F_FUNCTION(ebx, Key3, Key4, C1);
ebx += F_FUNCTION(edx, Key1, Key2, C1);
}
}