Дао универсальной распаковки Крис Касперски Хакер, номер #089, стр. 089-114-3 Возьмем, к примеру, тот же ASPack и посмотрим в его начало: [точка входа в распаковщик ASPack] :u eip 01010001 PUSHAD 01010002 CALL 0101000A 01010007 JMP 465E04F7 0101000C PUSH EBP 0101000D RET Замечательно! Первая же команда сохраняет все регистры в стеке. Очевидно, что непосредственно перед передачей управления на OEP они будут восстановлены командой POPA, выполнение которой очень легко отследить, установив точку останова на двойное слово, лежащее выше верхушки стека: "bpm esp - 4". Результат превосходит все ожидания: [передача управления на OEP] 010103AF POPAD ; на этой команде отладчик всплывает 010103B0 JNZ 010103BA 010103B2 MOV EAX,00000001 010103B7 RET 000C 010103BA PUSH 1006420 ; передача управления на OEP 010103BF RET Распаковав программу, ASPack заботливо выталкивает сохраненные регистры из стека, вызывая всплытие отладчика, и мы видим тривиальный код, передающий управление на OEP "классическим" способом через PUSH offset OEP/RET. Поиск исходной точки входа не затратил и десятка секунд! Ну разве не красота? А теперь возьмем UPX и проверим, удастся ли нам провернуть этот трюк и над ним? Ведь мы же претендуем на универсальный пример! [так начинается UPX] 01011710 PUSHAD ; <- упаковщик сохраняет регистры 01011711 MOV ESI,0100D000 01011716 LEA EDI,[ESI+FFFF4000] 0101171C PUSH EDI Вот он, уже знакомый нам PUSHAD, сохраняющий все регистры в стеке и восстанавливающий их непосредственно перед передачей управления на OEP. Даем команду "bpm esp-4" и выходим из отладчика, пока он не всплывет. [так UPX передает управление на OEP] 0101185E POPAD 0101185F JMP 01006420 А вот и отличия! Передача управления осуществляется командой JMP 1006420h, где 1006420h — исходная точка входа. Похоже, что все упаковщики работают по одному и тому же алгоритму и ломаются, как в ночь перед исходом. Но не будем смешить. Возьмем PE-compact и проверим свою догадку на нем. [точка входа в файл, упакованный PE-compact] 01001000 MOV EAX,01011974 01001005 PUSH EAX 01001006 PUSH DWORD PTR FS:[00000000] 0100100D MOV FS:[00000000],ESP Плохо дело! PE-compact никаких регистров вообще не сохраняет, а PUSH EAX используется только затем, чтобы установить свой обработчик структурных исключений. Тем не менее, на момент завершения распаковки указатель стека должен быть восстановлен, следовательно, точка останова на "bpm esp-4" все-таки может сработать…. [первое срабатывание точки останова на esp-4] 77F8AF78 PUSH DWORD PTR [EBX+04] 77F8AF7B LEA EAX,[EBP-10] 77F8AF7E PUSH EAX Так, ну это срабатывание явно левое (судя по EIP 77F8AF78h, мы находимся где-то внутри KERNEL32.DLL, использующим стек для нужд производственной необходимости), давим <Ctrl-D>, не желая здесь больше задерживаться. [Кузьмич?! Где это я?] 010119A6 PUSH EBP 010119A7 PUSH EBX 010119A8 PUSH ECX 010119A9 PUSH EDI Следующее всплытие отладчика также не проясняет ситуацию. Ясно только одно: в стек сохраняется регистр EBP вместе с другими регистрами. Давим <Ctrl-D> и ждем дальше. |