начал выкладывать подборку трюков препятствующих аттач на свой блог. фидбак всячески приветствуется. # try to attach to me: if you can! http://nezumi-lab.org/blog/?p=115 # attach to me: if you can (part II) http://nezumi-lab.org/blog/?p=122 # NtRequestWaitReplyPort abuses IDA-Pro http://nezumi-lab.org/blog/?p=139 # anti-attach: BaseThreadStartThunk => NO_ACCESS http://nezumi-lab.org/blog/?p=145 и для тех кто не боится зомби: http://nezumi-lab.org/blog/?p=143
У меня не работают эти трюки, после того как я пропустил создание потока нотификации ) Запустил олю под олей, а затем брякнулся сюда: Как тока происходит останов я перехожу на новый адрес 7С950852 и жму F12. Происходит останов - выполнен аттачь к процессу. Далее можно дебажить. Только один минус есть, оля не выполняет скан модулей, но думою это решится её патчем.
Матчасть(кому интересно). Аттачь выполняется сервисом NtDebugActiveProcess. После того как этот сервис вызван отладчик будет ждать возникновение событий в отлаживаемом процессе. Первое событие посылается кривым способом - создаётся удалённый поток в котором выполняется останов(DbgBreakPoint). Два способа выполнить аттачь: > DbgUiDebugActiveProcess(). К этой функции сводится DebugActiveProcess(). > Запрос на сервер. Один из сервисов Csrss позволяет выполнить аттачь. Для XP его ID = 0x30404. Оба варианта сводятся к вызову DbgUiIssueRemoteBreakin(), которая создаёт удалённый поток в отлаживаемом процессе со стартовым адресом DbgUiRemoteBreakin(). Последняя вызывает DbgBreakPoint() и далее поток завершается. При вызове DbgBreakPoint() выполняется инструкция Int 3, отладчику посылается сообщение об исключении. Собственно только к этой нотификации и сводится весь механизм. Как это скрыть и как это ловить является просто логическим выводом далее. Так как создаётся новый поток, он пройдёт весь путь начиная от входа в APC-диспетчер и до передачи управления на DbgUiRemoteBreakin(), поэтому каждая инструкция которую выполнит поток может быть перехвачена. Даже не нужна проверка потока на удалённость, например просто считать ThreadQuerySetWin32StartAddress и если адрес равен DbgUiRemoteBreakin(), то можно считать что выполнен аттачь. Эффективный способ словить создание потока и как следствие аттачь - установка точек останова на начало диспетчера. При начале исполнения потока управление получит диспетчер исключений в контексте нового потока, далее выполняется проверка на удалённость и пр. Способ обойти это - не создавать поток нотификации, а он и не нужен. Просто суспендить все потоки.
за фидбак спасибо. вот только я не согласен, что трюки не работают. они работают. другое дело, что Ольга позволяет их обойти и я там писал как. ловим создание потока, Ольга "всплывает". идем в окно threads. видим там системный поток (как видим? да по стартовому адресу хотя бы) и тупо киляем его ибо нафиг он нам нужен. после чего актуализируем основной поток и нормально его дебажим. мыщъх ведь прямо сказал - приттачься ко мне если сможешь и вовсе не утверждал, что приаттачиться вообще невозможно. приаттачиться _можно_ но для этого нужно совершить дополнительные телодвижения и нужно знать об этих трюках иначе ломаемая программа распознает факт аттача и... например, пустит отладчик по ложному следу. а если это малварь она может вычистить себя из памяти. вот только мне интересно как ты приаттачился к процессу который покоцал свой PEB. у меня Ольга его в упор не видит. или ты какой плагин использовал?
гм. сейчас попробовал твой метод. оригинально! покоцанный PEB не аттачит, остальное - работает. немного сложнее, чем мой способ (убивание системного потока), но зато твой способ креативнее и крышесрывательнее. запустить ольгу под ольгой я бы не додумался. ты не будешь против если я переведу твой пост и выложу его на свой блог с ссылкой на тебя?
kaspersky Не знаю как ты его ловил, я не читал. Сделой так. Поток начинается с APC-диспетчера, соответственно это экспорт ntdll!KiUserApcDispatcher. Чтобы не возиться с дизасмом длин просто поставь на него бряк(но не Int3, например инструкция Cli пойдёт) и мониторь исключения, например посредством VEH. Способ не очень хорош, в идеале нужно выполнить сплайсинг, в данном случае исполнится нотификация отладчика, но он не обработает STATUS_PRIVILEGED_INSTRUCTION, тоесть получит VEH управление, оттуда и прибивай поток. У меня JIT-ом является оля. В диспетчере задач жмём "Отладка" и всё окей. Я не протев.
Clerk > Не знаю как ты его ловил, я не читал. событие CREATE_PROCESS_DEBUG_EVENT при аттаче. впрочем, оно генерируется на довольно поздней стадии, когда часть кода в адресном пространстве ломаемого процесса уже успела выполниться, так что это можно и перехватить. в принципе. только ведь и твой способ можно обломать. в принцие. потому как ядро в процессе атача опирается на PEB и там можно например даже зациклить систему. т.е. мы аттачимся, а ядро циклиться. и усе. процесс даже прибить нельзя. а загрузка ядра 100%. (на одноядерных ЦП). правда это системно-зависимо. и нужно писать отдельный код для хрюши, висты и т.д., что не есть хорошо и маловероятно чтобы такие трюки можно было дотянуть до промышленного применения. > У меня JIT-ом является оля. В диспетчере задач жмём "Отладка" и всё окей. ага. теперь понятно. а я уж думал, что у тебя каким-то магическим способом File/attach заработал с которым собственно и борюсь. про борьбу с JIT планирую написать позднее, т.к. технически это не совсем аттач, хотя и способ подрубиться к процессу. > Я не протев. ок. вот так подойдет? "clerk /* a very clever guy from wasm.ru (http://www.wasm.ru/forum/profile.php?id=15484) */ offered another way to bypass anti-attach tricks... bla-bla-bla"
Clerk > Можно подробнее, как это ядро повесить, это невозможно.. на W2K SP4, XP SP3, S2K3 SP1 проверялось. можно. над Вистой мыщъх работает. Win7 - скорее всего зациклить невозможно. там короче где двунаправленные списки можно огранизовать запутанные петли, которая система не распознает и бегает по ним бесконечно. куча системных структур в PEB'е подвержена этому багу. уже на стадии выполнения OpenProcess мы имеем завис. нажимает Ctrl-D в айсе и видим как ядро бегает по испорченным структурам данных. наверное я неправильно выразился. ядро повесить конечно невозможно, но можно вызывать 100% загрузку ЦП в ядерном коде при исполнении OpenProcess. а без OpenProcess мы ничего умного сделать с ним не сможем. то есть конечно сможем например, если напишем драйвер. но это уже изврат. а так не смотря на 100% загрузку, система продолжает работать. на 2х ядерной машине загрузка всего 50% и потому тормоза уже незаметны. > Потести простейший пример. http://kpnc.org/to_clerk.gif облом-с ;(
kaspersky Ну в принципе да, там багов хватает. На XPSP2 помню баг был c NtSuspendThread, тоже ось вешало. Ну они там замутили.. NtSuspendProcess в экспорте есть, ZwSuspendProcess нет, хотя стубом является последняя.
Clerk зацени: # Olly loads Olly to bypass anti-attach tricks /* Clerk’ trick */ http://nezumi-lab.org/blog/?p=147
kaspersky Посмотрел. Очень просто: Когда жмём в меню File -> Attach, создаётся слепок(системинфо) процессов. Это делоет psapi!EnumProcesses(). Далее выполняется цикл, в котором открывается каждый процесс, извлекается имя первого модуля и добавляется в создаваемый список. Первый модуль возвращает psapi!EnumProcessModules(). Далее извлекается его имя с помощью psapi!GetModuleFileNameExA() 1. Если искажён PEB, либо Ldr не удастся считать инфу о модуле. psapi!EnumProcesses() Возвратит ноль и далее эта итерация заканчивается, следовательно процесс в конечный список не попадает. Делоем просто - условный переход по адресу(на фотке) 0x475213 заменяем на безусловный. Всё, теперь процесс попадёт в конечный список. Далее к нему можно аттачиться. 2. Так как psapi!GetModuleFileNameExA() извлекает имя из блока данных загрузчика, а он оказался не доступен, поэтому имя процесса оля не отобразит. Я сделол по хитрому. В томже модуле psapi.dll есть функция, которая возвращает полное имя процесса в NT-формате - GetProcessImageFileNameA. Эта функция сводится к сервису NtQueryInformationProcess(ProcessImageFileName). Значит мы должны заменить вызов psapi!GetModuleFileNameExA() на GetProcessImageFileNameA с учётом поправки параметров в стеке. Я сделол мост: Код (Text): push dword ptr [esp + 10h] push dword ptr [esp + 10h] push dword ptr [esp + 0Ch] call PSAPI.GetProcessImageFileNameA ret Этот код записал в гиперпространство(конец секции кода), а ссылку заменил в стеке(ссылка на переменную). После этих манипуляций мы получаем список всех процессов, независимо от памяти загрузчика, да есчо и с абсолютными путями:
ну ты прямо тут целый ресерч развернул. мыщъх так же нашел этот код в Ольге (просто установил бряки на OpenProcess, ntdll!ZwQuerySystemInformation, ntdll!ZwQueryInformationProcess. обнаружил циклический вызов OpenProcess, дождался "своего" PID'а (процесса с разрушенным PEB'ом) и стал смотреть почему он не появляется в списке процессов. думаю, что можно сделать патч для ольги. ИМХО самый простой путь - это просто делать аттач по заданную PID'у (ч/з Attachtoactiveprocess(int newprocessid)), а сам PID можно узнать например из диспетчера задач. еще как вариант - отпачить Ольгу, но плагин имхо все же лучше
kaspersky Я думол тебе интересно.., ну да ладно, я себе пропатчил(кому нужно вот): http://openfile.ru/205605/ Версия оли: 1.0.10.0 ps: вобщем то я довольно редко прибегаю к аттачу в оле, большинство задач я решаю средствами ядерного отладчика. Есчо мне кажется что желательно имена функций и пр. выделять в постах жирным шрифтом..
Clerk конечно, интересно! прочитал с большим удовольствием!!! вот только у меня аттач к процессу с покоцанным PEB'ом так и не работает, причем не работает на уровне системы (W2K), при попытке выполнения DebugActiveProcess даже безо всяких отладчиков система материться, что не может к нему подключиться... хрюшу еще не пробовал. p.s. имена выдедил
kaspersky Да ты прав, это смотря как PEB испортить. Ядро при аттаче из двух функций в PEB пишет, это DbgkpMarkProcessPeb(), она устанавливает один байт - поле BeingDebugged. Вторая функция лезет уже в загрузчик, пока не смотрел зачем.. это DbgkpPostFakeModuleMessages(). Я и не знал что ядро Ldr юзоет.. В принципе обойти можно всё, тока тут уже вероятно юзермодом не ограничиться. [Посмотрел, вобщем тока чтоб базу модуля считать, и поместить её в DBGKM_LOAD_DLL, далее эта инфа на отладочный порт отсылается.]
У кого-то остался живой патч оли ?! Так и не смог внятно перевести то что написано в блоге незуми http://nezumi-lab.org/blog/?p=147