<?xml version="1.0" encoding="utf-8"?> 
<rss version="2.0"
  xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd"
  xmlns:atom="http://www.w3.org/2005/Atom">

<channel>

<title>Блоги: заметки с тегом ассемблер</title>
<link>https://blogengine.me/blogs/tags/assembler/</link>
<description>Автоматически собираемая лента заметок, написанных в блогах на Эгее</description>
<author></author>
<language>ru</language>
<generator>Aegea 11.0 (v4079e)</generator>

<itunes:subtitle>Автоматически собираемая лента заметок, написанных в блогах на Эгее</itunes:subtitle>
<itunes:image href="" />
<itunes:explicit>no</itunes:explicit>

<item>
<title>Программа с именем 0xFF</title>
<guid isPermaLink="false">130929</guid>
<link>https://bolknote.ru/all/programma-s-imenem-0xff/</link>
<pubDate>Thu, 26 Sep 2024 10:59:20 +0500</pubDate>
<author>Евгений Степанищев</author>
<comments>https://bolknote.ru/all/programma-s-imenem-0xff/</comments>
<description>
&lt;p&gt;&lt;a href="https://bolknote.ru/"&gt;Евгений Степанищев&lt;/a&gt;:&lt;/p&gt;
&lt;p&gt;В ДОСе, как может кто-то ещё помнит, была своя, отличная от всего, кодировка русских букв, так называемая &lt;i&gt;CP866&lt;/i&gt;. Это однобайтовая кодировка, то есть в таблице символов всего 256 позиций.&lt;/p&gt;
&lt;p&gt;Поэтому странно, что пробельных символов в ней два, один из них — обычный пробел с кодом 32, именно его операционная система считает пробелом, второй — с кодом 255, он выводится как пробел, но считается обычным символом.&lt;/p&gt;
&lt;p&gt;Не помню, использовалось ли это свойство для чего-то полезного или интересного, но на днях &lt;a href="https://www.opennet.ru/openforum/vsluhforumID3/134899.html#50"&gt;прочитал&lt;/a&gt; как развлекались с его помощью в те времена:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;А 255 символ запретили? 30 лет назад, еще под &lt;i&gt;MSDOS&lt;/i&gt;, переименовали утилиту переворота экрана в 255 символ и вставили в &lt;i&gt;autoexec.bat&lt;/i&gt;. Хозяин компа уже психовать начал и монитор переворачивать :)) Показали ему прикол…&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Ну то есть переименовали программу так, чтобы её имя выглядело как пробельный символ и добавили её в скрипт автозагрузки. Хозяин компьютера, видимо, проверял скрипт, ничего не находил и не понимал что происходит.&lt;/p&gt;
&lt;p&gt;Мне стало интересно проверить — действительно ли это работает? Благо ДОС можно сейчас запустить &lt;a href="https://www.pcjs.org/software/pcx86/sys/dos/microsoft/6.22/"&gt;даже в браузере&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Тут надо пояснить, что «настоящий» пробел для этого не годится — ДОС просто не распознает его в автозагрузке как имя файла для запуска.&lt;/p&gt;
&lt;p&gt;Я не знаю как раньше вводили символ с кодом 255 в командную строку, поэтому просто набросал программу на ассемблере, которая переименовывает файл &lt;tt&gt;mem.exe&lt;/tt&gt; (которая обычно есть в составе ДОСа) в &lt;tt&gt; .com&lt;/tt&gt;:&lt;/p&gt;
&lt;pre class="e2-text-code"&gt;&lt;code class="asm"&gt;org 100h

section .data
    oldName db &amp;#039;MEM.EXE&amp;#039;, 0
    newName db 255, &amp;#039;.COM&amp;#039;, 0

section .text
global _start

_start:
    mov ah, 56h
    lea dx, oldName
    lea di, newName
    int 21h

    mov ax, 4C00h
    int 21h&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Необходимое пояснение: расширение обязательно, иначе ДОС не поймёт, что файл запускаемый. При запуске его можно не указывать — операционка догадается сама что именно подставить.&lt;/p&gt;
