Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
книги хакеры / Майкл_Сикорски,_Эндрю_Хониг_Вскрытие_покажет!_Практический_анализ.pdf
Скачиваний:
18
Добавлен:
19.04.2024
Размер:
17.17 Mб
Скачать

 

 

 

 

hang

e

 

 

 

 

 

 

 

C

 

E

 

 

 

 

X

 

 

 

 

 

 

-

 

 

 

 

 

d

 

 

F

 

 

 

 

 

 

t

 

 

D

 

 

 

 

 

 

 

i

 

 

 

 

 

 

 

 

 

r

P

 

 

 

 

 

NOW!

o

 

 

 

 

 

 

 

 

 

 

 

 

BUY

 

 

 

 

 

 

to

 

 

 

 

 

w Click

 

 

 

 

 

m

 

 

 

 

 

 

w

 

 

 

 

 

 

 

 

 

 

w

 

 

 

 

 

 

 

o

 

 

.

 

 

 

 

 

.c

 

 

 

p

 

 

 

 

g

 

 

 

 

 

df

 

 

n

e

 

 

 

 

 

-xcha

 

 

 

 

 

 

 

 

hang

e

 

 

 

 

 

 

 

C

 

E

 

 

 

 

X

 

 

 

 

 

 

-

 

 

 

 

 

d

 

 

F

 

 

 

 

 

 

t

 

 

D

 

 

 

 

 

 

 

i

 

 

 

 

 

 

 

 

 

r

P

 

 

 

 

 

NOW!

o

 

 

 

 

 

 

 

 

 

 

 

 

BUY

 

 

Глава 6. Распознавание конструкций языка C в ассемблере  139

to

 

 

 

 

 

w Click

 

 

 

 

 

m

 

 

 

 

 

 

w

 

 

 

 

 

 

 

 

 

 

w

 

 

 

 

 

 

 

o

 

 

.

 

 

 

 

 

.c

 

 

 

p

 

 

 

 

g

 

 

 

 

 

df

 

 

n

e

 

 

 

 

 

-x cha

 

 

 

 

Последние пять ассемблерных инструкций реализуют деление с остатком. При выполнении инструкций div или idiv edx:eax делится на операнд; результат сохраняется в регистре eax, а остаток — в edx. Именно поэтому edx перемещается в var_8 .

Распознавание выражений if

Программисты используют выражения if для изменения хода выполнения программы в зависимости от определенных условий. Эти конструкции часто применяются в ассемблере и коде на языке C. В этом разделе мы рассмотрим простое и вложенное ветвление. Ваша цель — научиться распознавать разные виды выражений if.

В листинге 6.8 показано простое ветвление на языке C, а в листинге 6.9 оно транслировано в ассемблер. Обратите внимание на условный переход jnz . Конструкция if всегда подразумевает условный переход, но не все условные переходы соответствуют конструкциям if.

Листинг 6.8. Пример выражения if на языке C

int x = 1; int y = 2;

if(x == y){

printf("x equals y.\n"); }else{

printf("x is not equal to y.\n");

}

Листинг 6.9. Пример выражения if из листинга 6.8, транслированный в ассемблер

00401006

mov

[ebp+var_8], 1

0040100D

mov

[ebp+var_4], 2

00401014

mov

eax, [ebp+var_8]

00401017

cmp

eax, [ebp+var_4]

0040101A

jnz

short loc_40102B

0040101C

push

offset aXEqualsY_ ; "x equals y.\n"

00401021

call

printf

00401026

add

esp, 4

00401029

jmp

short loc_401038

0040102B

loc_40102B:

 

0040102B

push

offset aXIsNotEqualToY ; "x is not equal to y.\n"

00401030

call

printf

В листинге 6.9 видно, что перед входом внутрь выражения if (см. листинг 6.8) нужно принять определенное решение, которое соответствует условному переходу jnz . Выполнение перехода зависит от сравнения (cmp), которое проверяет равенство переменных var_4 и var_8 (var_4 и var_8 представляют переменные x и y из нашего исходного кода). Если значения не равны, происходит переход и код выводит строку "x is not equal to y.". В противном случае поток выполнения продолжается и на экран выводится строка "x equals y.".

 

 

 

 

hang

e

 

 

 

 

 

 

 

C

 

E

 

 

 

 

