Дизасм библиотеки, вытащить алгоритм

Discussion in 'Реверсинг' started by fbidesign, 11 Aug 2012.

  1. fbidesign

    fbidesign Member

    Joined:
    13 Jul 2008
    Messages:
    66
    Likes Received:
    6
    Reputations:
    0
    Есть DLL в которой находится примерно следующий алгоритм:

    При запуске приложения с этой библиотекой она подключается к серверу (протокол TCP, IP берется из файла рандом).
    Сразу после подключения сервер отправляет этому клиенту постоянную строку данных. В ответ клиент отправляет последовательность байт. Сервер снова отвечает постоянной строкой. Далее клиент отправляет опять меняющийся запрос постоянной длины, сервер высылает зашифрованный файл (тот самый файл из которого клиент будет брать список IP).
    Далее идет еще несколько запосов - ответов неизвестного происхождения, на этом процесс "коннекта" завершается, постоянное соединение висит и периодически клиент отправляет на сервер постоянный набор данных (типа пинг) и при определенном событии отправляет на сервер другой набор данных.

    Я разобрал DLL c помощью IDA Pro, нашел нужные участки кода но моего ума не хватает для того чтобы вытащить из ассмблерного кода полный алгоритм описанного выше в том числе и алгоритм шифрования данных при передаче. И вообще опыта работы с IDA нет.

    Объемы данных небольшие, порядка 2кб, весь процесс составляет 12 пакетов (в сумме и туда и назад). Моя задача полностью воспроизвести это в своей программе.

    Кто может мне помочь с расшифровкой?

    P.S. это не бекдор ;)
     
  2. bad_boy

    bad_boy Elder - Старейшина

    Joined:
    30 Dec 2004
    Messages:
    189
    Likes Received:
    33
    Reputations:
    3
    Кнопка F5 работает в IDA ?
    Если нет, скачай более новую версию с HexRays.
     
    1 person likes this.
  3. fbidesign

    fbidesign Member

    Joined:
    13 Jul 2008
    Messages:
    66
    Likes Received:
    6
    Reputations:
    0
    Эврика! Серьезно не знал.
    Первые впечатления: сбивает с толку обращение к одним и тем же переменным сначала как к массивам потом как к адресам (арифметические операции) поэтому отличить массив от int можно только перелопатив половину процедуры.

    И еще не смог понять такую конструкцию
    Code:
     v12 = *(_DWORD *)(*(_DWORD *)(LBuf_v5 + 100) + 44)
    Допустим взяли 100й элемент массива-буффера данных но что с ним потом сделали?

    Кто-то может бегло посмотрев на код который ниже сказать похоже это на шифрование и если да то на что именно? Функция целиком которая вызывается из другой на этапе заполнения буффера данных перед отправкой. BUFFsh это новосозданный массив, transfa3 идет откуда-то раньше, BufLen длина 1 параметра. Куски данных преобразуются и копируются из 2 в 1

    Code:
    unsigned int __cdecl fillbuff1_sub_38347EC0(unsigned int BUFFsh_a1, int transfa3_a2, unsigned int BufLen_a3)
    {
      unsigned int BufLenLocal_v3; // ecx@1
      int v6; // edx@8
      unsigned int v7; // ecx@8
      unsigned int result; // eax@22
      int BufPointer_v9; // edi@26
      int TransPointer_v10; // esi@26
      int lenflag_v11; // edx@27
      unsigned int lenflag_v12; // ecx@27
      int v13; // eax@38
      unsigned int k; // edx@39
      unsigned int v15; // edx@39
      int v16; // ecx@39
      unsigned int l; // edx@42
      int v27; // ecx@44
      char v28; // al@45
      unsigned int m; // ecx@45
      int n; // ecx@47
      unsigned int v31; // eax@50
      int i; // ecx@50
      unsigned int j; // eax@52
      int v34; // [sp-8h] [bp-10h]@50
    
      _ESI = transfa3_a2;
      BufLenLocal_v3 = BufLen_a3;
      _EDI = BUFFsh_a1;
      if ( BUFFsh_a1 > transfa3_a2 && BUFFsh_a1 < transfa3_a2 + BufLen_a3 )
      {
        TransPointer_v10 = BufLen_a3 + transfa3_a2 - 4;
        BufPointer_v9 = BufLen_a3 + BUFFsh_a1 - 4;
        if ( BufPointer_v9 & 3 )
        {
          if ( BufLen_a3 >= 4 )
            JUMPOUT(__CS__, *((_DWORD *)loc_383480CC + (BufPointer_v9 & 3) + 1));
          switch ( BufLen_a3 )
          {
            case 0u:
    Lab_34_case0u:
              result = BUFFsh_a1;
              break;
            case 1u:
    Lab_35_case1u:
              *(_BYTE *)(BufPointer_v9 + 3) = *(_BYTE *)(TransPointer_v10 + 3);
              result = BUFFsh_a1;
              break;
            case 2u:
    Lab_36_case2u:
              *(_BYTE *)(BufPointer_v9 + 3) = *(_BYTE *)(TransPointer_v10 + 3);
              *(_BYTE *)(BufPointer_v9 + 2) = *(_BYTE *)(TransPointer_v10 + 2);
              result = BUFFsh_a1;
              break;
            case 3u:
              goto LABEL_37_CopyBytes;
          }
        }
        else
        {
          lenflag_v12 = BufLen_a3 >> 2;
          lenflag_v11 = BufLen_a3 & 3;
          if ( BufLen_a3 >> 2 < 8 )
          {
            switch ( -lenflag_v12 )
            {
              case 0:
                switch ( lenflag_v11 )
                {
                  case 0:
                    goto Lab_34_case0u;
                  case 1:
                    goto Lab_35_case1u;
                  case 2:
                    goto Lab_36_case2u;
                  case 3:
                    goto LABEL_37_CopyBytes;
                }
            }
          }
          else
          {
            memcpy((void *)BufPointer_v9, (const void *)TransPointer_v10, 4 * lenflag_v12);
            TransPointer_v10 += 4 * lenflag_v12;
            BufPointer_v9 += 4 * lenflag_v12;
            switch ( lenflag_v11 )
            {
              case 0:
                goto Lab_34_case0u;
              case 1:
                goto Lab_35_case1u;
              case 2:
                goto Lab_36_case2u;
              case 3:
                break;
            }
          }
    LABEL_37_CopyBytes:
          *(_BYTE *)(BufPointer_v9 + 3) = *(_BYTE *)(TransPointer_v10 + 3);
          *(_BYTE *)(BufPointer_v9 + 2) = *(_BYTE *)(TransPointer_v10 + 2);
          *(_BYTE *)(BufPointer_v9 + 1) = *(_BYTE *)(TransPointer_v10 + 1);
          result = BUFFsh_a1;
        }
      }
      else
      {
        if ( BufLen_a3 >= 0x80
          && dword_38622488
          && (_ESI = transfa3_a2, _EDI = BUFFsh_a1, (BUFFsh_a1 & 0xF) == (transfa3_a2 & 0xF)) )
        {
          v13 = transfa3_a2 & 0xF;
          if ( transfa3_a2 & 0xF )
          {
            v34 = BufLen_a3 - (16 - v13);
            v31 = 16 - v13;
            for ( i = v31 & 3; i; --i )
              *(_BYTE *)_EDI++ = *(_BYTE *)_ESI++;
            for ( j = v31 >> 2; j; --j )
            {
              *(_DWORD *)_EDI = *(_DWORD *)_ESI;
              _ESI += 4;
              _EDI += 4;
            }
            BufLenLocal_v3 = v34;
          }
          v15 = BufLenLocal_v3;
          v16 = BufLenLocal_v3 & 0x7F;
          for ( k = v15 >> 7; k; --k )
          {
            __asm
            {
              movdqa  xmm0, xmmword ptr [esi]
              movdqa  xmm1, xmmword ptr [esi+10h]
              movdqa  xmm2, xmmword ptr [esi+20h]
              movdqa  xmm3, xmmword ptr [esi+30h]
              movdqa  xmmword ptr [edi], xmm0
              movdqa  xmmword ptr [edi+10h], xmm1
              movdqa  xmmword ptr [edi+20h], xmm2
              movdqa  xmmword ptr [edi+30h], xmm3
              movdqa  xmm4, xmmword ptr [esi+40h]
              movdqa  xmm5, xmmword ptr [esi+50h]
              movdqa  xmm6, xmmword ptr [esi+60h]
              movdqa  xmm7, xmmword ptr [esi+70h]
              movdqa  xmmword ptr [edi+40h], xmm4
              movdqa  xmmword ptr [edi+50h], xmm5
              movdqa  xmmword ptr [edi+60h], xmm6
              movdqa  xmmword ptr [edi+70h], xmm7
            }
            _ESI += 128;
            _EDI += 128;
          }
          if ( v16 )
          {
            for ( l = (unsigned int)v16 >> 4; l; --l )
            {
              __asm
              {
                movdqa  xmm0, xmmword ptr [esi]
                movdqa  xmmword ptr [edi], xmm0
              }
              _ESI += 16;
              _EDI += 16;
            }
            v27 = v16 & 0xF;
            if ( v27 )
            {
              v28 = v27;
              for ( m = (unsigned int)v27 >> 2; m; --m )
              {
                *(_DWORD *)_EDI = *(_DWORD *)_ESI;
                _ESI += 4;
                _EDI += 4;
              }
              for ( n = v28 & 3; n; --n )
                *(_BYTE *)_EDI++ = *(_BYTE *)_ESI++;
            }
          }
          result = BUFFsh_a1;
        }
        else
        {
          if ( _EDI & 3 )
          {
            if ( BufLen_a3 >= 4 )
              JUMPOUT(__CS__, *((_DWORD *)loc_38347F40 + (_EDI & 3) + 1));
            JUMPOUT(__CS__, *((_DWORD *)loc_38348040 + BufLen_a3 - 4));
          }
          v7 = BufLen_a3 >> 2;
          v6 = BufLen_a3 & 3;
          if ( BufLen_a3 >> 2 < 8 )
          {
            switch ( v7 )
            {
              case 0u:
                goto LABEL_21;
              case 1u:
                goto LABEL_20;
              case 2u:
                goto LABEL_19;
              case 3u:
                goto LABEL_18;
              case 4u:
                goto LABEL_17;
              case 5u:
                goto LABEL_16;
              case 6u:
                break;
              case 7u:
                *(_DWORD *)(_EDI + 4 * v7 - 28) = *(_DWORD *)(_ESI + 4 * v7 - 28);
                break;
            }
            *(_DWORD *)(_EDI + 4 * v7 - 24) = *(_DWORD *)(_ESI + 4 * v7 - 24);
    LABEL_16:
            *(_DWORD *)(_EDI + 4 * v7 - 20) = *(_DWORD *)(_ESI + 4 * v7 - 20);
    LABEL_17:
            *(_DWORD *)(_EDI + 4 * v7 - 16) = *(_DWORD *)(_ESI + 4 * v7 - 16);
    LABEL_18:
            *(_DWORD *)(_EDI + 4 * v7 - 12) = *(_DWORD *)(_ESI + 4 * v7 - 12);
    LABEL_19:
            *(_DWORD *)(_EDI + 4 * v7 - 8) = *(_DWORD *)(_ESI + 4 * v7 - 8);
    LABEL_20:
            *(_DWORD *)(_EDI + 4 * v7 - 4) = *(_DWORD *)(_ESI + 4 * v7 - 4);
            _ESI += 4 * v7;
            _EDI += 4 * v7;
    LABEL_21:
            switch ( v6 )
            {
              case 0:
    LABEL_22:
                result = BUFFsh_a1;
                break;
              case 1:
    LABEL_23:
                *(_BYTE *)_EDI = *(_BYTE *)_ESI;
                result = BUFFsh_a1;
                break;
              case 2:
    LABEL_24:
                *(_BYTE *)_EDI = *(_BYTE *)_ESI;
                *(_BYTE *)(_EDI + 1) = *(_BYTE *)(_ESI + 1);
                result = BUFFsh_a1;
                break;
              case 3:
                goto LABEL_25;
            }
          }
          else
          {
            memcpy((void *)_EDI, (const void *)_ESI, 4 * v7);
            _ESI += 4 * v7;
            _EDI += 4 * v7;
            switch ( v6 )
            {
              case 0:
                goto LABEL_22;
              case 1:
                goto LABEL_23;
              case 2:
                goto LABEL_24;
              case 3:
                break;
            }
    LABEL_25:
            *(_BYTE *)_EDI = *(_BYTE *)_ESI;
            *(_BYTE *)(_EDI + 1) = *(_BYTE *)(_ESI + 1);
            *(_BYTE *)(_EDI + 2) = *(_BYTE *)(_ESI + 2);
            result = BUFFsh_a1;
          }
        }
      }
      return result;
    }
    
    Насколько сложно дописать в DLL кусок своего кода и поставить в начало нескольких функций jump (что-то типа сплайсинга) который бы кидал на мой кусок кода, дампил параметры в файлы и возвращал бы на исходную инструкцию?
     
    #3 fbidesign, 12 Aug 2012
    Last edited: 12 Aug 2012
  4. D4rkC10ud

    D4rkC10ud New Member

    Joined:
    30 Jul 2012
    Messages:
    27
    Likes Received:
    1
    Reputations:
    0
    это фича С/С++, которая так страшно выглядит, всего-лишь получение значения с двумерного массива значений типа DWORD. Советую просветиться по книге Стивен Пратта "Язык программирования С".

    Я б реализовал это отдельной отладочной DLL. Нифига не сложно, как вижу, ты про сплайсинг уже знаешь, а если функция экспортируемая, то можно поступить еще легче - править IAT(таблицу импорта) нужного модуля.
     
    #4 D4rkC10ud, 13 Aug 2012
    Last edited: 13 Aug 2012
  5. bad_boy

    bad_boy Elder - Старейшина

    Joined:
    30 Dec 2004
    Messages:
    189
    Likes Received:
    33
    Reputations:
    3
    fbidesign, код который ты привёл - похоже функция memcpy.
    Копирует из transfa3_a2 в BUFFsh_a1 данные в размере BufLen_a3 байт. Шифрования тут нет, только в зависиммости от длины буффера копирование происходит разными алгоритмами.
     
  6. fbidesign

    fbidesign Member

    Joined:
    13 Jul 2008
    Messages:
    66
    Likes Received:
    6
    Reputations:
    0
    Т.е это просто многобукаф вместо memcpy? Мне чего-то казалось что байты на разные места ставятся... А в зависимости от длины буффера используется ассемблерный код с процессорными инструкциями просто ради производительности?

    Если бы эти функции были экспортируемые я бы обошелся без дизассемблера :)
    хотя какая-то функция которая вызывает эти может быть и экспортируемой.

    Вопрос по теме: IDA называет функции вида sub_38347EC0 - это и есть адрес Entry Point?

    т.е. она получает 144й элемент массива? точнее DWORD начинающийся со 144го байта?

    Отладочная DLL хорошая идея. Та как раз использует из IPHLPAPI.DLL только GetAdaptersInfo, можно подставную DLL подложить наверное... Или классическими методами из примеров в интернете.

    я вообще веб разработчкик, но так ради интереса со многим разбирался, не так чтобы большой опыт работы но вспомнить что было года 2 назад могу
     
  7. bad_boy

    bad_boy Elder - Старейшина

    Joined:
    30 Dec 2004
    Messages:
    189
    Likes Received:
    33
    Reputations:
    3
    Да, может свою написали, а может из библиотеки вставилась.
    sub - сокращение от subprogram, любая подпрограмма. Entry Point можешь найти посмотреть в список экспортируюемых функций в IDA, она навреное будет называться "start", но в Dll там обычно код, который отвечает только за загрузку самой dll в процесс.
     
  8. fbidesign

    fbidesign Member

    Joined:
    13 Jul 2008
    Messages:
    66
    Likes Received:
    6
    Reputations:
    0
    я имел в виду Entry Point не библиотеки а экспортируемой функции
    в Total Commander есть плагин который отображает таблицу экспорта Entry Pt - Ordn - Name, вот и думал поискать функции с этим Entry Pt в названии
     
  9. D4rkC10ud

    D4rkC10ud New Member

    Joined:
    30 Jul 2012
    Messages:
    27
    Likes Received:
    1
    Reputations:
    0
    Двухмерного массива я написал - т.е элемент массива [44][100] не являеться 144 байтом, даде если элемент массива занимает один байт. Кури маны по указателям в приведенной мной книге - пригодиться.
    Особенности указателей в сях: указатели имеют тип, кроме (VOID *). Поэтому (DWORD *)(p++ ) увеличит адрес указазателя на 4, а (char *)(p++ ) на 1.

    Работа с указателями в сях отличаеться от других веб и не только языков программирования, не смотря на схожесть их синтаксиса, поэтому си заняло свою нишу в системном программировании.

    P.S.
    PE Explorer на кряклабе тебе в помощь! удобная штука по исследованию ехе\длл х86\х86-64 кода!
     
    #9 D4rkC10ud, 15 Aug 2012
    Last edited: 15 Aug 2012
Loading...