Главная » Статьи » Распаковка |
Распаковка ASProtect 1.23 RC4
Цель crackme - http://www.alex2kx.nm.ru/aspr123crackme.rar Инструменты SoftIce for NT SuperBpm for NT IceExt Loader 2.0 by Syd Hiew Imprec 1.6 LordPE PEeditor 1.7 Вступление В этой статье я расскажу как распаковать столь популярный в наше время пакер ASProtect, а именно версию 1.23 RC 4. Для большей наглядности я разделю статью на 2 части: восстановления импорта, восстановления спертых байтов (Stolen Bytes) и нахождение OEP. Целю нашей распаковки будет мною созданный crackme, и упакованный ASProtect 1.23 RC 4 build 08.07. Итак приступим.... Восстановление импорта.
Я начал распаковку программы именно с восстановления импорта, а не с
получения дампа и поиска OEP. Это связано с тем, что существует простой
способ нахождения создания импорта, а затем уже в нужном месте можно
брать дамп. Как всегда грузим программу под отладчиком, для этого я
использую Loader by Syd, но это только если у вас 2000 или XP. Этот
загрузчик, в отличии от загрузчиков типа break’n’enter не требует
восстановления затертого байта. Для тех, кто им ни разу не пользовался
объясню как его использовать. Для начала скачайте его, он входит в
комплект stripper’a by syd и его можно скачать на сайте
http://www.wasm.ru/. Затем необходимо открыть окно sice’a, и написать
I3HERE ON, потом открыть файл и нажать Break on Oep. Чтобы не возникло
проблем с обнаружением отладчика и с несрабатыванием бряков
рекомендуется включить IceExt и SuperBpm. Дальше используем загрузчик.
Как только мы оказались в отладчике на EP программы, ставим такой бряк:
bpm mapviewoffile x, почему - объясню ниже. Как вы наверное уже знаете,
я надеюсь, что для получения адреса функции служит GetProcAddress. Эта
функция используется много раз в аспре. После распаковки программы в
память функция GetProcAddress используется как раз для определения
адресов апи функций и заполнения этими адресами таблицу импорта. После
проверки и определения CRC программы, с помощью чего юзаются
конструкции CreateFileA, CreateFileMapping, MapViewOfFile.... можно уже
ставить бряк на GetProcAddress, тогда прога уже распакована в память.
После того как сработает бряк на MapViewOfFile, а он может сработать
два раза для обладателей XP c дополнительными темами XP, удаляем этот
бряк и ставим бряк на GetProcAddress. Бряк на GetProcAddress сработает
несколько раз, нас интересует срабатывание именно в таком месте:
001B:008E2F34 E88722FFFF CALL KERNEL32!GetProcAddressДалее нажимаем F12 до тех пор, пока не окажемся в таком месте: 001B:008E32B4 E847FCFFFF CALL 008E2F00 <- От сюда мы вышли 001B:008E32B9 E87EFEFFFF CALL 008E313CМы оказались в процедуре создания импорта. Тепер можем посмотреть, что творится в eax. А там как раз адрес АПИ функции. Следующий call, который находиться по адресу 008E32B9, принимает адресс апи функции и по нему возвращает адрес соответствующего переходника. Чтобы нам получить относительно чистый импорт мы должны обойти этот call, а именно за’nop’ить. Выглядит это так: 001B:008E32B4 E847FCFFFF CALL 008E2F00 001B:008E32B9 90 NOPЕсли внимательно приглядеться, то по адресу 008E32C0 происходит заполнение таблицы импорта адресами АПИ функций. Нам необходимо определить начало этой таблицы импорта, для этого становимся на 008E32BE и смотрим, что находиться в edx. В edx как раз начало нашего импорта: 004420F0. Теперь жмем F12, оказываемся в таком месте: 001B:008E3541 B904000000 MOV ECX,00000004 001B:008E3546 01CE ADD ESI,ECXКак мы видим, здесь цикл. На необходимо поставить бряк на 008E3550. Дальше трейсим, по пути встретиться SEH трюк : 001B:008E359C 648920 MOV FS:[EAX],ESP FS:00000000=817CDE84 001B:008E359F 3100 XOR [EAX],EAXТак вот, дойдя до 008E359C, необходимо ставить сразу бряк на 008E35A1, чтоб обойти XOR [EAX],EAX , иначе произойдет exception. Дальше доходим до такого места: 001B:008E35FC 60 PUSHAD 001B:008E35FD 68AC638E00 PUSH 008E63ACПо адресу 008E360B, происходит эмуляция таких функций как: GetModuleHandleA, GetProcAddress, GetVersion и других. Вам может показаться, что за’nop’ив этот call мы получим чистый импорт, без переходников. Но реально же по адресам в таблице импорта лежат не адреса этих апи функций, а левые адреса. Так что быдем ручками чистить импорт :) Ставим бряк на 008E360D и зацикливаем прогу. (a [enter] jmp eip [enter] - для тех кто в танке). Теперь можем сделать два дела сразу: сдампить прогу и получить таблицу импорта. Для начала сдампим прогу, я использовал LordPe. Выбираем в списке процессов нашу зацикленную программу и нажимаем правой кнопкой мыши. Далее выбираем Dump Full и сохраняем наш дамп. Теперь будем разбираться с импортом. Запускаем ImpRec, выбираем в процессах нашу зацикленную прогу, далее в поле RVA пишем адрес начала нашей таблицы импорта с учетом imagebase, т.е. мы впишем 0420F0. Размер таблицы импорта мы не знаем поэтому рекомендуется ставить значения побольше, лишнее потом можно удалить. Так как мой crackme программа относительно небольшая по размеру, я оставил значение по умолчанию - 1000. Теперь жмем GetImports. Что-то получили :) теперь будем чистить этот импорт. Жмем на ShowInvalid, оказываемся в таком месте: Неизвестные адреса, это адреса аспровских переходников о которых я говорил выше. Дальше необходимо определять, что эта за апи функция. Для упрощения и наглядности я ниже покажу вам как выглядят эти переходники/эмуляторы и объясню почему именно такой-то переходник есть такая-то функция. GetProcAddress: 008E17A4 push ebpПонять, что это за эмулируемая функция, можно, если прерваться на адресе 008E17A4 и проследить, как будет выполняться программа. В конце концов, я приду на адрес 008E17C4 и выполнится функция GetProcAddress, которая вернет адрес запрашиваемой функции в регистре eax и с тех пор, eax больше меняться не будет. Значит это так и есть функция GetProcAddress. GetModuleHandleA: 008E1C64 push ebpАналогично как и с GetProcAddress. Замечу, что значение 00400000 было получено где-то заранее, и по адресу 008E1C6A проверяется первый переданный параметр функции, если он равен 0, то в eax заносится значение 00400000, так как GetModuleHandleA(0)=00400000. GetCommandLineA: 008E1CD8 push 0По адресу 008E1CDA вызывается некая функция-пустышка, так как никакой роли она не играет. По адресу 008E1CE6 в eax заноситься какое-то значение. Если в отладчике посмотреть, что находиться по этому адресу (d eax), то мы увидем полный путь к файлу. Следовательно это и есть функция GetCommandLineA. LockResource: 008E1CC8 push ebp 008E1CC9 mov ebp,esp Эта функция возвращает то же самое значение, что и принимает. Т.е. когда происходит вызов функции call, то в esp помещается адрес возврата. Когда происходит команда push ebp, в esp уже заноситься значение ebp, и указатель стека смещается. Следовательно адрес возврата будет находиться по адресу [esp+4], а передаваемый параметр по адресу [esp+8]. Команда mov ebp,esp помещает начало стэка в ebp, поэтому значение [ebp+8] будет аналогично [esp+8]. А по этому адресу лежит передаваемый параметр, он же возвращается функцией. Так хитро аспр эмулирует LockResource GetVersion: 008E1C8C push dword ptr [8E7E14] // DWORD value: 0A280105 008E1C92 pop eaxМожем заметить, что в eax заносится небольшое значение. А если посмотреть в ImpRec к примеру, то в списках процессов, напротив нашего файла будет находиться как раз такое значение. Это есть идентификатор текущего процесса. Значит этот код эмулирует GetCurrentProcessId FreeResource: 008E1CF0 push ebp 008E1CF1 mov ebp,espСначала вам может показаться, что это еще одна эмуляция GetCommandLineA. Но функция GetCommandLineA не имеет параметров ! Аспротект так хитро эмулирует FreeResource. Для того, чтобы продемонстрировать еще одну эмуляцию, я в своем crackme сделал наг, окошко из ресурсов. Поэтому следующая функция эмулируется аспром вот так: DialogBoxParamA: 008E1D14 push ebpЕсли в отладчике набрать u DialogBoxParamA, то мы увидем точно такой же код, как и использует аспротект при умуляции. Еще есть эмуляция, которой в нашем случае не было, это эмуляция GetCurrentProcess. Там в эмуляторе заноситься в eax DWORD value: FFFFFFFF. Запомните ! Чтобы самому посмотреть, как выглядит код переходника/эмулятора, жмем правой кнопкой мыши по адресу и выбираем Dissassemler / Hex View. Как только определили функцию, кликаем два раза по этой строке и выбираем в списке функцию. Еще один момент. Вы можете увидеть такое: Т.е. F49C293 никак на адрес не смахивает, в данном месте это является "разделителем" между адресами апи функций разных библиотек. Выбираем, жмем Cut thunk(s). У нас появилась новая ветка :) Вот в таком духе делаем всё. В конце вы встретите кучу мусора, т.к. адрес мы не точный ставили, а примерный. Поэтому после последней определившейся апи функции жмем Cut thunk(s), а потом самая последняя ветвь и будет мусором, выбираем, жмем Delete thunk(s). В итоге вы получите чистый импорт, как и я получил: Теперь жмем Fix Dump, выбираем наш дамп. Теперь мы получили уже почти полную распакованную прогу. Нам осталось только восстановить спертые байты и найти OEP. Итак часть вторая... Восстановление спертых байтов и поиск OEP Грузим еще раз прогу, на EP проги ставим всем знакоый бряк bpm esp-4. На третий раз бряк сработает в нужном нам месте, дальше пойдет мусорный код, в котором и выполняются спертые команды. Для начала хотелось бы маленьки обратить внимание на термин "спертые байты". В нашем случае аспр забирает начало нашей проги, которая написана на Delphi. Начало у Delphi прог почти всегда такое, ну по крайней мере первые три инструкции: push ebpВ большинстве случаев, где-то 90 %, аспр забирает байты до первого call’a. В нашем случае именно так и происходит. Мусорный код выглядит примерно так: 001B:008F5A89 61 POPAD 001B:008F5A8A 3EEB02 JMP 008F5A8FНекоторые не любят копаться в этом мусорном коде, потому что он бывает очень большим и напутанным. Но мы попробуем это сделать. Трейсим по F8 немного этот код пока сразу же в глаза нам не попадется вот это: 001B:008F5AE6 E8558BEC81 CALL 827BE640Здесь как раз выполняются наши спертые команды. Замечу, что команда sub esp, 0000000C слишком большая, т.е. занимает целых 5 байт ! На деле эта команда выглядит так add esp, -0C ! и занимает всего 3 байта. Теперь нам осталось только узнать yyyy, трейсим наш мусорный код до ret и смотрим что у нас хранится в eax, а в eax у нас как раз нужное нам значение yyyyy. Т.е. в мусорном коде мы не найдем инструкцию mov eax, yyyyy. Значение yyyyy генерится теким способом, но нам это впринципе не важно, т.к. если уж аспр забрал команды, то он должен и также их восстановить, и как раз у нас при выходе из мусорного кода в eax будет нужный адрес. После мусорного кода мы попадем на переходник GetModuleHandleA. Аспр - первый пакер, который при краже байт стал заходить в call, в нашем случае call zzzzz. Теперь жмем F12, чтобы оказаться в главной ветви программы, т.е. рядом с OEP. Это выглядит так: 001B:0043F50B E8B469FCFF CALL 00405EC4Мы вышли как раз из call zzzzz. Выше этого call’a есть пустые байты, на месте которых должны были находиться спертые команды. Туда мы и будем вписывать спертые байты. Размер спертых байт составляет: 1 (push ebp)+2 (mov ebp,esp)+3 (add esp,-0C)+5 (mov eax,0043F3C8)=11 или B (hex) байт. Поэтому 0043F50B-B=0043F500, это и есть наше OEP ! Открываем файл в HIEW, по адресу 0043F500 начинаем писать: push ebpТеперь подправляем EP нашего дампа на 0003F500, например с помощью PEeditor, и можете смело запускать дамп. Если вы все сделали правильно, могу вас поздравить, вы теперь умеете распаковывать ASProtect 1.23 :). От вас осталось убрать наг :) :) На последок хотелось бы передать приветы этим людям: MozgC[TSRh], Kerghan, Hex, Angel_aka_K$, Madness, YMY, Bad_Guy и многим другим. Источник: http://www.dotfix.net | |
Просмотров: 3036 | Рейтинг: 0.0/0 |
Всего комментариев: 0 | |