&lt;p&gt;На следующем шаге я скомпилировал программу у себя прямо в «МакОСи» и вывел в шестнадцатеричном виде:&lt;/p&gt;
&lt;pre class="e2-text-code"&gt;&lt;code class="plaintext"&gt;$ hexdump -C &amp;lt;(nasm -f bin rename.asm -o /dev/stdout)
00000000  b4 56 8d 16 14 01 8d 3e  1c 01 cd 21 b8 00 4c cd  |.V.....&amp;gt;...!..L.|
00000010  21 00 00 00 4d 45 4d 2e  45 58 45 00 ff 2e 43 4f  |!...MEM.EXE...CO|
00000020  4d 00                                             |M.|
00000022&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Далее набрал её в кодах при помощи команды &lt;tt&gt;DEBUG&lt;/tt&gt; и запустил. В текущей директории появилась программа с нужным именем:&lt;/p&gt;
&lt;div class="e2-text-picture"&gt;
&lt;img src="https://bolknote.ru/pictures/2024.09.26.1@2x.webp" width="872" height="477" alt="" /&gt;
&lt;/div&gt;
&lt;p&gt;Для последнего шага мне нужно было как-то снова получить символ 255 в командной строке. Для этого я перенаправил вывод команды &lt;tt&gt;DIR&lt;/tt&gt; в файл &lt;tt&gt;START.BAT&lt;/tt&gt; и отредактировал получившееся при помощи команды &lt;tt&gt;EDIT&lt;/tt&gt; — убрал всё лишнее, кроме символа с именем команды (кажется у меня в файл попали ещё и лишние переводы строки, но они роли не играют).&lt;/p&gt;
&lt;p&gt;Попробовал запустить, сработало!&lt;/p&gt;
&lt;div class="e2-text-picture"&gt;
&lt;img src="https://bolknote.ru/pictures/2024.09.26.2@2x.webp" width="872" height="477" alt="" /&gt;
&lt;/div&gt;
</description>
</item>

