Трудовая дисциплина Крис Касперски aka мыщъх Хакер, номер #088, стр. 088-114-4 Во-первых, метка debugger_is_present не определена и вставлена чисто для наглядности, во-вторых, мы уже установили обработчик структурных исключений, флаг трассировки - взвели, а вот о том, что после завершения проверки на отладчик все необходимо вернуть обратно, забыли! Поэтому перед употреблением листинг необходимо слегка доработать, например, так: [законченная программа anti-debug.c] main() { int a; // через эту переменную мы возвратим значение eax __asm{ // ассемблерная вставка — начало push offset my_seh push dword ptr fs:[0] mov fs:[0],esp pushf or dword ptr[esp],100h ;set trap flag popf xor eax,eax my_seh: pop dword ptr fs:[0] ; восстанавливаем старый обработчик add esp,4 ; восстанавливаем стек mov a,eax ; возвращаем результат в переменной а } ; ассемблерная вставка - конец // проверка переменной a на равенство нулю printf("%s\n",a?"no debugger":"under debugger"); } Не самый лучший вариант, конечно. При входе в обработчик структурных исключений мы должны выйти из него через недокументированную API-функцию Continue, хотя… будет работать и так. Поэтому не будем отвлекаться на мелочи технической реализации, а сосредоточимся на оформлении ассемблерной вставки. Мы удаляем "jnz debugger_is_present", а вместо этого возвращаем значение через предварительно объявленную переменную "a". Компилируем программу как обычно ("cl.exe anti-debug.c") и пытаем, то есть делаем попытку запустить. При прогоне под SoftICE, OllyDbg или любым другим неэмулирующим отладчиком на экране покажется "under debugger" или "no debugger". Значит, наша программа работает правильно, и трансляция удалась! Отрываем мыщъху хвост от радости, тем более что с крышей у него проблемы (ну, с головой). Прохудилась и течет зараза, а времени на ремонт нет. Так что мыщъх пишет эти строки, сидя на ноотропах в состоянии измененного сознания и не вполне вменяем, а потому временами не совсем адекватен. Ладно, это мои личные проблемы, так что не высаживайтесь (мы с Крисом, наверное, разные ноотропы кушаем - меня от моих прет. - Прим. Горлума). А вот другой классический пример: .code ; секция кода start: ; точка входа push 0 ; uType push 0 ; lpCamtion push offset s0 ; lpText push 0 ; hWnd call MessageBoxA ; зовем функцию ret ; после нажатия на ок выходим отсюда на хер .data ; секция данных s0 db "hello,wordl",0Dh,0Ah,0 ; строка, которую мы будем выводить end start Попытка загнать текст программы в ассемблерную вставку ни к чему хорошему не приводит. Компилятор кроет нас матом и компилить отказывается. Вот… «не в эфире будет сказано»! Приходится действовать стратегически. То есть свирепо и радикально. Убираем директивы .code и .data вместе с ненужной инструкцей "ret" (в оригинале она завершает программу, пользуясь тем фактом, что при запуске PE-файла на вершине стека лежит адрес на термирующую процедуру, однако в стековом фрейме нашей ассемблерной вставки ничего подобного нет). |