Сейчас на форуме: jinoweb (+6 невидимых)

 eXeL@B —› Программирование —› Идентификация алгоритма
Посл.ответ Сообщение

Ранг: 25.2 (посетитель), 8thx
Активность: 0.030.01
Статус: Участник

Создано: 21 ноября 2018 07:48
· Личное сообщение · #1

Не секрет что в 80% случаев программисты народ ленивый и пользуется стандартными алгоритмами. Следующий кусок декомпиляции из IDA представляет собой функцию для расшифровки данных длиной 128 байт. Вопрос в том что это какой-то стандартный алгоритм или что-то самопальное. Прога написана в 2002 году. Данный после этого шифрования еще накрываются Blowfish и используется CRC16 для контроля целостности.
Есть у кого идеи по поводу этого алгоритма?

Code:
  1. ; char byte_40F34C[32]
  2. byte_40F34C     db      19h,       9,     17h,     0Ah
  3.                                         ; DATA XREF: sub_4038FD+42↑r
  4.                                         ; sub_4038FD+68↑r
  5.                 db        4,     16h,     18h,     1Dh
  6.                 db      15h,       3,     1Ch,       2
  7.                 db        1,     0Bh,     0Ch,     12h
  8.                 db      11h,     1Eh,     14h,     13h
  9.                 db      1Fh,       0,       7,     1Ah
  10.                 db        6,     1Bh,     10h,     0Eh
  11.                 db        8,     0Fh,     0Dh,       5
  12.  
  13. unsigned int __cdecl sub_40397F(int a1)
  14. {
  15.   unsigned int result; // eax
  16.   signed int v2; // [esp+0h] [ebp-8h]
  17.   signed int v3; // [esp+4h] [ebp-4h]
  18.  
  19.   v3 = 31;
  20.   do
  21.   {
  22.     v2 = 31;
  23.     do
  24.     {
  25.       result = v3;
  26.       if ( v3 != v2 )
  27.         result = sub_4038FD((unsigned int *)(a1 + 4 * v3), (unsigned int *)(a1 + 4 * v2));
  28.       --v2;
  29.     }
  30.     while ( v2 >= 0 );
  31.     --v3;
  32.   }
  33.   while ( v3 >= 0 );
  34.   return result;
  35. }
  36.  
  37. int __cdecl sub_4038FD(unsigned int *a1, unsigned int *a2)
  38. {
  39.   unsigned int v2; // eax
  40.   unsigned int v3; // eax
  41.   int result; // eax
  42.   unsigned int v5; // [esp+0h] [ebp-Ch]
  43.   unsigned int v6; // [esp+4h] [ebp-8h]
  44.   signed int v7; // [esp+8h] [ebp-4h]
  45.  
  46.   v6 = *a1;
  47.   v5 = *a2;
  48.   *a1 = 0;
  49.   *a2 = 0;
  50.   v7 = 0;
  51.   do
  52.   {
  53.     if ( v7 & 1 )
  54.       v2 = v5;
  55.     else
  56.       v2 = v6;
  57.     *a1 |= ((v2 >> v7) & 1) << byte_40F34C[v7];
  58.     if ( v7 & 1 )
  59.       v3 = v6;
  60.     else
  61.       v3 = v5;
  62.     result = ((v3 >> v7) & 1) << byte_40F34C[v7];
  63.     *a2 |= result;
  64.     ++v7;
  65.   }
  66.   while ( v7 < 32 );
  67.   return result;
  68. }





Ранг: 71.5 (постоянный), 95thx
Активность: 0.10.38
Статус: Участник

Создано: 21 ноября 2018 09:10 · Поправил: BlackCode
· Личное сообщение · #2

jinoweb
Тушку программы выложи, чтобы не гадать на кофейной гуще)



Ранг: 25.2 (посетитель), 8thx
Активность: 0.030.01
Статус: Участник

Создано: 21 ноября 2018 09:17
· Личное сообщение · #3

BlackCode пишет:

jinoweb
Тушку программы выложи, чтобы не гадать на кофейной гуще)


Если ты имеешь виду саму программу - то не могу ее выложить. Да и представленный кусок кода по-моему полностью самостоятелен.




Ранг: 271.4 (наставник), 331thx
Активность: 0.321.49
Статус: Участник

Создано: 21 ноября 2018 09:23 · Поправил: f13nd
· Личное сообщение · #4

Я бы придрался только к тому, что оно и так шифруется стандартным алгоритмом, какой смысл применять два. По содержанию вроде бы ни на что не похоже. Так что наверное придется сворачивать его самому, а не искать готовый алгоритм, как делают 80% ленивых программистов =)

ЗЫ: Ленивые программисты любят готовые библиотеки. Если этот код был подключен из такой, по тушке программы скорей всего было бы видно.

