ОБФУСКАЦИЯ И ЕЕ ПРЕОДОЛЕНИЕ КРИС КАСПЕРСКИ АКА МЫЩЪХ Спецвыпуск: Хакер, номер #066, стр. 066-008-3 .adata:00434013 seto bl ; прыжок в середину команды .adata:00434016 or ch, bh .adata:00434018 jmp short loc_434025 .adata:00434018 .adata:0043401A loc_43401A: ; CODE XREF: .adata:00434009j .adata:0043401A repne jmp short near ptr loc_43400E+4 .adata:0043401D .adata:0043401D loc_43401D: ; CODE XREF: .adata:loc_43400Cj .adata:0043401D jmp short near ptr loc_434013+2 Обрати внимание на команду «043401Dh:jmp short loc_434013+2», прыгающую по адресу 434013h+2h == 434015h, то есть в середину инструкции 434013h:seto bl. Именно что в середину! С точки зрения дизассемблера (даже такого продвинутого, как IDA Pro), команда является «атомарной» структурной единицей, то есть неделимой. На самом же деле всякая машинная инструкция состоит из последовательности байт и может быть выполнена с любого места! Во всяком случае, x86-процессоры не требуют выравнивания кода. Другими словами, не существует «команд» — существуют только байты. Если начать выполнение инструкции не с первого байта, получим совсем другую команду! К сожалению, IDA Pro не позволяет узнать какую. Чтобы выполнить переход «043401Dh:jmp short loc_434013+2», необходимо подвести курсор к метке loc_434013 и нажать <U> (так мы «раскрошим» дизассемблерный код на байты), а после перейти по адресу 434015h и нажать <C>, тем самым превратив байты в дизассемблерный код. «вскрытие» наложенной команды .adata:0043400E unk_43400E db 0B8h ; ¬ ; CODE XREF: .adata:loc_434023j .adata:0043400F db 0EBh ; ы .adata:00434010 db 7 .adata:00434011 db 0B9h ; | .adata:00434012 loc_434012: ; CODE XREF: .adata:loc_43401Aj .adata:00434012 jmp short loc_434023 .adata:00434014 .adata:00434014 nop .adata:00434015 .adata:00434015 loc_434015: ; CODE XREF: .adata:loc_43401Dj .adata:00434015 jmp short loc_43401F ; прыжок сюда .adata:00434017 .adata:00434017 std .adata:00434018 jmp short loc_434025 .adata:0043401A .adata:0043401A loc_43401A: ; CODE XREF: .adata:00434009j .adata:0043401A repne jmp short loc_434012 На месте seto bl возникла пара инструкций jmp loc_43401F/std. Какой из двух листингов правильный? По отдельности — ни тот, ни другой. Они становятся «правильными» только вдвоем! Однако удержать эти подробности в голове нереально, а IDA Pro не позволяет быстро переключаться между двумя вариантами. Остается загонять «альтернативный» листинг в комментарии. Если одна и та же машинная команда имеет три и более «точек входа», то комментарии уже не спасают и возникает путаница, вынуждающая использовать вместо дизассемблера трассер. [изощренные обфускаторы] отслеживают зависимости по данным, внедряя осмысленные инструкции с «нулевым эффектом». Поясним на конкретном примере. Допустим, обфускатору встретилась конструкция: оригинальный код до обфускации PUSH EAX ; последнее обращение к eax MOV EAX,EBX ; реинициализация eax Легко показать, что между последним обращением к eax и его реиницилизацией можно как угодно модифицировать регистр eax без ущерба для выполнения программы, поскольку любые операции присвоения все равно будут перекрыты командой mov eax,ebx. |