X

 

 

 

 

 

 

-

 

 

 

 

 

d

 

 

F

 

 

 

 

 

 

t

 

 

D

 

 

 

 

 

 

 

i

 

 

 

 

 

 

 

 

 

r

P

 

 

 

 

 

NOW!

o

 

 

 

 

 

 

 

 

 

 

 

 

BUY

 

 

w

 

 

to

 

 

140  Часть II  •  Продвинутый статический анализ

w Click

 

 

 

 

 

 

 

 

 

 

 

o

m

 

w

 

 

 

 

 

 

 

 

 

.

 

 

 

 

 

.c

 

 

 

p

 

 

 

 

g

 

 

 

 

 

df

 

 

n

e

 

 

 

 

 

-xcha

 

 

 

 

 

 

 

 

hang

e

 

 

 

 

 

 

 

C

 

E

 

 

 

 

X

 

 

 

 

 

 

-

 

 

 

 

 

d

 

 

F

 

 

 

 

 

 

t

 

 

D

 

 

 

 

 

 

 

i

 

 

 

 

 

 

 

 

 

r

P

 

 

 

 

 

NOW!

o

 

 

 

 

 

 

 

 

 

 

 

 

BUY

 

 

 

 

 

 

to

 

 

 

 

 

w Click

 

 

 

 

 

m

 

 

 

 

 

 

w

 

 

 

 

 

 

 

 

 

 

w

 

 

 

 

 

 

 

o

 

 

.

 

 

 

 

 

.c

 

 

 

p

 

 

 

 

g

 

 

 

 

 

df

 

 

n

e

 

 

 

 

 

-x cha

 

 

 

 

Обратите также внимание на переход jmp, который минует участок else . Важно понимать, что программа может пройти только по одному из этих двух маршрутов.

Графический анализ функций с помощью IDA Pro

IDA Pro предоставляет графические инструменты, которые могут пригодиться при распознавании конструкций. На рис. 6.1 показано представление, которое используется по умолчанию для анализа функций.

Рис. 6.1. Схематическое представление ассемблерного кода для примера из листинга 6.9

Вы можете видеть схему кода на ассемблере в листинге 6.9. К концу функции ведут два разных пути выполнения, и , и каждый из них выводит свою строку. Путь отображает "x equals y.", а путь "x is not equal to y.".

 

 

 

 

hang

e

 

 

 

 

 

 

 

C

 

E

 

 

 

 

X

 

 

 

 

 

 

-

 

 

 

 

 

d

 

 

F

 

 

 

 

 

 

t

 

 

D

 

 

 

 

 

 

 

i

 

 

 

 

 

 

 

 

 

r

P

 

 

 

 

 

NOW!

o

 

 

 

 

 

 

 

 

 

 

 

 

BUY

 

 

 

 

 

 

to

 

 

 

 

 

w Click

 

 

 

 

 

m

 

 

 

 

 

 

w

 

 

 

 

 

 

 

 

 

 

w

 

 

 

 

 

 

 

o

 

 

.

 

 

 

 

 

.c

 

 

 

p

 

 

 

 

g

 

 

 

 

 

df

 

 

n

e

 

 

 

 

 

-xcha

 

 

 

 

 

 

 

 

hang

e

 

 

 

 

 

 

 

C

 

E

 

 

 

 

X

 

 

 

 

 

 

-

 

 

 

 

 

d

 

 

F

 

 

 

 

 

 

t

 

 

D

 

 

 

 

 

 

 

i

 

 

 

 

 

 

 

 

 

r

P

 

 

 

 

 

NOW!

o

 

 

 

 

 

 

 

 

 

 

 

 

BUY

 

 

Глава 6. Распознавание конструкций языка C в ассемблере  141

to

 

 

 

 

 

w Click

 

 

 

 

 

m

 

 

 

 

 

 

w

 

 

 

 

 

 

 

 

 

 

w

 

 

 

 

 

 

 

o

 

 

.

 

 

 

 

 

.c

 

 

 

p

 

 

 

 

g

 

 

 

 

 

df

 

 

n

e

 

 

 

 

 

-x cha

 

 

 

 

IDA Pro добавляет метки false и true в точках принятия решений (снизу от верхнего блока кода). Как можно догадаться, схематическое представление функций может здорово ускорить процесс обратного проектирования.

