Отслеживаем транзакции Bitcoin при помощи Python, BlockExplorer и Webhose.io

Эта статья была впервые опубликована в блоге AutomatingOSINT.com.

В последнее время появляется все больше исследований, посвященных работе сети Tor, а также транзакциям Bitcoin. Система Bitcoin была создана таким образом, чтобы сделки в ней проводились в условиях полной анонимности, но существует множество других факторов, которые влияют на то, правильно ли обеспечивается защита личных данных владельца кошелька Bitcoin. При помощи вторичных запросов по адресам Bitcoin чаще всего можно обнаружить взаимосвязь или следы, которые могут привести к интересной информации.

В этой статье мы с вами поговорим о том, как создать инструмент для поиска по определенному адресу Bitcoin, визуально представить связанные с ним входящие и исходящие операции и запустить повторный поиск в даркнете с использованием Webhose.io, чтобы найти скрытые сервисы, где упомянуты кошельки Bitcoin. Результаты нашей работы будут представлены в наглядном виде для того, чтобы их было удобно анализировать.

Итак, за дело!

Что нам понадобится

Если у вас уже есть Python, установите библиотеку запросов (pip install requests). Не знаете, как это сделать? Посмотрите на этой странице в разделе Setup.

Заходим на сайт Webhose.io и запрашиваем ключ API.

Кроме того, нам понадобится несколько библиотек Python. Делаем следующее:

Итак, переходим к самому коду.

Пишем код

Создаем в Python новый скрипт, называем его bitcoindarkweb.py (полностью исходный код можно загрузить отсюда) и вбиваем следующий отрезок кода:

Ничего особо сложного тут нет, но давайте все же обсудим несколько наиболее важных моментов:

  • Строка 5: это ключ доступа с Webhose.io, который понадобится нам для того, чтобы запустить поиск в даркнете.
  • Строка 7: это черный список скрытых сервисов Tor, которые будут исключены из поиска и из графика. Нужен он потому, что существует множество скрытых сервисов Bitcoin, на которых указана масса адресов, и среди результатов поиска они нам ни к чему. Так что лучше добавьте этот список в свой код.

Теперь укажем несколько переменных и настроим способы разбора аргумента командной строки. Продолжаем печатать код:

  • Строка 29: функции get_all_transactions в качестве переменной задаем адрес Bitcoin. Эта функция нужна для того, чтобы загрузить все транзакции по данному адресу – они пригодятся нам позже.
  • Строка 35: составляем URL BlockExplorer в формате, который требуется для того, чтобы загружать порции данных о транзакциях с сервера.
  • Строки 37-47: направляем запрос к BlockExplorer.com (37) и разбираем результат JSON (40). Если разбор провести не удалось, выводим соответствующее сообщение (42) и возвращаем пустой список транзакций (43). Если провести разбор удалось, но транзакции по проверяемому адресу отсутствуют (45), выводим соответствующее сообщение (46) и возвращаем пустой список (47).
  • Строка 49: берем получившийся список транзакций и добавляем их в основной список транзакций.
  • Строки 51-62: создаем цикл, чтобы выводить транзакции по 50 штук за один раз (51), затем постепенно увеличиваем переменные from (от) (53) и to (до) (54), чтобы «просмотреть» все транзакции. Отправляем эти переменные вместе с API BlockExplorer (56) и добавляем результаты в основной список транзакций (62), после чего возвращаемся к началу цикла.
  • Строка 66: после того как все транзакции выведены, возвращаем список транзакций.

Итак, у нас есть алгоритм, при помощи которого можно получить информацию обо всех входящих и исходящих операциях по определенному адресу Bitcoin. Отлично! Теперь пропишем функцию, которая проанализирует все транзакции Bitcoin и вычленит из них уникальные адреса. Это нужно для того, чтобы создать уникальный список адресов Bitcoin, которые мы потом зададим в поиск на Webhose.io. Вбиваем следующий код:

  • Строка 72: в качестве аргумента присваиваем функции список транзакций, которые нам удалось извлечь.
  • Строки 79-80: проверяем адрес отправителя, и если это новый адрес, который не встречался нам раньше, добавляем его в список bitcoin_addresses (80).
  • Строки 83-91: анализируем ту часть транзакции, которая касается получающей стороны (83), и проходим по всем адресам, которые удалось найти (87). По очереди проверяем каждый адрес (89), и если он нам еще не встречался, добавляем его в список bitcoin_addresses (91).
  • Строки 93-95: после того как все уникальные адреса, связанные с анализируемым адресом Bitcoin, были извлечены, возвращаем список, чтобы потом использовать его для запросов к Webhose.io.

Ну что же, теперь у нас есть список всех транзакций, связанных с изучаемым адресом Bitcoin, кроме того, мы нашли все уникальные адреса, которые получали биткойны от нашего «подозреваемого» или направляли ему платежи в этой цифровой валюте. Пришло время включить в программу поиск по сайту Webhose.io, что поможет нам найти дополнительные улики и, возможно, обнаружить скрытые сервисы, на которых упоминались извлеченные адреса. Добавляем следующий отрезок кода:

  • Строка 101: функции search_webhose в качестве аргумента присваиваем список адресов Bitcoin, по которым мы собираемся вести поиск.
  • Строки 106-115: проходим каждую позицию из списка адресов Bitcoin (106) и добавляем ее в поисковый URL Webhose (111), после чего отправляем запрос (113) и разбираем полученные в ответ данные JSON (115).
  • Строки 118-128: прописываем цикл, который позволит загрузить все результаты (118), а затем проходим по очереди каждый результат поиска (121). Проверяем, есть ли текущий адрес Bitcoin в словаре bitcoin_to_hidden_services (123), и если его там нет, добавляем его в словарь и создаем для него пустой список (124). Проводим повторную проверку, чтобы посмотреть, нет ли текущего скрытого сервиса в списке, связанном с текущим адресом Bitcoin (126), и если его там нет, то добавляем его (128). Вся эта канитель нужна для того, чтобы создать для каждого адреса Bitcoin список уникальных скрытых сервисов.
  • Строки 130-131: если количество результатов меньше 10 (130), выходим из цикла (131) и возвращаемся к началу функции, чтобы начать проверку по следующему адресу Bitcoin из списка.
  • Строки 135-142: продолжаем извлекать дополнительную информацию с сайта Webhose – для этого мы используем первоначальный запрос, а потом добавляем в черный список сайты, которые хотим исключить из результатов поиска. За счет этого также сократится общее количество запросов API, нужное для того, чтобы завершить поиск и получить всю интересующую нас информацию. Для этого проходим обнаруженные скрытые сервисы (137) и указываем, что результаты по ним выводить не нужно (138). Затем проходим черный список, который у нас был в начале скрипта (141), и добавляем в него новые скрытые сервисы (142).
  • Строки 144-148: отправляем новый запрос (144), разбираем полученный JSON (148), возвращаемся к началу цикла (строка 118) и продолжаем анализировать другие скрытые сервисы.

Уф, какой большой получился отрезок кода! Наконец-то мы с ним разобрались. Итак, наша программа уже может найти все транзакции Bitcoin, все уникальные адреса Bitcoin, связанные с этими транзакциями, а также все упоминания этих адресов в даркнете, которые сохранились на Webhose.io. Осталось наглядно представить результаты нашего расследования – то есть объединить все эти данные в красивую картинку. Добавим ту часть кода, которая отвечает за визуализацию:

  • Строка 160: функции build_graph в качестве аргумента присваиваем анализируемый адрес Bitcoin, список транзакций Bitcoin и словарь скрытых сервисов.
  • Строка 162: создаем графический объект NetworkX. Обратите внимание на то, что это будет DiGraph, т. е. ориентированный граф, на котором отображены направления транзакций Bitcoin (входящие и исходящие).
  • Строки 165-173: проходим список транзакций (165) и извлекаем адрес отправителя (168). Если адрес отправителя совпадает с анализируемым адресом Bitcoin (170), добавляем в граф узел со специальным параметром type, который равняется Target Bitcoin Wallet («Анализируемый кошелек Bitcoin») (171). В противном случае значение параметра равняется Bitcoin Address («Адрес Bitcoin»). Мы используем два разных параметра, чтобы на графе в Gephi окрасить соответствующие узлы в разные цвета.
  • Строки 177-187: теперь проходим список получателей (177), а затем – каждый адрес, упомянутый в транзакции (180). Проводим аналогичную проверку для анализируемого кошелька Bitcoin (182), используя те же параметры. Наконец, проводим линию (edge) между отправителем и получателем, чтобы продемонстрировать связь между ними. Обратите внимание на то, что в функции add_edge первым указан отправитель средств – это нужно для того, чтобы стрелка на графе смотрела в направлении получателя платежа.
  • Строка 189-195: пришло время добавить в график данные о скрытых сервисах. Для этого проходим наш словарь (189), а затем – каждый скрытый сервис, хранящийся в словаре под определенным ключом (191). Если скрытый сервис не входит в черный список (193), добавляем в граф новый узел с параметром type Hidden Service («Скрытый сервис») (194), а затем проводим линию (edge) между соответствующим адресом Bitcoin и скрытым сервисом (195).
  • Строка 199: последнее, что нам нужно сделать, – вывести граф в файл GEXF, который можно просмотреть в Gephi.

Чудненько! Последний этап – это связать все функции воедино, а потом можно будет устроить тестовый прогон. Мы почти закончили, осталось совсем немного:

  • Строка 207: вызываем функцию get_all_transactions, чтобы извлечь список транзакций для анализируемого кошелька Bitcoin.
  • Строки 209-212: если у нас есть действительный список транзакций (209), извлекаем из него все уникальные адреса Bitcoin (212).
  • Строка 216: задействуем Webhose.io, чтобы найти все скрытые сервисы, связанные с обнаруженными адресами Bitcoin.
  • Строка 219: создаем графический объект, который наглядно представит результаты нашей работы.

Отлично! Если у вас есть ключ доступа с Webhose.io и адрес Bitcoin, который вы хотите проанализировать, то можно опробовать программу в действии.

Погнали!

Наконец пришла пора опробовать нашу программу. Я использовал следующие данные. Получившийся в итоге файл GEXF можно загрузить по этой ссылке.

[*] Retrieving all transactions from the blockchain for 19m9yEChBSPuzCzEMmg1dNbPvdLdWA59rS (Извлечение всех транзакций из блокчейна для адреса 19m9yEChBSPuzCzEMmg1dNbPvdLdWA59rS)
[*] Retrieved 594 bitcoin transactions (Извлечено 594 транзакции).
[*] Identified 1998 unique bitcoin addresses (Выявлено 1998 уникальных адресов Bitcoin).
[*] Searching 1 of 1998 bitcoin addresses (Поиск по 1 из 1998 адресов Bitcoin).
[*] Searching 2 of 1998 bitcoin addresses (Поиск по 2 из 1998 адресов Bitcoin).
[*] Searching 3 of 1998 bitcoin addresses (Поиск по 3 из 1998 адресов Bitcoin).
[*] Discovered 2 hidden services connected to 19m9yEChBSPuzCzEMmg1dNbPvdLdWA59rS (Обнаружено 2 скрытых сервиса, связанных с адресом 19m9yEChBSPuzCzEMmg1dNbPvdLdWA59rS)
[*] Searching 4 of 1998 bitcoin addresses (Поиск по 4 из 1998 адресов Bitcoin).

[*] Searching 1997 of 1998 bitcoin addresses (Поиск по 1997 из 1998 адресов Bitcoin).
[*] Searching 1998 of 1998 bitcoin addresses (Поиск по 1998 из 1998 адресов Bitcoin).
[*] Done! Open the graph file and happy hunting! (Готово! Файл с графом можно открыть. Успехов!)

Теперь можете открыть граф в Gephi (о том, как работать с Gephi, я подробно написал вот тут) и изучить транзакции и скрытые сервисы, которые нашла наша замечательная программка. Хотите собрать еще больше данных? Добавьте в скрипт поиск по обычным сайтам при помощи системы Searx. Подробнее о том, как это сделать, читайте здесь.