Овощи.

Тема в разделе "WASM.HEAP", создана пользователем Clerk, 9 окт 2010.

  1. qqwe

    qqwe New Member

    Публикаций:
    0
    Регистрация:
    2 янв 2009
    Сообщения:
    2.914
    Clerk
    а вы задавайте задачки иногда. вроде как блэк миррор. интересное развлечение иногда подумать как в старые добрые времена.
     
  2. PSR1257

    PSR1257 New Member

    Публикаций:
    0
    Регистрация:
    30 ноя 2008
    Сообщения:
    933
    Clerk

    Выполнение кода на эмуляторе с синхронизацией исполнения в исследуемом процессе. Все попытки установки callback'ов переставляются на свои процедурки и уже в них управление передается на настоящие колбэки.

    Если честно, я так и не смог въехать в точную формулировку задачи :) Можно простейший пример (в виде схемы) - в чем конкретно сложность и чего именно нужно перехватить?

    Если исследуемый код просто обфусцирован (те просто попытка скрыть функциональность) и не напичкан системными вызовами - то я к примеру трассировал куски sys-драйвера через SEH в usermode а потом писал фильтры для лога.
     
  3. Clerk

    Clerk Забанен

    Публикаций:
    0
    Регистрация:
    4 янв 2008
    Сообщения:
    6.689
    Адрес:
    РБ, Могилёв
    PSR1257
    Кодом не совсем корректно описывать задачу. Доступ к ресурсу зависит от SFN. Тоесть:
    AcquireResource()
    Callback()
    ReleaseResource()
    Необходимо выполнить некоторые действия при освобождении ресурса.
     
  4. PSR1257

    PSR1257 New Member

    Публикаций:
    0
    Регистрация:
    30 ноя 2008
    Сообщения:
    933
    Clerk

    Попробую пересказать как я понимаю это (выполнение приведено как это выглядит во времени):

    Variant I.
    1. AcquireResource()
    2. return from AcquireResource;
    3. Callback(&ProcX); // Инициализация callback?!
    4. return from Callback(& ...
    (Сейчас в любой момент управление может быть передано на ProcX асинхронно)
    5. ... выполнение некоего кода сразу после Callback(&...
    6. ... Асинхронный вызов ProcX, возврат ...
    7. ReleaseResource()

    Variant II. ReleaseResource() находится внтури колбэка и вызывается асинхронно.
    1. AcquireResource()
    2. return from AcquireResource;
    3. Callback(&ProcX); // Инициализация callback?!
    4. return from Callback(& ...
    (Сейчас в любой момент управление может быть передано на ProcX асинхронно)
    5. ... выполнение некоего кода сразу после Callback(&...
    6. ... Асинхронный вызов ProcX, ReleaseResource() ВНУТРИ, возврат ...
    7. ...

    Какая схема является актуальной?

    Все происходит в SYS, и нельзя (нежелательно) прибегать к аппаратным методам отладки: любая возня с IDT (int 1,3 included) - лучше избежать, помечать страницы как выгруженные и поставить свой обработчик (врезка в старый тоже) PageFault - нельзя - ... - какие еще ограничения?

    Так или иначе, а по условию нельзя патчить ReleaseResource (саму) - ?, нельзя сажать в систему свой SYS чтобы ловить патченный импорт приложения - ReleaseResourceXXX.

    Все это в реальном времени или речь идет о де-обфускации (можно трейсить код часами и медитировать)?

    Ну и собственно главное - задача получить управление СРАЗУ ПОСЛЕ ReleaseRSRC?
     
  5. Clerk

    Clerk Забанен

    Публикаций:
    0
    Регистрация:
    4 янв 2008
    Сообщения:
    6.689
    Адрес:
    РБ, Могилёв
    PSR1257
    Не рассматривайте AcquireResource() как просто процедуру. Это может быть очень большой код, сотни вложенных процедур. Как например любой системный сервис, где управление начинается от входа в ядро и путь через множество процедур вглубь. Просто это механизм, который не позволяет выполнить некоторые действия в калбэке, они возможны только после возврата и освобождения ресурса.
    Незачем использовать всякий изврат с сепшенами и пр. Нужно просто спустится по стеку вызовов. Допустим ресурс свободен при SFN1, калбэк имеет SFN2 = SFN1 + M, он освобождается когда SFN <= SFN1.
     
  6. PSR1257

    PSR1257 New Member

    Публикаций:
    0
    Регистрация:
    30 ноя 2008
    Сообщения:
    933
    Clerk
    Опять непонятно :) Есть некий SYS, он вызывает AcquireResource тем самым где-то в глубине системы захватывая этот ресурс, далее все это когда-то вернется назад, будет выполнены другие команды этого же SYS и в самом конце - ReleaseResource.

    Callback-процедура же установлена Вами (?) самим приложением (?) и переиодически получая управление (или один раз - что за условие?) должна выполнить некое действие но при этом вначале нужно как-то узнать достигло ли управление ReleaseResource() (строго после возврата или допустимо выполнение следующих команд?).

    Callback-процедуре дозволяется (?) перехват перед Acquire, она может (?) в этот момент проводить анализ кода, стека... - ?
     
  7. Clerk

    Clerk Забанен

    Публикаций:
    0
    Регистрация:
    4 янв 2008
    Сообщения:
    6.689
    Адрес:
    РБ, Могилёв
    PSR1257
    Проще показать пример.
    Код (Text):
    1. NtCreateProcessEx
    2.    PspCreateProcess
    3.       MmInitializeProcessAddressSpace
    4.          PsMapSystemDll
    5.             MmMapViewOfSection
    6.             LOCK_ADDRESS_SPACE
    7.                MiMapViewOfImageSection
    8.                   PsCallImageNotifyRoutines
    9.                      Notify()
    10.             UNLOCK_ADDRESS_SPACE
    Это вызов LoadImage нотификатора при создании процесса. АП не доступно и пр. необходимый функционал. Нужно получить управление при возврате из PspCreateProcess(), тогда процесс инициализирован и можно выполнить необходимые действия.

    Код (Text):
    1. LdrInitializeThunk
    2. LdrpInitialize
    3. _LdrpInitialize
    4. LOCK_LOADER_LOCK
    5.    LdrpInitializeThread
    6.       LdrpCallInitRoutine
    7.          InitRoutine()
    8. UNLOCK_LOADER_LOCK
    Вызов "DllMain" при создании потока. Загрузчик залочен, необходимо выполнить некоторые действия после его освобождения и вобще по возврете из LdrpInitialize().

    Код (Text):
    1. NtReadVirtualMemory
    2.    MmCopyVirtualMemory
    3.       MiDoMappedCopy
    4.          MmProbeAndLockPages
    5.          LOCK_PFN
    6.             MmAccessFault
    7.             RAISE_IRQL
    8.             LOCK_WORKING_SET
    9.                MmPageFaultNotifyRoutine
    10.                   Notify()
    11.             UNLOCK_WORKING_SET
    12.             LOWER_IRQL
    13.          UNLOCK_PFN
    PageFault нотификатор, нужно выполнить некоторые действия при возврате из MmAccessFault().
     
  8. Clerk

    Clerk Забанен

    Публикаций:
    0
    Регистрация:
    4 янв 2008
    Сообщения:
    6.689
    Адрес:
    РБ, Могилёв
    Вот скрин отлично отражающий суть из топика про IDP:
    [​IMG]
    Большая часть сделанных реализаций этой техники требует понижение SFN для получения контроля на необходимой точке.
     
  9. Clerk

    Clerk Забанен

    Публикаций:
    0
    Регистрация:
    4 янв 2008
    Сообщения:
    6.689
    Адрес:
    РБ, Могилёв
    PSR1257
    Вот общая модель механизма:
    ; Routine() -> ... -> Notify().

    Initialize:
    Graph = CreateGraph(@Routine, NL = 1)

    Notify:
    Frame:PSTACK_FRAME
    Frame = rEbp
    Do
    if CheckIpBelongToGraph(Graph, Frame.Ip)
    Tls = AllocateTls()
    Tls.Ip = Frame.Ip
    Frame.Ip = @2ndDispatch()
    End
    endif
    Frame = Frame.Next
    Loop END_OF_CHAIN

    2ndDispatch:
    Payload()
    Jmp Tls.Ip
     
  10. PSR1257

    PSR1257 New Member

    Публикаций:
    0
    Регистрация:
    30 ноя 2008
    Сообщения:
    933
    Clerk

    О, спасибо - я наверное почти все понял.

    Код (Text):
    1. NtCreateProcessEx
    2.    PspCreateProcess
    3.       MmInitializeProcessAddressSpace
    4.          PsMapSystemDll
    5.             MmMapViewOfSection
    6.             LOCK_ADDRESS_SPACE
    7.                MiMapViewOfImageSection
    8.                   PsCallImageNotifyRoutines
    9.                      Notify(&OurCallBack)
    10.             UNLOCK_ADDRESS_SPACE
    11. ... где-то в нашем SYS ...
    12. OurCallBack proc
    13. ...
    В данном примере мы получаем управление внутри вызываемой OurCallBack и мы видим (?) куда будет выполнен возврат (а именно - в следующую инструкцию после Notify(&OurCallBack)), нам нужно каким-то образом поймать завершение процедуры в UNLOCK_ADDRESS_SPACE. Верно?

    Допустим мы точно знаем этот адрес - что далее? Мы будет патчить это место создавая переходник на втрой обработчик?
     
  11. Clerk

    Clerk Забанен

    Публикаций:
    0
    Регистрация:
    4 янв 2008
    Сообщения:
    6.689
    Адрес:
    РБ, Могилёв
    PSR1257
    Мы ищем в SFC необходимый фрейм с адресом возврата принадлежащим функции PspCreateProcess(). Если этот адрес найден, мы его(или следующий фрейм, это адрес возврата из PspCreateProcess()) заменяем на OurCallBack(у меня это 2ndDispatch()). После возврата выполняем необходимые действия и возвращаемся обратно на оригинальный адрес возврата. Проблема в определении необходимого фрейма, о чём и топик.
     
  12. PSR1257

    PSR1257 New Member

    Публикаций:
    0
    Регистрация:
    30 ноя 2008
    Сообщения:
    933
    Clerk

    Может быть прокатит идейка с эмулятором? Найденный фрейм PspCreateProcess() -> ссылка на системный модуль -> считываем его в user32 и выполняем на эмуляторе -> естественно после эмуляции мы знаем когда и как произошел возврат.

    Также можно предложить сигнатурный метод. Прогоняем для каждого конкретнго перехвата все это под отладчиком и накапливаем фреймы со стеков (может быть в разных версиях win тоже). То есть например с точностью до локации модулей адреса и данные конкретного фрейма будут выглядеть так:

    FRAME_BEGIN:
    RET_ADDRESS // Always belong to current IB of system module - то, чего нам нужно но мы точно его не знаем.
    // Но мы знаем что он ВСЕГДА +1000h...1800h от EP / Code section begin / etc.
    SAVED_EBP // Мы опять не знаем точного значения но мы знаем что это будет в пределах current_stack_space
    LOCAL_VAR1 // Какая-то локальная переменная, она всегда 0xC???????
    ...
    SOME_CONST1 // Допустим тут всегда ref to str - имя для AllocatePoolWithTag.
    ...
     
  13. Clerk

    Clerk Забанен

    Публикаций:
    0
    Регистрация:
    4 янв 2008
    Сообщения:
    6.689
    Адрес:
    РБ, Могилёв
    PSR1257
    Как найдём, если адрес возврата не известен ?
    Это никакой не перехват, а отложенный способ вызова кода на подобие DPC.
     
  14. PSR1257

    PSR1257 New Member

    Публикаций:
    0
    Регистрация:
    30 ноя 2008
    Сообщения:
    933
    Clerk

    Насчет сигнатуры фрейма. Имелось в виду ЗАРАНЕЕ составляем сигнатурки и потом используем их (уже в реалтайм) для скана стека в поисках нужного фрейма. Никакой трассировки.
     
  15. Clerk

    Clerk Забанен

    Публикаций:
    0
    Регистрация:
    4 янв 2008
    Сообщения:
    6.689
    Адрес:
    РБ, Могилёв
  16. Clerk

    Clerk Забанен

    Публикаций:
    0
    Регистрация:
    4 янв 2008
    Сообщения:
    6.689
    Адрес:
    РБ, Могилёв
    Хотелось бы услышать мнение главного овоща с рсдн..
     
  17. green

    green New Member

    Публикаций:
    0
    Регистрация:
    15 июл 2003
    Сообщения:
    1.217
    Адрес:
    Ukraine
    Clerk
    Мне кажется, Ваше решение не универсальное. Или чтобы быть таковым, потребует реализации анализатора кода, не уступающего по сложности движку IDA.
    Например, как Вы предлагаете строить граф в случае, если ф-ция содержит chunks, связанные косвенными переходами?
     
  18. Clerk

    Clerk Забанен

    Публикаций:
    0
    Регистрация:
    4 янв 2008
    Сообщения:
    6.689
    Адрес:
    РБ, Могилёв
    green
    Оно не нужно, очень редко это может понадобиться. Этого достаточно почти для всего системного кода.
     
  19. green

    green New Member

    Публикаций:
    0
    Регистрация:
    15 июл 2003
    Сообщения:
    1.217
    Адрес:
    Ukraine
    Clerk
    Гм..
    jump table - типичнейшая оптимизация сишного switch.
     
  20. PSR1257

    PSR1257 New Member

    Публикаций:
    0
    Регистрация:
    30 ноя 2008
    Сообщения:
    933
    Clerk

    Попробовал быстро вникнуть в Ваш сэмпл - навскидку нет - мне нужно время.

    Поэтому попробую опейсать идейку - это очень тупо и вроде бы очень просто реализуемо.

    Part I. "Дома"

    Берем отладчик, ida, все что нужно для анализа. Запускаем код и останавливаемся внутри нашей CallBack которую позвал Notify(). Поднимаясь вверх по стеку находим нужный фрейм и адрес возврата. Дампим фрейм в файл.

    Далее пытаемся составить СИГНАТУРУ (гибкую). В фрейме не только адрес возврата но и еще другие адреса и переменные и константы - все это ХАРАКТЕРНО для данного модуля и данной версии винды и конкретного порядка и расположения сисмодулей в памяти.

    Пытаемся абстрагироваться от конкретики - допустим (грубо) мы нашли что по смещению RET_ADDR-50h ВСЕГДА есть какая-то константа - например это было:

    push "MTag"
    ...
    call AllocatePoolWithTag

    В данном случае в фрейме ВСЕГДА есть "MTag". Также можно маскировать и адреса, допустим IB может быть разная но (например) разница элментов RET_ADDR-34h и RET_ADDR-48h всегда равна 120h. Даже если эта разница плавает от версии к версии винды, то мы все равно можем фильтровать: разница от 120h (min) до 180h (max).

    Можно продолжать долго но думаю что 4-8 фильтров должно хватить. Плюс проверки типа адрес принадлежит данному SYS, etc, etc.

    Part II. "В поле"

    В реальных условиях мы просто сканируем из CallBack стек вверх применяя сигны. Никой отладки и вообще участия человека уже не нужно, это все идентично распознаванию LibraryCode через сигны Flirt в IDA.

    Если мы нашли что данная сигна подошла мы делаем практически 100% заключение где адрес возврата и меняем его.