По­мимо дизас­сем­бли­рова­ния, сущес­тву­ет и дру­гой спо­соб иссле­дова­ния прог­рамм — отладка. Изна­чаль­но под отладкой понима­лось пошаго­вое исполне­ние кода, так­же называ­емое трас­сиров­кой. Сегод­ня же прог­раммы рас­пухли нас­толь­ко, что трас­сировать их бес­смыс­ленно — мы момен­таль­но уто­нем в ому­те вло­жен­ных про­цедур, так и не поняв, что они, собс­твен­но, дела­ют. Отладчик не луч­шее средс­тво изу­чения алго­рит­ма прог­раммы — с этим эффектив­нее справ­ляет­ся инте­рак­тивный дизас­сем­блер (нап­ример, IDA).

«Фундаментальные основы хакерства»

Пе­ред тобой уже во вто­рой раз обновлен­ная вер­сия статьи «Зна­комс­тво с отладчи­ком» (пер­вое обновле­ние пуб­ликова­лось в 2018 году в рам­ках цик­ла «Фун­дамен­таль­ные осно­вы хакерс­тва»). В прош­лый раз текст Кри­са Кас­пер­ски был переде­лан для соот­ветс­твия новым вер­сиям Windows и Visual Studio, а теперь обновлен с уче­том отладки прог­рамм для 64-раз­рядной архи­тек­туры. Читай так­же обновлен­ную пер­вую статью серии. Обе статьи дос­тупны без плат­ной под­писки.

Цикл «Фун­дамен­таль­ные осно­вы хакерс­тва» с «апгрей­дом» пер­вых глав до x86-64 опуб­ликован в виде кни­ги, ку­пить ее ты можешь на сай­те изда­тель­ства «Солон‑пресс».

 

Способности отладчиков

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

  • от­сле­жива­ние обра­щений на запись, чте­ние и исполне­ние к задан­ной ячей­ке (реги­ону) памяти, далее по тек­сту име­нуемое бря­ком (брей­ком);
  • от­сле­жива­ние обра­щений на запись и чте­ние к пор­там вво­да‑вывода (уже неак­туаль­но для сов­ремен­ных опе­раци­онных сис­тем, зап­реща­ющих поль­зователь­ским при­ложе­ниям про­делы­вать такие трю­ки, — это теперь пре­рога­тива драй­веров, а на уров­не драй­веров реали­зова­ны очень нем­ногие защиты);
  • от­сле­жива­ние заг­рузки DLL и вызова из них таких‑то фун­кций, вклю­чая сис­темные ком­понен­ты (как мы уви­дим далее, это основное ору­жие сов­ремен­ного взлом­щика);
  • от­сле­жива­ние вызова прог­рам­мных и аппа­рат­ных пре­рыва­ний (боль­шей частью уже неак­туаль­но — не так мно­го защит балу­ется с пре­рыва­ниями);
  • от­сле­жива­ние сооб­щений, посыла­емых при­ложе­нием окну;
  • и, разуме­ется, кон­текс­тный поиск в памяти.

Как имен­но это дела­ет отладчик, пока знать необя­затель­но, дос­таточ­но знать, что он это уме­ет, и все. Куда акту­аль­нее воп­рос, какой отладчик уме­ет это делать.

 

Герои прошлого

В прош­лом в качес­тве отладчи­ка хакеры исполь­зовали широко извес­тный SoftICE. Это был дей­стви­тель­но мощ­ный инс­тру­мент, и даже по про­шес­твии мно­гих лет луч­ше него ничего не было изоб­ретено. Неос­поримым его пре­иму­щес­твом была воз­можность отладки ядра Windows с помощью одно­го компь­юте­ра. Меж­ду тем, не без дав­ления Microsoft, в 2006 году его раз­работ­ка была прек­ращена. А пос­коль­ку SoftICE очень силь­но зависел от опе­раци­онной сис­темы Windows, в более поз­дних ее вер­сиях он прос­то не работа­ет. Пос­ледней вер­сией Windows, в которой мож­но поль­зовать­ся SoftICE, была Windows XP SP 2. В SP 3 он уже не фун­кци­они­ровал, а в Vista и Windows 7 и подав­но.

SoftICE
SoftICE

Ха­керы, конеч­но, при­уны­ли, но не ста­ли посыпать голову пеп­лом, а начали изоб­ретать аль­тер­натив­ные отладчи­ки. Пос­ледова­ла эпо­ха рас­цве­та новых отладчи­ков. Но какая кар­тина на этом поле сей­час? Нет ни одно­го нового хороше­го отладчи­ка! Передо­вым сре­ди всех был ком­мерчес­кий Syser китай­ских раз­работ­чиков. Ему про­рочи­ли свет­лое будущее, воз­можность заменить SoftICE, но где он сей­час? Может быть, пара копий сох­ранилась где‑то на фай­ловых свал­ках, но он дав­но не раз­вива­ется.

Syser
Syser

Сей­час по боль­шому сче­ту у хакера есть выбор толь­ко из двух по‑нас­тояще­му год­ных отладчи­ков: WinDbg и x64dbg. Пос­ледний годит­ся лишь для иссле­дова­ния при­ложе­ний поль­зователь­ско­го режима, тог­да как с помощью WinDbg мож­но занимать­ся и ядер­ной отладкой Windows. Но в этом слу­чае при­дет­ся исполь­зовать два компь­юте­ра, объ­еди­нен­ных про­водом или по локаль­ной сети.

 

Современный инструмент кодокопателя

Ког­да‑то хакеры пре­неб­регали WinDbg, но со вре­менем он вырос и стал дей­стви­тель­но мощ­ным и полез­ным инс­тру­мен­том иссле­дова­ния кода. Не сто­ит забывать, что имен­но он исполь­зует­ся коман­дой раз­работ­ки Windows. Для него мож­но изго­тав­ливать рас­ширения путем под­клю­чаемых DLL. Начиная с Windows XP, дви­жок отладки вклю­чен непос­редс­твен­но в опе­раци­онную сис­тему. Он сос­тоит из двух DLL: dbgeng.dll и dbghelp.dll. Кро­ме непос­редс­твен­но средств отладки, в чис­ло которых вхо­дит сам WinDbg, его дви­жок исполь­зует­ся в том чис­ле «Док­тором Ват­соном» (drwtsn32.exe).

Средс­тво отладки для Windows сос­тоит из четырех при­ложе­ний, исполь­зующих dbgeng.dll:

  • cdb и ntsd — отладчи­ки поль­зователь­ско­го режима с кон­соль­ным интерфей­сом. Они раз­лича­ются толь­ко одним: при запус­ке из сущес­тву­юще­го кон­соль­ного окна ntsd откры­вает новое кон­соль­ное окно, a cdb это­го не дела­ет;
  • kd — отладчик режима ядра с кон­соль­ным интерфей­сом;
  • WinDbg может исполь­зовать­ся как отладчик поль­зователь­ско­го режима либо режима ядра, но не одновре­мен­но. У WinDbg есть гра­фичес­кий интерфейс.

Сле­дова­тель­но, WinDbg пред­став­ляет собой толь­ко обо­лоч­ку для отладки с помощью движ­ка.

Вспо­мога­тель­ный файл dbghelp.dll исполь­зует­ся внеш­ними тул­зами для иссле­дова­ния внут­реннос­тей Windows, нап­ример отладчи­ком OllyDbg, прог­раммой Process Explorer за авторс­твом Мар­ка Рус­синови­ча и про­чими.

У WinDbg есть две вер­сии: клас­сичес­кая и UWP. Пер­вая уста­нав­лива­ется вмес­те с набором тулз Debugging Tools for Windows. Этот набор содер­жит две вер­сии WinDbg. Одна пред­назна­чена для отладки 32-раз­рядных при­ложе­ний, дру­гая — 64-раз­рядных. Вер­сию UWP мож­но ска­чать из Windows Store, она име­ет толь­ко 32-бит­ную вер­сию. Обе 32-раз­рядные вер­сии абсо­лют­но рав­ноцен­ны, не счи­тая того, что в UWP прод­винутый поль­зователь­ский интерфейс Windows 10. Кста­ти, весь­ма удоб­ный при работе на боль­шом экра­не.

Для наших экспе­римен­тов я буду при­менять UWP-вер­сию. Раз­ницы в их исполь­зовании прак­тичес­ки нет, могут раз­ве что нем­ного раз­личать­ся коман­ды в поль­зователь­ском интерфей­се, имен­но над­писи на эле­мен­тах интерфей­са, но не коман­ды встро­енно­го язы­ка.

 

Способ 0. Бряк на оригинальный пароль

С помощью WinDbg заг­рузим лома­емый нами файл — passCompare1.exe — через пункт меню Launch Executable или Open Executable в клас­сичес­ком при­ложе­нии. В даль­нейшем я не буду при­водить ана­логи команд.

www

Фай­лы с при­мера­ми мож­но ска­чать с GitHub.

Сра­зу пос­ле откры­тия исполня­емо­го фай­ла WinDbg заг­рузит при­ложе­ние, в окне Disassembly отладчи­ка появят­ся дизас­сем­бли­рован­ные коман­ды, а в окне Command отоб­разят­ся резуль­таты их выпол­нения.

Пос­ле соз­дания окна при­ложе­ния еще до вывода каких‑либо дан­ных выпол­нение тут же пре­рыва­ется на инс­трук­ции int 3 — это прог­рам­мная точ­ка оста­нова. Час­то нович­ки счи­тают, что выпол­нение прог­раммы начина­ется с фун­кции main или WinMain. Это­му их учат в шко­ле, либо они сами чер­пают такие све­дения из учеб­ников по C/C++. Конеч­но, это неп­равда.

Преж­де чем попасть в фун­кцию main кон­крет­ного при­ложе­ния, про­цес­сор зарыва­ется в деб­ри сис­темно­го кода заг­рузчи­ка обра­зов, выпол­няет горы инс­трук­ций ини­циали­зации при­ложе­ния внут­ри Windows, под­клю­чения биб­лиотек и про­чего. Поэто­му про­изо­шед­ший бряк не озна­чает вход в main нашей прог­раммы. Если взгля­нуть в окош­ко дизас­сем­бле­ра, мы уви­дим, что пре­рыва­ние про­изош­ло в сис­темной фун­кции LdrpDoDebuggerBreak модуля ntdll.

Пер­вым делом заг­рузим отла­доч­ную информа­цию для ком­понен­тов опе­раци­онной сис­темы. Для это­го в коман­дную стро­ку вве­дем

.symfix d:\debugSymbols

Эта коман­да опре­деля­ет пап­ку, ука­зан­ную в парамет­ре, куда отладчик при необ­ходимос­ти заг­рузит отла­доч­ные сим­волы для под­систем Windows. Затем надо отпра­вить коман­ду для заг­рузки или обновле­ния фай­лов:

.reload

Пос­ле это­го WinDbg заг­рузит нуж­ные дан­ные с сер­веров Microsoft.

Кро­ме того, мож­но вос­поль­зовать­ся уже име­ющей­ся отла­доч­ной информа­цией, для это­го сущес­тву­ет коман­да .sympath+ <путь к директории>. Если файл с отла­доч­ными сим­волами находит­ся в одной пап­ке с исполня­емым фай­лом, он под­хва­тит­ся авто­мати­чес­ки. Еще мож­но исполь­зовать фай­лы исходно­го кода, но в таком слу­чае про­ще вос­поль­зовать­ся отладчи­ком, вхо­дящим в сре­ду раз­работ­ки.

Да­вай поп­робу­ем нат­равить отладчик на дебаж­ную вер­сию passCompare1 и при дос­тижении пер­вой точ­ки оста­нова пос­тавим бряк на фун­кцию main:

bp passCompare1!main

Те­перь про­дол­жим выпол­нение коман­дой g. Ког­да отладчик дос­тигнет пос­тавлен­ной точ­ки оста­нова (начало фун­кции main), в окне дизас­сем­бле­ра уви­дим, что лис­тинг раз­делен на сег­менты, в заголов­ке которых находят­ся име­на фун­кций, в час­тнос­ти main.

В релиз­ной вер­сии исполня­емо­го фай­ла это­го не будет. Если же мы пос­тавим точ­ку оста­нова по адре­су начала модуля и при­бавим адрес точ­ки вхо­да, то мы попадем не в начало фун­кции main, а в сис­темный заг­рузчик — фун­кцию mainCRTStartup, под­готов­ленную ком­пилято­ром.

Кро­ме Microsoft, мало кто пре­дос­тавля­ет отла­доч­ные сим­волы, не будем при­выкать к лег­кой жиз­ни, тем более WinDbg спе­циаль­но пред­назна­чен для отладки прог­рамм без отла­доч­ной информа­ции и исходно­го кода. Будем при­менять его по наз­начению! Меж­ду тем, если приг­лядеть­ся к окош­ку дизас­сем­бле­ра пов­ниматель­нее, мож­но заметить, что в отли­чие от дизас­сем­бле­ра dumpbin, который мы исполь­зовали в прош­лой статье, WinDbg рас­позна­ет име­на сис­темных фун­кций, чем сущес­твен­но упро­щает ана­лиз.

WinDbg распознает имена системных функций
WinDbg рас­позна­ет име­на сис­темных фун­кций

Точ­ки оста­нова могут быть двух типов: прог­рам­мные и аппа­рат­ные. С пер­выми мы уже встре­чались. В прог­рамме их может быть любое количес­тво. Для сво­ей работы они модифи­циру­ют память исполня­емо­го про­цес­са, то есть в том мес­те, где дол­жен сто­ять бряк, отладчик запоми­нает ассем­блер­ную инс­трук­цию и заменя­ет ее int 3. Из‑за того что прог­рам­мная точ­ка оста­нова изме­няет память, ее мож­но уста­новить не вез­де. В этом зак­люча­ется ее основной недос­таток. Глав­ной коман­дой для уста­нов­ки прог­рам­мной точ­ки оста­нова явля­ется bp. Для получе­ния спис­ка уста­нов­ленных точек слу­жит коман­да bl, а для уда­ления — коман­да bc, парамет­ром которой явля­ется индекс точ­ки оста­нова. Звез­дочка в качес­тве парамет­ра уда­ляет все бря­ки. Коман­ды be и bd, соот­ветс­твен­но, вклю­чают и вык­люча­ют брейк‑пой­нты.

Ко­личес­тво аппа­рат­ных точек оста­нова, незави­симо от раз­ряднос­ти про­цес­сора, всег­да четыре. Хотя в про­цес­соре при­сутс­тву­ют восемь регис­тров отладки (DR-0 — DR-7), толь­ко пер­вые четыре могут быть исполь­зованы для хра­нения адре­сов точек оста­нова. Аппа­рат­ные бря­ки могут ста­вить­ся в любое мес­то памяти про­цес­са. Таким обра­зом, они лишены недос­татка прог­рам­мных бря­ков. Осталь­ные регис­тры пред­назна­чены для хра­нения усло­вий дос­тупа — сра­баты­вания точек оста­нова, нап­ример чте­ние, запись, исполне­ние. Малое количес­тво — основной недос­таток аппа­рат­ных бря­ков. Для уста­нов­ки аппа­рат­ной точ­ки оста­нова исполь­зует­ся коман­да ba с тре­мя парамет­рами: тип дос­тупа, раз­мер и адрес.

Итак, мы рас­смот­рели неболь­шой спи­сок команд внут­ренне­го язы­ка отладчи­ка WinDbg. Навер­няка ты обра­тил вни­мание на их запись. В язы­ке отладчи­ка при­сутс­тву­ют три вида команд:

  • встро­енные коман­ды слу­жат для отладки про­цес­са и записы­вают­ся без лидиру­юще­го сим­вола, к таким коман­дам отно­сят­ся g, bp, bd;
  • ме­тако­ман­ды управля­ют работой отладчи­ка, перед ними ста­вит­ся сим­вол точ­ки, нап­ример: .reload, .symfix, .cls;
  • ко­ман­ды‑рас­ширения, заг­ружа­емые из внеш­них DLL, име­ют в начале сим­вол вос­кли­цатель­ного зна­ка, нап­ример: !heap, !dh.

Поиск адреса

Да­вай поп­робу­ем нас­коро най­ти защит­ный механизм и, не вни­кая в под­робнос­ти его фун­кци­они­рова­ния, нап­рочь отру­бить защиту. Вспом­ним, по какому адре­су рас­положен в памяти ори­гиналь­ный пароль. Заг­лянем в дамп сек­ции .rdata, где хра­нит­ся пароль. Исходный пароль myGOODpassword находит­ся по сме­щению 0x140002280. Поп­робу­ем вывес­ти находя­щиеся по это­му адре­су в памяти дан­ные:

dc 0x140002280

Су­щес­тву­ет боль­шое количес­тво команд для отоб­ражения содер­жимого памяти: da, db, dd и про­чие. Мы исполь­зовали dc, потому что она показы­вает зна­чения двой­ных слов и ASCII-сим­волы. Что мы видим? Неини­циали­зиро­ван­ные дан­ные.

Рань­ше (до Windows Vista) кодоко­пате­лям было про­ще. Windows заг­ружала обра­зы в вир­туаль­ную память по опре­делен­ному при ком­пиляции адре­су. В этом лег­ко убе­дить­ся: запус­тим при­ложе­ние в Windows XP, затем при помощи того же SoftICE узна­ем адре­са сек­ций (коман­да mod -u) и выпишем их. Пос­ле перезаг­рузки сис­темы и пов­торно­го запус­ка при­ложе­ния уви­дим, что они оста­нут­ся неиз­менны­ми.

На­чиная с Windows Vista, прог­раммы пос­ле переза­пус­ка сис­темы получа­ют слу­чай­ные адре­са, а не те, что опре­деле­ны при ком­пиляции. Поэто­му нам при­дет­ся самим искать сек­цию .rdata уже не на дис­ке, а в памяти. Лег­ко ска­зать, но сде­лать еще про­ще!

Най­дем, по какому адре­су рас­положен наш модуль в памяти. Для это­го в отладчи­ке вве­дем lmf m passcompare1. Вто­рой параметр — имя модуля, адрес которо­го надо опре­делить. В резуль­тате на сво­ем ком­пе я получил:

start end module name
00007ff7`159b0000 00007ff7`159b8000 passCompare1 passCompare1.exe

От­сюда сле­дует, что начало модуля находит­ся по адре­су 0x7ff7159b0000. Пос­ле каж­дой перезаг­рузки сис­темы модуль кон­крет­ного при­ложе­ния про­еци­рует­ся в раз­личные адре­са. Теперь выведем кар­ту памяти нашего модуля и получим све­дения обо всех сек­циях PE-фай­ла:

!dh passCompare1

Вы­вод коман­ды доволь­но объ­емный. !dh — в некото­ром роде ана­лог коман­ды map32 из SoftICE, при этом пер­вая пре­дос­тавля­ет боль­ше све­дений. Най­дем в выводе опи­сание целевой сек­ции .rdata:

SECTION HEADER #2
.rdata name
101C virtual size
2000 virtual address
1200 size of raw data
1400 file pointer to raw data
0 file pointer to relocation table
0 file pointer to line numbers
0 number of relocations
0 number of line numbers
40000040 flags
Initialized Data
(no align specified)
Read Only

Здесь нас инте­ресу­ет чет­вертая строч­ка — вир­туаль­ный адрес. Сле­дом мож­но най­ти, где в памяти рас­полага­ется .rdata, для это­го надо сло­жить началь­ный адрес модуля и вир­туаль­ный адрес сек­ции. Пос­мотрим, что там находит­ся:

dc 0x7ff7159b0000 + 2000

Уже теп­лее, чита­емые сим­волы. Прой­дем глуб­же в сек­цию и рас­печата­ем диапа­зон адре­сов:

dc 0x7ff7159b2000 0x7ff7159b2300

А вот и наш пароль по адре­су 0x7ff7159b2280! Дамп памяти про­цес­са:

00007ff7`159b2250 159b4040 00007ff7 159b40e0 00007ff7 @@.......@......
00007ff7`159b2260 ffffffff ffffffff ffffffff ffffffff ................
00007ff7`159b2270 65746e45 61702072 6f777373 003a6472 Enter password:.
00007ff7`159b2280 4f47796d 6170444f 6f777373 000a6472 myGOODpassword..
00007ff7`159b2290 6e6f7257 61702067 6f777373 000a6472 Wrong password..
00007ff7`159b22a0 73736150 64726f77 0a4b4f20 00000000 Password OK.....
00007ff7`159b22b0 00000140 00000000 00000000 00000000 @...............
Найденный адрес
Най­ден­ный адрес

Есть кон­такт! Задума­емся еще раз. Что­бы про­верить кор­рек­тность вве­ден­ного поль­зовате­лем пароля, защита, оче­вид­но, дол­жна срав­нить его с ори­гиналь­ным. А раз так, уста­новив точ­ку оста­нова на чте­нии памяти по адре­су 0x7ff7159b2280, мы пой­маем за хвост срав­нива­ющий механизм. Ска­зано — сде­лано.

Пос­тавим аппа­рат­ный бряк, он же бряк по дос­тупу (break on access), так как при прог­рам­мном будет ошиб­ка дос­тупа к памяти, воз­ника­ющая по при­чине попыт­ки записи в сек­цию, дос­тупную толь­ко для чте­ния, какой .rdata и явля­ется. А прог­рам­мно­му бря­ку надо модифи­циро­вать память.

ba r4 0x7ff7159b2280

Пер­вый параметр — тип дос­тупа: r — чте­ние; вто­рой параметр — количес­тво бай­тов, под­верга­емых опе­рации; пос­ледний параметр — адрес.

По коман­де g про­дол­жим отладку и вве­дем любой при­шед­ший на ум пароль, нап­ример KPNC++. Отладчик незамед­литель­но «всплы­вет» в биб­лиотеч­ной фун­кции срав­нения строк strcmp:

00007ffb`5d375670 488b01 mov rax, qword ptr [rcx]
00007ffb`5d375673 483b040a cmp rax, qword ptr [rdx+rcx]
00007ffb`5d375677 75bf jne ucrtbase!strcmp+0x8 (7ffb5d375638)
00007ffb`5d375679 4e8d0c10 lea r9, [rax+r10]
00007ffb`5d37567d 48f7d0 not rax

В силу архи­тек­турных осо­бен­ностей про­цес­соров Intel бряк сра­баты­вает пос­ле инс­трук­ции, выпол­нившей «попол­зно­вение», то есть RIP ука­зыва­ют на сле­дующую выпол­няемую коман­ду. В нашем слу­чае (выделен­ная стро­ка) — jne ucrtbase!strcmp+0x8, а к памяти, ста­ло быть, обра­тилась инс­трук­ция cmp rax, qword ptr [rdx+rcx]. А что находит­ся в RAX? Под­нима­ем взгляд еще стро­кой выше — mov rax, qword ptr [rcx]. Мож­но пред­положить, что RCX содер­жит ука­затель на стро­ку ори­гиналь­ного пароля (пос­коль­ку он выз­вал всплы­тие отладчи­ка), но не будем спе­шить с вывода­ми, в срав­нении еще при­сутс­тву­ет ука­затель [rdx+rcx]. Куда ука­зыва­ет он? Про­верить это в отладчи­ке про­ще прос­того. Сна­чала про­верим, куда ука­зыва­ет RCX:

0:000> dc rcx
00000093`bf5cfbd0 434e504b 000a2b2b 00000000 00000000 KPNC++..........

Ока­зыва­ется, RCX ука­зыва­ет на вве­ден­ный поль­зовате­лем пароль! А куда ука­зыва­ет вто­рой ука­затель?

0:000> dc [rdx+rcx]
00007ff7`159b2280 4f47796d 6170444f 6f777373 000a6472 myGOODpassword..

Здесь как раз при­таил­ся ори­гиналь­ный пароль! Кар­тина начина­ет при­обре­тать очер­тания.

Те­перь воп­рос: а как это заломить? Вот, ска­жем, JNE мож­но поменять на JE. Или еще ори­гиналь­нее — заменить RCX [RDX+RCX]. Тог­да ори­гиналь­ный пароль будет срав­нивать­ся сам с собой!

Вый­дем из текущей фун­кции, для это­го надо два раза нажать кноп­ку Step Out в отладчи­ке. В резуль­тате мы ока­жем­ся в фун­кции main, сра­зу пос­ле срав­нения строк:

0007ff7`159b10b2 488d15c7110000 lea rdx, [passCompare1!`string' (7ff7159b2280)]
00007ff7`159b10b9 488d4c2420 lea rcx, [buff{[0]} (rsp+20h)]
00007ff7`159b10be e88c0d0000 call passCompare1!strcmp (7ff7159b1e4f)
00007ff7`159b10c3 85c0 test eax, eax
00007ff7`159b10c5 7458 je passCompare1!main+0xaf (7ff7159b111f)

В пер­вой строч­ке при­веден­ного лис­тинга в регистр RDX записы­вает­ся ука­затель на эта­лон­ный пароль. Что­бы про­верить это, выпол­ни коман­ду dc 7ff7159b2280. Во вто­рой строч­ке в регистр RCX помеща­ется ука­затель на содер­жимое стро­ково­го буфера, в который записы­вает­ся вве­ден­ный поль­зовате­лем пароль. Пос­ле вызова strcmp сле­дует test, про­веря­ющий на ноль регистр EAX. Зна­комые мес­та! Пом­нишь, мы посеща­ли их дизас­сем­бле­ром? Далее сле­дует JE, совер­шающий пры­жок на осно­ве пре­дыду­щего усло­вия.

Ал­горитм дей­ствий преж­ний — запоми­наем адрес коман­ды TEST для пос­леду­ющей замены ее на XOR или записы­ваем пос­ледова­тель­ность бай­тов.

По­годи! Не сто­ит так спе­шить! Мож­но ли быть уве­рен­ным, что эти бай­тики по этим самым адре­сам будут находить­ся в исполня­емом фай­ле? В Windows XP и вер­сиях до нее на это в подав­ляющем боль­шинс­тве слу­чаев мож­но было хотя бы наде­ять­ся, но про­вер­ка не была лиш­ней. Хотя сис­темный заг­рузчик раз­мещал модули по заранее опре­делен­ным адре­сам, сущес­тво­вали хит­рые защит­ные механиз­мы, заг­ружав­шие один и тот же модуль по двум раз­ным адре­сам одновре­мен­но. В Windows 10 такой трюк не про­каты­вает, вин­да видит, что это один и тот же модуль, и раз­меща­ет его в памяти лишь еди­нож­ды.

Тем не менее в Windows 10 мы даже не можем наде­ять­ся, что находя­щиеся по опре­делен­ным адре­сам бай­ты, най­ден­ные в памяти с помощью отладчи­ка, будут по тем же адре­сам находить­ся в фай­ле на дис­ке. Ког­да прог­рамма выпол­няет­ся, все ее сек­ции про­еци­руют­ся в адресное прос­транс­тво вир­туаль­ной памяти, которое кар­диналь­но отли­чает­ся от началь­ной. В Vista и пос­леду­ющих сис­темах в дело всту­пает механизм ASLR (Address Space Layout Randomization), который, исполь­зуя MMU (Memory Management Unit), слу­чай­ным обра­зом изме­няет рас­положе­ние в адресном прос­транс­тве про­цес­са важ­ных струк­тур дан­ных. ASLR в некото­рых слу­чаях впол­не успешно борет­ся с перепол­нени­ем буфера, воз­вра­том в биб­лиоте­ку и дру­гими типами атак.

  • Подпишись на наc в Telegram!

    Только важные новости и лучшие статьи

    Подписаться

  • Подписаться
    Уведомить о
    2 комментариев
    Старые
    Новые Популярные
    Межтекстовые Отзывы
    Посмотреть все комментарии