查找加密算法的解密算法

逆向工程 部件 C 加密 解密
2021-06-12 04:02:24

我最近研究了一种加密 8 字节长度的数据的算法。我努力工作并成功获得了这个算法,但我需要解密这个算法。我怎样才能反转它?

我想这是一个散列算法,我不能反转它。但我想确定一下。

int tmp1 = 0;
int tmp2 = 0;
unsigned short int _array_1[8]={0};
unsigned short int _array_out[8]={0};

for(int j = 0 ; j <5; j++)
        tmp1 = tmp1 * 0x40 + _array_1[j];
    for(int j = 5; j<8; j++)
        tmp2 = (tmp2 << 5) + _array_1[j];
    for (int j = 0 ; j<4; j++)
        _array_1[j] = (tmp1 >> 8*j ) & 0xFFFF ;
    for (int j = 4 ; j<6; j++)
        _array_1[j] = (tmp2 >> 8*(j-4) ) & 0xFFFF ;
    _array_1[6] = 0;
    _array_1[7] = 0;

    _array_out [0] = (get_diff (_array_1[1],0x1A)) * (get_diff (_array_1[4],0x9C));
    _array_out [1] = (get_diff (_array_1[1],0x9C)) * (get_diff (_array_1[4],0x2E));
    _array_out [2] = (get_diff (_array_1[5],0x1A)) * (get_diff (_array_1[2],0x9C));
    _array_out [3] = (get_diff (_array_1[5],0x9C)) * (get_diff (_array_1[2],0x2E));
    _array_out [4] = (get_diff (_array_1[3],0x1A)) * (get_diff (_array_1[0],0x9C));
    _array_out [5] = (get_diff (_array_1[3],0x9C)) * (get_diff (_array_1[0],0x2E));

uint8_t get_diff(uint8_t a, uint8_t b)
{
    uint8_t result =0;
    result = (a> b )?  (a-b) : (b-a);
    return result;
}

编辑:
根据局域网评论,我编辑了我的问题,添加了一些数据,例如tmp1tmp2
另外,我将举一个例子作为例子。
示例
输入 = 0x01、0x05、0x00、0x0C、0x1B、0x14、0x18、0x1A
输出= 0xAE、0xF4、0x48、0x6A、0x99、0x81
谢谢。

1个回答

不可逆 (1)

绝对不是可逆的。

要看到这一点,您只需要考虑tmp1第一个循环的 2 次迭代后的内容

让我们展开这 2 次迭代(并且,为了简单起见,假设 tmp1 在进入循环时为零。)这给出 -

tmp1 = _array_1[ 0 ] * 64 + _array_1[ 1 ];

前两个输入值的值正在“重叠”,这意味着在这 2 次迭代后,这些值的多组值会为 tmp1 生成相同的值。

例如

_array_1[ 0 ] = 0, _array_1[ 1 ] = 64 => tmp1 = 64
_array_1[ 0 ] = 1, _array_1[ 1 ] =  0 => tmp1 = 64

由于循环的前 2 次迭代是唯一使用前两个输入值的地方,因此此处丢失的信息无法在其他地方恢复,因此我们知道不可能反转。


不可逆 (2)

另外,如果我们知道输出数据也被视为字节,那么您甚至不需要查看算法的数学细节来理解不可逆性。

相反,观察到有 8 个字节的输入但只有 6 个字节的输出足以证明这一点。这是因为每个可能的输出平均由 65536 个不同的输入产生,所以你不能走另一条路。


查找单个有效输入值集的算法

为了使您的示例向前工作,我不得不假设您显示的代码是错误的,并且您的输入和输出数组的类型恰好是 8 位(此处unsigned char) not unsigned short

在此基础上,并假设您说您对给定输出的(多值)反向算法的任何任意单一解决方案感到满意,您可以尝试这个 -

unsigned char in[] = { 0xAE, 0xF4, 0x48, 0x6A, 0x99, 0x81 };
unsigned char out[8];

brute_force_bifactor( in[0], in[1], &out[1], &out[4] );
brute_force_bifactor( in[2], in[3], &out[5], &out[2] );
brute_force_bifactor( in[4], in[5], &out[3], &out[0] );

int tmp1 = 0;
int tmp2 = 0;
for( int j = 0; j < 4; ++j )
    tmp1 |= out[j] << 8 * j;
for( int j = 4; j < 6; ++j )
    tmp2 |= out[j] << 8 * (j - 4);

/* the following lines are one of many possible ways of splitting tmp1 & tmp2 that successfully invert the algorithm */
for( int j = 0; j < 5; ++j )
    out[j] = (tmp1 >> 6 * (4 - j)) & 0x3F;
for( int j = 5; j < 8; ++j )
    out[j] = (tmp2 >> 5 * (7 - j)) & 0x1F;

void brute_force_bifactor( unsigned char a, unsigned char b, unsigned char* px, unsigned char* py )
{
    /* this returns the first pair of values x & y that satisfy the inversion criteria */
    for( int x = 0; x < 256; ++x )
    {
        for( int y = 0; y < 256; ++y )
        {
            if( ((abs( x - 0x1A ) * abs( y - 0x9C )) & 0xFF) != a ) continue;
            if( ((abs( x - 0x9C ) * abs( y - 0x2E )) & 0xFF) != b ) continue;
            *px = x;
            *py = y;
            return;
        }
    }
    exit( 1 );
}

brute_force_bifactor使用一些巧妙的数学方法可能会改进此函数,但由于内部循环最多需要 65k 次迭代,因此无论如何它都非常快。