Распознавание вложенных выражений if

В листинге 6.10 показан код на языке C с вложенным выражением if. Он похож на листинг 6.8, но содержит два дополнительных условных выражения, которые проверяют, равно ли z нулю.

Листинг 6.10. Код на языке C с вложенными выражениями if

int x = 0; int y = 1; int z = 2;

if(x == y){ if(z==0){

printf("z is zero and x = y.\n"); }else{

printf("z is non-zero and x = y.\n");

}

}else{

if(z==0){

printf("z zero and x != y.\n"); }else{

printf("z non-zero and x != y.\n");

}

}

Несмотря на незначительное изменение исходного текста на языке C, код на ассемблере выглядит более сложным (листинг 6.11).

Листинг 6.11. Код на ассемблере для вложенного выражения if из листинга 6.10

00401006

mov

[ebp+var_8], 0

0040100D

mov

[ebp+var_4], 1

00401014

mov

[ebp+var_C], 2

0040101B

mov

eax, [ebp+var_8]

0040101E

cmp

eax, [ebp+var_4]

00401021

jnz

short loc_401047

00401023

cmp

[ebp+var_C], 0

00401027

jnz

short loc_401038

00401029

push

offset aZIsZeroAndXY_ ; "z is zero and x = y.\n"

0040102E

call

printf

00401033

add

esp, 4

00401036

jmp

short loc_401045

00401038

loc_401038:

 

00401038

push

offset aZIsNonZeroAndX ; "z is non-zero and x = y.\n"

0040103D

call

printf

00401042

add

esp, 4

00401045

loc_401045:

 

00401045

jmp

short loc_401069

 

 

 

 

hang

e

 

 

 

 

 

 

 

 

 

C

 

E

 

 

 

 

 

 

X

 

 

 

 

 

 

 

 

-

 

 

 

 

 

d

 

 

 

 

F

 

 

 

 

 

 

t

 

 

 

 

D

 

 

 

 

 

 

 

i

 

 

 

 

 

 

 

 

 

 

 

r

 

 

P

 

 

 

 

 

NOW!

o

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

BUY

 

 

 

 

w

 

 

to

 

 

142  Часть II 

•  Продвинутый статический анализ

w Click

 

 

 

 

 

 

 

 

 

 

 

 

 

o

m

 

 

 

w

 

 

 

 

 

 

 

 

 

 

 

.

 

 

 

 

 

.c

 

 

 

 

 

p

 

 

 

 

g

 

 

 

 

 

 

 

df

 

 

n

e

 

 

 

 

 

 

 

-xcha

 

 

 

 

 

 

 

 

 

 

 

 

 

 

00401047 loc_401047:

 

 

 

 

 

 

 

 

 

00401047

cmp

[ebp+var_C], 0

 

 

 

 

 

 

 

 

0040104B

jnz

short loc_40105C

 

 

 

 

 

 

 

 

0040104D

push

offset aZZeroAndXY_ ; "z zero and x != y.\n"

 

 

 

 

 

 

 

 

00401052

call

printf

 

 

 

 

 

 

 

 

00401057

add

esp, 4

 

 

 

 

 

 

 

 

0040105A

jmp

short loc_401069

 

 

 

 

 

 

 

 

0040105C loc_40105C:

 

 

 

 

 

 

 

 

 

0040105C

push

offset aZNonZeroAndXY_ ; "z non-zero and x != y.\n"

 

 

 

 

 

 

 

 

00401061

call

printf00401061

 

 

 

 

hang

e

 

 

 

 

 

 

 

C

 

E

 

 

 

 

X

 

 

 

 

 

 

-

 

 

 

 

 

d

 

 

F

 

 

 

 

 

 

t

 

 

D

 

 

 

 

 

 

 

i

 

 

 

 

 

 

 

 

 

r

P

 

 

 

 

 

NOW!

o

 

 

 

 

 

 

 

 

 

 

 

 

BUY

 

 

 

 

 

 

to

 

 

 

 

 

w Click

 

 

 

 

 

m

 

 

 

 

 

 

w

 

 

 

 

 

 

 

 

 

 

w

 

 

 

 

 

 

 

o

 

 

.

 

 

 

 

 

.c

 

 

 

p

 

 

 

 

g

 

 

 

 

 

df

 

 

n

