Фундаментальные основы хакерства. Определяем курс выполнения программ при реверсинге - «Новости» » Самоучитель CSS
Меню
Наши новости
Учебник CSS

Невозможно отучить людей изучать самые ненужные предметы.

Введение в CSS
Преимущества стилей
Добавления стилей
Типы носителей
Базовый синтаксис
Значения стилевых свойств
Селекторы тегов
Классы
CSS3

Надо знать обо всем понемножку, но все о немногом.

Идентификаторы
Контекстные селекторы
Соседние селекторы
Дочерние селекторы
Селекторы атрибутов
Универсальный селектор
Псевдоклассы
Псевдоэлементы

Кто умеет, тот делает. Кто не умеет, тот учит. Кто не умеет учить - становится деканом. (Т. Мартин)

Группирование
Наследование
Каскадирование
Валидация
Идентификаторы и классы
Написание эффективного кода

Самоучитель CSS

Вёрстка
Изображения
Текст
Цвет
Линии и рамки
Углы
Списки
Ссылки
Дизайны сайтов
Формы
Таблицы
CSS3
HTML5

Новости

Блог для вебмастеров
Новости мира Интернет
Сайтостроение
Ремонт и советы
Все новости

Справочник CSS

Справочник от А до Я
HTML, CSS, JavaScript

Афоризмы

Афоризмы о учёбе
Статьи об афоризмах
Все Афоризмы

Видео Уроки


Наш опрос



Наши новости

       
18-05-2022, 00:02
Фундаментальные основы хакерства. Определяем курс выполнения программ при реверсинге - «Новости»
Рейтинг:
Категория: Новости

стра­нице авто­ра.

Рань­ше мы уже встре­чались с условным ходом выпол­нения прог­рамм, одна­ко огра­ничи­вались корот­кими опи­сани­ями команд и повер­хностным раз­бором выпол­няемых ими опе­раций. Управля­емый ход выпол­нения, без сом­нения, самая важ­ная веха раз­вития прог­рамми­рова­ния сво­его вре­мени и зат­мева­ет мно­гие пос­леду­ющие, даже такие, как струк­турное прог­рамми­рова­ние или ООП. Толь­ко с высоты высоко­уров­невого язы­ка кажет­ся, что в усло­вии if then else нет ничего любопыт­ного и оно лишено какого‑либо раз­нооб­разия. Но для ком­пилято­ра это прос­тор для самоде­ятель­нос­ти! И в близ­ких по духу ситу­ациях он может пос­тро­ить кар­диналь­но раз­лича­ющий­ся код.


В про­цес­сорной архи­тек­туре x86 пре­дус­мотрен весь­ма «ори­гиналь­ный» набор команд для перенап­равле­ния хода выпол­нения прог­рам­мно­го кода. «Ори­гиналь­ный» не зна­чит хороший или пло­хой, это зна­чит, что он отли­чает­ся от набора мик­ропро­цес­соров дру­гих архи­тек­тур и про­изво­дите­лей: ARM, MIPS, SPARC и так далее. Как ты зна­ешь, пер­вый про­цес­сор этой серии соз­давал­ся впо­пыхах для вре­мен­ной замены еще не готово­го iAPX-432, пос­ледний, в свою оче­редь, дол­жен был уметь в мно­гоза­дач­ность и управле­ние памятью на аппа­рат­ном уров­не. Чего в ито­ге не слу­чилось. А x86 про­дол­жил свое раз­витие. Поэто­му сей­час, ког­да за годы эво­люции про­цес­соров серии x86 ско­пил­ся набор инс­трук­ций, хакерам при­ходит­ся раз­гре­бать весь этот хлам, дабы рас­кру­тить порядок выпол­нения машин­ных инс­трук­ций.


 

Идентификация условных операторов


Су­щес­тву­ет два вида алго­рит­мов — безус­ловные и условные. Порядок дей­ствий безус­ловно­го алго­рит­ма всег­да пос­тоянен и не зависит от вход­ных дан­ных. Нап­ример, a = b + c. Порядок дей­ствий условных алго­рит­мов, нап­ротив, зависит от дан­ных, пос­тупа­ющих «на вход». Нап­ример:


ес­ли c не рав­но нулю,
то: a = b/c;
ина­че: вывес­ти сооб­щение об ошиб­ке


Об­рати вни­мание на выделен­ные жир­ным шриф­том клю­чевые сло­ва «если», «то» и «ина­че», называ­емые опе­рато­рами усло­вия или условны­ми опе­рато­рами. Без них не обхо­дит­ся ни одна прог­рамма (вырож­денные при­меры наподо­бие «Hello, World!» не в счет). Условные опе­рато­ры — сер­дце любого язы­ка прог­рамми­рова­ния. Поэто­му чрез­вычай­но важ­но уметь их пра­виль­но опре­делять.


