Использование SEH для антиотладки
Использование SEH для антиотладки
В сегодняшней статье разберем использование SEH в качестве антиотладочного приема. Трюк старый, как бивень мамонта, опытным реверсерам обнаружить и обойти его не составит абсолютно никакого труда, а новичкам может быть интересно. Например, в исполняемых файлах, упакованных PECompact, управление с точки входа на процедуру распаковки передается именно таким способом.
Принцип использования этого трюка в точности повторяет штатное использование SEH для обработки ошибок и исключений. То есть установка SEH на определенный адрес обработчика и искусственное создание условий для его исполнения. Вот упомянутый обработчик из PECompact:
Передача управления в PECompact
Устанавливается адрес, на который будет выполнен переход, затем генерируется исключение типа ACCESS VIOLATION при попытке записи в нулевую ячейку памяти.
Немного более продвинутый способ антиотладки с использованием SEH - внедрение в линейный код большого количества команд, которые будут генерировать исключения, и "мусорного" кода, который никогда не будет выполняться. При просмотре дизассемблерного листинга такие участки могут ввести исследователя в заблуждение. Вот простейший пример для демонстрации этой техники:
Code (Assembler) : Убрать нумерацию
- ; Добавить наш обработчик в цепочку
- push seh_antidebug
- push dword [fs:0]
- mov [fs:0],esp
- ; Первое срабатывание - SINGLE STEP
- pushfd
- ; Установить флаг отладки
- or dword [esp],0x100
- popfd
- or eax,eax
- skip_data:
- invoke ExitProcess,0
- len_skip = $-skip_data
- ; Второе срабатывание - BREAKPOINT
- int3
- invoke ExitProcess,0
- ; Третье срабатывание - ACCESS VIOLATION
- xor eax,eax
- mov [eax],ecx
- invoke ExitProcess,0
- ; Четвертое срабатывание - ILLEGAL INSTRUCTION
- ud2
- invoke ExitProcess,0
- ; Убрать наш обработчик
- pop dword[fs:0]
- add esp, 4
Code (Assembler) : Убрать нумерацию
- ;-------------------------------------------------------------------------
- ; Обработчик критических ошибок
- ;-------------------------------------------------------------------------
- proc seh_antidebug pExcept:DWORD, pFrame:DWORD, pContext:DWORD, pDispatch:DWORD
- mov edi,[pContext]
- ; Получить адрес, по которому произошло срабатывание
- mov eax,[edi+0xB8]
- ; Пропустить ud2
- cmp word[eax],0B0Fh
- jne @f
- add dword [edi+0xB8],2
- @@:
- ; Пропустить mov [eax],ecx
- cmp word[eax],0889h
- jne @f
- add dword [edi+0xB8],2
- @@:
- ; Пропустить int3
- cmp byte[eax],0CCh
- jne @f
- inc dword [edi+0xB8]
- @@:
- ; Увеличить regEip на длину вызова ExitProcess
- add dword [edi+0xB8],len_skip
- xor eax,eax
- ret
- endp
А вот теперь переходим к самому интересному - наномитам. Эта технология применялась в навесном протекторе Armadillo. Смысл наномитов заключается в том, что протектор анализирует бинарный код и заменяет некоторые условные переходы на вызов точки останова int 3. Все адреса замененных переходов, их условия и адреса передачи управления в случае выполнения условий сохраняются в секции протектора. При получении управления замененной командой срабатывает исключение, протектор проверяет адрес, откуда пришло исключение, по нему получает условие и адреса переходов и обрабатывает это все в своем коде.
Давайте попробуем сделать нечто подобное, но на основе своего кода. Например, реализуем обработку двух типов переходов - условного JE и безусловного JMP. Для этого в коде будет конструкция, включающая в себя команду для генерации исключения, тип перехода, а также адрес, куда нужно передать управление в случае выполнения условия.
Code (Assembler) : Убрать нумерацию
- NANO_JE = 1
- NANO_JMP = 2
- NANO_FIX_LEN = 3
Code (Assembler) : Убрать нумерацию
- ; Добавить наш обработчик в цепочку
- push seh_antidebug
- push dword [fs:0]
- mov [fs:0],esp
- invoke MessageBox,HWND_DESKTOP,szMess,szTitle,MB_YESNOCANCEL
- cmp eax,IDYES
- ; JE loc_yes
- db 0x0F,0x0B,NANO_JE
- dw loc_yes-$+NANO_FIX_LEN
- cmp eax,IDNO
- ; JE loc_no
- db 0x0F,0x0B,NANO_JE
- dw loc_no-$+NANO_FIX_LEN
- invoke MessageBox,HWND_DESKTOP,szCancel,szTitle,MB_OK
- ; JMP loc_exit
- db 0x0F,0x0B,NANO_JMP
- dw loc_exit-$+NANO_FIX_LEN
- loc_no:
- invoke MessageBox,HWND_DESKTOP,szNo,szTitle,MB_OK
- loc_exit:
- ; Убрать наш обработчик
- pop dword[fs:0]
- add esp, 4
- invoke ExitProcess,0
- loc_yes:
- invoke MessageBox,HWND_DESKTOP,szYes,szTitle,MB_OK
- ; JMP loc_exit
- db 0x0F,0x0B,NANO_JMP
- dw loc_exit-$+NANO_FIX_LEN
Code (Assembler) : Убрать нумерацию
- ;-----------------------------------------------
- ; Обработчик критических ошибок
- ;-----------------------------------------------
- proc seh_antidebug pExcept:DWORD, pFrame:DWORD, pContext:DWORD, pDispatch:DWORD
- mov edi,[pContext]
- ; Получить адрес, по которому произошло срабатывание
- mov eax,[edi+0xB8]
- ; Это наш наномит?
- cmp word [eax],0B0Fh
- jne .loc_ret
- ; Обработка команды JE
- cmp byte [eax+2],NANO_JE
- je .loc_je
- ; Обработка команды JMP
- cmp byte [eax+2],NANO_JMP
- je .loc_jmp
- ; Неизвестная команда
- jmp .loc_ret
- ;----------------------------------------
- ; Эмуляция JMP
- ;----------------------------------------
- .loc_jmp:
- ; Получить длину перехода
- movsx eax,word [eax+3]
- ; Увеличить/уменьшить regEip на длину перехода
- add dword [edi+0xB8],eax
- jmp .loc_ret
- ;----------------------------------------
- ; Эмуляция JE
- ;----------------------------------------
- .loc_je:
- ; Проверить ZF (бит 6) в regFlag
- test dword [edi+0xC0],40h
- jnz @f
- ; Условие для JE не выполнено
- add dword [edi+0xB8],5
- jmp .loc_ret
- @@:
- ; Получить длину условного перехода
- movsx eax,word [eax+3]
- ; Увеличить/уменьшить regEip на длину условного перехода
- add dword [edi+0xB8],eax
- .loc_ret:
- xor eax,eax
- ret
- endp
Это лишь краткий пример, подобную обработку можно использовать для динамической модификации кода, расшифровки кода перед выполнением и шифрованием после выполнения, да вообще, при наличии фантазии и нужного радиуса кривизны рук возможности открываются поистине безграничные.
В приложении примеры программ с исходными текстами, которые используют описанные в статье антиотладочные техники.
Просмотров: 1560 | Комментариев: 0
Внимание! Статья опубликована больше года назад, информация могла устареть!
Комментарии
Отзывы посетителей сайта о статье
Комментариeв нет
Добавить комментарий
Заполните форму для добавления комментария