<item>
<title>Дизассемблируй это</title>
<guid isPermaLink="false">136262</guid>
<link>https://bolknote.ru/all/4656/</link>
<pubDate>Sat, 27 Jan 2018 15:19:00 +0500</pubDate>
<author>Евгений Степанищев</author>
<comments>https://bolknote.ru/all/4656/</comments>
<description>
&lt;p&gt;&lt;a href="https://bolknote.ru/"&gt;Евгений Степанищев&lt;/a&gt;:&lt;/p&gt;
&lt;div class="e2-text-picture"&gt;
&lt;img src="https://bolknote.ru/pictures/2018.01.27.jpg" width="640" height="400" alt="" /&gt;
&lt;div class="e2-text-caption"&gt;«ДУМ», скомпилированный с использованием одних только команд &lt;i&gt;MOV&lt;/i&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;В моей жизни последовательно сменяли друг друга три ассемблера. Первый, для компьютера «Радио-86РК», я выучил по комментариям к ассемблерному коду в журнале «Радио» — другой литературы не было, а до моего знакомства с интернетом оставалось несколько лет. Потом были последовательно ассемблеры для «Спектрума» и интеловских процессоров.&lt;/p&gt;
&lt;p&gt;В те времена я думал, что всю жизнь буду программировать на ассемблере, на деле же последнюю программу на нём написал в начале 2000-х. Сейчас на чистом ассемблере мало кто пишет, а тем временем в этом мире иногда происходят интересные вещи.&lt;/p&gt;
&lt;p&gt;В ассемблере есть такая команда — &lt;i&gt;MOV&lt;/i&gt; (в некоторых ассемблерах — &lt;i&gt;LD&lt;/i&gt;), записывает содержимое одного аргумента в другой.  Сейчас набор комманд разросся, аргументом может быть почти что угодно — регистр, ячейка в памяти, сумма некоторого числа, одного регистра и другого, умноженного на число, но по сути это всегда присваивание.&lt;/p&gt;
&lt;p&gt;И вот оказалось, что эта команда — полная по Тьюрингу. Звучит невероятно, но это так. Некие ребята заморочились и сделали компилятор, который компилирует любую программу на Си в последовательность команд &lt;i&gt;MOV&lt;/i&gt;. Причём им даже &lt;a href="https://github.com/xoreaxeaxeax/movfuscator/tree/master/validation/doom"&gt;ДУМ удалось скомпилировать&lt;/a&gt;, правда один кадр рисуется семь часов. Кстати, такая программа неуязвима для горюшка века — Мелтдауна и Спектра.&lt;/p&gt;
&lt;p&gt;Есть &lt;a href="https://github.com/xoreaxeaxeax/movfuscator/blob/master/slides/domas_2015_the_movfuscator.pdf"&gt;небольшая (на 156 страниц и 90% воды) презентация&lt;/a&gt;, достаточно популярно объясняющая как этого удалось достичь, но для её чтения надо знать ассемблер, поэтому я позволю себе раскрыть детали трансляции двух инструкций, чтобы пояснить принцип для тех, кто ассемблера не знает или ленится причитать.&lt;/p&gt;
&lt;p&gt;Например, сравнение двух чисел делается при помощи следующего псеводокода:&lt;/p&gt;
&lt;pre class="e2-text-code"&gt;&lt;code class=""&gt;mov [X], 0
mov [Y], 1
mov R, [X]&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;У нас есть два числа в аргументах «&lt;i&gt;X&lt;/i&gt;» и «&lt;i&gt;Y&lt;/i&gt;», результат сравнения которых попадает в «&lt;i&gt;R&lt;/i&gt;» — там будет ноль, если числа не равны и единица в противном случае. Как же это работает?&lt;/p&gt;
&lt;p&gt;Первой командой ноль записывается в ячейку по адресу «&lt;i&gt;X&lt;/i&gt;». Это ассемблер, у нас тут всё — число, остальное — человеческие интерператации, поэтому записанное в «&lt;i&gt;X&lt;/i&gt;» мы используем как адрес. Второй командой единица записывается в ячейку по адресу «&lt;i&gt;Y&lt;/i&gt;». Третьей командой мы читаем значение по адресу «&lt;i&gt;X&lt;/i&gt;» и если значения в «&lt;i&gt;X&lt;/i&gt;» и «&lt;i&gt;Y&lt;/i&gt;» совпадают, то ноль перетрётся единицей (и она попадёт в &lt;i&gt;R&lt;/i&gt;), если нет, то в ячейке по адресу «&lt;i&gt;X&lt;/i&gt;» ноль останется (который попадёт в &lt;i&gt;R&lt;/i&gt;).&lt;/p&gt;
&lt;p&gt;Несложно. Но из кода выше непонятно как получаются другие необходимые инструкции. Увы, но какого-то единого принципа для всего нет, авторам для каждого набора приходилось придумывать что-то новое. Думаю интересно будет взглянуть на реализацию чего-нибудь ещё.&lt;/p&gt;
&lt;p&gt;Возьмём, например, логическое «ИЛИ» («OR»), тут чуточку сложнее:&lt;/p&gt;
&lt;pre class="e2-text-code"&gt;&lt;code class=""&gt;OR_ADDRS: dd OR_0, OR_1
OR_0: dd 0, 1
OR_1: dd 1, 1
; …
mov eax, X
mov edx, [OR_ADDRS + eax]
mov eax, Y
mov eax, [eax + edx]
mov R, eax&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Во всех логических операциях ребята используют записанные заранее неизменяемые массивы значений.&lt;/p&gt;
&lt;p&gt;Что тут происходит? В регистр (переменную, с которыми работает процессор) «&lt;i&gt;eax&lt;/i&gt;» записывается значение «&lt;i&gt;X&lt;/i&gt;» (возможные входные значения у нас тут — ноль или единица, численное представление булевых значений).&lt;/p&gt;
&lt;p&gt;Далее в регистр «&lt;i&gt;edx&lt;/i&gt;» записывается число из адреса, который является суммой адреса массива &lt;i&gt;OR_ADDRS&lt;/i&gt; и содержимого регистра &lt;i&gt;eax&lt;/i&gt;. Таким образом в &lt;i&gt;eax&lt;/i&gt; попадёт &lt;i&gt;OR_0&lt;/i&gt; или &lt;i&gt;OR_1&lt;/i&gt;, в зависимости от того былы записаны в &lt;i&gt;eax&lt;/i&gt; ноль или единица. Эти значения — тоже числа и являются адресами двух других массивов из двух элементов.&lt;/p&gt;
&lt;p&gt;Далее в &lt;i&gt;eax&lt;/i&gt; мы записываем аргумент &lt;i&gt;Y&lt;/i&gt;, его значение складывается с адресом полученным на предыдущем шаге и из получившегося адреса мы читаем записанное там значение. В переводе на ПХП получается следующее:&lt;/p&gt;
&lt;pre class="e2-text-code"&gt;&lt;code class=""&gt;function mov_or(int $X, int $Y): int
{
    define(&amp;#039;OR_0&amp;#039;, [0, 1]);
    define(&amp;#039;OR_1&amp;#039;, [1, 1]);

    define(&amp;#039;OR_ADDRS&amp;#039;, [OR_0, OR_1]);

    $R = OR_ADDRS[$X][$Y];

    return $R;
}&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Кстати, интересно, что у знаменитого дисассемблера «&lt;a href="https://ru.wikipedia.org/wiki/IDA"&gt;ИДА&lt;/a&gt;» от полученной таким образом программы крепко уносит крышу — при попытке отладки диссасемблер не видит никаких ветвлений и падает на анализе кода. Получился бы неплохой метод защиты от анализа, если бы не производительность.&lt;/p&gt;
</description>
</item>

<item>
<title>Пацакку</title>
<guid isPermaLink="false">124596</guid>
<link>https://bolknote.ru/all/3880/</link>
<pubDate>Fri, 22 Feb 2013 08:53:00 +0500</pubDate>
<author>Евгений Степанищев</author>
<comments>https://bolknote.ru/all/3880/</comments>
<description>
&lt;p&gt;&lt;a href="https://bolknote.ru/"&gt;Евгений Степанищев&lt;/a&gt;:&lt;/p&gt;
&lt;div class="e2-text-picture"&gt;
&lt;img src="https://bolknote.ru/pictures/2013.02.22.png" width="644" height="257" alt="" /&gt;
&lt;div class="e2-text-caption"&gt;Пацак.Ку&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Далёкие дни, Университет, вирус «&lt;a href="https://web.archive.org/web/20130302102522/http://www.securelist.com/ru/descriptions/68323/Virus.DOS.Pacakku.1120"&gt;Пацакку&lt;/a&gt;». С большим трудом припоминаю, что это был простой, написанный на Ассемблере вирус для ДОСа, который в день моего рождения выдвигал шторку сидирома (если он есть) и печатал на принтере (кажется; или в корень клал файл, или то и другое, не помню) фразу «в обществе где нет цветовой дифференциации штанов, нет и цели», цитату из любимого моего фильма «&lt;a href="http://ru.wikipedia.org/wiki/Кин-дза-дза!"&gt;Кин-дза-дза!&lt;/a&gt;». Судя по названию, данному в Лаборатории Касперского, там где-то были фразы «пацак» и «ку», но я помню это как-то туманно.&lt;/p&gt;
&lt;p&gt;Кстати, в Университетe самодельных вирусов хватало. Особенно мне запомнился вирус «TV» (был так назван моим тогдашним другом А.Г. из-за того, что проверял своё содержимое в памяти по этим двум байтам, записанным по определённому адресу), который доводил студентов до истерик — он менял местами действие клавиш «&lt;i&gt;Esc&lt;/i&gt;» и «&lt;i&gt;Enter&lt;/i&gt;». Когда программа спрашивала «Сохранить?» на выходе, студент жал «энтер», на самом деле нажимался «эскейп» и вся работа за день терялась.&lt;/p&gt;
&lt;p&gt;Тогда же я придумал свой первый антивирус, который назвал просто «Вакцина» (файл запуска — «vac.com» или «vac.exe», не помню точно размер), «вакциной» он назывался вполне заслуженно, так как именно &lt;i&gt;вакцинировал&lt;/i&gt; компьютеры. Это была одна из &lt;a href="https://bolknote.ru/all/1899/"&gt;двух утилит&lt;/a&gt;, которые сильно упрощали мою тогда лаборантскую жизнь. Принцип действия был следующий.&lt;/p&gt;
&lt;p&gt;Большинство вирусов того времени ставили какой-то маркер в памяти компьютера, чтобы определить заражали они этот компьютер уже или нет. Чаще всего перехватывался вектор прерывания &lt;a href="http://en.wikipedia.org/wiki/INT_21h"&gt;21h&lt;/a&gt; и создавалась какая-нибудь функция, досом не используемая, но были и другие варианты (например, тот же «TV»). При появлении нового вируса я его анализировал, определял эту функцию и добавлял её в свою «вакцину».&lt;/p&gt;
&lt;p&gt;Вирус, запущенный на таком компьютере, думал, что он тут уже есть и не заражал машину. Кроме того, моя вакцина предупреждала о попытке заражения вируса при вызове этих самых функций. У вакцины был ещё встроенный монитор перехвата вектора &lt;a href="http://en.wikipedia.org/wiki/INT_13h"&gt;13h&lt;/a&gt;, который использовали более серьёзные функции, принцип был подсказан тем же А.Г. — если обработчик 13h, при запуске моей программы, был не в БИОСе (а адреса его были известны), так же поднималась тревога.&lt;/p&gt;
&lt;p&gt;Если честно, я смутно помню, что принцип был чуть хитрее, но в чём была тонкость, не помню. Если вспомню, расскажу.&lt;/p&gt;
&lt;p&gt;Позднее я придумал и начал писать конфигуратор на Турбо Паскале, но так и не дописал, терпение кончилось на интерфейсе.&lt;/p&gt;
&lt;p&gt;У моего антивируса было несколько достоинств: он ловил все тогдашние студенческие поделки, ходившие в нашем Университете, включая мои собственные, ну и просто популярные вирусы того времени, он был бесплатен и быстро обновлялся, был крошечным, не жрал ресурсы компьютера (что было особенно актуально в нашем компьютерном классе на &lt;i&gt;IBM XT&lt;/i&gt;, там процессоры были 8086 и даже «Нортон» работал медленно) и &lt;i&gt;предотвращал заражение&lt;/i&gt;, а не просто поднимал тревогу, когда вирус уже внедрился, т. е. лечить такой компьютер было не нужно, что было очень актуально в случае печально известного вируса «&lt;a href="http://ru.wikipedia.org/wiki/CIH"&gt;Чернобыль&lt;/a&gt;», эпидемию которого в своих классах я быстро пресёк на корню.&lt;/p&gt;
&lt;p&gt;И раз уж у меня сегодня рубрика «воспоминания в утренней пробке», расскажу как лечили порчу вирусом «Чернобылем» БИОСа. Лечил всё тот же А.Г. Поражённый компьютер вскрывался, в него ставился такой же чип БИОСа с другого компьютера (напоминаю, дело в компьютерных классах было, когда я лаборантом работал в Университете, там было много однотипных машин), компьютер загружался, обычной программой для прошивки БИОСа с чипа списывалось его содержимое (или оно, как вариант, бралось из интернета), потом &lt;i&gt;наживую&lt;/i&gt; чип доставался и вставлялся испорченный, после чего пациент перепрошивался правильной прошивкой.&lt;/p&gt;
&lt;p&gt;Кстати, мне «повезло» учиться и лаборантить в классах где стоял весь зоопарк: 8086, 80286, 80386 и даже бездисковые станции, которые грузились по сети, настоящие (тормозные) тонкие клиенты с утилитами &lt;a href="http://ru.wikipedia.org/wiki/Novell"&gt;Новелла&lt;/a&gt;.&lt;/p&gt;
</description>
</item>


</channel>
</rss>