Хакерские трюки или как поставить бряк на jmp eax

       

Первые шаги или установка точки останова на одну команду


Начнем с простого. Возьмем демонстрационный пример TF.exe и попытаемся брякнуться на команду PUSHFD. Загружаем программу в отладчик, в меню "debug" выбираем "set condition" или нажимаем <CTRL-T>. На экране появляется симпатичное диалоговое окно "condition to pause run trace" (см.рис. 1), позволяющее обрывать трассировку при выходе регистра EIP за определенный диапазон ("EIP is in range") или, наоборот, при входе в него ("EIP is outside the range"). Так же поддерживается останов по срабатыванию некоторого условия ("condition is TRUE") или выполнению одной из следующий команд ("command is one of"). Как раз это нам и нужно!

Рисунок 1 диалоговое окно отладчика OllyDbg, позволяющее устанавливать точки останова на произвольные машинные команды

Вводим в окно редактирования "PUSHD" (ес-но без кавычек), взводим соседствующию с ним галочку и говорим "OK". Диалоговое окно исчезает и мы возвращаемся в OllyDbg. Если теперь нажать <F9> (run), то... ничего не получится, поскольку условные точки останова работают _только_ в режиме трассировки, поэтому мы жмем <CTRL-F11> (debug à trace into). Экран отладчика остается неизменным и кажется, что ничего не происходит, только в правом нижнем углу строки статуса появляется надпись "tracing", подтверждающая, что трассировка идет полным ходом и сильно загружает ядро операционной системы.

Рисунок 2 надпись в строке статуса, свидетельствующая о том, что отладчик работает в режиме трассировки

Если во время трассировки нажать <CTRL-SHIFT-ESC> (комбинация, вызывающая "диспетчер задач"), мы увидим извилистую красную кривую (см. рис. 3), сигнализирующую о необычно высоком уровне активности отладчика (если красной кривой нет, взведите галочку "вывод времени ядра" в меню "вид").

Рисунок 3 в режиме трассировки OllyDbg сильно загружает осевое ядро


Если вместо <CTRL-F11> нажать <CTRL-F7> ("animate into"), то скорость трассировки упадет в десятки раз, но зато OllyDbg будет обновлять окно CPU на каждом шагу, подсвечивая текущую выполняемую команду курсором (см. рис. 4). Выглядит очень красиво (особенно интересно наблюдать за циклами), но для практической работы оно непригодно. Прервать трассировку (как анимационную, так и обычную) можно в любой момент клавишей <ESC>, при этом отладчик остановится на последней выполненной инструкции.



Рисунок 4 анимированная трассировка в OllyDbg (в правом нижнем углу строки статуса горит "animating")



Если же вести трассировку до победоносного конца, то спустя некоторое время (определяемое в первую очередь мощностью вашего ЦП), отладчик остановится на инструкции PUSHFD (см. рис. 5). Это и есть "сердце" защитного механизма, который нам предстоит проанализировать и обезвредить.



Рисунок 5 остановка отладчика по срабатыванию точки останова на команду PUSHFD

Антиотладочный код предельно прост и укладывается всего в четыре строки (см. листинг 1):

0040100E |. 9C                    PUSHFD

0040100F |. 58                    POP EAX

00401010 |. 25 00010000    AND EAX,100

00401015 |. 75 03          JNZ SHORT TF.0040101A

Листинг 1 антиотладочный код, основанный на чтении регистра флагов

Защита заталкивает в стек регистр флагов командой PUSHFD и тут же выталкивает его в EAX, проверяя бит трассировки логической операцией AND EAX 100h. Только никакого бита трассировки в стеке ни хрена не окажется — OllyDbg автоматически удалит его, но чтобы программа работала и под другими отладчиками, необходимо заменить JNZ на NOP/NOP или AND EAX, 100h на AND EAX, 0h.

Если немного потрассировать программу, мы выйдем из антиотладочной процедуры и попадем в довольно типичный для высокоуровневых программ машинный код, проверяющий значение, возращенное функций, с помощью пары инструкций TEST EAX,EAX/Jx (см. листинг 2):



0040102A |. E8 D1FFFFFF    CALL TF.00401000

0040102F |. 85C0           TEST EAX,EAX

00401031 |. 74 0F          JE SHORT TF.00401042

00401033 |. 68 30604000    PUSH TF.00406030; ASCII "debugger was not been detected"

00401038 |. E8 6C000000    CALL TF.004010A9

0040103D |. 83C4 04        ADD ESP,4

00401040 |. EB 0D          JMP SHORT TF.0040104F

00401042 |> 68 50604000    PUSH TF.00406050 ;  ASCII "debugger has been detected!"

00401047 |. E8 5D000000    CALL TF.004010A9

0040104C |. 83C4 04        ADD ESP,4

Листинг 2 обработка результата работы функции

Давайте попробуем установить точку останова на комбинацию команд CALL XXX\TEST EAX,EAX\JX. А вот не получается! В окно "condition to pause run trace" ясно сказано "command is one of" (одна из следующий команд), то есть если ввести "call const; test eax,eax; jСС const", отладчик будет останавливаться на _каждой_ из перечисленных команд, что совсем не входит в наши планы, но такой уж у OllyDbg синтаксис!

Кстати, о синтаксисе. Отладчик поддерживает шаблоны, позволяющие составлять простейшие регулярные выражения. Например, R32 обозначает любой 32-разрядный регистр общего назначения и "TEST R32, R32" – останавливает трассировку при выполнении команд TEST EAX, EAX; TEST ESI, EDX и т. д. "RA" – любой регистр общего назначения не такой как "RB", поэтому, шаблон "TEST RA, RA" будет останавливаться на инструкции "TEST EAX, EAX", но проскочит мимо "TEST EAX, EBX". Соответственно, "TEST RA, RB" останется равнодушным к "TEST EAX, EAX". Ключевое слово "CONST" заменяет любой непосредственный операнд, например, "MOV RA, CONST" останавливается на "MOV AL, 69h" и "MOV ESI, 666h", а "CALL CONST" – на всяком прямом вызове процедуры.


Выражение "JCC CONST" соответствует любому условному (но _не_ безусловному!) переходу по непосредственному адресу. Остальные ключевые слова перечислены в таблице 1.

ключевое слово

назначение

R8

любой 8-битный регистр (AL,BL, CL, DL, AH, BH, CH, DH)

R16

любой 16-битный регистр (AX, BX, CX, DX, SP, BP, SI, DI)

R32

любой 32-битный регистр (EAX, EBX, ECX, EDX, ESP, EBP, ESI, EDI)

FPU

любой регистр математического сопроцессора (ST0..ST7)

MMX

любой MMX-регистр (MM0..MM7)

CRX

любой регистр управления (CR0..CR7)

DRX

любой отладочный регистр (DR0..DR7)

CONST

любая константа

OFFSET

любое смещение (равнозначно константе)

JCC

любой условный переход (JE, JC, JNGE...)

SETCC

любая инструкция условной установки байт (SETE, SETC, SETNGE... )

CMOVCC

любая условная пересылка (CMOVE, CMOVC, CMOVNGE...)

Таблица 1 ключевые слова, поддерживаемые OllyDbg в выражениях точек останова

Все это, конечно, замечательно и немного потренировавшись мы сможем брякаться на любой машинной команде (за исключением адресации типа mem, которую Olly не поддерживает), но нам-то нужны не отдельные команды, а сочетания _нескольких_ команд. Как быть, что делать?


Содержание раздела