Avanguard: The Win32 Anti-Intrusion Library

Тема в разделе "CHEATS", создана пользователем HoShiMin, 17 мар 2019.

Метки:
  1. HoShiMin

    HoShiMin Well-Known Member

    Публикаций:
    5
    Регистрация:
    17 дек 2016
    Сообщения:
    1.455
    Адрес:
    Россия, Нижний Новгород
    С одной стороны, Avn в этой ситуации всё сделал правильно - нет оснований для блокировки. С другой - напрашивается более "глубокий" анализ трейса, чтобы понять, мог ли вообще поток оказаться на каждом фрейме из предыдущего
     
  2. Indy_

    Indy_ Well-Known Member

    Публикаций:
    4
    Регистрация:
    29 апр 2011
    Сообщения:
    4.775
    HoShiMin,

    > Здесь, как ни крути, для защиты нужны твои визоры

    Смотри вот что под визором у тебя. На первом скрине в лог идут базовые события, это ядерные обратные вызовы(Ki*, системные инструкции и три события NtAlloc/NtMap/NtProtect). На втором тоже, но без Nt*. Третий скрин это выборка из твоего модуля в ntdll, проверка целостности. Последний скрин это сервисный лог в цикле видно что проверяется память. Визор не видит инжект, так как он выполняется в его контексте.
     

    Вложения:

    • vi.png
      vi.png
      Размер файла:
      97,2 КБ
      Просмотров:
      327
    q2e74 нравится это.
  3. Indy_

    Indy_ Well-Known Member

    Публикаций:
    4
    Регистрация:
    29 апр 2011
    Сообщения:
    4.775
    HoShiMin,

    Попробовал обойти проверку целостности. Можно накопить адреса, откуда происходит чтение:

    df.png

    Далее пропатчить их на стабы и подменять адрес на оригинальную копию секции:

    thunk.png

    Крэшит на int29:

    Код (Text):
    1. 709c60ee e86acafaff      call    Avanguard!JNI_OnLoad+0x3836 (70972b5d)
    2. 709c60f3 e97bffffff      jmp     Avanguard!JNI_OnLoad+0x56d4c (709c6073)
    3. 709c60f8 33c9            xor     ecx,ecx
    4. 709c60fa cd29            int     29h
    5. 709c60fc c645fc00        mov     byte ptr [ebp-4],0
    6. 709c6100 8d4d8c          lea     ecx,[ebp-74h]
    7. 709c6103 e855cafaff      call    Avanguard!JNI_OnLoad+0x3836 (70972b5d)
    8. 709c6108 e966ffffff      jmp     Avanguard!JNI_OnLoad+0x56d4c (709c6073)
    Те в списке это выборка из ag в nt. В свой же образ отследить сложнее, нужно маркировать код и искать его чтение. Наверно где то есчо есть выборки ?

    Теоретически ведь должно сработать.
    --- Сообщение объединено, 19 фев 2020 ---
    Есть символы, адреса из _t1ha0_ia32aes_avx(). Походу не все выделены :scratch_one-s_head:

    Код (Text):
    1.         VOID FindChangedModules(__out std::set<HMODULE>& ChangedModules) const {
    2.             ChangedModules.clear();
    3.             Lock.LockShared();
    4.             for (const auto& Module : Modules) {
    5.                 UINT64 CurrentHash = CalcModuleHashSafe(Module.second.ExecutableSections);
    6.                 if (CurrentHash && Module.second.Hash != CurrentHash) {
    7.                     ChangedModules.emplace(Module.second.Base);
    8.                 }
    9.             }
    10.             Lock.UnlockShared();
    11.         }
    --- Сообщение объединено, 19 фев 2020 ---
    Если посмотреть адреса возврата при чтении ntdll, то всего 4 адреса. Если при выборке к avn проверять адрес возврата на эти 4-ре, то получаются выборки:

    dstk.png

    Если каждый исполняемый адрес в avn маркировать(всю инструкцию), а затем отследить чтение по этим адресам, получается 8 инструкций:

    dxmap.png

    Где есчо память читается хз :dash1:
     

    Вложения:

    • Pay.7z
      Размер файла:
      682,5 КБ
      Просмотров:
      297
    q2e74 нравится это.
  4. Indy_

    Indy_ Well-Known Member

    Публикаций:
    4
    Регистрация:
    29 апр 2011
    Сообщения:
    4.775
    HoShiMin,

    Инжект через запись в память, тоже не палится:

    ij6.png
    --- Сообщение объединено, 21 фев 2020 ---
    HoShiMin,

    Вот твоя ошибка.

    sa.png
     

    Вложения:

    • Ij6.7z
      Размер файла:
      400,1 КБ
      Просмотров:
      299
    HoShiMin и q2e74 нравится это.
  5. HoShiMin

    HoShiMin Well-Known Member

    Публикаций:
    5
    Регистрация:
    17 дек 2016
    Сообщения:
    1.455
    Адрес:
    Россия, Нижний Новгород
    Indy_, ты прям разошёлся, инжектишь в хвост и в гриву)
     
  6. Indy_

    Indy_ Well-Known Member

    Публикаций:
    4
    Регистрация:
    29 апр 2011
    Сообщения:
    4.775
    HoShiMin,

    Так ведь нужно было с тестов и начинать. Вот есчо твой косяк - можно изменять тип доступа к секциям любого модуля и никакой реакции нет. Секции с импортом тоже нужно проверять, они имеют тип R, можно туда записать указатели. А самая жесть это буфера для патчей RWE, можно найти такой буфер и туда загрузиться. Или вот есчо:

    Код (Text):
    1. .text:10163259                 jmp     _OriginalApcDispatcher
    2. .text:10163259 _KiApcStub@0    endp
    3.  
    4. .data:1033C328 _OriginalApcDispatcher
    - указатель в секции данных, не защищён.
     
  7. Indy_

    Indy_ Well-Known Member

    Публикаций:
    4
    Регистрация:
    29 апр 2011
    Сообщения:
    4.775
    Прикинул как можно управление получить переписав глобальный указатель, их не много. Для исключений указатели шифруются RtlEncodePointer(). Ключ нельзя получить из чужого процесса. Но можно выполнить обратную крипто функцию для известного указателя, к примеру UnhandledExceptionFilter.

    V = (K xor P) ror (K & 31); V и P известны, можно как то решить кроме брута.. хотя не важно, на весь перебор ~6s.

    Все указатели защищены cfg, тогда проще переписать функцию проверки cf: guard_check_icall_fptr, R секция mrdata:

    cf.png
    - адреса возврата из этой функции, видно что активно вызывается вектор. Заодно и проблем с cfg в таком случае не будет.
    --- Сообщение объединено, 23 фев 2020 ---
    Через cfg получается самое просто.

    cfg.png
     

    Вложения:

    • ij7.7z
      Размер файла:
      3,4 КБ
      Просмотров:
      276
    q2e74 нравится это.
  8. Indy_

    Indy_ Well-Known Member

    Публикаций:
    4
    Регистрация:
    29 апр 2011
    Сообщения:
    4.775
    С RtlEncodePointer не вышло из за коллизии хэшей. Оказалось есть RtlEncodeRemotePointer(), которая аналогична. Можно из другого процесса этот ключ получить.

    veh.png
     

    Вложения:

    • ij8.7z
      Размер файла:
      6,3 КБ
      Просмотров:
      266
  9. Indy_

    Indy_ Well-Known Member

    Публикаций:
    4
    Регистрация:
    29 апр 2011
    Сообщения:
    4.775
    HoShiMin,

    Что думаешь на счёт этого всего ?
     
  10. HoShiMin

    HoShiMin Well-Known Member

    Публикаций:
    5
    Регистрация:
    17 дек 2016
    Сообщения:
    1.455
    Адрес:
    Россия, Нижний Новгород
    Полагаю, более глубокий анализ трейса и проверка всей исполняемой памяти на каждую попытку что-то подгрузить должны помочь. На LdrLoadDll и на NtContinue проверять не просто принадлежность фрейма валидному модулю, а проверять, мог ли поток оказаться там, где оказался, исходя из всех предыдущих фреймов (думаю, это задетектит и ROP-цепочку). И сверять хэши секций, чтобы искать код-кейвы.
    Загрузка модулей и смена контекста - не такая частая операция, можно не беспокоиться о снижении производительности из-за проверок в этих местах.
    --- Сообщение объединено, 25 фев 2020 ---
    Между тем, подобными техниками обходят и ААА-античиты и пока эффективного средства защиты нет.

    Но это слишком сложные обходы. Ничто не мешает добавить в импорты одной из неподписанных системных библиотек, которая грузится приложением, свою дллку. И, не имея огромной базы с хэшами всех системных библиотек всех версий, а также базы с сигнатурами читов, практически невозможно отличить обычную дллку от дллки чита.
    --- Сообщение объединено, 26 фев 2020 ---
    Возможно, здесь нашли бы применение нейросети, по набору импортов, экспортов и структуре кода предугадывая опасность дллки, но - на чём их обучать?
     
  11. Indy_

    Indy_ Well-Known Member

    Публикаций:
    4
    Регистрация:
    29 апр 2011
    Сообщения:
    4.775
    HoShiMin,

    Я только хотел написать что ты не разговорчивый совсем.. :sad:

    > мог ли поток оказаться там, где оказался, исходя из всех предыдущих фреймов (думаю, это задетектит и ROP-цепочку).

    Это несомненно тупик. Нельзя предсказать последовательность, ранее вроде обсуждали что это можно сделать двумя путями(визор и наследование указателей).

    В данный момент мне вот что интересно. Так как все функции определены cfg защитой(описаны начала), то передать управление безопасно при включённой проверке(guard_check_icall_fptr) можно лишь сформировав спец вызов. Для этого нужно два параметра в секции данных(вектор и аргумент), при этом необходимо найти функцию, которая приведёт к вызову аргумента. Вручную это найти не представляется возможным, как это провернуть автоматикой пока не понятно.

    Есчо есть нюанс по какому то из инжектов выше. Там где была попытка обойти патчи.
    Инструкции копировались вручную, это дикий колхоз", так не делается, впрочем как и не ставятся патчи. Сделано было по одной причине - старый мотор для пересборки графа(kite) использовал 86 базовый малварный диз длин. А у тебя там новая математика, поэтому я пересобрал с intel-xed. Перемещает всё, весь твой код с выборкой и весь нэйтив без ошибок. Могу выложить сборку если интересно.
    --- Сообщение объединено, 26 фев 2020 ---
    Да и есчо есть вопрос. Если твой семпл запустить под олли это вешает ядро 8-ки на пару минут(что даже звук ось перестаёт воспроизводить). Такое происходит и на 7-ке под варей. Интересно как это ?
    --- Сообщение объединено, 26 фев 2020 ---
    HoShiMin,

    > Но это слишком сложные обходы.

    Я тебе отвечу вот этой цитатой:

    Это значит что нет понятия сложности, а есть понятие уязвимости.
     

    Вложения:

  12. HoShiMin

    HoShiMin Well-Known Member

    Публикаций:
    5
    Регистрация:
    17 дек 2016
    Сообщения:
    1.455
    Адрес:
    Россия, Нижний Новгород
    Разумеется интересно.

    Вообще, я с ROP'ами раньше не сталкивался, но подозреваю, что в момент, когда из них вызывают функцию, на которую мы поставим фильтр, где-то они спалятся.

    Допустим, мы не сможем проследить прямую цепочку вызовов, но можем ли косвенно определить, что стек подозрительный?
    Например, как будет выглядеть фрейм перед фреймом первого гаджета в цепочке? Откатываемся на несколько байт назад от адреса возврата и пытаемся подобрать инструкцию, которая привела бы нас на первый гаджет. Сразу подозрительно, если не получается сформировать call или push/jmp из N предшествующих байт. Возможно, стоит подизасмить вокруг фреймов - велика вероятность наткнуться на несуществующие или недопустимые инструкции. В совокупности - основание для блокировки.

    Именно под олли? Без неё или с другим отладчиком всё норм? У себя не сталкивался.
    Все античиты априори уязвимы, потому что полная неуязвимость сделала бы неработоспособным защищаемое приложение: слишком много точек входа, которые требуется держать открытыми, чтобы не сломать совместимость с другим софтом. И тут уже приходится выбирать между юзабельностью и дозволенным диаметром дыр.
     
  13. Indy_

    Indy_ Well-Known Member

    Публикаций:
    4
    Регистрация:
    29 апр 2011
    Сообщения:
    4.775
    HoShiMin,

    > можем ли косвенно определить, что стек подозрительный?

    Не заворачивайся на этом, поверь это тупик. Можно любые фреймы сформировать. Был защитный тулз EMET, там это пытались реализовать, но всё бестолку.

    > Именно под олли? Без неё или с другим отладчиком всё норм?

    Именно под отладчиком. Я раньше не говорил тк думал что ты знаешь про такое поведение..

    Есчо есть интересный момент. Весьма давно при отработке обхода cfg я заметил что контекст остановленного потока не читаем, хоть сервис и возвращает s_success. Тогда я так и не понял почему. Но вот на одном из семплов выше произошла та же ситуация, я пытался опять повторить но безуспешно. В какой то ситуации на XP и 8 запрос контекста возвращает полностью обнулённый и NtGetCtx() == STATUS_SUCCESS. Это какой то плавающий баг связанный с последовательностью suspendprocess/suspendthread/getctx.
     
  14. HoShiMin

    HoShiMin Well-Known Member

    Публикаций:
    5
    Регистрация:
    17 дек 2016
    Сообщения:
    1.455
    Адрес:
    Россия, Нижний Новгород
    Вот это и подвисание ядра заинтересовало. Когда будет время, гляну.
    Особенно интересно, потому что я никаких трюков внутри не делаю - никакого влияния на ядро сам эйвон не оказывает, а значит, воспроизводиться должно и на простых сэмплах.
    В каком-то из разделов здесь недавно кто-то тоже возился с подобной проблемой - возвращался пустой контекст при замороженном процессе...
     
  15. Indy_

    Indy_ Well-Known Member

    Публикаций:
    4
    Регистрация:
    29 апр 2011
    Сообщения:
    4.775
    HoShiMin,

    > Вот это и подвисание ядра заинтересовало. Когда будет время, гляну

    Это не относится к висяку, разные проблемы не связанные.

    > возвращался пустой контекст при замороженном процессе...

    Можешь поискать тему ?
     
  16. HoShiMin

    HoShiMin Well-Known Member

    Публикаций:
    5
    Регистрация:
    17 дек 2016
    Сообщения:
    1.455
    Адрес:
    Россия, Нижний Новгород
    https://wasm.in/threads/vyzova-dllmain.33603/
    Вроде, оно. В PsGetContext отдаём юзермодный буфер, отдаём флажок UserMode - должны получить контекст.
    То, что ТС сделал через Psp - хоть и работает, но костыль. Когда писал кб, у меня работало и через Ps. Видимо, что-то с тех пор поменялось.
     
  17. Indy_

    Indy_ Well-Known Member

    Публикаций:
    4
    Регистрация:
    29 апр 2011
    Сообщения:
    4.775
    HoShiMin,

    Так там совсем иное. Не знаю с чем это связано, я давно очень пытался воспроизвести баг и вчера-сегодня, безуспешно. Хотя и можно было, на билде стабильно была ошибка, но я по своей тупости или спешки как лучше сказать его потерял.. при сборке множества проектов за час столько семплов, что уже и не найти где нужный. Перебор саспенд тред/процесс/апк и их комбинации ошибку не воспроизводят.

    Ну а на счёт висяка могу попробовать записать видос. Не уверен что получится, если в олли на 8-64 я открою твой Tc.exe ось встанет минут на пять.
     
  18. UbIvItS

    UbIvItS Well-Known Member

    Публикаций:
    0
    Регистрация:
    5 янв 2007
    Сообщения:
    6.243
    Друзья, хомячка (то бишь антиинжект) можно довольно весело обойти..

    1. грузим пацЫЁнта под виртой.
    2. зеркалим целевые функи/либы в память хоста и тамо их пачим.
    3. при сверке хэш-сумм да маркеров хомячок видит оригинальное тело портянки, а вот на исполнение цепляем зеркала.
    ====
    технически, правда, можно хомячка развивать на борьбу против такой методЪЫ. Но трудозатраты (на такие алго) и ресурсоёмкость (таких алго) не стоит свечЪЪЪ :)
     
  19. galenkane

    galenkane Active Member

    Публикаций:
    0
    Регистрация:
    13 янв 2017
    Сообщения:
    301
    что если накрыть вирт.машиной сие чудо?
     
  20. UbIvItS

    UbIvItS Well-Known Member

    Публикаций:
    0
    Регистрация:
    5 янв 2007
    Сообщения:
    6.243
    о каком "чуде" речь?