-----
2 оттенка серого


| Сообщение посчитали полезным: BlackCode

Ранг: 25.2 (посетитель), 8thx
Активность: 0.030.01
Статус: Участник

Создано: 21 ноября 2018 09:40
· Личное сообщение · #5

f13nd пишет:
Если этот код был подключен из такой, по тушке программы скорей всего было бы видно.


Этот код из отдельной маленькой dll которая является плагином к программе. Если какой-то стандартный алгоритм и был взят, то он внедрен в нее на уровне кода а не линка с какой-то библиотекой




Ранг: 1053.6 (!!!!), 1078thx
Активность: 1.060.81
Статус: Участник

Создано: 21 ноября 2018 09:40
· Личное сообщение · #6

с большой натяжкой может быть des, только там в shuffle out OR на результат по массиву в массив
но должны быть еще функции



Ранг: 51.8 (постоянный), 58thx
Активность: 0.03=0.03
Статус: Участник

Создано: 21 ноября 2018 09:41
· Личное сообщение · #7

f13nd пишет:
По содержанию вроде бы ни на что не похоже.

Тоже ничего стандартного не вспомнилось.
Алгоритм на самом деле примитивный, биты меняются местами и всё, даже ксоров нет. На беглый взгляд, сделать обратное преобразование будет несложно.



Ранг: 419.0 (мудрец), 647thx
Активность: 0.460.51
Статус: Участник
"Тибериумный реверсинг"

Создано: 21 ноября 2018 10:32
· Личное сообщение · #8

jinoweb пишет:
Этот код из отдельной маленькой dll

40397F - ImageBase явно не dll. Тамщемта ладно.
Вставьте хотя бы код, который xref's на sub_40397F.
Если несколько раз уже зашифрованный код прогнать, через этот алго, фигня получается?
Одно можно сказать точно - всё привязано к четной/нечетной итерации
Code:
  1. v7 & 1, (v2 >> v7) & 1
  2. таблица:
  3. 25, 9, 23, 
  4. 10, 4, 22, 24, 
  5. 29, 21, 3
  6. 28, 2,
  7. 1, 11,
  8. 12, 18,
  9. 17, 
  10. 30,20,
  11. 19, 31,
  12. 0
  13. 7,
  14. 26,
  15. 6,
  16. 27,
  17. 16, 14, 8,
  18. 15, 13, 5




Ранг: 25.2 (посетитель), 8thx
Активность: 0.030.01
Статус: Участник

Создано: 21 ноября 2018 10:37
· Личное сообщение · #9

ELF_7719116 пишет:
Вставьте хотя бы код, который xref's на sub_40397F


Вот код где вызывается sub_40397F:

Code:
  1. int __cdecl sub_401346(void *ptr)
  2. {
  3.   int v1; // eax
  4.   const char *v2; // eax
  5.   int v3; // eax
  6.   char src; // [esp+0h] [ebp-5D0h]
  7.   char s; // [esp+40h] [ebp-590h]
  8.   char dest; // [esp+140h] [ebp-490h]
  9.   struct _WIN32_FIND_DATAA FindFileData; // [esp+244h] [ebp-38Ch]
  10.   char v9; // [esp+384h] [ebp-24Ch]
  11.   CHAR FileName; // [esp+488h] [ebp-148h]
  12.   char *v11; // [esp+58Ch] [ebp-44h]
  13.   int v12; // [esp+590h] [ebp-40h]
  14.   int handle; // [esp+594h] [ebp-3Ch]
  15.   FILE *stream; // [esp+598h] [ebp-38h]
  16.   HANDLE hFindFile; // [esp+59Ch] [ebp-34h]
  17.   int v16; // [esp+5A0h] [ebp-30h]
  18.   __int16 v17; // [esp+5B4h] [ebp-1Ch]
  19.   int v18; // [esp+5C0h] [ebp-10h]
  20.   int v19; // [esp+5C8h] [ebp-8h]
  21.  
  22.   v1 = __InitExceptBlockLDTC();
  23.   v16 = 0;
  24.   v2 = (const char *)sub_4039D0(v1);
  25.   strcpy(&FileName, v2);
  26.   strcat(&FileName, ::src);
  27.   strcpy(&v9, &FileName);
  28.   strcat(&FileName, aEptEsl);
  29.   hFindFile = FindFirstFileA(&FileName, &FindFileData);
  30.   if ( hFindFile == (HANDLE)-1 )
  31.     return v16;
  32.   do
  33.   {
  34.     strcpy(&dest, &v9);
  35.     strcat(&dest, FindFileData.cFileName);
  36.     stream = fopen(&dest, mode);
  37.     if ( stream )
  38.     {
  39.       handle = stream->fd;
  40.       v12 = filelength(handle);
  41.       if ( v12 == 128 && fread(ptr, 0x80u, 1u, stream) == 1 )
  42.       {
  43.         v11 = a6yuhg663ddqg17;
  44.         strcpy(&src, FindFileData.cFileName);
  45.         _lstrlwr(&src);
  46.         strcpy(&s, v11);
  47.         strcat(&s, &src);
  48.         v17 = 8;
  49.         sub_403B14(&v19);
  50.         ++v18;
  51.         v17 = 20;
  52.         v3 = strlen(&s);
  53.         sub_404804(&v19, (int)&s, v3);
  54.         sub_4049D0((int)&v19, ptr, ptr, 0x80u);
  55.         sub_40397F((int)ptr);
  56.         if ( sub_4012F8(ptr) )
  57.         {
  58.           ++v16;
  59.           ptr = (char *)ptr + 128;
  60.         }
  61.         --v18;
  62.         sub_403B70((int)&v19, 2);
  63.         v17 = 0;
  64.       }
  65.       fclose(stream);
  66.     }
  67.   }
  68.   while ( FindNextFileA(hFindFile, &FindFileData) );
  69.   FindClose(hFindFile);
  70.   return v16;
  71. }