В общем виде (не углубля­ясь в син­такси­чес­кие под­робнос­ти отдель­ных язы­ков) опе­ратор усло­вия схе­матич­но изоб­ража­ется так:


IF (усло­вие) THEN { опе­ратор1; опе­ратор2; } ELSE { опе­раторa; опе­раторb; }


За­дача ком­пилято­ра — пре­обра­зовать эту конс­трук­цию в пос­ледова­тель­ность машин­ных команд, выпол­няющих опе­ратор1, опе­ратор2, если усло­вие истинно, и опе­раторa, опе­раторb — если оно лож­но. Одна­ко мик­ропро­цес­соры серии 80x86 под­держи­вают весь­ма скром­ный набор условных команд, огра­ничен­ный фак­тичес­ки одни­ми условны­ми перехо­дами. Прог­раммис­там, зна­комым лишь с IBM PC, такое огра­ниче­ние не покажет­ся чем‑то неес­тес­твен­ным, меж­ду тем сущес­тву­ет мас­са про­цес­соров, под­держи­вающих пре­фикс условно­го выпол­нения инс­трук­ции. То есть вмес­то того, что­бы писать:


TEST ECX,ECX
JNZ xxx
MOV EAX,0x666

там пос­тупа­ют так:


TEST ECX,ECX
IFZ MOV EAX,0x666

IFZ и есть пре­фикс условно­го выпол­нения, раз­реша­ющий выпол­нение сле­дующей коман­ды толь­ко в том слу­чае, если уста­нов­лен флаг нуля. В этом смыс­ле мик­ропро­цес­соры 80x86 мож­но срав­нить с ран­ними диалек­тами язы­ка Basic, не раз­реша­ющи­ми исполь­зовать в условных выраже­ниях никакой дру­гой опе­ратор, кро­ме GOTO. Срав­ни:


Ста­рый диалект Basic:
10 IF A=B THEN GOTO 30
20 GOTO 40
30 PRINT "A=B"
40 ... // Прочий код программы

Но­вый диалект Basic:
IF A=B THEN PRINT "A=B"

Ес­ли ты ког­да‑нибудь прог­рамми­ровал на ста­рых диалек­тах Basic, то, веро­ятно, пом­нишь, что гораз­до выгод­нее выпол­нять GOTO, если усло­вие лож­но, а в про­тив­ном слу­чае про­дол­жать нор­маль­ное выпол­нение прог­раммы. Как видишь, воп­реки рас­хожему мне­нию, навыки прог­рамми­рова­ния на Basic отнюдь не бес­полез­ны, осо­бен­но в дизас­сем­бли­рова­нии прог­рамм.


Боль­шинс­тво ком­пилято­ров (даже не опти­мизи­рующих) инверти­руют истинность усло­вия, тран­сли­руя конс­трук­цию


IF (усло­вие) THEN { опе­ратор1; опе­ратор2; }


в сле­дующий псев­докод:



IF (NOT усло­вие) THEN continue
опе­ратор1;
опе­ратор2;
continue:



Сле­дова­тель­но, для вос­ста­нов­ления исходно­го тек­ста прог­раммы нам при­дет­ся вновь инверти­ровать усло­вие и «под­цепить» блок опе­рато­ров { опе­ратор1; опе­ратор2; } к клю­чево­му сло­ву THEN. Ина­че говоря, если откомпи­лиро­ван­ный код выг­лядит так:


10 IF A<>B THEN 30
20 PRINT "A=B"
30 ...// Прочий код программы

мож­но с уве­рен­ностью утвер­ждать, что в исходном тек­сте при­сутс­тво­вали стро­ки IF A=B THEN PRINT "A=B". А если прог­раммист, наобо­рот, про­верял перемен­ные A и B на неравенс­тво, то есть в коде при­сутс­тво­вала конс­трук­ция IF A<>B THEN PRINT "A<>B"? Все рав­но ком­пилятор инверти­рует истинность усло­вия и сге­нери­рует сле­дующий код:


10 IF A=B THEN 30
20 PRINT "A<>B"
30 ... // Прочий код программы

Ко­неч­но, встре­чают­ся и ком­пилято­ры, стра­дающие мно­гос­лови­ем. Их лег­ко рас­познать по безус­ловно­му перехо­ду, сле­дующе­му сра­зу же пос­ле условно­го опе­рато­ра:



IF (усло­вие) THEN do
GOTO continue
do:
опе­ратор1;
опе­ратор2;
continue:



В таком слу­чае инверти­ровать усло­вие не нуж­но. Впро­чем, если это сде­лать, ничего страш­ного не про­изой­дет, раз­ве что код прог­раммы ста­нет менее понят­ным, да и то не всег­да.


Рас­смот­рим теперь, как тран­сли­рует­ся пол­ная конс­трук­ция


IF (усло­вие) THEN { опе­ратор1; опе­ратор2; } ELSE { опе­раторa; опе­раторb; }.


Од­ни ком­пилято­ры пос­тупа­ют так:



