Блокчейн Namecoin был создан как защищенная от цензуры и принудительного изъятия доменов альтернатива традиционным регистраторам DNS. В последние несколько лет его начали использовать операторы таких ботнетов, как Dimnie, Shifu, RTM и Gandcrab, для управления адресами C&C-серверов.
С одной стороны, децентрализованность и устойчивость блокчейна не позволяют исследователям и провайдерам удалить такие домены или перехватить управление ими. С другой стороны, инфраструктура на основе блокчейна имеет архитектурную особенность: все изменения в сети публично доступны и могут быть использованы для изучения и отслеживания действий злоумышленников.
В этой работе представлен подход, использованный для картографирования активов ботнета в Namecoin и дальнейшего их отслеживания для извлечения новых IOC. С помощью описанного подхода были собраны перечни активов (см. приложение), использованных упомянутыми выше ботнетами.
Лирическое отступление
Изобретения, меняющие интернет, зачастую решают не только и не столько техническую проблему, сколько социальную. Именно такие технологии и сервисы позволяют сообществу взглянуть со стороны на некоторые аксиомы, казавшиеся незыблемыми, переосмыслить их, пересоздать from scratch, оставив лишь идею и сбросив накопленный годами груз унаследованных условностей и ограничений. Блокчейн и Bitcoin, Tor, Wikipedia — за успехом каждого из них стоит небольшая группа энтузиастов с горящими глазами, искренне верящих, что они делают общество лучше.
Увы, зачастую следом за ними приходят другие — чуждые странным для них идеалам пионеров интернета, но гораздо более практичные. Они находят для технологии альтернативное применение, о котором создатели и не думали (или не хотели думать). Находясь на границе (а чаще, чего уж скрывать, откровенно за границей) допустимого, это альтернативное применение, зачастую не без помощи СМИ, для большинства превращается в подразумеваемое по умолчанию, а то и в единственное.
Эквивалентность технологии как идеи и наиболее обсуждаемого метода ее использования способна привести к отторжению обществом самой технологии. В результате криминализации ее использования незрелый сервис может быть низведен до уровня маргинальной культуры или быть полностью уничтожен. Так давным-давно случилось с Napster, не так давно — с BitTorrent и Tor, прямо сейчас это происходит с Bitcoin.
Не миновало это и героя настоящей работы — Namecoin. Namecoin — блокчейн, предназначенный для хранения произвольных пар вида «ключ — значение», наиболее известным применением которого является децентрализованная, устойчивая к цензуре система регистрации имен DNS — Dot-Bit.
Наш интерес к Namecoin вырос после того, как группа, управляющая ботнетом RTM, начала использовать Dot-Bit для управления своими C&C-серверами. В какой-то момент нам стало интересно — а возможно ли обнаруживать новые C&C-серверы непосредственно после их регистрации в Dot-Bit? И если с обновлениями известных доменов проблем не предвиделось, то разработка подхода, позволяющего обнаруживать строгие доказательства связи новых доменов с интересующей персоной, внезапно оказалась захватывающей исследовательской задачей, результатом которой и стала эта работа.
В целом исследования Namecoin и сбор индикаторов компрометации в Dot-Bit проводились и ранее. Наиболее детальной работой можно считать статью Кевина Перлоу. Он первым обратил внимание на принципиальную возможность извлечения данных из Namecoin и описал несколько эвристических техник, позволяющих эксперту находить домены, схожие по характеристикам с известными C&C-серверами той или иной группы.
Подход, представленный в этом исследовании, имеет несколько существенных отличий от экспертной техники indexing and pivoting, описанной Кевином. Разработанные нами эвристические правила определения владельцев доменов выводятся из принципов работы блокчейна и формирования транзакций в нем и, помимо общего описания, представлены в виде строгих логических формулировок. Вместе с формальным описанием алгоритма обхода это позволяет автоматизировать поиск IOC, что существенно повышает эффективность расследования. Кроме этого, разработанный алгоритм помогает не только найти другие имена, когда-то использованные исследуемой группой, но и позволяет отслеживать создание новых доменов, которыми управляет та же персона.
Вся работа поделена на три главы. В первой главе дается описание основ работы Bitcoin, код которой использовался как платформа для создания Namecoin. Многие сущности, взаимосвязи и их реализации, определенные в Bitcoin, были унаследованы Namecoin. Их понимание является критически важным для дальнейшего изложения.
Вторая глава посвящена непосредственно Namecoin и ее основному применению — Dot-Bit.
В третьей главе приводится описание предлагаемого подхода для извлечения данных из Namecoin, а также дается формальное описание алгоритма обхода блокчейна и эвристических правил, используемых для установления взаимосвязей между доменами.
В приложениях приведены IOC, собранные с использованием описанного метода для некоторых ботнетов, а также список литературы и репозиториев, которые помогут исследователям, желающим продолжить работу над этой темой.
Bitcoin 201
Большая часть информации этого раздела собрана из материалов цикла статей Сергея Pavlov_dog Потехина «Bitcoin in a nutshell». Для русскоязычных читателей этот источник, на наш взгляд, является наиболее полным и глубоким из публично доступных, но при этом удивительно легко читается. Исследователей, интересующихся внутренним устройством Bitcoin, мы призываем не ограничиваться выдержками, приведенными в этом разделе, а ознакомиться с полным текстом статей, доступным по ссылке в приложении. Остальным же изложенной ниже информации будет достаточно, чтобы понять описание алгоритма и эвристических правил поиска взаимосвязей между адресами в Namecoin, приводимыми в последней главе.
Хотя рассказ о блокчейне принято обычно начинать с блоков и связывающей их криптографии, мы начнем с транзакций.
Транзакция
Как известно, наиболее близким аналогом Bitcoin является бухгалтерская книга, в которую записаны все транзакции с монетами. Но, как ни странно, в Bitcoin не существует никакой общей таблицы вида
<адрес, баланс>
, ровно как и не существует главного бухгалтера, который бы эту таблицу редактировал.Вместо этого используется тот самый пресловутый блокчейн, то есть хранятся вообще все транзакции. Для простоты можно считать, что это сообщения вида:
<address 1> sent <amount> BTC to <address 2>
А значит, если пройтись по всему блокчейну, то можно посчитать, сколько монет «принадлежит» конкретному адресу.
Входы и выходы
Реальная транзакция в сети Bitcoin немного сложнее описанной выше. Это структура, главными составляющими которой являются входы (inputs) и выходы (outputs).
Inputs — это транзакции, на которые вы «ссылаетесь». Представим, что на ваш адрес X когда-то было отправлено три транзакции:
TXN_ID: 123456, VALUE: 40 BTC
TXN_ID: 645379, VALUE: 10 BTC
TXN_ID: 888888, VALUE: 100 BTC
Если вам нужно потратить, например,
45 BTC
, то вы можете сослаться на транзакцию 888888
или сразу на две транзакции: 123456
и 645379
. Outputs — дословно «выходы». Можно считать, что это “адреса”, на которые в результате исполнения транзакции будут «отправлены» монеты. Выходов также может быть несколько, для каждого из них указывается своя сумма.
Outputs — дословно «выходы». Можно считать, что это «адреса», на которые в результате исполнения транзакции будут «отправлены» монеты. Выходов также может быть несколько, для каждого из них указывается своя сумма.
На картинке ниже создается новая транзакция
C
, которая ссылается на два выхода — A
и B
. В результате на входе у транзакции получается 0.008 BTC
, которые потом разделяются на два выхода — на первый адрес отправляется 0.001 BTC
, а на второй 0.006 BTC
.Возможность указать сразу несколько выходов — это очень важная фича, потому что выход транзакции можно использовать как вход только один раз и только целиком. Если у вас есть входящая транзакция на
10 BTC
, а вам нужно потратить 8 из них, вы просто создаете транзакцию с одним входом и двумя выходами: на 8 BTC
продавцу и на 2 BTC
обратно на свой адрес. Если же вы создадите транзакцию, в которой сумма выходов меньше суммы входов (как на картинке), то разница отправляется на адрес майнера, записавшего вашу транзакцию в блок.Fee
Именно эта разница между суммой входов и суммой выходов и называется «комиссия за транзакцию»,
transaction fee
. Она является вторым по важности источником дохода для майнеров и именно от нее зависит время включения транзакции в блокчейн. Это связано с тем, что у каждого майнера существует некоторый пул непроверенных транзакций, которые претендуют на попадание в блок, и, как правило, майнер просто сортирует их по убыванию комиссии, тем самым максимизируя свою прибыль. Поэтому чем больше комиссия, тем выше вы окажетесь в очереди и тем быстрее пройдет ваш платеж.Общий вид транзакции описан в официальной спецификации протокола, здесь же приведен один из самых распространенных частных случаев.
previous output hash
— идентификатор (хеш) транзакции, на которую ссылаемся. previous output index
— поскольку сослаться нам нужно не на саму транзакцию, а на один из ее выходов, то в этом параметре мы и указываем, какой конкретно выход нас интересует. Нумерация начинается с нуля. value
— количество сатоши (1/100000000
BTC), направляемых на выход. Записывается в little-endian форме, то есть 62 64 01 00 00 00 00 00
— это 0x016462
или 0.00091234 BTC
.Параметры
block lock time
и sequence
довольно редко используются на практике. Нам они не интересны, поэтому описание их назначения опустим.А вот на параметрах со словом
script
в названии остановимся подробнее.Script
В сети Bitcoin существует механизм, основанный на криптоалгоритмах с открытым ключом, позволяющий создать систему, в которой только владелец ключа может воспользоваться монетами, ассоциированными с адресом, полученным из этого ключа. Разберемся, как это реализовано под капотом.
Начнем с того, что внутри Bitcoin существует простой стековый язык программирования, названный
Script
. Вот простейшая программа на Script:2 3 OP_ADD 5 OP_EQUAL
Каждая инструкция называется
opcode
, всего их порядка 80. На картинке ниже изображен процесс исполнения приведенной выше программы.В Bitcoin
Script
применяется для того, чтобы задать условие, при котором можно будет потратить выход, и для возможности подтвердить то, что условие выполнено. Условие (locking script
) сохраняется в транзакции в поле scriptPubKey
для каждого выхода. Подтверждение того, что условие выполнено (unlocking script
) пишется в поле scriptSig
для каждого входа.Для проверки права использовать выход нужно соединить
unlocking script
+ locking script
и запустить получившуюся программу как одно целое. Если после исполнения сверху стека останется TRUE
, то транзакция валидна.Pay to Public Key Hash (P2PKH)
Скрипт
P2PKH
используется в большинстве транзакций, так что стоит разобраться, как он работает. Вот его общий вид:Этот скрипт известен с самого появления Bitcoin и именно он выполняет ту задачу, которая упоминалась в начале главы — сделать так, чтобы только владелец ключа смог воспользоваться монетами, ассоциированными с адресом, полученным из этого ключа.
Идея такая: пусть вашему другу
B
принадлежит пара ключей — P
(приватный) и K
(публичный). С помощью функции хеширования он получает из публичного ключа адрес A
и сообщает адрес вам. Далее вы отправляете, к примеру, 1 BTC
на адрес A
и в поле locking script
пишете примерно следующее:Только тот, кто владеет приватным ключом для адресаA
, сможет потратить эту транзакцию. В качестве доказательства запишите вunlocking script
, во-первых, публичный ключK
, а во-вторых — подпись транзакции приватным ключомP
.
Когда
B
решит использовать вашу транзакцию в качестве входа, он создаст свою, например на 0.5 BTC
, а в поле unlocking script
поместит подпись своей транзакции приватным ключом P
— sig
и сам публичный ключ K — PubK
.Вот процесс выполнения объединенной программы:
Блоки и blockchain
Если блокчейн целиком — это книга, то отдельные блоки можно представлять как страницы, на которых записываются транзакции. Каждый блок «ссылается» на предыдущий, и так до самого первого блока (
genesis block
). Именно это и создает такую особенность блокчейна, как неизменяемость. Нельзя взять и изменить блок #123
так, чтобы этого никто не заметил: блокчейн устроен таким образом, что это повлечет изменение блока #124
, потом #125
и так далее, до самого верха.Структура блока выглядит так:
Первые шесть параметров (все кроме
txn_count
и txns
) образуют заголовок блока (header
). Именно хеш заголовка называют хешем блока; сами транзакции непосредственного участия в хешировании не принимают. За их неизменность отвечает merkle_root
— если упрощенно, то это хеш всех транзакций в блоке. Подробнее об алгоритме построения дерева Меркла можно почитать вот по этой ссылке.Nonce и bits имеют непосредственное отношение к процессу появления блоков — майнингу.
Mining
Майнинг — это критически важный для Bitcoin процесс, состоящий в создании новых блоков и преследующий сразу две цели. Первая — производство денежной массы. Каждый раз, когда майнер создает новый блок, ему за это полагается награда в N-е число монет, которые он потом где-нибудь тратит, тем самым запуская в сеть новые средства.
Вторая, и куда более важная, цель — контроль соблюдения правил в сети. Именно майнеры проверяют скрипты и входы транзакций перед включением их в блок.
Желающим узнать подробнее о финансовых основах Bitcoin можно посоветовать вот эту статью. Я же не буду уделять много внимания первому аспекту майнинга и сконцентрируюсь на втором — проверке транзакций и запуске их в сеть.
Proof-of-Work
Пусть вы — майнер. У вас есть 10 транзакций, которые вы хотите включить в блок. Вы проверяете эти транзакции на валидность, формируете из них блок, в поле
nonce
указываете 0 и считаете хеш блока. Потом меняете nonce
на 1, снова считаете хеш.Ваша задача — найти такой
nonce
, при котором хеш блока (256-битное число) меньше заранее заданного числа N
. Поиск такого хеша возможен только перебором nonce
. Поэтому чем быстрее вы хотите найти nonce, тем больше мощностей вам понадобится.Число
N
— именно тот параметр (его еще называют target
), который сеть подстраивает в зависимости от суммарной мощности майнеров. Если завтра блоки начнут выходить, условно говоря, раз в три минуты, то N
будет уменьшено, времени на поиск nonce потребуется больше и block time
снова вырастет до 10 минут. И наоборот.Так выглядит алгоритм Proof-of-Work, лежащий в основе Bitcoin и многих других блокчейнов. При кажущейся простоте он обладает рядом важных характеристик:
- Создание нового блока — вычислительно сложная задача. При этом проверка блока на корректность — простая и практически мгновенная операция.
- На вычисление нового блока у всей сети уходит 10 минут (в среднем). Конкретное время отличается для каждого блокчейна, но суть заключается именно в том, что среднее время заранее установлено. Более того, это время не зависит от числа участников сети. Даже если однажды майнеров станет в сто раз больше, алгоритм так изменит свои параметры, чтобы блок стало находить сложнее, и
block time
опустился обратно в окрестность заданного времени.
Как было написано выше, процесс майнинга сводится к тому, чтобы найти хеш блока меньше числа, называемогоtarget
. В структуре блока это число записывается в поле bits. Например, для блока#277316 target
равнялся1903a30c
.
Как было написано выше, процесс майнинг сводится к тому, чтобы найти хэш блока меньше числа, называемого
target
. В структуре блока это число записывается в поле bits
. Например, для блока #277316
target
равнялся 1903a30c
.$ bitcoin-cli getblock 0000000000000001b6b9a13b095e96db41c4a928b97ef2d944a9b31b2cc7bdc4
{
"hash" : "0000000000000001b6b9a13b095e96db41c4a928b97ef2d944a9b31b2cc7bdc4",
"confirmations" : 35561,
"size" : 218629,
"height" : 277316,
"version" : 2,
"merkleroot" : "c91c008c26e50763e9f548bb8b2fc323735f73577effbc55502c51eb4cc7cf2e",
"tx" : ["d5ada064c6417ca25c4308bd158c34b77e1c0eca2a73cda16c737e7424afba2f", ...],
"time" : 1388185914,
"nonce" : 924591752,
"bits" : "1903a30c", // <-- Вот он
"difficulty" : 1180923195.25802612,
"chainwork" : "000000000000000000000000000000000000000000000934695e92aaf53afa1a",
"previousblockhash" : "0000000000000002a7bbd25a417c0374cc55261021e8a9ca74442b01284f0569",
"nextblockhash" : "000000000000000010236c269dd6ed714dd5db39d36b33959079d78dfd431ba7"
}
В
bits
на самом деле записаны сразу два числа: первый байт 0x19
— экспонента, оставшиеся три байта 0x03a30c
— мантисса. Чтобы получить target
из bits
, нужно воспользоваться следующей формулой: target = mantissa * 2^(8 * (exponent - 3))
Но именно
bits
, как правило, указывается во всех онлайн-реестрах блоков, таких как, например, https://namecha.in/ — реестр блоков Namecoin. И да, достаточно теории. Все то, о чем мы говорили выше в применении к Bitcoin, в равной мере относится и к Namecoin — кроме небольших отличий, о которых мы и поговорим в следующем разделе.
Namecoin
Namecoin — блокчейн, основанный на алгоритмах и исходном коде Bitcoin, основной идеей которого является применение схемы распределенного реестра транзакций для управления системой доменных имен, аналогом традиционной DNS.
Namecoin копирует основные подходы Bitcoin (Proof-of-Work, 10-минутный интервал генерации блоков) и форматы данных, за исключением небольших дополнений, о которых мы и поговорим дальше.
Домены Namecoin имеют суффикс .bit. Эта зона не выделялась IANA и не была отнесена к списку доменов специального назначения. Обычные серверы DNS, как правило, отвечают на такие запросы NXDOMAIN. Но существуют шлюзы из DNS в Namecoin (например, OpenNIC), публичные прокси с поддержкой Namecoin, плагины к браузерам, а также проект с открытым кодом, позволяющий запустить свой собственный сервер DNS с поддержкой Namecoin.
Для того чтобы управлять доменом c именем, скажем,
facebook.bit
, достаточно зарегистрировать ключ d/facebook
(префикс d/ используется в Namecoin для доменов) и определить его значение. Для задания значений используется формат JSON. Запись, задающая разрешение домена в IP-адрес 1.2.3.4
, выглядит так:{"ip": ["1.2.3.4"]}
Namecoin выделяет имена по принципу first-come-first-served. Даже для самого Марка Цукерберга будет криптографически невозможно отобрать у владельца домен
facebook.bit
.На самом деле ничто не ограничивает область использования Namecoin только лишь управлением связками имя DNS — IP-адрес. Namecoin может быть использована (и используется) как распределенная таблица для сопоставления произвольных ключей со значениями. Но мы сконцентрируемся именно на том сценарии ее использования, в котором она представляет собой альтернативный DNS over blockchain.
Управление доменами
Для хранения записи о домене в Namecoin используется транзакция. А именно — поле
scriptPubKey
, содержащее программу — условие использования выхода транзакции, которой мы посвятили так много времени в предыдущей главе. Для управления записями в Namecoin ввели три новых оператора (точнее, переопределили существующие):- NAME_NEW
- NAME_FIRSTUPDATE
- NAME_UPDATE
Их смысл понятен из названий, но тем не менее мы разберем назначение и формат использования каждого их них.
Можно заметить, что отсутствует оператор удаления или инвалидации домена. Для очистки реестра от неиспользуемых имен в сеть встроен механизм, автоматически освобождающий имя, которое не обновлялось 36 000 блоков (~ 250 дней).
NAME_NEW
На первом шаге необходимо анонсировать в сеть намерение зарегистрировать новое имя. Для этого достаточно создать специальную монету (выход) весом не менее
0.01 NMC
, output script
которой будет выглядеть примерно так:OP_NAMENEW <20 byte hash> OP_2DROP <lock script>
Для демонстрации я буду использовать транзакции, которые сделал Стивен Морс для иллюстрации своей статьи.
Итак, если мы хотим анонсировать регистрацию имени
d/stephenmorse
, то нам необходимо сделать следующее:Глядя на получившуюся транзакцию, можно заметить два любопытных факта. Во-первых, несмотря на то, что
output script
составлен в нотации Namecoin, он по-прежнему валиден и с точки зрения оригинального Bitcoin. Создатели Namecoin так удачно выбрали коды для своих операций, что в Bitcoin они соответствуют операциям, которые по сути равносильны записи в стек констант. Код NAME_NEW (0x51)
в Bitcoin соответствует OP_1
, которая помещает в стек 1. Похожая история и с NAME_FIRSTUPDATE
(0x52
или OP_2
, помещает 2) и с NAME_UPDATE
(0x53
или OP_3
, помещает 3). Так что первые два шага скрипта лишь помещают в стек два значения. А идущая следом операция OP_2DROP
удаляет их из стека, так что дальше P2PKH
работает «с чистого листа». Поэтому все те трюки со скриптами, которые мы разбирали в главе про Bitcoin, применимы и в Namecoin, несмотря на переопределения некоторых операций.Во-вторых, ключи, которыми открываются специальная монета и сдача, отличаются. Хотя технически ничто не мешает использовать один и тот же ключ многократно, общепринятая практика — генерировать новый ключ для каждого поступления. Это сделано для того, чтобы затруднить выявление корреляций между транзакциями и повысить уровень анонимности в сети.
На первый взгляд кажется странным, что, вопреки здравому смыслу, невозможно сразу взять и зарегистрировать имя плюс IP-адрес для него. Это сделано для того, чтобы никто не смог перехватить имя, как только увидит, что вы хотите его зарегистрировать (и потом перепродать вам).
Например, майнеры, анализируя неподтвержденные (пока не включенные ни в один из блоков) транзакции в сети, могли бы создать свою транзакцию на регистрацию того же домена и включить ее (а не вашу) в свой блок. Для реализации этой атаки необязательно даже майнить свой блок. Достаточно будет выложить в сеть свою транзакцию с большим fee. Поэтому и введены две раздельных операции
NAME_NEW
и NAME_FIRSTUPDATE
, и вторую может провести только тот, кто проводил первую, и только после того, как NAME_NEW
попадет в какой-либо блок. На самом деле это ограничение даже чуть строже:
NAME_FIRSTUPDATE
возможна не ранее чем через 12 блоков после NAME_NEW
(что составляет около 2 часов). Чтобы понять, почему блоков в этом ограничении не 1, не 2, не 3, а именно 12, нам придется немного отойти от основного рассказа и разобраться, что такое fork
и 51% attack
.Fork
Представим, что майнеры ищут блок
Возможно ли такое? Да, возможно. Более того, такое происходит довольно часто. В этом случае каждый узел продолжает придерживаться своей версии блокчейна до тех пор, пока кто-нибудь не найдет следующий блок. Предположим, что новый блок продолжает зеленую ветку, как на картинке ниже. В этом случае те узлы, которые придерживаются красной версии, автоматически синхронизируют зеленую, потому что в Bitcoin (и, соответственно, в Namecoin) работает правило: истинна самая длинная версия блокчейна. Красная версия блокчейна будет попросту забыта, вместе с наградами для тех, кто ее нашел.
Конечно, теоретически на втором шаге ситуация может повториться и одновременно с фиолетовым найдут еще один, который будет продолжать красную версию блокчейна. И на третьем, и так далее. Но вероятность даже первого форка довольно мала, второго — еще меньше и так далее. Самый длинный форк за всю историю Bitcoin составил всего четыре блока. Так что в какой-то момент одна из веток все-таки вырвется вперед, и вся сеть перейдет на нее.
#123456
. И примерно в одно и то же время он был найден независимо друг от друга двумя майнерами, один из которых живет в Австралии, а другой в США. Каждый из них начинает раскидывать свою версию блока по сети, и в результате получается, что у одной половины мира один блокчейн, а у другой — другой.Возможно ли такое? Да, возможно. Более того, такое происходит довольно часто. В этом случае каждый узел продолжает придерживаться своей версии блокчейна до тех пор, пока кто-нибудь не найдет следующий блок. Предположим, что новый блок продолжает зеленую ветку, как на картинке ниже. В этом случае те узлы, которые придерживаются красной версии, автоматически синхронизируют зеленую, потому что в Bitcoin (и, соответственно, в Namecoin) работает правило: истинна самая длинная версия блокчейна. Красная версия блокчейна будет попросту забыта, вместе с наградами для тех, кто ее нашел.
Конечно, теоретически на втором шаге ситуация может повториться и одновременно с фиолетовым найдут еще один, который будет продолжать красную версию блокчейна. И на третьем, и так далее. Но вероятность даже первого форка довольно мала, второго — еще меньше и так далее. Самый длинный форк за всю историю Bitcoin составил всего четыре блока. Так что в какой-то момент одна из веток все-таки вырвется вперед, и вся сеть перейдет на нее.
51% attack
На том факте, что в блокчейне самая длинная цепочка — доминирующая, основана атака, носящая имя 51%.
Представьте, что вы мошенник и покупаете товар на
В это время вы включаете свою майнинг-ферму и начинаете майнить, начиная с блока
Гарантировано осуществить такую атаку получится только в том случае, если у вас в распоряжении более половины хешрейта всей сети. Меньшие мощности дают меньшую вероятность успеха. В разделе 11 вот этой статьи приведены вычисления, показывающие, что длины цепочки в 6 блоков достаточно, чтобы снизить до величины ниже 0,1% вероятность успешной атаки злоумышленника, контролирующего не более 10% хешрейта. Эту цифру до сих пор считают общепринятой границей, за которой вероятностью исчезновения транзакции из блокчейна можно пренебречь. Вероятно, создатели Namecoin решили перестраховаться и удвоили эту планку, застраховавшись от атакующих с 20% мощности сети.
Но вернемся к процессу регистрации доменного имени. Итак, я объявил сети о намерении зарегистрировать новое имя. С момента моей транзакции, содержащей
Представьте, что вы мошенник и покупаете товар на
1000 BTC
в каком-нибудь магазине. Вы договариваетесь с продавцом и отправляете ему деньги. Продавец проверяет блокчейн, видит, что такая транзакция действительно была, прошла все проверки и даже попала в какой-нибудь блок, например #123
. После этого продавец идет на почту и отправляет вам товар.В это время вы включаете свою майнинг-ферму и начинаете майнить, начиная с блока
#122
. Если у вас достаточно мощностей, то вы можете обогнать всю остальную сеть и быстрее всех досчитать до блока #124
, после чего весь мир перейдет на вашу версию блокчейна. При этом свою транзакцию на 1000 BTC
, вы не будете включать ни в один из блоков, а значит она будет навсегда забыта, как будто ее никогда и не было. В результате продавец лишится товара и не получит своих денег.Гарантировано осуществить такую атаку получится только в том случае, если у вас в распоряжении более половины хешрейта всей сети. Меньшие мощности дают меньшую вероятность успеха. В разделе 11 вот этой статьи приведены вычисления, показывающие, что длины цепочки в 6 блоков достаточно, чтобы снизить до величины ниже 0,1% вероятность успешной атаки злоумышленника, контролирующего не более 10% хешрейта. Эту цифру до сих пор считают общепринятой границей, за которой вероятностью исчезновения транзакции из блокчейна можно пренебречь. Вероятно, создатели Namecoin решили перестраховаться и удвоили эту планку, застраховавшись от атакующих с 20% мощности сети.
Но вернемся к процессу регистрации доменного имени. Итак, я объявил сети о намерении зарегистрировать новое имя. С момента моей транзакции, содержащей
NAME_NEW
, прошло 12 блоков, и теперь сеть позволяет мне выполнить NAME_FIRSTUPDATE
.NAME_FIRSTUPDATE
Цель операции
NAME_FIRSTUPDATE
— опубликовать имя, которое я анонсировал в NAME_NEW
, и указать для него значение. Для этого мне потребуется запустить в сеть транзакцию, входом которой является та самая специальная монета, которую я сформировал на выходе NAME_NEW
. Для того, чтобы подтвердить право ее использовать, я предъявляю в input script свой публичный ключ и подпись транзакции NAME_NEW
, сделанной парным приватным ключом, — точно по схеме, которую мы разобрали в главе про P2PKH
.Одним из выходов транзакции будет новая специальная монета весом, как и предыдущая, не менее
0.01 NMC
. Ее output script должен быть таким:OP_NAME_FIRSTUPDATE <Name> <Salt> <Value> OP_2DROP OP_2DROP <lock script>
Salt
— то самое случайное число 0xd5eeb22ee8117f57
, которое мы создали на первом этапе подготовки скрипта для NAME_NEW
. Name
— это d/stephenmorse
в шестнадцатеричном виде, 0x642f7374657068656e6d6f727365
.Поле
Value
должно содержать ассоциативный массив, представляющий правила, по которым будет разрешаться имя. Полный список возможных ключей и правил их наполнения приведен здесь. В первом приближении это аналог файла зоны; по ссылке выше приведен маппинг сущностей Namecoin в привычные сущности DNS. Самые популярные из них — ip, пример с которым был выше, и ns, который мы используем сейчас.Чтобы указать, что NS-сервером для домена будет
1.2.3.4
, в Value поместим значение {“ns”:[“1.2.3.4”]}
, но, разумеется, в шестнадцатеричном виде — 0x7b226e73223a5b22312e322e332e34225d7d
.Как и в прошлый раз, закроем монету с помощью
P2PKH
. В своем примере Стивен специально создал на шаге NAME_NEW монету весом не точно 0.01 NMC
, а с запасом, чтобы на следующем шаге этого запаса хватило на комиссию майнеру. В общем случае у транзакции будет еще один вход для обеспечения комиссии — и еще один выход, для сдачи. Собираем все в транзакцию и кидаем в сеть.
Когда транзакция попадет в блок, узлы сети обновят в своих таблицах значение для ключа
d/stephenmorse
на {“ns”:[“1.2.3.4”]}
. Все браузеры с поддержкой Namecoin теперь будут разрешать домен stephenmorse.bit
и его поддомены в IP-адреса через DNS-сервер, расположенный по адресу 1.2.3.4
.NAME_UPDATE
«Таблица» с ключами и их значениями, которую я упомянул в конце прошлого раздела, на самом называется
UTXO set (unspent transaction output)
. Поскольку для сети критически важно не допустить повторного расхода средств, то перед добавлением транзакции в блок майнер проверяет, не использовались ли ранее указанные в транзакции входы. Для ускорения этой операции все неиспользованные выходы хранятся в отдельной структуре данных. Эта структура не существует на уровне сети, но рассчитывается и хранится каждым узлом локально.После того как я выполнил транзакцию
NAME_FIRSTUPDATE
, выход моей монеты весом 0.01 NMC
, к которому прикреплено значение для ключа d/stephenmorse
, попал в таблицу UTXO
. Если этот выход не будет потрачен в течение 36 000 блоков (что составляет больше 8 месяцев при 10 минутах на блок в среднем), то он будет рассматриваться как недействительный, а соответствующее ему имя — как свободное.Этот период в 36 000 блоков (как и минимальная величина специальной монеты в
0.01 NMC
) явно определен при запуске сети и неизменяем. Чтобы продлить регистрацию имени, а также для любых изменений записи или передачи ее другому владельцу используется транзакция NAME_UPDATE
.Правила формирования такой транзакции практически не отличаются от описанных выше. Входом для транзакции должен быть выход монеты, получившейся в транзакции
NAME_FIRSTUPDATE
. Дополнительный вход нужен для обеспечения комиссии. Из двух выходов транзакции один представляет собой новую монету с обновленным значением для имени, а второй предназначен для перевода сдачи с комиссии. Формат output script для монеты такой:OP_NAME_UPDATE <Name> <Value> OP_2DROP OP_DROP <lock script>
Как и в предыдущем случае,
Name
— это d/stephenmorse
, а Value
— JSON со значением, оба в шестнадцатеричном виде. Закрываем выход с помощью P2PKH и кидаем транзакцию в сеть.В целом это практически всё, что я хотел рассказать про управление именами в Namecoin. Остается разве что сказать несколько слов про затраты на владение доменом.
Затраты
Давайте посчитаем, сколько стоит содержание имени в
Dot-Bit
(название DNS-зоны .bit, функционирующей на базе Namecoin) в криптовалюте и, переведя цифры в фиатную валюту, сравним со стоимостью «обычного» домена DNS.Итак, как видно из предыдущего раздела, для транзакции
NAME_NEW
затраты владельца домена составят 0.01 NMC
на создание монеты, к которой будет крепиться зона, плюс комиссия майнера. Для транзакции NAME_FIRSTUPDATE
новая монета создается за счет старой, и дополнительно владелец оплачивает только комиссию. Примерно через 8 месяцев владельцу придется провести транзакцию NAME_UPDATE
для сохранения за собой зарегистрированного имени. И на этом обязательные затраты на первый год заканчиваются.Большинство статей о Namecoin (включая цитируемую ранее статью Стивена Морса) основаны на данных первых лет существования сети и утверждают, что комиссия майнера составляет 0.005 NMC. Но с тех пор медианное значение комиссии постепенно снижалось и на начало 2019 года составляет около 0.0003 NMC. Курс NMC к доллару CША, наоборот, претерпев несколько взлетов, вернулся к уровню 2015 года и составляет порядка $0.7 за 1 NMC. Несложно посчитать, что домен в зоне .bit в первый год будет стоить владельцу от 0.0109 NMC или $0.00763. Возможно, кому-то проще будет запомнить примерный аналог этой суммы в российской валюте — 50 копеек.
Хорошо, это нижний предел, соответствующий сценарию покупки имени впрок или киберсквоттинга. А что с верхним пределом? Поскольку входом каждой транзакции, обновляющей зону, должна служить монета из одного из предыдущих блоков, то теоретический максимум частоты обновления имени равен частоте появления новых блоков. Вспомнив, что среднее значение этой величины заложено при запуске сети и составляет порядка 10 минут, можно посчитать, что верхний предел затрат на содержание домена составит 15,7744 NMC или чуть больше $11.
Как видно, даже такой фантастический сценарий использования имени в Namecoin по стоимости получается примерно равноценным первому году владения обычным доменом в самой популярной зоне .com. Если же сравнивать более реалистичный сценарий с обновлением в среднем раз в сутки, то имя в зоне .bit обойдется примерно в 8 центов в год, что на порядок дешевле самых выгодных предложений в традиционном DNS, которые не опускаются ниже $1. В сценарии же краткосрочного использования домена (от нескольких часов до месяца) разница в пользу Namecoin составит уже два порядка.
Принимая во внимание финансовую привлекательность сервиса, а также анонимность владельца домена, включая отсутствие традиционного для обычного DNS «денежного следа», становится понятно, почему Namecoin стал популярной сетью для владельцев сервисов с повышенным риском отключения или блокировки — в частности, ботнетов.
Ботнеты в Namecoin
Действительно, в том, что операторы ботнетов стали использовать анонимность
Dot-Bit
для защиты своих С&C-серверов, ничего удивительного нет. Интереснее другое — насколько долго ботнеты в .bit остаются активными.Домены C&C, зарегистрированные в «обычных» DNS-зонах, рано или поздно изымаются у владельца, что вынуждает оператора платить за регистрацию нового имени и запускать в сеть новую сборку бота, с новым управляющим сервером. Принципиальная невозможность изъятия домена в зоне .bit увеличила время жизни ботнета на порядки.
Возьмем для примера
pationare.bit
— домен, зарегистрированный в декабре 2016 года. Он использовался для управления ботнетом Chthronic
(распространяющим банковский троян, построенный на базе известного ZeuS). Кампания распространения Chthronic
была связана с использованием эксплойт-пака RIG и подробно описывалась различными исследователями (например, malware-traffic-analysis.net) в конце 2016-го — первой половине 2017 года.Можно было бы предположить, что этот ботнет давным-давно уничтожен. Но нет — спустя более чем два года после запуска C&C-домен ботнета и связанная с ним сеть все еще активны. Как видно из скриншота ниже, последнее обновление было сделано в декабре 2018 года.
Выглядит заманчиво, не так ли? Поскольку DNS-имя управляющего сервера остается нетронутым, то нет необходимости в частом обновлении кода ботов и перезапуске кампании по распространению. Остаются лишь затраты на смену хостинга после блокировки IP-адреса, но и эти затраты можно снизить за счет использования в качестве прокси взломанных веб-серверов, шеллы к которым стоят меньше доллара.
С другой стороны, все транзакции в блокчейне публично доступны любому участнику. Как мы подробно обсудили в предыдущих главах, монеты в Namecoin не исчезают бесследно, и значит, мы можем отследить их перераспределение между адресами. А зная правила и ограничения, с учетом которых формируются транзакции в Namecoin, мы можем найти осмысленные паттерны, при которых единое управление некоторых адресов, участвовавших в транзакции, будет очевидно. В этом случае у доменов, оплаченных монетами с этих адресов, будет общий владелец — исследуемая нами группа, управляющая ботнетом.
Эту идею мы и разовьем далее.
Общая схема сбора IOC
Опишем общую схему поиска на примере реального ботнета группы RTM. Будем отталкиваться вот от этого сэмпла, который был идентифицирован как
Win32/Spy.RTM.N
. Как видно из скриншота выше, после запуска он пытается получить IP-адрес для имени
stat-counter-4.bit
. Получаем информацию об истории транзакций по этому имени в Namecoin.Идентификатор транзакции, создавшей этот домен, мы получаем, перейдя по ссылке на операцию NAME_NEW. Адрес на входе этой транзакции, с помощью средств которого был создан домен, очевидно, управляется интересующей нас группой. Он и будет начальным набором данных:
N3KPt8py24EAsAiKquyFgoKGyTYeR5Tmry
. Оттолкнувшись от начального набора данных, мы итеративно обойдем блокчейн, двигаясь по направлению его роста (восходящее движение, или upstream movement). В начале каждого шага мы получаем транзакцию, определенная монета на входе которой принадлежит интересующей нас персоне. На первом шаге мы проверяем транзакцию из начального набора данных, владелец монет на входе которой нам известен априори.
Транзакция проверяется на соответствие эвристическим правилам (их мы сформулируем ниже), которые гарантируют, что определенная монета (или монеты) на выходе транзакции принадлежат той же персоне, что и известная нам монета на входе. Если рассматриваемая транзакция удовлетворяет одной или нескольким эвристикам, то такие направляющие монеты будут указывать направление дальнейшего движения. Транзакция, которая тратит направляющую монету, и будет следующим шагом итерации.
На каждом шаге итерации мы пополняем список доменов, которые участвовали в транзакциях, и список IP-адресов, в которые разрешались эти домены. Это исторические идентификаторы компрометации (IOC), которые могут быть использованы для форензистов, а также для выявления тактик и методов группировки.
Движение останавливается, если рассматриваемая транзакция не удовлетворяет ни одной из эвристик. Это означает, что мы не можем с уверенностью говорить о том, что какой-либо из выходов рассматриваемой транзакции управляется интересующей нас персоной.
Еще одна ситуация, останавливающая движение — отсутствие транзакций с адреса на выходе. Такие адреса мы будет сохранять в отдельный список непотраченных монет (UTXO). Они представляют самую большую ценность во всем исследовании. Поскольку мы уверены, что эти адреса управляются интересующей нас персоной, то любая будущая транзакция с использованием этих адресов генерирует новый, ранее неизвестный IOC — имя домена или IP-адрес — который еще не использовался группировкой. Но с большой вероятностью скоро будет.
Для обхода блокчейна его удобно экспортировать в базу данных. Для этого можно воспользоваться, например, модифицированной утилитой rusty-blockparser, в которой мы улучшили поддержку Namecoin, добавив распознавание операций
NAME_*
, структуры данных Auxiliary Proof-of-Work
и расширив формат экспорта.Псевдокод на Python для восходящего движения представлен ниже. Здесь и далее предполагается, что данные транзакций блокчейна хранятся в MongoDB.
start = "37d40bc2f3ca7415908dc9e276593b50d3120158cd540cb088246f2e2cf88b16"
tx = namecoin.transactions.find_one({"id": start})
def upstream_movement(tx):
global names
global IPs
global utxo
global known_addresses
heuristic_result = upstream_heuristic_test(tx)
if heuristic_result and heuristic_result.guiding_outs:
if tx.has_name_op():
names.add(tx.name_op.name)
for ip_address in tx.name_op.get_ip():
IPs.add(ip_address)
for guiding_out in heuristic_result.guiding_outs:
known_addresses.add(guiding_out.address)
tx = namecoin.transactions.find_one({"in.id": guiding_out.id})
if tx:
upstream_movement(tx)
else:
utxo.add(guiding_out)
Вторая часть обхода блокчейна — движение против роста блокчейна (нисходящее движение, или downstream movement). В целом алгоритм нисходящего движения не отличается от алгоритма восходящего. Движение начинается с транзакции из первоначального набора данных. На каждом шаге транзакция проверяется на соответствие эвристическим правилам (в общем случае отличающимся от правил для восходящего движения). Различие заключается лишь в том, что монета, принадлежность которой известна априори, находится на выходе транзакции, а эвристики гарантируют принадлежность той же персоне одной или нескольких монет на входе.
Нисходящее движение также останавливается, если текущая транзакция не удовлетворяет ни одной из эвристик. В отличие от восходящего движения, мы не можем встретить непотраченные монеты среди направляющих, и этот вариант выхода из рекурсии в нисходящем движении не сработает. Но, как и при восходящем движении, мы пополняем и список имен, и список IP-адресов.
Псевдокод на Python для нисходящего движения выглядел бы так:
start = "37d40bc2f3ca7415908dc9e276593b50d3120158cd540cb088246f2e2cf88b16"
tx = namecoin.transactions.find_one({"id": start})
def downstream_movement(tx):
global names
global IPs
global utxo
global known_addresses
heristic_result = downstream_heuristic_test(tx)
if heuristic_result and heuristic_result.guiding_ins:
if tx.has_name_op():
names.add(tx.name_op.name)
for ip_address in tx.name_op.get_ip():
IPs.add(ip_address)
for guiding_in in heuristic_result.guiding_ins:
known_addresses.add(guiding_in.address)
tx = namecoin.transactions.find_one({"out.id": guiding_in.id})
if tx:
downstream_movement(tx)
Теперь рассмотрим эвристические правила, которые мы будем использовать при движении по блокчейну.
Эвристические правила
Common Change
Посмотрим еще раз на транзакцию, скриншот которой приведен выше. На вход транзакции подается адрес
N3KPt8py24EAsAiKquyFgoKGyTYeR5Tmry
, содержащий деньги для создания нового имени. Для транзакций NAME_FIRSTUPDATE
и NAME_UPDATE
на входе будет два адреса — специальная монета с зоной от предыдущей транзакции по домену и дополнительные средства на покрытие комиссии.Я сразу отмечу, что в контексте транзакций мы будем говорить как про монеты, так и про адреса. Несмотря на то, что в некоторых работах эти понятия считаются практически равнозначными, для нас важно четко обозначить разницу между этими терминами, поскольку в ходе исследования мы будем делать выводы как касательно монет, так и адресов.
Говоря «монета», мы будем подразумевать положительный баланс, сформированный как выход какой-либо транзакции. Эта монета идентифицируется номером транзакции, которая ее породила, и индексом выхода. Например, монета на входе рассмотренной выше транзакции имеет идентификатор
5778be8e1901e9931e9b41a128a0b7f963e6e1ae72e461df2cba26e6279d433a:1
, поскольку была сформирована как выход (c индексом 1) транзакции 5778be8e1901e9931e9b41a128a0b7f963e6e1ae72e461df2cba26e6279d433a
.Специальной монетой, как и ранее, мы будем называть монету номиналом в
0.01 NMC
, в locking script
которой содержится операция с доменным именем. Мы подробно разбирали механизм формирования таких монет в разделе Управление доменами. Обычной монетой мы будем называть монету произвольного номинала, к которой не привязана операция с доменом.Основным свойством монет является их неразменность. Любая монета может быть потрачена только единожды и только целиком. Таким образом, любая упоминается в сети Namecoin максимум два раза: один раз при создании, а второй раз при расходовании.
Говоря «адрес», мы будем подразумевать идентификатор, однозначно определяющий пару ключей, которая может раскрыть locking script в формате
P2PKH
, закрывающий монету, находящуюся на входе или выходе транзакции. Поскольку только ключ, соответствующий адресу, может потратить монету, то ближайшей аналогией физического мира для адреса является кошелек, в котором сохраняются (и из которого тратятся) монеты.Несмотря на то что в Namecoin адрес зачастую также используется лишь дважды, для получения и расхода одной-единственной монеты это не обязательно так. Факты переиспользования адресов нам немного помогут в дальнейшем.
Подробнее о входах, выходах и адресах мы говорили в главе Bitcoin 201.
Итак, на выходе транзакции сформированы две монеты. На адрес
N2hgZoWaTKoJ7FPmLuytTow3XrCCfEj2ca
ушла та самая специальная монета весом 0.01 NMC, к которой привязан домен. На второй адрес NKMMLwyMw4nwGuke6vd3AuDBMP18FWRaF1
ушла обычная монета со сдачей.Это самая часто встречающаяся схема транзакции. Бывают еще варианты, когда на входе больше одной монеты, но их общее свойство в том, что монета со сдачей всегда ровно одна.
Можно догадаться, что такая транзакция соответствует простому обновлению информации о домене. Оплата за обновление выполняется с помощью одной (реже нескольких) монет, принадлежащих одной персоне. Действительно, поскольку у транзакции всегда только один автор, то он должен управлять всеми адресами на входе. Без этого он не сможет сформировать unlocking script, который нужен для того, чтобы воспользоваться монетами из этого кошелька.
Ну и поскольку вся сдача с этой операции собирается в одну монету, то понятно, что эта монета принадлежит той же персоне, что и монеты на входе.
Похожая схема для Bitcoin описана в этой работе, где называется
one-time change
. Она отражает метод, которым проводят транзакции нативные приложения Bitcoin — bitcoind
и bitcoin-qt
. Одноразовой (one-time) она называется из-за еще одной особенности этих приложений. По умолчанию они генерируют новые адреса для монет на выходе создаваемой транзакции. Namecoin вместе с кодовой базой Bitcoin унаследовал и основную часть кода этих приложений, которые здесь называются
namecoind
и namecoin-qt
. В том, что касается обычных монет, мы можем смело воспользоваться этой эвристикой без каких-либо изменений.Статистика переиспользования адресов для хранения специальных монет показывает, это правило в большинстве случае соблюдается и для них. Повторное использование таких адресов встречается достаточно редко. Адресов, использованных более одного раза, около 6% от общего количества; более двух раз — около 1%. Исходя из предназначения Namecoin, представляется оправданным предположение, что большинство транзакций со специальными монетами в сети является простыми операциями создания и обновления, в ходе которых владелец домена не меняется. Поэтому мы можем утверждать, что такой операции соответствует вывод специальной монеты на новый, ранее неиспользованный адрес.
Теперь посмотрим на пример транзакции с повторно использованным адресом для специальной монеты на выходе. Для этого возьмем еще одну транзакцию группы RTM —
b3c7ce9ca3a689c6236b9d6df3c257c5fab6c3985187669ccf731ac42a127a11
.Адрес
NDpWDEx1mBkUYywqxDTAZZeGCfUV4GkVE8
, на который ушла специальная монета, уже использовался в предыдущих транзакциях.Как было сказано ранее, сценарии, настроенные по умолчанию в нативных клиентских приложениях для Namecoin, не приводят в переиспользованию адресов. Чтобы отправить специальную монету на уже существующий адрес, владельцу потребуется приложить отдельные, необязательные усилия, выяснив и указав адрес выхода явно на этапе формирования транзакции.
Зачем может это потребоваться? Единственное упоминание ситуации, в которой адрес выхода указывается вручную, мне встретилось лишь в инструкции по передаче домена другому владельцу.
Догадка подтверждается, если рассмотреть дальнейшую судьбу адресов на выходе рассматриваемой транзакции. На схеме ниже эта транзакция отмечена ярко-зеленой вехой. Видно, что следующая транзакция
9e16f6be
по домену stat-counter-4 прошла с привлечением денежного адреса NJ8xUePv
, не имеющего явной связи с адресом, использованным в «материнской» транзакции. Очевидно, что домен был передан в управление другой персоне. В общем случае это может быть как продажа домена другому владельцу, не связанному с деятельностью рассматриваемой персоны, так и передача домена между счетами одной персоны. За второй вариант выступают простота и низкая стоимость регистрации нового домена, а также отсутствие видимого интереса организаций и владельцев торговых марок к регистрации доменов в зоне .bit. Нам не удалось придумать хотя бы мало-мальски обоснованной мотивации покупки домена, замеченного в зловредной активности. Поэтому мы считаем, что несмотря на возможность передачи домена другой персоне, транзакции с многократно используемыми адресами для вывода специальной монеты представляют собой перегруппировку активов между несколькими счетами, контролируемыми одной группой.
Сформулируем приведенные выше рассуждения в виде эвристического правила, которое назовем common change:
Если на выходе транзакции находится лишь одна обычная монета, то будем считать, что эта монета принадлежит той же персоне, что и монеты на входе.
Если при этом на выходе есть еще и специальная монета, то она также принадлежит персоне, владеющей монетами на входе.
Все адреса, использованные в такой транзакции, будем считать управляемыми одной персоной.
Схема использования этого правила показана на рисунке. Серые потоки — обычные монеты, зеленый — специальная монета. Направляющими будут все монеты с конца транзакции напротив монеты, через которую мы пришли к этой транзакции: все выходы — для восходящего движения, и все входы — для нисходящего.
Отметим несколько особенностей этой эвристики. Во-первых, двунаправленность: она работает и для восходящего движения, когда мы знаем владельца входа, и для нисходящего, когда нам известен владелец одной из монет на выходе.
Во-вторых, опциональность наличия специальной монеты: несмотря на то, что в ее отсутствие транзакция не имеет отношения к обновлению домена, приведенные выше логические рассуждения относительно владельца обычной монеты на выходе остаются справедливыми.
Псевдокод тестирования транзакции на соответствие правилу common change выглядел бы так:
def common_change(tx):
result = {"guiding_outs": [], "guiding_ins": []}
if len(tx.outs.money) != 1:
return {}
addr = tx.outs.money[0].address
first_tx = namecoin.tx.find_one({"out.id": addr}, sort=[("block", 1)])
if first_tx.id != tx.id:
return {}
else:
result["guiding_outs"] = tx.outs.all
result["guiding_ins"] = tx.ins.all
return result
Common Spending
Рассмотренная выше эвристика обладает еще одним важным свойством, помимо двунаправленности. Common change — эвристика «без памяти»; результат проверки определяется только характеристиками рассматриваемой транзакции и никак не зависит от результатов других эвристик и накопленных данных. Такая эвристика незаменима на первых итерациях обхода, для первоначального наполнения набора данных. С другой стороны, легко заметить ограниченность ее применения. Например, она остановится на транзакции, содержащей два или более денежных выхода.
В качестве примера такой транзакции рассмотрим
db4ff4082f39d0a501508706e627f26aa92712d27b4f633ded59917d201cfae5
. Эта транзакция относится к деятельности группы, управляющей ботнетом Dimnie.Мы вышли на эту транзакцию в нисходящем движении через адрес
My7Ap3nH5f4X6Us2KiUWisd77wRpMG1MDY
, который использовался в предыдущей CC-транзакции в качестве адреса входа. Несмотря на то, что его отношение к изучаемой персоне не вызывает сомнений, мы не может утверждать того же (равно как и обратного) о любом из остальных выходов и входов. Это может быть перераспределение монет между адресами группы, и в этом случае все адреса контролируются интересующей нас персоной. Или это, возможно, пополнение с адресов какой-либо из бирж, продающей токены Namecoin. Или перевод от другого участника сети, не имеющего отношения к деятельности изучаемой персоны. По атрибутам одной лишь этой транзакции сделать однозначный вывод невозможно.Рассмотрим адрес
N4XtLb7xpC4Zk72T8QcshKhTW17ZCyQ1j1
на входе этой транзакции. Этот адрес уже использовался ранее («ранее» для нисходящего движения означает «в будущем», «в направлении роста блокчейна») на входе CC-транзакции 6bffc741eb66de074c09a380fb5e6bd13d4bd5205c36a76e3682674dba08461e
, что позволяет считать этот адрес управляемым интересующей нас персоной. А поскольку, как уже было показано, ключами от всех монет на входе транзакции управляет одна персона (чего нельзя сказать о выходах), у нас появляются основания считать, что все остальные входы также принадлежат интересующей нас группе.Строгое условие эвристики common spending выглядит очень просто:
Если известно, что хотя бы один из адресов на входе транзакции управляется определенной персоной, то и все остальные адреса на входах этой транзакции управляются этой же персоной. Монеты на этих входах принадлежат этой же персоне.
Как видно, эта эвристика имеет смысл только для нисходящего движения. При движении в направлении роста блокчейна мы приходим к изучаемой транзакции через один из входов. В этом случае условие правила выполняется автоматически, но ничего не говорит о выходах транзакции и не позволяет продолжить движение в восходящем направлении. Другими словами, это однонаправленная эвристика.
Вторая особенность этой эвристики, которую стоит отметить, заключается в том, что здесь мы впервые использовали данные, накопленные в результате проверки предыдущих транзакций, — список адресов, управляемых исследуемой персоной. По этой причине эта вторичная эвристика не может использоваться для самостоятельного движения, без какой-либо первичной эвристики, не зависящей от накопленных результатов (такой, как common change).
Псевдокод тестирования транзакции на соответствие правилу common spending выглядел бы так:
def common_spending(tx):
result = { "guiding_ins": [] }
for input in tx.get_ins():
if input.address in known_addresses:
return {"guiding_ins": tx.ins.all}
return {}
Known Address
Последняя эвристика, которую мы рассмотрим в рамках этого раздела, самая простая из всех. Это вторичная двунаправленная эвристика, которая (поскольку является двунаправленной) может быть использована как для восходящего, так и для нисходящего движения. Строгая формулировка эвристики known address для восходящего движения выглядит так:
Если известно, что адрес на входе (на выходе) транзакции управляется определенной персоной, то монеты, поступившие на этот адрес (потраченные с этого адреса), принадлежат той же персоне.
Несмотря на то, что эвристика выглядит как откровенный трюизм, это правило помогает находить ответвления и пересечения в потоках монет и добавляет связности дереву транзакций. Кроме того, оно позволяет не останавливать движение на транзакциях, которые не попадают под остальные эвристики. В качестве примера можно привести транзакцию
7a35b9cb0a16b3eba92781be014555eaa4255bd17655bb00f2b3f42c3950ac69
уже упоминавшегося ботнета Dimnie.Дойдя до нее в восходящем движении, мы не сможем продвинуться дальше с помощью common change, поскольку на выходе больше одной обычной монеты. Глядя на транзакцию, мы не можем утверждать, сколько монет на выходе принадлежат той же персоне, что и монета на входе — обе, какая-то одна или вообще ни одной. Применение эвристики known address позволяет продвинуться дальше за счет того, что адрес
MwMdTb8WQvoRW9jEW5dHn9SkkCJTRn31wQ
был задействован во встреченной ранее в восходящем движении CC-транзакции cf7ac8986f9855246c6cf26df9a24aa5645cb9258bf787e034a33e75101ae1fc
, создавшей домен d/sectools
.Для полноты описания приведем псевдокод эвристики known address:
def known_address(tx):
result = { "guiding_outs": [], "guiding_ins": [] }
for output in tx.get_outs():
if output.address in known_addresses:
result["guiding_outs"].append(output)
for input in tx.get_ins():
if input.address in known_addresses:
result["guiding_ins"].append(input)
return result
Итак, теперь у нас есть и общий алгоритм обхода, и эвристики, необходимые для движения по блокчейну, так что мы можем собрать их вместе, чтобы добыть из Namecoin немного IOC.
Поехали!
Пройдем по транзакциям RTM восходящим и нисходящим движением, начав с
37d40bc2f3ca7415908dc9e276593b50d3120158cd540cb088246f2e2cf88b16
. В ходе продвижения по блокчейну будем собирать не только IOC, но и сами транзакции, удовлетворяющие эвристикам. Потоки монет между транзакциями мы визуализируем с помощью диаграммы Sankey. Полная диаграмма слишком велика для отображения в формате этого документа, поэтому я приведу здесь только ее часть, необходимую для дальнейшего рассказа.
Серым выделен поток обычных монет. Остальные цвета соответствуют потокам специальных монет. Для каждого имени выбран отдельный цвет. Белые вехи соответствуют транзакциям, которые удовлетворяют условиям эвристик. Ярко-красные вехи в правой части — UTXO.
Элемент диаграммы, на который я хотел бы обратить внимание, выделен голубой вехой. Это повисший вход — монета, которая возникла на входе транзакции, которую алгоритм прошел на восходящем движении, но транзакция, создавшая эту монету, ему не встретилась.
Повисшие входы являются признаками того, что в исследуемой структуре есть боковые ветви, не связанные с основным стволом, по которому движется алгоритм. В показанном случае это еще один независимый счет. Он, как можно увидеть на диаграмме, начинает использоваться для оплаты изменений в уже известных нам доменах. Из этого факта можно сделать вывод, что этот счет также контролируется исследуемой персоной. Для получения IOC, связанных с операциями по этому счету до момента его появления на диаграмме, мы запустим отдельное нисходящее движение, начинающееся в транзакции с повисшим входом.
Аналогичным образом при нисходящем движении могут возникать повисшие выходы. Для каждого из них мы будем запускать отдельное восходящее движение, начинающееся из соответствующей транзакции.
Помимо транзакций группы, управляющей ботнетом RTM, нами также были исследованы транзакции групп, контролирующих ботнеты Shifu, Dimnie и GandCrab. В результате были найдены 164 домена, зарегистрированных в интересах этих групп, и 277 IP-адресов, связанных с этими именами. На момент написания этой статьи из собранных UTXO, принадлежащих этим группам, действующими оставались 39 монет.
Списки IOC, а также адреса Namecoin, на которых остались неизрасходованные монеты групп, приведены в приложении A.
Заключение
Испытания реальной жизнью становятся вызовом практически для любой технологии. К середине 2000-х годов Wikipedia стала настолько популярным доверенным источником информации, что с помощью изменения текстов статей стало возможно управлять общественным мнением, раскручиваться, зарабатывать. Этот период в истории сервиса знаменит грандиозными по своим масштабам войнами правок — агрессивным использованием механизма исправления статей и отката правок несколькими противоборствующими сторонами с целью победить в споре о содержании статьи. Страницы Wikipedia превратились в международную ярмарку тщеславия, где каждому хотелось сказать в буквальном смысле последнее слово.
С войной правок, с одной стороны, начали бороться, установив специальные правила, которые позволяют в случае возникновения спора временно исключить возможность редактировать статью — до тех пор, пока спорщики в разделе «Обсуждение» не отыщут компромиссную формулировку. С другой стороны, война правок заставила Wikipedia запустить динамический механизм управления ресурсами администраторов, позволивший оперативно привлекать их для решения конфликтов на наиболее горячих участках. Более того, энциклопедия воспользовалась тем общественным вниманием, которое обратили на нее столкновения вокруг отдельных статей, чтобы привлечь к редактированию этих статей больше участников и добиться наиболее корректного и полного освещения той или иной темы.
Сможет ли Namecoin, подобно Wikipedia, повзрослеть и справиться со своим вызовом? Поживем — увидим.
P. S. Таблицы с индикаторами компрометации доступны на GitHub.
Автор: Алексей Гончаров, PT Expert Security Center