e

 

 

 

 

 

-x cha

 

 

 

 

Здесь присутствуют три условных перехода. Первый происходит в случае, если var_4 не равно var_8 . Остальные два становятся возможными, когда переменная var_C не равна нулю, и .

Распознавание циклов

Циклы и повторяемые задачи широко используются в любых программах. Важно, чтобы вы могли их распознать.

Поиск цикла for

Выражение for является базовым циклическим механизмом в языке C. Циклы for всегда состоят из четырех этапов: инициализации, сравнения, выполнения инструкций и инкремента/декремента.

Пример цикла for показан в листинге 6.12.

Листинг 6.12. Цикл for в языке C int i;

for(i=0; i<100; i++)

{

printf("i equals %d\n", i);

}

Вэтом примере во время инициализации переменной i присваивается 0 (ноль),

апри сравнении проверяется, является ли i меньше 100. Если i меньше 100, будет выполнена инструкция printf, переменная i будет инкрементирована на 1, и затем процесс опять выполнит ту же проверку. Эти шаги будут повторяться, пока i не превысит или не станет равно 100.

Вассемблере цикл for можно распознать по его четырем компонентам: инициализации, сравнению, выполнению инструкций и инкременту/декременту. Например,

в листинге 6.13 шаг соответствует инициализации. Код между и отведен для инкремента, который изначально переходит к шагу с помощью инструкции jmp. Сравнение происходит на шаге , а в условный переход принимает решение. Если переход не выполнится, будет вызвана инструкция printf, после чего в строке произойдет безусловный переход, который инициирует инкремент.

 

 

 

 

hang

e

 

 

 

 

 

 

 

 

C

 

E

 

 

 

 

 

X

 

 

 

 

 

 

 

-

 

 

 

 

 

d

 

 

 

F

 

 

 

 

 

 

t

 

 

 

D

 

 

 

 

 

 

 

i

 

 

 

 

 

 

 

 

 

 

r

 

P

 

 

 

 

 

NOW!

o

 

 

 

 

 

 

 

 

 

 

 

 

 

 

BUY

 

 

 

w

 

 

to

 

 

 

 

 

Глава 6. Распознавание конструкций

w Click

 

 

 

 

 

 

 

 

 

 

 

 

o

m

 

 

w

 

 

 

 

 

 

 

 

 

 

.

 

 

 

 

 

.c

 

 

 

 

p

 

 

 

 

g

 

 

 

 

 

 

df

 

 

n

e

 

 

 

 

 

 

-xcha

 

 

 

 

 

Листинг 6.13. Код на ассемблере для цикла for из листинга 6.12

 

 

 

 

hang

e

 

 

 

 

 

 

 

C

 

E

 

 

 

 

X

 

 

 

 

 

 

-

 

 

 

 

 

d

 

 

F

 

 

 

 

 

 

t

 

 

D

 

 

 

 

 

 

 

i

 

 

 

 

 

 

 

 

 

r

P

 

 

 

 

 

NOW!

o

 

 

 

 

 

 

 

 

 

 

 

 

BUY

 

 

языка C в ассемблере  143

to

 

 

 

 

 

w Click

 

 

 

 

 

m

 

 

 

 

 

 

w

 

 

 

 

 

 

 

 

 

 

w

 

 

 

 

 

 

 

o

 

 

.

 

 

 

 

 

.c

 

 

 

p

 

 

 

 

g

 

 

 

 

 

df

 

 

n

e

 

 

 

 

 

-x cha

 

 

 

 

00401004

mov

[ebp+var_4], 0

0040100B

jmp

short loc_401016

0040100D

loc_40100D:

 

0040100D

mov

eax, [ebp+var_4]

00401010

add

eax, 1

00401013

mov

[ebp+var_4], eax

00401016

loc_401016:

 

00401016

cmp

[ebp+var_4], 64h

0040101A

jge

short loc_40102F

0040101C

mov

ecx, [ebp+var_4]

0040101F

push

ecx

00401020

push

offset aID ; "i equals %d\n"

00401025

call

printf

0040102A

add

esp, 8

0040102D

jmp

short loc_40100D

Цикл for можно распознать с помощью схематического режима IDA Pro, как показано на рис. 6.2.

Рис. 6.2. Схема дизассемблированного кода для цикла for из листинга 6.13