Издательский дом ООО "Гейм Лэнд"СПЕЦВЫПУСК ЖУРНАЛА ХАКЕР #66, МАЙ 2006 г.

ОБФУСКАЦИЯ И ЕЕ ПРЕОДОЛЕНИЕ

КРИС КАСПЕРСКИ АКА МЫЩЪХ

Спецвыпуск: Хакер, номер #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.

Назад на стр. 066-008-2  Содержание  Вперед на стр. 066-008-4