Функция шифрования с 32-битной обратной обработкой, 64-битная ошибка - PullRequest
1 голос
/ 07 декабря 2011
signed int _rotr( int a1, int a2 )
{
    return (a1 << a2 % 0x20u) | ((unsigned int)a1 >> (char)(32 - a2 % 0x20u));
}
int _encrypt_password( int a1, int a2, signed int a3 )
{
    signed int  v10; // [sp+10h] [bp-8h]@3
    int         result; // eax@1
    int         v4; // ebx@3
    int         v5; // edi@3
    int         v6; // esi@3
    int         v7; // eax@4
    int         v8; // [sp+14h] [bp-4h]@2
    int         v9; // [sp+Ch] [bp-Ch]@2

    result = 8 * a3 / 8;
    a3 = 8 * a3 / 8;
    if ( result > 0 )
    {
        result = a2;
        v8 = 0;
        v9 = a2;
        while ( a3 / 8 > v8 )
        {
            v4 = *(_DWORD *)v9 + *(_DWORD *)(a1 + 16);
            v6 = *(_DWORD *)(v9 + 4) + *(_DWORD *)(a1 + 20);
            v10 = 1;
            v5 = a1 + 24;
            do
            {
                v7 = *(_DWORD *)v5 + _rotr(v6 ^ v4, v6);
                v4 = v7;
                v6 = *(_DWORD *)(v5 + 4) + _rotr(v7 ^ v6, v7);
                ++v10;
                v5 += 8;
            }
            while ( v10 <= 12 );
            result = v9;
            *(_DWORD *)v9 = v4;
            *(_DWORD *)(v9 + 4) = v6;
            ++v8;
            v9 += 8;
        }
    }
    return result;
}

Выше представлен набор функций с обратной инженерией, который обеспечивает шифрование строки (пароля) для аутентификации игрового клиента на игровом сервере. Оригинальное шифрование больше не доступно, и для этой цели оно было перепроектировано.

Код отлично работает в 32-битной среде, однако при компиляции для 64-битных систем я сталкиваюсь с некоторыми проблемами. Код строится успешно, как и в 32-битном, однако при выполнении функции он выходит из строя (EXC_BAD_ACCESS), когда достигает первой строки назначения v4:

v4 = *(_DWORD *)v9 + *(_DWORD *)(a1 + 16);

Я попытался понять функцию и выяснить, какой тип шифрования она на самом деле обеспечивает, однако мне это не удалось. Сначала я работал с RC5, но это заняло около 2 дней математики, что в конечном итоге оказалось чрезвычайно полезным для моих навыков криптографии, но бесполезно для рассматриваемой проблемы.

Я хотел бы знать одну или обе вещи об этом коде:

Первый и самый простой, кто-нибудь узнает алгоритм или криптографический метод, который он использует? Это даже с использованием стандартного метода? Для меня это выглядит как RC5 / ROT13 / DES / AES в той или иной форме, но я не могу сказать.

Во-вторых, есть ли признаки того, почему это не сработает в 64-битной версии?

** Извините, _DWORD длинная без знака.

Ответы [ 2 ]

3 голосов
/ 08 декабря 2011

a1 и a2 не являются целыми числами, они являются указателями, аналогично, они не подписаны, они не подписаны. В 64-битной системе эти указатели могут иметь значения выше max (int32), вы можете попробовать преобразовать их в значения 64-битного размера, скажем, uint64_t.

0 голосов
/ 07 декабря 2011

Попробуйте заменить все вхождения int и _DWORD на int32_t (вам нужно #include <stdint.h>. Вы сказали, что _DWORD определяется как unsigned long, что на многих 32-битных машинах будет 32-битное количество, но на 64-битных машинах часто будет 64.

Или, если функция на самом деле вызывается с адресами в качестве аргументов, как это может выглядеть, вы можете попробовать использовать int64_t везде. У вас есть пример того, как вызывается функция, и несколько примеров ввода в 64-битной системе?

...