Сканер сигнатур :)

Тема в разделе "WASM.BEGINNERS", создана пользователем CrawlUp, 22 янв 2019.

  1. CrawlUp

    CrawlUp Member

    Публикаций:
    0
    Регистрация:
    1 фев 2018
    Сообщения:
    88
    Пишу тему, скорее не для какого-либо ответа, а скорее поделиться очередным неудачным опытом.
    Проходил уроки по реверсу IdaPro сделанные yashechka и тут, как мне показалось, у меня возникла "блестящая" идея, а почему бы не менять необходимую мне информацию прямо в памяти программы.

    Поразбиравшись в этой теме, начал писать свой сканер сигнатур. Сначала начал делать вывод информации на основе ListView, но он оказался не подходящим для этого дела. Я это понял, когда уже написал пару тысяч строк. Ну что же, мне в первой, переписывать. Сел и хорошенько всё обдумал, решил что подходящим для вывода информации будет контрол TreeView. Опять начал писать программу и вот когда уже набралось три тысячи строк(почему я пишу про количество строк, для того что бы было понятно, что первая неудачная часть программы заняла не одну неделю усилий и вторая часть также), пришёл к печальному выводу:
    если ты знаешь сигнатуру, то это еще не значит, что ты сможешь узнать в какую ячейку памяти, последовательность инструкций запишет данные.

    К примеру, возьмём всем известную программу CheatEngine, она сканируя память находит адрес с необходимым значением, после этого, каким то чудесным образом устанавливает инструкции которые пишут в эту ячейку памяти и читают из неё. Но вот обратный вариант, если ты знаешь инструкции, найти ячейку памяти в которую пишут эти инструкции (по моему мнению) уже невозможно, потому что одни и те же инструкции могут записывать кучу разных данных не имеющих к друг другу ни какого отношения.
    Например:
    Код (Text):
    1. mov ecx,[rdx]
    2. mov  [rax],ecx
    Тему это пишу, потому что вроде бы надо продолжать писать программу, но смысла она уже не имеет даже для "внутреннего использования". Вообщем очередной кризис, делал, делал, что-то а оказалось впустую.
     
  2. f13nd

    f13nd Active Member

    Публикаций:
    0
    Регистрация:
    22 июн 2009
    Сообщения:
    402
    На то, что ты привел, делать сигнатуру неразумно. Сигнатура должна цепляться за уникальную последовательность/константы. Какой толк от десятков тысяч попаданий в последовательность из двух мувов? Интел не очень подходит для всех этих фокусов: из-за sib-байта и нескольких вариантов как можно закодировать одну и ту же инструкцию, а также причуд компилеров, если просто обрубать последовательность конъюнкцией с маской и сравнивать, выхлоп будет слабоват. Опять же выбирать последовательность для сигнатуры надо так, чтобы было можно из найденного достать нужный адрес/смещение. Вообще идасигнатуры делаются по распространенным либам с отладочной информацией в надежде, что именно эта версия либы будет подключена. Сигнатурные движки даже не оперируют с битами, максимум - с ниблами. Единственное по-моему исключение - yara, но сигнатуры на регулярках полная дичь. Мой колхоз-стайл для не-интелов выглядит так:
    [​IMG]
    [​IMG]
    и работает пугающе хорошо. Но это все от простоты компилера и самого набора инструкций зависит. Для интела это все надо серьезно усложнять. То есть первый этап например брать последовательность одних только опкодов, а далее - взаимосвязь источников-приемников и так, чтобы порядок был необязательно таким и возможно даже с разрывами. По сути граф получится.
     
    Последнее редактирование: 23 янв 2019
    q2e74 нравится это.
  3. q2e74

    q2e74 Active Member

    Публикаций:
    0
    Регистрация:
    18 окт 2018
    Сообщения:
    259
    Почему? скорость или еще что?
     
  4. f13nd

    f13nd Active Member

    Публикаций:
    0
    Регистрация:
    22 июн 2009
    Сообщения:
    402
    Во-первых скорость, во-вторых яра оперирует с нех-строками например "CE 20 00 50", если тебе нужно взять 7 бит из 8 ты делаешь 2 кейса, 6 из 8 - 4 кейса. Регулярки в принципе для этого не подходят, это удобное средство работы блин с текстами. Ее автор похоже просто хотел как бы попроще намутить что-то более-менее пригодное, не особенно напрягаясь. А комьюнитям предлагается это жрать и нахваливать.
     
  5. q2e74

    q2e74 Active Member

    Публикаций:
    0
    Регистрация:
    18 окт 2018
    Сообщения:
    259
    Предлагаете нахваливаеть какой-нибудь OSSIM ? А если серьезно, то каким алгоритмом это было бы делать правильнее всего?
     
  6. gazlan

    gazlan Member

    Публикаций:
    0
    Регистрация:
    22 май 2005
    Сообщения:
    413
    Именно Yara это и делает правильно. RegExp там просто надстройка над автоматом поиска константных сигнатур. В сущности, это тот же движок, что у ClamAV (модифицированный Aho-Corasic).
     
    q2e74 нравится это.
  7. f13nd

    f13nd Active Member

    Публикаций:
    0
    Регистрация:
    22 июн 2009
    Сообщения:
    402
    Я и про константные сигнатуры упомянул и почему яра не лучше, хотя могёт немного больше их. Нравится - пользуйтесь. Если пользуетесь.
     
  8. gazlan

    gazlan Member

    Публикаций:
    0
    Регистрация:
    22 май 2005
    Сообщения:
    413
    A Generic Virus Scanner in C++
     

    Вложения:

  9. f13nd

    f13nd Active Member

    Публикаций:
    0
    Регистрация:
    22 июн 2009
    Сообщения:
    402
    Код (Text):
    1. for (every character in the virus signature)
    2. {
    3. if(the character is a hexadecimal digit)
    4. {
    5. make a child of t
    6. corresponding to this fixed nibble;
    7. t = this child;
    8. }
    9. else if(the character is ?)
    10. create a child of t labeled ?;
    11. t = this child;
    12. /* there may be several marked ?
    13. if two signatures have a common
    14. prefix including a ?
    15. */
    16. }
    17. else if(the next two characters are
    18. of the form %d)
    19. create a child of t labeled %;
    20. t = this child;
    21. /* there may be several
    22. marked % similarly */
    23. }
    Это обработка "константных сигнатур", дискретная единица - нибл (4 бита, 1 символ в нех-представлении). Это в пользу яры был аргумент или рандомные пдфки? Не открою америку, если сообщу, что у интелов номера регистров кодируются в 0-2 и 3-5 битах байта (3 бита, карл), что не очень кратно 4. Есть например архитектура PowerPC, где опкод почти любой инструкции - 6 бит младшего байта и чаще всего оставшиеся два бита относятся к номеру регистра. И ярой, которая "делает это правильно" отсечь эти два оставшихся бита можно только 4мя возможными комбинациями статического опкода и произвольных двух оставшихся бит. Потому что в яре применены передовые технологии обработки поэзии и прозы.
     
    Последнее редактирование: 24 янв 2019
  10. gazlan

    gazlan Member

    Публикаций:
    0
    Регистрация:
    22 май 2005
    Сообщения:
    413
    OT: Тут есть блэк-лист? Очень нужно.
     
  11. q2e74

    q2e74 Active Member

    Публикаций:
    0
    Регистрация:
    18 окт 2018
    Сообщения:
    259
    f13nd, чет может туплю, но не пойму, причем тут адреса регистров? ты же не байт с байтом сигнатуры и регистров сравниваешь. Зарядил один массив, зарядил второй. По любому, до сравнения они много раз где будут перемещаться и копироваться, что бы учитывать такую мелочь. Возможно, глуп и не прав, поэтому прошу, объясни еще раз схему потерь "на тактах". Что б даже ребенку было понятно.
     
  12. f13nd

    f13nd Active Member

    Публикаций:
    0
    Регистрация:
    22 июн 2009
    Сообщения:
    402
    Просто по наблюдениям, регистры это первое что будет отличаться в другой сборке того же алгоритма. Максимум что можно выдавить из битовых масок - оставить в них одни опкоды и характерные константы, относящиеся к алгоритму, а не к адресации локальных/глобальных переменных например. Для PE-файлов windows, повторюсь, всё это, в том числе регулярки на хексотекст работают очень условно. Считай не работают. Компилеры далеко не только регистры на свое усмотрение крутят. Даже объяснил в первом посте откуда в иде сигнатуры берутся и почему так.
    --- Сообщение объединено, 24 янв 2019 ---
    Если совсем "на кошках", то вот GetKeyState windows 8.1:
    Код (Text):
    1. .text:6BA8BBD0 8B FF                                   mov     edi, edi
    2. .text:6BA8BBD2 55                                      push    ebp
    3. .text:6BA8BBD3 8B EC                                   mov     ebp, esp
    4. .text:6BA8BBD5 64 A1 18 00 00 00                       mov     eax, large fs:18h
    5. .text:6BA8BBDB 53                                      push    ebx
    6. .text:6BA8BBDC 8B 80 70 0F 00 00                       mov     eax, [eax+0F70h]
    7. .text:6BA8BBE2 83 78 78 00                             cmp     dword ptr [eax+78h], 0
    8. .text:6BA8BBE6 0F 84 28 7F 03 00                       jz      loc_6BAC3B14
    9. .text:6BA8BBEC                         loc_6BA8BBEC:                           ; CODE XREF: GetKeyState(x)+37F4D↓j
    10. .text:6BA8BBEC 8B 5D 08                                mov     ebx, [ebp+nVirtKey]
    11. .text:6BA8BBEF 83 FB 20                                cmp     ebx, 20h
    12. .text:6BA8BBF2 0F 83 43 0F 00 00                       jnb     loc_6BA8CB3B
    13. .text:6BA8BBF8 64 A1 18 00 00 00                       mov     eax, large fs:18h
    14. .text:6BA8BBFE 8B 0D F0 40 B0 6B                       mov     ecx, _gpsi
    15. .text:6BA8BC04 8B 80 70 0F 00 00                       mov     eax, [eax+0F70h]
    16. .text:6BA8BC0A 8B 90 70 08 00 00                       mov     edx, [eax+870h]
    17. .text:6BA8BC10 3B 91 08 0F 00 00                       cmp     edx, [ecx+0F08h]
    18. .text:6BA8BC16 0F 85 1F 0F 00 00                       jnz     loc_6BA8CB3B
    19. .text:6BA8BC1C 0F B6 CB                                movzx   ecx, bl
    20. .text:6BA8BC1F BA 01 00 00 00                          mov     edx, 1
    21. .text:6BA8BC24 56                                      push    esi
    22. .text:6BA8BC25 8B F1                                   mov     esi, ecx
    23. .text:6BA8BC27 C1 E9 02                                shr     ecx, 2
    24. .text:6BA8BC2A 83 E6 03                                and     esi, 3
    25. .text:6BA8BC2D 57                                      push    edi
    26. .text:6BA8BC2E 33 FF                                   xor     edi, edi
    27. .text:6BA8BC30 0F B6 9C 01 74 08 00 00                 movzx   ebx, byte ptr [ecx+eax+874h]
    28. .text:6BA8BC38 8B C2                                   mov     eax, edx
    29. .text:6BA8BC3A 8D 0C 75 01 00 00 00                    lea     ecx, ds:1[esi*2]
    30. .text:6BA8BC41 D3 E0                                   shl     eax, cl
    31. .text:6BA8BC43 85 C3                                   test    ebx, eax
    32. .text:6BA8BC45 0F 85 7A FF 00 00                       jnz     loc_6BA9BBC5
    33. ...
    34.  
    GetKeyState XP SP3
    Код (Text):
    1. .text:7E379ED9 8B FF                                   mov     edi, edi
    2. .text:7E379EDB 55                                      push    ebp
    3. .text:7E379EDC 8B EC                                   mov     ebp, esp
    4. .text:7E379EDE 57                                      push    edi
    5. .text:7E379EDF 64 A1 18 00 00 00                       mov     eax, large fs:18h
    6. .text:7E379EE5 33 FF                                   xor     edi, edi
    7. .text:7E379EE7 39 78 40                                cmp     [eax+40h], edi
    8. .text:7E379EEA 0F 84 D2 4C FF FF                       jz      loc_7E36EBC2
    9. .text:7E379EF0                         loc_7E379EF0:                           ; CODE XREF: GetKeyState(x)-B30E↑j
    10. .text:7E379EF0 83 7D 08 20                             cmp     [ebp+nVirtKey], 20h
    11. .text:7E379EF4 73 56                                   jnb     short loc_7E379F4C
    12. .text:7E379EF6 64 A1 18 00 00 00                       mov     eax, large fs:18h
    13. .text:7E379EFC 8B 88 10 07 00 00                       mov     ecx, [eax+710h]
    14. .text:7E379F02 8B 15 80 10 3C 7E                       mov     edx, _gpsi
    15. .text:7E379F08 3B 8A 24 09 00 00                       cmp     ecx, [edx+924h]
    16. .text:7E379F0E 75 3C                                   jnz     short loc_7E379F4C
    17. .text:7E379F10 0F B6 4D 08                             movzx   ecx, byte ptr [ebp+nVirtKey]
    18. .text:7E379F14 56                                      push    esi
    19. .text:7E379F15 8B F1                                   mov     esi, ecx
    20. .text:7E379F17 C1 E9 02                                shr     ecx, 2
    21. .text:7E379F1A 0F B6 94 01 14 07 00 00                 movzx   edx, byte ptr [ecx+eax+714h]
    22. .text:7E379F22 33 C0                                   xor     eax, eax
    23. .text:7E379F24 83 E6 03                                and     esi, 3
    24. .text:7E379F27 40                                      inc     eax
    25. .text:7E379F28 8D 4C 36 01                             lea     ecx, [esi+esi+1]
    26. .text:7E379F2C D3 E0                                   shl     eax, cl
    27. .text:7E379F2E 85 C2                                   test    edx, eax
    28. .text:7E379F30 75 15                                   jnz     short loc_7E379F47
    29. .text:7E379F32                         loc_7E379F32:                           ; CODE XREF: GetKeyState(x)+71↓j
    30. .text:7E379F32 33 C0                                   xor     eax, eax
    31. .text:7E379F34 8D 0C 36                                lea     ecx, [esi+esi]
    32. .text:7E379F37 40                                      inc     eax
    33. .text:7E379F38 D3 E0                                   shl     eax, cl
    34. .text:7E379F3A 5E                                      pop     esi
    35. .text:7E379F3B 85 C2                                   test    edx, eax
    36. ...
    37.  
    Как бы корелляции видны, но что насчет сигнатуры на обе функции? Алгоритм-то один и вряд ли вообще исходник менялся с тех пор. В принципе для винды, у которой конечное число официальных сборок, можно обойтись конечным числом сигнатур. Но через битовые маски эта задача только так и решается. Если у нас есть библиотека функций X в составе программы Y, то даже регулярки не помогут. Можно хоть зачитаться пдфами об антивирусах дос-эпохи.
    --- Сообщение объединено, 24 янв 2019 ---
    Щас перечитываю, будто марсианин с марса вещает.
    В общем случае т.н. сигнатура выглядит так:
    05B8FFFFEB278A4606B4008BD8B8....8EC0
    или так:
    05B8FFFFEB278A4606B4008BD8B8????8EC0
    Или как-нибудь еще. Маска может отдельно задаваться и прочее.
    yara-сигнатуры выглядят как регулярные выражения. То же самое, по в синтаксисе RegEx.
    Смысл этих буквоцифр сводится к к тому, что мы получаем из этого паттерна:
    05 B8 FF FF EB 27 8A 46 06 B4 00 8B D8 B8 .. .. 8E C0
    маску:
    FF FF FF FF FF FF FF FF FF FF FF FF FF FF 00 00 FF FF
    и значение:
    05 B8 FF FF EB 27 8A 46 06 B4 00 8B D8 B8 00 00 8E C0
    Маску применяем логическим "И" на наши данные, обнулив незначащие биты (2 байта вон там в конце), и сравниваем со значением.
    У яры обработка чуть сложней, там всё колдунство над текстом происходит. Если знаете что такое регулярные выражения, должно быть понятно как.
    Потери происходят там, где в очередных 4 битах есть как значащие биты, так и те, которые не мешало бы выкинуть. Это происходит либо в сторону большего числа возможных ложных срабатываний или меньшего числа правильных срабатываний. Если приходится лавировать между разными факторами и хочется сделать экстремально короткую сигнатуру, но с максимальным выхлопом, эта 4битность так себе союзник.
    Если в короткой форме inc reg:
    01000rrr, где rrr - номер регистра
    то мы вынуждены либо взять оба нибла
    01000000 inc eax
    либо один нибл
    0100.... inc/dec rn
    И это практически по каждому формату инструкции так. Чаще всего выбором занимается машина на усмотрение разработчика утилиты, сгенерировавшей сигнатуру. А результатом пользоваться предстоит тебе.
     
  13. q2e74

    q2e74 Active Member

    Публикаций:
    0
    Регистрация:
    18 окт 2018
    Сообщения:
    259
    f13nd, ну, это я понял. Если бы мы говорили про железно-аппаратный фильтр, куда сигнатуры заливались бы, допустим по выделенному каналу, тогда имело бы смысл об этом думать. А так, это не большая плата за удобство для оператора, потому как ярой много чего ищется. Например, можно сделать правило по стрингам, вдруг там где-то домен прописан. С ярой изначально надо понимать, что будет временной лаг, между замеченным дампом и созданием правил. Но зато это возможно практически в любой организации рядовым сисадмином. ИМХО, яра - это инструмент ответа команды реагирования, а не превентивный антивирус на входном потоке. Вместе с rasm2 (от radare2) как инструмент, имеет не то что право на жизнь, а даже кое какие плюсы. Ведь существует как tshark, так и wireshark. Тут просто задачи разные. Ну такое мое мнение. Я думал он текстом ищет, в правила же "558BEC" текстом забиваются, а не байтовым потоком.
     
  14. f13nd

    f13nd Active Member

    Публикаций:
    0
    Регистрация:
    22 июн 2009
    Сообщения:
    402
    Я не заметил в какой момент речь пошла об антивирусах :superstition: Мне просто этот движок кажется странным и категорически не подходит, это не значит, что он совсем не работает и пользоваться им нельзя.
     
  15. q2e74

    q2e74 Active Member

    Публикаций:
    0
    Регистрация:
    18 окт 2018
    Сообщения:
    259
    Признаю, был не прав. Но и сравнивать задачу ТС поиска байтов в рантайме, с текстовым поиском по файлам - это тоже перебор. Кажется мне, что postgresql + jsonb такие задачи отработает быстрее яры.