Сейчас на форуме: (+5 невидимых) |
eXeL@B —› Дневники и блоги —› Блог DenCoder'а |
<< . 1 . 2 . 3 . |
Посл.ответ | Сообщение |
|
Создано: 05 июля 2015 15:23 · Поправил: DenCoder · Личное сообщение · #1 Всем привет! Всем здоровья, достатка, удачи, успехов... всех благ! ) Вот и нашлось немножко времени, чтобы завести блог. Давно хотел, но время для меня на вес золота... С вашего позволения здесь буду описывать процессы обхода/взлома/разбора защит, с которыми приходилось сталкиваться. Кому-то может пригодиться, кому-то - нет... Но за время работы немного узнал, что есть такая защита, перед которой некоторые коллеги пасуют - VMProtect. Может, в общем и есть такие страшные версии вмпрота, на которые терять кучу времени бессмысленно - не знаю, я с такими не сталкивался. Но скажу, что очень часто снимать вмпрот или разбирать то, что им накрыто, просто нет необходимости! Вмпроты, которые мне попались в мае (сразу 2 подряд) - не такие страшные. Первым из них была накрыта lockpdfu.dll - компонент DRM защиты pdf-ок. Подробнее Человек 2 или 3 года ждал, когда же, наконец, найдётся кто-нибудь, кто даст возможность свободно пользоваться pdf-документами на любом компе и редактировать. И находился некто с других сайтов, кто чуть не кинул... Попробую объяснить морально-идеологический аспект в двух словах прежде всего: Человек - учитель, ему необходим учебный материал без ограничений использования с возможностью редактировать. Одна из купленных тетрадей, на файле которой я помогал решить задачу, стоила что-то вроде 70 гривен, использовать можно только на 2х компах и никак нельзя что-то пометить, что-то исправить. Чтобы, например, поделиться с учениками, сколько-то нужно дополнительно проплачивать... мда... куда катится мир, одни то ли бизнесмены, то ли барыги... Ставим задачу: перехватить расшифровку запротекченной тетради, записать в отдельную папку оригинальный pdf. Из совета Vovan666 запротектил пдф-ку персональной версией, после чего без проблем из памяти AcroRd32 достал чистую pdf-ку. честно говоря, не понял про протект персональной версией, но проверил можно ли что-то из памяти выцепить: даже и обычные pdf-ки в первозданном виде в памяти не хранятся, сигнатур %pdf-1.4 .. %pdf-1.7 нет. То, что находится с такой сигной - какая-то полоска для самого ридера ) Я пошёл своим путём. Раз нельзя выцепить из памяти - незаметно (для защиты) встанем на место после декрипта и незаметно сольём поток в файл. Звучит просто, но пришлось немного попотеть... CreateFile, SetFilePointer, CloseHandle удалось хукнуть джампом без проблем. А вот ветка кода из acrord32.dll, вызывающая чтение функой ReadFile была хукнута в NtReadFile защитой + каким-то магическим образом проверялся crc этой ветки, а также защита не давала поставить ни софт бряк, ни джамп на ReadFile ни до, ни внутри, ни после... в дрова лезть не будем! Софт бряк нельзя поставить, а против харда защита ничего не имеет против! Вспомнил, что имеется такая функция AddVectoredExceptionHandler и быстро нарисовалась идея (что не я - первооткрыватель, знаю, потому и пишу, что вспомнил) поставить 2 харда на ReadFile и после и обрабтать по своему. Потратил немножко времени на кодинг, но удалось, с первой подзадачей справился, осталось только записать файл. Записать файл - тут кажется, проще не бывает. Но во-первых под 7кой и выше нужно перевести для этого акроридер в незащищённый режим, чтобы были привилегии, во-вторых - NtWriteFile также хукнута защитой и возвращала жестокий AD. Снимать хук без изучения защиты бесполезно - работать как надо не будет. ReadFile, WriteFile - так защита обменивалась какими-то важными данными. Не стал тратить время на изучение механизмов, сделал проще: против вызова NtWriteFile в месте после хука защита тоже ничего не имела против. Тут, я думаю, подробности излишни, в ntdll индексы всех фунок(nt-сервисов) идут по возрастающей по порядку во всех версиях винды, не встречалось другого(берём адрес хукнутого сервиса, находим следующий/предыдущий, берём оттуда индекс сервиса и минус/плюс 1) Новичкам с опытом кодинга может быть полезно В следующий раз (может быть сегодня вечером, может и через года 2) опишу отлом какой-то из версий вмпрота под x64, где тоже есть морально-идеологический аспект ----- IZ.RU | Сообщение посчитали полезным: TLN, Zoeken |
|
Создано: 14 марта 2017 04:48 · Личное сообщение · #2 Детектом только псевдоциклов и непрозрачных предикатов проблему не решить. Попадаются довольно сложные выражения, общий принцип решения которых довольно сложно, почти невозможно реализовать на ЯП. Например, что-то вида Code:
или Code:
Проблемно такие выражения решать в статике, без эмулятора сложно обойтись... На помощь приходит Unicorn! Без проблем эмулирует нужные куски ARM-кода. Использование Unicorna облегчает жизнь, но тогда возникает соблазн изменить план для достижения цели - отэмулировать почти всё, не только трудные конструкции кода... В расшифровке строк, что как я читал - одна из основных черт многих запутывающих LLVM-компиляторов, мы преуспели - расшифровываются имена проверяемых файлов и строки команд, запускаемых через system(). Но у Unicorn'а нет поддержки набора инструкций Advanced SIMDv1, который часто используется компилятором для оптимизации кода, (аналогично как и в SSE/SSE2 под x86/x64), и здесь не исключение. Нужны-то всего 2 инструкции: VMOV и VST. Искать и собирать другой эмулятор? - Один из возможных выходов, но в других эмуляторах возможны свои проблемы... Искать и пробовать - тоже нет времени! Решил самостоятельно добавить поддержку эмуляции этих инструкций. Чуть позже выложу скрипт детекта и эмуляции их на питоне. Добавлено спустя -59 минут За Unicorn много благодарностей автору!!! Добавлено спустя 4 часа 16 минут Даже работает mu.reg_write(UC_ARM_REG_D16, 9)! Эмуляцию регистров не надо делать ) Вот только на UC_ARM_REG_Q8 единорог никак не реагирует. ----- IZ.RU | Сообщение посчитали полезным: Jupiter |
|
Создано: 14 марта 2017 17:23 · Личное сообщение · #3 |
|
Создано: 14 марта 2017 18:15 · Личное сообщение · #4 Ну, дело будет - разберёшься. ) По мере работы с ним какие-то скрипты буду выкладывать. Может, помогут. Юникорн хорош! Достаточно прост в использовании. Правда, ограничения в использовании есть. По архитектуре ARM. например, с которой я сейчас работаю, много задумано и пока не реализовано, оставлено. Но, умеючи, можно эти ограничения обойти... ) Автор aquynh на джитхабе, как я понял = Jupiter здесь? Или ошибаюсь? ----- IZ.RU |
|
Создано: 14 марта 2017 18:21 · Личное сообщение · #5 |
|
Создано: 14 марта 2017 18:33 · Поправил: DenCoder · Личное сообщение · #6 хм... Судя по Добавлено спустя -59 минут Jupiter Ну так подумалось почему-то... Не принимал участие в разработке капители и единорога? ) ----- IZ.RU |
|
Создано: 15 марта 2017 14:23 · Личное сообщение · #7 DenCoder пишет: Автор aquynh на джитхабе, как я понял = Jupiter здесь? Или ошибаюсь? aquynh это Nguyen Anh Quynh из Вьетнама ----- http://ntinfo.biz | Сообщение посчитали полезным: DenCoder |
|
Создано: 15 марта 2017 22:16 · Личное сообщение · #8 |
|
Создано: 18 марта 2017 16:49 · Поправил: DenCoder · Личное сообщение · #9 Прошло меньше полнедели и более менее освоился в питоне. Передела часть idc-скрипта, адаптировал под нужды "поиска альтернативной ветви кода"(не закончил, пока полуавтоматом ищет). Что это такое? Бывает, в реверсе "LLVM-кода" эмулятор или дебаггер выводит всегда на одну тупиковую ветвь, как будто условие какое-то не срабатывает - то ли файл не в том формате, то ли детект задержек. Этот скрипт проверяет, можно ли избежать этой ветви, и если да, показывает путь. Заодно собирает блоки и циклы, как и в версии idc-скрипта(исправлены некоторые ошибки сбора циклов и блоков). Выглядит красивей и компактней, чем версия на idc и работает много шустрее - не ожидал от питона ) Code:
findPaths(start, path, avoid_addr) start - адрес начального блока, откуда начинать проверку, у меня here() - аналог idc-функции ScreenEA() path - список с адресами пройденных блоков avoid_addr - адрес, которого хотелось бы избежать Пока версия для полуавтоматической работы - если не находит, надо подняться по графу повыше. Если альтернативная ветка найдена, отображает список адресов блоков, в самом верху тот адрес блока, в котором проверка условия(тот самый непрозрачный предикат). Возможно, будет модернизироваться. Добавлено спустя 6 минут Скрипт эмуляции на юникорне с маппингом и загрузкой секций so-модуля, с добавлением эмуляции неоновских инструкций, с эмуляцией некоторых линуксовых функций весь пока не могу выложить - громоздкий, несколько модулей... Может быть, чуть позже освоюсь на гитхабе... Добавлено спустя 16 минут Часть скрипта, как можно инициировать юникорн для эмуляции: Code:
mu.hook_add(UC_HOOK_INTR, hook_intr) ставит хук на sysenter/sysexit под x86/x64, под ARM - на svc 0, R7 будет индексом системной функции, список которых под ARM можно найти В mu.hook_add(UC_HOOK_CODE, hook_code, ADDRESS + 0x31FA0, ADDRESS + 0x31FA0) так и не понял, зачем 2 последних аргумента - полный их игнор Добавлено спустя 1 час 7 минут Из догадок по аргументам begin, end ф-ции hook_add() - begin, end == 1, 0 -> вызов колбэка до выполнения инструкции begin, end == 0, 1 -> вызов колбэка после выполнения инструкции Добавлено спустя 10 часов 14 минут День или 2 копался в коде под толстым слоем LLVM, смотрел для чего читается /proc/self/status. Оказывается, по его содержимому тоже можно определить факт динамического исследования работы кода через TracerPid. Наличие чего-либо, кроме нуля(точнее, там должно быть TracerPid:\t0\n) и попадаем в ловушку - в тупиковую ветвь. Эмулятор так не задетектить, если пример вывода из /proc/self/status взять с реальной машины, а не с сайта ----- IZ.RU |
|
Создано: 20 марта 2017 03:21 · Поправил: DenCoder · Личное сообщение · #10 Обнаружена непонятная хрень с юникорном, из-за которой пришлось сделать массу экспериментов, чтоб докопаться до причин и потратить ещё один ненужный день. Суть проблемы - невозможно остановить процесс эмуляции кода в колбэке, установленном как UC_HOOK_CODE, если текущая инструкция - BL (на x86 можно проверить это насчёт CALL). Пробовал uc.emu_stop(), пробовал raise - и то, и то игнорится, хотя сообщение какое-то можно вывести. Другие условия несработки останова пока не были выявлены, на других инструкциях хватает uc.emu_stop(), чтоб прервать выполнение... Хотя на счёт raise - только что провёл ещё один эксперимент. После emu_stop() на инструкции BL единорог отказывается воспринимать raise. Как будто emu_stop() становится на время эмуляции одной инструкции emu_continue_and_ignore_all_errors(). Но без emu_stop() рэйзится нормально и из except уже можно остановить процесс. Вот в чём там дело? Сие мне стоило одного дня... Добавлено спустя 18 минут Оказалось, что и raise на BL не всегда работает... Добавлено спустя 3 часа 1 минуту Ещё одна интересная особенность юникорна из инсталлера... даже 2: 1) Если в функции-хуке кода попробовать прочитать из незамапленной памяти кусок даже нулевого размера под идапитоном, зависнет однорогий 2) Вывод при эмуляции идёт параллельным тредом и отстаёт от эмуляции, поэтому вы не увидите, на чём именно зависло. Я увидел это только когда догадался вставить идовскую AskYN(), чтоб пошагово эмулировать. Добавлено спустя 3 часа 30 минут А причина такой ошибки проста: Code:
код эмулирует функцию memcpy(). В функцию, которая её вызывает, передаётся структура, недоинициализированная. Значит, где-то опять проскочил условие и опять угодил в ловушку. ----- IZ.RU |
|
Создано: 20 марта 2017 12:04 · Личное сообщение · #11 |
|
Создано: 20 марта 2017 14:35 · Поправил: DenCoder · Личное сообщение · #12 Не уверен, что реакция будет быстрая, и мои найденные баги - приоритетные. Список TODO у автора большой. По ошибке с emu_stop() там уже попадалось. Да, может быть стоит написать, добавить, что почему-то именно на BL такая проблема... По зависанию на чтении/записи незамапленных регионов - решается ассертами. Не лениться их вставлять, от лишних проблем избавит. ----- IZ.RU |
|
Создано: 24 марта 2017 23:19 · Поправил: DenCoder · Личное сообщение · #13 |
|
Создано: 28 мая 2017 17:00 · Личное сообщение · #14 2 месяца уже как работаю по функциям реверс-инженером, но официально - программистом. З/п не скажу, но достойная. ) Работа нашла меня, повезло... Ввиду этих обстоятельств здесь что-то будет появляться ещё реже, так как времени первые 2-3 месяца не будет на то, чем мог бы поделиться... Ходит слух что деятельность реверс-инженеров будет строго запрещена в РФ и как-то по закону караться. В америке или где-то там уже слышал, что запретили, но у нас не америка, конечно. Будем надеяться, что это не правда ) ----- IZ.RU |
|
Создано: 09 июля 2017 01:24 · Личное сообщение · #15 |
|
Создано: 09 июля 2017 02:35 · Поправил: Abraham · Личное сообщение · #16 |
|
Создано: 11 июля 2017 10:33 · Поправил: DenCoder · Личное сообщение · #17 |
|
Создано: 21 июля 2017 03:12 · Личное сообщение · #18 |
|
Создано: 26 июля 2017 15:01 · Личное сообщение · #19 |
|
Создано: 23 октября 2019 21:39 · Личное сообщение · #20 Долго не появлялся... Поделюсь интересным наблюдением: В ws2_32.dll есть неэскпортируемая функция CheckForHookersOrChainers(). Вызывается из WSAStartup(). Её смысл - проверка на наличие хуков в экспорте этой dll. То есть, если перехватить GetProcAddress() и подменить адрес функции на адрес своего обработчика(1 случай), или подменить rva функции в экспорте(2 случай), то функция возвращает -1 и сокеты не заводятся, WSAStartup() возвращает WSASYSNOTREADY(10091). На первый взгляд защита. В первом случае обходится вставкой в хук на GetProcAddress() кода Code:
Во втором случае аналогично, только при определении вызова GetProcAddress() из ws2_32 в хуке вместо GetProcAddress() подсунуть сохранённый оригинальный адрес. ----- IZ.RU | Сообщение посчитали полезным: morgot |
|
Создано: 12 декабря 2019 22:33 · Личное сообщение · #21 Ох, замучал меня verifier. Так-то неплохой способ через IFEO цепляться. Но verifier.dll много лишнего делает, серьёзное приложение, которое "без ошибок", не загрузишь с ним. Ну или все пишут с ошибками, и тогда добрую половину софта можно браковать. В общем, начинаю учиться его выгружать. Добавлено спустя 14 часов 39 минут И вот пишу из браузера с моей приаттаченой через IFEO dll. Браузер работает более менее нормально, хотя verifier.dll в него тоже подгружена. Кодом Code:
убираем перехваты верифером функций, за которыми он следит. Просто верифер не успевает их перехватить. Раньше с ним не могла загрузиться даже простенькая страничка. Но всё равно почему-то тормозно работает, хотя хуки функций моей dll почти ничего не делают. Добавлено спустя 18 часов 1 минуту Проблема с 10кой остаётся - способ передачи объекта AVRF-провайдерской структуры отличается (не через стек, а через регистр), структура отличается... ----- IZ.RU |
|
Создано: 13 декабря 2019 20:57 · Личное сообщение · #22 DenCoder > Ну или все пишут с ошибками, и тогда добрую половину софта можно браковать. Верно, он весь кривой. Потому что не нэйтив. Именно по этому и валится почти всегда при верификации. Собственно для этого инструмент и нужен. Это лишь системный способ загрузки в процесс, причём обычно не нужный. Никто голый нэйтив не пишет. В очень редких случаях, когда нужно загрузить монитор в последовательность процессов. Иначе достаточно создать процесс остановленным и фиксить в памяти что угодно. Своего рода инжект. ----- vx |
<< . 1 . 2 . 3 . |
eXeL@B —› Дневники и блоги —› Блог DenCoder'а |