Сейчас на форуме: Magister Yoda (+3 невидимых) |
![]() |
eXeL@B —› Основной форум —› Вопросы по написанию универсального распаковщика |
<< . 1 . 2 . 3 . >> |
Посл.ответ | Сообщение |
|
Создано: 16 января 2009 11:21 · Поправил: Wolfram · Личное сообщение · #1 Привет всем! Форум читаю достаточно давно, узнал много нового, но сейчас возникли вопросы, на которые я не смог ответить самостоятельно, поэтому прошу помощи. Сначала краткая предыстория. Крякингом я занимаюсь меньше полугода, научился за это время ломать сильно тупые защиты, где разработчик понадеялся на упаковщик/протектор. Автоматическим распаковщиком (или на "полуавтомате" - break'n'enter - EP - bpm esp-4 - OEP - dump - ImpRec) снимаем защиту, патчим пару байт - и готово. Но это, понятно, проходит далеко не всегда. Тупая защита + не самый простой пакер = приехали ![]() И где-то месяца 2 назад я начал писать собственный универсальный распаковщик. Принцип действия у него задумывается такой: - создаём замороженный поток. - в EP втыкаем хук (jmp eip, чтобы не трассировать стандартным методом через TF, что обычно палится защитой) отпускаем программу до EP, замораживаем (SuspendThread), снимаем хук. - далее эмулируем работу подопытной программы на виртуальных регистрах, но на её реальной памяти (Read/WriteProcessMemory). - при этом ловим программу при возникновении исключений на входе в обработчик и на выходе из него; на возврате из системных вызовов (KiFastSystemCallRet); вообще, полностью отслеживаем передачу управления. Для этого предусмотрено втыкание хука в любое нужное место. - на всём пути выполнения каким-либо образом запоминаем порядок передачи управления и адреса участков памяти, которые были изменены в адресном пространстве подопытной программы. - когда доходим до OEP (определим, например, на основе статистики по нескольким файлам, покарёженных одним и тем же пакером), дампим всё, что было изменено. - восстанавливаем импорт (пока с этим вопросом подробно не разбирался) - делаем ещё какие-нибудь дополнительные приседания - получаем рабочий дамп, который можно изучать в дизассемблере ![]() Понятно, что, например, для Armadillo дополнительных приседаний будет очень много, но ASProtect вполне мог бы поддаться на такую провокацию. С него я и решил начать. Запаковал виндовский блокнот с помощью ASProtect2.1, научился проходить на EP и стал "обучать" свой распаковщик ассемблерным инструкциям по одной. Проверка простая: если при встрече с незнакомой инструкцией актуализировать контекст и отпустить программу (ResumeThread), и она не грохнется, то с большой вероятностью все предыдущие инструкции выучены правильно. <отредактировано Wolfram> (Перенёс первый вопрос в свой второй пост, чтобы он не повторялся на каждой странице) Заранее спасибо за ответы. Прошу модераторов не закрывать данную тему, когда они будут получены, потому что распаковщик пишется, и новые вопросы непременно будут возникать. ![]() |
|
Создано: 18 января 2009 06:00 · Личное сообщение · #2 Gideon Vi Обучалась вобщем так: Уних в базе были забиты пакеры-проты и когда что то попадалось новое эта прога анализировала действия крякера в отладчеке и добавляла в свою базу новый способ распаковки. И если напремер прот вел себя не совсем стандартно но есть на него сигнатура и способ взлома она могла додумать как поступить в том или ином случае. Например как в аспре исключительные ситуации или импорт,прога такое запросто фиксила сама. Вобщем теми людми кто это писал был проделан адский труд. Приятно было посмотреть на такого монстра в действии. ![]() |
|
Создано: 18 января 2009 06:23 · Личное сообщение · #3 |
|
Создано: 18 января 2009 07:27 · Личное сообщение · #4 |
|
Создано: 18 января 2009 07:57 · Личное сообщение · #5 |
|
Создано: 18 января 2009 09:11 · Личное сообщение · #6 F_a_u_s_t пишет: Уних в базе были забиты пакеры-проты и когда что то попадалось новое эта прога анализировала действия крякера в отладчеке и добавляла в свою базу новый способ распаковки. Это типа фантазии на тему любимого китайцами олимашин ![]() Пока что ничего круче темного анпакера не выплывало. Такая же байка ![]() |
|
Создано: 18 января 2009 10:47 · Личное сообщение · #7 PE_Kill пишет: А это как вообще может быть? Эмулируешь команды, а ругается винда??? Как при эмуляции прога может упасть??? Может возникнуть эксепшн в эмуляторе, но прога то при чем, это же не процесс а образ в эмуляторе. ИМХО понос мыслей. Нет, это именно процесс, который запускается и тормозится на EP. Может быть, следовало написать "трассировка" вместо "эмуляция" (мне кажется, что здесь и то, и другое), но принцип такой: анпакер работает на виртуальных регистрах (переменные в адресном пространстве анпакера) и на памяти программы (в её адресном пространстве). Через ReadProcessMemory читаем очередную инструкцию, если нужно, читаем некоторую область памяти программы (ReadProcessMemory), изменяем значения переменных, соответствующих регистрам, изменяем некоторую область памяти программы (WriteProcessMemory). При встрече с неописанной пока инструкцией делаем SetThreadContext и ResumeThread. И если перед этим мы что-то не то сделали в адресном пространстве проги, или установили не тот контекст, то она упадёт! Поскольку падает не на первой инструкции, то, думаю, такой метод имеет право на существование. Archer пишет: Глядя на концепт-сразу скажу про потенциальные косяки и ограничения: -патчить код на оеп не всегда хорошо, ТЛС коллбек может пропалить это; -полная эмуляция кода распаковщика штука адская, учитывая трюки антэмуляции и тд, писать будешь до пенсии; -если дампить всё, что изменено, дамп будет под 100М, ибо там будет стек, куча, возможно, патч системных либ и фиг знает, что ещё; -если за основу ОЕП брать статистику по пакеру, это не generic unpacker, а multi unpacker, другими словами, неизвестное не возьмёт; -не совсем ясно, как ставится хук, если за основу взят DebugApi-это зло; -некоторые концептуальные вещи могут быть не охвачены, типа многопоточности: иногда расшифровкой кода занимается 1 поток, он запускает поток 2, который и идёт на оеп, а 1 дохнет, как это будет обработано-хз. Я не ставлю цель, чтобы брал всё и сразу. Про TLS и многопоточность знаю, но не все же пакеры их используют. Обработку всех этих фишек буду прикручивать потом, а пока считаем, что их нет. Хук в моём анпакере - это 2 байта 0xebfe (jmp eip). Если нужно, чтобы какой-то кусок кода исполнила сама программа, то сразу после него втыкается такой хук, а затем ждём, когда управление дойдёт до него, а дальше, очевидно, не пройдёт. Теперь останавливаем поток и возвращаем оригинальные байты на место. Этот метод я уже проверил, пока работает без косяков. Если не сложно, расскажи, пожалуйста, про трюки антиэмуляции, которые могут испортить жизнь при _таком_ подходе (кроме многопоточности). Собственно, к вопросу про mov. SetThreadContext работает, но как-то странно. Устанавливается только eip, остальные регистры остаются без изменений. Кто-нибудь может объяснить, почему так происходит, и что с этим делать? ![]() |
|
Создано: 18 января 2009 11:33 · Личное сообщение · #8 Трюков антиэмуляции может быть много, начиная с того, что цикл какой-нить с парой инструкций выполняется много раз, на чём эмуль задумается надолго, и заканчивая вызовом разных апишек (а ты их не эмулишь, как я понял) и дальше управление может быть передано (может, апи хитрая, может, код подправлен) в произвольное место, а не сразу после её вызова, тогда контроль потеряешь. Обращения к невалидной памяти тоже хз, как эмулить будешь, надо исключение кидать, а чтоб не потерять управление разглядывать СЕХИ/ВЕХИ/UnhandledExeceptionFilter. Это из основного, что сходу в голову пришло. С SetThreadContext, имхо, после ЕП не может он работать странно в 1 потоке. Сам забыл выставить регистры в контексте, флаги контекста, проверяешь неправильно или что ещё. Не совсем понятно, как анпакер может обучаться. В теории оно звучит хорошо, конечно, а в реальности хз. Видео даёшь ему посмотреть, что ли, а он втыкает и учится... ![]() |
|
Создано: 18 января 2009 12:38 · Поправил: AlexZ · Личное сообщение · #9 |
|
Создано: 18 января 2009 14:12 · Личное сообщение · #10 |
|
Создано: 18 января 2009 15:35 · Поправил: mak · Личное сообщение · #11 F_a_u_s_t Прав что есть такой анпакер. Всплывать он и не будет , люди которые его делали занимаются наукой и делом. На вопрос бываете ли вы на форумах по системам защиты, ответ был таков - нет не бываем , мы учим будущие поколения , все самые новые технологии рождаются у нас. У меня есть повод , ну оч большой доверять им по самое нехочу. ASMax в шутку называют так сами разработчики , есть 2 варианта реализации. Первый это был не столь интересный , в основном методы математические по ИИ. А вот потом был бум , был создан организм , как его назвать фиг знает , он как бы и техниа и живой , он может думать как человек и в тоже время является кибермашиной. В основу мозга положена находка биологов. Которые нашли жизнь схожую с нашей, но которая перестала развиваться по каким то причинам. Это особый кристаллический состав , точнее это квазикристалический состав. Его мощность мыслительсная состоит просто из невероятной вычислетельной силой и скорости обучения. А вообще второму виду мало уделяют внимания , имеется ввиду по анпкам, потому что с такой машиной появились другие задачи. Archer скоро увидишь =) уже вон сколько людей над этим работают ----- RE In Progress [!] Coding Hazard [!] Stay Clear of this Cube ![]() |
|
Создано: 18 января 2009 16:30 · Личное сообщение · #12 |
|
Создано: 18 января 2009 16:37 · Личное сообщение · #13 |
|
Создано: 18 января 2009 18:25 · Личное сообщение · #14 Я понял, мы все умрём, боты нас поработят. Не то, чтобы я совсем не верил в движение прогресса и революционные открытия, но как-то сомнительно, что они придут ко мне, чтоб анпачить мне упх. Предвижу тут адский оффтоп, поэтому сразу говорю, давайте с этим понемногу завязывать и ближе к теме держаться. ![]() |
|
Создано: 18 января 2009 18:27 · Личное сообщение · #15 mak пишет: был создан организм , как его назвать фиг знает , он как бы и техниа и живой , он может думать как человек и в тоже время является кибермашиной. В основу мозга положена находка биологов. Которые нашли жизнь схожую с нашей, но которая перестала развиваться по каким то причинам. Это особый кристаллический состав , точнее это квазикристалический состав. Его мощность мыслительсная состоит просто из невероятной вычислетельной силой и скорости обучения. Ссылками на материалы по теме не угостишь? Можно даже на мед.ресурсы, так даже лучше. ----- Я медленно снимаю с неё UPX... *FF_User* ![]() |
|
Создано: 19 января 2009 02:17 · Личное сообщение · #16 to all: Ну конечно все это чушь,просто решил проверить теорию спекза что флудерры номер 1 как раз старички а не нубики. ![]() Извините меня не удержался. mak Я тоже где то читал подобное ну как сказал Gideon Vi Идея отладки такого рода систем на апаке смешна и нелепа... другое дело научные иследования. Archer Обещаю больше не ставить таких флудерских экспериментов. ![]() |
|
Создано: 19 января 2009 02:25 · Личное сообщение · #17 |
|
Создано: 19 января 2009 02:30 · Личное сообщение · #18 |
|
Создано: 19 января 2009 10:42 · Личное сообщение · #19 |
|
Создано: 20 января 2009 15:33 · Личное сообщение · #20 |
|
Создано: 28 января 2009 15:41 · Личное сообщение · #21 Это снова я со своим распаковщиком. Проблему с неустанавливающимся контекстом я решил, правда, через ![]() mov eax, ... mov ecx, ... .................. push ... popf jmp eip отпускаем прогу, замораживаем на jmp, возвращаем всё на место. Невероятно, но это работает! Нормальное решение пытался найти, но SetThreadContext не хочет устанавливать ничего, кроме eip, хоть ты тресни. Рапаковщик уже знает около 200 инструкций. Т.е. берём прогу, запакованную чем-то, он доходит до первой неизвестной инструкции, сообщает об этом и отпускает прогу, и она после этого не грохается. В ASProtect выученных инструкций уже хватает, чтобы дойти до первого вызова VirtualAlloc и пройти её код до системного вызова sysenter (0x0f34). Обратно в ring3 управление вернётся на KiFastSystemCallRet. У меня на XP SP2 она находится по адресу 0x7c90eb94. Теперь можно отпустить прогу, а потом поймать, или использовать VirtualAllocEx, чтобы эмулировать вызов. Второй вариант мне нравится больше, правда, тогда придётся и другие вызовы эмулировать, но мы же не ищем лёгких путей! ![]() Отсюда вопрос: положение KiFastSystemCallRet зависит только от версии ОС, или от чего-то ещё? И ещё один вопрос: можно ли без написания ring0 драйвера (я этого пока не умею) прочитать дескрипторы сегментов, зная их селекторы? Может, где-нибудь в нижней половине памяти лежит копия GDT, или ещё как-то? Хочется знать базовые адреса и размеры сегментов. И может ли ring3 протектор каким-либо образом изменить GDT (вряд ли, конечно, но вдруг), или создать LDT? Заранее спасибо за ответы. Не бейте сильно, если опять с терминами напутал ![]() ![]() |
|
Создано: 28 января 2009 16:44 · Личное сообщение · #22 Контекст жёсткий, лучше бы поотлаживал и разобрался. Положение KiFastSystemCallRet хардкодить нельзя, много, от чего зависит, от СП и патчей вполне может. Может и от архитектуры, ибо при инсталле на разные архитектуры немного разные либы ставятся. С селекторами юзай GetThreadSelectorEntry, если вопрос правильно понял, погугли статью на эту тему, можно добавлять свои записи в табличку. ![]() |
|
Создано: 29 января 2009 06:38 · Личное сообщение · #23 Спасибо огромное за GetThreadSelectorEntry, это как раз то, что мне нужно. На тему KiFastSystemCallRet до меня наконец-то дошло. Адрес её загрузки можно посмотреть в таблице экспорта ntdll.dll. Только хочу спросить: всегда ли адрес, полученный таком образом, будет валидным? И может ли протектор сделать так, чтобы в ntdll.dll был один адрес, а на деле - другой? А на тему жёсткого контекста - полностью согласен, но я убил на эту проблему целый день, да так и не понял, в чём дело. Когда осознАю - сделаю по-нормальному. Просто решил не топтаться на месте слишком долго. Кстати, по этой же причине пока реализовал эмуляцию системных вызовов через исполнение, с ловлей на KiFastSystemCallRet. Думаю, что после появления первой версии анпакера, вскоре начнут появляться и следующие, с исправлением этих "заплаток". ![]() |
|
Создано: 29 января 2009 19:07 · Личное сообщение · #24 |
|
Создано: 29 января 2009 19:37 · Поправил: SemDJ · Личное сообщение · #25 |
|
Создано: 29 января 2009 20:58 · Личное сообщение · #26 |
|
Создано: 30 января 2009 13:54 · Личное сообщение · #27 2 Archer: Спасибо большое. 2 SVIN95 & SemDJ: Я его сейчас тестирую на нескольких пакерах сразу, по принципу: реализовал несколько инструкций - потестил на всех по очереди. Если ни на одном не упало - значит, наверное, всё правильно. И, наконец, 2 all: Мы добрались до OEP в UPX!!!!!!!!!!!!!!!!!!! Ура!!!!!!!!!!!!!!! ![]() |
|
Создано: 30 января 2009 20:11 · Личное сообщение · #28 |
|
Создано: 30 января 2009 22:25 · Личное сообщение · #29 |
|
Создано: 02 февраля 2009 12:34 · Личное сообщение · #30 С контекстом я разобрался окончательно. Как и предполагалось, не хватало одной строчки: lpContext->ContextFlags = CONTEXT_ALL; Собственно, поэтому не все регистры и устанавливались. Сейчас распаковщик уже доходит до OEP в UPX, ASPack, NSPack и ORiEN. Также стало известно, что PECompact, MEW, ASProtect и многие другие активно юзают математический сопроцессор. Ну, не беда, доку по нему я уже нарыл, буду раскуривать ![]() Вопрос такой: Системные вызовы я пока эмулирую через исполнение с ловлей на KiFastSystemCallRet, с этим пока, вроде, проблем нет. А при возникновении исключения просто передаю управление на KiUserExceptionDispatcher, а дальше работаю в обычном режиме, не заботясь, что лежит в FS:[0] и пр. Два первых исключения в ASProtect и одно в PECompact таким способом проходятся отлично (дальше начинается FPU). Может ли протектор заставить нас потерять управление при таком подходе? ![]() |
|
Создано: 02 февраля 2009 19:33 · Личное сообщение · #31 А я тебе сразу сказал, с контекстом поглядеть на флаги, что наверняка сам чо-нить забыл. Если используется ринг0 драйвер с обработкой исключений, типа 3 стара, то просто передача на KiUserExceptionDispatcher пойдёт лесом ввиду неправильности. Самоотладка типа 2 процессов в арме аналогично. Возможно, есть ещё косяки. Проще дать выполниться 1 вызывающей исключение инструкции и пусть управление само пойдёт на KiUserExceptionDispatcher. Хотя в описанных выше случаях приложение заработает при этом, но управление ты потеряешь. З.Ы. На этапе обкатки ещё обнаружишь, где не работает ![]() ![]() |
<< . 1 . 2 . 3 . >> |
![]() |
eXeL@B —› Основной форум —› Вопросы по написанию универсального распаковщика |