Добавлено спустя 2 минуты
ELF_7719116 пишет:
Если несколько раз уже зашифрованный код прогнать, через этот алго, фигня получается?


Наверное я неправильно обьяснил. Blowfish накладывается после шифрования нашей неизвестной функцией




Ранг: 1053.6 (!!!!), 1078thx
Активность: 1.060.81
Статус: Участник

Создано: 21 ноября 2018 10:41
· Личное сообщение · #10

sub_404804(&v19, (int)&s, v3);
sub_4049D0((int)&v19, ptr, ptr, 0x80u);
sub_4012F8(ptr);
sub_403B70((int)&v19, 2);

а эти функи



Ранг: 25.2 (посетитель), 8thx
Активность: 0.030.01
Статус: Участник

Создано: 21 ноября 2018 11:08
· Личное сообщение · #11

reversecode пишет:
sub_404804(&v19, (int)&s, v3);
sub_4049D0((int)&v19, ptr, ptr, 0x80u);
sub_4012F8(ptr);
sub_403B70((int)&v19, 2);

а эти функи


В процедуре sub_401346 идет расшифровка файлов в цикле по FindNextFile.
Инициализируется Blowfish ключем - sub_404804
Расшифровка Blowfish - sub_4049D0
Снятие неизвестного шифра - sub_40397F
Проверка чексуммы - sub_4012F8




Ранг: 1053.6 (!!!!), 1078thx
Активность: 1.060.81
Статус: Участник

Создано: 21 ноября 2018 11:20
· Личное сообщение · #12

как уже говорил это очень похоже на пермутацию с дес
https://en.wikipedia.org/wiki/Data_Encryption_Standard
The algorithm's overall structure is shown in Figure 1: there are 16 identical stages of processing, termed rounds. There is also an initial and final permutation, termed IP and FP, which are inverses (IP "undoes" the action of FP, and vice versa). IP and FP have no cryptographic significance, but were included in order to facilitate loading blocks in and out of mid-1970s 8-bit based hardwar




Ранг: 605.2 (!), 341thx
Активность: 0.470.25
Статус: Модератор
Research & Development

Создано: 21 ноября 2018 14:11
· Личное сообщение · #13

Не нашёл в теме упоминание о FLIRT сигнатурах, поэтому поработаю немного Капитаном Очевидность и предложу то, с чего, по идее, следовало бы начинать:

Применить к базе данных IDA все крипто сигны, какие найдёшь, в том числе:
- отдельные sig (FLIRT)
- сигнатуры на базе Yara
- плагины

Если не поможет, то взять все популярные крипто библиотеки того времени (времени создания программы), собрать их тем же компилятором, что и собрана программа (файл ты не выкладываешь, поэтому хз, что за компилятор), после чего создать на основе собранных объектников/либ собственные FLIRT сигнатуры.

Это если точно уверен, что автор брал что-то готовое.

В большинстве случаев проблема с крипто в оптимизации алгоритмов и в том, что проще всего ловить по константам.

-----
EnJoy!




Ранг: 158.4 (ветеран), 123thx
Активность: 0.140.49
Статус: Участник

Создано: 21 ноября 2018 15:00 · Поправил: rmn
· Личное сообщение · #14

-

| Сообщение посчитали полезным: jinoweb
 eXeL@B —› Программирование —› Идентификация алгоритма
Эта тема закрыта. Ответы больше не принимаются.
   Для печати Для печати