ОБФУСКАЦИЯ И ЕЕ ПРЕОДОЛЕНИЕ КРИС КАСПЕРСКИ АКА МЫЩЪХ Спецвыпуск: Хакер, номер #066, стр. 066-008-6 Если писать трассер лень, можно использовать Soft-Ice, просто отключив окно кода командой WC. Тогда результат трассировки командой T будет «вываливать» в нижнее окно, откуда его можно добыть сохранив историю команд в Symbol Loader’е: File> Save Soft-Ice History As. протокол трассера 001B:00434001 E800000000 CALL 00434006 001B:00434006 5D POP EBP 001B:00434007 50 PUSH EAX 001B:00434008 51 PUSH ECX 001B:00434009 EB0F JMP 0043401A 001B:0043401A F2EBF5 REPNZ JMP 00434012 001B:00434012* EB0F JMP 00434023 001B:00434023 EBE9 JMP 0043400E 001B:0043400E B8EB07B9EB MOV EAX,EBB907EB 001B:00434013* 0F90EB SETO BL 001B:00434016* 08FD OR CH,BH 001B:00434018 EB0B JMP 00434025 001B:00434025 F3EBE4 REPZ JMP 0043400C 001B:0043400C EB0F JMP 0043401D 001B:0043401D EBF6 JMP 00434015 001B:00434015 EB08 JMP 0043401F 001B:0043401F F2EB08 REPNZ JMP 0043402A 001B:0043402A 59 POP ECX 001B:0043402B 58 POP EAX 001B:0043402C 50 PUSH EAX 001B:0043402D 51 PUSH ECX 001B:0043402E EB0F JMP 0043403F 001B:0043403F F2EBF5 REPNZ JMP 00434037 001B:00434037 EB0F JMP 00434048 001B:00434048 EBE9 JMP 00434033 001B:00434033 B8EB07B9EB MOV EAX,EBB907EB 001B:00434038 0F90EB SETO BL 001B:0043403B 08FD OR CH,BH 001B:0043403D EB0B JMP 0043404A 001B:0043404A F3EBE4 REPZ JMP 00434031 001B:00434031 EB0F JMP 00434042 001B:00434042 EBF6 JMP 0043403A 001B:0043403A EB08 JMP 00434044 001B:00434044 F2EB08 REPNZ JMP 0043404F 001B:0043404F 59 POP ECX 001B:00434050 58 POP EAX Намного нагляднее дизассемблерного листинга. Теперь не нужно прыгать по условным переходам, гадая, какие из них выполняются, а какие нет. К тому же естественным образом исчезает проблема перекрытия машинных команд. Обрати внимание на адреса 434012h, 00434013h и 00434016h — это наши «перекрытые» команды. То, что дизассемблеру удавалось показать с таким трудом, трассер отдает нам задаром! Это реальный поток выполнения программы, в котором много мусора, но, по крайней мере, нет скрытых команд, с которыми приходится сталкиваться в дизассемблере. Полученный протокол трассировки можно (и нужно!) прогонять через различные программы-фильтры (их придется написать тоже самостоятельно), которые распознают и удаляют мусорные инструкции. Впрочем, эту операцию можно выполнить и вручную, загрузив протокол в любой редактор (например, в тот, который встроен в FAR). После нескольких минут работы получишь реально значимый код. «вычищено» вручную 001B:00434001 E800000000 CALL 00434006 001B:00434006 5D POP EBP 001B:00434077 33C9 XOR ECX,ECX 001B:004340C3 33C0 XOR EAX,EAX 001B:004340D3 8B0424 MOV EAX,[ESP] 001B:004340DB C60090 MOV BYTE PTR [EAX],90 001B:00434105 83ED06 SUB EBP,06 [основную проблему] создают циклы. Трассер разворачивает их в длинный многокилометровый, многократно повторяющийся код. Запаришься пролистывать его. Так что не обойтись без фильтра, распознающего и «сворачивающего» повторяющие конструкции. Хорошая идея — пропустить протокол трассера через оптимизирующий компилятор, использующий системы графов для устранения лишних операций присвоения (пропускать именно протокол трассера, а не дизассемблерный листинг, поскольку последний неверен, неполон и вообще никуда не годится). Конечно же, он не сможет распознать математические преобразования в стиле sin(x)2+cos(x)2, но выбросит значительную часть «инструкций с нулевым эффектом», а тебе не придется реализовывать систему графов и писать то, что было написано задолго до нас. |