IF (усло­вие) THEN do_it
// Вет­ка ELSE
опе­раторa;
опе­раторb;
GOTO continue
do_it:
//Вет­ка IF
опе­ратор1;
опе­ратор2;
continue:



А дру­гие — так:



IF (NOT усло­вие) THEN else
// Вет­ка IF
опе­ратор1;
опе­ратор2;
GOTO continue
else:
// Вет­ка ELSE
опе­раторa;
опе­раторb
continue:



Раз­ница меж­ду ними в том, что вто­рые инверти­руют истинность усло­вия, а пер­вые — нет. Поэто­му, не зная «нра­ва» ком­пилято­ра, опре­делить, как выг­лядел под­линный исходный текст прог­раммы, невоз­можно! Одна­ко это не соз­дает проб­лем, ибо усло­вие всег­да мож­но записать так, как это удоб­но. Допус­тим, не нра­вит­ся тебе вот такая конс­трук­ция:


IF (c <> 0) THEN a = b / c ELSE PRINT "Ошиб­ка!"


Пи­ши ее так:


IF (c == 0) THEN PRINT "Ошиб­ка!" ELSE a = b / c


И никаких гвоз­дей!


стра­нице авто­ра. Рань­ше мы уже встре­чались с условным ходом выпол­нения прог­рамм, одна­ко огра­ничи­вались корот­кими опи­сани­ями команд и повер­хностным раз­бором выпол­няемых ими опе­раций. Управля­емый ход выпол­нения, без сом­нения, самая важ­ная веха раз­вития прог­рамми­рова­ния сво­его вре­мени и зат­мева­ет мно­гие пос­леду­ющие, даже такие, как струк­турное прог­рамми­рова­ние или ООП. Толь­ко с высоты высоко­уров­невого язы­ка кажет­ся, что в усло­вии if — then — else нет ничего любопыт­ного и оно лишено какого‑либо раз­нооб­разия. Но для ком­пилято­ра это прос­тор для самоде­ятель­нос­ти! И в близ­ких по духу ситу­ациях он может пос­тро­ить кар­диналь­но раз­лича­ющий­ся код. В про­цес­сорной архи­тек­туре x86 пре­дус­мотрен весь­ма «ори­гиналь­ный» набор команд для перенап­равле­ния хода выпол­нения прог­рам­мно­го кода. «Ори­гиналь­ный» не зна­чит хороший или пло­хой, это зна­чит, что он отли­чает­ся от набора мик­ропро­цес­соров дру­гих архи­тек­тур и про­изво­дите­лей: ARM, MIPS, SPARC и так далее. Как ты зна­ешь, пер­вый про­цес­сор этой серии соз­давал­ся впо­пыхах для вре­мен­ной замены еще не готово­го iAPX-432, пос­ледний, в свою оче­редь, дол­жен был уметь в мно­гоза­дач­ность и управле­ние памятью на аппа­рат­ном уров­не. Чего в ито­ге не слу­чилось. А x86 про­дол­жил свое раз­витие. Поэто­му сей­час, ког­да за годы эво­люции про­цес­соров серии x86 ско­пил­ся набор инс­трук­ций, хакерам при­ходит­ся раз­гре­бать весь этот хлам, дабы рас­кру­тить порядок выпол­нения машин­ных инс­трук­ций. Идентификация условных операторов Су­щес­тву­ет два вида алго­рит­мов — безус­ловные и условные. Порядок дей­ствий безус­ловно­го алго­рит­ма всег­да пос­тоянен и не зависит от вход­ных дан­ных. Нап­ример, a = b c. Порядок дей­ствий условных алго­рит­мов, нап­ротив, зависит от дан­ных, пос­тупа­ющих «на вход». Нап­ример: ес­ли c не рав­но нулю, то: a = b/c; ина­че: вывес­ти сооб­щение об ошиб­ке Об­рати вни­мание на выделен­ные жир­ным шриф­том клю­чевые сло­ва «если», «то» и «ина­че», называ­емые опе­рато­рами усло­вия или условны­ми опе­рато­рами. Без них не обхо­дит­ся ни одна прог­рамма (вырож­денные при­меры наподо­бие «Hello, World!» не в счет). Условные опе­рато­ры — сер­дце любого язы­ка прог­рамми­рова­ния. Поэто­му чрез­вычай­но важ­но уметь их пра­виль­но опре­делять. В общем виде (не углубля­ясь в син­такси­чес­кие под­робнос­ти отдель­ных язы­ков) опе­ратор усло­вия схе­матич­но изоб­ража­ется так: IF (усло­вие) THEN _

Теги: CSS

Просмотров: 422
Комментариев: 0:   18-05-2022, 00:02
Уважаемый посетитель, Вы зашли на сайт как незарегистрированный пользователь. Мы рекомендуем Вам зарегистрироваться либо войти на сайт под своим именем.

 
Еще новости по теме:



Другие новости по теме: