<?xml version="1.0" encoding="utf-8" ?><rss version="2.0" xmlns:tt="http://teletype.in/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:media="http://search.yahoo.com/mrss/"><channel><title>Anon</title><generator>teletype.in</generator><description><![CDATA[https://t.me/anon_chan_by]]></description><image><url>https://teletype.in/files/a4/25/a4255b4b-a68e-479d-b143-c1c355e78160.jpeg</url><title>Anon</title><link>https://teletype.in/@anon_channel</link></image><link>https://teletype.in/@anon_channel?utm_source=teletype&amp;utm_medium=feed_rss&amp;utm_campaign=anon_channel</link><atom:link rel="self" type="application/rss+xml" href="https://teletype.in/rss/anon_channel?offset=0"></atom:link><atom:link rel="next" type="application/rss+xml" href="https://teletype.in/rss/anon_channel?offset=10"></atom:link><atom:link rel="search" type="application/opensearchdescription+xml" title="Teletype" href="https://teletype.in/opensearch.xml"></atom:link><pubDate>Tue, 26 May 2026 18:52:31 GMT</pubDate><lastBuildDate>Tue, 26 May 2026 18:52:31 GMT</lastBuildDate><item><guid isPermaLink="true">https://teletype.in/@anon_channel/R9RK4RTXPUl</guid><link>https://teletype.in/@anon_channel/R9RK4RTXPUl?utm_source=teletype&amp;utm_medium=feed_rss&amp;utm_campaign=anon_channel</link><comments>https://teletype.in/@anon_channel/R9RK4RTXPUl?utm_source=teletype&amp;utm_medium=feed_rss&amp;utm_campaign=anon_channel#comments</comments><dc:creator>anon_channel</dc:creator><title>Хакер - Фундаментальные основы хакерства. Ищем операнды при взломе программ</title><pubDate>Fri, 27 May 2022 10:15:11 GMT</pubDate><media:content medium="image" url="https://img1.teletype.in/files/c8/19/c819fd78-0eb7-4d88-8836-3d3579986ee4.png"></media:content><description><![CDATA[<img src="https://justpaste.it/img/66cb3df8384587c030595dcbdce431a8.png"></img>https://t.me/anon_chan_by]]></description><content:encoded><![CDATA[
  <figure id="6PkY" class="m_original">
    <img src="https://justpaste.it/img/66cb3df8384587c030595dcbdce431a8.png" width="1865" />
  </figure>
  <p id="OO7h"><a href="https://t.me/anon_chan_by" target="_blank">https://t.me/anon_chan_by</a></p>
  <p id="SQCb">Крис Касперски, Юрий Язев</p>
  <h3 id="JS2u">Содержание статьи</h3>
  <ul id="RXWT">
    <li id="p4FI">Идентификация констант и смещений</li>
    <li id="rLhl">Определение типа непосредственного операнда</li>
    <li id="gniX">Сложные случаи адресации или математические операции с указателями</li>
    <li id="8BHn">Порядок индексов и указателей</li>
    <li id="ISVl">Использование LEA для сложения констант</li>
    <li id="dqBJ">Заключение</li>
  </ul>
  <p id="hemJ">Ког­да мы занима­емся ана­лизом лома­емой прог­раммы, пыта­ясь вос­ста­новить алго­ритм ее работы, нам нуж­но опре­делить типы опе­ран­дов ассем­блер­ных инс­трук­ций. Для это­го есть нес­коль­ко прос­тых пра­вил. Меж­ду тем сре­ди опе­ран­дов при­сутс­тву­ют кон­стан­ты и сме­щения, которые внеш­не очень похожи, но в то же вре­мя силь­но раз­лича­ются по спо­собам и целям вза­имо­дей­ствия. Поэто­му важ­но отде­лить одно от дру­гого, так как такие «игры» — один из глав­ных инс­тру­мен­тов раз­работ­чиков защит.</p>
  <h4 id="gr2u">Фундаментальные основы хакерства</h4>
  <p id="V9Qe">Пят­надцать лет назад эпи­чес­кий труд Кри­са Кас­пер­ски «Фун­дамен­таль­ные осно­вы хакерс­тва» был нас­толь­ной кни­гой каж­дого начина­юще­го иссле­дова­теля в области компь­ютер­ной безопас­ности. Одна­ко вре­мя идет, и зна­ния, опуб­ликован­ные Кри­сом, теря­ют акту­аль­ность. Редак­торы «Хакера» попыта­лись обно­вить этот объ­емный труд и перенес­ти его из вре­мен Windows 2000 и Visual Studio 6.0 во вре­мена Windows 10 и Visual Studio 2019.</p>
  <p id="Fe4Q">Ссыл­ки на дру­гие статьи из это­го цик­ла ищи на <a href="https://justpaste.it/redirect/3rpi8/https://xakep.ru/author/yurembo/" target="_blank">стра­нице авто­ра</a>.</p>
  <h3 id="JaKh">ИДЕНТИФИКАЦИЯ КОНСТАНТ И СМЕЩЕНИЙ</h3>
  <p id="OsP0">Мик­ропро­цес­соры серии 80x86 под­держи­вают опе­ран­ды трех типов: регистр, непос­редс­твен­ное зна­чение, непос­редс­твен­ный ука­затель. Тип опе­ран­да явно зада­ется в спе­циаль­ном поле машин­ной инс­трук­ции, име­нуемом <code>mod</code>, поэто­му никаких проб­лем в иден­тифика­ции типов опе­ран­дов не воз­ника­ет. Регистр — ну, все мы зна­ем, как выг­лядят регис­тры; ука­затель по общепри­нято­му сог­лашению зак­люча­ется в квад­ратные скоб­ки, а непос­редс­твен­ное зна­чение записы­вает­ся без них. Нап­ример:</p>
  <p id="rDlk"><code>MOV ECX, EAX; ← регистровые операнды</code></p>
  <p id="Wm8E"><code>MOV ECX, 0x666; ← левый операнд регистровый, правый — непосредственный</code></p>
  <p id="97XW"><code>MOV [0x401020], EAX; ← левый операнд — указатель, правый — регистр</code></p>
  <p id="ln6Q">Кро­ме это­го, мик­ропро­цес­соры серии 80x86 под­держи­вают два вида адре­сации памяти: не­пос­редс­твен­ную и кос­венную. Тип адре­сации опре­деля­ется типом ука­зате­ля. Если опе­ранд — непос­редс­твен­ный ука­затель, то и адре­сация непос­редс­твен­на. Если же опе­ранд‑ука­затель — регистр, то такая адре­сация называ­ется кос­венной. Нап­ример:</p>
  <p id="5QBr"><code>MOV ECX,[0x401020] ← непосредственная адресация</code></p>
  <p id="EZag"><code>MOV ECX, [EAX] ← косвенная адресация</code></p>
  <p id="lYl9">Для ини­циали­зации регис­тро­вого ука­зате­ля раз­работ­чики мик­ропро­цес­сора вве­ли спе­циаль­ную коман­ду, вычис­ляющую зна­чение адресно­го выраже­ния <code>addr</code> и прис­ваивающую его регис­тру <code>REG</code>, — <code>LEA REG, [addr]</code>. Нап­ример:</p>
  <p id="2SkY"><code>LEA EAX, [0x401020] ; Регистру EAX присваивается значение указателя 0x401020</code></p>
  <p id="h7V0"><code>MOV ECX, [EAX] ; Косвенная адресация — загрузка в ECX двойного слова,</code></p>
  <p id="hDTT"><code>; расположенного по смещению 0x401020</code></p>
  <p id="fQPB">Пра­вый опе­ранд коман­ды <code>LEA</code> всег­да пред­став­ляет собой ближ­ний (near) ука­затель (исклю­чение сос­тавля­ют слу­чаи исполь­зования <code>LEA</code> для сло­жения кон­стант — под­робнее об этом см. в одно­имен­ном пун­кте). И все было бы хорошо... да вот, ока­зыва­ется, внут­реннее пред­став­ление ближ­него ука­зате­ля экви­вален­тно кон­стан­те того же зна­чения. Отсю­да <code>LEA EAX, [0x401020]</code> рав­носиль­но <code>MOV EAX, 0x401020</code>. В силу опре­делен­ных при­чин <code>MOV</code> зна­читель­но обог­нал в популяр­ности <code>LEA</code>, прак­тичес­ки вытес­нив пос­леднюю инс­трук­цию из упот­ребле­ния.</p>
  <p id="DhtV">От­каз от <code>LEA</code> породил фун­дамен­таль­ную проб­лему ассем­бли­рова­ния — проб­лему OFFSET’a. В общих чер­тах ее суть зак­люча­ется в син­такси­чес­кой нераз­личимос­ти кон­стант и сме­щений (ближ­них ука­зате­лей). Конс­трук­ция <code>MOV EAX, 0x401020</code> может гру­зить в <code>EAX</code> и кон­стан­ту, рав­ную <code>0x401020</code> (при­мер соот­ветс­тву­юще­го C-кода: <code>a=0x401020</code>), и ука­затель на ячей­ку памяти, рас­положен­ную по сме­щению <code>0x401020</code> (при­мер соот­ветс­тву­юще­го C-кода: <code>a=&amp;x</code>). Сог­ласись, <code>a=0x401020</code> сов­сем не одно и то же, что <code>a=&amp;x</code>! А теперь пред­ставь, что про­изой­дет, если в пов­торно ассем­бли­рован­ной прог­рамме перемен­ная <code>х</code> ока­жет­ся рас­положе­на по ино­му сме­щению, а не <code>0x401020</code>? Пра­виль­но — прог­рамма рух­нет, ибо ука­затель <code>a</code> по‑преж­нему ука­зыва­ет на ячей­ку памяти <code>0x401020</code>, но здесь теперь «про­жива­ет» сов­сем дру­гая перемен­ная!</p>
  <p id="2fGJ">По­чему перемен­ная может изме­нить свое сме­щение? Основных при­чин тому две. Во‑пер­вых, язык ассем­бле­ра неод­нозна­чен и допус­кает дво­якую интер­пре­тацию. Нап­ример, конс­трук­ции <code>ADD EAX, 0x66</code> соот­ветс­тву­ют две машин­ные инс­трук­ции: <code>83 C0 66</code> и <code>05 66 00 00 00</code> дли­ной три и пять байт соот­ветс­твен­но. Тран­сля­тор может выб­рать любую из них, и не факт, что ту же самую, которая была в исходной прог­рамме (до дизас­сем­бли­рова­ния). Невер­но «уга­дан­ный» раз­мер вызовет сме­щение всех осталь­ных инс­трук­ций, а вмес­те с ними и дан­ных. Во‑вто­рых, сме­щение не замед­лит выз­вать модифи­кацию прог­раммы (разуме­ется, речь идет не о замене <code>JZ</code> на <code>JNZ</code>, а о нас­тоящей адап­тации или модер­низации), и все ука­зате­ли тут же «посып­лются».</p>
  <p id="eE1M">Вер­нуть работос­пособ­ность прог­раммы помога­ет дирек­тива <code>offset</code>. Если <code>MOV EAX, 0x401020</code> дей­стви­тель­но заг­ружа­ет в <code>EAX</code> ука­затель, а не кон­стан­ту, по сме­щению <code>0x401020</code> сле­дует соз­дать мет­ку, име­нуемую, ска­жем, <code>loc_401020</code>. Так­же нуж­но <code>MOV EAX, 0x401020</code> заменить на <code>MOV EAX, offset loc_401020</code>. Теперь ука­затель <code>EAX</code> свя­зан не с фик­сирован­ным сме­щени­ем, а с мет­кой!</p>
  <p id="q8uP">А что про­изой­дет, если пред­варить дирек­тивой <code>offset</code> кон­стан­ту, оши­боч­но при­няв ее за ука­затель? Прог­рамма отка­жет или ста­нет работать некор­рек­тно. Допус­тим, чис­ло <code>0x401020</code> выража­ло собой объ­ем бас­сей­на, в который вода вте­кает через одну тру­бу, а вытека­ет через дру­гую. Если заменить кон­стан­ту ука­зате­лем, то объ­ем бас­сей­на ста­нет равен... сме­щению мет­ки в заново ассем­бли­рован­ной прог­рамме и все рас­четы полетят к чер­ту.</p>
  <p id="VbJ0">Та­ким обра­зом, очень важ­но опре­делить типы всех непос­редс­твен­ных опе­ран­дов, и еще важ­нее опре­делить их пра­виль­но. Одна ошиб­ка может сто­ить прог­рамме жиз­ни (в смыс­ле работос­пособ­ности), а в типич­ной прог­рамме тысячи и десят­ки тысяч опе­ран­дов!</p>
  <p id="mGRx">От­сюда воз­ника­ет два воп­роса:</p>
  <ul id="qcWP">
    <li id="ixqe">Как вооб­ще опре­деля­ют типы опе­ран­дов?</li>
    <li id="xt39">Мож­но ли их опре­делять авто­мати­чес­ки (или на худой конец хотя бы полу­авто­мати­чес­ки)?</li>
  </ul>
  <figure id="708F" class="m_original">
    <img src="https://justpaste.it/img/a0360b19c6735dd34595922370b6f49b.png" width="1419" />
  </figure>
  <h3 id="zpBO">Определение типа непосредственного операнда</h3>
  <p id="QRMl">Не­пос­редс­твен­ный опе­ранд коман­ды <code>LEA</code> всег­да ука­затель (исклю­чение сос­тавля­ют ассем­блер­ные «извра­щения»: что­бы сбить хакеров с тол­ку, в некото­рых защитах <code>LEA</code> исполь­зуют­ся для заг­рузки кон­стан­ты).</p>
  <p id="ajif">Не­пос­редс­твен­ные опе­ран­ды команд <code>MOV</code> и <code>PUSH</code> могут быть как кон­стан­тами, так и ука­зате­лями. Что­бы опре­делить тип непос­редс­твен­ного опе­ран­да, необ­ходимо про­ана­лизи­ровать, как исполь­зует­ся его зна­чение в прог­рамме. Для кос­венной адре­сации памяти — это ука­затель, в про­тив­ном слу­чае — кон­стан­та.</p>
  <p id="0a0p">Нап­ример, мы встре­тили в тек­сте прог­раммы коман­ду <code>MOV EAX, 0x401020</code>. Что это такое: кон­стан­та или ука­затель?</p>
  <figure id="ivzd" class="m_original">
    <img src="https://justpaste.it/img/07308ceb378c9148c4947fc2bf9e7549.png" width="1123" />
  </figure>
  <p id="ZSQN">От­вет на воп­рос дает стро­ка <code>MOV ECX, [EAX]</code>, под­ска­зыва­ющая, что зна­чение <code>0x401020</code> исполь­зует­ся для кос­венной адре­сации памяти. Сле­дова­тель­но, непос­редс­твен­ный опе­ранд не что иное, как ука­затель.</p>
  <p id="6JQn">Су­щес­тву­ет два типа ука­зате­лей — ука­зате­ли на дан­ные и ука­зате­ли на фун­кцию. Ука­зате­ли на дан­ные исполь­зуют­ся для извле­чения зна­чения ячей­ки памяти и встре­чают­ся в ариф­метичес­ких коман­дах и коман­дах пересыл­ки (нап­ример, <code>MOV</code>, <code>ADD</code>, <code>SUB</code>). Ука­зате­ли на фун­кцию исполь­зуют­ся в коман­дах кос­венно­го вызова и реже в коман­дах кос­венно­го перехо­да — <code>CALL</code> и <code>JMP</code> соот­ветс­твен­но.</p>
  <p id="fWE2">Сле­дующий при­мер (<code>const_pointers_cb</code>) откомпи­лируй с помощью C++Builder. В нем мы изу­чим раз­ницу меж­ду кон­стан­тами и ука­зате­лями:</p>
  <p id="ZI4j"><code>int _tmain(int argc, _TCHAR* argv[])</code></p>
  <p id="e7Xd"><code>{</code></p>
  <p id="5SSn"><code>static int a = 0x777;</code></p>
  <p id="oSjT"><code>int* b = &amp;a;</code></p>
  <p id="sxJv"><code>int c = b[0];</code></p>
  <p id="sEyu"><code>}</code></p>
  <p id="H6zO">Ре­зуль­тат ком­пиляции дол­жен выг­лядеть приб­лизитель­но так:</p>
  <p id="ccz8"><code>main proc near</code></p>
  <p id="0nNO"><code>var_1C = dword ptr -1Ch</code></p>
  <p id="tE5I"><code>var_18 = qword ptr -18h</code></p>
  <p id="apAd"><code>var_10 = qword ptr -10h</code></p>
  <p id="S1XO"><code>var_8 = dword ptr -8</code></p>
  <p id="3iYI"><code>var_4 = dword ptr -4</code></p>
  <p id="N9Yt"><code>; Открытие кадра стека</code></p>
  <p id="gpT6"><code>push rbp</code></p>
  <p id="tXkl"><code>; Выделение 0x20 байт для локальных переменных</code></p>
  <p id="QuN7"><code>sub rsp, 20h</code></p>
  <p id="pOY7"><code>; Кадр стека указывает на дно стека</code></p>
  <p id="UqKW"><code>lea rbp, [rsp+20h]</code></p>
  <p id="LzYK">Наз­вание сме­щения <code>unk_451110</code> говорит о том, что зна­чение по адре­су <code>451110</code> име­ет неоп­ределен­ный тип.</p>
  <p id="dHM7">Пе­рей­дем по нему и пос­мотрим, что там находит­ся.</p>
  <figure id="VnrP" class="m_original">
    <img src="https://justpaste.it/img/aa21115a912c0b1b31527a331c82a0fe.png" width="389" />
  </figure>
  <p id="w9hn">Так как чис­ло <code>0x777</code> не уме­щает­ся в одном бай­те, ком­пилятор раз­местил его в двух бай­тах. Сле­дова­тель­но, в <code>RAX</code> помеща­ется ссыл­ка на это чис­ло.</p>
  <p id="ENuX"><code>lea rax, unk_451110</code></p>
  <p id="Dd6P">Хо­тя IDA пред­ста­вила дан­ные прог­раммы так, как их при­гото­вил ком­пилятор, мы уже самос­тоятель­но опре­дели­ли, что по сме­щению <code>unk_451110</code> находит­ся чис­ло, занима­ющее боль­ше одно­го бай­та. Поэто­му мы можем помочь IDA пра­виль­но отоб­разить дан­ные. Для это­го, перей­дя по сме­щению, надо нажать кла­вишу с англий­ской o, что соот­ветс­тву­ет коман­де: Edit → Operand Type → Offset → Offset (data segment). В резуль­тате сме­щение будет пере­име­нова­но, а зна­чение, на которое оно ука­зыва­ет, при­мет бла­город­ный вид: <code>777h</code>. Кро­ме того, коман­да пре­обра­зова­ния неоп­ределен­ных бай­тов в дан­ные с <code>db</code> (один байт) изме­нит­ся на <code>dq</code> (восемь байт).</p>
  <figure id="oI7v" class="m_original">
    <img src="https://justpaste.it/img/26adfa3ef931098da6bc11bdfaa7e404.png" width="365" />
  </figure>
  <p id="mlh1">Ини­циали­зация локаль­ных перемен­ных:</p>
  <p id="ud25"><code>mov [rbp+var_4], 0</code></p>
  <p id="y1af"><code>mov [rbp+var_8], ecx</code></p>
  <p id="OYx5"><code>mov [rbp+var_10], rdx</code></p>
  <p id="PSga">В <code>RAX</code> рас­положе­на ссыл­ка на зна­чение, она копиру­ется в перемен­ную <code>var_18</code>. Пос­коль­ку зна­чение по ссыл­ке <code>unk_451110</code> находит­ся в сег­менте дан­ных, мож­но сде­лать вывод, что <code>var_18</code> — ста­тичес­кая перемен­ная.</p>
  <p id="gV7L"><code>mov [rbp+var_18], rax</code></p>
  <p id="AhbI">Ко­пиру­ем ссыл­ку на перемен­ную в памяти и таким обра­зом получа­ем воз­можность изме­нить ссыл­ку, но не зна­чение.</p>
  <p id="3kNY"><code>mov rax, [rbp+var_18]</code></p>
  <p id="6IcX">Заг­ружа­ем содер­жимое локаль­ной перемен­ной <code>var_18</code> в регистр <code>ECX</code>. Отсю­да мож­но сде­лать вывод, что в <code>RAX</code> все‑таки ука­затель. Тог­да локаль­ная перемен­ная <code>var_18</code> тоже ука­затель!</p>
  <p id="VymI"><code>mov ecx, [rax]</code></p>
  <p id="UaXF">Прис­ваиваем локаль­ной перемен­ной <code>var_1C</code> зна­чение, содер­жаще­еся в <code>ECX</code>. А там хра­нит­ся ука­затель на <code>0x777</code>.</p>
  <p id="xHjD"><code>mov [rbp+var_1C], ecx</code></p>
  <p id="FZXv"><code>mov [rbp+var_4], 0</code></p>
  <p id="WiU8"><code>; Функция возвращает ноль</code></p>
  <p id="SRX4"><code>mov eax, [rbp+var_4]</code></p>
  <p id="aaJ0"><code>; Очищаем стек</code></p>
  <p id="rYwA"><code>add rsp, 20h</code></p>
  <p id="pzvo"><code>; Закрываем кадр стека</code></p>
  <p id="m2rT"><code>pop rbp</code></p>
  <p id="dFkI"><code>retn</code></p>
  <p id="1WBM"><code>main endp</code></p>
  <p id="UcTD">Черт ногу сло­мит с эти­ми ука­зате­лями! Теперь рас­смот­рим при­мер <code>func_pointers_cb</code> с кос­венным вызовом фун­кции (так­же ском­пилиро­ван­ный с помощью C++Builder):</p>
  <p id="JBRG"><code>int func(int a, int b)</code></p>
  <p id="G5bQ"><code>{</code></p>
  <p id="msDy"><code>return a + b;</code></p>
  <p id="M6XG"><code>}</code></p>
  <p id="4xFp"><code>int _tmain(int argc, _TCHAR* argv[])</code></p>
  <p id="iLLX"><code>{</code></p>
  <p id="EZOP"><code>int (*zzz) (int a, int b) = func;</code></p>
  <p id="JEaK"><code>// Вызов функции происходит косвенно — по указателю zzz</code></p>
  <p id="W7e2"><code>zzz(0x666, 0x777);</code></p>
  <p id="pRUt"><code>return 0;</code></p>
  <p id="OEYW"><code>}</code></p>
  <p id="lO7k">Ре­зуль­тат ком­пиляции дол­жен выг­лядеть приб­лизитель­но так:</p>
  <p id="mAqU"><code>main proc near</code></p>
  <p id="OPaP"><code>var_1C = dword ptr -1Ch</code></p>
  <p id="ykpU"><code>var_18 = qword ptr -18h</code></p>
  <p id="7NHX"><code>var_10 = qword ptr -10h</code></p>
  <p id="JZsD"><code>var_8 = dword ptr -8</code></p>
  <p id="gNKq"><code>var_4 = dword ptr -4</code></p>
  <p id="TuDu"><code>; Открываем кадр стека</code></p>
  <p id="Ub3G"><code>push rbp</code></p>
  <p id="xp0w"><code>; Выделяем 0x40 под локальные переменные</code></p>
  <p id="eR8V"><code>sub rsp, 40h</code></p>
  <p id="PfLm"><code>; Указатель кадра стека</code></p>
  <p id="nEzD"><code>lea rbp, [rsp+40h]</code></p>
  <p id="uymU"><code>; В EAX заносим значение 0x666, пока непонятно для чего, но явно не для передачи</code></p>
  <p id="PA6M"><code>mov eax, 666h</code></p>
  <p id="rWAC"><code>; В R8D заносим значение 0x777</code></p>
  <p id="brpn"><code>mov r8d, 777h</code></p>
  <p id="tQr3"><code>; Смотри! В R9 заносим указатель на функцию</code></p>
  <p id="ARqc"><code>lea r9, func(int,int)</code></p>
  <p id="w2cJ"><code>; Инициализируем локальные переменные</code></p>
  <p id="Xjx2"><code>mov [rbp+var_4], 0</code></p>
  <p id="b3Yf"><code>mov [rbp+var_8], ecx</code></p>
  <p id="BJVU"><code>mov [rbp+var_10], rdx</code></p>
  <p id="9SDg"><code>; В var_18 помещаем указатель на функцию func</code></p>
  <p id="X0J4"><code>mov [rbp+var_18], r9</code></p>
  <p id="PlRF"><code>; Теперь ECX равна 0x666</code></p>
  <p id="TSRL"><code>mov ecx, eax</code></p>
  <p id="gCiv"><code>; а EDX — 0x777, регистры загружены и готовы для передачи параметров</code></p>
  <p id="B7Fl"><code>mov edx, r8d</code></p>
  <p id="64W2"><code>; Погляди-ка! Косвенный вызов функции!</code></p>
  <p id="iJXG"><code>call [rbp+var_18]</code></p>
  <p id="DLdk"><code>mov [rbp+var_4], 0</code></p>
  <p id="SNnl"><code>mov [rbp+var_1C], eax</code></p>
  <p id="urll"><code>mov eax, [rbp+var_4]</code></p>
  <p id="oDW4"><code>; Очищаем стек</code></p>
  <p id="Sx0S"><code>add rsp, 40h</code></p>
  <p id="qMQW"><code>; Восстанавливаем регистр</code></p>
  <p id="yKGB"><code>pop rbp</code></p>
  <p id="4QoP"><code>retn</code></p>
  <p id="VxpT"><code>main endp</code></p>
  <p id="TfJV">А вот и кос­венно вызыва­емая фун­кция <code>func</code>. Иссле­дуем ее, что­бы опре­делить тип переда­ваемых ей непос­редс­твен­ных зна­чений.</p>
  <p id="VIAB"><code>func(int, int) proc near</code></p>
  <p id="sERV"><code>var_C = dword ptr -0Ch</code></p>
  <p id="Yh5A"><code>var_8 = dword ptr -8</code></p>
  <p id="T0mt"><code>var_4 = dword ptr -4</code></p>
  <p id="C6rR">IDA не опре­дели­ла аргу­мен­ты, но мы‑то зна­ем, что они есть! Сей­час, ког­да парамет­ры всег­да переда­ются через регис­тры, раз­личие меж­ду аргу­мен­тами и локаль­ными перемен­ными — чис­тая фор­маль­ность.</p>
  <p id="JMca"><code>; Открываем кадр стека</code></p>
  <p id="lp8x"><code>push rbp</code></p>
  <p id="1zWF"><code>; Выделяем память для содержимого стека</code></p>
  <p id="3fQp"><code>sub rsp, 10h</code></p>
  <p id="zdei"><code>; Кадр стека указывает на дно стека</code></p>
  <p id="oLTW"><code>lea rbp, [rsp+10h]</code></p>
  <p id="A8CE">Прис­ваиваем зна­чение перемен­ной <code>var_4</code>, учи­тывая, что в регис­тре <code>ECX</code> переда­ется параметр, <code>var_4</code> — аргу­мент:</p>
  <p id="315O"><code>mov [rbp+var_4], ecx</code></p>
  <p id="tYKk">Прис­ваиваем зна­чение перемен­ной <code>var_8</code>, учи­тывая, что в регис­тре <code>EDX</code> переда­ется параметр, <code>var_8</code> — аргу­мент:</p>
  <p id="ltpi"><code>mov [rbp+var_8], edx</code></p>
  <p id="zprx"><code>; В ECX размещаем первое слагаемое</code></p>
  <p id="ZG38"><code>mov ecx, [rbp+var_4]</code></p>
  <p id="8jS7"><code>; Выполняем сложение с переменной, записывая сумму на место первого слагаемого</code></p>
  <p id="5xk0"><code>add ecx, [rbp+var_8]</code></p>
  <p id="7ldE"><code>; Значение суммы копируем в переменную var_C</code></p>
  <p id="nyY6"><code>mov [rbp+var_C], ecx</code></p>
  <p id="hYNd"><code>; В качестве результата возвращаем сумму</code></p>
  <p id="mAxI"><code>mov eax, [rbp+var_C]</code></p>
  <p id="UDnA"><code>; Удаляем содержимое стека</code></p>
  <p id="3tgu"><code>add rsp, 10h</code></p>
  <p id="gn9c"><code>; Закрываем кадр стека</code></p>
  <p id="mfJ2"><code>pop rbp</code></p>
  <p id="m6qM"><code>retn</code></p>
  <p id="cSCI"><code>func(int, int) endp</code></p>
  <h3 id="7HKf">Сложные случаи адресации или математические операции с указателями</h3>
  <p id="EWSb">C/C++ и некото­рые дру­гие язы­ки прог­рамми­рова­ния допус­кают выпол­нение над ука­зате­лями раз­личных ариф­метичес­ких опе­раций, чем серь­езно зат­рудня­ют иден­тифика­цию типов непос­редс­твен­ных опе­ран­дов. В самом деле, если бы такие опе­рации с ука­зате­лями были зап­рещены, то любая матема­тичес­кая инс­трук­ция, манипу­лиру­ющая с непос­редс­твен­ным опе­ран­дом, однознач­но ука­зыва­ла бы на его кон­стантный тип.</p>
  <p id="W1yt">К счастью, даже в тех язы­ках, где это раз­решено, над ука­зате­лями выпол­няет­ся огра­ничен­ное чис­ло матема­тичес­ких опе­раций. Так, совер­шенно бес­смыс­ленно сло­жение двух ука­зате­лей, а уж тем более умно­жение или деление их друг на дру­га. Вычита­ние — дело дру­гое. Исполь­зуя тот факт, что ком­пилятор рас­полага­ет фун­кции в памяти сог­ласно поряд­ку их объ­явле­ния в прог­рамме, мож­но вычис­лить раз­мер фун­кции, отни­мая ее ука­затель от ука­зате­ля на сле­дующую фун­кцию. Такой трюк встре­чает­ся в упа­ков­щиках (рас­паков­щиках) исполня­емых фай­лов, защитах с самомо­дифи­циру­ющим­ся кодом, но в прик­ладных прог­раммах исполь­зует­ся ред­ко.</p>
  <figure id="t3GZ" class="m_original">
    <img src="https://justpaste.it/img/8c004a1b15f5f8a8e9a4e7e5e5b96e4e.png" width="697" />
  </figure>
  <p id="tx2P">Ска­зан­ное выше отно­силось к слу­чаям «ука­затель + ука­затель». Меж­ду тем ука­затель может сочетать­ся и с кон­стан­той. При­чем такое сочета­ние нас­толь­ко популяр­но, что про­цес­соры серии 80x86 даже под­держи­вают для это­го спе­циаль­ную адре­сацию — <strong>ба­зовую</strong>. Пусть, к при­меру, име­ется ука­затель на мас­сив и индекс некото­рого эле­мен­та мас­сива. Оче­вид­но: что­бы получить зна­чение это­го эле­мен­та, необ­ходимо сло­жить ука­затель с индексом, умно­жен­ным на раз­мер эле­мен­та.</p>
  <p id="fqBm">Вы­чита­ние кон­стан­ты из ука­зате­ля встре­чает­ся гораз­до реже: это­му соот­ветс­тву­ет мень­ший круг задач, и сами прог­раммис­ты избе­гают вычита­ния, пос­коль­ку оно неред­ко при­водит к серь­езным проб­лемам. Сре­ди нович­ков популя­рен сле­дующий при­ем: если им тре­бует­ся мас­сив, начина­ющий­ся с еди­ницы, они, объ­явив обыч­ный мас­сив, получа­ют на него ука­затель и... умень­шают его на еди­ницу! Эле­ган­тно, не прав­да ли?</p>
  <p id="43uN">Но подумай, что про­изой­дет, если ука­затель на мас­сив будет равен нулю. Пра­виль­но, змея уку­сит свой хвост — ука­затель ста­нет очень боль­шим положи­тель­ным чис­лом. Вооб­ще‑то под Windows NT мас­сив гаран­тирован­но не может быть раз­мещен по нулево­му сме­щению, но не сто­ит при­выкать к трю­кам, при­вязан­ным к одной плат­форме и не работа­ющим на дру­гих.</p>
  <p id="tv7M">«Нор­маль­ные» язы­ки прог­рамми­рова­ния зап­реща­ют сме­шение типов, и пра­виль­но дела­ют. Сущес­тву­ет и еще одна фун­дамен­таль­ная проб­лема дизас­сем­бли­рова­ния — <strong>оп­ределе­ние типов в ком­биниро­ван­ных выраже­ниях</strong>. Рас­смот­рим сле­дующий при­мер:</p>
  <p id="pjRQ"><code>MOV EAX, 0x...</code></p>
  <p id="Q3D5"><code>MOV EBX, 0x...</code></p>
  <p id="BTAB"><code>ADD EAX, EBX</code></p>
  <p id="i8HO"><code>MOV ECX, [EAX]</code></p>
  <p id="BSW7">Сум­ма двух непос­редс­твен­ных зна­чений здесь исполь­зует­ся для кос­венной адре­сации. Ну, положим, оба они ука­зате­лями быть не могут, исхо­дя из самых общих сооб­ражений. Навер­няка одно из непос­редс­твен­ных зна­чений — ука­затель на мас­сив (струк­туру дан­ных, объ­ект), а дру­гое — индекс в этом мас­сиве. Для сох­ранения работос­пособ­ности прог­раммы ука­затель необ­ходимо заменить сме­щени­ем мет­ки, а вот индекс при­дет­ся оста­вить без изме­нений (ведь индекс — это кон­стан­та).</p>
  <p id="gNT2">Как же раз­личить, что есть что? Увы, нет уни­вер­саль­ного отве­та, а в кон­тек­сте при­веден­ного выше при­мера это и вов­се невоз­можно!</p>
  <p id="hOHt">Рас­смот­рим сле­дующий при­мер, демонс­три­рующий опре­деле­ние типов в ком­биниро­ван­ных выраже­ниях (<code>combined_exp_types</code>):</p>
  <p id="ZnCL"><code>void MyFunc(char* a, int i)</code></p>
  <p id="XDoH"><code>{</code></p>
  <p id="4U7u"><code>a[i] = &#x27;\n&#x27;;</code></p>
  <p id="i99h"><code>a[i + 1] = 0;</code></p>
  <p id="CaFe"><code>}</code></p>
  <p id="V5e9"><code>int main()</code></p>
  <p id="B9JS"><code>{</code></p>
  <p id="VWqe"><code>static char buff[] = &quot;Hello,Sailor!&quot;;</code></p>
  <p id="cz2y"><code>MyFunc(&amp;buff[0], 5);</code></p>
  <p id="kJbE"><code>}</code></p>
  <p id="8O0U">Ре­зуль­тат ком­пиляции с помощью Microsoft Visual C++ дол­жен выг­лядеть так:</p>
  <p id="Vx40"><code>main proc near</code></p>
  <p id="OlNZ"><code>; Выделение памяти для локальных переменных</code></p>
  <p id="21bv"><code>sub rsp, 28h</code></p>
  <p id="wWTi"><code>; Определяем смещение — указатель на элемент в массиве</code></p>
  <p id="GC1M"><code>mov eax, 1</code></p>
  <p id="9yS7"><code>imul rax, 0</code></p>
  <p id="Xz6m"><code>; В регистр RCX загружаем указатель на строку</code></p>
  <p id="517i"><code>lea rcx, buff ; &quot;Hello, Sailor!&quot;</code></p>
  <p id="N1n5"><code>add rcx, rax</code></p>
  <p id="5H95"><code>; Указатель на строку копируется в RAX</code></p>
  <p id="GzgN"><code>mov rax, rcx</code></p>
  <p id="lC35"><code>; Подготовка параметров:</code></p>
  <p id="djJT"><code>; в регистр EDX помещается число 5 — второй параметр</code></p>
  <p id="JEPy"><code>mov edx, 5 ; i</code></p>
  <p id="5zY7"><code>; указатель на строку вновь копируется в RCX — первый параметр</code></p>
  <p id="0Lsv"><code>mov rcx, rax ; a</code></p>
  <p id="4Kvg"><code>; Параметры укомплектованы — вызываем функцию</code></p>
  <p id="Gfy0"><code>call MyFunc(char *,int)</code></p>
  <p id="UEpH"><code>; Функция возвращает ноль</code></p>
  <p id="2jLP"><code>xor eax, eax</code></p>
  <p id="m0wI"><code>; Очистка стека</code></p>
  <p id="4FGP"><code>add rsp, 28h</code></p>
  <p id="RHdD"><code>retn</code></p>
  <p id="2nFr"><code>main endp</code></p>
  <p id="idKD">Мы можем с пол­ной уве­рен­ностью ска­зать, где какой параметр, толь­ко в наших искусс­твен­ных при­мерах. При изу­чении чужих прог­раммок такой уве­рен­ности, к сожале­нию, не будет. Поэто­му, рас­смат­ривая парамет­ры в фун­кции ниже, мы, по идее, дол­жны видеть их как два чис­ловых аргу­мен­та. И наша задача разоб­рать­ся, пред­став­ляют ли они кон­стан­ты или ука­зате­ли.</p>
  <p id="F4Pf"><code>void MyFunc(char *, int) proc near</code></p>
  <p id="JFfI"><code>; Два параметра — все верно</code></p>
  <p id="li3H"><code>arg_0 = qword ptr 8</code></p>
  <p id="uMlH"><code>arg_8 = dword ptr 10h</code></p>
  <p id="o8jx"><code>; Перенос значений параметров из регистров в память</code></p>
  <p id="WEmX"><code>mov [rsp+arg_8], edx ; Число 5</code></p>
  <p id="FmwQ"><code>mov [rsp+arg_0], rcx ; Указатель на строку</code></p>
  <p id="Qbiu"><code>; Копирование двойного слова со знаком в четверное</code></p>
  <p id="duhF"><code>movsxd rax, [rsp+arg_8]</code></p>
  <p id="EhNR"><code>; Копирование четверного слова в четверное</code></p>
  <p id="haK6"><code>mov rcx, [rsp+arg_0]</code></p>
  <p id="8ucx">Сум­ма непос­редс­твен­ных зна­чений исполь­зует­ся для кос­венной адре­сации памяти, зна­чит, это кон­стан­та и ука­затель. Но кто есть кто?</p>
  <p id="WpKo"><code>mov byte ptr [rcx+rax], 0Ah</code></p>
  <p id="Y64f">Для отве­та на этот воп­рос нам необ­ходимо понять смысл кода прог­раммы — чего же добивал­ся прог­раммист сло­жени­ем ука­зате­лей? Пред­положим, что зна­чение 5 — ука­затель. Логич­но? Да вот не очень‑то логич­но: если это ука­затель, то ука­затель на что?</p>
  <p id="1zFi">Пер­вые 64 килобай­та адресно­го прос­транс­тва Windows NT заб­локиро­ваны для «отлавли­вания» нулевых и неини­циали­зиро­ван­ных ука­зате­лей. Ясно, что рав­ным пяти ука­затель быть никак не может, раз­ве что прог­раммист исполь­зовал какой‑нибудь очень извра­щен­ный трюк. А если ука­затель <code>0x140003038</code> (фак­тичес­кий адрес <code>buff</code>)? Выг­лядит прав­доподоб­ным легаль­ным сме­щени­ем...</p>
  <p id="CMhh">Кста­ти, что там у нас рас­положе­но? Секун­дочку...</p>
  <p id="7jFp"><code>.data:0000000140003038 buff db &#x27;Hello, Sailor!&#x27;,0</code></p>
  <p id="0lYq">Те­перь все схо­дит­ся — фун­кции передан ука­затель на стро­ку &quot;Hello, Sailor!&quot; (зна­чение <code>0x140003038</code>) и индекс сим­вола этой стро­ки (зна­чение 5). Фун­кция сло­жила ука­затель со стро­кой и записа­ла в получен­ную ячей­ку сим­вол &quot;\n&quot;.</p>
  <p id="g0sL">Сле­дующая инс­трук­ция заносит зна­чение аргу­мен­та <code>arg_8</code> в регистр <code>EAX</code>. Как мы уста­нови­ли, это кон­стан­та:</p>
  <p id="Hi0G"><code>mov eax, [rsp+arg_8]</code></p>
  <p id="5JGt"><code>; Инкрементируем значение в EAX на 1</code></p>
  <p id="Gvmy"><code>inc eax</code></p>
  <p id="HZ45"><code>; Преобразуем двойное слово (значение в EAX) в четверное слово (значение в RAX)</code></p>
  <p id="4721"><code>cdqe</code></p>
  <p id="wTKr"><code>; Помещаем в RCX значение аргумента arg_0</code></p>
  <p id="3gZ4"><code>; Как мы выяснили, оно представляет собой указатель на строку</code></p>
  <p id="OJfH"><code>mov rcx, [rsp+arg_0]</code></p>
  <p id="DI4Z">Сум­ма <code>RCX</code> и <code>RAX</code> исполь­зует­ся для кос­венной адре­сации памяти, точ­нее кос­венно‑базовой, так как к ука­зате­лю при­бав­ляет­ся еще и еди­ница. В эту ячей­ку памяти заносит­ся ноль. Дру­гими сло­вами, мы про­писы­ваем ноль за сим­волом &quot;\n&quot;.</p>
  <p id="bFdk"><code>mov byte ptr [rcx+rax], 0</code></p>
  <p id="vmtj"><code>retn</code></p>
  <p id="F2IA"><code>void MyFunc(char *, int) endp</code></p>
  <p id="fRIf">На­ши пред­положе­ния под­твер­дились — фун­кции переда­ются ука­затель на стро­ку и индекс пер­вого «отсе­каемо­го» сим­вола стро­ки. А теперь ском­пилиру­ем тот же самый при­мер ком­пилято­ром Embarcadero C++Builder и срав­ним, чем он отли­чает­ся от Microsoft Visual C++:</p>
  <p id="fqPU"><code>; int __cdecl main(int argc, const char **argv, const char **envp)</code></p>
  <p id="z2pw"><code>public main</code></p>
  <p id="hwbg"><code>main proc near ; DATA XREF: __acrtused+29↑o</code></p>
  <p id="TI2V"><code>var_10 = qword ptr -10h</code></p>
  <p id="ZuoH"><code>var_8 = dword ptr -8</code></p>
  <p id="cCWk"><code>var_4 = dword ptr -4</code></p>
  <p id="9BWS"><code>; Открытие кадра стека</code></p>
  <p id="SeLY"><code>push rbp</code></p>
  <p id="SRgF"><code>; Выделение 0х30 байт памяти для локальных переменных</code></p>
  <p id="NPBx"><code>sub rsp, 30h</code></p>
  <p id="LAD0"><code>; Копирование в RBP указателя на дно стека, ибо после вычитания получилась вершина,</code></p>
  <p id="Qqsx"><code>; а после сложения — дно</code></p>
  <p id="wAXI"><code>lea rbp, [rsp+30h]</code></p>
  <p id="2RvX"><code>; В RAX — указатель на строку</code></p>
  <p id="zuZb"><code>lea rax, aHelloSailor ; &quot;Hello, Sailor!&quot;</code></p>
  <p id="RVqn"><code>; В R8D — значение 5</code></p>
  <p id="dxFN"><code>mov r8d, 5</code></p>
  <p id="ORSZ"><code>; Инициализация локальных переменных...</code></p>
  <p id="RPg0"><code>mov [rbp+var_4], 0</code></p>
  <p id="FXE3"><code>; ...перебрасываем содержимое регистров в память</code></p>
  <p id="sWGf"><code>mov [rbp+var_8], ecx</code></p>
  <p id="YqG8"><code>mov [rbp+var_10], rdx</code></p>
  <p id="1AjV"><code>; Готовим параметры для передачи:</code></p>
  <p id="znGG"><code>; в RCX копируем указатель на строку...</code></p>
  <p id="GEdI"><code>mov rcx, rax</code></p>
  <p id="CSjT"><code>; ...в EDX — значение 5</code></p>
  <p id="A2dQ"><code>mov edx, r8d</code></p>
  <p id="yz59"><code>; Вызов функции вместе с передачей параметров</code></p>
  <p id="8YKn"><code>call MyFunc(char *,int)</code></p>
  <p id="H1Qi"><code>mov [rbp+var_4], 0</code></p>
  <p id="MPZy"><code>; Обнуляем EAX для возвращения нуля</code></p>
  <p id="urPN"><code>mov eax, [rbp+var_4]</code></p>
  <p id="f1RQ"><code>; Очищаем стек</code></p>
  <p id="tBZJ"><code>add rsp, 30h</code></p>
  <p id="4rgX"><code>; Закрываем кадр стека</code></p>
  <p id="0lXa"><code>pop rbp</code></p>
  <p id="u0Lp"><code>retn</code></p>
  <p id="xZ3B"><code>main endp</code></p>
  <p id="uFkL"><code>; __int64 __fastcall MyFunc(char *, int)</code></p>
  <p id="6ODS"><code>public MyFunc(char *, int)</code></p>
  <p id="11vl"><code>MyFunc(char *, int) proc near ; CODE XREF: main+2B↓p</code></p>
  <p id="wxcZ"><code>var_C = dword ptr -0Ch</code></p>
  <p id="nU8F"><code>var_8 = qword ptr -8</code></p>
  <p id="Fviu"><code>; Открытие кадра стека</code></p>
  <p id="XAwM"><code>push rbp</code></p>
  <p id="LcSL"><code>; Выделение памяти</code></p>
  <p id="aEmi"><code>sub rsp, 10h</code></p>
  <p id="ylrT"><code>; Указатель кадра стека</code></p>
  <p id="yOoz"><code>lea rbp, [rsp+10h]</code></p>
  <p id="Fl4V"><code>; Принятые параметры размещаем в локальных переменных</code></p>
  <p id="nopx"><code>mov [rbp+var_8], rcx</code></p>
  <p id="HYvK"><code>mov [rbp+var_C], edx</code></p>
  <p id="jh95"><code>; Первый параметр возвращаем в RCX</code></p>
  <p id="nCwT"><code>mov rcx, [rbp+var_8]</code></p>
  <p id="UVEz"><code>; Копирование двойного слова со знаком в четверное</code></p>
  <p id="1euT"><code>movsxd rax, [rbp+var_C]</code></p>
  <p id="wXce">Сум­ма непос­редс­твен­ных зна­чений исполь­зует­ся для кос­венной адре­сации памяти. Этот при­ем мы уже про­ходи­ли, раз­бирая дизас­сем­блер­ный лис­тинг от Visual C++. Одна­ко воп­рос все тот же: как понять, где кон­стан­та, а где ука­затель? Как и в пре­дыду­щем слу­чае, необ­ходимо про­ана­лизи­ровать их зна­чения.</p>
  <p id="cPIm"><code>mov byte ptr [rcx+rax], 0Ah</code></p>
  <p id="9CFv"><code>; Копирование значений из локальных переменных в регистры</code></p>
  <p id="vgGs"><code>mov rax, [rbp+var_8]</code></p>
  <p id="5Hwn"><code>mov edx, [rbp+var_C]</code></p>
  <p id="86hr"><code>; Увеличение var_C на 1, а Visual C++ в этом месте использовал инструкцию inc</code></p>
  <p id="ctJR"><code>add edx, 1</code></p>
  <p id="xoIe"><code>; Копирование двойного слова со знаком в четверное</code></p>
  <p id="zKAa"><code>movsxd rcx, edx</code></p>
  <p id="DbVN"><code>; Снова косвенная адресация памяти, чтобы поставить после символа новой строки &quot;\n&quot; 0</code></p>
  <p id="phRk"><code>mov byte ptr [rax+rcx], 0</code></p>
  <p id="7pqF"><code>; Восстановление стека</code></p>
  <p id="PtNd"><code>add rsp, 10h</code></p>
  <p id="MWYq"><code>; Закрытие кадра стека</code></p>
  <p id="kcJm"><code>pop rbp</code></p>
  <p id="PANa"><code>retn</code></p>
  <p id="5TTI"><code>MyFunc(char *, int) endp</code></p>
  <p id="JQrr">По срав­нению с лис­тингом от Visual C++ лис­тинг от C++Builder име­ет минималь­ные раз­личия. Рань­ше было не так... Даже не знаю, радовать­ся это­му или огор­чать­ся.</p>
  <h3 id="vpjl">Порядок индексов и указателей</h3>
  <p id="IK4g">От­крою малень­кий сек­рет: при сло­жении ука­зате­ля с кон­стан­той боль­шинс­тво ком­пилято­ров на пер­вое мес­то помеща­ют ука­затель, а на вто­рое — кон­стан­ту, каким бы ни было их рас­положе­ние в исходной прог­рамме. Ина­че говоря, выраже­ния <code>a[i]</code>, <code>(a+i)[0]</code>, <code>*(a+i)</code> и <code>*(i+a)</code> ком­пилиру­ются в один и тот же код! Даже если извра­тить­ся и написать так: <code>(0)[i+a]</code>, ком­пилятор все рав­но выд­винет <code>a</code> на пер­вое мес­то. Что это — осли­ное упрямс­тво, игра слу­чая или фича? Ответ до смеш­ного прост — сло­жение ука­зате­ля с кон­стан­той дает ука­затель! Поэто­му резуль­тат вычис­лений всег­да записы­вает­ся в перемен­ную типа «ука­затель».</p>
  <p id="iMLN">Вер­немся к пос­ледне­му рас­смот­ренно­му при­меру (<code>combined_exp_types_cb</code>), при­менив для ана­лиза наше новое пра­вило:</p>
  <p id="DG2B"><code>; Копирование значений из локальных переменных в регистры</code></p>
  <p id="42LF"><code>mov rax, [rbp+var_8] ; В RAX теперь указатель на строку</code></p>
  <p id="Ltu3"><code>mov edx, [rbp+var_C]</code></p>
  <p id="Qg2q"><code>; Увеличение var_C на 1, а там (следовательно, теперь в регистре) значение 5</code></p>
  <p id="2c5x"><code>add edx, 1</code></p>
  <p id="rqPX"><code>; Копирование двойного слова со знаком в четверное</code></p>
  <p id="3Lnq"><code>movsxd rcx, edx ; теперь значение 6 в RCX</code></p>
  <p id="I9yt">Сло­жение RAX и RCX. Опе­рация сло­жения ука­зыва­ет на то, что по край­ней мере один из них кон­стан­та, а дру­гой — либо кон­стан­та, либо ука­затель.</p>
  <p id="vUmg"><code>mov byte ptr [rax+rcx], 0</code></p>
  <p id="Vhm8">Ага! Сум­ма непос­редс­твен­ных зна­чений исполь­зует­ся для кос­венной адре­сации памяти, зна­чит, это кон­стан­та и ука­затель. Но кто из них кто? С боль­шой сте­пенью веро­ятности <code>RAX</code> — ука­затель (так оно и есть), пос­коль­ку он сто­ит на пер­вом мес­те, а <code>RCX</code> — индекс, так как он сто­ит на вто­ром!</p>
  <h3 id="Y25A">Использование LEA для сложения констант</h3>
  <p id="in6V">Инс­трук­ция <code>LEA</code> широко исполь­зует­ся ком­пилято­рами не толь­ко для ини­циали­зации ука­зате­лей, но и для сло­жения кон­стант. Пос­коль­ку внут­ренне пред­став­ление кон­стант и ука­зате­лей иден­тично, резуль­тат сло­жения двух ука­зате­лей иден­тичен сум­ме тож­дес­твен­ных им кон­стант. То есть <code>LEA EBX, [EBX+0x666] == ADD EBX, 0x666</code>, одна­ко по сво­им фун­кци­ональ­ным воз­можнос­тям <code>LEA</code> зна­читель­но обго­няет <code>ADD</code>. Вот, нап­ример, <code>LEA ESI, [EAX*4+EBP-0x20]</code>, поп­робуй то же самое «скор­мить» инс­трук­ции <code>ADD</code>!</p>
  <p id="Cj55">Встре­тив в тек­сте прог­раммы коман­ду <code>LEA</code>, не торопись навеши­вать на воз­вра­щен­ное ею зна­чение ярлык «ука­затель»: с не мень­шим успе­хом он может ока­зать­ся и кон­стан­той! Если «подоз­рева­емый» ни разу не исполь­зует­ся в выраже­нии кос­венной адре­сации — никакой это не ука­затель, а самая нас­тоящая кон­стан­та!</p>
  <h4 id="K8vt">«Визуальная» идентификация констант и указателей</h4>
  <p id="UPoU">Вот нес­коль­ко при­емов, помога­ющих отли­чить ука­зате­ли от кон­стант.</p>
  <ol id="lvVi">
    <li id="bH81">В 64-раз­рядных Windows-прог­раммах ука­зате­ли могут при­нимать огра­ничен­ный диапа­зон зна­чений. Дос­тупный про­цес­сорам реги­он адресно­го прос­транс­тва начина­ется со сме­щения</li>
    <li id="QL86"><code>0x00000000 00010000</code> и прос­тира­ется до сме­щения <code>0x000003FF FFFFFFFF</code>. Поэто­му все непос­редс­твен­ные зна­чения, мень­шие <code>0x00000000 00010000</code> и боль­шие <code>0x000003FF FFFFFFFF</code>, пред­став­ляют собой кон­стан­ты, а не ука­зате­ли. Исклю­чение сос­тавля­ет чис­ло ноль, обоз­нача­ющее нулевой ука­затель. Некото­рые защит­ные механиз­мы непос­редс­твен­но обра­щают­ся к коду опе­раци­онной сис­темы, рас­положен­ному выше адре­са <code>0x000003FF FFFFFFFF</code>, где начина­ются вла­дения ядра.</li>
    <li id="T0aI">Ес­ли непос­редс­твен­ное зна­чение сма­хива­ет на ука­затель, пос­мотри, на что он ука­зыва­ет. Если по дан­ному сме­щению находит­ся про­лог фун­кции или осмыслен­ная тек­сто­вая стро­ка, ско­рее все­го, мы име­ем дело с ука­зате­лем, хотя, может быть, это все­го лишь сов­падение.</li>
    <li id="FQWv">Заг­ляни в таб­лицу переме­щаемых эле­мен­тов. Если адрес «под­следс­твен­ного» непос­редс­твен­ного зна­чения есть в таб­лице, это, несом­ненно, ука­затель. Беда в том, что боль­шинс­тво исполня­емых фай­лов непере­меща­емы и такой при­ем акту­ален лишь для иссле­дова­ния DLL (а DLL переме­щаемы по опре­деле­нию).</li>
  </ol>
  <p id="fR0w">К сло­ву ска­зать, дизас­сем­блер IDA Pro исполь­зует все три опи­сан­ных спо­соба для авто­мати­чес­кого опоз­навания ука­зате­лей.</p>
  <h3 id="tVDx">ЗАКЛЮЧЕНИЕ</h3>
  <p id="ScPZ">Как мы уви­дели выше, пра­виль­ное опре­деле­ние кон­стант и сме­щений зависит от мно­гих фун­дамен­таль­ных фак­торов: от опе­раци­онной сис­темы, ее раз­ряднос­ти, даже от язы­ка ассем­бле­ра, в котором отра­жает­ся про­цес­сорная архи­тек­тура! Эти понятия сос­тавля­ют осно­ву любой прог­раммы. А рас­смот­ренные в статье при­меры показа­ли важ­ность их пра­виль­ной иден­тифика­ции.</p>
  <p id="Gh1f"><a href="https://t.me/anon_chan_by" target="_blank">https://t.me/anon_chan_by</a></p>

]]></content:encoded></item><item><guid isPermaLink="true">https://teletype.in/@anon_channel/dUcRnBL6CCV</guid><link>https://teletype.in/@anon_channel/dUcRnBL6CCV?utm_source=teletype&amp;utm_medium=feed_rss&amp;utm_campaign=anon_channel</link><comments>https://teletype.in/@anon_channel/dUcRnBL6CCV?utm_source=teletype&amp;utm_medium=feed_rss&amp;utm_campaign=anon_channel#comments</comments><dc:creator>anon_channel</dc:creator><title>Linux за 30 минут. Руководство по выбору и использованию Linux для новичков</title><pubDate>Sun, 21 Nov 2021 11:39:43 GMT</pubDate><media:content medium="image" url="https://img3.teletype.in/files/6b/a2/6ba2416b-a266-4bf2-8e4d-e799dbffdbc1.png"></media:content><description><![CDATA[<img src="https://justpaste.it/img/1af081b890d7ca802ee917e5b53fe048.png"></img>Содержание статьи]]></description><content:encoded><![CDATA[
  <h3 id="5Rv6"><a href="https://t.me/anon_chan_by" target="_blank">t.me/anon_chan_by</a></h3>
  <p id="rRqN">Содержание статьи</p>
  <ul id="3FMe">
    <li id="8gyp">Какой бывает Linux</li>
    <li id="AhxF">Ядро</li>
    <li id="9UTK">Пакетный менеджер</li>
    <li id="fi1W">Графическая система</li>
    <li id="VROR">Командный интерпретатор</li>
    <li id="frEt">Домашний каталог и скрытые файлы</li>
    <li id="kj1V">Ввод-вывод и пайпы</li>
    <li id="03G3">Файловые системы</li>
    <li id="eU14">Система каталогов</li>
    <li id="65IB">Пользователи, права на файлы</li>
    <li id="j86w">Ссылки</li>
    <li id="K1Zo">Установка софта</li>
    <li id="tROI">Init и systemd</li>
    <li id="Be0O">Прочие приложения</li>
    <li id="WADZ">Итоги</li>
  </ul>
  <p id="JoQN">Со­вер­шенно не важ­но, какую опе­раци­онку ты пред­почита­ешь иметь на рабочем компь­юте­ре, — Linux сегод­ня бук­валь­но пов­сюду: на сер­верах, на желез­ках вро­де Raspberry Pi, на умных устрой­ствах, на компь­юте­рах в госуч­режде­ниях... Да что там, даже в Windows теперь <a href="https://justpaste.it/redirect/394ty/https://xakep.ru/2017/02/03/wsl-in-colors/" target="_blank">мож­но запус­кать Linux</a>, что­бы лег­че было, к при­меру, тес­тировать сер­верный софт. Хакеру же ори­енти­ровать­ся в Linux прос­то необ­ходимо.</p>
  <p id="8iva">Ог­ромное количес­тво хакер­ско­го соф­та работа­ет толь­ко на Linux и соб­рано в спе­циали­зиро­ван­ных дис­три­бути­вах вро­де Kali. К тому же при пен­тесте ты час­то будешь стал­кивать­ся с сис­темами на Linux и дол­жен уметь с ними обра­щать­ся. Да и прос­то полез­но иметь опыт работы с этой мощ­ной, абсо­лют­но бес­плат­ной сис­темой. В жиз­ни при­годит­ся, поверь!</p>
  <p id="mbQE">В этой статье мы попыта­емся рас­ска­зать все, что сами хотели бы знать, ког­да начина­ли инте­ресо­вать­ся «Линук­сом» мно­го лет назад. Это и теоре­тичес­кие све­дения, которые помогут ори­енти­ровать­ся, и впол­не прак­тичные советы.</p>
  <h4 id="m589">Важное предупреждение</h4>
  <p id="cQ8j">По уров­ню слож­ности это не впол­не харак­терная для «Хакера» статья — она рас­счи­тана на сов­сем‑сов­сем новых поль­зовате­лей. Мысль о ней появи­лась, ког­да мы ста­ли ком­поновать под­борку матери­алов об исполь­зовании Linux и обна­ружи­ли, что у нас нет ничего, что подош­ло бы в качес­тве самого начала. А если и есть, то пок­рыто тол­сты­ми мха­ми.</p>
  <p id="MwqW">Ес­ли ты про­тив таких ста­тей в «Хакере», можешь, конеч­но, отме­тить­ся в ком­мента­риях, но, пра­во сло­во, луч­ше иди почитай про <a href="https://justpaste.it/redirect/394ty/https://xakep.ru/2021/10/19/linux-core-cve/" target="_blank">экс­плу­ата­цию ядра</a> или про то, <a href="https://justpaste.it/redirect/394ty/https://xakep.ru/2021/08/24/reverse-shell-237-bytes/" target="_blank">как писать минима­лис­тичный бэк‑шелл на ассем­бле­ре</a>. Бла­го таких ста­тей у нас боль­шинс­тво и менять в этом пла­не мы ничего не собира­емся.</p>
  <p id="M9B3">Ес­ли же тема кажет­ся тебе в самый раз, то прис­тегивай­ся — наш звез­долет отправ­ляет­ся, что­бы про­нес­тись по осно­вам Linux со сверх­све­товой ско­ростью.</p>
  <h3 id="kxeg">КАКОЙ БЫВАЕТ LINUX</h3>
  <p id="NnvG">Пер­вое, с чем стал­кива­ется человек, жела­ющий уста­новить Linux, — это огромное раз­нооб­разие дис­три­бути­вов. Все эти наз­вания прос­то невоз­можно упом­нить, но в реаль­нос­ти и не нуж­но.</p>
  <p id="4zwT">Три основных семей­ства дис­три­бути­вов, о которых нуж­но знать в пер­вую оче­редь, — это Debian, Red Hat и Arch. Еще мож­но вспом­нить SUSE, Mandriva и Gentoo, но день­ки их сла­вы уже позади, да прос­тят нас их поль­зовате­ли!</p>
  <h4 id="0n2p">INFO</h4>
  <p id="514S">Chrome OS — это тоже внут­ри впол­не нас­тоящий Linux, и в новых вер­сиях под­держи­вает­ся запуск прог­рамм для Linux. Но в один ряд с дру­гими дис­три­бути­вами эту ОС все же не пос­тавишь.</p>
  <p id="XOYi">Из семей­ства ­Debian в пер­вую оче­редь сто­ит обра­тить вни­мание на <a href="https://justpaste.it/redirect/394ty/https://ubuntu.com/" target="_blank">Ubuntu</a>. Это и есть самый оче­вид­ный выбор, если ты раз­думыва­ешь, с чего начать. Ком­пания Canonical, сто­ящая за Ubuntu, прик­ладыва­ет огромные силы для того, что­бы этот дис­три­бутив хорошо работал и был дру­желю­бен к поль­зовате­лю. Для это­го дис­три­бути­ва име­ется широчай­ший выбор ста­биль­но работа­ющих прог­рамм — ты точ­но не будешь испы­тывать в них недос­татка.</p>
  <figure id="VHb0" class="m_original">
    <img src="https://justpaste.it/img/1af081b890d7ca802ee917e5b53fe048.png" width="1600" />
  </figure>
  <figure id="SS1N" class="m_original">
    <img src="https://justpaste.it/img/ee22908543ec20b2a8464c9a4da9a6d5.png" width="1600" />
  </figure>
  <p id="jKKC">К тому же у Ubuntu огромное сооб­щес­тво, что зна­читель­но упро­щает решение проб­лем: в 99% слу­чаев ты будешь не пер­вый, кто испы­тыва­ет ту или иную слож­ность. Прос­то копируй сооб­щение об ошиб­ке, и навер­няка най­дешь вет­ку форума, где более опыт­ные товари­щи объ­ясня­ют дру­гим пос­тра­дав­шим, как с этим спра­вить­ся.</p>
  <p id="GsKQ">Есть и дру­гие популяр­ные дис­три­бути­вы, осно­ван­ные на Debian, — к при­меру, Raspberry Pi OS, MX Linux или <a href="https://justpaste.it/redirect/394ty/https://www.kali.org/" target="_blank">Kali Linux</a>. А на Ubuntu базиру­ются <a href="https://justpaste.it/redirect/394ty/https://linuxmint.com/" target="_blank">Linux Mint</a>, <a href="https://justpaste.it/redirect/394ty/https://elementary.io/" target="_blank">elementary OS</a> и мно­гие дру­гие. Кста­ти, Mint и elementary тоже неп­лохие вари­анты для нович­ков.</p>
  <p id="IM47">Ста­вить Kali в качес­тве пер­вой сис­темы обыч­но не рекомен­дуют: этот узкоспе­циали­зиро­ван­ный хакер­ский дис­три­бутив пло­хо прис­пособ­лен для пов­седнев­ной работы, и уста­нав­ливать его пред­полага­ется в вир­туал­ку или в качес­тве вто­рой ОС. К тому же он под завяз­ку забит хак­тулза­ми вмес­то обыч­ных при­ложе­ний, что будет сби­вать с тол­ку. Но если ты ста­вишь Linux спе­циаль­но, что­бы заполу­чить все это богатс­тво, то кто мы такие, что­бы тебя оста­нав­ливать?</p>
  <p id="VUzo">Что до самого Debian, то его глав­ная фиш­ка — это лицен­зион­ная чис­тота. Раз­работ­чики вни­матель­но сле­дят за тем, что­бы в него не попало ни строч­ки кода, который рас­простра­няет­ся не по сво­бод­ной лицен­зии. Что может быть и пох­валь­но с точ­ки зре­ния иде­оло­гии, но, ког­да ты хочешь осво­ить­ся с Linux, ско­рее все­го, обер­нется раз­ного рода слож­ностя­ми.</p>
  <p id="5et3">К семей­ству дис­три­бути­вов <a href="https://justpaste.it/redirect/394ty/http://www.redhat.com/" target="_blank">Red Hat</a> отно­сят­ся в пер­вую оче­редь <a href="https://justpaste.it/redirect/394ty/https://getfedora.org/" target="_blank">Fedora</a>, <a href="https://justpaste.it/redirect/394ty/http://www.redhat.com/rhel" target="_blank">Red Hat Enterprise Linux (RHEL)</a> и <a href="https://justpaste.it/redirect/394ty/https://rockylinux.org/" target="_blank">Rocky Linux</a>. На обыч­ный ПК есть смысл ста­вить «Федору», тог­да как RHEL — это ком­мерчес­кое решение для сер­веров, а Rocky Linux — его неком­мерчес­кий клон, соз­данный сооб­щес­твом.</p>
  <figure id="6Ugy" class="m_original">
    <img src="https://justpaste.it/img/f7b0ccbb33b88920168dcb27b415716c.png" width="1600" />
  </figure>
  <p id="8OkE">И наконец, <a href="https://justpaste.it/redirect/394ty/https://archlinux.org/" target="_blank">Arch</a> — это край­не инте­рес­ный «гиков­ский» дис­три­бутив, который ты можешь сам соб­рать по кир­пичикам и нас­тро­ить как тебе захочет­ся. Одна­ко нырять в это без пред­варитель­ных поз­наний в Linux не совету­ем. Решая проб­лемы, ты, конеч­но, при­обре­тешь мно­го цен­ных зна­ний, но это далеко не самый прос­той путь, и луч­ше отло­жить хож­дение по нему на потом.</p>
  <p id="beOh">У Arch есть и менее суровые вари­ации — <a href="https://justpaste.it/redirect/394ty/https://manjaro.org/" target="_blank">Manjaro</a> и <a href="https://justpaste.it/redirect/394ty/https://endeavouros.com/" target="_blank">EndeavourOS</a>. В обе­их хотя бы при­сутс­тву­ют заранее нас­тро­енные и под­готов­ленные к работе окру­жения, но тоже аске­тич­ные. С дру­гой сто­роны, отсутс­твие необуз­данно­го раз­нооб­разия может быть плю­сом при пер­вом зна­комс­тве, так что начинать с Manjaro — не такая пло­хая идея. Осо­бен­но если ты пла­ниру­ешь ста­вить Linux на сла­бый компь­ютер.</p>
  <figure id="vnJw" class="m_original">
    <img src="https://justpaste.it/img/91a24e888b71198f8805250ec279ebae.png" width="1920" />
  </figure>
  <h4 id="Udni">Not Unix</h4>
  <p id="jvDU">В чем отли­чие Linux от Unix? Если очень‑очень упростить, то мож­но ска­зать, что Unix — это пре­док Linux. Более слож­ный и раз­верну­тый ответ тре­бует нем­ного углу­бить­ся в исто­рию.</p>
  <p id="SAIS">В семиде­сятые годы Ричард Стол­лман при­думал кло­ниро­вать ком­мерчес­кий и по тем вре­менам дорогос­тоящий Unix и соз­дать свою опе­раци­онку, которую он наз­вал GNU is not Unix или прос­то GNU. Стол­лман и ком­пания перепи­сали все ком­понен­ты Unix и опуб­ликова­ли их под при­думан­ной ими «вирус­ной» лицен­зией GPL.</p>
  <p id="kW1H">Из­началь­но сло­вом Linux называ­ли толь­ко соз­данное Линусом Тор­валь­дсом ядро. Но наз­вание Linux и мас­кот‑пин­гвин быс­тро при­жились, и ими теперь обоз­нача­ют всю ОС — нес­мотря на воз­ражения Стол­лма­на и прось­бы писать толь­ко GNU/Linux.</p>
  <p id="ebYe">Linux в эпо­ху интерне­та стал быс­тро набирать популяр­ность, и ком­мерчес­ким вари­антам Unix со вре­менем прос­то не оста­лось мес­та. Тем не менее до сих пор живы его потом­ки — опе­раци­онные сис­темы FreeBSD и OpenBSD, которые теперь бес­плат­ны и мно­гое заимс­тву­ют из сов­ремен­ного «Линук­са». Кста­ти, на FreeBSD осно­ваны macOS и iOS.</p>
  <p id="dqV7">По­луча­ется, что выбор дис­три­бути­ва — это в пер­вую оче­редь выбор под­хода и даже иде­оло­гии. Одна­ко более при­зем­ленным ори­енти­ром обыч­но слу­жит набор основных ком­понен­тов, из которых стро­ятся дис­тры. Давай обсу­дим глав­ные из них.</p>
  <h3 id="gl0a">ЯДРО</h3>
  <p id="IQ5L">Яд­ро, хоть и кри­тичес­ки важ­но для работы сис­темы, осо­бо не инте­рес­но с точ­ки зре­ния поль­зовате­ля — вза­имо­дей­ство­вать с ним нап­рямую тебе вряд ли при­дет­ся, пока ты не ста­нешь нас­тоящим гуру.</p>
  <p id="Hf5z">Воз­можно, ты час­то слы­шал про «сбор­ку ядра» и можешь даже самос­тоятель­но поп­робовать сде­лать это. Пос­коль­ку ядро Linux монолит­ное, в него дол­жна вхо­дить под­дер­жка мно­жес­тва вещей, которые каса­ются всех аспектов работы компь­юте­ра. Соот­ветс­твен­но, перед сбор­кой мож­но и нуж­но задать кучу вся­ких нас­тро­ек, но ничего осо­бен­но увле­катель­ного в этом, поверь, нет, хотя про­цесс край­не поз­наватель­ный.</p>
  <p id="rUci">В сис­теме может одновре­мен­но при­сутс­тво­вать сколь­ко угод­но ядер, а какое имен­но будет исполь­зовать­ся, ты можешь выб­рать в заг­рузчи­ке. Апгрейд ядра до более новой вер­сии — совер­шенно рутин­ное дело в Linux и обыч­но про­исхо­дит авто­мати­чес­ки.</p>
  <h3 id="Rk6v">ПАКЕТНЫЙ МЕНЕДЖЕР</h3>
  <p id="7CoQ">Лю­бой Linux сос­тоит из тысяч мел­ких ком­понен­тов — прог­рамм, биб­лиотек и ресур­сов (нап­ример, фай­лов кон­фигура­ции, наборов ико­нок и так далее). Рас­простра­няют­ся они в виде пакетов (package).</p>
  <p id="O4kV">Па­кет­ный менед­жер — это спе­циаль­ная прог­рамма, которая выпол­няет уста­нов­ку, нас­трой­ку, уда­ление, а так­же обновле­ние как отдель­ных при­ложе­ний, так и всей сис­темы в целом или ее ком­понен­тов.</p>
  <p id="vqDF">Очень час­то один пакет тре­бует для работы наличия дру­гих, и сле­дить за эти­ми зависи­мос­тями вруч­ную на сов­ремен­ной сис­теме невоз­можно. Поэто­му осно­ва каж­дого дис­три­бути­ва — это пакет­ный менед­жер, который рулит уста­нов­кой и обновле­нием соф­та. В дис­три­бути­вах, осно­ван­ных на Debian, он называ­ется APT, в Red Hat — DNF, а в Arch — pacman.</p>
  <p id="LowA">Па­кеты менед­жер берет из репози­тория — боль­шого скла­да, куда соз­датели дис­три­бути­ва заг­ружа­ют их. Репози­тори­ев зачас­тую мож­но под­клю­чить сра­зу нес­коль­ко. Нап­ример, в Ubuntu есть четыре основных: Main (под­держи­ваемый раз­работ­чиками), Universe (под­держи­ваемый сооб­щес­твом), Restricted (с проп­риетар­ным ПО) и Multiverse (с ПО, на которые дей­ству­ют нес­вобод­ные лицен­зии).</p>
  <p id="L2fR">Пос­коль­ку вско­ре пос­ле уста­нов­ки Linux ты обна­ружишь необ­ходимость в драй­верах для железа, допол­нитель­ных шриф­тах, кодеках и тому подоб­ных вещах, ско­рее все­го, понадо­бит­ся раз­решить сис­теме дос­туп к запят­нанным ком­мерци­ей репози­тори­ям. В Ubuntu это дела­ется в меню «Прог­раммы и обновле­ния».</p>
  <h3 id="8nPQ">ГРАФИЧЕСКАЯ СИСТЕМА</h3>
  <p id="fc29">Да­леко не каж­дый Linux снаб­жен гра­фичес­кой сис­темой или вооб­ще нуж­дает­ся в ней — очень мно­гие дей­ствия здесь мож­но делать и из коман­дной стро­ки. Одна­ко сов­ремен­ный рабочий стол — это все же икон­ки и окош­ки.</p>
  <p id="WABA">Что­бы работать с гра­фикой, в Linux дол­жны при­сутс­тво­вать сер­вер дис­плея X.Org (тра­дици­онный вари­ант) либо новомод­ный ком­позитор Wayland, на который сей­час перехо­дят наибо­лее передо­вые дис­три­бути­вы. Плюс тре­бует­ся окон­ный менед­жер — прог­рамма, которая отве­чает за то, как выг­лядят и работа­ют эле­мен­ты интерфей­са.</p>
  <p id="dfqt">Впро­чем, это всё доволь­но низ­коуров­невые под­робнос­ти, нырять в которые с ходу не обя­затель­но. Куда ско­рее тебе при­дет­ся задумать­ся о выборе рабочей сре­ды (Desktop Environment, DE). Это совокуп­ность окон­ного менед­жера и раз­ного рода прог­рамм, мел­ких (нап­ример, рису­ющих раз­ные панели, рабочий стол, вид­жеты) и круп­ных — вро­де фай­лового менед­жера. Сюда же обыч­но вхо­дит и набор базово­го соф­та: кален­дарь, поч­товик и про­чее в таком духе.</p>
  <p id="jdCU">Са­мые извес­тные окон­ные сре­ды — это <a href="https://justpaste.it/redirect/394ty/https://www.gnome.org/" target="_blank">GNOME</a> и <a href="https://justpaste.it/redirect/394ty/https://www.kde.org/" target="_blank">KDE</a>. Но в реаль­нос­ти их спи­сок гораз­до длин­нее. Любите­ли минима­лиз­ма могут прис­мотреть­ся к Xfce или LXDE, а Ratpoison, dwm, i3 и xmonad пре­дос­тавля­ют сре­ду с неперек­рыва­ющи­мися окна­ми, что некото­рые находят удоб­ным.</p>
  <p id="rOqx">А еще от GNOME отва­лились про­екты MATE и Cinnamon — их раз­работ­чикам не пон­равил­ся интерфейс GNOME 3, и они про­дол­жили раз­вивать вто­рую вет­ку. А в elementary OS исполь­зует­ся своя сре­да под наз­вани­ем Pantheon, которую не встре­тишь боль­ше ниг­де. В общем, раз­нооб­разие огромно!</p>
  <p id="B4SW">Соз­датели дис­три­бути­вов, в которые вхо­дит гра­фичес­кая сре­да, обыч­но выбира­ют одну или нес­коль­ко сред, которые будут под­держи­вать офи­циаль­но. Но при этом тебе нич­то не меша­ет поменять DE или уста­новить одновре­мен­но боль­ше одной, что­бы перек­лючать­ся меж­ду ними или исполь­зовать прог­раммы одной сре­ды из дру­гой. Про­буй, экспе­римен­тируй, и сам пой­мешь, что тебе бли­же.</p>
  <h3 id="RAqy">КОМАНДНЫЙ ИНТЕРПРЕТАТОР</h3>
  <p id="9dcq">Поль­зовате­ли Windows при­вык­ли к тому, что в этой опе­раци­онной сис­теме име­ется стан­дар­тный интер­пре­татор команд <code>cmd.exe</code>, который при­нято называть коман­дной стро­кой. В пос­ледних вер­сиях вин­ды его орга­нич­но допол­нил PowerShell, одна­ко эти­ми дву­мя сре­дами ассорти­мент коман­дных интер­пре­тато­ров в Windows исчерпы­вает­ся.</p>
  <p id="ZGOV">В Linux коман­дных интер­пре­тато­ров сущес­тву­ет мно­жес­тво, и, если для Windows они лишь вспо­мога­тель­ное средс­тво адми­нис­три­рова­ния, здесь это один из основных и очень мощ­ных инс­тру­мен­тов работы с сис­темой.</p>
  <p id="YRFY">Собс­твен­но, сама исто­рия Linux началась имен­но с коман­дной стро­ки, точ­нее тер­минала или даже телетай­па. Гра­фичес­кий интерфейс к нему при­дела­ли уже зна­читель­но поз­же. Имен­но поэто­му коман­дную стро­ку в Linux час­то называ­ют «эму­лятор тер­минала», а про­цес­сы с ними носят пре­фикс <code>tty</code> (teletype).</p>
  <p id="hpeV">Как ты зна­ешь, с исполь­зовани­ем команд в Windows мож­но писать скрип­ты, авто­мати­зиру­ющие какие‑либо дей­ствия: пакет­ные фай­лы (batch files) были в ходу еще со вре­мен MS-DOS, а PowerShell замет­но рас­ширил и углу­бил эту тех­нологию. В Linux мож­но делать то же самое: соб­ранный в файл набор команд интер­пре­тато­ра может работать как слож­ная прог­рамма, а сами коман­ды явля­ются по боль­шому сче­ту язы­ком прог­рамми­рова­ния.</p>
  <p id="2VMa">На­боры команд, сох­ранен­ные одним фай­лом, при­нято называть сце­нари­ями или скрип­тами. Все скрип­ты в Linux начина­ются с сим­волов <code>#!</code> (это сочета­ние называ­ется «шебанг») и пути к интер­пре­тато­ру — коман­де, которая будет исполнять скрипт.</p>
  <p id="s9xz">Стан­дар­тным коман­дным интер­пре­тато­ром в Linux явля­ется bash — обновлен­ная и модер­низиро­ван­ная вер­сия коман­дной обо­лоч­ки Bourne shell, которая была изоб­ретена Сти­веном Бор­ном в 1978 году и исполь­зовалась еще в клас­сичес­ком Unix.</p>
  <p id="q3Zd">Прож­женные линук­соиды пред­почита­ют ста­вить вмес­то bash более прод­винутый интер­пре­татор — Z shell (ZSH), обратно сов­мести­мый с bash, но име­ющий по срав­нению с ним мно­жес­тво улуч­шений. Для этой обо­лоч­ки сооб­щес­твом был раз­работан спе­циаль­ный откры­тый и бес­плат­ный фрей­мворк <a href="https://justpaste.it/redirect/394ty/https://ohmyz.sh/" target="_blank">Oh My ZSH</a>, который содер­жит мно­жес­тво пла­гинов для авто­мати­зации работы с коман­дами и скрип­тами. Как минимум Oh My ZSH поз­воля­ет исполь­зовать кра­сивые темы офор­мле­ния окна коман­дной стро­ки, бла­года­ря которым окру­жающие точ­но соч­тут тебя гени­аль­ным хакером.</p>
  <h4 id="7JcZ">INFO</h4>
  <p id="x9X4">Под­робнее о ZSH и Oh My ZSH читай в статье «<a href="https://justpaste.it/redirect/394ty/https://xakep.ru/2017/05/18/cli-console-tips/" target="_blank">Про­качай тер­минал! Полез­ные трю­ки, которые сде­лают тебя гуру кон­соли</a>».</p>
  <p id="31lu">Пре­дуп­редим о проб­леме, с которой момен­таль­но стал­кива­ется каж­дый новый поль­зователь Linux. Если ты зай­дешь в какой‑то каталог и попыта­ешь­ся написать наз­вание исполня­емо­го фай­ла, что­бы запус­тить его, то ничего не получит­ся. Почему?</p>
  <p id="egvb">При­чина в том, что интер­пре­татор ищет фай­лы толь­ко в катало­гах, которые ука­заны в перемен­ной окру­жения <code>$PATH</code>. То есть тебе нуж­но либо задать пол­ный путь к исполня­емо­му фай­лу, либо явно ука­зать на текущий каталог. Как ты зна­ешь, родитель­ский каталог отме­чает­ся дву­мя точ­ками (<code>../</code>), а что­бы ука­зать на текущий, нуж­но писать <code>./</code>. То есть вмес­то <code>program</code> пиши <code>./program</code>, и все получит­ся!</p>
  <p id="XVja">И еще один очень важ­ный момент. В Windows тип фай­ла опре­деля­ется его рас­ширени­ем — в зависи­мос­ти от него коман­дный интер­пре­татор и обо­лоч­ка опре­деля­ют, как они будут обра­баты­вать файл. В Linux все устро­ено нем­ного по‑дру­гому: у bash пол­ностью отсутс­тву­ет какое‑либо ува­жение к рас­ширени­ям фай­лов. Исполня­емый файл отли­чает­ся от обыч­ного не рас­ширени­ем, а наличи­ем пра­ва на его исполне­ние: если оно есть, сис­тема счи­тает такой файл прог­раммой (или скрип­том) и пыта­ется выпол­нить. О пра­вах на фай­лы мы под­робнее погово­рим чуть даль­ше в соот­ветс­тву­ющем раз­деле.</p>
  <h3 id="fBAO">ДОМАШНИЙ КАТАЛОГ И СКРЫТЫЕ ФАЙЛЫ</h3>
  <p id="c9SK">Пос­коль­ку Linux изна­чаль­но задумы­вал­ся как мно­гополь­зователь­ская опе­раци­онная сис­тема, все пути к «домаш­ним» пап­кам, перемен­ные окру­жения, прог­раммы, которые запус­кают­ся при откры­тии тер­минала, и дру­гие нас­трой­ки зада­ются в про­филе поль­зовате­ля. У раз­ных юзе­ров они, соот­ветс­твен­но, раз­ные. Бла­года­ря это­му ты можешь, нап­ример, нас­тро­ить сис­темное окру­жение так, как ком­фор­тно имен­но тебе.</p>
  <p id="EfoJ">Что­бы ука­зывать на домаш­ний каталог, очень удоб­но исполь­зовать сим­вол <code>~</code>. Так, вмес­то <code>/home/vasya/</code> мож­но писать прос­то <code>~/</code>, если ты залоги­нен как <code>vasya</code>.</p>
  <p id="SR30">В Linux час­то встре­чает­ся то, что в Windows поп­росту невоз­можно: фай­лы, имя которых начина­ется с точ­ки (поль­зовате­ли вин­ды с неп­ривыч­ки дума­ют, буд­то это фай­лы без име­ни, име­ющие одно толь­ко рас­ширение). На самом деле в Linux так обоз­нача­ют скры­тые фай­лы. Нап­ример, имя <code>.htacess</code> говорит нам о том, что этот файл скры­тый, — бла­года­ря наличию точ­ки перед име­нем его лег­ко отли­чить от дру­гих фай­ловых объ­ектов.</p>
  <p id="97nD">В домаш­нем катало­ге поль­зовате­ля хра­нит­ся нес­коль­ко скры­тых фай­лов, которые могут быть очень полез­ны при работе в Linux. Что­бы прос­мотреть скры­тые фай­лы в текущем катало­ге, исполь­зуй кон­соль­ную коман­ду <code>ls -a</code> или поковы­ряй­ся в меню фай­лового менед­жера: нап­ример, в Nautilus пункт «Показать скры­тые фай­лы» пря­чет­ся в меню «Вид». Обра­ти вни­мание на сле­дующие скры­тые фай­лы:</p>
  <ul id="EBr3">
    <li id="nMDH"><code>.bash_profile</code> — содер­жит информа­цию о поль­зователь­ском окру­жении и запус­каемых при авто­риза­ции поль­зовате­ля прог­раммах. В некото­рых дис­три­бути­вах, осно­ван­ных на Debian, дан­ного фай­ла по умол­чанию не сущес­тву­ет, но ты можешь соз­дать его самос­тоятель­но;</li>
    <li id="HauI"><code>.bash_login</code> — этот файл исполня­ется, если отсутс­тву­ет <code>.bash_profile</code>, и выпол­няет схо­жую фун­кцию. Это­го фай­ла не сущес­тву­ет по умол­чанию ни в дис­три­бути­ве Debian, ни в дис­три­бути­ве Red Hat;</li>
    <li id="O5dd"><code>.profile</code> — выпол­няет­ся при отсутс­твии <code>.bash_profile</code> и <code>.bash_login</code>;</li>
    <li id="GFzA"><code>.bash_logout</code> — сце­нарий, который выпол­няет­ся авто­мати­чес­ки при завер­шении работы коман­дной обо­лоч­ки;</li>
    <li id="jg26"><code>.bash_history</code> — хра­нит информа­цию обо всех коман­дах, наб­ранных в bash;</li>
    <li id="yLP8"><code>.ssh</code> — каталог, в котором хра­нят­ся клю­чи шиф­рования для под­клю­чения по SSH;</li>
    <li id="GBER"><code>.bashrc</code> — сце­нарий, который обыч­но нас­тра­ивает­ся дру­гими сце­нари­ями для сво­их собс­твен­ных нужд — нап­ример, запус­ка демонов или обра­бот­ки каких‑либо команд.</li>
  </ul>
  <h4 id="VekM">Необходимый минимум команд</h4>
  <p id="Leke">Итак, запоми­най самые важ­ные коман­ды, если еще не зна­ешь их:</p>
  <ul id="RfmF">
    <li id="fKxJ"><code>man</code> — чуть ли не самая важ­ная коман­да — она отоб­ража­ет справ­ку о коман­де, наз­вание которой ты напишешь сле­дом;</li>
    <li id="VyQ0"><code>ls</code> (от сло­ва list, спи­сок) — перечис­лить все фай­лы в текущей дирек­тории, ана­лог вин­довой коман­ды <code>dir</code>. Самые важ­ные клю­чи: <code>-a</code> (all) — показы­вать скры­тые фай­лы, <code>-l</code> (long) — показы­вать под­робнос­ти, <code>-h</code> (human) — показы­вать раз­меры в «челове­чес­ких» еди­ницах, а не в бай­тах. Мож­но писать все клю­чи сра­зу: <code>ls -lha</code>;</li>
    <li id="xtJd"><code>cd</code> (change directory) — сме­нить дирек­торию. Даль­ше мож­но ука­зать пап­ку, в которую ты хочешь перей­ти;</li>
    <li id="TWvT"><code>pwd</code> (print working directory) — узнать текущий путь;</li>
    <li id="pAKT"><code>cp</code> (copy) — ско­пиро­вать файл. Даль­ше нуж­но ука­зать, что и куда копиро­вать;</li>
    <li id="Wy29"><code>mv</code> (move) — перемес­тить файл. Тоже ука­зыва­ем какой, затем — куда;</li>
    <li id="aH8J"><code>rm</code> (remove) — сте­реть файл. Если сти­раешь каталог, ука­зывай опцию <code>-r</code> (recursive), что­бы сте­реть все под­катало­ги внут­ри, под­катало­ги внут­ри них и так далее;</li>
    <li id="nji7"><code>chmod</code> и <code>chown</code> — поменять пра­ва на файл или вла­дель­ца фай­ла;</li>
    <li id="6ZP8"><code>cat</code> (concatenate) — при­дума­на, что­бы объ­еди­нять фай­лы, но час­то исполь­зует­ся, что­бы все­го лишь вывес­ти содер­жимое тек­сто­вого фай­ла. Прос­то напиши его наз­вание пос­ле <code>cat</code>;</li>
    <li id="DmCR"><code>less</code> — если файл длин­ный, то его удоб­но прок­ручивать. Для это­го и при­дума­на коман­да <code>less</code>;</li>
    <li id="OqvU"><code>head</code> и <code>tail</code> — с опци­ей <code>-n число</code> показы­вают сколь­ко‑то строк от начала (<code>head</code>) или кон­ца (<code>tail</code>) ука­зан­ного фай­ла;</li>
    <li id="FCMt"><code>grep</code> — поиск в стро­ке по подс­тро­ке или регуляр­ному выраже­нию;</li>
    <li id="IP9E"><code>find</code> — поиск фай­лов;</li>
    <li id="iTDL"><code>mkdir</code> (make directory) — соз­дание дирек­тории;</li>
    <li id="pmyV"><code>touch</code> — соз­дание пус­того фай­ла. Прос­то ука­жи его наз­вание;</li>
    <li id="knr7"><code>sudo</code> — выпол­нить сле­дующую далее коман­ду от име­ни супер­поль­зовате­ля;</li>
    <li id="KPiZ"><code>df</code> (disk free) — пос­мотреть, сколь­ко на дис­ках сво­бод­ного мес­та. Рекомен­дую писать <code>df -h</code> по ана­логии с <code>ls -h</code>;</li>
    <li id="UXyf"><code>du</code> (disk usage) — узнать, сколь­ко занима­ет каталог. Тоже есть опция <code>-h</code>;</li>
    <li id="3gUn"><code>ps</code> (processes) — пос­мотреть спи­сок запущен­ных тобой про­цес­сов и их иден­тифика­торы;</li>
    <li id="2eSb"><code>kill</code> и иден­тифика­тор — завер­шить какой‑то про­цесс.</li>
  </ul>
  <p id="IicJ">Нес­коль­ко важ­ных сетевых команд:</p>
  <ul id="MMTA">
    <li id="CXsc"><code>ping</code> — попин­говать узел;</li>
    <li id="Tz88"><code>nslookup</code> — узнать информа­цию об узле;</li>
    <li id="IjTh"><code>traceroute</code> — прос­ледить путь пакетов до узла;</li>
    <li id="2NU8"><code>netstat</code> — информа­ция об откры­тых пор­тах и соеди­нени­ях;</li>
    <li id="iM7L"><code>whois</code> — информа­ция о регис­тра­ции домена.</li>
  </ul>
  <p id="x41m">По­мимо это­го, в Linux обыч­но есть нес­коль­ко ути­лит, которые силь­но облегчат тебе жизнь. Если их нет, то сто­ит их уста­новить:</p>
  <ul id="SvxU">
    <li id="41sz"><code>git</code> — популяр­ней­шая сис­тема кон­тро­ля вер­сий, как и ядро Linux, соз­данная Линусом Тор­валь­дсом;</li>
    <li id="v8iH"><code>nano</code> — прос­тей­ший тек­сто­вый редак­тор, работа­ющий в тер­минале;</li>
    <li id="ixHU"><code>unzip</code> и <code>unrar</code> — думаю, ты догады­ваешь­ся, зачем они нуж­ны;</li>
    <li id="gAd1"><code>curl</code> нужен для веб‑зап­росов;</li>
    <li id="n2IR"><code>wget</code> — для ска­чива­ния боль­ших фай­лов;</li>
    <li id="5lKg"><code>htop</code> показы­вает уро­вень заг­рузки сис­темы и спи­сок про­цес­сов.</li>
  </ul>
  <p id="Ij9Q"><strong>Важ­но:</strong> вый­ти из прог­рамм, которые не зак­рыва­ются сами, обыч­но мож­но, нажав Q. Прер­вать работу — Ctrl-C. А что­бы вый­ти из <code>vim</code>, если ты его открыл слу­чай­но, набери пос­ледова­тель­ность <code>:q!</code> и наж­ми Enter.</p>
  <h3 id="ZNmV">ВВОД-ВЫВОД И ПАЙПЫ</h3>
  <p id="0RfT">Боль­шинс­тво прог­рамм, работа­ющих из коман­дной стро­ки, при­нима­ют дан­ные на вход и что‑то выда­ют на выходе. При этом вывод одной прог­раммы мож­но нап­равить на ввод дру­гой и таким обра­зом дос­тичь какой‑то более слож­ной цели или авто­мати­зиро­вать какой‑то про­цесс. Давай раз­берем­ся под­робнее.</p>
  <p id="uhFs">Стан­дар­тный поток вво­да, к которо­му по умол­чанию «при­вяза­на» кла­виату­ра, называ­ется standard input (stdin). Стан­дар­тный поток вывода носит наз­вание standard output (stdout). Сущес­тву­ет и отдель­ный поток вывода, пред­назна­чен­ный исклю­читель­но для сооб­щений об ошиб­ках. Он называ­ется standard error, или stderr. По умол­чанию с эти­ми дву­мя потока­ми вывода свя­зан монитор.</p>
  <p id="XDpc">По­токи при­ложе­ний и команд мож­но перенап­равлять в фай­лы или в дру­гие коман­ды. Пос­коль­ку стан­дар­тные потоки вво­да/вывода пред­назна­чены в основном для обме­на тек­сто­вой информа­цией, такое перенап­равле­ние поз­воля­ет наладить «обще­ние» прог­рамм меж­ду собой.</p>
  <p id="10jc">Са­мый прос­той при­мер подоб­ного обще­ния — это ког­да мы переда­ем стан­дар­тный вывод (stdout) одной прог­раммы на стан­дар­тный ввод (stdin) дру­гой. Такой вари­ант перенап­равле­ния обоз­нача­ется в Linux сим­волом <code>|</code> и называ­ется тер­мином «кон­вей­ер» или «пайп» (pipe). Нап­ример, если мы исполь­зуем запись вида <code>команда 1 |команда 2</code>, это будет озна­чать, что весь стан­дар­тный вывод коман­ды 1, который по умол­чанию был бы нап­равлен на дис­плей (stdout), будет передан на стан­дар­тный ввод (stdin) коман­ды 2. Это и есть реали­зация прос­тей­шего пай­па или кон­вей­ера.</p>
  <p id="5Z5v">Воз­можно, ты уже натыкал­ся на исполь­зование пай­пов в сочета­нии с коман­дой <code>grep</code>, пред­назна­чен­ной для филь­тра­ции тек­сто­вых дан­ных. Работа­ет она так:</p>
  <p id="oz42"><code>$ команда | grep [опции] шаблон</code></p>
  <p id="tMhf">где <code>команда</code> — это коман­да, стан­дар­тный вывод которой перенап­равля­ется коман­де <code>grep</code>;</p>
  <p id="yQg0"><code>опции</code> — это раз­личные парамет­ры поис­ка;</p>
  <p id="PVAl"><code>шаблон</code> — стро­ка или зна­чение, которые мы ищем.</p>
  <p id="X83t">Нап­ример, коман­да <code>ls | grep string</code> озна­чает, что мы, получив спи­сок содер­жимого текущей дирек­тории c помощью кон­соль­ной коман­ды <code>ls</code>, ищем в нем файл или пап­ку, в име­ни которых содер­жится стро­ка <code>string</code>.</p>
  <p id="J47F">Еще вывод коман­ды быва­ет удоб­но перенап­равить в файл. Напиши <code>ls -lha &gt; list.txt</code>, и получишь файл <code>list.txt</code> с под­робным перечис­лени­ем все­го, что содер­жится в текущем катало­ге.</p>
  <h4 id="j7bc">Полезные шпаргалки</h4>
  <p id="WGgc">Вся мощь команд Linux — в допол­нитель­ных парамет­рах, которые ты можешь ука­зать. Что­бы узнать о них, нуж­но читать справ­ку (man), но есть спо­собы схит­рить и облегчить себе жизнь.</p>
  <ul id="wKNF">
    <li id="AUh1"><a href="https://justpaste.it/redirect/394ty/https://tldr.sh/" target="_blank">tldr pages</a> — сок­ращен­ная вер­сия man, в которой дотош­ные опи­сания пок­ромса­ли до абсо­лют­ного миниму­ма (<a href="https://justpaste.it/redirect/394ty/https://xakep.ru/2017/12/15/www-tldr-pages/" target="_blank">под­робнее</a>);</li>
    <li id="gVQE"><a href="https://justpaste.it/redirect/394ty/https://github.com/chubin/cheat.sh" target="_blank">cheat.sh</a> — онлай­новая база дан­ных с при­мера­ми популяр­ных вари­антов команд (<a href="https://justpaste.it/redirect/394ty/https://xakep.ru/2018/07/13/www-cheatsh/" target="_blank">под­робнее</a>);</li>
    <li id="erPK"><a href="https://justpaste.it/redirect/394ty/https://github.com/pindexis/marker" target="_blank">Marker</a> — похожая шту­ка, но офлай­новая и с под­сказ­ками «на лету» (<a href="https://justpaste.it/redirect/394ty/https://xakep.ru/2019/03/06/www-marker/" target="_blank">под­робнее</a>);</li>
    <li id="V9PA"><a href="https://justpaste.it/redirect/394ty/https://explainshell.com/" target="_blank">explainshell.com</a> — сер­вис, который авто­мати­чес­ки раз­бира­ет слож­ную коман­ду и объ­ясня­ет зна­чение ее сос­тавных час­тей.</li>
  </ul>
  <p id="QUEv">За­пом­нить все парамет­ры всех команд невоз­можно, поэто­му даже заяд­лые линук­соиды при­бега­ют к таким хит­ростям (и неус­танно изоб­рета­ют всё новые)!</p>
  <h3 id="etjo">ФАЙЛОВЫЕ СИСТЕМЫ</h3>
  <p id="pCOd">В Linux есть под­дер­жка раз­ных фай­ловых сис­тем. Любой сов­ремен­ный Linux по умол­чанию уста­нав­лива­ется на ext4 и тре­бует соз­дания отдель­ного раз­дела типа Swap (ана­лог фай­ла под­качки в Windows). Помимо это­го, обыч­но под­держи­вают­ся дис­ки ext2 и ext3, XFS и FAT раз­ных вер­сий. В Ubuntu и некото­рых дру­гих дис­три­бути­вах из короб­ки дос­тупна работа с раз­делами NTFS на чте­ние и запись. Что до маков­ских HFS+ и APFS, то для них обыч­но тре­бует­ся отдель­ный драй­вер.</p>
  <p id="ITTy">Что­бы работать с какой‑то ФС (рас­положен­ной на жес­тком дис­ке или на внеш­нем носите­ле), ее нуж­но при­мон­тировать, а перед завер­шени­ем работы — демон­тировать. За это отве­чают коман­ды <code>mount</code> и <code>umount</code>. В фай­ле <code>/etc/fstab</code> ука­зыва­ются сис­темы, которые Linux будет мон­тировать авто­мати­чес­ки при заг­рузке.</p>
  <p id="MLOY">От­дель­ного упо­мина­ния зас­лужива­ет сис­тема FUSE — Filesystem in Userspace (в про­тиво­вес под­дер­жке на уров­не ядра). Через эту шту­ку мож­но под­клю­чать непод­держи­ваемые по умол­чанию фай­ловые сис­темы или даже сде­лать подобие фай­ловой сис­темы из API облачно­го сер­виса. Под­робнее об этом читай в статье «<a href="https://justpaste.it/redirect/394ty/https://xakep.ru/2017/08/07/fs-tricks/" target="_blank">Все есть файл! Мон­тиру­ем Git-репози­тории, FTP- и SSH-ресур­сы, ZIP-архи­вы, тор­ренты, маг­нитные ссыл­ки и мно­гое дру­гое</a>».</p>
  <h3 id="0U08">СИСТЕМА КАТАЛОГОВ</h3>
  <p id="ofc3">В любой ОС есть катало­ги с сис­темны­ми фай­лами, которые луч­ше не тро­гать без лиш­ней надоб­ности. Но если в Windows пап­ки с сис­темой прос­то лежат в сто­рон­ке, то в Linux все наобо­рот: ты работа­ешь внут­ри уже задан­ной струк­туры катало­гов, при­чем во мно­гие из них мож­но и нуж­но заг­лядывать.</p>
  <p id="ZLgj">Од­на из при­чин такой орга­низа­ции в том, что фай­лами в Linux могут быть не толь­ко дан­ные на дис­ке, но и пор­ты, про­цес­сы и дру­гие сущ­ности. Как ты можешь догадать­ся, читать и писать в них теми же средс­тва­ми, что и при работе с обыч­ными фай­лами, иног­да очень удоб­но.</p>
  <p id="8QUj">Сле­ши «не в ту сто­рону» вряд ли тебя сму­тят, но гораз­до более неп­ривыч­но пос­ле Windows то, что пути пол­ностью вир­туаль­ны и никак не свя­заны с дис­ками. Дан­ные по раз­ным путям могут быть на раз­ных раз­делах, на раз­ных носите­лях или даже на раз­ных компь­юте­рах.</p>
  <p id="Qzkp">Итак, давай пос­мотрим на струк­туру катало­гов, которую ты уви­дишь поч­ти в любом Linux:</p>
  <ul id="YT7H">
    <li id="yRPn"><code>/</code> — кор­невая пап­ка, или, как ее еще называ­ют, root directory — пап­ка, в которой хра­нит­ся все осталь­ное содер­жимое фай­ловой сис­темы;</li>
    <li id="5fUx"><code>/bin</code> (от сло­ва binary) — здесь лежат дво­ичные исполня­емые фай­лы со все­ми основны­ми коман­дами;</li>
    <li id="gJUZ"><code>/boot</code> — здесь рас­положен заг­рузчик и ядро ОС (фай­лы <code>vmlinuz</code> — это как раз оно и есть);</li>
    <li id="EM7Z"><code>/dev</code> — фай­лы в этой пап­ке — это пор­ты и устрой­ства. Работая с эти­ми фай­лами, при­ложе­ния и драй­веры могут обме­нивать­ся информа­цией нап­рямую с обо­рудо­вани­ем. Впро­чем, некото­рые фай­лы — это не нас­тоящие устрой­ства, а вир­туаль­ные. Нап­ример, зна­мени­тый <code>/dev/null</code> при­нима­ет любую информа­цию и ничего с ней не дела­ет, а <code>/dev/random</code> генери­рует слу­чай­ные чис­ла;</li>
    <li id="lesI"><code>/etc</code> — в этой пап­ке содер­жатся обще­сис­темные фай­лы кон­фигура­ции (тог­да как поль­зователь­ские фай­лы кон­фигура­ции находят­ся в домаш­нем катало­ге каж­дого поль­зовате­ля). Если ты адми­нис­тра­тор сис­темы, то сюда при­дет­ся час­то заг­лядывать при нас­трой­ке раз­ных прог­рамм;</li>
    <li id="NnB5"><code>/home</code> — в этой пап­ке содер­жатся домаш­ние катало­ги поль­зовате­лей Linux. Нап­ример, если твое имя поль­зовате­ля — <code>xakep</code>, твоя домаш­няя пап­ка будет называть­ся <code>/home/xakep/</code>;</li>
    <li id="PsA2"><code>/lib</code> — пап­ка для хра­нения биб­лиотек, необ­ходимых исполня­емым фай­лам в пап­ках <code>bin</code> и <code>sbin</code>;</li>
    <li id="SJNa"><code>/lost+found</code> — в эту пап­ку сох­раня­ются вос­ста­нов­ленные в слу­чае сис­темно­го сбоя фай­лы;</li>
    <li id="1c9H"><code>/media</code> — в некото­рых сис­темах допол­нитель­ный каталог, где отоб­ража­ются все смон­тирован­ные в сис­теме съем­ные носите­ли информа­ции. В ста­рых ОС может называть­ся <code>/cdrom</code>;</li>
    <li id="bRYP"><code>/mnt</code> — пап­ка, содер­жащая вре­мен­ные точ­ки мон­тирова­ния: сюда мон­тиру­ются фай­ловые сис­темы для вре­мен­ного исполь­зования;</li>
    <li id="cOui"><code>/opt</code> — каталог содер­жит под­катало­ги для допол­нитель­ных пакетов прог­рам­мно­го обес­печения. Обыч­но исполь­зует­ся проп­риетар­ным ПО, которое не под­чиня­ется стан­дар­тной иерар­хии фай­ловой сис­темы Linux;</li>
    <li id="aDim"><code>/proc</code> — каталог со спе­циаль­ными фай­лами, которые пре­дос­тавля­ют информа­цию о сис­теме и про­цес­сах;</li>
    <li id="4vFw"><code>/root</code> — домаш­ний каталог супер­поль­зовате­ля root;</li>
    <li id="nTnZ"><code>/run</code> — этот каталог пре­дос­тавля­ет при­ложе­ниям стан­дар­тное мес­то для фай­лов, сущес­тву­ющих толь­ко во вре­мя работы сис­темы (отсю­да наз­вание), таких как сокеты и иден­тифика­торы про­цес­сов;</li>
    <li id="r1Hu"><code>/sbin</code> — эта пап­ка по сво­ему наз­начению ана­логич­на пап­ке <code>bin</code>. Здесь лежат дво­ичные исполня­емые фай­лы, которые обыч­но пред­назна­чены для запус­ка поль­зовате­лем <code>root</code> в целях сис­темно­го адми­нис­три­рова­ния;</li>
    <li id="ZLDw"><code>/tmp</code> — пап­ка для хра­нения вре­мен­ных фай­лов по умол­чанию;</li>
    <li id="11XF"><code>/srv</code> — содер­жит дан­ные о сер­висах, пре­дос­тавля­емых сис­темой;</li>
    <li id="ayim"><code>/usr</code> — в этой пап­ке содер­жатся при­ложе­ния и фай­лы поль­зовате­лей сис­темы. В ста­рых Unix это был ана­лог <code>/home</code>, но затем эти вещи раз­делили. Условно: в <code>/usr/</code> — прог­раммы, в <code>/home</code> — вся­кое барах­ло. Находя­щиеся здесь катало­ги <code>/usr/bin</code>, <code>/usr/sbin</code> и <code>/usr/lib</code> рань­ше име­ли то же наз­начение, что и ана­логи, лежащие в кор­не, но для фай­лов поль­зовате­лей (в то вре­мя как пап­ки в кор­не — для фай­лов, исполь­зуемых самой сис­темой). А еще есть каталог <code>/usr/local</code>, где есть свои <code>bin</code>, <code>sbin</code> и <code>lib</code>! Ког­да‑то под­разуме­валось, что здесь будут прог­раммы, спе­цифич­ные для кон­крет­ного компь­юте­ра, то есть в теории завися­щие от его железа. На прак­тике софт сюда попада­ет по самым раз­ным при­чинам;</li>
    <li id="uk9D"><code>/var</code> — от сло­ва variable, то есть что‑то, что может менять­ся. Здесь лежат бэкапы, кеши, биб­лиоте­ки, логи и тому подоб­ные вещи. Одна из важ­ных дирек­торий — это <code>/var/www</code>, где хра­нят­ся дан­ные веб‑сай­тов, если на машине уста­нов­лен веб‑сер­вер.</li>
  </ul>
  <figure id="zLu3" class="m_original">
    <img src="https://justpaste.it/img/485203f77276bbab4868f88d390f5f4d.jpg" width="1524" />
  </figure>
  <p id="MAzv">Ес­ли эта сис­тема катало­гов кажет­ся тебе нем­ного запутан­ной, не вол­нуй­ся, это совер­шенно нор­маль­но! Она соз­давалась годами, и что вырос­ло, то вырос­ло. Упро­щать ее в бли­жай­шем будущем ник­то не собира­ется, пос­коль­ку она стан­дар­тна и любые изме­нения пов­лияют на сов­мести­мость.</p>
  <h3 id="xadZ">ПОЛЬЗОВАТЕЛИ, ПРАВА НА ФАЙЛЫ</h3>
  <p id="XOWv">Linux изна­чаль­но задумы­вал­ся как мно­гополь­зователь­ская сис­тема, а потому раз­деление фай­лов и про­филей поль­зовате­лей здесь орга­низо­вано на высочай­шем уров­не. Поль­зователь с огра­ничен­ными пра­вами в сис­теме может вза­имо­дей­ство­вать с теми или ины­ми фай­лами и катало­гами.</p>
  <p id="VRuu">Важ­но пом­нить, что в Linux сущес­тву­ет супер­поль­зователь с име­нем <code>root</code>, обла­дающий пол­ными адми­нис­тра­тор­ски­ми при­виле­гиями в опе­раци­онной сис­теме, — так ска­зать, самый глав­ный босс всех бос­сов. Он может соз­давать и уда­лять учет­ки дру­гих юзе­ров и вооб­ще менять гло­баль­ные нас­трой­ки ОС. Любой юзер может вре­мен­но побывать в роли <code>root</code> с помощью коман­ды <code>sudo</code> (Substitute User and do, дос­ловно «под­менить поль­зовате­ля и выпол­нить»). Но сра­бота­ет этот sudo, толь­ко если ты зна­ешь пароль от учет­ной записи супер­поль­зовате­ля.</p>
  <p id="3hjr">Каж­дому фай­лу в Linux наз­нача­ется опре­делен­ный набор раз­решений, опре­деля­ющих, кто и что может делать с этим фай­лом. Эти раз­решения обоз­нача­ются спе­циаль­ными бук­вами:</p>
  <ul id="3tX7">
    <li id="gO4z"><code>r</code> (read) — раз­решение на чте­ние фай­ла;</li>
    <li id="hE2M"><code>w</code> (write) — раз­решение на запись в файл;</li>
    <li id="udEl"><code>x</code> (execute) — раз­решение на запуск фай­ла;</li>
    <li id="hq0E"><code>-</code> (про­черк) — раз­решение не уста­нов­лено.</li>
  </ul>
  <p id="davd">Важ­но пом­нить, что катало­ги Linux тоже счи­тает фай­лами, поэто­му для них дей­стви­тель­ны все те же раз­решения и огра­ниче­ния. Одна­ко ука­зан­ные раз­решения не име­ли бы боль­шого смыс­ла, если бы они рас­простра­нялись на всех поль­зовате­лей опе­раци­онной сис­темы. К счастью, это не так: в Linux име­ется три раз­ных катего­рии поль­зовате­лей, для каж­дой из которых мож­но уста­нав­ливать свои собс­твен­ные раз­решения дос­тупа к фай­лам:</p>
  <ul id="etGc">
    <li id="Popm">вла­делец — поль­зователь, который соз­дал этот файл или наз­начен его вла­дель­цем. Вла­дель­цем фай­ла может быть не толь­ко учет­ная запись, но и сама опе­раци­онная сис­тема или при­ложе­ние, которое соз­дало файл;</li>
    <li id="7xuH">груп­па — груп­па поль­зовате­лей, «при­вязан­ная» к дан­ному фай­лу. Ты можешь узнать, к какой груп­пе поль­зовате­лей отно­сит­ся твоя учет­ная запись, с помощью кон­соль­ной коман­ды <code>groups &lt;username&gt;</code>. Спи­сок всех зарегис­три­рован­ных в сис­теме групп обыч­но хра­нит­ся в пап­ке <code>/etc/group</code>;</li>
    <li id="pCVG">дру­гие — все, кто не отно­сит­ся к вла­дель­цу фай­лового объ­екта или груп­пам поль­зовате­лей.</li>
  </ul>
  <p id="S8ht">Та­ким обра­зом, раз­решения дос­тупа к любому фай­лу или пап­ке мож­но записать в виде стро­ки, сос­тоящей из девяти сим­волов и име­ющей сле­дующий вид:</p>
  <p id="vQsZ"><code>rwxrwxrwx</code></p>
  <p id="4O25">Пер­вые три сим­вола здесь опре­деля­ют раз­решения для вла­дель­ца фай­лового объ­екта, вто­рые — для груп­пы, к которой отно­сит­ся вла­делец фай­ла или пап­ки, пос­ледние три — для всех осталь­ных. Раз­решения всег­да сле­дуют имен­но в таком поряд­ке: «чте­ние, запись, запуск», то есть <code>rwx</code>. Нап­ример, обоз­начение вида <code>rwxrw-r--</code> озна­чает, что вла­делец это­го фай­ла может делать с ним что угод­но, чле­ны его груп­пы — толь­ко читать и писать в файл, но не запус­кать его (раз­решение <code>x</code> не уста­нов­лено), а всем осталь­ным поль­зовате­лям сис­темы файл дос­тупен толь­ко на чте­ние.</p>
  <p id="2O4g">Ес­ли эти раз­решения уста­нов­лены для пап­ки, это озна­чает, что поль­зовате­ли груп­пы так­же не смо­гут запус­кать хра­нящи­еся в ней фай­лы, а про­чим поль­зовате­лям открыт дос­туп к содер­жимому пап­ки исклю­читель­но в режиме read only.</p>
  <p id="N58l">Прос­мотреть пра­ва и раз­решения фай­лов и папок мож­но с помощью кон­соль­ной коман­ды <code>ls</code>, снаб­женной клю­чом <code>-l</code>.</p>
  <p id="zpys">Что­бы изме­нить пра­ва дос­тупа, сущес­тву­ет коман­да <code>chmod</code> (Change Mode). При помощи этой коман­ды мож­но даже не про­писы­вать все тре­буемые раз­решения вруч­ную: для лен­тяев в Linux пре­дус­мотре­ны циф­ровые обоз­начения стан­дар­тных наборов раз­решений. Нап­ример, коман­да <code>chmod 755 filename</code> прис­воит фай­лу <code>filename</code> раз­решения <code>rwxr-xr-x</code> (каж­дый поль­зователь име­ет пра­во читать и запус­кать на выпол­нение; вла­делец может редак­тировать), <code>chmod 777 filename</code> даст на выходе <code>rwxrwxrwx</code> (все могут делать все, что захотят), а «дьяволь­ская» коман­да <code>chmod 666 filename</code> — вер­нет <code>rw-rw-rw-</code> (все поль­зовате­ли могут читать и редак­тировать файл).</p>
  <p id="6awI">В сов­ремен­ном Linux сущес­тву­ют еще так называ­емые спе­циаль­ные раз­решения, но их мы рас­смат­ривать не будем: для начала информа­ции впол­не дос­таточ­но, что­бы чувс­тво­вать себя в сис­теме более‑менее уве­рен­но.</p>
  <h3 id="saya">ССЫЛКИ</h3>
  <p id="pmt6">В Windows сущес­тву­ют ярлы­ки — что это такое, объ­яснять, дума­ем, никому не нуж­но. В Linux вмес­то них ссыл­ки, при­чем двух видов — жес­ткие и сим­воличес­кие.</p>
  <p id="Edkz">Жес­ткая ссыл­ка — это, счи­тай, наз­вание фай­ла. Прос­то в Linux их у фай­ла может быть нес­коль­ко, при­чем находить­ся они могут в раз­ных катало­гах. Сле­дова­тель­но, если ты соз­дашь жес­ткую ссыл­ку, а потом уда­лишь исходный файл, то он по‑преж­нему будет дос­тупен по ссыл­ке — ведь она ничем не хуже исходно­го наз­вания, которое ты стер!</p>
  <p id="vRBU">Ес­ли же ты уда­лишь пос­леднюю жес­ткую ссыл­ку, фай­ловая сис­тема боль­ше не будет счи­тать, что файл сущес­тву­ет, и приз­нает мес­то, где он рас­положен, при­год­ным для записи дру­гой информа­ции.</p>
  <p id="C6Og">Сим­воличес­кие ссыл­ки боль­ше похожи на стан­дар­тные ярлы­ки Windows. Они содер­жат адрес целево­го фай­ла или катало­га (жес­тких ссы­лок на каталог не быва­ет), и если он исчезнет, то ссыл­ка будет вес­ти «в никуда».</p>
  <p id="V40x">Жес­ткие ссыл­ки соз­дают­ся коман­дой <code>ln файл ссылка</code>, а если нуж­но сде­лать сим­воличес­кую ссыл­ку, добавь ключ <code>-s</code>.</p>
  <h3 id="jypK">УСТАНОВКА СОФТА</h3>
  <p id="rNLf">Те­бе, конеч­но, ник­то не меша­ет заг­рузить прог­рамму в виде одно­го бинар­ного фай­ла и запус­тить. Глав­ное — не забыть дать ему пра­ва на исполне­ние! Но такие отдель­но сто­ящие фай­лы — ред­кость. Обыч­но, что­бы прог­рамма работа­ла, в сис­тему нуж­но уста­новить сра­зу мно­го все­го. Имен­но поэто­му прог­раммы рас­простра­няют­ся в виде пакетов через репози­торий.</p>
  <p id="5t8H">Нап­ример, в Ubuntu для уста­нов­ки пакета дос­таточ­но написать <code>sudo apt install пакет</code>. Одна­ко рекомен­дует­ся сна­чала сде­лать <code>sudo apt update</code>, что­бы ОС обно­вила свой спи­сок пакетов и узна­ла о выходе новых вер­сий.</p>
  <p id="UkLj">Важ­ное отли­чие Linux зак­люча­ется в том, что прог­рамма пос­ле уста­нов­ки будет раз­бро­сана по раз­ным катало­гам. Исполня­емые фай­лы — в свой каталог, гра­фичес­кие ресур­сы — в свой, нас­трой­ки — в свой, и так далее. При этом прог­раммы обыч­но исполь­зуют общие биб­лиоте­ки, что нем­ного эко­номит мес­то на дис­ке, но иног­да соз­дает неудоб­ные ситу­ации с вер­сиями биб­лиотек.</p>
  <p id="pldC">При исполь­зовании такой сис­темы уста­нов­ки прак­тичес­ки бес­полез­но пытать­ся выяс­нить, куда же уста­нови­лась прог­рамма. Если тебе вдруг понадо­бит­ся уда­лить ее, пиши <code>apt remove пакет</code>, и его содер­жимое покинет твой диск, а вмес­те с ним уйдут и все ком­понен­ты, которые ник­то, кро­ме него, не исполь­зовал.</p>
  <p id="eZgi">Но Linux — это стра­на сво­бод­ных исходных кодов, а потому сбор­ка прог­раммы из исходни­ков — обыч­ное дело. Счи­тай, что вмес­то крес­ла ты купил «конс­трук­тор» из IKEA. Важ­ное отли­чие от нее зак­люча­ется в том, что вмес­то инс­трук­ции со смеш­ными человеч­ками ты получа­ешь Makefile — сце­нарий для прог­раммы <code>make</code>, который соберет все сам на авто­пило­те. А по дороге он изу­чит и учтет все осо­бен­ности тво­ей сис­темы либо наруга­ется на тебя из‑за отсутс­твия каких‑то ком­понен­тов (в отли­чие от пакет­ного менед­жера, который уста­новил бы их сам).</p>
  <p id="t040">Итак, пред­положим, ты нашел на гит­хабе ути­литу <a href="https://justpaste.it/redirect/394ty/https://github.com/jarun/nnn" target="_blank">nnn</a> (это такой минима­лис­тичный фай­ловый менед­жер, работа­ющий в тер­минале) и хочешь ее уста­новить из исходни­ков. Тебе понадо­бит­ся сде­лать сле­дующее.</p>
  <ol id="gA1T">
    <li id="uidn">Удос­товерить­ся, что у тебя в сис­теме есть сам Git. Если его нет — уста­нови:</li>
    <li id="6TDn"><code>sudo apt install git</code></li>
    <li id="kNyx">Ус­тановить зависи­мос­ти для nnn. Все их собирать из исходни­ков — нем­ного слиш­ком, поэто­му прос­то пиши</li>
    <li id="SGiI"><code>sudo apt install pkg-config libncursesw5-dev libreadline-dev</code></li>
    <li id="sY46">Те­перь пора дос­тать <code>nnn</code> с GitHub. Это дела­ется такой коман­дой:</li>
    <li id="4TBY"><code>git clone https://github.com/jarun/nnn.git</code></li>
    <li id="wM8j">За­ходи в ска­чан­ный каталог: <code>cd nnn</code>.</li>
    <li id="hJdw">Пи­ши <code>make</code> и жми Enter. Эта коман­да най­дет Makefile и выпол­нит инс­трук­ции по ком­пиляции.</li>
    <li id="SDJh">Пи­ши <code>sudo make install</code> — эта коман­да раз­ложит соз­данные бинар­ные фай­лы по катало­гам.</li>
  </ol>
  <p id="TqbO">Го­тово! Можешь писать <code>nnn</code>, находясь в любом катало­ге, и фай­ловый менед­жер запус­тится.</p>
  <figure id="tBZI" class="m_original">
    <img src="https://justpaste.it/img/ae6bc784a86895895f445a7db51ac632.jpg" width="1648" />
  </figure>
  <figure id="Moyb" class="m_original">
    <img src="https://justpaste.it/img/da9066827a36686809ab9f71eb2a9333.jpg" width="1538" />
  </figure>
  <p id="8FxH">Об­рати вни­мание, это была лишь демонс­тра­ция. В реаль­нос­ти про­ще и луч­ше будет уста­новить вер­сию nnn из репози­тория. В таком слу­чае пакет­ный менед­жер смо­жет обновлять уста­нов­ленную прог­рамму и уда­лить под­чистую, если понадо­бит­ся. Сбор­ка из исходных кодов может понадо­бить­ся, если софт ред­кий или нуж­на самая‑самая новая вер­сия.</p>
  <p id="J60p">Кста­ти, помимо бинар­ных пакетов, в репози­тори­ях быва­ют и пакеты с исходни­ками. Их сбор­ка прой­дет на авто­мате и поз­волит не морочить­ся с уста­нов­кой зависи­мос­тей.</p>
  <p id="LJf7">В пос­леднее вре­мя набира­ют популяр­ность новые сис­темы уста­нов­ки, в которых прог­раммы рас­простра­няют­ся вмес­те со все­ми зависи­мос­тями и биб­лиоте­ками: AppImage, Flatpak и Snap. Это менее эко­ном­ный метод, но более удоб­ный и надеж­ный. Так­же некото­рые прог­раммы удоб­но уста­нав­ливать через Docker — то есть вмес­те с мини­атюр­ным обра­зом Linux. Но раз­говор обо всем этом выходит за рам­ки сегод­няшней статьи.</p>
  <h3 id="5U9I">INIT И SYSTEMD</h3>
  <p id="xUPV">В Unix и Linux боль­шую роль игра­ет про­цесс ини­циали­зации сис­темы, за который отве­чает ути­лита init. Древ­ние юник­сы до пятой вер­сии прос­то исполня­ли скрипт при вклю­чении — счи­тай, ана­лог autoexec.bat. Ког­да соф­та ста­ло слиш­ком мно­го, приш­лось добавить такое понятие, как runlevel.</p>
  <p id="o0l2">Сис­тема при заг­рузке перехо­дит из одной ста­дии в дру­гую и при каж­дом перехо­де запус­кает скрип­ты из опре­делен­ной пап­ки <code>/etc/rcX.d/</code>, где X — один из уров­ней заг­рузки:</p>
  <ul id="58D9">
    <li id="3bLx">0 — сис­тема вык­лючена;</li>
    <li id="LdOk">1 — одно­поль­зователь­ский режим;</li>
    <li id="98bZ">2 — мно­гополь­зователь­ский;</li>
    <li id="9pOe">3 — с под­дер­жкой сети;</li>
    <li id="yhbQ">5 — пол­ная заг­рузка;</li>
    <li id="pbGs">6 — перезаг­рузка.</li>
  </ul>
  <p id="Bk9M">Так, если добавить ссыл­ку на скрипт в пап­ку <code>rc0.d</code>, то он будет исполнять­ся каж­дый раз перед вык­лючени­ем.</p>
  <figure id="NXKJ" class="m_original">
    <img src="https://justpaste.it/img/3cf1488b691426518c72a5037965de66.jpg" width="1642" />
  </figure>
  <p id="8kAP">Имен­но так сис­тема дела­ет все, что ей положе­но делать, — нап­ример, запус­кает про­вер­ку дис­ка пос­ле вне­зап­ного вык­лючения, ротиру­ет логи, запус­кает и оста­нав­лива­ет работа­ющие в фоне служ­бы (в Unix и Linux они называ­ются демона­ми).</p>
  <p id="Vukw">В сов­ремен­ном Linux на сме­ну этой сис­теме приш­ла еще более изощ­ренная — systemd. Она может заод­но рулить устрой­ства­ми и сетевы­ми соеди­нени­ями и делать дру­гие вещи. В systemd для каж­дого дей­ствия или служ­бы соз­дают­ся кон­фигура­цион­ные фай­лы, в которых ука­зано, ког­да и при каких усло­виях нуж­но что‑то запус­кать или оста­нав­ливать. Най­ти их спи­сок ты можешь в <code>/lib/systemd/</code>, а работа­ют с ними при помощи коман­ды <code>service</code>.</p>
  <p id="2uBZ">При этом сис­тема с уров­нями заг­рузки пока что тоже под­держи­вает­ся в популяр­ных дис­три­бути­вах, нес­мотря на при­сутс­твие systemd. Ина­че были бы проб­лемы с сов­мести­мостью.</p>
  <h4 id="lPWb">INFO</h4>
  <p id="Jjs2">Под­робнее о systemd читай в статье «<a href="https://justpaste.it/redirect/394ty/https://xakep.ru/2019/10/31/systemd/" target="_blank">По­лез­ный демон. Как перес­тать боять­ся systemd и сде­лать свой сер­вис для Linux</a>».</p>
  <h3 id="RMgB">ПРОЧИЕ ПРИЛОЖЕНИЯ</h3>
  <p id="Fw9s">При нас­той­ке сети в Linux ты, ско­рее все­го, стол­кнешь­ся с iptables — стан­дар­тным фай­рво­лом и частью сис­темы Netfilter. Если ты выб­рал Ubuntu, то нас­тра­ивать его мож­но при помощи удоб­ной ути­литы <code>ufw</code>.</p>
  <p id="UFZv">Дру­гая полез­ней­шая ути­лита в Linux — это cron. Она дела­ет при­мер­но то же, что и пла­ниров­щик заданий в Windows. В новых сис­темах cron работа­ет бок о бок с уже упо­мяну­тым (и гораз­до более наворо­чен­ным) systemd, одна­ко исполь­зовать cron гораз­до про­ще. Все­го лишь напиши <code>crontab -e</code>, и в тек­сто­вом редак­торе откро­ется файл со спис­ком прог­рамм, которые запус­кают­ся в опре­делен­ное вре­мя. Фор­мат обыч­но опи­сан там же.</p>
  <h4 id="v6no">WWW</h4>
  <p id="WIYu">Сайт <a href="https://justpaste.it/redirect/394ty/https://crontab.guru/" target="_blank">crontab.guru</a> очень силь­но упро­щает работу с crontab.</p>
  <h3 id="qY7N">ИТОГИ</h3>
  <p id="pRqB">Про­дол­жать рас­ска­зывать о Linux мож­но прак­тичес­ки бес­конеч­но, одна­ко мы оста­вим это дру­гим стать­ям. Нашей целью не было заменить этим тек­стом серь­езные кни­ги по Linux. Мы лишь хотели дать необ­ходимый минимум тем, кто хочет начать пос­корее раз­бирать­ся на прак­тике. Наде­емся, что нам уда­лось снаб­дить тебя необ­ходимым набором началь­ных зна­ний, которые помогут тебе не заб­лудить­ся и не про­пасть в тем­ных зако­улках Linux!</p>
  <p id="5UM1"><a href="https://t.me/anon_chan_by" target="_blank">t.me/anon_chan_by</a></p>

]]></content:encoded></item><item><guid isPermaLink="true">https://teletype.in/@anon_channel/2v3pKTjDjsn</guid><link>https://teletype.in/@anon_channel/2v3pKTjDjsn?utm_source=teletype&amp;utm_medium=feed_rss&amp;utm_campaign=anon_channel</link><comments>https://teletype.in/@anon_channel/2v3pKTjDjsn?utm_source=teletype&amp;utm_medium=feed_rss&amp;utm_campaign=anon_channel#comments</comments><dc:creator>anon_channel</dc:creator><title>Внедрение кода в ехе-файл в конец секции без добавления API-функций.</title><pubDate>Sun, 14 Nov 2021 11:15:52 GMT</pubDate><media:content medium="image" url="https://img4.teletype.in/files/f9/7b/f97be5aa-dfe5-403b-9442-0153e3f8c532.jpeg"></media:content><description><![CDATA[<img src="https://wasm.in/attachments/000-jpg.4701/"></img>t.me/anon_chan_by]]></description><content:encoded><![CDATA[
  <p id="ZNhX"><a href="https://t.me/anon_chan_by" target="_blank">t.me/anon_chan_by</a></p>
  <p id="MrBZ"><strong>Алгоритм внедрения кода</strong><br />Технология внедрения кода в ехе-файл применяется для изменения исходного функционирования программы при отсутствии исходного текста программы.<br />При низкой подготовке хакера внедрение кода может вызвать проблемы и ошибки в приложениях. Эту технологию часто используют и вредоносные приложения. Фактически, внедрение кода – это грязный взлом.<br />Но в учебных целях технологию внедрения знать необходимо хотя бы по тому, что необходимо представлять этот механизм и противостоять ему.</p>
  <p id="Lulb">Сначала рассмотрим механизм внедрения кода без использования новых API-функций, т.к. при таком внедрении необходимо представлять все параметры внедряемых функций и способы их передачи. А это сильно усложняет процесс внедрения.</p>
  <p id="B3UV">В начале процесса внедрения необходимо подсчитать количество <em>свободных байт</em> в секции кода. Пример такого подсчета был изложен при рассмотрении РЕ-формата.</p>
  <p id="zu4t"><strong>Для внесения изменений </strong>в ехе-файл необходимо найти в программе <strong>свободное место. </strong>В простейшем случае, когда код внедрения небольшой и простой (т.е. не внедряются дополнительные API-функции) – его всегда можно найти в конце исполняемого ехе-файла (CodeCave).<strong> Механизм внедрения </strong>состоит в том, что сначала одну или две команды (в зависимости от необходимого количества байтов) необходимо скопировать и перенести в конец ехе-файла. А на их место поставить jmp на новый адрес, куда перенесена команда (команды). После написания в конце ехе-файла нового фрагмента последней командой необходимо также поставить команду jmp на адрес возврата – адрес первой неизмененной в начале ехе-файла команды.</p>
  <p id="cDB0"><strong>Алгоритм внедрения</strong> простейшего кода (без добавления API-функций) в ехе-файл может быть следующий:</p>
  <ol id="pIM6">
    <li id="VPvg">Подсчет числа свободных байтов в секции кода. Пример такого подсчета при помощи программы-анализатора LordPE был изложен при рассмотрении РЕ-формата.</li>
    <li id="yGOQ">Открываем в отладчике x64Dbg ранее полученный ехе-файл: Файл/Открыть.</li>
    <li id="bQbe">Выполняем программу, нажимая кнопку F9.Копируем одну (как правило) или две (для того, чтобы вставить команду jmp с адресом перехода) команды с начала программы.</li>
    <li id="hDBC">Копируем одну (как правило) или две (для того, чтобы вставить команду jmp с адресом перехода) команды с начала программы.</li>
    <li id="ZQDF">Вставляем скопированные команды с начала программы в конец файла и копируем адрес начала этого нового фрагмента.</li>
    <li id="8GUX">На освободившееся место в начале программы вставляем команду jmp c адресом на начало нового в конце кода фрагмента.</li>
    <li id="xMAk">Изменяем и/или дописываем необходимый код.</li>
    <li id="Ifbi">Последней командой в конце нового фрагмента должна быть команда jmp с адресом возврата – адресом первой не измененной в начале программы команды.</li>
    <li id="k48d">Сохраняем изменения.</li>
  </ol>
  <p id="68L7">Рассмотрим процесс внедрения на примере программы 4.1, в которой решается уравнение ab+c/d в среде masm64 и осуществляется вывод времени ее выполнения. Сначала напишем программу, получим ее ехе-файл и проанализируем его в отладчике x64Dbg.</p>
  <p id="TnkW"><strong>Программа 4.1.</strong> Решение уравнения ab+c/d в среде masm64 и вывод времени ее выполнения:<br />Код (ASM):</p>
  <ol id="AfW8">
    <li id="6y9c">include win64a.inc</li>
    <li id="UqTT">.data  ; директива начала сегмента данных</li>
    <li id="eTsg">a1 dq 1 ; резервирование в памяти 8 байтов для переменной Х</li>
    <li id="Yu0o">b1 dq 2 ;</li>
    <li id="8yGh">c1 dq 4 ;</li>
    <li id="A0Y3">d1 dq 2</li>
    <li id="FcUx">res1 dq ?</li>
    <li id="zjuw">titl db «Вывод через функцию MessageBox»,0; название упрощенного окна</li>
    <li id="D6CX">st1 dq ?,0  ; буфер выведения сообщения.</li>
    <li id="QyEN">ifmt db «Вывод чисел с памяти через MessageBox:»,10,9,»ab+c/d»,10,</li>
    <li id="fh5F">«a = %d»,10,»b = %d»,10,»c = %d»,10,»d = %d»,10,»res = %d»,10,10,</li>
    <li id="BYaf">«Время выполнения = %d тиков»,10,  ;</li>
    <li id="tBqi">«Автор программы:  НТУ ХПИ, каф. ВТП»,0 ;</li>
    <li id="UHMV">.code  ; директива начала сегментa команд</li>
    <li id="gMEd">WinMain proc</li>
    <li id="9Xpw">sub rsp,28h; cтек: 28h=32d+8; 8 — возврат</li>
    <li id="7JIr">mov rbp,rsp</li>
    <li id="HioC">rdtsc</li>
    <li id="WNnH">xchg rax,r15</li>
    <li id="1u1n">mov r10,a1 ; a:=1</li>
    <li id="YxNP">imul r10,r10,2 ; ab</li>
    <li id="xF9m">xor rdx,rdx  ; подготовка к делению</li>
    <li id="xJmD">mov rax,c1 ; c:=4</li>
    <li id="hQmS">mov r11,d1 ; d:=2</li>
    <li id="ilv9">div r11  ; c/d</li>
    <li id="ONKV">add rax,r11 ; ab+c/d</li>
    <li id="mgEh">mov res1,rax</li>
    <li id="QGA4">rdtsc</li>
    <li id="QfsD">sub rax,r15</li>
    <li id="7lGM">invoke wsprintf,ADDR st1,ADDR ifmt,a1,b1,c1,d1,res1,rax</li>
    <li id="VyZb">invoke MessageBox,0,addr st1,addr titl,MB_ICONINFORMATION;</li>
    <li id="DQ7G">invoke RtlExitUserProcess,0 ;возвращение упр. ОС и освобожд. ресурсов</li>
    <li id="MRjY">WinMain endp</li>
    <li id="H4uE">end</li>
  </ol>
  <p id="DOgO">Результат выполнения программы приведен на рис.</p>
  <figure id="Bntt" class="m_original">
    <img src="https://wasm.in/attachments/000-jpg.4701/" width="322" />
  </figure>
  <p id="6wEd">Алгоритм программы – линейный, переходы отсутствуют</p>
  <figure id="zDFL" class="m_original">
    <img src="https://wasm.in/attachments/001-jpg.4702/" width="392" />
  </figure>
  <p id="UOcS">При анализе алгоритма видно, что в начале программы располагаются две команды, которые предназначены для резервирования стека и его выравнивания на границу, кратную 16 байтам.</p>
  <p id="i3Pb">Первая команда программы – это rdtsc. Команда rdtsc – ассемблерная инструкция, которая читает счётчик TSC (<em>Time Stamp Counter</em>) и возвращающая в регистрах RDX:RAX количество тактов с момента последнего сброса процессора.<br />Команда rdtsc чаще всего используется:</p>
  <ul id="6xTk">
    <li id="ZhcB">для измерения времени;</li>
    <li id="ZRm2">для точного измерения временных интервалов, в том числе при проведении оптимизации (измерение времени, необходимого для выполнения конкретных инструкций или их набора);</li>
    <li id="FQNn">в антиотладочных целях;</li>
    <li id="lVqd">как источник энтропии для генераторов псевдослучайных чисел.</li>
  </ul>
  <p id="Kzem">Содержимое ячеек памяти, которые указаны в программе можно просмотреть, если нажать правую кнопку мыши и выбрать Перейти к дампу/ Константа.</p>
  <p id="0RX8">Рассмотрим внедрение нового кода в предыдущий пример. В качестве кода внедрения заменим арифметические операции на логические. Для упрощения программы фукционал и начальные условия оставим прежние.</p>
  <p id="2F8m">Первоначальный вариант изменяем на новый, но с использования вместо команд умножения и деления логических команд, который может быть таким: Код (ASM):</p>
  <ol id="hAWZ">
    <li id="xyjx">mov r10,1 ;</li>
    <li id="BlU8">sal r10,1  ; сдвиг влево на 1 разряд – умножение на 2</li>
    <li id="CJUO">mov r11,4  ;</li>
    <li id="oJUr">sar r11,1  ; сдвиг вправо на 1 разряд – деление на 2</li>
    <li id="TLS2">add r10,r11 ; результат операции ab + c/d</li>
    <li id="e61e">mov res1,r10</li>
  </ol>
  <p id="DyjH"><em>Необходимо обратить внимание</em> на команду занесения результата в ячейку памяти, например res1: mov res1,r10. Для записи такой команды в отладчик x64Dbg (в ехе-файл) сначала необходимо выяснить адрес ячейки памяти, а потом применить запись в виде:<br />mov qword ptr ds:[7FF6478B3020],r10<br />Фрагмент кода с применением логических команд всегда короче, а отсутствие «тяжелых» команд умножения и деления позволяет выполнить этот фрагмент намного быстрее. В рассматриваем примере, если вырезать старый функционал, то новый функционал вместится на его место. Но так бывает не всегда. Для простоты рассмотрения новый функционал разместим в конце ехе-файла. Естественно, что в таком случае необходимо проверить объем свободного места в секции программами-анализаторами РЕ-формата. Но и этот вопрос отложим для последующего рассмотрения. Будем считать, что для нашего простого внедрения места вполне достаточно.</p>
  <p id="SG40">Действия по внедрению простейшего кода (без добавления API-функций) в ехе-файл следующие:</p>
  <ol id="80yX">
    <li id="xQUb">Открываем в отладчике x64Dbg ранее полученный ехе-файл: Файл/ Открыть.</li>
    <li id="3mWt">Выполняем программу, нажимая кнопку <strong>F9</strong>.</li>
    <li id="4bEy">Определяем, какие команды удалить (или скопировать, если надо) как старый функционал, чтобы освободить место для команды <em>jmp</em>.<br />Если необходимо только скопировать дизассемблерный код, то выполняем действия: Shift + правая клавиша мышки (для выбора нескольких команд); «Копировать»/ «Дизассемблерный код».<br />Сначала устанавливаем курсор на первую команду,</li>
    <li id="z00v">00007FF69013100B 4C:8B15 EE1F0000 mov r10,qword ptr ds:[7FF690133000]которую хотим переместить и дважды нажимаем на левую клавишу мыши.<br />Выделенная команда имеет размерность в 7 байт. Вводим на первой выбранной команде пустую команду <em>nop</em>. Команда nop имеет размерность один байт. Для того, чтобы произошло автоматическое заполнение командами nop всех байт уничтожаемой команды необходимо поставить галочку Сохранить размер во всплывающем окне (рис. 4.3).</li>
    <li id="YCI4">По очереди выделяем следующие команды, дважды нажимаем левую клавишу мыши, набираем команду nop и нажимаем OK.</li>
    <li id="FaZj">Пропускаем 4-й шаг алгоритма, т.к. по условию задачи не надо оставлять старый функционал.</li>
    <li id="dv4W">Вставляем команду jmp c адресом на адрес начала фрагмента нового в конце кода. Для этого ставим курсор после последней команды<br />call qword ptr ds:[&lt;&amp;RtlExitUserProcess&gt;]<br />Копируем адрес свободной ячейки. Для этого нажимаем на ней правую кнопку мыши и выбираем Копировать/ Адрес.</li>
    <li id="Rwx8">После этого, ставим курсор в начало кода после команды<br />xchg rcx,rax<br />на первую пустую команду <em>nop</em>.<br />Дважды нажимаем правую клавишу мыши и в появившемся окне вводим слово <em>jmp</em>, затем пробел и вставляем адрес на свободную ячейку в конце программы сочетанием клавиш <strong>Ctrl + C</strong> </li>
    <li id="6EMa">Нажимаем <strong>OK</strong>. Команда <em>jmp 7FF6BC9010A4</em> вставилась.</li>
    <li id="nfCT">Дописываем необходимый код. Для этого, в конце программы, на свободный адрес (<em>00007FF6BC9010A4</em>), на который будем переходить командой <em>jmp </em>ставим курсор мыши. Дважды нажимаем левую клавишу мыши и вводим сначала первую новую команду с новым функционалом). А затем – и все остальные.<br />Последней командой в конце нового фрагмента должна быть команда jmp с адресом возврата – адресом первой неизмененной в начале программы команды.<br />Для того, чтобы не записывать адрес возврата вручную, выделим команду в начале кода, на которую планируем возвратиться. Этой командой будет:</li>
    <li id="gYm5">00007FF7BF051034 0F31 rdtscДля этого нажимаем на ней правую кнопку мыши и выбираем Копировать/ Адрес. Необходимый адрес скопируется в буфер.<br />В результате, новый блок кода будет иметь вид </li>
    <li id="8Aiz">Необходимо сохранить внесенные изменения. Это можно сделать двумя способами.</li>
  </ol>
  <p id="wOwc">Первый способ: выбираем Файл/ Исправить файл. В новом окне выбрать пункт Исправить файл. Затем – новое имя и расширение ехе. Для того, чтобы иметь возможность вернуться и загрузить наиболее правильную исправленную версию необходимо сохранять изменения и давать каждый раз новые имена или индексы к ним для сохраненных ехе-файлов.</p>
  <p id="oTM5">Второй способ: выбрать пиктограмму с названием Исправления, нажать на кнопку Исправить файл, а далее новое имя и расширение ехе.<br />После проведенных преобразований новый ехе-файл выводит сообщение, которое в дальнейшем можно тоже изменить.</p>
  <figure id="3rL3" class="m_original">
    <img src="https://wasm.in/attachments/005-jpg.4710/" width="153" />
  </figure>
  <p id="neh2">Можно изменить и текстовые сообщения.<br />Для внесения изменений в упрощенное окно вывода информации можно использовать функцию преобразования wsprintf. Это позволит также внести изменения в вывод информации в самом окне.<br />При передаче параметров в функции <em>wsprintf</em></p>
  <ul id="mp7s">
    <li id="W7GB">первым параметром является параметр ADDR st1, который передается функции через регистр RCX.</li>
    <li id="rpOc">Второй параметр – это ADDR ifmt – строка форматирования, который передается через регистр RDX.</li>
    <li id="tdOH">Третий параметр – Z – передается через регистр R8.</li>
    <li id="iYju">Четвертый параметр – X – передается через регистр R9.</li>
    <li id="99Gg">Остальные параметры передаются через стек. Например, пятый – параметр Y – через [rsp + 20h]. Шестой – параметр rax – через [rsp + 28h] и т.д.</li>
  </ul>
  <p id="CQej">Можно внести изменения и в функцию <em>MessageBox</em>. Эта функция предназначена для вывода сообщений. В ней можно поменять и титул упрощенного окна, и непосредственное сообщение.<br />Для внесения изменений в вывод информации необходимо воспользоваться таблицей кодировки символов страницы кодировки 1251, например <a href="http://foxtools.ru/ASCII#1251" target="_blank">http://foxtools.ru/ASCII#1251</a> </p>
  <figure id="OEvx" class="m_original">
    <img src="https://wasm.in/attachments/006-jpg.4706/" width="886" />
  </figure>
  <p id="llhk">Будем менять второй параметр функции wsprintf – это ADDR ifmt – строка форматирования, который передается через регистр RDX.<br />Для этого, выделяем правой кнопкой мыши строку с передачей второго параметра<br />lea rdx,qword ptr ds:[7FF608483057]<br />и выбираем Перейти к дампу/ Константа.</p>
  <p id="dzOi">После того, как в дампе памяти будет отображаться содержимое, начиная с адреса 7FF608483057,необходимо подвести курсор к тем байтам дампа памяти, которые будем менять. Дважды нажать левую клавишу мышки на ячейке дампа памяти и в появившемся окне исправляем кодировку символов </p>
  <figure id="y4Ns" class="m_original">
    <img src="https://wasm.in/attachments/007-jpg.4707/" width="410" />
  </figure>
  <p id="vqzU">Наиболее часто применяемый символ – это символ пробела. Он имеет кодировку = 20. Этой кодировкой можно затереть всю ненужную информацию. А более практично – это написать любой текст, например, слово Инфицировано, каждая буква которого кодируется соответствующим символом, а все слово пишется как C8 ED F4 E8 F6 E8 F0 EE E2 E0 ED EE. Для изменения нескольких подряд расположенных байтов в дампе памяти удобнее мышкой выделить эти значения, нажать на правую клавишу мышки Двоичные операции/Заполнить и ввести новую текстовую информацию </p>
  <figure id="ujPJ" class="m_original">
    <img src="https://wasm.in/attachments/008-jpg.4708/" width="396" />
  </figure>
  <p id="fKeQ">Окно с окончательным результатом внедрения приведено на рис. </p>
  <figure id="LYoM" class="m_original">
    <img src="https://wasm.in/attachments/009-jpg.4709/" width="148" />
  </figure>
  <p id="oq77">Таким образом, после проведенного внедрения кода можно сделать выводы:</p>
  <ul id="0kez">
    <li id="0COf">проще внедрять изменения в окончательную функцию вывода информации. В рассматриваемом примере – это функция <em>MessageBox</em>;</li>
    <li id="6aLh">после каждого законченного этапа внедрения обязательно делать сохранение ехе-файла и каждый раз с новым именем или с индексом для его расширения.</li>
  </ul>
  <p id="HVbO"><a href="https://t.me/anon_chan_by" target="_blank">t.me/anon_chan_by</a></p>

]]></content:encoded></item><item><guid isPermaLink="true">https://teletype.in/@anon_channel/okPXD17gNMG</guid><link>https://teletype.in/@anon_channel/okPXD17gNMG?utm_source=teletype&amp;utm_medium=feed_rss&amp;utm_campaign=anon_channel</link><comments>https://teletype.in/@anon_channel/okPXD17gNMG?utm_source=teletype&amp;utm_medium=feed_rss&amp;utm_campaign=anon_channel#comments</comments><dc:creator>anon_channel</dc:creator><title>Как стать хакером: гайд по основам для новичков</title><pubDate>Fri, 12 Nov 2021 10:48:03 GMT</pubDate><media:content medium="image" url="https://img2.teletype.in/files/57/c4/57c46f6a-941e-4e44-a603-332553711a81.jpeg"></media:content><description><![CDATA[<img src="https://media.proglib.io/wp-uploads/2018/01/wannabe-h.jpg"></img>t.me/anon_chan_by]]></description><content:encoded><![CDATA[
  <p id="pHAz"><a href="https://t.me/anon_chan_by" target="_blank">t.me/anon_chan_by</a></p>
  <p id="a6rX">Хакерство - это поиск уязвимостей в сети или компьютере с целью получения доступа. Стать хакером непросто, и в этой статье мы затронем основы.</p>
  <p id="YtxR">Чтобы стать хакером, необходимы глубокие знания языков программирования, методов взлома, поиска уязвимостей, устройства сетей, операционных систем и проч. Также у вас должен быть творческий тип мышления. Вы должны быстро адаптироваться под ситуацию, находить нестандартные решения, проявлять креативность.</p>
  <figure id="KEsY" class="m_custom">
    <img src="https://media.proglib.io/wp-uploads/2018/01/wannabe-h.jpg" width="1600" />
  </figure>
  <p id="N4EF">Если описанные выше навыки можно развить со временем, то чтобы понять, например, устройство MySQL или научиться работать с PGP-шифрованием, придется много учиться. И долго.</p>
  <h1 id="DJhz">Чтобы стать хакером, вам нужно:</h1>
  <h3 id="Изучите-и-используйте-UNIX-систему,-например,-Ubuntu-или-MacOS">Изучить и использовать UNIX-систему, например, Ubuntu или MacOS</h3>
  <p id="UnV9">Изначально UNIX-системы были предназначены для программистов, разрабатывающих ПО, а не для пользователей, которые никак не относятся к сфере IT. UNIX-системы - это системы, на которых стоит почти весь Интернет, т. к. в качестве сервера в основном используют их же (чаще всего Debian и Ubuntu). Вы не можете стать хакером, не изучив их и не научившись работать с терминалом.</p>
  <h4 id="Для-пользователей-Windows">Для пользователей Windows</h4>
  <p id="dWch">Если вы используете Windows, для вас есть хорошая новость: не надо удалять текущую систему и форматировать диск. Есть несколько вариантов работы с Linux:</p>
  <ol id="qfaJ">
    <li id="jB0G">Изучите VirtualBox (программа-эмулятор для операционной системы). Изучив его, вы сможете запускать операционную систему в операционной системе. Звучит страшно, но программа бывает очень полезна.</li>
    <li id="EiBB">Установите Linux рядом с Windows. Если вы всё сделаете правильно, загрузчики систем не будут конфликтовать. Делается это довольно просто: есть много мануалов в Интернете.</li>
  </ol>
  <h3 id="Изучите-язык-разметки-HTML">Изучить язык разметки HTML</h3>
  <p id="y0iX">Если вы ещё не знакомы с программированием, <s>тогда я вообще не понимаю, что вы делаете тут</s> тогда у вас есть отличная возможность начать свой путь с изучения <a href="https://www.w3schools.com/html/" target="_blank">Hyper Text Mark-Up Language</a>. Независимо от того, что вы видите на сайте, знайте, что всё это HTML.</p>
  <p id="DlHx">Приведу пример использования HTML, пусть он и немного связан с PHP. В начале 2015 года была обнаружена уязвимость в теме WordPress, позволяющая закачивать производные (исполнительные) файлы на сервер. Файл, в котором была найдена уязвимость - admin/upload-file.php. Вот он:</p>
  <pre id="6ikV" data-lang="php">&lt;?php
 
//Upload Security
 
$upload_security = md5($_SERVER[&#x27;SERVER_ADDR&#x27;]);
 
$uploaddir = &#x27;../uploads/&#x27;;
 
if($_FILES):
 
    foreach($_FILES as $file):
 
         $file = $uploaddir . basename($file[&#x27;name&#x27;]);
    
         if (move_uploaded_file($_FILES[$upload_security][&#x27;tmp_name&#x27;], $file)) {
             echo &quot;success&quot;;
         } else {
             echo &quot;error&quot;.$_FILES[$upload_security][&#x27;tmp_name&#x27;];
         }
 
    endforeach;
 
endif;
 
?&gt;</pre>
  <p id="8WMh">Чтобы сделать форму отправки для этого файла, нужно знать HTML. Отправив файл, который, к примеру, вытаскивает все пароли или даёт доступ к базе данных, вы вольны делать с веб-сервисом всё, что вам угодно.</p>
  <p id="iWnQ">Итак, знание HTML нужно для того, чтобы:</p>
  <ol id="Pv0l">
    <li id="7oOs">Искать уязвимости веб-ресурсов.</li>
    <li id="CK9L">Использовать эти уязвимости.</li>
  </ol>
  <h3 id="Изучите-несколько-языков-программирования">Изучить несколько языков программирования</h3>
  <p id="30wv">Как мы все знаем, чтобы нарушать правила, нужно для начала знать их. Этот же принцип работает для программирования: чтобы взломать чей-то код, вы должны знать, как работают языки программирования, и самому уметь программировать. Некоторые из наиболее рекомендуемых ЯП для изучения:</p>
  <ul id="si2E">
    <li id="MoB0"><strong>Python :</strong> это, пожалуй, самый лучший язык для веб-разработки. На нём написаны два крупных фреймворка, на которых создано огромное кол-во веб-приложений, это Flask и Django. Язык хорошо построен и задокументирован. Самое главное, что его очень просто выучить. К слову, много разработчиков используют Python для создания простой и полной автоматизации.</li>
    <li id="qCWu"><strong>C++ : </strong>язык, использующийся в промышленном программировании. Его преподают в школах, вузах. На нём пишутся сервера. Рекомендую начать изучение языков с него, т. к. он содержит в себе все принципы ООП. Научившись работать с ним, вы с лёгкостью освоите другие языки.</li>
    <li id="1icl"><strong>JavaScript, JQuery : </strong>в основном, практически все сайты используют JS и JQuery. Необходимо знать, что на этих сайтах зависит от JS, например, формы для ввода паролей. Ведь некоторые сайты не дают выделить и скопировать некоторую информацию, не дают скачать файл или просмотреть содержимое, однако, чтобы сделать это, достаточно отключить JS в браузере. Ну а чтобы отключить JavaScript, нужно знать: а) в каких ситуациях работа (защита) сайта зависит от него; б) как JavaScript подключается и какими способами можно блокировать работу скриптов.</li>
    <li id="w6rs"><strong>SQL :</strong> самое интересное. Все пароли, личные данные, хранятся в базах данных, написанных на SQL. Самая распространённая система управления БД - MySQL. Чтобы понять, как использовать MySQL-инъекцию, нужно знать, что такое MySQL-инъекция. Чтобы уловить суть MySQL-инъекции, нужно знать, что такое MySQL-запросы, каков синтаксис этих запросов, каково устройство базы данных, как хранятся данные, что такое таблицы и т. д.</li>
  </ul>
  <h3 id="Изучите-устройства-сетей">Изучить устройства сетей</h3>
  <p id="58H2">Вы должны чётко понимать устройства сетей и принципы их работы, если хотите стать хакером. Важно понять, как создаются сети, понять различие между протоколами TCP/IP и UDP и проч. Узнайте, какой сетью пользуетесь вы. Научитесь настраивать её. Выясняйте возможные векторы атаки.</p>
  <p id="whpF">Имея глубокие знания о различных сетях, вы сможете использовать их уязвимости. Также вам необходимо понять устройство и принцип работы веб-сервера и веб-сайта.</p>
  <h3 id="Изучите-криптографию">Изучить <a href="https://proglib.io/p/cryptography/" target="_blank">криптографию</a></h3>
  <p id="CRqW">Это неотъемлемая часть обучения. Необходимо понимать алгоритмы различных шифров, например, SHA-512, алгоритм OpenSSL и проч. Также нужно разобраться с хешированием. Криптография используется везде: пароли, банковские карты, криптовалюты, торговые площадки и проч.</p>
  <h3 id="Kali-Linux:-некоторый-полезный-софт">Kali Linux: некоторый полезный софт</h3>
  <ul id="eGBR">
    <li id="Fscs"><strong>NMAP :-</strong> <a href="https://nmap.org/" target="_blank">Nmap (“Network Mapper”)</a> бесплатная open-source программа, которая является предустановленной в Kali. Написана <a href="https://en.wikipedia.org/wiki/Gordon_Lyon" target="_blank">Gordon Lyon</a> (также известен под псевдонимом <em>Fyodor Vaskovich</em>). Она нужна для обнаружения хостов и различных сервисов, создавая таким образом &quot;карту сети&quot;. Она используется для проверки сети или аудита безопасности, для быстрого сканирования больших сетей, хотя она отлично работает с одиночными хостами. Программное обеспечение предоставляет ряд функций для исследование компьютерных сетей, включая обнаружение узлов и операционной системы. Nmap использует необработанные IP-пакеты чтобы определить, какие хосты доступны в сети, какие службы (имя и версия приложения) эти хосты предлагают, какие ОС они запускают, какие типы фильтров пакетов/файрволлы используют, а также десятки других характеристик.</li>
    <li id="4ioE"><strong>Aircrack-Ng :-</strong> <a href="https://www.aircrack-ng.org/" target="_blank">Aircrack</a> - это одна из самых популярных программ для взлома WEP/WPA/WPA2 протокола. Комплект Aircrack-ng содержит инструменты для захвата пакетов и &quot;рукопожатий&quot;, деавторизации подключённых пользователей, создания трафика и инструментов для брутфорса сети и атак по словарю.</li>
  </ul>
  <h1 id="xws4">Заключение</h1>
  <p id="44mJ">В этой статье мы разобрались в основах, без которых вы вряд ли сможете стать хакером. К слову о трудоустройстве. Как правило, люди, занимающиеся информационной безопасностью либо работают фрилансерами, выполняя заказы частных лиц, либо работают на компанию, обеспечивая безопасность хранящихся данных, выполняют работу системного администратора, etc.</p>
  <p id="uViK"><a href="https://t.me/anon_chan_by" target="_blank">t.me/anon_chan_by</a></p>

]]></content:encoded></item><item><guid isPermaLink="true">https://teletype.in/@anon_channel/wz1TQ5gpB1E</guid><link>https://teletype.in/@anon_channel/wz1TQ5gpB1E?utm_source=teletype&amp;utm_medium=feed_rss&amp;utm_campaign=anon_channel</link><comments>https://teletype.in/@anon_channel/wz1TQ5gpB1E?utm_source=teletype&amp;utm_medium=feed_rss&amp;utm_campaign=anon_channel#comments</comments><dc:creator>anon_channel</dc:creator><title>На страже ядра. Обнаруживаем руткиты с помощью нового плагина DRAKVUF</title><pubDate>Thu, 11 Nov 2021 08:13:51 GMT</pubDate><media:content medium="image" url="https://img2.teletype.in/files/51/6c/516c9336-7689-4359-be6b-6d5ef8649101.jpeg"></media:content><description><![CDATA[<img src="https://justpaste.it/img/759ba8b4c02c5b48b72a42475aaab9b4.png"></img>Ча­ще все­го при ана­лизе поведе­ния подоз­ритель­ной прог­раммы наб­люда­ют за поль­зователь­ским режимом, а код в ядре оста­ется вне поля зре­ния ана­лити­ка. Отчасти это пра­виль­но, пос­коль­ку боль­ше все­го вре­донос­ной деятель­нос­ти ведет­ся имен­но в поль­зователь­ском прос­транс­тве. Тем не менее вре­донос­ный код в ядре может нанес­ти боль­ше ущер­ба, и его слож­нее обна­ружить. Одна­ко это воз­можно.]]></description><content:encoded><![CDATA[
  <h3 id="BWJw">Содержание статьи</h3>
  <ul id="RNAg">
    <li id="ZmUl">Техники</li>
    <li id="yPEN">Inline-перехваты</li>
    <li id="44KA">Перехват таблицы системных вызовов</li>
    <li id="xWtI">Перехваты IDT/GDT</li>
    <li id="kl7n">MSR LSTAR</li>
    <li id="u3zR">Перехваты функций DRIVER_OBJECT</li>
    <li id="Ia6g">Техника сокрытия процесса от Task Manager</li>
    <li id="pkVV">Регистрация системных функций обратного вызова</li>
    <li id="mqlu">Заключение</li>
  </ul>
  <p id="uwlb">Ча­ще все­го при ана­лизе поведе­ния подоз­ритель­ной прог­раммы наб­люда­ют за поль­зователь­ским режимом, а код в ядре оста­ется вне поля зре­ния ана­лити­ка. Отчасти это пра­виль­но, пос­коль­ку боль­ше все­го вре­донос­ной деятель­нос­ти ведет­ся имен­но в поль­зователь­ском прос­транс­тве. Тем не менее вре­донос­ный код в ядре может нанес­ти боль­ше ущер­ба, и его слож­нее обна­ружить. Одна­ко это воз­можно.</p>
  <p id="y0xb">С появ­лени­ем KPP (Kernel Patch Protection), или сок­ращен­но PatchGuard, в Windows ста­ло слож­нее модифи­циро­вать ядро без пос­ледс­твий. Если рань­ше, нап­ример, таб­лицу сис­темных вызовов с целью филь­тра­ции сис­темных вызовов перех­ватыва­ли даже такие легитим­ные прог­раммы, как анти­виру­сы, то с появ­лени­ем KPP это ста­ло не так прос­то. Тем не менее для рут­китов PatchGuard не пред­став­ляет осо­бой угро­зы, пос­коль­ку тех­ники его обхо­да мож­но най­ти в откры­том дос­тупе, они раз­вива­ются и акту­аль­ны по сей день. В этой статье будет рас­смат­ривать­ся мно­жес­тво тех­ник модифи­кации ядра, вклю­чая те, что обна­ружи­вает PatchGuard, на при­мере нового пла­гина для DRAKVUF — rootkitmon.</p>
  <p id="pFG0">Мы уже нес­коль­ко лет раз­рабаты­ваем песоч­ницу для рис­кори­енти­рован­ной защиты, исполь­зующую фрей­мворк DRAKVUF. DRAKVUF — безаген­тная песоч­ница, осно­ван­ная на биб­лиоте­ке LIBVMI и гипер­визоре XEN. Все воз­можнос­ти DRAKVUF реали­зова­ны в пла­гинах. Каж­дый из двад­цати с лиш­ним пла­гинов выпол­няет опре­делен­ную работу: для обна­руже­ния дос­тупа к фай­лам есть пла­гин filetracer, для трас­сиров­ки сис­темных вызовов — пла­гин syscalls. Rootkitmon — новый пла­гин, поз­воля­ющий отсле­живать вре­донос­ную активность в ядре средс­тва­ми DRAKVUF.</p>
  <p id="sZiT">Су­щес­тву­ет мно­жес­тво опре­деле­ний понятия «рут­кит», мы же будем опи­рать­ся на сле­дующее: «компь­ютер­ная прог­рамма, которая исполь­зует недоку­мен­тирован­ные и (или) зап­рещен­ные тех­ники для манипу­ляции ядром опе­раци­онной сис­темы в сво­их целях».</p>
  <h3 id="GbBt">ТЕХНИКИ</h3>
  <p id="8e8G">В «джен­тель­мен­ский набор» пла­гина вхо­дят воз­можнос­ти детек­тировать сле­дующие типы перех­ватов:</p>
  <ul id="c1VF">
    <li id="Hca0">мо­дифи­кация кода заг­ружен­ных драй­веров в памяти (inline-перех­ваты);</li>
    <li id="xjRA">мо­дифи­кация таб­лиц сис­темных вызовов, таб­лиц пре­рыва­ний и таб­лиц дес­крип­торов;</li>
    <li id="Jnyy">мо­дифи­кация регис­тра <code>MSR LSTAR</code>;</li>
    <li id="EuwN">мо­дифи­кация ука­зате­лей на фун­кции <code>DRIVER_OBJECT</code>, стек <code>DEVICE_OBJECT</code>;</li>
    <li id="HXE0">сок­рытие про­цес­са из спис­ка <code>EPROCESS</code>;</li>
    <li id="eTmC">ре­гис­тра­ция раз­личных сис­темных фун­кций обратно­го вызова.</li>
  </ul>
  <p id="vfG2">Пос­коль­ку рут­китов нам­ного мень­ше, чем вре­донос­ного ПО в поль­зователь­ском прос­транс­тве, и вре­мя выпол­нения образца всег­да огра­ничен­но, умень­шение наг­рузки пла­гина на работа­ющую сис­тему было при­ори­тет­ной задачей. Для это­го во мно­гих слу­чаях было решено све­рять целос­тность кри­тичес­ких струк­тур в начале ана­лиза и в кон­це, а не выпол­нять непос­редс­твен­ный перех­ват на запись стра­ниц памяти.</p>
  <h3 id="oRlz">Inline-перехваты</h3>
  <p id="Uicg">Рас­смот­рим самый рас­простра­нен­ный тип перех­ватов и, воз­можно, самый лег­ко обна­ружи­ваемый — inline-перех­ваты. Inline-перех­ваты очень популяр­ны, и даже Microsoft пре­дос­тавля­ет воз­можность перех­ватить API-биб­лиоте­ки, добав­ляя перед фун­кци­ями двух­бай­товый про­лог вро­де mov edi, edi для быс­тро­го редак­тирова­ния фун­кци­ональ­нос­ти уже заг­ружен­ных и работа­ющих ком­понен­тов. Конеч­но, такие перех­ваты воз­можны толь­ко в поль­зователь­ском режиме, а в ядре кара­ются синим экра­ном с кодом ошиб­ки <code>0x109</code>, если PatchGuard не вык­лючен.</p>
  <p id="t6e1">Inline-перех­ваты обыч­но сос­тоят из трех час­тей:</p>
  <ul id="2LcJ">
    <li id="Ypht">под­мена пер­вых нес­коль­ких инс­трук­ций целевой фун­кции для перенап­равле­ния потока выпол­нения на код сво­его при­ложе­ния;</li>
    <li id="D5zy">об­работ­ка целевой фун­кции: изме­нение парамет­ров, филь­тра­ция, логиро­вание;</li>
    <li id="0tiI">вы­пол­нение под­менен­ных инс­трук­ций и воз­врат на ори­гиналь­ную фун­кцию.</li>
  </ul>
  <p id="whK6">Рас­смот­рим прос­той при­мер вызова <code>CreateFileW</code> из биб­лиоте­ки <code>kernel32.dll</code>. Прой­дя все биб­лиоте­ки, в ито­ге код ока­жет­ся в ядер­ной фун­кции <code>nt!NtCreateFile</code>. Если бы рут­кит уста­новил перех­ват на эту фун­кцию, он бы мог выг­лядеть сле­дующим обра­зом.</p>
  <figure id="2P1f" class="m_original">
    <img src="https://justpaste.it/img/759ba8b4c02c5b48b72a42475aaab9b4.png" width="853" />
  </figure>
  <p id="gegp">Пос­коль­ку код находит­ся в стра­ницах с пра­вами толь­ко на чте­ние и выпол­нение, для записи в такие стра­ницы необ­ходимо либо выделить новую вир­туаль­ную стра­ницу с пра­вами на запись и спро­еци­ровать ее на физичес­кую стра­ницу, где находит­ся код, либо отклю­чить бит Write Protect в спе­циаль­ном регис­тре управле­ния <code>CR0</code>, что поз­волит выпол­нять запись в стра­ницы в обход их прав для текуще­го ядра.</p>
  <figure id="Ymls" class="m_original">
    <img src="https://justpaste.it/img/741ab47aaeaba3dede0ac1a2f3ede8bc.png" width="515" />
  </figure>
  <figure id="gXSJ" class="m_original">
    <img src="https://justpaste.it/img/8cb33970db24c89ff5787f968db891be.png" width="795" />
  </figure>
  <p id="8pjg">Об­наруже­ние таких перех­ватов сво­дит­ся к под­сче­ту кон­троль­ной сум­мы сек­ций драй­вера в момент начала ана­лиза и перес­чету, свер­ке кон­троль­ной сум­мы в кон­це. В отли­чие от PatchGuard, который защища­ет толь­ко неболь­шой спи­сок сис­темных драй­веров, мы можем про­верять абсо­лют­но все заг­ружен­ные драй­веры из спис­ка <code>PsLoadedModules</code>.</p>
  <p id="Scmr"><code>PsLoadedModules</code> — двус­вязный спи­сок струк­тур <code>_KLDR_DATA_TABLE_ENTRY</code>, опи­сыва­ющих заг­ружен­ный драй­вер: его базовый адрес, раз­мер, имя, харак­терис­тики и про­чее.</p>
  <figure id="xCzw" class="m_original">
    <img src="https://justpaste.it/img/5b112d63f1d9ae21221e0282ba68c26b.png" width="1367" />
  </figure>
  <figure id="W9MQ" class="m_original">
    <img src="https://justpaste.it/img/c28c0f4fc83f8d6aaf26294947a08bef.png" width="515" />
  </figure>
  <p id="f8DG">Для перечис­ления заг­ружен­ных модулей ядра с помощью DRAKVUF API мы реали­зова­ли метод <code>drakvuf_enumerate_drivers</code>. В пла­гине rootkitmon спи­сок <code>PsLoadedModules</code> про­ходит­ся два раза: в начале ини­циали­зации пла­гина — для под­сче­та кон­троль­ных сумм сек­ций драй­веров — и в кон­це — для срав­нения зна­чений.</p>
  <figure id="3cSo" class="m_original">
    <img src="https://justpaste.it/img/9158ec6a848c05cf23e97ac0c928feb4.png" width="942" />
  </figure>
  <p id="sFh9">В слу­чае рас­хожде­ния в логе появит­ся стро­ка:</p>
  <p id="qyHi"><code>&quot;\Device\HarddiskVolume2\Windows\System32\explorer.exe&quot;:KiDeliverApc SessionID:0 PID:1968 PPID:476 Reason:&quot;Driver section modification&quot; Driver:&quot;ntoskrnl.exe&quot;</code></p>
  <p id="Roiw">Для отра­бот­ки в кон­це ана­лиза мы добав­ляем перех­ват час­то вызыва­емой ядер­ной фун­кции <code>KiDeliverApc</code>. Пос­коль­ку мы заранее не зна­ем, какой поток вызовет эту фун­кцию и в каком кон­тек­сте про­цес­са этот поток находил­ся, имя про­цес­са, его PID и PPID, которые DRAKVUF авто­мати­чес­ки сох­раня­ет в жур­нале, не име­ют отно­шения к детек­ту, в то вре­мя как поле Reason и все поля, сле­дующие за ним, име­ют. В дан­ном слу­чае поле Reason озна­чает обна­ружен­ную вре­донос­ную тех­нику, а поле Driver — наз­вание модифи­циро­ван­ного драй­вера.</p>
  <h3 id="iy1Z">Перехват таблицы системных вызовов</h3>
  <p id="hbzQ">SSDT (System Service Descriptor Table) — мас­сив ука­зате­лей на обра­бот­чики сис­темных вызовов в 32-бит­ных сис­темах или спи­сок сме­щений отно­ситель­но базово­го адре­са таб­лицы на 64-бит­ных ОС. Как говори­лось ранее, до появ­ления PatchGuard эта таб­лица активно исполь­зовалась легитим­ными прог­рамма­ми, а так­же рут­китами для филь­тра­ции и монито­рин­га сис­темных вызовов. Переза­пись одно­го ука­зате­ля в такой таб­лице рав­носиль­на перех­вату всех вызовов опре­делен­ного обра­бот­чика, что нам­ного про­ще inline-перех­ватов, рас­смот­ренных до это­го.</p>
  <p id="Ehrt">На дан­ный момент в ОС Windows сущес­тву­ет два таких мас­сива под сим­волами <code>nt!KiServiceTable</code> и <code>win32k!W32pServiceTable</code> для сис­темных вызовов к модулю <code>ntoskrnl.exe</code> и гра­фичес­кой под­систе­ме <code>win32k.sys</code> соот­ветс­твен­но. Количес­тво эле­мен­тов в этих мас­сивах сох­ранено в перемен­ных <code>nt!KiServiceLimit</code> и w<code>in32k!W32pServiceLimit</code>.</p>
  <figure id="Dpxp" class="m_original">
    <img src="https://justpaste.it/img/087583730085ab987eae13880255a43b.png" width="481" />
  </figure>
  <p id="ljYO">Ука­затель на SSDT находит­ся в спе­циаль­ной струк­туре <code>KSYSTEM_SERVICE_TABLE</code>, или <code>SST</code>, под име­нем <code>ServiceTableBase</code>:</p>
  <h4 id="ZNp0">Опи­сание струк­туры KSYSTEM_SERVICE_TABLE</h4>
  <p id="E4Q0"><code>typedef struct _KSYSTEM_SERVICE_TABLE</code></p>
  <p id="qT58"><code>{</code></p>
  <p id="1l58"><code>PULONG ServiceTableBase;</code></p>
  <p id="oSBN"><code>PULONG ServiceCounterTableBase;</code></p>
  <p id="Dykz"><code>ULONG NumberOfService;</code></p>
  <p id="hmLL"><code>ULONG ParamTableBase;</code></p>
  <p id="QGWf"><code>} KSYSTEM_SERVICE_TABLE, *PKSYSTEM_SERVICE_TABLE;</code></p>
  <p id="ddSf">В то же вре­мя мас­сив этих струк­тур лежит в таб­лицах <code>nt!KeServiceDescriptorTable</code> и <code>nt!KeServiceDescriptorTableShadow</code>. Если в пер­вой хра­нит­ся толь­ко SST для обра­бот­чиков сис­темных вызовов NT, то во вто­рой добав­ляет­ся SST-таб­лица гра­фичес­кой под­систе­мы win32k.</p>
  <figure id="xg2W" class="m_original">
    <img src="https://justpaste.it/img/ab07bac3e8e99024401931bd3d17343c.png" width="728" />
  </figure>
  <p id="X9wx">Мож­но заметить, что пер­вая SST-струк­тура в обе­их таб­лицах оди­нако­ва. При сис­темном вызове ОС Windows исполь­зует ниж­ние 12 бит регис­тра <code>eax</code> как индекс в одной из SSDT-таб­лиц, а биты 12–13 ука­зыва­ют, какую SDT-струк­туру выб­рать: <code>nt!KeServiceDescriptorTable</code> или <code>nt!KeServiceDescriptorTableShadow</code>.</p>
  <p id="Ay7b">В пер­вой час­ти статьи уже шла речь о том, что на 64-бит­ных сис­темах SSDT содер­жит мас­сив сме­щений, а вир­туаль­ный адрес обра­бот­чика сис­темно­го вызова вычис­ляет­ся по фор­муле</p>
  <p id="Q67W"><code>RoutineAddress = ServiceTableBase + (ServiceTableBase[index] &gt;&gt; 4)</code></p>
  <p id="arEh">Сдвиг на 4 необ­ходим, пос­коль­ку пер­вые 4 бита содер­жат количес­тво парамет­ров, переда­ваемых через стек.</p>
  <figure id="VdPA" class="m_original">
    <img src="https://justpaste.it/img/7e14d75a2d3dc22aab86d3db80fb1b10.png" width="577" />
  </figure>
  <p id="Qjen">Ес­ли взгля­нуть на при­мер с вызовом <code>CreateFileW</code>, учи­тывая выше­изло­жен­ное, он будет выг­лядеть сле­дующим обра­зом.</p>
  <figure id="RqQK" class="m_original">
    <img src="https://justpaste.it/img/cce83136ad4f52f5c4f00c8f780c6118.png" width="1123" />
  </figure>
  <p id="oC4i">Мо­нито­ринг модифи­кации SSDT-таб­лиц зак­люча­ется в выс­тавле­нии ловушек на запись в физичес­кие стра­ницы памяти дан­ных таб­лиц и реали­зован в пла­гине ssdtmon.</p>
  <p id="ZFPX">Пе­рех­ват <code>nt!KiServiceTable</code> уже был реали­зован в этом пла­гине, и мы лишь добави­ли под­дер­жку таб­лицы <code>win32k!W32pServiceTable</code>. Так­же в пла­гине вре­донос­ной счи­тает­ся запись, совер­шенная на 8 байт ниже начала таб­лицы. Это свя­зано с тем, что с помощью 16-бит­ных XMM-инс­трук­ций мож­но перепи­сать пер­вые 12 байт таб­лицы, записы­вая на 4 бай­та ниже ее начала. Тем самым мож­но обой­ти три­виаль­ную про­вер­ку гра­ниц. Сто­ит заметить, что в то вре­мя, как таб­лица <code>nt!KiServiceTable</code> находит­ся в сек­ции дан­ных модуля <code>ntoskrnl.exe</code> и дос­тупна из все­го ядер­ного прос­транс­тва, <code>win32k!W32pServiceTable</code> при­над­лежит модулю <code>win32k.sys</code> и для дос­тупа к дан­ному драй­веру нуж­но находить­ся в кон­тек­сте какого‑либо гра­фичес­кого про­цес­са, нап­ример <code>explorer.exe</code>.</p>
  <p id="whOx">Что­бы получить физичес­кий адрес стра­ницы таб­лицы <code>win32k!W32pServiceTable</code>, пла­гин находит PID гра­фичес­кого про­цес­са <code>explorer.exe</code> и исполь­зует регистр CR3 это­го про­цес­са для тран­сля­ции вир­туаль­ного адре­са таб­лицы в физичес­кий:</p>
  <h4 id="jjyH">Код получе­ния зна­чений win32k!W32pServiceTable и win32k!W32pServiceLimit</h4>
  <p id="gjh6"><code>vmi_pid_t gui_pid = 0;</code></p>
  <p id="Wr8c"><code>if (!drakvuf_get_process_pid(drakvuf, gui_process, &amp;gui_pid))</code></p>
  <p id="VEFM"><code>{</code></p>
  <p id="FqIe"><code>PRINT_DEBUG(&quot;[SSDTMON] Failed to get PID of &quot;explorer.exe&quot;\n&quot;);</code></p>
  <p id="AYe0"><code>throw -1;</code></p>
  <p id="hxqM"><code>}</code></p>
  <p id="LjJS"><code>addr_t w32k_base = 0;</code></p>
  <p id="30sF"><code>vmi_lock_guard vmi(drakvuf);</code></p>
  <p id="WNG9"><code>// Locate Win32k.sys base address</code></p>
  <p id="kbYM"><code>if (!get_driver_base(vmi, this, &quot;win32k.sys&quot;, &amp;w32k_base))</code></p>
  <p id="gukN"><code>{</code></p>
  <p id="PViF"><code>PRINT_DEBUG(&quot;[SSDTMON] Failed to find win32k.sys in PsLoadedModuleList\n&quot;);</code></p>
  <p id="7qIP"><code>throw -1;</code></p>
  <p id="39Lx"><code>}</code></p>
  <p id="c3xh"><code>// Read ssdt shadow size</code></p>
  <p id="ynM4"><code>if (VMI_SUCCESS != vmi_read_32_va(vmi, w32k_base + w32psl_rva, gui_pid, &amp;this-&gt;w32pservicelimit))</code></p>
  <p id="juc5"><code>{</code></p>
  <p id="I8VM"><code>PRINT_DEBUG(&quot;[SSDTMON] Failed to read W32pServiceLimit\n&quot;);</code></p>
  <p id="6oMD"><code>throw -1;</code></p>
  <p id="AICe"><code>}</code></p>
  <p id="yCRa"><code>if (VMI_SUCCESS != vmi_translate_uv2p(vmi, w32k_base + w32pst_rva, gui_pid, &amp;this-&gt;w32pservicetable))</code></p>
  <p id="mIBi"><code>{</code></p>
  <p id="NsoR"><code>PRINT_DEBUG(&quot;[SSDTMON] Failed to translate win32k!W32pServiceTable to physical address\n&quot;);</code></p>
  <p id="tTC5"><code>throw -1;</code></p>
  <p id="1k5D"><code>}</code></p>
  <p id="8hvo">Пос­ле чего выс­тавля­ются ловуш­ки на эти физичес­кие стра­ницы, и, пос­коль­ку обе таб­лицы находят­ся в сек­циях READ ONLY, любая запись в них может рас­ценивать­ся как вре­донос­ная.</p>
  <h3 id="p99E">Перехваты IDT/GDT</h3>
  <p id="ReQt">Про­дол­жая тему перех­вата таб­лиц, отме­тим, что сущес­тву­ет еще два типа, которые могут пред­став­лять инте­рес: таб­лицы IDT и GDT.</p>
  <p id="e1By">IDT (Interrupt Descriptor Table) — таб­лица пре­рыва­ний в архи­тек­туре х86, которая слу­жит для кор­рек­тно­го отве­та на пре­рыва­ния и исклю­чения. В IDT исполь­зуют­ся сле­дующие типы пре­рыва­ний: аппа­рат­ные, прог­рам­мные и пре­рыва­ния, зарезер­вирован­ные про­цес­сором, — они называ­ются исклю­чени­ями (пер­вые 32 шту­ки) и исполь­зуют­ся на слу­чай воз­никно­вения некото­рых недопус­тимых событий, таких как деление на ноль, ошиб­ка трас­сиров­ки, перепол­нение.</p>
  <p id="1fch">Ре­гистр <code>IDTR</code> содер­жит базовый адрес (32 бита в защищен­ном режиме, 64 бита в режиме IA-32e) и 16-бит­ный раз­мер таб­лицы в бай­тах. Инс­трук­ции <code>LIDT</code> и <code>SIDT</code> заг­ружа­ют и сох­раня­ют регистр IDTR соот­ветс­твен­но.</p>
  <figure id="FljN" class="m_original">
    <img src="https://justpaste.it/img/8d6f2e8848ca62c0a5b925505165239b.png" width="1297" />
  </figure>
  <figure id="NXiF" class="m_original">
    <img src="https://justpaste.it/img/502f5061cda83b818410075bd7097bfb.png" width="626" />
  </figure>
  <p id="gEpr">Таб­лица дес­крип­торов пре­рыва­ний исполь­зует­ся для того, что­бы показать про­цес­сору, какую про­цеду­ру обслу­жива­ния пре­рыва­ния (ISR) вызывать для обра­бот­ки исклю­чения. Для этой же цели сущес­тву­ет ассем­блер­ная инс­трук­ция <code>int N</code>, где <code>N</code> — это номер пре­рыва­ния.</p>
  <p id="hn6R">Каж­дый эле­мент в таб­лице пре­рыва­ний на 64-бит­ных сис­темах име­ет струк­туру IDTENTRY64.</p>
  <figure id="gXJU" class="m_original">
    <img src="https://justpaste.it/img/032dbf4e013fe6fa2c9bbc26f5b9e166.png" width="392" />
  </figure>
  <p id="O7lY">Ре­аль­ный же адрес обра­бот­чика пре­рыва­ния вычис­ляет­ся по сле­дующей фор­муле:</p>
  <p id="3CJ9"><code>RoutineAddress = OffsetHigh &lt;&lt; 32 + OffsetMiddle &lt;&lt; 16 + OffsetLow</code></p>
  <figure id="14iy" class="m_original">
    <img src="https://justpaste.it/img/9077453b39dc6a23e778c946fe979e20.png" width="525" />
  </figure>
  <p id="jfQb">В пла­гине мы под­счи­тыва­ем кон­троль­ную сум­му всей IDT-таб­лицы на каж­дом логичес­ком ядре и сох­раня­ем для про­вер­ки в кон­це ана­лиза.</p>
  <figure id="ZGFe" class="m_original">
    <img src="https://justpaste.it/img/3ee572f0516485394e99a3892ee8115e.png" width="745" />
  </figure>
  <p id="GE9t">На рисун­ке выше вид­но, что, помимо IDT, мы так­же перечис­ляем и сох­раня­ем GDT-таб­лицу. GDT (Global Descriptor Table) — струк­тура в архи­тек­туре х86, помога­ющая про­цес­сору рас­пре­делить память по сег­ментам. Каж­дый эле­мент таб­лицы, называ­емый сег­мен­тным дес­крип­тором, содер­жит адрес, раз­мер (лимит), фла­ги прав и атри­бутов таких областей.</p>
  <figure id="221e" class="m_original">
    <img src="https://justpaste.it/img/7361293e0e26e3b95e51de43999a6f2d.png" width="576" />
  </figure>
  <p id="va14">Ад­рес и раз­мер таб­лицы хра­нит­ся в отдель­ном сис­темном регис­тре GDTR.</p>
  <figure id="0JLh" class="m_original">
    <img src="https://justpaste.it/img/217693605a373a71195896570f561e35.png" width="370" />
  </figure>
  <p id="eH1P">В режиме х64 из‑за линей­ной модели памяти каж­дый сег­мент в таб­лице охва­тыва­ет все адресное прос­транс­тво и раз­личие мож­но наб­людать лишь в фла­гах дос­тупа к дан­ным сег­ментам. К сожале­нию, мы не обна­ружи­ли рут­киты, которые как‑либо модифи­циро­вали таб­лицу GDT. Но пос­коль­ку PatchGuard защища­ет ее, мы так­же добави­ли про­вер­ку на добав­ление, уда­ление и модифи­кацию эле­мен­тов таб­лицы.</p>
  <p id="NDyE">Ес­ли IDT- или GDT-таб­лицы рас­ходят­ся в начале и в кон­це ана­лиза образца, пла­гин выписы­вает сле­дующие строч­ки:</p>
  <p id="zgpF"><code>&quot;\Device\HarddiskVolume2\Windows\System32\explorer.exe&quot;:KiDeliverApc SessionID:0 PID:1968 PPID:476 Reason:&quot;IDT modification&quot;</code></p>
  <p id="xuJb"><code>&quot;\Device\HarddiskVolume2\Windows\System32\explorer.exe&quot;:KiDeliverApc SessionID:0 PID:1968 PPID:476 Reason:&quot;GDT modification&quot;</code></p>
  <h3 id="1LxB">MSR LSTAR</h3>
  <p id="INb9">Еще одна воз­можная цель рут­китов — переза­пись сис­темно­го регис­тра <code>MSR LSTAR (0xc0000082)</code>. Сог­ласно спе­цифи­кации, пос­ле сис­темно­го вызова инс­трук­цией <code>syscall</code> в регистр <code>RIP</code> будет заг­ружено зна­чение <code>MSR LSTAR</code>, которое в Windows ука­зыва­ет на адрес сис­темной фун­кции <code>KiSystemCall64</code>.</p>
  <figure id="tMHP" class="m_original">
    <img src="https://justpaste.it/img/154b7221b2c6cdc9d5d861fc2712bd30.png" width="791" />
  </figure>
  <p id="0flu">Как вид­но, пер­вая инс­трук­ция в ядре пос­ле сис­темно­го вызова — <code>swapgs</code>. Сог­ласно докумен­тации Intel, SWAPGS exchanges the current GS base register value with the value contained in MSR address C0000102H (IA32_KERNEL_GS_BASE).</p>
  <p id="9xA4">В то вре­мя как поль­зователь­ский регистр <code>gs</code> всег­да ука­зыва­ет на TEB текуще­го потока, в ядре <code>gs</code> будет ука­зывать на Processor control region текуще­го ядра.</p>
  <figure id="0KYf" class="m_original">
    <img src="https://justpaste.it/img/0ef0078e3645ead816f78d1564568446.png" width="574" />
  </figure>
  <p id="eEMx">В отли­чие от SSDT-перех­ватов, переза­пись <code>LSTAR</code> поз­воля­ет перех­ватывать и филь­тро­вать все сис­темные вызовы сра­зу. Но для это­го рут­киту нуж­но сде­лать допол­нитель­ную работу, а имен­но: выз­вать инс­трук­цию <code>swapgs</code>, сох­ранить поль­зователь­ский стек, заг­рузить ядер­ный стек. Час­то в перех­вачен­ном обра­бот­чике <code>LSTAR</code> мож­но встре­тить сле­дующий код.</p>
  <figure id="fpdH" class="m_original">
    <img src="https://justpaste.it/img/261e9e142959bcbe49551fb9774aad18.png" width="512" />
  </figure>
  <p id="mOB7">Rootkitmon обна­ружи­вает модифи­кацию <code>MSR LSTAR</code>, све­ряя его зна­чение с адре­сом фун­кции <code>KiSystemCall64</code> в кон­це ана­лиза. Монито­ринг записи в <code>MSR LSTAR</code> в DRAKVUF на дан­ный момент невоз­можен. Во‑пер­вых, перех­ватывать­ся могут толь­ко записи во все MSR-регис­тры. Во‑вто­рых, перех­ват MSR на запись силь­но наг­ружа­ет сис­тему, пос­коль­ку на каж­дом сис­темном вызове инс­трук­ция <code>swapgs</code> записы­вает в <code>IA32_KERNEL_GS_BASE MSR</code>, как говори­лось выше. В‑треть­их, монито­ринг <code>MSR LSTAR</code> на запись час­то при­водит к лож­ным сра­баты­вани­ям, пос­коль­ку, как мы замети­ли, PatchGuard сам переза­писы­вает этот MSR во вре­мя выпол­нения сво­их про­верок.</p>
  <figure id="5bIp" class="m_original">
    <img src="https://justpaste.it/img/e3dd352761478daaee49178b07a4c0e5.png" width="540" />
  </figure>
  <h3 id="Aaet">ПЕРЕХВАТЫ ФУНКЦИЙ DRIVER_OBJECT</h3>
  <p id="MnWE">У каж­дого заг­ружен­ного драй­вера в сис­теме есть струк­тура <code>DRIVER_OBJECT</code>. Она опи­сыва­ет сос­тояние драй­вера, который отве­чает за ее ини­циали­зацию во вре­мя сво­ей заг­рузки. В час­тнос­ти, для ком­муника­ции с поль­зователь­ски­ми прог­рамма­ми драй­вер дол­жен ини­циали­зиро­вать мас­сив <code>MajorFunction</code>. Он, в свою оче­редь, содер­жит адре­са обра­бот­чиков для всех зап­росов, на которые драй­вер может отве­чать. Нап­ример, ког­да поль­зователь­ское ПО будет исполь­зовать API ReadFile с опи­сате­лем драй­вера, Windows соз­даст спе­циаль­ный IRP-зап­рос и вызовет обра­бот­чик из мас­сива <code>MajorFunction</code> это­го драй­вера — в дан­ном слу­чае <code>IRP_MJ_READ</code>.</p>
  <figure id="ky6e" class="m_original">
    <img src="https://justpaste.it/img/1cea23181804ad16540d47848e322185.png" width="633" />
  </figure>
  <p id="ptok">Пе­реза­пись ука­зате­лей на обра­бот­чики, как и в слу­чае с SSDT, при­ведет к перех­вату всех вызовов опре­делен­ного типа зап­роса к драй­веру. Осо­бен­ность этой тех­ники сос­тоит в том, что PatchGuard защища­ет толь­ко неболь­шой спи­сок объ­ектов драй­веров и перех­ват любого драй­вера не из спис­ка не при­ведет к BSOD’у сис­темы.</p>
  <p id="leUw">По­мимо мас­сива <code>MajorFunction</code>, так­же сущес­тву­ет мас­сив быс­трых IO-опе­раций — <code>FastIoDispatch</code>. В отли­чие от <code>MajorFunction</code>, быс­трые IO-опе­рации пред­назна­чены исклю­читель­но для драй­веров фай­ловой сис­темы и сетевых драй­веров. Рас­смот­рим, что такое объ­екты и как мож­но их перечис­лять непос­редс­твен­но из кон­тек­ста гипер­визора.</p>
  <p id="E0hC">В Windows каж­дый ресурс (про­цесс, поток, файл и так далее) пред­став­лен в виде объ­екта и управля­ется дис­петче­ром объ­ектов Windows. Нап­ример, в Windows 10 1803 сущес­тву­ет око­ло 64 раз­личных типов объ­ектов.</p>
  <p id="koA1">Каж­дый объ­ект сос­тоит из двух час­тей:</p>
  <ul id="EY4l">
    <li id="NKBV">OBJECT_HEADER — спе­циаль­ный заголо­вок фик­сирован­ного раз­мера, который находит­ся перед телом объ­екта и которым вла­деет дис­петчер объ­ектов;</li>
    <li id="vhzF">Body — часть объ­екта, пред­став­ляющая сис­темный ресурс (<code>EPROCESS</code> для про­цес­сов, <code>ETHREAD</code> для потоков, <code>FILE_OBJECT</code> для фай­лов и так далее).</li>
  </ul>
  <figure id="jb1S" class="m_original">
    <img src="https://justpaste.it/img/8f1a50af5c2d3b4d99492904c37d9f13.png" width="563" />
  </figure>
  <p id="B5n0">Мно­гие объ­екты содер­жат дан­ные, которые пос­тоян­ны для всех объ­ектов одно­го типа. Для эко­номии памяти дис­петчер объ­ектов хра­нит ста­тич­ные дан­ные одно­го типа объ­ектов в спе­циаль­ной струк­туре <code>OBJECT_TYPE</code>.</p>
  <figure id="N4NH" class="m_original">
    <img src="https://justpaste.it/img/60ad627182a09f667dce0c01e18bcd88.png" width="650" />
  </figure>
  <p id="faWH">Все типы объ­ектов хра­нят­ся в мас­сиве под сим­волом <code>nt!ObTypeIndexTable</code>. В то же вре­мя в заголов­ке объ­екта находит­ся поле <code>TypeIndex</code>, которое ука­зыва­ет на индекс в дан­ном мас­сиве. Для наг­ляднос­ти най­дем струк­туру типа объ­екта <code>EPROCESS</code>.</p>
  <figure id="FsbR" class="m_original">
    <img src="https://justpaste.it/img/eaeae4b6c2f377669d5747546cb16780.png" width="827" />
  </figure>
  <p id="64ct">Объ­екты хра­нят­ся в спе­циаль­ной дирек­тории <code>_OBJECT_DIRECTY</code>. Ука­затель на кор­невую дирек­торию содер­жится в <code>nt!ObpRootDirectoryObject</code>.</p>
  <figure id="mgpY" class="m_original">
    <img src="https://justpaste.it/img/23a3b5cd19a43d75e5bf24adf0482e0f.png" width="645" />
  </figure>
  <p id="04mg">Все­го в дирек­тории может быть 37 записей, где каж­дая запись — ука­затель на связ­ный спи­сок <code>_OBJECT_DIRECTORY_ENTRY</code> со сле­дующей струк­турой.</p>
  <figure id="T1w8" class="m_original">
    <img src="https://justpaste.it/img/5d2f37efa6bc4aa7acb9d16d487a5e3e.png" width="654" />
  </figure>
  <p id="l6Lj"><code>Object</code> — это тело объ­екта. Дирек­тории так­же могут быть вло­жен­ными, для них сущес­тву­ет спе­циаль­ный тип <code>Directory</code>, и, если <code>Object</code> име­ет дан­ный тип, он трак­тует­ся как <code>OBJECT_DIRECTORY</code>.</p>
  <figure id="VbBC" class="m_original">
    <img src="https://justpaste.it/img/5b552743f471193cf61060252ce0aff6.png" width="1261" />
  </figure>
  <p id="q6PF">Со­ответс­твен­но, для перечис­ления всех объ­ектов драй­веров в сис­теме rootkitmon рекур­сивно обхо­дит каж­дую дирек­торию и сох­раня­ет объ­ект, если он отно­сит­ся к типу Driver.</p>
  <figure id="MaTc" class="m_original">
    <img src="https://justpaste.it/img/6a70b7dc4814ccd8e9211418b52970e5.png" width="992" />
  </figure>
  <p id="Wwwo">У каж­дого получен­ного объ­екта под­счи­тыва­ется кон­троль­ная сум­ма мас­сивов <code>MajorFunction</code> и <code>FastIoDispatch</code>, а так­же ука­зате­лей <code>DriverStartIo</code> и <code>DriverUnload</code>. Несов­падение кон­троль­ной сум­мы по резуль­татам ана­лиза озна­чает вре­донос­ную модифи­кацию этих струк­тур.</p>
  <figure id="zDcm" class="m_original">
    <img src="https://justpaste.it/img/fa500308bd55082a49d71bc979553a8a.png" width="635" />
  </figure>
  <p id="nzI5">По­мимо <code>DRIVER_OBJECT</code>, мы так­же сох­раня­ем каж­дый <code>DEVICE_OBJECT</code> в сте­ке девай­сов. <code>DEVICE_OBJECT</code> может пред­став­лять логичес­кое, физичес­кое устрой­ство или прос­то некие воз­можнос­ти драй­вера. Сама струк­тура <code>DEVICE_OBJECT</code> всег­да соз­дает­ся драй­вером фун­кци­ей <code>IoCreateDevice</code>. Ког­да сис­тема посыла­ет IRP-зап­рос драй­веру, она нап­равля­ет его какому‑либо девай­су. Мас­сив <code>MajorFunction</code> име­ет ука­зате­ли на обра­бот­чики зап­росов со сле­дующим про­тоти­пом.</p>
  <figure id="9TsL" class="m_original">
    <img src="https://justpaste.it/img/3599c8ae41210f2cc37a3a4440abb3cd.png" width="418" />
  </figure>
  <p id="NzjP">Пер­вым аргу­мен­том всег­да будет ука­затель на девайс‑объ­ект, к которо­му был отправ­лен зап­рос. Соот­ветс­твен­но, драй­вер может иметь бес­конеч­но мно­го раз­личных девай­сов и обра­баты­вать каж­дый по‑сво­ему.</p>
  <p id="gXuy">Windows поз­воля­ет фор­мировать стек девайс‑объ­ектов. Обыч­но, ког­да на девайс оправля­ется зап­рос, его помога­ют обра­ботать нес­коль­ко драй­веров. Каж­дый из этих драй­веров свя­зан с девайс‑объ­ектом, и такие объ­екты рас­положе­ны в сте­ке. Пос­ледова­тель­ность девайс‑объ­ектов с соот­ветс­тву­ющи­ми драй­верами называ­ется сте­ком девайс‑объ­ектов. Нап­ример, так выг­лядит стек девайс‑объ­ектов жес­тко­го дис­ка.</p>
  <figure id="VOZ8" class="m_original">
    <img src="https://justpaste.it/img/a8dbe3f596b71701b5d59cbafcb9399d.png" width="646" />
  </figure>
  <p id="cvAF">Вид­но, что зап­рос прой­дет нес­коль­ко «высоко­уров­невых» драй­веров, преж­де чем ока­зать­ся в обра­бот­чике кон­трол­лера жес­тко­го дис­ка stornvme. Такие зап­росы мож­но перех­ватывать, регис­три­руя свой драй­вер в стек‑девай­се объ­ектов с помощью <code>IoAttachDeviceToDeviceStack</code>. Так­же Windows поз­воля­ет регис­три­ровать спе­циаль­ный драй­вер — мини‑филь­тр с помощью <code>FltRegisterFilter</code>, который может вызывать­ся на раз­личных IO-зап­росах. Отличный при­мер работы мини‑филь­тров показан на рисун­ке ниже.</p>
  <figure id="Nft0" class="m_original">
    <img src="https://justpaste.it/img/e1c3a0dc744957b1ed155d4ed82e6f5d.gif" width="385" />
  </figure>
  <p id="4iEn">Хо­тя регис­тра­ция мини‑филь­тра не счи­тает­ся вре­донос­ной, перех­ват этой фун­кции может дать отличное пред­став­ление о воз­можнос­тях ана­лизи­руемо­го драй­вера.</p>
  <figure id="pE7P" class="m_original">
    <img src="https://justpaste.it/img/56d509e7fe7533f5287c4d77951f4671.png" width="1383" />
  </figure>
  <p id="QMNK">Ес­ли стек девай­сов модифи­циро­ван или зарегис­три­рован мини‑филь­тр, DRAKVUF покажет сле­дующие стро­ки:</p>
  <p id="E7wk"><code>&quot;\Device\HarddiskVolume2\Windows\System32\explorer.exe&quot;:KiDeliverApc SessionID:0 PID:1968 PPID:476 Reason:&quot;Driver stack modification&quot;</code></p>
  <p id="WSUB"><code>&quot;\Device\HarddiskVolume2\Windows\System32\explorer.exe&quot;:KiDeliverApc SessionID:0 PID:1968 PPID:476 Reason:&quot;FltRegisterFilter&quot;</code></p>
  <h3 id="ioKr">ТЕХНИКА СОКРЫТИЯ ПРОЦЕССА ОТ TASK MANAGER</h3>
  <p id="uNZt">Од­на из клас­сичес­ких тех­ник сок­рытия про­цес­са — уда­ление его из связ­ного спис­ка струк­тур <code>EPROCESS</code>. <code>EPROCESS</code> — ядер­ная струк­тура, опи­сыва­ющая сос­тояние запущен­ного про­цес­са. Дру­гими сло­вами, на каж­дый запущен­ный про­цесс заводит­ся отдель­ная струк­тура <code>EPROCESS</code>. Сис­тема свя­зыва­ет каж­дую струк­туру <code>EPROCESS</code> с дру­гими с помощью двой­ного связ­ного спис­ка <code>LIST_ENTRY</code>. Сам спи­сок сос­тоит из двух эле­мен­тов — ука­зате­ля <code>Flink</code> на сле­дующую струк­туру <code>EPROCESS</code> в цепоч­ке и ука­зате­ля <code>Blink</code> на пре­дыду­щую струк­туру в цепоч­ке. <code>PsProcessActiveHead</code> — ука­затель на связ­ный спи­сок про­цес­сов.</p>
  <figure id="hM2y" class="m_original">
    <img src="https://justpaste.it/img/4d7233ec2328de3b1fc4cda7a40676aa.png" width="852" />
  </figure>
  <p id="ckKB">Так, при вызове коман­ды <code>cmd /c tasklist</code> или откры­тии Task Manager Windows прос­матри­вает связ­ный спи­сок про­цес­сов и воз­вра­щает информа­цию по каж­дому из них. Что­бы про­цесс не выс­вечивал­ся в дан­ных спис­ках, дос­таточ­но уда­лить его из цепоч­ки. Для это­го необ­ходимо, что­бы <code>Flink</code> пре­дыду­щего про­цес­са в цепоч­ке ука­зывал на струк­туру сле­дующе­го, а <code>Blink</code> сле­дующе­го про­цес­са ука­зывал на пре­дыду­щий. Так­же во избе­жание BSOD’ов ссыл­ки скры­того про­цес­са дол­жны ука­зывать друг на дру­га, как показа­но на рисун­ке ниже.</p>
  <figure id="OXoG" class="m_original">
    <img src="https://justpaste.it/img/d3a40a678a5d7af804cbf6a31dec7fc5.png" width="842" />
  </figure>
  <p id="310V">Для монито­рин­га сок­рытия про­цес­са из связ­ного спис­ка пла­гин rootkitmon перех­ватыва­ет две сис­темные фун­кции: <code>PspInsertProcess</code> и <code>PspProcessDelete</code>. Как мож­но догадать­ся по наз­ванию, пер­вая фун­кция встав­ляет толь­ко что соз­данный про­цесс в связ­ный спи­сок струк­тур <code>EPROCESS</code>, а вто­рая уда­ляет.</p>
  <p id="xOxY">Так­же пла­гин содер­жит внут­ренний спи­сок всех запущен­ных про­цес­сов в сис­теме, который запол­няет­ся при ини­циали­зации пла­гина и попол­няет­ся (или отчи­щает­ся) при соз­дании и завер­шении про­цес­са.</p>
  <p id="77tj">Со­ответс­твен­но, если на завер­шении про­цес­са его ука­зате­ли <code>Flink</code> и <code>Blink</code> зам­кну­ты — про­цесс был скрыт.</p>
  <figure id="bhmY" class="m_original">
    <img src="https://justpaste.it/img/05bd52b369d6f0cbe309282c873d4423.png" width="653" />
  </figure>
  <p id="1YgF">Но что, если про­цесс не был завер­шен в кон­це ана­лиза? Для это­го пла­гин перечис­ляет связ­ный спи­сок струк­тур <code>EPROCESS</code> и срав­нива­ет его с име­ющим­ся в момент завер­шения: если про­цесс из ста­рого спис­ка не был най­ден в новом, он был скрыт.</p>
  <figure id="8XF0" class="m_original">
    <img src="https://justpaste.it/img/35f25304d3aba8014633dd54592baa34.png" width="1561" />
  </figure>
  <p id="Lcy2">Та­кой под­ход не наг­ружа­ет сис­тему и очень эффекти­вен. Если будет обна­ружен скры­тый про­цесс, в логах DRAKVUF появит­ся такая стро­ка:</p>
  <p id="yjd9"><code>&quot;\Device\HarddiskVolume2\Windows\System32\explorer.exe&quot;:KiDeliverApc SessionID:0 PID:1968 PPID:476 Reason:&quot;Hidden process&quot; HiddenPid:1624</code></p>
  <p id="lYrQ">где <code>HiddenPid</code> — PID скры­того про­цес­са.</p>
  <h3 id="l76r">РЕГИСТРАЦИЯ СИСТЕМНЫХ ФУНКЦИЙ ОБРАТНОГО ВЫЗОВА</h3>
  <p id="PDeU">На­пос­ледок раз­берем нес­коль­ко инди­като­ров, которые не явля­ются вре­донос­ными, но могут таковы­ми ока­зать­ся.</p>
  <p id="qxEG">Microsoft пре­дос­тавля­ет «офи­циаль­ный» спо­соб перех­вата сис­темных событий с помощью регис­тра­ции фун­кций обратно­го вызова (кол­бэков). Нап­ример, что­бы получать опо­веще­ния о соз­дании или завер­шении про­цес­сов, драй­вер может зарегис­три­ровать кол­бэк с помощью API <code>PsSetCreateProcessNotifyRoutine</code>, для под­писки на соз­дание потоков — <code>PsSetCreateThreadNotifyRoutine</code>.</p>
  <p id="LWRA">Толь­ко докумен­тирован­ных кол­бэков боль­ше пят­надца­ти, в DRAKVUF мы перех­ватыва­ем сле­дующие API регис­тра­ции кол­бэков:</p>
  <ul id="94iZ">
    <li id="Nvyp"><code>PspSetCreateProcessNotifyRoutine</code> — под­писка на соз­дание/завер­шение про­цес­са;</li>
    <li id="NwhX"><code>PspSetCreateThreadNotifyRoutine</code> — под­писка на соз­дание/завер­шение потока;</li>
    <li id="ukip"><code>PsSetLoadImageNotifyRoutine</code> — под­писка на заг­рузку модулей;</li>
    <li id="e3ry"><code>CmpRegisterCallbackInternal</code> — под­писка на работу с реес­тром;</li>
    <li id="kmwj"><code>ObRegisterCallbacks</code> — под­писка на получе­ние опи­сате­лей про­цес­са, потока и рабоче­го сто­ла;</li>
    <li id="pv6y"><code>FsRtlRegisterFileSystemFilterCallbacks</code> — под­писка на работу с фай­ловой сис­темой.</li>
  </ul>
  <p id="WvmO">Спи­сок не исчерпы­вающий и в будущих ревизи­ях пла­гина может изме­нять­ся. Сама по себе регис­тра­ция кол­бэка не счи­тает­ся вре­донос­ной, но дает хорошее пред­став­ление, что дела­ет ана­лизи­руемый драй­вер в песоч­нице. На текущий момент пла­гин прос­то перех­ватыва­ет фун­кции регис­тра­ции кол­бэков и фик­сиру­ет наз­вания фун­кций регис­тра­ции, если такие были выз­ваны.</p>
  <figure id="yd37" class="m_original">
    <img src="https://justpaste.it/img/fcd2c107f1bba23476bfb2f4caf63a16.png" width="575" />
  </figure>
  <h3 id="Omqk">ЗАКЛЮЧЕНИЕ</h3>
  <p id="pq3F">Пла­гин rootkitmon находит­ся на ран­них ста­диях раз­работ­ки, но уже поз­воля­ет обна­ружить такие рут­киты, как Moriya, TDSS, Necurs и мно­гие дру­гие. Rootkitmon не наг­ружа­ет сис­тему и под­держи­вает как Windows 7 x64, так и Windows 10 x64. Даль­ше количес­тво тех­ник обна­руже­ния вре­донос­ной активнос­ти будет толь­ко уве­личи­вать­ся.</p>

]]></content:encoded></item><item><guid isPermaLink="true">https://teletype.in/@anon_channel/_NIaLfUkH-C</guid><link>https://teletype.in/@anon_channel/_NIaLfUkH-C?utm_source=teletype&amp;utm_medium=feed_rss&amp;utm_campaign=anon_channel</link><comments>https://teletype.in/@anon_channel/_NIaLfUkH-C?utm_source=teletype&amp;utm_medium=feed_rss&amp;utm_campaign=anon_channel#comments</comments><dc:creator>anon_channel</dc:creator><title>Хакер - Не App Store единым. Устанавливаем сторонние приложения в iOS без джейла</title><pubDate>Wed, 10 Nov 2021 16:59:27 GMT</pubDate><media:content medium="image" url="https://img1.teletype.in/files/40/57/40571a1b-89e2-4735-a44b-e13dde572aa9.jpeg"></media:content><description><![CDATA[<img src="https://st768.s3.eu-central-1.amazonaws.com/0b8d51abf8afdecf90906eebe9e102fc/19643/nullximpactor_Nu34RCo.jpg"></img>Содержание статьи]]></description><content:encoded><![CDATA[
  <h3 id="Содержание-статьи"><a href="https://t.me/anon_chan_by" target="_blank">t.me/anon_chan_by</a></h3>
  <p id="BKod">Содержание статьи</p>
  <ul id="SABa">
    <li id="Wfwh">Почему нельзя просто установить приложение</li>
    <li id="2jsq">Официальный путь: аккаунт разработчика</li>
    <li id="xm7e">Полуофициальный путь: Cydia Impactor</li>
    <li id="qAkT">Идем в серую зону: подпись пакета обычным Apple ID</li>
    <li id="6R5a">Nullximpactor</li>
    <li id="AweW">iOS App Signer</li>
    <li id="pCFq">AltDeploy и AltStore</li>
    <li id="g80G">Подпись в режиме онлайн</li>
    <li id="YSpM">Альтернативные магазины приложений</li>
    <li id="oWrT">TestFlight</li>
    <li id="GPxl">Где взять пакеты приложений?</li>
    <li id="Rtpi">Заключение</li>
  </ul>
  <p id="uSmo">Эко­сис­тему Apple недаром называ­ют «ого­рожен­ным садом»: ком­пания жес­тко кон­тро­лиру­ет, что поль­зователь может, а чего не может делать со сво­ими устрой­ства­ми. В слу­чае с iOS и iPadOS этот кон­троль дос­тига­ет абсур­дных мас­шта­бов, ког­да закон­ный вла­делец устрой­ства теря­ет воз­можность уста­нав­ливать при­ложе­ния в обход модери­руемо­го и цен­зуриру­емо­го магази­на при­ложе­ний. В этой статье мы рас­смот­рим спо­собы сня­тия это­го огра­ниче­ния, от самых прос­тых, «в один клик», до слож­ных, но надеж­ных.</p>
  <h3 id="ПОЧЕМУ-НЕЛЬЗЯ-ПРОСТО-УСТАНОВИТЬ-ПРИЛОЖЕНИЕ">ПОЧЕМУ НЕЛЬЗЯ ПРОСТО УСТАНОВИТЬ ПРИЛОЖЕНИЕ</h3>
  <p id="JiZL">На сов­ремен­ных мобиль­ных плат­формах мож­но запус­кать толь­ко код, под­писан­ный циф­ровой под­писью. Но если в Android мож­но залить пакет при­ложе­ния, под­писан­ный обыч­ным циф­ровым сер­тифика­том, то в iOS ситу­ация слож­нее: пакет под­писыва­ется в момент уста­нов­ки, а уни­каль­ная для каж­дого устрой­ства циф­ровая под­пись раз­реша­ет запус­кать его лишь на том устрой­стве, для которо­го она была соз­дана.</p>
  <p id="aB4T">До­бавим сюда тот факт, что циф­ровые под­писи в одно лицо выда­ет (а может и отоз­вать!) толь­ко сама ком­пания Apple, и получим ситу­ацию, в которой никакой непод­писан­ный (точ­нее — под­писан­ный «неп­равиль­ной» циф­ровой под­писью) код на устрой­стве выпол­нять­ся не может.</p>
  <h3 id="ОФИЦИАЛЬНЫЙ-ПУТЬ:-АККАУНТ-РАЗРАБОТЧИКА">ОФИЦИАЛЬНЫЙ ПУТЬ: АККАУНТ РАЗРАБОТЧИКА</h3>
  <p id="apAT">Са­мый прос­той и единс­твен­но чес­тный путь решения этой проб­лемы — офи­циаль­ный. При желании при­ложе­ния все‑таки мож­но уста­нав­ливать, минуя App Store, но путь этот тер­нист, а для обыч­ного поль­зовате­ля прос­то недос­тупен.</p>
  <p id="hN6g">Один из таких спо­собов — раз­личные вари­анты <a href="https://developer.apple.com/custom-apps/" target="_blank">кор­поратив­ной и спе­циаль­ной дис­три­буции</a>. Так, в слу­чае с кор­поратив­ной дис­три­буци­ей кли­ент (обра­зова­тель­ное учрежде­ние или круп­ная ком­пания — нап­ример, тран­спортная) регис­три­рует кор­поратив­ную учет­ную запись, получая воз­можность самос­тоятель­но под­писывать пакеты при­ложе­ний и рас­сылать их на кор­поратив­ные устрой­ства через MDM (Mobile Device Management).</p>
  <p id="iKRY">Для под­писи исполь­зует­ся спе­циаль­ный enterprise-сер­тификат, срок дей­ствия которо­го, как пра­вило, огра­ничен одним годом, зато отсутс­тву­ют огра­ниче­ния на чис­ло под­писыва­емых им при­ложе­ний. При пер­вом запус­ке под­писан­ного таким сер­тифика­том при­ложе­ния поль­зовате­лю (если его устрой­ство не было заранее нас­тро­ено ком­пани­ей‑вла­дель­цем) нуж­но будет открыть нас­трой­ки и добавить сер­тификат в спи­сок доверен­ных. В этот момент устрой­ство свя­жет­ся с сер­вером Apple, который и выдаст (или не выдаст; об этом — ниже) раз­решение на это дей­ствие.</p>
  <p id="0AOK">В чем под­вох? Их сра­зу нес­коль­ко. Во‑пер­вых, в прог­рамме кор­поратив­ной дис­три­буции могут учас­тво­вать орга­низа­ции, но не час­тные лица. Во‑вто­рых, учас­тие в прог­рамме плат­ное. Наконец, мы не выходим из‑под кон­тро­ля Apple; ком­пания по‑преж­нему сох­раня­ет кон­троль над тем, раз­решить ли запуск при­ложе­ния на кон­крет­ном устрой­стве. Если Apple покажет­ся, что выдан­ный орга­низа­ции enterprise-сер­тификат исполь­зует­ся с наруше­нием лицен­зион­ного сог­лашения, этот сер­тификат будет момен­таль­но отоз­ван и под­писать с его помощью вновь уста­нав­лива­емые при­ложе­ния не удас­тся. Подоб­ные сер­тифика­ты регуляр­но «уте­кают» и исполь­зуют­ся раз­личны­ми «аль­тер­натив­ными магази­нами при­ложе­ний» для подписи при­ложе­ний.</p>
  <p id="4VRL">Ва­риация на ту же тему — спе­циаль­ная дис­три­буция для учас­тни­ков прог­раммы Apple для раз­работ­чиков. Ее основное пред­назна­чение — тес­тирова­ние раз­работ­чиками прог­рамм собс­твен­ного про­изводс­тва на сво­их же устрой­ствах; соот­ветс­твен­но, для ее исполь­зования нуж­на учет­ная запись раз­работ­чика (Apple Developer Account). В рам­ках спе­циаль­ной дис­три­буции воз­можно пакети­рова­ние: одну и ту же сбор­ку мож­но под­писать сра­зу для сот­ни устрой­ств.</p>
  <p id="em6Y">У это­го спо­соба есть как несом­ненные пре­иму­щес­тва, так и недос­татки в срав­нении с методом кор­поратив­ной дис­три­буции.</p>
  <p id="2NKz">В дос­тоинс­тва запишем в пер­вую оче­редь то, что при­ложе­ние прос­то уста­нав­лива­ется и запус­кает­ся; нет необ­ходимос­ти под­тверждать сер­тификат, как нет и необ­ходимос­ти каж­дый раз для уста­нов­ки при­ложе­ния свя­зывать­ся с сер­вером Apple. Отсю­да сле­дует воз­можность уста­новить при­ложе­ние на iPhone, у которо­го отсутс­тву­ет под­клю­чение к сети, — в пол­ностью офлай­новом режиме.</p>
  <p id="Kl9F">Вто­рое дос­тоинс­тво метода — это его дос­тупность для обыч­ного поль­зовате­ля. Все­го 99 дол­ларов в год — и ты можешь открыть собс­твен­ную учет­ную запись раз­работ­чика, которая поз­волит тебе уста­нав­ливать любые при­ложе­ния на устрой­ства чис­лом до ста штук!</p>
  <p id="4mEs">Так, а это точ­но «дос­тоинс­тво»? 99 дол­ларов в год — это немало все­го лишь за пра­во уста­нав­ливать собс­твен­ные при­ложе­ния на собс­твен­ный iPhone, да и сто устрой­ств — это за целый год: уда­ление ранее зарегис­три­рован­ного устрой­ства из учет­ной записи не выс­вобож­дает один из ста сло­тов.</p>
  <p id="BYVY">Еще один недос­таток офи­циаль­ного спо­соба — жес­ткая при­вяз­ка дис­три­буции к сре­де раз­работ­ки Xcode, для работы которой, в свою оче­редь, пот­ребу­ется компь­ютер с macOS. Получа­ется слож­новато и дорого­вато, если у тебя слу­чай­но нет Mac.</p>
  <p id="e0SU">На­конец, пос­ледний недос­таток метода — открыть учет­ную запись для раз­работ­чика час­тно­му лицу неп­росто из‑за рогаток, уста­нов­ленных Apple. Об исполь­зовании одно­разо­вых Apple ID мож­но забыть: Apple верифи­циру­ет дан­ные и может отка­зать в регис­тра­ции без объ­ясне­ния при­чин. Наши раз­работ­чики говорят, что неп­лохие шан­сы получить акка­унт при исполь­зовании неново­го Apple ID, в котором ука­зан реаль­ный адрес (тот же, к которо­му при­вяза­на пла­теж­ная кар­та); регис­три­ровать­ся луч­ше с мака, а наличие исто­рии покупок с этой же учет­ной записи еще повыша­ет шан­сы. Нес­мотря на это, гаран­тии того, что учет­ную запись в прог­рамме для раз­работ­чиков зарегис­три­руют, нет; отка­зыва­ют обыч­но без ука­зания при­чин.</p>
  <p id="nTnx">На этом офи­циаль­ные спо­собы закан­чива­ются и начина­ются полу­офи­циаль­ные.</p>
  <h3 id="ПОЛУОФИЦИАЛЬНЫЙ-ПУТЬ:-CYDIA-IMPACTOR">ПОЛУОФИЦИАЛЬНЫЙ ПУТЬ: CYDIA IMPACTOR</h3>
  <p id="OtyX">По­луофи­циаль­ный спо­соб — исполь­зование все той же офи­циаль­ной учет­ной записи для раз­работ­чиков, но для под­писи пакета вмес­то Xcode будем исполь­зовать при­ложе­ние <a href="http://www.cydiaimpactor.com/" target="_blank">Cydia Impactor</a>. Чем это луч­ше Xcode? Во‑пер­вых, про­ще. В Xcode нуж­но задавать мас­су полей, соз­давать про­филь, экспор­тировать сер­тификат — квест дос­таточ­но запутан­ный даже для нас­тоящих раз­работ­чиков. Cydia Impactor поз­воля­ет прос­то взять и залить при­ложе­ние на iPhone, не тре­буя ничего, кро­ме логина и пароля от акка­унта раз­работ­чика.</p>
  <p id="q7KK">Во‑вто­рых, в отли­чие от Xcode и мно­гих аль­тер­натив­ных решений, Cydia Impactor дос­тупен для мно­жес­тва плат­форм, вклю­чая macOS, Windows и Linux.</p>
  <p id="13li">Не­дос­таток один: тре­бует­ся учет­ная запись Apple ID, зарегис­три­рован­ная в прог­рамме Apple для раз­работ­чиков. Если такой акка­унт у тебя есть, то про­цеду­ра дос­таточ­но прос­та, но к ней нуж­но под­готовить­ся — соз­дать в учет­ной записи Apple ID так называ­емый <a href="https://support.apple.com/ru-ru/HT204397" target="_blank">па­роль при­ложе­ния</a>.</p>
  <p id="Ez9b">Итак, метод уста­нов­ки при­ложе­ния с исполь­зовани­ем акка­унта раз­работ­чика и Cydia Impactor:</p>
  <ol id="tEUH">
    <li id="Ah8E">Под­клю­чаем iPhone к компь­юте­ру, уста­нав­лива­ем доверен­ную связь (под­твержда­ем зап­рос «Trust this computer?» на iPhone и вво­дим код бло­киров­ки экра­на).</li>
    <li id="UOZa">За­пус­каем Cydia Impactor.</li>
    <li id="JqoA">Бро­саем на окно Cydia Impactor файл IPA уста­нав­лива­емо­го при­ложе­ния.</li>
    <li id="7TDG">Вво­дим логин и «пароль при­ложе­ния» от Apple ID (обя­затель­но зарегис­три­рован­ного в прог­рамме Apple для раз­работ­чиков).</li>
    <li id="peGD">Ес­ли Apple ID зарегис­три­рован более чем в одной прог­рамме для раз­работ­чиков, выбира­ем нуж­ную.</li>
    <li id="b06I">Под­твержда­ем зап­рос, и Cydia Impactor под­пишет IPA и передаст его на устрой­ство.</li>
    <li id="LHqu">Все, при­ложе­нием мож­но поль­зовать­ся!</li>
  </ol>
  <p id="dKeT">Спо­соб кор­рек­тный. Одна­ко хотелось бы того же самого, но с исполь­зовани­ем обыч­ного Apple ID. Как ни стран­но, это воз­можно, но с рядом огра­ниче­ний.</p>
  <h3 id="ИДЕМ-В-СЕРУЮ-ЗОНУ:-ПОДПИСЬ-ПАКЕТА-ОБЫЧНЫМ-APPLE-ID">ИДЕМ В СЕРУЮ ЗОНУ: ПОДПИСЬ ПАКЕТА ОБЫЧНЫМ APPLE ID</h3>
  <p id="OyGc">Итак, ты решил под­писать пакет при­ложе­ния обыч­ным Apple ID, не зарегис­три­рован­ным в прог­рамме Apple для раз­работ­чиков. До 2019 года эта опция была хоть и не широко извес­тной, но впол­не работос­пособ­ной с уче­том некото­рых огра­ниче­ний: под­писан­ное таким обра­зом при­ложе­ние работа­ло толь­ко семь дней, а уста­новить на одно устрой­ство мож­но было не более трех под­писан­ных пер­сональ­ными сер­тифика­тами при­ложе­ний. Три года назад в Apple решили прик­рыть этот спо­соб уста­нов­ки, но сде­лали это не до кон­ца. Оставша­яся лазей­ка, впро­чем, работа­ет толь­ко на компь­юте­рах с macOS. Соот­ветс­твен­но, если у тебя есть Mac, то ты можешь поп­робовать одно из сле­дующих при­ложе­ний.</p>
  <h3 id="Nullximpactor">Nullximpactor</h3>
  <p id="tCbH"><a href="https://impactor.nullx.me/" target="_blank">Nullximpactor</a> — фак­тичес­ки аль­тер­натива Cydia Impactor, работа­ющая толь­ко на macOS, но поз­воля­ющая исполь­зовать для под­писи обыч­ные учет­ные записи.</p>
  <p id="NZqE">Раз­работ­чик @nullx рекомен­дует исполь­зовать для под­писи одно­разо­вые Apple ID без двух­фактор­ной аутен­тифика­ции. В про­тив­ном слу­чае тебе при­дет­ся соз­дать в сво­ей учет­ной записи «пароль при­ложе­ния».</p>
  <p id="PMOD"><strong>Дос­тоинс­тва:</strong> пос­ле началь­ной нас­трой­ки исполь­зовать дос­таточ­но прос­то.</p>
  <p id="h3mU"><strong>Не­дос­татки:</strong> толь­ко macOS; тре­бует­ся началь­ная нас­трой­ка AltDeploy (<a href="https://kubadownload.com/news/nullximpactor/" target="_blank">инс­трук­ция</a>); оста­ются все огра­ниче­ния пер­сональ­ной учет­ной записи (при­ложе­ние будет работать не доль­ше семи дней, а уста­новить мож­но не более трех при­ложе­ний).</p>
  <figure id="dA6H" class="m_original">
    <img src="https://st768.s3.eu-central-1.amazonaws.com/0b8d51abf8afdecf90906eebe9e102fc/19643/nullximpactor_Nu34RCo.jpg" width="600" />
    <figcaption>Nullximpactor</figcaption>
  </figure>
  <h3 id="iOS-App-Signer">iOS App Signer</h3>
  <p id="uObQ"><a href="https://dantheman827.github.io/ios-app-signer/" target="_blank">iOS App Signer</a> — инте­рес­ное решение, прин­ципи­аль­но отли­чающееся от всех осталь­ных прог­рамм подоб­ного наз­начения. iOS App Signer исполь­зует для под­писи при­ложе­ний штат­ную сре­ду раз­работ­ки Xcode, обхо­дя при этом тре­бова­ние учет­ной записи раз­работ­чика (впро­чем, семид­невное огра­ниче­ние или огра­ниче­ние на чис­ло уста­нов­ленных таким обра­зом при­ложе­ний раз­работ­чикам обой­ти не уда­лось).</p>
  <p id="ATaS">Поль­зовать­ся iOS App Signer дос­таточ­но слож­но, но на GitHub есть под­робные инс­трук­ции.</p>
  <p id="KUnZ"><strong>Дос­тоинс­тва:</strong> ори­гиналь­ный метод, не тре­бующий уста­нов­ки AltDeploy.</p>
  <p id="jhOT"><strong>Не­дос­татки:</strong> толь­ко macOS; нужен Xcode; слож­но нас­тра­ивать; огра­ниче­ния пер­сональ­ной учет­ной записи.</p>
  <figure id="q1zs" class="m_original">
    <img src="https://st768.s3.eu-central-1.amazonaws.com/0b8d51abf8afdecf90906eebe9e102fc/19638/ios-app-signer-screenshot.png" width="736" />
    <figcaption>iOS App Signer</figcaption>
  </figure>
  <h3 id="ALTDEPLOY-И-ALTSTORE">ALTDEPLOY И ALTSTORE</h3>
  <p id="xYcD"><a href="https://altstore.io/faq" target="_blank">AltStore</a> — инте­рес­ный и рас­простра­нен­ный спо­соб для уста­нов­ки неофи­циаль­ных при­ложе­ний и эму­лято­ров на устрой­ства с iOS без джей­лбрей­ка. С инс­трук­циями по уста­нов­ке мож­но озна­комить­ся на <a href="https://altstore.io/faq/" target="_blank">сай­те про­екта</a>.</p>
  <p id="lazc">В срав­нении с опи­сан­ными ниже онлай­новыми магази­нами при­ложе­ний AltStore дей­стви­тель­но дос­той­ная аль­тер­натива. Ты можешь лич­но про­кон­тро­лиро­вать про­исхожде­ние пакета IPA, а под­писан он будет тво­им собс­твен­ным пер­сональ­ным сер­тифика­том, который Apple вне­зап­но не анну­лиру­ет, как это час­то про­исхо­дит с сер­висами типа IPWind и аль­тер­натив­ными магази­нами при­ложе­ний, опи­сан­ными ниже.</p>
  <figure id="pZLn" class="m_original">
    <img src="https://st768.s3.eu-central-1.amazonaws.com/0b8d51abf8afdecf90906eebe9e102fc/19640/install-altstore.jpg" width="640" />
    <figcaption>Ус­танов­ка AltStore</figcaption>
  </figure>
  <p id="lrcA">Не­дос­татков у это­го решения тоже хва­тает. Во‑пер­вых, все минусы пер­сональ­ных сер­тифика­тов: огра­ниче­ние на чис­ло уста­нов­ленных при­ложе­ний (не более трех) и вре­мя их работы (не более семи дней). Во‑вто­рых, необ­ходимость уста­нов­ки и нас­трой­ки как при­ложе­ния iTunes с вклю­чен­ной син­хро­низа­цией через Wi-Fi, так и сер­верной час­ти AltServer (которая будет исполь­зовать­ся, что­бы авто­мати­чес­ки перепод­писывать уста­нов­ленные при­ложе­ния каж­дые семь дней).</p>
  <p id="a0ou">Сто­ят ли уси­лия того, что­бы уста­новить на устрой­ство до трех сто­рон­них ути­лит? Здо­рово сом­нева­юсь. А вот сов­мес­тно с учет­ной записью раз­работ­чика это уже впол­не может иметь смысл для уста­нов­ки при­ложе­ний, которых нет и не будет в офи­циаль­ном App Store.</p>
  <p id="qQVa"><a href="https://github.com/pixelomer/AltDeploy/releases" target="_blank">AltDeploy</a> — фак­тичес­ки форк решения AltStore. В отли­чие от AltStore, который уста­нав­лива­ется на само устрой­ство с iOS, AltDeploy поз­воля­ет уста­новить и под­писать при­ложе­ние непос­редс­твен­но с компь­юте­ра. При этом тре­бует­ся компь­ютер с macOS и тра­дици­онные для AltServer прыж­ки по коч­кам. Под­робные инс­трук­ции по уста­нов­ке — <a href="https://iosninja.io/blog/sideload-ios-apps-with-altdeploy/" target="_blank">здесь</a>.</p>
  <figure id="ditE" class="m_original">
    <img src="https://st768.s3.eu-central-1.amazonaws.com/0b8d51abf8afdecf90906eebe9e102fc/19633/altdeploy.png" width="1184" />
    <figcaption>AltDeploy</figcaption>
  </figure>
  <h3 id="ПОДПИСЬ-В-РЕЖИМЕ-ОНЛАЙН">ПОДПИСЬ В РЕЖИМЕ ОНЛАЙН</h3>
  <p id="Rabq">Су­щес­тву­ют бес­плат­ные сер­висы, поз­воля­ющие под­писать пакет при­ложе­ния в режиме онлайн, без свя­зи устрой­ства с компь­юте­ром. При­мер такого сер­виса — <a href="https://ipasign.herokuapp.com/upload" target="_blank">IPASign</a>.</p>
  <figure id="GS2s" class="m_original">
    <img src="https://st768.s3.eu-central-1.amazonaws.com/0b8d51abf8afdecf90906eebe9e102fc/19641/ipasign.jpg" width="900" />
    <figcaption>Сер­вис IPASign</figcaption>
  </figure>
  <p id="uwKP">По­мимо собс­твен­но фай­ла IPA, сер­вис про­сит пре­дос­тавить сер­тификат p12 для под­писи, пароль и файл provisioning. Сер­вис выдаст QR-код, отска­ниро­вав который на iPhone мож­но уста­новить под­писан­ный IPA без свя­зи с компь­юте­ром. Если ты собира­ешь­ся вос­поль­зовать­ся сво­им собс­твен­ным сер­тифика­том — дваж­ды подумай, сто­ит ли доверять ано­ним­ному сер­вису. Впро­чем, если к тебе в руки попал кор­поратив­ный сер­тификат из утеч­ки и ты хочешь про­тес­тировать его работу — воп­росов не воз­ника­ет.</p>
  <p id="cXsi">Как это реали­зова­но? С боль­шой веро­ятностью за кулиса­ми спря­тан компь­ютер с macOS и Xcode, к которо­му прик­ручен веб‑интерфейс. Детали реали­зации неиз­вес­тны.</p>
  <p id="nXzx"><a href="https://ipawind.com/" target="_blank">IPAWind</a> — еще один подоб­ный сер­вис. Поз­воля­ет под­писывать пакеты не толь­ко сво­им сер­тифика­том, но и их собс­твен­ным (такой сер­тификат может быть анну­лиро­ван в любой момент, зато твой акка­унт оста­нет­ся вне подоз­рений). Как бонус: воз­можность редак­тировать манифест, бла­года­ря чему мож­но уста­нав­ливать дуб­ликат при­ложе­ния (нап­ример, иметь на iPhone два WhatsApp), а так­же вклю­чать опцию iTunes Sharing, которая сде­лает рабочие фай­лы при­ложе­ния дос­тупны­ми через iTunes.</p>
  <h3 id="АЛЬТЕРНАТИВНЫЕ-МАГАЗИНЫ-ПРИЛОЖЕНИЙ">АЛЬТЕРНАТИВНЫЕ МАГАЗИНЫ ПРИЛОЖЕНИЙ</h3>
  <p id="wpza">Вы­ше были опи­саны штат­ные спо­собы уста­новить при­ложе­ние на устрой­ство; в худ­шем слу­чае мы всту­пали на тер­риторию «серой зоны». Спо­собы, опи­сан­ные далее, в явном виде наруша­ют полити­ки Apple и в некото­рых слу­чаях могут нарушать пра­ва дру­гих пра­вооб­ладате­лей.</p>
  <p id="dqC5">Пер­вый такой вари­ант — сто­рон­ние магази­ны при­ложе­ний. Все подоб­ные решения харак­теризу­ются прос­тотой уста­нов­ки и исполь­зования (открыл стра­ницу магази­на в Safari, нажал кноп­ку, получил на устрой­ство аль­тер­натив­ный магазин при­ложе­ний, под­твер­дил сер­тификат — и мож­но работать). Есть как плат­ные, так и бес­плат­ные вари­анты. Самые извес­тные из них:</p>
  <ul id="mhci">
    <li id="ZDhT"><a href="https://app.ignition.fun/" target="_blank">Ignition</a> — спе­циали­зиру­ется на ути­литах джей­лбрей­ка, тви­ках и пат­ченных при­ложе­ниях;</li>
    <li id="ccYe"><a href="https://www.tweakboxapp.com/" target="_blank">TweakBox</a> — содер­жит в катало­ге ути­литы, эму­лято­ры, джей­лбрей­ки и мно­гое дру­гое (<a href="https://sideload.tweakboxapp.com/" target="_blank">ка­талог</a>);</li>
    <li id="ZtQw"><a href="https://ipastore.me/" target="_blank">iPASTORE</a> — плат­ный (под­писка) сто­рон­ний магазин при­ложе­ний.</li>
  </ul>
  <p id="pUNG">Эти­ми тре­мя спи­сок подоб­ных сер­висов не огра­ничи­вает­ся. AppValley, CokernutX, Panda Helper, плат­ный AppDB, TweakDoor, Emus4u, iPABox, Zestia… Не все пережи­ли выход iOS 14, но мно­гие про­дол­жают работать и поныне.</p>
  <p id="wEGh">Все эти магази­ны, вклю­чая плат­ные сер­висы, фун­кци­они­руют с наруше­нием полити­ки Apple: нецеле­вое исполь­зование сер­тифика­тов раз­работ­чиков, исполь­зование «утек­ших» или спе­циаль­но куп­ленных кор­поратив­ных сер­тифика­тов и соот­ветс­тву­ющих механиз­мов дос­тавки. Apple регуляр­но бло­киру­ет такие сер­тифика­ты, но сер­висы всег­да находят замену и перепод­писыва­ют как само при­ложе­ние‑магазин, так и уста­нов­ленные с его помощью ути­литы. <a href="https://ipastore.me/replacements-exchanges/" target="_blank">Вот что пишет об этом сам сер­вис</a>.</p>
  <p id="JkgA">Ка­кие рис­ки воз­можны при исполь­зовании подоб­ных сер­висов? Отоз­ванный Apple сер­тификат может при­вес­ти к невоз­можнос­ти запус­тить уста­нов­ленное при­ложе­ние. Тех­ничес­кая воз­можность модифи­циро­вать (пат­чить) при­ложе­ния на сто­роне сер­виса озна­чает веро­ятность получить вмес­те с уста­нов­ленной прог­раммой неп­рият­ный «довесок», который (в слу­чае ста­рых вер­сий iOS) может даже взло­мать устрой­ство.</p>
  <p id="wTG5">Поль­зовать­ся подоб­ными магази­нами или нет — решать тебе.</p>
  <p id="FoDa">Для взло­ман­ных устрой­ств дос­тупно нес­коль­ко магази­нов при­ложе­ний: <a href="https://cydia.saurik.com/" target="_blank">Cydia</a>, <a href="https://getsileo.app/" target="_blank">Sileo</a>, <a href="https://getzbra.com/" target="_blank">Zebra</a>, <a href="https://apptapp.me/repo" target="_blank">Installer 5</a>. <a href="https://www.reddit.com/r/jailbreak/comments/kfv68a/question_cydia_vs_sileo_vs_zebra_vs_installer_5/" target="_blank">Ка­кой из них выб­рать?</a> У раз­работ­чиков ути­лит для джей­лбрей­ка, как пра­вило, есть свой «любимый» магазин при­ложе­ний, который и будет уста­нов­лен на устрой­ство пос­ле взло­ма. При этом ты всег­да можешь парал­лель­но уста­новить допол­нитель­ный магазин при­ложе­ний.</p>
  <p id="d1CS">На взло­ман­ных устрой­ствах нет огра­ниче­ний, свя­зан­ных с исполь­зовани­ем пер­сональ­ных про­филей. Мож­но уста­нав­ливать любое количес­тво при­ложе­ний; не будет и огра­ниче­ний по вре­мени работы.</p>
  <h3 id="TESTFLIGHT">TESTFLIGHT</h3>
  <p id="zkye">TestFlight — это сер­вис тес­тирова­ния iOS-при­ложе­ний и одно­имен­ное при­ложе­ние, которое поль­зователь может уста­новить на свое устрой­ство. С тех­ничес­кой точ­ки зре­ния TestFlight упро­щает дис­три­буцию тес­товых сбо­рок, облегчая про­цесс сбо­ра кодов тес­товых устрой­ств (UDID) и поз­воляя рас­простра­нять сбор­ки сре­ди зарегис­три­рован­ных учас­тни­ков тес­тирова­ния. До бес­конеч­ности тес­товыми сбор­ками поль­зовать­ся нель­зя; рано или поз­дно сер­тификат исте­кает, и поль­зовате­лю при­ходит­ся или обновлять­ся на офи­циаль­ную вер­сию при­ложе­ния, или уста­нав­ливать све­жую тес­товую сбор­ку, которую пре­дос­тавит раз­работ­чик.</p>
  <p id="auAq">Сер­висом TestFlight могут вос­поль­зовать­ся как кор­поратив­ные, так и час­тные раз­работ­чики. В пос­леднем слу­чае будет огра­ниче­ние на мак­сималь­ное чис­ло учас­тни­ков бета‑тес­тирова­ния — не более 100 UDID в год. Уда­ление UDID из прог­раммы не осво­бож­дает слот.</p>
  <p id="J4DH">Не­кото­рые раз­работ­чики поль­зуют­ся этим сер­висом для дис­три­буции ПО, которое по тем или иным при­чинам не при­нима­ют в App Store. Самый извес­тный при­мер такого при­ложе­ния — Soap4me для плат­формы iOS, которое находит­ся в сос­тоянии пер­манен­тно­го бета‑тес­тирова­ния. В прин­ципе, впол­не себе решение — но для обыч­ного поль­зовате­ля избы­точ­но слож­ное.</p>
  <h3 id="ГДЕ-ВЗЯТЬ-ПАКЕТЫ-ПРИЛОЖЕНИЙ?">ГДЕ ВЗЯТЬ ПАКЕТЫ ПРИЛОЖЕНИЙ?</h3>
  <p id="9ciL">На­вер­ное, самый извес­тный репози­торий пакетов IPA — <a href="https://iosninja.io/ipa-library" target="_blank">iOS Ninja</a>. С сай­та мож­но ска­чать как сами пакеты при­ложе­ний, так и обра­зы про­шивок Apple для ряда устрой­ств (по пря­мым ссыл­кам с сай­та Apple). Ска­чан­ные с сай­та пакеты для уста­нов­ки на iPhone пот­ребу­ется под­писать одним из опи­сан­ных выше спо­собов.</p>
  <h3 id="ЗАКЛЮЧЕНИЕ">ЗАКЛЮЧЕНИЕ</h3>
  <p id="x09g">«Пла­ти или стра­дай» — такой вывод мож­но сде­лать из этой статьи. Дей­стви­тель­но, опла­тив учас­тие в прог­рамме для раз­работ­чиков, мож­но забыть о сом­нитель­ных (час­то так­же небес­плат­ных) сер­висах и свя­зан­ных с ними рис­ках. Впро­чем, не факт, что в прог­рамме Apple для раз­работ­чиков вооб­ще удас­тся зарегис­три­ровать­ся; в пос­леднее вре­мя это ста­ло неп­росто. Бес­плат­ная аль­тер­натива — AltStore — тре­бует серь­езных уси­лий для уста­нов­ки и нас­трой­ки, а так­же пос­тоян­ной воз­ни с перепод­писыва­нием уста­нов­ленных при­ложе­ний, для авто­мати­зации которой нуж­на пос­тоян­но работа­ющая на компь­юте­ре сер­верная часть. Уста­нов­ка джей­лбрей­ка — уни­вер­саль­ное решение, лиша­ющее, впро­чем, одно­го из основных пре­иму­ществ iOS — дос­тупа к регуляр­ным обновле­ниям. Каким из этих спо­собов вос­поль­зовать­ся и сто­ит ли овчинка выдел­ки? Решать, как водит­ся, тебе.</p>
  <p id="ZDIE"><a href="https://t.me/anon_chan_by" target="_blank">t.me/anon_chan_by</a></p>

]]></content:encoded></item><item><guid isPermaLink="true">https://teletype.in/@anon_channel/K0x7IzLUBoN</guid><link>https://teletype.in/@anon_channel/K0x7IzLUBoN?utm_source=teletype&amp;utm_medium=feed_rss&amp;utm_campaign=anon_channel</link><comments>https://teletype.in/@anon_channel/K0x7IzLUBoN?utm_source=teletype&amp;utm_medium=feed_rss&amp;utm_campaign=anon_channel#comments</comments><dc:creator>anon_channel</dc:creator><title>Хакер - Вкуриваем QR. Как сделать QR-код с сюрпризом</title><pubDate>Tue, 09 Nov 2021 03:57:15 GMT</pubDate><media:content medium="image" url="https://img4.teletype.in/files/bf/13/bf13b4cc-5b85-426b-9c0b-a61de447b026.png"></media:content><description><![CDATA[<img src="https://st768.s3.eu-central-1.amazonaws.com/4a82c206403f6b33f051b6ca44df24fa/14202/protected.png"></img>Содержание статьи]]></description><content:encoded><![CDATA[
  <h3 id="Содержание-статьи"><a href="https://t.me/anon_chan_by" target="_blank">https://t.me/anon_chan_by</a></h3>
  <p id="v4sb">Содержание статьи</p>
  <ul id="Lv9k">
    <li id="KP0v">История вектора атаки</li>
    <li id="FMcf">QRGen — каждому по коду</li>
    <li id="PHvs">Возможные атаки</li>
    <li id="IGDj">Практика</li>
    <li id="TeiV">QRLJacker</li>
    <li id="5OrZ">Написание своих модулей</li>
    <li id="vgOh">Угоняем сессию</li>
    <li id="xkdf">Итоги</li>
  </ul>
  <p id="rsdb">QR-код сейчас совершенно обыденная вещь — они встречаются повсюду, их используют как один из способов авторизации крупные сервисы вроде WhatsApp, Яндекса и AliExpress, встречаются QR-коды для подключения к Wi-Fi. Но насколько надежна эта технология? Можно ли создать такой QR-код, при сканировании которого выполнится нагрузка на девайсе жертвы? Этот вопрос мы сегодня разберем подробнее.</p>
  <p id="snVx">QR-код (англ. Quick Response Code — код быстрого реагирования) — это матричный или двумерный штрих-код, который может содержать до 4296 символов ASCII. То есть, проще говоря, картинка, в которой зашифрован текст.</p>
  <h3 id="История-вектора-атаки">История вектора атаки</h3>
  <p id="KPbK">В мае 2013 года специалисты компании по сетевой безопасности Lookout Mobile разработали специальные QR-коды, которые смогли скомпрометировать очки Google Glass. На тот момент очки сканировали все фотографии, «которые могут быть полезны их владельцу», — и предоставили взломщикам полный удаленный доступ к устройству. Исследователи сообщили в Google о данной уязвимости, и ее закрыли буквально за несколько недель. К счастью, исправить успели до того, как ее можно было использовать вне лаборатории, ведь взлом очков реального пользователя мог привести к большим проблемам.</p>
  <p id="6wXN">В 2014 году программа Barcode Scanner для мобильных устройств из проекта ZXing практически не проверяла тип URI, передаваемый через QR-код. В результате любой эксплоит, который мог быть исполнен браузером (например, написанный на JavaScript), можно было передать через QR.</p>
  <p id="VOdD">Сканер пытался отфильтровать опасные виды атак с помощью регулярных выражений, требуя, чтобы URI имел период с последующим продлением как минимум на два символа, транспортный протокол длиной не менее двух символов, за которым следует двоеточие, и чтобы в URI не было пробелов.</p>
  <p id="pdRh">Если содержимое не соответствует хотя бы одному из требований, то оно определяется как обычный текст, а не URI. Этот механизм блокирует атаки вроде <code>javascript;alert(&quot;You have won 1000 dollars! Just Click The Open Browser Button&quot;);</code>, но, внеся пару простых изменений в код, мы получаем вариант, который программа исполняла в браузере, ведь она считала JS-код обыкновенным, «нормальным» URI!</p>
  <p id="d743">Вот как это выглядело.</p>
  <figure id="QTHj" class="m_original">
    <img src="https://st768.s3.eu-central-1.amazonaws.com/4a82c206403f6b33f051b6ca44df24fa/14202/protected.png" width="951" />
    <figcaption>Вариант кода, который блокировался защитным механизмом сканера</figcaption>
  </figure>
  <p id="DrxF">Как мы можем увидеть, уведомление появилось в браузере, а значит, URI с потенциально вредоносным кодом был выполнен. Однако выполняется данный JS-код лишь тогда, когда пользователь нажимает Open Browser (то есть «Открыть в браузере»).<br />Еще один интересный пример из 2012 года: эксперт по информационной безопасности Равишанкар Боргаонкар (Ravishankar Borgaonkar) продемонстрировал, как сканирование простейшего QR может привести к форматированию устройств Samsung! Что же было внутри? MMI-код для сброса до заводских настроек: <code>*2767*3855#</code>, а также префикс <code>tel:</code> для совершения USSD-запроса.</p>
  <p id="CtQz">Самое опасное здесь — что человек без предварительной подготовки не может узнать содержимое кода, не отсканировав его. А человек очень любопытен: в различных исследованиях большинство испытуемых (которые, кстати, даже не знали об эксперименте) сканировали QR-код именно из любопытства, забывая о собственной безопасности. Поэтому всегда будь внимателен!</p>
  <h3 id="WWW">WWW</h3>
  <p id="HK6g">Если у тебя нет сканера кодов, но уйма свободного времени — можно попробовать расшифровать код вручную. Инструкция есть на <a href="https://habr.com/ru/post/127197/" target="_blank">Хабре</a>.</p>
  <h3 id="QRGen-—-каждому-по-коду">QRGen — каждому по коду</h3>
  <p id="BW5d">Для демонстрации средств работы с QR-кодами я буду использовать Kali Linux 2019.2 с установленным Python версии 3.7 — это необходимо для корректной работы утилит.</p>
  <h3 id="WARNING">WARNING</h3>
  <p id="Y8nu">Не забывай про уголовную ответственность за создание и распространение вредоносных программ, к которым в широком смысле относятся и наши «заряженные» QR-коды.</p>
  <p id="9XVi">Начнем с утилиты QRGen, которая позволяет создавать QR-коды с закодированными в них скриптами. Копируем репозиторий и переходим в папку с содержимым.</p>
  <pre id="VTOX">git clone https://github.com/h0nus/QRGen
cd QRGen &amp;&amp; ls
</pre>
  <h3 id="INFO">INFO</h3>
  <p id="o1Yx">QRGen требует Python версии 3.6 и выше. Если возникает ошибка, попробуй обновить интерпретатор.</p>
  <p id="nGQb">Устанавливаем все зависимости и запускаем сам скрипт.</p>
  <pre id="Rks5">pip3 install -r requirements.txt
## или python3 -m pip install -r requirements.txt
python3 qrgen.py
</pre>
  <p id="J619">Видим справку.</p>
  <figure id="9014" class="m_original">
    <img src="https://st768.s3.eu-central-1.amazonaws.com/4a82c206403f6b33f051b6ca44df24fa/14206/qrgenhelp.png" width="626" />
    <figcaption>Справка QRGen</figcaption>
  </figure>
  <p id="NCoa">Аргумент <code>-h</code> выведет то же самое, а вот запуск с ключом <code>-l</code> приведет к генерации QR-кодов из определенной категории. Всего их восемь.</p>
  <ol id="pI49">
    <li id="6cM1">SQL-инъекции.</li>
    <li id="oWdd">XSS.</li>
    <li id="foUn">Инъекции команд.</li>
    <li id="RWNN">QR с форматированной строкой.</li>
    <li id="NRf5">XXE.</li>
    <li id="7Zb6">Фаззинг строк.</li>
    <li id="35oZ">SSI-инъекции.</li>
    <li id="RkTs">LFI или получение доступа к скрытым каталогам.</li>
  </ol>
  <h3 id="Возможные-атаки">Возможные атаки</h3>
  <p id="CCwA">Теперь давай посмотрим на примеры из каждой категории, а также разберемся, какой урон и каким устройствам они могут нанести.</p>
  <pre id="W8SF">1. 0&#x27;XOR(if(now()=sysdate(),sleep(6),0))XOR&#x27;Z
2. &lt;svg onload=alert(1)&gt;
3. cat /etc/passwd
4. %d%d%d%d%d%d%d%d%d%d
5. &lt;!ENTITY % xxe SYSTEM &quot;php://filter/convert.base64-encode/resource=/etc/passwd&quot; &gt;
6. &quot;A&quot; x 33
7. &lt;pre&gt;&lt;!--#exec cmd=&quot;ls&quot; --&gt;&lt;/pre&gt;
8. ../../../../../../etc/passwd
</pre>
  <p id="fWAR">Посмотреть текстовые файлы со всеми вариантами «начинки» QR-кодов ты можешь в папке <code>words</code> (они разделены по категориям, указанным выше).</p>
  <p id="LpkQ">Теперь пара слов о последствиях атак подобными нагрузками.</p>
  <p id="h1Fz">Первый класс атак — SQL-инъекции — используют при взломе БД и нарушении работы веб-сайтов. Например, запрос может вызывать зависание сайта.</p>
  <p id="6TQD">Следующий пример (под номером 2) демонстрирует эксплуатацию XSS-уязвимости при атаке на веб-приложения с использованием SVG (Scalable Vector Graphic). К чему может привести XSS, ты, думаю, и без меня прекрасно знаешь, так что подробно на этом останавливаться не буду.</p>
  <p id="WSsG">Третий пункт выводит на экран жертвы содержимое файла <code>/etc/passwd</code>: список аккаунтов Linux-based-систем и дополнительную информацию о них (раньше — хеши паролей этих учетных записей). В подобных случаях обычно стараются получить <code>/etc/shadow</code> и конфигурацию сервера, но все очень сильно зависит от цели, так что какие файлы читать — решай сам.</p>
  <p id="AhaA">Четвертый пример представляет собой выражение, которое вызовет переполнение буфера (buffer overflow). Оно возникает, когда объем данных для записи или чтения больше, чем вмещает буфер, и способно вызвать аварийное завершение или зависание программы, ведущее к отказу в обслуживании (denial of service, DoS). Отдельные виды переполнений дают злоумышленнику возможность загрузить и выполнить произвольный машинный код от имени программы и с правами учетной записи, от которой она выполняется, что делает эту ошибку довольно опасной.</p>
  <p id="IVri">Пятый по счету класс атак (XXE Injections) представляет собой вариант получения скрытой информации веб-сервера с помощью анализа вывода XML-файлов. Конкретно в нашем примере при запросе к серверу тот ответит зашифрованным в Base64 содержимым файла <code>/etc/passwd</code>, который уже упоминался. Однако расшифровать его не составит труда — достаточно лишь воспользоваться встроенной в большинство дистрибутивов Linux утилитой <code>base64</code> либо же онлайн-конвертером.</p>
  <p id="pxYz">Атаки форматной строки (пример 6) — это класс уязвимостей, который включает в себя предоставление «специфичных для языка маркеров формата» для выполнения произвольного кода или сбоя программы. Говоря человеческим языком, это класс атак, при которых приложение некорректно очищает пользовательский ввод от управляющих конструкций, из-за чего эти конструкции в результате исполняются. Если ты программировал на С, то, конечно, помнишь те интересности с выводом переменных через <code>printf</code>: надо было в первом аргументе (который строка) указать на тип выводимого значения (<code>%d</code> для десятичного числа и так далее).</p>
  <p id="9zqQ">Седьмой пункт представляет собой вариант command injection, которая выполняет определенный код на стороне сервера. В моем примере будет выполнена команда <code>ls</code>, которая покажет содержимое текущей директории, но, конечно, там может быть гораздо более опасный код.</p>
  <p id="9B2e">И наконец, последняя категория — это LFI-уязвимости (Local File Inclusion; включение локальных файлов), позволяющие просмотреть на уязвимых (или неправильно настроенных) серверах файлы и папки, которые не должны были быть видны всем. Один из возможных вариантов — просмотреть файл <code>/etc/passwd</code>, о котором мы с тобой уже не раз говорили. Это может выглядеть вот так.</p>
  <figure id="nnqU" class="m_original">
    <img src="https://st768.s3.eu-central-1.amazonaws.com/4a82c206403f6b33f051b6ca44df24fa/14198/dvwalfidemo.png" width="624" />
  </figure>
  <p id="sLNR">Обрати внимание, что в качестве тестового веб-приложения используется <a href="http://www.dvwa.co.uk/" target="_blank">DVWA</a> (Damn Vulnerable Web Application), который был специально разработан для обучения пентесту. Многие атаки на веб-приложения можно отработать на нем.</p>
  <h3 id="Практика">Практика</h3>
  <p id="jBV5">А сейчас перейдем к практике — протестируем эту утилиту сами.</p>
  <p id="AJWz">Например, запустим ее с ключом <code>-l 5</code>:</p>
  <pre id="ybRj">python3 qrgen.py -l 5
</pre>
  <p id="7Vj1">Утилита сгенерировала 46 QR-кодов с полезными нагрузками. Все они лежат в папке <code>genqr</code>.</p>
  <figure id="jjPo" class="m_original">
    <img src="https://st768.s3.eu-central-1.amazonaws.com/4a82c206403f6b33f051b6ca44df24fa/14208/qrgenok.png" width="661" />
  </figure>
  <p id="NLHZ">Каждый из них содержит вредоносный код, поэтому хоть я и приведу пример, но часть его будет вырезана.</p>
  <figure id="cJ9u" class="m_original">
    <img src="https://st768.s3.eu-central-1.amazonaws.com/4a82c206403f6b33f051b6ca44df24fa/14204/qrexample0.png" width="290" />
  </figure>
  <p id="8sod">Теперь можем запустить скрипт с флагом <code>-w</code> (напомню, он заставляет скрипт использовать кастомный словарь), но сначала нам нужен файл с нашими полезными (и не очень) нагрузками. Можем использовать готовые нагрузки из Metasploit (в Kali они находятся по пути <code>/usr/share/metasploit-framework/modules/payloads</code>) либо же создать новый текстовый документ и в него записать что-нибудь «плохое», например команду для удаления всех файлов на Linux-based-системе:</p>
  <pre id="mFFc">rm -rf /*
</pre>
  <p id="DopQ">Итак, я назвал наш «вирус» <code>clear.txt</code> и запускаю QRGen (предварительно удалив или очистив папку <code>genqr</code>):</p>
  <pre id="x9iU">python3 qrgen.py -w /путь/до/clear.txt
</pre>
  <p id="eRDC">Иногда может возникать ошибка, как на скриншоте ниже. Не пугайся, на работоспособность генератора кодов она не влияет.</p>
  <figure id="ULBy" class="m_original">
    <img src="https://st768.s3.eu-central-1.amazonaws.com/4a82c206403f6b33f051b6ca44df24fa/14203/pyerror.png" width="713" />
    <figcaption>Ошибка</figcaption>
  </figure>
  <p id="hw1e">Если ты перфекционист и хочешь ее исправить, то замени <code>format(i-1)</code> на <code>format(i)</code> в самом конце скрипта.</p>
  <p id="Mq2d">Теперь давай посмотрим на сам QR-код (естественно, с вырезанной частью) и отсканируем его на одном из онлайн-сервисов.</p>
  <figure id="uTqE" class="m_original">
    <img src="https://st768.s3.eu-central-1.amazonaws.com/4a82c206403f6b33f051b6ca44df24fa/14205/qrexample1.png" width="290" />
  </figure>
  <p id="mGDt">Как мы можем видеть из скриншота выше, наш текст был абсолютно верно перенесен в QR-код!</p>
  <p id="JJwz">Эта утилита (и вектор атаки) направлена скорее на проверку незащищенного и непопулярного ПО либо же узкоспециализированных инструментов (вроде складских QR-сканеров, отправляющих SQL-запросы к базе данных компании). Большинство современных сканеров из соображений безопасности не выполняют находящийся в QR код. Соответственно, вариантов развития событий после сканирования два.</p>
  <ol id="sPZC">
    <li id="veH0">Сканер просто выводит содержимое нашего изображения (невыгодный для хакера вариант).</li>
    <li id="e4PE">Сканер исполняет код, находящийся внутри изображения, либо же, используя пример, о котором мы говорили раньше, отправляет SQL-запрос к БД организации. Он и становится первым шагом к взлому базы данных компании. Естественно, глупо при таком раскладе рассчитывать, что распознанный текст будет выполнен как самостоятельный запрос, так что бери нагрузку вроде той, которую обычно используешь в веб-приложениях.</li>
  </ol>
  <h3 id="QRLJacker">QRLJacker</h3>
  <p id="Lu0F">Теперь переходим ко второму инструменту — QRLJacker. Он отчасти похож на QRGen, но представляет совершенно другой вектор атаки — QRLJacking.</p>
  <p id="60Kc">SQRL (произносится как squirrel — белка, а расшифровывается как Secure, Quick, Reliable Login или Secure Quick Response Login) — открытый проект для безопасного входа на веб-сайт и аутентификации. При входе, естественно, используется QR-код, который обеспечивает проверку подлинности.</p>
  <h3 id="WWW">WWW</h3>
  <p id="Hnts"><a href="https://www.grc.com/sqrl/sqrl.htm" target="_blank">Официальная страница проекта</a></p>
  <p id="s0e7">Как же выполняется вход при использовании данного способа аутентификации?</p>
  <figure id="SFCC" class="m_original">
    <img src="https://st768.s3.eu-central-1.amazonaws.com/4a82c206403f6b33f051b6ca44df24fa/14215/sqrlnormal.png" width="753" />
  </figure>
  <ol id="0mZQ">
    <li id="br9e">Пользователь посещает сайт и открывает сессию.</li>
    <li id="fJqK">Сайт генерирует QR-код с ключом сессии. Этот код регулярно меняется в целях безопасности.</li>
    <li id="hxvV">Пользователь сканирует QR-код.</li>
    <li id="ABgg">Мобильное приложение генерирует аутентификационный сигнал, который содержит секретный токен (в него входят ID пользователя, код сессии, специальное сообщение, созданное с помощью приватного ключа пользователя).</li>
    <li id="olH1">Сайт получает сигнал и идентифицирует пользователя, производя вход (если, конечно, верификация завершена корректно).</li>
  </ol>
  <p id="zd8p">Довольно долго метод SQRL считался действительно безопасным, пока Мохамед Бассет (Mohamed Basset) не предложил способ атаки на сервисы, использующие SQRL, который был назван QRLJacking. Способ требует создать фишинговую страницу и разместить на ней генерируемый через определенные промежутки времени QR-код. Давай рассмотрим его поподробнее.</p>
  <figure id="HbOX" class="m_original">
    <img src="https://st768.s3.eu-central-1.amazonaws.com/4a82c206403f6b33f051b6ca44df24fa/14214/sqrlhack.png" width="672" />
  </figure>
  <ol id="XJ6B">
    <li id="i5z2">Злоумышленник инициирует клиентскую QR-сессию и клонирует код QR-логина на фишинговую страницу.</li>
    <li id="TBDp">Жертве отправляется ссылка на эту страницу. Выглядит страничка вполне безопасно.</li>
    <li id="MmE8">Жертва сканирует поддельный QR-код, а приложение отправляет секретный токен, завершающий процесс аутентификации.</li>
    <li id="vcgw">Злоумышленник получает подтверждение от сервиса и теперь может контролировать аккаунт жертвы.</li>
  </ol>
  <p id="Bh07">Именно для реализации данного метода была создана утилита QRLJacker, о которой сейчас и пойдет речь.</p>
  <p id="m8ov">Какие веб-ресурсы уязвимы перед подобным вектором атаки? По заверению разработчиков, это популярные мессенджеры вроде WhatsApp, WeChat, Discord, Line, все сервисы Яндекса (ведь для входа в любой из них требуется вход в Яндекс.Паспорт, который и предоставляет возможность аутентификации через QR), популярные торговые площадки Alibaba, AliExpress, Tmall и Taobao, сервис AliPay, а также приложение для удаленного доступа AirDroid. Само собой, список неполный, ведь все ресурсы, использующие SQRL, просто не перечесть.</p>
  <p id="CYK9">Теперь давай установим утилиту QRLJacker (программа работает только на Linux и macOS, более подробную информацию можешь найти в <a href="https://github.com/OWASP/QRLJacking/tree/master/QRLJacker#prerequisites-before-installing" target="_blank">README проекта</a>, к тому же нам необходим Python 3.7+).</p>
  <ol id="jiqk">
    <li id="WcBo">Заходим в систему от имени суперпользователя (root), иначе Firefox может выдать ошибку при запуске модулей фреймворка QRLJacker.</li>
    <li id="zNEy">Обновляем Firefox до последней версии.</li>
    <li id="7NS8">Скачиваем самый новый <code>geckodriver</code> с <a href="https://github.com/mozilla/geckodriver/releases" target="_blank">GitHub</a> и распаковываем файл, затем выполняем команды</li>
  </ol>
  <pre id="t34E">chmod +x geckodriver 
sudo mv -f geckodriver /usr/local/share/geckodriver 
sudo ln -s /usr/local/share/geckodriver /usr/local/bin/geckodriver 
sudo ln -s /usr/local/share/geckodriver /usr/bin/geckodriver 
</pre>
  <ol id="h0NN">
    <li id="lJ1X">Клонируем репозиторий и переходим в папку с содержимым:</li>
  </ol>
  <pre id="hzax">git clone https://github.com/OWASP/QRLJacking 
cd QRLJacking/QRLJacker &amp;&amp; ls
</pre>
  <ol id="X1aN">
    <li id="zqy1">Устанавливаем все зависимости:</li>
  </ol>
  <pre id="xcPq">python3.7 -m pip install -r requirements.txt
</pre>
  <ol id="u2ym">
    <li id="FnnO">Запускаем фреймворк (с ключом <code>--help</code> для получения краткой справки):</li>
  </ol>
  <pre id="37bN">python3.7 QrlJacker.py --help
</pre>
  <figure id="u2KN" class="m_original">
    <img src="https://st768.s3.eu-central-1.amazonaws.com/4a82c206403f6b33f051b6ca44df24fa/14210/qrljackhelp.png" width="639" />
  </figure>
  <p id="Qfx1">При обычном запуске (без аргументов вовсе) ты увидишь примерно такую картинку.</p>
  <figure id="IH2I" class="m_original">
    <img src="https://st768.s3.eu-central-1.amazonaws.com/4a82c206403f6b33f051b6ca44df24fa/14211/qrljackloaded.png" width="806" />
  </figure>
  <p id="53pN">Прописав команду <code>help</code> внутри фреймворка, ты получишь полную справку по командам QRLJacker.</p>
  <p id="u5nl">Теперь давай запустим единственный (на данный момент) модуль — <code>grabber/whatsapp</code>. Список всех доступных модулей можем посмотреть командой <code>list</code>, выбрать модуль для использования — командой <code>use</code>. Команда <code>options</code> подскажет нам текущие значения опций, а <code>set</code> задаст то или иное значение опции. Команда <code>run</code> запустит наш модуль, а командой <code>jobs</code> мы можем просмотреть активные задачи.</p>
  <figure id="cSQS" class="m_original">
    <img src="https://st768.s3.eu-central-1.amazonaws.com/4a82c206403f6b33f051b6ca44df24fa/14216/akamsf.jpg" width="1175" />
    <figcaption>Вдохновлено Metasploit</figcaption>
  </figure>
  <p id="ory5">Порт 1337 стандартный для данного фреймворка, остальные опции я трогать не стал. <code>HOST</code> оставил локальным (0.0.0.0), но вывести его в сеть — не проблема. Это можно сделать, используя, например, <code>ngrok</code>:</p>
  <pre id="jzx2">ngrok http 1337
</pre>
  <p id="8UKL">Параметр <code>User-Agent</code> также решил оставить дефолтным (по умолчанию), но всего там три варианта: стандартный, случайный и кастомный (ручная настройка). Используй вариант, который тебе больше всего подходит.</p>
  <p id="mDxV">После чего запускаю модуль и смотрю текущие задачи. Там указан их ID, название модуля, а также адрес, на котором располагается страница модуля. По стандарту она выглядит так (QR-код частично замазан для защиты от ~~людей в погонах~~ злоупотреблений):</p>
  <figure id="4xhG" class="m_original">
    <img src="https://st768.s3.eu-central-1.amazonaws.com/4a82c206403f6b33f051b6ca44df24fa/14212/qrljackwaexample.png" width="1420" />
  </figure>
  <p id="Q0lj">Изменить эту страницу можно, поправив по своему вкусу файл <code>QRLJacker/core/templates/phishing_page.html</code>.</p>
  <p id="zZRO">Оригинальный исходник прост и незамысловат, что позволяет быстро изменить текст даже неподготовленному взломщику.</p>
  <figure id="XTMD" class="m_original">
    <img src="https://st768.s3.eu-central-1.amazonaws.com/4a82c206403f6b33f051b6ca44df24fa/14201/pagesrc.png" width="1706" />
  </figure>
  <p id="W9Q3">После внесения изменений в файле они будут автоматически применены в фреймворке.</p>
  <h3 id="Написание-своих-модулей">Написание своих модулей</h3>
  <p id="VoT3">Давай обсудим, что необходимо для создания своего модуля для QRLJacker.</p>
  <p id="LHmQ">Документацию и инструкцию по созданию модулей ты можешь найти в <a href="https://github.com/OWASP/QRLJacking/blob/master/QRLJacker/docs/README.md" target="_blank">репозитории проекта</a> либо в папке, которую ты клонировал раньше (<code>QRLJacker/docs/README.md</code>). Модули-грабберы — основа фреймворка, и располагаются они в <code>QRLJacker/core/modules/grabber</code>. Когда ты добавляешь туда любой Python-файл, он появляется в фреймворке с тремя опциями — хост, порт и юзерагент.</p>
  <p id="JoGl">Код модуля должен быть построен по такому шаблону:</p>
  <pre id="VDiT">## -*- coding: utf-8 -*-
from
 core.module_utils import types

class info:
    author = &quot;&quot;
    short_description = &quot;&quot;
    full_description = None

class execution:
    module_type= types.grabber
    name = &quot;&quot;
    url = &quot;&quot;
    image_xpath = &quot;&quot;
    img_reload_button = None
    change_identifier = &quot;&quot;
    session_type = &quot;localStorage&quot;
</pre>
  <p id="GHpY">Например, модуль <code>grabber/whatsapp</code> сделан именно в этом формате, посмотреть его также можно в <a href="https://github.com/OWASP/QRLJacking/blob/master/QRLJacker/core/modules/grabber/whatsapp.py" target="_blank">репозитории</a> или открыв сам Python-файл, лежащий в <code>QRJacker/core/modules/grabber/whatsapp.py</code>.</p>
  <p id="CEVZ">Теперь давай разберемся, что означает каждая из переменных, которые мы задаем на этих строках.</p>
  <h4 id="Класс-info">Класс info</h4>
  <p id="3jCX">Тут твое имя (или никнейм), которое появится при вызове справки модуля, краткое описание модуля и его полное описание (можно заполнять, можно оставить значение <code>None</code>). Больше ничего интересного в классе <code>info</code> нет, но прежде, чем мы перейдем к следующему (<code>execution</code>), давай посмотрим вызов справки (которая будет черпать информацию из кода) на примере модуля WhatsApp. Вот код <code>info</code>:</p>
  <pre id="mU9b">class info:
    author            = &quot;Karim Shoair (D4Vinci)&quot;
    short_description = &quot;Whatsapp QR-sessions grabber and controller&quot;
    full_description  = None
</pre>
  <p id="vcnv">А вот справка по модулю.</p>
  <p id="lo0G"><code>$ info grabber/whatsapp</code></p>
  <p id="PpgU">Module : grabber/whatsapp</p>
  <p id="wjLX">Provided by : Karim Shoair (D4Vinci)</p>
  <p id="3OyL">Description : Whatsapp QR-sessions grabber and controller</p>
  <h4 id="Класс-execution">Класс execution</h4>
  <p id="Saaj">Тут возни уже побольше: нужно не только название модуля, но и URL сайта, откуда будет браться QR-код и где будет производиться авторизация. Также нужен XPATH изображения с QR-кодом на странице. Чтобы понять, что это, опять обратимся к примеру в виде модуля WhatsApp. Там данный параметр выглядит как <code>/html/body/div[1]/div/div/div[2]/div[1]/div/div[2]</code>, то есть путь до объекта внутри HTML-документа.</p>
  <p id="fVkw">Далее нужен XPATH кнопки, которая обновляет QR-код на странице (если таковая имеется, в противном случае оставь значение None). Для большей конспирации используется XPATH элемента, который исчезает после получения сессии. Например, разработчики QRLJacker в модуле <code>grabber/whatsapp</code> использовали чекбокс «Запомнить меня».</p>
  <p id="RlIe">И напоследок нужна переменная, которая принимает значения <code>localStorage</code> или <code>Cookies</code>. Она должна соответствовать способу, с помощью которого на веб-сайте определяется пользовательская сессия.</p>
  <p id="mZ5g">Вот и все — после того как разберешься со всеми этими пунктами, тебе останется лишь добавить файл в папку с граббер-модулями и создать HTML-файл (<code>index.html</code>) со страницей в <code>core/www/твое_имя_модуля</code>.</p>
  <p id="PfxU">Готово! Ты создал свой модуль.</p>
  <h3 id="Угоняем-сессию">Угоняем сессию</h3>
  <p id="m2Zn">А теперь бегло посмотрим, как можно использовать этот фреймворк для атаки QRLJacking. Например, злоумышленник может скопировать оригинальный сайт <code>web.whatsapp.com</code> и вставить туда фальшивый QR-код для получения доступа к сессии. Или пример, который приводит сам создатель утилиты QRLJacker.</p>
  <figure id="lNMk" class="m_original">
    <img src="https://st768.s3.eu-central-1.amazonaws.com/4a82c206403f6b33f051b6ca44df24fa/14217/qrljackexample.jpg" width="650" />
  </figure>
  <p id="CImo">Это плагин, который, если зайти на популярный зарубежный сайт Amazon, выдаст тематическое уведомление о «получении подарка от WhatsApp в честь Дня святого Валентина» (обрати внимание на правый верхний угол). Естественно, чтобы получить подарок, нужно отсканировать QR-код, что не даст тебе ничего, кроме утечки личных данных. Будь очень бдителен, ведь, как я и показал раньше, этот вектор атаки и утилиты для его использования находятся в открытом доступе, а написать модуль для QRLJacker — задача, посильная даже начинающему питонисту.</p>
  <h3 id="Итоги">Итоги</h3>
  <p id="FEV4">Как ты (теперь) знаешь, даже использование QR-кода для логина больше нельзя считать безопасной практикой. Любой школьник с пачкой убедительно написанных писем может заманить на вполне настоящий сайт и угнать твой WhatsApp. Надеюсь, этот небольшой обзор отучит тебя бездумно сканировать каждый попавшийся на глаза код.</p>
  <figure id="66tY" class="m_original">
    <img src="https://st768.s3.eu-central-1.amazonaws.com/4a82c206403f6b33f051b6ca44df24fa/14213/readqr.png" width="376" />
  </figure>
  <figure id="QXqA" class="m_original">
    <img src="https://st768.s3.eu-central-1.amazonaws.com/4a82c206403f6b33f051b6ca44df24fa/14207/qrgenls.png" width="1291" />
  </figure>
  <figure id="VnrM" class="m_original">
    <img src="https://st768.s3.eu-central-1.amazonaws.com/4a82c206403f6b33f051b6ca44df24fa/14199/exploited.png" width="957" />
  </figure>
  <figure id="VA7A" class="m_original">
    <img src="https://st768.s3.eu-central-1.amazonaws.com/4a82c206403f6b33f051b6ca44df24fa/14200/notprotected.png" width="951" />
    <figcaption>https://t.me/anon_chan_by</figcaption>
  </figure>
  <p id="DpJQ"><a href="https://t.me/anon_chan_by" target="_blank">https://t.me/anon_chan_by</a></p>

]]></content:encoded></item><item><guid isPermaLink="true">https://teletype.in/@anon_channel/wyFwNAgy9f-</guid><link>https://teletype.in/@anon_channel/wyFwNAgy9f-?utm_source=teletype&amp;utm_medium=feed_rss&amp;utm_campaign=anon_channel</link><comments>https://teletype.in/@anon_channel/wyFwNAgy9f-?utm_source=teletype&amp;utm_medium=feed_rss&amp;utm_campaign=anon_channel#comments</comments><dc:creator>anon_channel</dc:creator><title>Хакер - Картинки с секретами. Тестируем восемь утилит для сокрытия данных</title><pubDate>Sun, 07 Nov 2021 11:05:19 GMT</pubDate><media:content medium="image" url="https://img3.teletype.in/files/62/b9/62b937fd-e258-402e-be6a-4636d8bf51ec.jpeg"></media:content><description><![CDATA[<img src="https://st768.s3.eu-central-1.amazonaws.com/8b8d72f768a36d74ce62299f401cca64/21176/cloakify.jpg"></img>https://t.me/anon_chan_by]]></description><content:encoded><![CDATA[
  <p id="5BaR"><a href="https://t.me/anon_chan_by" target="_blank">https://t.me/anon_chan_by</a></p>
  <p id="L2aN">Ес­ли ты дума­ешь, что в фот­ках с котика­ми не может скры­вать­ся ничего пос­торон­него, — спе­шу тебя разоча­ровать (или, наобо­рот, порадо­вать!). Сей­час я покажу, как внед­рить в кар­тинку, архив или пес­ню любую пос­торон­нюю информа­цию, да так, что­бы ее ник­то там не заметил. Инте­рес­но? Пог­нали!</p>
  <p id="67pV">О прин­ципах сте­ганог­рафии мы уже не раз писали — смот­ри, к при­меру, статью «<a href="https://teletype.in/@anon_channel/cenCMOzItK5" target="_blank">Пря­чем фай­лы в кар­тинках: семь сте­ганог­рафичес­ких ути­лит для Window</a><a href="https://xakep.ru/2017/01/23/windows-stenographic-tools/" target="_blank">s</a>». Одна­ко в ней перечис­лены далеко не все ути­литы и при­цел сде­лан на Windows. Сегод­ня мы рас­смот­рим восемь аль­тер­натив­ных ути­лит, в основном — кросс‑плат­формен­ные.</p>
  <h3 id="CLOAKIFY">CLOAKIFY</h3>
  <ul id="jMYK">
    <li id="vdmj">Плат­форма: любая</li>
    <li id="1dMk">Где ска­чивать: <a href="https://github.com/TryCatchHCF/Cloakify" target="_blank">GitHub</a></li>
  </ul>
  <p id="CG3d">CloakifyFactory — это боль­шая и лег­ко рас­ширя­емая прог­рамма, которая исполь­зует скрип­ты Cloakify Toolset. Осо­бен­ность ее в том, что перед мас­киров­кой наг­рузки она кодиру­ется в Base64.</p>
  <figure id="oqik" class="m_original">
    <img src="https://st768.s3.eu-central-1.amazonaws.com/8b8d72f768a36d74ce62299f401cca64/21176/cloakify.jpg" width="643" />
  </figure>
  <p id="YLNT">У прог­раммы есть огромный плюс — она уме­ет мас­кировать что угод­но не прос­то в кар­тинках, а еще и в видео, музыке и даже прог­раммах, хоть и с пос­ледни­ми получа­ется пло­хо — выход­ной файл силь­но раз­дува­ется.</p>
  <p id="9ZAv">Ра­бота­ет Cloakify на Python 2.7, который уже мораль­но и физичес­ки уста­рел, а исполь­зование Base64 для скры­тия информа­ции от нево­ору­жен­ного гла­за при­водит к силь­ному уве­личе­нию раз­мера, не давая никако­го замет­ного пре­иму­щес­тва.</p>
  <p id="VPJa">Для при­мера давай обыч­ный тек­сто­вый документ внед­рим в кар­тинку фор­мата JPEG. Мой исходный файл называ­ется <code>save.txt</code> и лежит в одной дирек­тории с самой прог­раммой. Внед­рение фай­ла край­не прос­тое и выг­лядит при­мер­но так.</p>
  <figure id="q3Sj" class="m_original">
    <img src="https://st768.s3.eu-central-1.amazonaws.com/8b8d72f768a36d74ce62299f401cca64/21177/cloakify-2.jpg" width="641" />
  </figure>
  <p id="kUEX">Про­пус­каем фун­кцию добав­ления шумов. Для нас они погоды не сде­лают, но, если ты хочешь допол­нитель­но замас­кировать информа­цию, могут помочь.</p>
  <figure id="RLgE" class="m_original">
    <img src="https://st768.s3.eu-central-1.amazonaws.com/db7bf1a5fd461713fc6939f2d7d8756b/21384/cloakify-3.jpg" width="1003" />
  </figure>
  <p id="xOPz">Как ты уже мог догадать­ся, этот софт для сок­рытия дей­стви­тель­но сек­ретной информа­ции при­менять стрем­но. Но есть и плю­сы, вро­де прос­тоты работы и того, что выход­ных фор­матов чуть более чем куча.</p>
  <h3 id="STEGHIDE">STEGHIDE</h3>
  <ul id="jrNW">
    <li id="3ptm">Плат­форма: любая</li>
    <li id="weGz">Где ска­чивать: <a href="https://github.com/StefanoDeVuono/steghide" target="_blank">GitHub</a></li>
  </ul>
  <p id="Mmv6">Steghide — кон­соль­ная ути­лита, написан­ная на C++. Скры­вает информа­цию в стан­дар­тных фай­лах фор­матов JPEG, BMP, WAV и AU. В арсе­нале прог­раммы пол­но шиф­ров — даже Blowfish, которо­го я у дру­гих не замечал. Теоре­тичес­ки исполь­зование такой экзо­тики может помочь запутать сле­ды еще силь­нее.</p>
  <p id="2OyO">Steghide уме­ет не прос­то упа­ковы­вать дан­ные в кар­тинку или трек, а еще и шиф­ровать сек­ретную наг­рузку.</p>
  <p id="iP6b">Но есть и минус: не все фотог­рафии и ауди­офай­лы подой­дут для внед­рения в них сек­ретной наг­рузки. Если файл слиш­ком малень­кий — внед­рить в него ничего нель­зя.</p>
  <p id="GWUL">Да­вай поп­робу­ем объ­еди­нить кар­тинку <code>cats.jpg</code> и сек­ретный фай­лик <code>save.txt.</code></p>
  <p id="bR3W">От­кры­ваем тер­минал и пишем:</p>
  <p id="U1Nf"><code>steghide embed -cf cats.jpg -ef save.txt</code></p>
  <ul id="EALi">
    <li id="Eibw"><code>--embedfile [-ef]</code> — файл, который мы будем встра­ивать;</li>
    <li id="SfW1"><code>--coverfile [-cf]</code> — файл‑обложка, в который внед­ряет­ся сек­ретная инфа;</li>
    <li id="eaXO"><code>--compress [-z]</code> — сжи­мать дан­ные перед упа­ков­кой;</li>
    <li id="h3UV"><code>--encryption [-e]</code> — шиф­ровать внед­ряемые дан­ные.</li>
  </ul>
  <p id="zSFm">Рас­паков­ка так же прос­та, как упа­ков­ка:</p>
  <p id="WqiF"><code>steghide extract -sf cats.jpg</code></p>
  <p id="F6Tg">Ключ <code>--stegofile [-sf]</code> поз­воля­ет выб­рать файл со скры­той информа­цией, а <code>--passphrase [-p]</code> ука­зыва­ет пароль.</p>
  <figure id="yr4u" class="m_original">
    <img src="https://st768.s3.eu-central-1.amazonaws.com/db7bf1a5fd461713fc6939f2d7d8756b/21395/steghide.jpg" width="999" />
    <figcaption>Вот что получи­лось</figcaption>
  </figure>
  <p id="DDm9">Из‑за при­мене­ния сжа­тия раз­ница раз­меров до и пос­ле внед­рения минималь­на.</p>
  <p id="UalL">Мне пон­равилась воз­можность ста­вить пароли и сжи­мать дан­ные. Однознач­но хорошая шту­ка, которую мож­но исполь­зовать в любитель­ских целях. К тому же мож­но соз­дать цепоч­ку из объ­ектов, которые будут спря­таны друг в дру­ге. А минус толь­ко в том, что не вся­кое изоб­ражение под­ходит для этой манипу­ляции, но мы же живем в XXI веке, и най­ти новую фот­ку вооб­ще не воп­рос, прав­да?</p>
  <h3 id="SPECTROLOGY">SPECTROLOGY</h3>
  <ul id="b6Dh">
    <li id="6Fgg">Плат­форма: любая</li>
    <li id="9P6m">Где ска­чивать: <a href="https://github.com/solusipse/spectrology" target="_blank">GitHub</a></li>
  </ul>
  <p id="f8Fa">Наз­вание прог­раммы Spectrology говорит само за себя — она поз­воля­ет прев­ращать изоб­ражения в ауди­одо­рож­ки с «заряжен­ными» спек­трог­рамма­ми, из которых потом мож­но дос­тать кар­тинки. Зву­чит кру­то, но без проб­лем не обош­лось.</p>
  <p id="pxqk">Пе­ред пер­вым запус­ком нуж­но пос­тавить модуль <code>pillow</code>.</p>
  <p id="QFMK"><code>python3 -m pip install --upgrade pip</code></p>
  <p id="feM8"><code>python3 -m pip install --upgrade Pillow</code></p>
  <p id="ks3Z">Сра­зу бро­сает­ся в гла­за вто­рой огромный минус — край­не мед­ленная работа. Хоть он и с лих­вой перек­рыва­ется плю­сами в виде необыч­ного алго­рит­ма работы и перено­симос­ти (написа­на на Python).</p>
  <p id="pFAZ">Да­вай запаку­ем изоб­ражение BMP в файл WAV. Дела­ется это так:</p>
  <p id="9gT2"><code>python spectrology.py your_filename.bmp -o music.wav</code></p>
  <ul id="RtJI">
    <li id="exTf"><code>--output [-o]</code> — флаг, отве­чающий за наз­вание выход­ного ауди­офай­ла;</li>
    <li id="Cw4w"><code>--botton [-b]</code> зада­ет ниж­ний час­тотный диапа­зон;</li>
    <li id="ztrH"><code>--pixels [-p]</code> поз­воля­ет уста­новить количес­тво пик­селей в секун­ду;</li>
    <li id="1mJR"><code>--sampling [-s]</code> ста­вит час­тоту дис­кре­тиза­ции.</li>
  </ul>
  <p id="Cuwz">Да­вай пос­мотрим, какого раз­мера будет готовый ауди­офайл.</p>
  <figure id="bCpv" class="m_original">
    <img src="https://st768.s3.eu-central-1.amazonaws.com/db7bf1a5fd461713fc6939f2d7d8756b/21394/spectrology.jpg" width="992" />
  </figure>
  <p id="Wsz3">В целом работа­ет мед­ленно и из короб­ки даже не запус­кает­ся — при­ходит­ся недос­тающие модули ста­вить вруч­ную. Не про­изво­дит впе­чат­ления хорошо про­рабо­тан­ного инс­тру­мен­та, хотя задум­ка, безус­ловно, клас­сная.</p>
  <h3 id="IMAGESPYER-G2">IMAGESPYER G2</h3>
  <ul id="K7pP">
    <li id="NBS0">Плат­форма: Windows</li>
    <li id="gN6Y">Где ска­чивать: где получит­ся</li>
  </ul>
  <p id="LASP">Это одна из древ­них ути­лит, ког­да‑то написан­ных Алек­сан­дром Мяс­никовым и ныне встре­чающаяся лишь на прос­торах фай­лопомо­ек. Офи­циаль­ный сайт у нее если ког­да‑то и был, то дав­но не работа­ет. Тем не менее прог­рамма зас­лужива­ет вни­мания.</p>
  <p id="4j0E">ImageSpyer пря­чет сек­ретные фай­лы толь­ко в кар­тинки и даже раз­реша­ет ста­вить пароль, что­бы зашиф­ровать дан­ные перед внед­рени­ем. Прог­рамма под­держи­вает око­ло 30 алго­рит­мов шиф­рования внед­ряемой информа­ции и 25 хеш‑фун­кций для под­писи, что­бы убе­дить­ся, что встро­енный в кар­тинку файл не побил­ся при переда­че.</p>
  <figure id="b4Qj" class="m_original">
    <img src="https://st768.s3.eu-central-1.amazonaws.com/8b8d72f768a36d74ce62299f401cca64/21181/imagespyer.jpg" width="664" />
  </figure>
  <p id="gWmW">Боль­шой плюс — наличие гра­фичес­кого интерфей­са с понят­ными пояс­нени­ями и мно­жес­твом нас­тро­ек. Выход­ных фор­матов все­го два: BMP и TIFF.</p>
  <figure id="uwK4" class="m_original">
    <img src="https://st768.s3.eu-central-1.amazonaws.com/8b8d72f768a36d74ce62299f401cca64/21182/imagespyer-2.jpg" width="800" />
  </figure>
  <p id="u8Yb">Пос­мотрим, нас­коль­ко силь­но уве­личил­ся объ­ем фотог­рафии.</p>
  <figure id="VTLS" class="m_original">
    <img src="https://st768.s3.eu-central-1.amazonaws.com/8b8d72f768a36d74ce62299f401cca64/21183/imagespyer-3.jpg" width="994" />
    <figcaption>Сле­ва — пос­ле обра­бот­ки, спра­ва — до</figcaption>
  </figure>
  <p id="cKz6">Как видишь, из малень­кого котика раз­мером 59,6 Кбайт мы сде­лали тол­сто­го кота на целых 1530 Кбайт. Резуль­тат неп­лохой, да и работа­ет ImageSpyer быс­тро, так что сме­ло рекомен­дуем к исполь­зованию.</p>
  <h3 id="REDJPEG">REDJPEG</h3>
  <ul id="o5rU">
    <li id="8W7U">Плат­форма: Windows</li>
    <li id="igzV">Где ска­чивать: где получит­ся</li>
  </ul>
  <p id="jco6">Еще один сте­гозавр авторс­тва Алек­сан­дра Мяс­никова. На этот раз — с собс­твен­ным алго­рит­мом внед­рения изоб­ражения в кар­тинки, сжа­тием LZMA и офор­мле­нием для нос­таль­гиру­ющих по СССР.</p>
  <figure id="08qx" class="m_original">
    <img src="https://st768.s3.eu-central-1.amazonaws.com/db7bf1a5fd461713fc6939f2d7d8756b/21388/redjpeg.jpg" width="731" />
    <figcaption>Вождь чита­ет инс­трук­цию</figcaption>
  </figure>
  <figure id="JbG3" class="m_original">
    <img src="https://st768.s3.eu-central-1.amazonaws.com/db7bf1a5fd461713fc6939f2d7d8756b/21389/redjpeg-2.jpg" width="503" />
    <figcaption>Нас­трой­ки</figcaption>
  </figure>
  <p id="r3Rm">А что у нас по объ­ему пос­ле запаков­ки тек­ста в кар­тинку?</p>
  <figure id="Ah5x" class="m_original">
    <img src="https://st768.s3.eu-central-1.amazonaws.com/db7bf1a5fd461713fc6939f2d7d8756b/21390/redjpeg-3.jpg" width="1001" />
  </figure>
  <p id="7vBD">Впе­чат­ления исклю­читель­но позитив­ные. Прог­рамма поз­воля­ет хорошо спря­тать и зашиф­ровать любую нуж­ную информа­цию. Под­ходит для пос­тоян­ного исполь­зования.</p>
  <h3 id="OPENSTEGO">OPENSTEGO</h3>
  <ul id="0ZPf">
    <li id="SnZm">Плат­форма: любая</li>
    <li id="eOnM">Где ска­чивать: <a href="https://github.com/syvaidya/openstego/releases" target="_blank">GitHub</a></li>
  </ul>
  <p id="ATyC">Про­ект OpenStego реали­зован на Java, име­ет под­дер­жку шиф­рования AES и край­не популя­рен сре­ди жела­ющих поз­накомить­ся со сте­ганог­рафи­ей. Под­держи­вает пла­гины, что­бы ты сам смог реали­зовать какой‑нибудь сте­ганог­рафичес­кий алго­ритм. Есть вер­сии и для Windows, и для Linux.</p>
  <figure id="VOfb" class="m_original">
    <img src="https://st768.s3.eu-central-1.amazonaws.com/db7bf1a5fd461713fc6939f2d7d8756b/21387/openstego.jpg" width="658" />
  </figure>
  <p id="pJ0P">Как и ImageSpyer, OpenStego зна­читель­но раз­дува­ет раз­меры фай­ла, хоть и не нас­толь­ко силь­но. Под­держи­вает­ся так­же все­го один спо­соб упа­ков­ки, но это лег­ко поп­равить пла­гина­ми. Выход­ные фай­лы могут быть толь­ко в фор­мате PNG, но это нель­зя наз­вать сов­сем уж боль­шим минусом, тем более что на вход мож­но подавать поч­ти любой фор­мат.</p>
  <p id="pRDy">Есть и инте­рес­ная фун­кция, которой я не нашел у кон­курен­тов, — Digital Watermarking. Она поз­воля­ет тай­ком пометить фотог­рафию, что­бы лег­ко най­ти вора. Для это­го прог­рамма внед­ряет в кар­тинку незамет­ный иден­тифика­тор, который в даль­нейшем мож­но будет дос­тать и про­верить, кто взял кар­тинку без спро­са.</p>
  <p id="BHTX">Прог­рамма не тре­бует уста­нов­ки, а запус­кает­ся бат­ником.</p>
  <figure id="fHNW" class="m_original">
    <img src="https://st768.s3.eu-central-1.amazonaws.com/8b8d72f768a36d74ce62299f401cca64/21185/openstego-2.jpg" width="995" />
    <figcaption>Срав­нение</figcaption>
  </figure>
  <p id="Bl4i">Файл на выходе получил­ся куда тол­ще, чем был, — раз­мер уве­личил­ся поч­ти на 800 Кбайт.</p>
  <p id="4rNe">По срав­нению с ImageSpyer OpenStego все же более богат фичами, что мне пон­равилось.</p>
  <h3 id="SILENTEYE">SILENTEYE</h3>
  <ul id="Gqix">
    <li id="j3fi">Плат­форма: любая</li>
    <li id="fEzL">Где ска­чивать: <a href="https://achorein.github.io/silenteye/" target="_blank">сайт на GitHub</a></li>
  </ul>
  <p id="WNqm">SilentEye — кросс‑плат­формен­ный софт с прос­тым интерфей­сом. Обла­дает мно­жес­твом пла­гинов и при­ятным GUI. Исполь­зует сов­ремен­ные алго­рит­мы сте­ганог­рафии и мас­киров­ки.</p>
  <figure id="SaYq" class="m_original">
    <img src="https://st768.s3.eu-central-1.amazonaws.com/8b8d72f768a36d74ce62299f401cca64/21189/silenteye.jpg" width="477" />
  </figure>
  <p id="Irqh">Из оче­вид­ных пре­иму­ществ отме­чу ввод мас­киру­емо­го тек­ста пря­мо в окне прог­раммы вмес­то заг­рузки тек­сто­вых фай­лов из сто­рон­него редак­тора. Серь­езно, фича прос­тая, а ник­то до это­го не додумал­ся. Фор­маты выход­ных фай­лов кар­тинок — BMP, JPEG, PNG, GIF, TIFF, зву­ка — толь­ко WAV.</p>
  <figure id="GarE" class="m_original">
    <img src="https://st768.s3.eu-central-1.amazonaws.com/db7bf1a5fd461713fc6939f2d7d8756b/21392/silenteye-3.jpg" width="659" />
  </figure>
  <p id="D1As">Мож­но нас­тро­ить качес­тво выход­ного изоб­ражения — оно опре­деля­ет, сколь­ко потерь будет при кодиро­вании в JPEG.</p>
  <p id="Xlyy">Для шиф­рования внед­ренных дан­ных при­меня­ется AES, но нас­тро­ек куда боль­ше, чем у OpenStego.</p>
  <figure id="JlX2" class="m_original">
    <img src="https://st768.s3.eu-central-1.amazonaws.com/db7bf1a5fd461713fc6939f2d7d8756b/21391/silenteye-2.jpg" width="500" />
  </figure>
  <p id="q3mP">При про­вер­ке уве­личе­ния объ­ема приш­лось исполь­зовать дру­гую кар­тинку в качес­тве исходной, но вид­но, что объ­ем поч­ти не изме­нил­ся, то есть прог­рамма работа­ет эффектив­но.</p>
  <figure id="47Rm" class="m_original">
    <img src="https://st768.s3.eu-central-1.amazonaws.com/db7bf1a5fd461713fc6939f2d7d8756b/21393/silenteye-4.jpg" width="1004" />
  </figure>
  <p id="6Ehi">Раз­мер фай­ла с кар­тинкой уве­личил­ся все­го на 13,5 Кбайт — очень хороший резуль­тат!</p>
  <p id="qCHf">Ути­лита может спо­кой­но заменить ста­рич­ка OpenStego. Работа­ет она чуть мед­леннее кон­курен­тов, но зачас­тую это нек­ритич­но. Тоже рекомен­дую.</p>
  <h3 id="IMAGEJS">IMAGEJS</h3>
  <ul id="Jpgf">
    <li id="n6MQ">Плат­форма: Linux</li>
    <li id="L9U9">Где ска­чивать: <a href="https://github.com/jklmnn/imagejs" target="_blank">GitHub</a></li>
  </ul>
  <p id="EekV">ImageJS пред­назна­чена не сов­сем для сок­рытия информа­ции от людей. Вмес­то это­го она помога­ет обма­нывать бра­узе­ры, которые совер­шенно обос­нован­но пред­полага­ют, что в валид­ных кар­тинках ничего пос­торон­него быть не дол­жно.</p>
  <p id="ILxb">ImageJS поз­воля­ет соз­дать кар­тинки, которые одновре­мен­но пред­став­ляют собой нас­тоящие JS-скрип­ты. Это нуж­но, что­бы упростить про­веде­ние более опас­ных XSS-атак, в которых иног­да тре­бует­ся под­гру­зить скрипт имен­но с ата­кован­ного домена. Вот тут на помощь при­ходит воз­можность заг­рузить туда ава­тар­ку, которая одновре­мен­но содер­жит JavaScript payload для даль­нейшей ата­ки. Прог­рамма под­держи­вает внед­рение в фор­маты BMP, GIF, WEBP, PNG и PDF.</p>
  <p id="SlVV">Для сбор­ки нуж­ны пакеты <code>build-esential</code> и <code>cmake</code>. Даль­ше все прос­то:</p>
  <p id="oVoZ"><code>$ git clone https://github.com/jklmnn/imagejs.git</code></p>
  <p id="oEEI"><code>$ cd imagejs</code></p>
  <p id="SOnn"><code>$ mkdir build</code></p>
  <p id="fvbK"><code>$ cd build</code></p>
  <p id="ycDL"><code>$ cmake ..</code></p>
  <p id="UiVt"><code>$ make</code></p>
  <p id="4Dr9">Да­вай соз­дадим <code>script.js</code> со сле­дующим кодом, а потом упа­куем его в <code>image.gif</code>:</p>
  <p id="30tl"><code>alert(&quot;Hello, Xakep!&quot;);</code></p>
  <p id="Fdsq"><code>./imagejs gif script.js -i image.gif</code></p>
  <p id="rn8n">На выходе будет файл с двой­ным рас­ширени­ем, но это не беда.</p>
  <p id="rYkw">Сей­час мы про­верим все в деле! Соз­давай HTML-стра­нич­ку со сле­дующим кодом и сох­раняй ее рядом с нашей заряжен­ной кар­тинкой.</p>
  <p id="EaMp"><code>&lt;html&gt;</code></p>
  <p id="PnK0"><code> &lt;title&gt;Knock, Knock, Neo&lt;/title&gt;</code></p>
  <p id="uKqW"><code> &lt;head&gt;</code></p>
  <p id="szFj"><code> &lt;img src=&quot;script.js.gif&quot; alt=&quot;Matrix&quot;&gt;</code></p>
  <p id="0Ctt"><code> &lt;script src=&quot;script.js.gif&quot;&gt;&lt;/script&gt;</code></p>
  <p id="KtPH"><code> &lt;/head&gt;</code></p>
  <p id="GTar"><code>&lt;/html&gt;</code></p>
  <p id="hqTU">Сох­раня­ем и откры­ваем. Дол­жно получить­ся как на скрин­шоте.</p>
  <figure id="aDTB" class="m_original">
    <img src="https://st768.s3.eu-central-1.amazonaws.com/db7bf1a5fd461713fc6939f2d7d8756b/21385/imagejs.jpg" width="1240" />
  </figure>
  <p id="VSwM">Раз­мер кар­тинки поч­ти не меня­ется, что нам очень на руку.</p>
  <figure id="4NvD" class="m_original">
    <img src="https://st768.s3.eu-central-1.amazonaws.com/db7bf1a5fd461713fc6939f2d7d8756b/21386/imagejs-1.jpg" width="999" />
  </figure>
  <p id="Maz5">Прог­рамма шикар­на, хоть и при­мени­ма толь­ко в очень спе­цифич­ных целях.</p>
  <h3 id="ВЫВОДЫ">ВЫВОДЫ</h3>
  <p id="MQyS">За­менить кросс‑плат­формен­ный и богатый фичами OpenStego слож­но, но при желании мож­но. SilentEye будет неп­лохим выбором, но и ути­лит­ки Алек­сан­дра Мяс­никова тоже рекомен­дую поп­робовать, если у тебя Windows. Если же ты фанат кон­соли или мас­теришь какую‑то авто­мати­зиро­ван­ную сис­тему, то тебе может при­годить­ся один из вари­антов, написан­ных на Pyhton.</p>
  <figure id="whq8" class="m_original">
    <img src="https://st768.s3.eu-central-1.amazonaws.com/470b2dc3afd8c19e0db40986e407d2f8/21468/table.png" width="865" />
  </figure>
  <p id="S3SO">В таб­лице я свел воеди­но информа­цию об упо­мяну­тых прог­раммах и про­тес­тировал сте­ганог­рафиро­вание в кар­тинки тек­сто­вого фай­ла раз­мером 1,07 Кбайт.</p>
  <p id="6f5Y"><a href="https://t.me/anon_chan_by" target="_blank">https://t.me/anon_chan_by</a></p>

]]></content:encoded></item><item><guid isPermaLink="true">https://teletype.in/@anon_channel/cenCMOzItK5</guid><link>https://teletype.in/@anon_channel/cenCMOzItK5?utm_source=teletype&amp;utm_medium=feed_rss&amp;utm_campaign=anon_channel</link><comments>https://teletype.in/@anon_channel/cenCMOzItK5?utm_source=teletype&amp;utm_medium=feed_rss&amp;utm_campaign=anon_channel#comments</comments><dc:creator>anon_channel</dc:creator><title>Прячем файлы в картинках: семь стеганографических утилит для Windows</title><pubDate>Sun, 07 Nov 2021 10:52:04 GMT</pubDate><media:content medium="image" url="https://img3.teletype.in/files/27/64/2764b8a5-e8dd-4f8d-b574-dfd1753d3d74.png"></media:content><description><![CDATA[<img src="https://xakep.ru/wp-content/uploads/2017/01/Wallpaper.png"></img>23.01.2017]]></description><content:encoded><![CDATA[
  <p id="RHj7">23.01.2017</p>
  <p id="gbvt"><a href="https://t.me/anon_chan_by" target="_blank">https://t.me/anon_chan_by</a></p>
  <p id="q70J">Содержание статьи</p>
  <ul id="VMCJ">
    <li id="01.">От фараонов до наших дней</li>
    <li id="02.">Anubis</li>
    <li id="03.">DeEgger Embedder</li>
    <li id="04.">DeepSound</li>
    <li id="05.">Hallucinate</li>
    <li id="06.">JHide</li>
    <li id="07.">OpenPuff</li>
    <li id="08.">OpenStego</li>
    <li id="09.">RARJPEG</li>
    <li id="10.">Выводы</li>
  </ul>
  <p id="HfsJ">Шифрование помогает сохранять данные в секрете, но одновременно привлекает лишнее внимание. Если файл так просто не открыть, значит, в нем наверняка есть что-то ценное. Поэтому бывает важно скрыть само наличие секретной информации. Проще всего это сделать, растворив конфиденциальные данные внутри какого-нибудь безобидного файла. Решается такая задача с помощью стеганографических утилит, которые мы и протестируем.</p>
  <h2 id="2FzY">От фараонов до наших дней</h2>
  <p id="oNEW">Если считать, что история развивается по спирали, то современная жизнь, похоже, вышла на тот же виток, что и Древний Египет. Люди снова поклоняются кошкам и хранят их изображения повсюду. Параллельно возрождается культ тайного знания — одни прячут информацию, другие ищут способы получить ее. Так что идеальный способ скрыть секретные данные — это смешать их с тривиальным контентом вроде фотографий кошек.</p>
  <p id="TYmx">По одной из версий, криптография зародилась как раз в Древнем Египте. Ее дочка — стеганография, или «тайнопись», появилась уже ближе к расцвету Римской империи. Отдельные приемы тайного письма практиковались еще до нашей эры, но в самостоятельную прикладную дисциплину стеганография оформилась лишь к XVI веку.</p>
  <p id="XnkQ">Современная стеганография — цифровая и компьютерная. Последнюю можно разделить на три больших направления. Первое — это собственно тайнопись, или методы сокрытия одних файлов (которые принято называть сообщением) внутри других («контейнера»). После заполнения сообщением контейнер внешне меняется незаметно и полностью сохраняет свою функциональность.</p>
  <p id="OAYo">Второе направление изучает методы добавления к сообщению скрытых или стеганографических меток (stegomarks). Это незаметные без специальной обработки метки, идентичные для всех файлов одного человека или устройства. Например, такие стегометки записываются в цифровые фотографии для того, чтобы можно было доказать их авторство. Крэкеры иногда оставляют стегометки в лицензионных ключах. Они зашиты на уровне алгоритма генерации, а потому сохраняются при попытке изменить интерфейс кейгена и выдать его за свой.</p>
  <p id="8zti">Третье направление — внедрение в сообщение цифровых отпечатков (digital fingerprints). В отличие от стегометок, эти скрытые знаки уникальны для каждого сообщения. Они служат в основном для защиты интересов правообладателей, позволяя отследить распространение контента. К примеру, многие интернет-магазины внедряют цифровые отпечатки в продаваемые книги и музыкальные композиции. В них кодируется информация о дате продажи и аккаунте купившего (имя, IP-адрес и прочее). Если купленные файлы позже появятся среди торрентов или на файлообменниках, то правообладатели смогут установить распространителя нелегального контента. Для этого будет достаточно считать из контрафактного файла вкрапленный цифровой отпечаток.</p>
  <p id="phHN">Использует ли твой любимый онлайновый сервис стегометки? Это легко проверить. Достаточно купить два экземпляра одного и того же произведения с разных аккаунтов и сделать побайтное сравнение файлов. Разница между ними и покажет скрытые метки. Если же файлы скачались идентичные (и их хеши полностью совпадают), то стегометок внутри нет.</p>
  <p id="644w">О каждом из этих направлений написано множество книг и статей, но до сих пор нет единой терминологии. Одни авторы дробят перечисленные ветви на десятки более мелких, а другие не видят принципиальной разницы и между крупными. Для кого-то есть тонкая грань между скрытым хранением и скрытой передачей данных, а для других это лишь частности.</p>
  <p id="ba9x">Не будем вдаваться в полемику, гораздо интереснее попробовать стеганографию в деле. Для начала рассмотрим поближе ее основное применение — сокрытие данных. Из полусотни утилит для маскировки одних файлов внутри других мы отобрали всего семь. В обзор вошли только те, которые гарантированно работают в Windows 10.</p>
  <p id="Fkbn">Для теста мы возьмем картинку с обоями для рабочего стола. За этой растительностью можно уместить много интересного.</p>
  <figure id="kbXe" class="m_custom">
    <img src="https://xakep.ru/wp-content/uploads/2017/01/Wallpaper.png" width="1200" />
  </figure>
  <h2 id="OV5L">Anubis</h2>
  <p id="z7dK"><a href="https://sourceforge.net/projects/anubisstegano/files/latest/download" target="_blank">https://sourceforge.net/projects/anubisstegano/files/latest/download</a></p>
  <p id="wtjy">Анубис — супергерой древних египтян. Человек-шакал, в честь которого спустя шесть тысяч лет назвали бесплатную программу. Ее первая и, к сожалению, последняя версия была написана в 2014 году на Java. Поэтому утилита получилась кросс-платформенной, но требующей установки JRE, а также (в случае с Windows 10) виртуальной машины DOS — NTVDM.</p>
  <figure id="qGgf" class="m_custom">
    <img src="https://xakep.ru/wp-content/uploads/2017/01/1484562909_f8c6_anubis-java.png" width="742" />
    <figcaption>Принести Анубису Джаву!</figcaption>
  </figure>
  <p id="6cH4">Другие статьи в выпуске:</p>
  <p id="ooDM"><a href="https://xakep.ru/issues/xa/215" target="_blank">Xakep #215. Второй фактор</a></p>
  <ul id="b1TK">
    <li id="1plw"><a href="https://xakep.ru/issues/xa/215" target="_blank">Содержание выпуска</a></li>
    <li id="VTNk"><a href="https://xakep.ru/about" target="_blank">Подписка на «Хакер»</a></li>
  </ul>
  <p id="bESS">Основное окно программы выглядит максимально аскетично. Нажимаем Encrypt и в открывающейся вкладке указываем необходимые действия: какой файл поместить внутрь какого и где сохранить результат. Гарантированно работает только сокрытие текстовых файлов внутри картинок формата BMP. Несколько таких уже есть в Windows 10 — это иконки пользователей. Было бы занятно спрятать в user.bmp список паролей или еще какую-нибудь конфиденциальную инфу. Давно подмечено, что лучшие тайники стоят на видном месте.</p>
  <figure id="5wVK" class="m_custom">
    <img src="https://xakep.ru/wp-content/uploads/2017/01/1484562917_0a21_anubis-enc.png" width="587" />
    <figcaption>Прячем TXT в BMP</figcaption>
  </figure>
  <p id="iKUE">Дополнительно можно защитить полученный файл пин-кодом — тогда он потребуется для обратного преобразования. Утилита некорректно обрабатывает строку с указанием места результирующего файла. Он может быть сохранен на уровень выше заданного или вообще в исходном каталоге.</p>
  <figure id="kabC" class="m_custom">
    <img src="https://xakep.ru/wp-content/uploads/2017/01/1484562923_f27c_anubis_diff.png" width="1003" />
    <figcaption>Сравнение пустого и наполненного контейнера</figcaption>
  </figure>
  <p id="cFN1">Как видно из побайтного сравнения исходного файла BMP с содержащим скрытый текст, программа работает очень примитивно. Она просто дописывает данные в конец файла. Данные зашифрованы, но снабжены характерными указателями: <code>limiter1</code>, <code>limiter2</code>, <code>inserted length begins</code>. Простым поиском файлов, содержащих такие строки, легко найти все стегоконтейнеры. Такую утилиту можно использовать в качестве иллюстрации простейшего метода стеганографии, но для серьезных задач она совершенно не подходит.</p>
  <h2 id="BWfg">DeEgger Embedder</h2>
  <p id="6DIU"><a href="http://www.softpedia.com/get/Security/Encrypting/DeEgger-Embedder.shtml#download" target="_blank">http://www.softpedia.com/get/Security/Encrypting/DeEgger-Embedder.shtml#download</a></p>
  <p id="W1Xt">DeEgger Embedder — еще одна маленькая программа для стеганографии. В ней реализован уже больший набор функций, но его использование требует установки .NET Framework 3.5. Помимо редко используемых сегодня картинок BMP, программа поддерживает в качестве контейнеров PNG, JPG, видеофайлы AVI и музыкальные MP3. Утилита ведет подробный лог своих действий, который отображается прямо в главном окне.</p>
  <figure id="Fu4c" class="m_custom">
    <img src="https://xakep.ru/wp-content/uploads/2017/01/1484562934_6a63_deegger-combine.png" width="637" />
    <figcaption>Делаем пасхальные яйца!</figcaption>
  </figure>
  <p id="8j43">Кнопка запуска алгоритма называется Combine, а не Encrypt, что более точно отражает процесс внедрения файлов. Извлекаются скрываемые файлы (стегосообщения) из мультимедийных контейнеров нажатием единственной кнопки Extract. Никакой защиты пин-кодом здесь нет.</p>
  <figure id="QvgF" class="m_custom">
    <img src="https://xakep.ru/wp-content/uploads/2017/01/1484562940_5e13_deegger-extraction.png" width="1040" />
    <figcaption>Комбайн и экстракт</figcaption>
  </figure>
  <p id="uhMv">Зато программа может обрабатывать несколько файлов сразу. Можно поместить несколько сообщений в один контейнер или одно в разные контейнеры.</p>
  <figure id="FSBc" class="m_custom">
    <img src="https://xakep.ru/wp-content/uploads/2017/01/1484562948_1353_deegger_multiple.png" width="637" />
    <figcaption>Записываем несколько файлов в один контейнер</figcaption>
  </figure>
  <p id="VU1I">После обработки в DeEgger утилиты для сравнения изображений считают идентичными исходный и конечный файлы BMP. Реально же это пустой и заполненный контейнер в терминологии стеганографии.</p>
  <figure id="Saag" class="m_custom">
    <img src="https://xakep.ru/wp-content/uploads/2017/01/1484562953_4471_deegger_beyond_compare.png" width="1040" />
    <figcaption>Мнимая идентичность</figcaption>
  </figure>
  <p id="1sGv">Сделаем побайтное сравнение. Знакомая картина? Так же как и Anubis, утилита DeEgger Embedder дописала стегосообщение в конец файла-контейнера. В картинке user.bmp много однотонных областей, поэтому такой аппендикс выглядит особенно заметно.</p>
  <figure id="uZFR" class="m_custom">
    <img src="https://xakep.ru/wp-content/uploads/2017/01/1484562964_1e71_deegger-diff-1.png" width="1040" />
    <figcaption>Те же пасхальные яйца, вид в коде</figcaption>
  </figure>
  <p id="1s2h">На первый взгляд, здесь нет явных указателей, по которым можно сделать поиск файлов, содержащих определенную строку. Однако приглядимся внимательнее. Для этого сделаем еще один контейнер с другим сообщением и сравним уже два заполненных контейнера между собой.</p>
  <figure id="oDkv" class="m_custom">
    <img src="https://xakep.ru/wp-content/uploads/2017/01/1484562972_7721_deegger_diff_msgs.png" width="1003" />
    <figcaption>Находим указатель внедренного файла</figcaption>
  </figure>
  <p id="E86V">Вот одинаковый участок в шестнадцатеричном виде: <code>24 23 26 29 2A 40 26 28 23 5E 2A 00 D1 8B 87 8B FF</code>.</p>
  <p id="pujf">Как видишь, несмотря на поддержку большего числа форматов, DeEgger недалеко ушел от Anubis. Скрываемые файлы так же записываются в конец файла-контейнера и имеют характерный вид, по которому их легко обнаружить.</p>
  <h2 id="xhVu">DeepSound</h2>
  <p id="nHFM"><a href="http://jpinsoft.net/DeepSound/Overview.aspx" target="_blank">http://jpinsoft.net/DeepSound/Overview.aspx</a></p>
  <p id="wzkw">Последняя версия этой программы вышла в ноябре 2015 года. В отличие от предыдущих утилит в этом обзоре, она прячет данные внутри звуковых файлов. В качестве контейнеров DeepSound может использовать WAV (только несжатый, PCM), а также MP3, CDA, WMA, APE и FLAC. DeepSound умеет внедрять файлы любого типа и автоматически рассчитывает доступное для них место в зависимости от размера контейнера и настроек качества аудио.</p>
  <p id="8j9K">При использовании MP3 доступное место для стегосообщения показывается больше самого контейнера, но это иллюзия. Независимо от исходного формата файла новый контейнер создается только в одном из несжатых форматов: WAV, APE или FLAC. Поэтому размер первоначального контейнера значения не имеет. В итоге сообщение будет занимать какой-то процент от объема нового (несжатого) аудиофайла.</p>
  <figure id="yzOj" class="m_custom">
    <img src="https://xakep.ru/wp-content/uploads/2017/01/1484562985_3e9c_deepsound-pdf.png" width="1032" />
    <figcaption>Большой объем для любых файлов</figcaption>
  </figure>
  <p id="Wob6">Программа может просто поместить любой файл внутри музыкального, или предварительно зашифровать его по алгоритму AES с длиной ключа 256 бит. Опытным путем было установлено, что предельная длина пароля — всего 32 символа. Мои обычные пароли были длиннее и приводили к ошибке (an unhandled exception).</p>
  <figure id="Thse" class="m_custom">
    <img src="https://xakep.ru/wp-content/uploads/2017/01/1484562996_78c8_deepsound_encrypting.png" width="1040" />
    <figcaption>Шифрование AES</figcaption>
  </figure>
  <p id="DVBf">В один контейнер можно поместить любое количество файлов, пока не заполнится счетчик свободного места. Его количество зависит от степени качества (то есть вносимых в аудиофайл искажений). Всего доступны три настройки: высокое, обычное и низкое качество. Каждая из них увеличивает полезный объем контейнера вдвое. Однако рекомендую не жадничать и всегда использовать максимальное качество — так сложнее будет обнаружить скрытый файл.</p>
  <p id="Fxjn">Извлекается стегосообщение после выбора соответствующего контейнера вручную. Если использовалось шифрование, то без ввода пароля программа не покажет даже название скрытого файла. Кириллические символы в названиях файлов не поддерживаются. При извлечении они заменяются на XXXX, однако на содержимое файла это никак не влияет.</p>
  <p id="liyH">DeepSound умеет конвертировать MP3 и CDA, поэтому мы легко можем преобразовать исходный файл из MP3 в WAV и сравнить два контейнера: пустой и заполненный.</p>
  <figure id="0t5y" class="m_custom">
    <img src="https://xakep.ru/wp-content/uploads/2017/01/1484563010_c177_deepsound-diff.png" width="1003" />
    <figcaption>PDF размазан внутри WAV</figcaption>
  </figure>
  <p id="IP6R">Здесь нас ждет приятный сюрприз: размеры файлов идентичны, а их содержимое различается сразу после заголовка. Байты отличаются почти везде через один, причем на малые значения. Скорее всего, перед нами реализация алгоритма LSB (Least Significant Bit — наименьший значащий бит). Суть его в том, что скрываемый файл кодируется как изменения младших битов в отдельных байтах контейнера. Это приводит к небольшим искажениям (изменению оттенка пикселя в BMP и частоты звука в WAV), которые человек обычно не воспринимает. Чем больше контейнер по отношению к скрываемому файлу, тем меньше вероятность обнаружить последний. Такой алгоритм не оставляет явных указателей на наличие внедренного файла. Предположить его наличие может только статистический анализ шумов (акустических, яркостных, цветовых и прочих), но это уже совсем другой уровень стегоанализа.</p>
  <p id="19BQ">DeepSound уже вполне годится для сокрытия важной информации (кроме гостайны, разумеется). Можно применять и встроенное шифрование, но, насколько качественно оно реализовано, никто не знает, потому что открытого аудита у программы не было. Поэтому надежнее будет предварительно поместить секретные файлы в какой-нибудь надежный криптоконтейнер (например, TrueCrypt или VeraCrypt), а затем уже прятать его внутри аудиофайла. Если ты будешь использовать в качестве контейнеров уникальные аудиофайлы (например, собственные записи), то побайтно сравнить их будет не с чем и твою «матрешку» вряд ли кто-нибудь сможет найти. Просто запиши в тот же каталог несколько гигабайтов теплого несжатого звука для лучшей маскировки.</p>
  <h2 id="f2sH">Hallucinate</h2>
  <p id="dGWf"><a href="http://sourceforge.net/projects/hallucinate/" target="_blank">http://sourceforge.net/projects/hallucinate/</a></p>
  <p id="v6nL">Последняя версия программы Hallucinate (v. 1.2) вышла в ноябре 2015 года. Эта компактная (всего 34 Кбайт) утилита написана на Java и не требует установки. В качестве контейнера она поддерживает форматы BMP и PNG, что делает ее гораздо удобнее Anubis. Картинки PNG используются сегодня куда чаще, чем BMP. Их полно даже во временных каталогах браузера, поэтому лежать одиноким и очень заметным файлом на диске такой контейнер точно не будет.</p>
  <figure id="1XCz" class="m_custom">
    <img src="https://xakep.ru/wp-content/uploads/2017/01/1484563026_be64_hallucinate-01-png.png" width="1040" />
    <figcaption>Галлюцинации со смыслом</figcaption>
  </figure>
  <p id="e2rE">Интерфейс у Hallucinate прост и функционален. Требуется выбрать контейнер, указать скрываемый в нем файл и желаемую степень качества итоговой картинки. Доступны восемь вариантов. Чем сильнее огрубляется исходное изображение, тем больше в нем можно спрятать, но тем заметнее становятся артефакты. Выберем в настройках лучшее качество и проиллюстрируем эту разницу, повторив операцию с файлом BMP.</p>
  <figure id="8wgC" class="m_custom">
    <img src="https://xakep.ru/wp-content/uploads/2017/01/1484563035_7d0d_hal_diff_bc.png" width="1040" />
    <figcaption>Видишь отличия? А они есть!</figcaption>
  </figure>
  <p id="8BJk">Визуально картинки слева и справа не отличаются. Однако программа Beyond Compare показывает разницу между ними в кадре по центру. Текстовый файл закодирован как изменения яркости отдельных пикселей, равномерно распределенных по всему кадру. Только в самых темных и самых светлых участках они кучкуются плотно.</p>
  <p id="UsId">При побайтном сравнении файлов эта же разница в шестнадцатеричном формате выглядит знакомо: тот же алгоритм LSB, что и у DeepSound. Графический файл или звуковой — в данном случае значения не имеет. В оба формата вносятся минимальные искажения, неразличимые без специальных методов сравнения. Обнаружить их без исходного файла (имея на руках только контейнер) довольно сложно. Никаких явных указателей на внедрение стегосообщения он не содержит. Выдает скрытый файл только частотный анализ, но хорошо работает этот метод только для обнаружения крупных «матрешек». Мелкий файл в большой картинке остается практически незаметным.</p>
  <p id="OVqB">Извлекается скрытый файл буквально в два клика. Достаточно выбрать контейнер (HAL-file в терминологии автора программы), нажать Decode и указать место для сохранения файла.</p>
  <figure id="ceDQ" class="m_custom">
    <img src="https://xakep.ru/wp-content/uploads/2017/01/1484563057_70cc_hal_decode.png" width="1040" />
    <figcaption>Раздеваем матрешку</figcaption>
  </figure>
  <h2 id="oXIN">JHide</h2>
  <p id="ILRU"><a href="https://sourceforge.net/projects/jhideapp/" target="_blank">https://sourceforge.net/projects/jhideapp/</a></p>
  <p id="Pzoc">JHide (не путать с джихадом) — еще одна подобная программа на Java. Компактной ее не назовешь, она занимает почти три мегабайта. Однако в отличие от Hallucinate, помимо BMP и PNG, она поддерживает TIFF, а также позволяет использовать защиту паролем.</p>
  <figure id="tWzd" class="m_custom">
    <img src="https://xakep.ru/wp-content/uploads/2017/01/1484563065_9783_jhide-02-interface.png" width="627" />
    <figcaption>Интерфейс jHide</figcaption>
  </figure>
  <p id="NnIv">Сравнение утилитой Beyond Compare показывает едва различимые отличия. В первую секунду их не видно вообще. Надо прибавить яркости и присмотреться, чтобы разглядеть на черном фоне равномерно рассеянные темно-синие точки.</p>
  <figure id="Xh4s" class="m_custom">
    <img src="https://xakep.ru/wp-content/uploads/2017/01/1484563072_67da_jhide-bc.png" width="1040" />
    <figcaption>Результат работы jHide</figcaption>
  </figure>
  <p id="b21n">Сравнение в hex-кодах показывает все тот же алгоритм LSB, однако его реализация здесь более удачная. Измененные пиксели не группируются крупными блоками от начала файла, а равномерно рассеяны по всему контейнеру. Так гораздо сложнее обнаружить скрытое сообщение в картинке. При малом размере стегосообщения это практически невозможно сделать, не имея для сравнения оригинал (пустой контейнер).</p>
  <figure id="IuEG" class="m_custom">
    <img src="https://xakep.ru/wp-content/uploads/2017/01/1484563081_43ab_jhide_bit_cmp.png" width="1012" />
    <figcaption>Правильный LSB</figcaption>
  </figure>
  <p id="sm09">Программа сама пытается максимально сжать скрываемый файл перед его помещением в контейнер. Поэтому извлекается он всегда в формате ZIP, а спрятанный файл находится уже внутри этого архива. Парольную защиту необходимо деактивировать перед распаковкой вручную — jHide сама не покажет, надо ли его вводить. Это тоже плюс, поскольку исключает возможность использования утилиты для проверки изображений на наличие в них скрытых файлов.</p>
  <figure id="Iw4D" class="m_custom">
    <img src="https://xakep.ru/wp-content/uploads/2017/01/1484563090_461f_jhide-unhide.png" width="629" />
    <figcaption>Распаковка контейнера в jHide</figcaption>
  </figure>
  <p id="2vcq">Утилита иногда игнорирует вводимое имя файла и извлекает его с шаблонным именем <code>stego_%name%.bmp</code>, однако эту недоработку можно и простить. Содержимое файла считывается ей без искажений.</p>
  <h2 id="0YhV">OpenPuff</h2>
  <p id="2SO8"><a href="http://download.cnet.com/windows/openpuff-team/3260-20_4-10146585-1.html" target="_blank">http://download.cnet.com/windows/openpuff-team/3260-20_4-10146585-1.html</a></p>
  <p id="cSTJ">Самая сложная утилита в этом обзоре — OpenPuff. Ее последняя версия (4.00) поддерживает не только сокрытие одних файлов внутри других, но и работу со стегометками произвольного формата. Ей даже можно выделить несколько процессорных ядер, если предстоит большой объем работы.</p>
  <figure id="anYO" class="m_custom">
    <img src="https://xakep.ru/wp-content/uploads/2017/01/1484563100_aa72_openpuff-iface.png" width="431" />
    <figcaption>Основное окно OpenPuff</figcaption>
  </figure>
  <p id="JCzA">В отличие от других утилит, поддерживающих парольную защиту скрываемого сообщения, OpenPuff умеет использовать для шифрования криптографически стойкий генератор псевдослучайных чисел (CSPRNG — Cryptographically secure pseudorandom number generator). Если простого пароля недостаточно, то поставь флажки напротив полей <code>B</code> и <code>C</code>, а затем введи в них три разных пароля длиной от 8 до 32 символов. На их основе CSPRNG сгенерирует уникальный ключ, которым и будет зашифровано сообщение.</p>
  <figure id="KZey" class="m_custom">
    <img src="https://xakep.ru/wp-content/uploads/2017/01/1484563106_b5d2_openpuff_hidden.png" width="748" />
    <figcaption>Использование CSPRNG</figcaption>
  </figure>
  <p id="ZuDs">Мелкие файлы можно хранить в картинках и аудиозаписях, а крупные (например, криптоконтейнеры) удобнее прятать в видеозаписях — OpenPuff поддерживает MP4, MPG, VOB и множество других форматов. Максимальный размер скрываемого файла — 256 Мбайт.</p>
  <figure id="WD6p" class="m_custom">
    <img src="https://xakep.ru/wp-content/uploads/2017/01/1484563112_6f15_openpuff_bc.png" width="1040" />
    <figcaption>Результат работы OpenPuff</figcaption>
  </figure>
  <p id="pI8f">Применение CSPRNG на малых файлах сильно увеличивает итоговый размер стегосообщения. Поэтому разница между пустым и заполненным контейнером становится слишком очевидной. Мы снова видим, что измененные пиксели в основном распределяются равномерно, однако на самых светлых и самых темных участках они образуют крупные блоки. Если бы таких блоков не было, результат был бы больше похож на артефакты, получаемые при сжатии при помощи JPEG.</p>
  <p id="vTwr">Побайтное сравнение тоже дает очень характерную картину. Несмотря на малый размер скрываемого файла, в контейнере изменены значения у большинства пикселей. Если jHide хватило 330 байт для записи стегосообщения, то OpenPuff использовал для этой же задачи более 170 Кбайт.</p>
  <figure id="NeZj" class="m_custom">
    <img src="https://xakep.ru/wp-content/uploads/2017/01/1484563132_bf08_openpuff_bitcmp.png" width="1027" />
    <figcaption>Изменения затронули большинство пикселей</figcaption>
  </figure>
  <p id="7qc8">С одной стороны, это плюс: нет прямой корреляции между размером сообщения и числом измененных пикселей. Анализ такого контейнера существенно усложняется. С другой стороны, на создание контейнера приходится затратить дополнительные усилия, что может оттолкнуть неискушенного пользователя.</p>
  <p id="sqff">Другой режим работы программы — запись и чтение стегометок. Это скрытые строки длиной до 32 символов, которые можно использовать для защиты авторского права. Например, спрятать копирайт в фотографии, музыкальном файле или документе.</p>
  <p id="NrfQ">Работает эта функция исключительно просто. Пишешь произвольную стегометку в верхней части окна и указываешь ниже файлы, в которые ее надо добавить. Исходные файлы останутся нетронутыми, а их копии с меткой сохранятся в указанном тобой каталоге.</p>
  <figure id="Lo7v" class="m_custom">
    <img src="https://xakep.ru/wp-content/uploads/2017/01/1484563144_2903_openpuff-stegomarks.png" width="1040" />
    <figcaption>Работа со стегометками в OpenPuff</figcaption>
  </figure>
  <p id="Mr4n">При возникновении любых правовых споров просто запускаешь OpenPuff и показываешь изумленному оппоненту ранее внедренную метку.</p>
  <figure id="9ax3" class="m_custom">
    <img src="https://xakep.ru/wp-content/uploads/2017/01/1484563151_a4e9_openpuff-stegomark-frog.png" width="1040" />
    <figcaption>Даже лягушка может сказать, кто ее сфотографировал</figcaption>
  </figure>
  <p id="yLF8">Сложности возникают в том случае, если файл подвергался модификации. Даже простое конвертирование в другой формат стирает стегометку. Не удается ее считать и в том случае, если файл был снова приведен к исходному формату. Стойкие стегометки существуют, но внедрять их умеют только отдельные программы. Как правило, они привязаны к какому-то конкретному оборудованию (например, модели камеры).</p>
  <figure id="q32i" class="m_custom">
    <img src="https://xakep.ru/wp-content/uploads/2017/01/1484563179_b6fa_openpuff_stegomark_erased.png" width="783" />
    <figcaption>Стегометка испарилась после конвертации файла</figcaption>
  </figure>
  <h2 id="AfDX">OpenStego</h2>
  <p id="MW0X"><a href="http://www.openstego.com/" target="_blank">http://www.openstego.com/</a></p>
  <p id="4UNX">Последняя версия OpenStego (0.61) вышла в 2014 году. Программа работает в Windows и Linux. Она поддерживает BMP, PNG, JPG, GIF и WBMP. Заполненный контейнер всегда сохраняется в формате PNG.</p>
  <p id="ucYA">OpenStego занимает всего 203 Кбайт, но после знакомства с Hallucinate это уже не впечатляет. Формально утилита требует установки, хотя может быть легко превращена в портейбл-версию. OpenStego привлекает тем, что поддерживает парольную защиту и тоже умеет внедрять стегометки (правда, эта функция пока что имеет статус «бета»).</p>
  <figure id="C7gD" class="m_custom">
    <img src="https://xakep.ru/wp-content/uploads/2017/01/1484563186_9ca8_openstego_iface.png" width="714" />
    <figcaption>Интерфейс OpenStego</figcaption>
  </figure>
  <p id="fDPj">После добавления к выбранному изображению небольшого текстового файла визуально отличия между пустым и заполненным контейнером практически отсутствуют.</p>
  <figure id="Fb2Q" class="m_custom">
    <img src="https://xakep.ru/wp-content/uploads/2017/01/1484563191_45c9_openstego-bc_diff.png" width="1040" />
    <figcaption>Найди десять отличий</figcaption>
  </figure>
  <p id="C7SB">Однако размер файла увеличился на один мегабайт, а из-за конвертации в PNG с другой степенью сжатия это стал просто другой файл. При побайтном сравнении с оригиналом отличия будут во всех значениях сразу после заголовка.</p>
  <figure id="S7bv" class="m_custom">
    <img src="https://xakep.ru/wp-content/uploads/2017/01/1484563200_797e_openstego_bit_diffs.png" width="1001" />
    <figcaption>OpenStego: hex-сравнение</figcaption>
  </figure>
  <p id="vSm9">Интересно, что программа никак не проверяет правильность вводимого пароля при извлечении стегосообщения из контейнера. Она честно пытается собрать извлекаемый файл в любом случае и всегда сообщает, что операция прошла успешно. В действительности же спрятанный файл будет извлечен только после ввода правильного пароля. В остальных случаях произойдет ошибка и файл не запишется. Такой подход слегка затрудняет использование классических методов перебора паролей, в которых следующая комбинация подставляется после неудачной проверки предыдущей. Однако маркер успешного извлечения все же есть. Достаточно указать в качестве каталога пустой и перебирать пароли до тех пор, пока в нем не появится файл. Было бы лучше записывать любой результат извлечения как файл — это бы повысило уровень защиты.</p>
  <p id="ncBK">Внедрение стегометок в этой программе происходит не как в других. Сначала генерируется сигнатура, которая сохраняется в отдельный файл с расширением SIG. Какую-то осмысленную информацию в ней записать нельзя — это просто уникальный битовый набор, вроде приватного ключа.</p>
  <figure id="9q5j" class="m_custom">
    <img src="https://xakep.ru/wp-content/uploads/2017/01/1484563210_08fc_openstego_sig.png" width="715" />
    <figcaption>Создаем «водяной знак»</figcaption>
  </figure>
  <p id="byyi">После внедрения стегометки создается новый и визуально идентичный файл изображения, в котором она «растворяется». Процесс верификации сводится к проверке наличия указанной сигнатуры внутри файла. Если она сохранилась полностью, то совпадение будет стопроцентным. Если же файл подвергался модификации, то стегометка может быть частично утрачена. Метод задумывался как попытка внедрения стойких водяных знаков, однако в текущей реализации он практически бесполезен. Программа показывает нулевой процент соответствия уже после небольшой обрезки картинки и пересохранения в PNG с большим сжатием.</p>
  <figure id="BEp1" class="m_custom">
    <img src="https://xakep.ru/wp-content/uploads/2017/01/1484563217_9e03_openstego_watermarks.png" width="1040" />
    <figcaption>Водяные знаки испаряются после небольшой обработки</figcaption>
  </figure>
  <h2 id="QHeD">RARJPEG</h2>
  <p id="rWZi">Скрывать одни файлы внутри других можно и безо всяких стеганографических утилит. Конечно, это будет не аккуратное «растворение» по алгоритму LSB, а простое слияние, однако у этого известного в узких кругах метода есть и свои преимущества. Во-первых, он доступен без дополнительных инструментов. Во-вторых, позволяет легко передать любой файл, загрузив его как графический на какой-нибудь сайт (например, хостинг картинок или, чаще, имиджборд).</p>
  <p id="5jzr">Смысл метода в том, что графические файлы (в частности, JPEG) начинают интерпретироваться сразу с заголовка, в то время как архивы считываются только с метки начала архива. Сама метка может располагаться внутри файла где угодно, так как, помимо обычных архивов, есть многотомные и самораспаковывающиеся.</p>
  <p id="z6Pe">В качестве эксперимента упакуем все программы из сегодняшнего обзора в архив ZIP и добавим этот архив к файлу Wallpaper.jpg, создав новую картинку: Wallpaper-x.jpg. Просто запустим консоль Windows и напишем:</p>
  <pre id="jZh5">type Wallpaper.jpg Steg.zip &gt; wallpaper-x.jpg</pre>
  <figure id="qVHe" class="m_custom">
    <img src="https://xakep.ru/wp-content/uploads/2017/01/1484563227_d0e9_wallpaper-x.png" width="400" />
    <figcaption>Дописываем ZIP к JPG</figcaption>
  </figure>
  <p id="5frj">На выходе получится объединенный файл <code>wallpaper-x.jpg</code>. Его можно просмотреть как картинку или же открыть любым архиватором, который поддерживает формат ZIP. Если изменить расширение файла на ZIP, то он откроется файловым менеджером как каталог. Можно даже обойтись без переименования, а сразу использовать архивный плагин через команду быстрой распаковки (например, {ALT}+{F9} в Total Commander). Все файлы из такой «картинки» будут извлечены без проблем.</p>
  <p id="rMsI">Описанный трюк известен давно и работает также с некоторыми другими форматами файлов (как графических, так и архивов), однако наибольшую популярность получило сочетание RAR + JPEG.</p>
  <figure id="TQTO" class="m_custom">
    <img src="https://xakep.ru/wp-content/uploads/2017/01/1484563235_9f90_rarjpeg.png" width="799" />
    <figcaption>Начало архива ZIP внутри картинки и имя первого архивного файла</figcaption>
  </figure>
  <h2 id="rMC5">Выводы</h2>
  <p id="EOYB">Итак, мы рассмотрели семь утилит, одинаковых по своему назначению. Если одни можно смело рекомендовать, то другие я привел, чтобы проиллюстрировать типичные ошибки.</p>
  <p id="uUwo">Настоящие стеганографические утилиты не меняют размер файла-контейнера. Они «растворяют» скрываемое сообщение по алгоритму LSB или более продвинутому, стремясь сделать распределение измененных байтов неотличимым от наложения случайных шумов. Продвинутые утилиты умеют использовать шифрование, но добавить его можно и самому — например, используя VeraCrypt или тот же RAR.</p>
  <p id="xIbJ">Обнаружилось немало программ, которые вроде бы обещают защиту, но на деле имеют очень косвенное отношение к стеганографии. Они просто дописывают скрываемый файл в конец исходного, используют узнаваемые указатели и слабое шифрование.</p>
  <p id="12OT">Стеганографию эффективнее всего использовать не вместо криптографии, а вместе с ней. Такое сочетание позволяет скрыть как саму информацию, так и факт ее хранения или передачи.</p>
  <p id="tf1D"><a href="https://t.me/anon_chan_by" target="_blank">https://t.me/anon_chan_by</a></p>

]]></content:encoded></item><item><guid isPermaLink="true">https://teletype.in/@anon_channel/osint_probiv_infi</guid><link>https://teletype.in/@anon_channel/osint_probiv_infi?utm_source=teletype&amp;utm_medium=feed_rss&amp;utm_campaign=anon_channel</link><comments>https://teletype.in/@anon_channel/osint_probiv_infi?utm_source=teletype&amp;utm_medium=feed_rss&amp;utm_campaign=anon_channel#comments</comments><dc:creator>anon_channel</dc:creator><title>OSINT по-русски. Выбираем мощные бесплатные сервисы для пробива и конкурентной разведки.</title><pubDate>Sun, 20 Jun 2021 18:48:25 GMT</pubDate><media:content medium="image" url="https://teletype.in/files/7e/07/7e07e899-4f9a-4092-9985-915869d4fbfa.jpeg"></media:content><description><![CDATA[<img src="https://teletype.in/files/72/4e/724e5dee-7756-47ea-b4d7-fac61325fff0.png"></img>Телеграм канал.]]></description><content:encoded><![CDATA[
  <p id="YNVR"><a href="https://t.me/anonchanby" target="_blank">Телеграм канал.</a></p>
  <p id="Sagi"><strong>OSINT (Open Source INTelligence) — это раз­ведка по откры­тым источни­кам, то есть поиск информа­ции о челове­ке или орга­низа­ции по базам дан­ных, которые дос­тупны всем. Этим занима­ются как спе­циаль­ные орга­низа­ции и служ­бы, так и ком­пании (что­бы про­верить сот­рудни­ков или узнать боль­ше о кон­курен­тах) и прос­то люди, ког­да хотят получ­ше узнать, с кем они обща­ются в интерне­те и не ока­жет­ся ли «сер­цеед888» мань­яком‑убий­цей.</strong></p>
  <p id="BH2I">Я Собрал несколько сервисов, которые помогут в этом. Упор был сделан на РФ, т.к. в разных странах разные форматы данных и это затрудняет поиск.</p>
  <p id="1Js8">Перед тем как начнем, советую ознакомиться с 137 УК РФ.</p>
  <h3 id="po8y"><strong>ПОИСК ПО EMAIL</strong></h3>
  <p id="NHaW"><a href="https://emailrep.io/" target="_blank">Emailrep.io</a> находит, на каких сай­тах зарегис­три­рова­ны акка­унты, исполь­зующие опре­делен­ную поч­ту.</p>
  <figure id="BBXj" class="m_original">
    <img src="https://teletype.in/files/72/4e/724e5dee-7756-47ea-b4d7-fac61325fff0.png" width="644" />
  </figure>
  <p id="MNqJ">До­пол­нитель­но на осно­ве про­вер­ки по спам‑базам, а так­же базам вре­донос­ной активнос­ти сер­вис про­веря­ет репута­цию акка­унта: в час­тнос­ти, не попадал­ся ли он в утеч­ках.</p>
  <p id="eVlg"></p>
  <h3 id="Zn82">ПОИСК ПО НИКНЕЙМУ</h3>
  <p id="YPOA">Когда поиск по email не дает особых результатов, стоит попробовать поискать по никнейму.</p>
  <p id="sW6E"><a href="https://whatsmyname.app/" target="_blank">WhatsMyName</a> — это не прос­то сер­вис, а целый ком­байн, который ищет по 280 сер­висам!</p>
  <figure id="WZIn" class="m_original">
    <img src="https://teletype.in/files/24/45/2445e222-f928-4061-8f9c-62e9f7f198d7.png" width="1179" />
  </figure>
  <p id="2ncY">Здесь мож­но сор­тировать сер­висы по катего­риям, а еще есть воз­можность экспор­тировать резуль­тат поис­ка (URL най­ден­ных про­филей) в нес­коль­ких фор­матах.</p>
  <p id="KvdF"></p>
  <p id="hv2f">Сер­вис <strong><a href="https://usersearch.org/index.php" target="_blank">Usersearch.org</a></strong> пре­дос­тавля­ет поиск не толь­ко по популяр­ным соц­сетям, но и по темати­чес­ким форумам и сай­там зна­комств.</p>
  <figure id="9BXl" class="m_original">
    <img src="https://teletype.in/files/2c/ce/2cce8e9f-ba80-4ed7-a96e-165a0d725150.png" width="1177" />
  </figure>
  <p id="Rlh0">Вы­дача удоб­на тем, что ты не толь­ко получа­ешь спи­сок сер­висов со ссыл­кой на акка­унт, но и для каж­дого сер­виса есть ссыл­ка на стра­ницу уда­ления акка­унта, на слу­чай, если это вдруг твой акка­унт. Так­же сер­вис может допол­нитель­но искать по телефо­ну, email и про­бивать по базе <strong><a href="https://haveibeenpwned.com/" target="_blank">HIBP</a></strong>.</p>
  <h3 id="VQlG">ПОИСК ПО НОМЕРУ ТЕЛЕФОНА</h3>
  <p id="XPpe"><strong><a href="http://spra.vkaru.net" target="_blank">SpravkaRU.Net</a></strong> — весь­ма объ­емный телефон­ный спра­воч­ник, который может искать так­же по ФИО.</p>
  <figure id="6lia" class="m_original">
    <img src="https://teletype.in/files/3f/8f/3f8f39f8-af36-4ed4-a644-0aab1ab8c9e4.png" width="1029" />
  </figure>
  <p id="Nir7"><strong><a href="https://github.com/martinvigo/email2phonenumber" target="_blank">Email2phonenumber</a></strong> собира­ет дан­ные со стра­ниц вос­ста­нов­ления акка­унта во мно­жес­тве сер­висов и находит номер телефо­на.</p>
  <figure id="hL0W" class="m_original">
    <img src="https://st768.s3.eu-central-1.amazonaws.com/dd8cca8113b2746be6ea037b43d083d6/19835/email2h.jpg" width="620" />
  </figure>
  <p id="yiBy">По­мимо это­го, ути­лита может генери­ровать спи­сок номеров и переби­рать сер­висы на наличие номера телефо­на (где он ука­зан в про­филе).</p>
  <p id="62oh">Бот <strong><a href="https://t.me/last4mailbot" target="_blank">last4mailbot</a></strong> най­дет пос­ледние четыре циф­ры номера телефо­на кли­ента Сбер­банка.</p>
  <figure id="cPzH" class="m_original">
    <img src="https://teletype.in/files/c1/44/c144abb1-9db1-444f-8d44-d4939de2cd03.png" width="524" />
  </figure>
  <p id="RuWm">По­иск про­изво­дит­ся исклю­читель­но по email. Про­вер­ка нес­коль­ких почт, заведо­мо при­вязан­ных к Сбер­банку, показа­ла, что бот дей­стви­тель­но выда­ет вер­ные дан­ные.</p>

]]></content:encoded></item></channel></rss>