Отправляем анонимное СМС из Консоли на нужный номер используя сервис bytehand и C++

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

Во многих фильмах есть момент, когда хакеру, взламывающего человека, нужно отправить сообщение на его номер, чтобы его отвлечь или напугать и в таких ситуациях самое важное, чтобы, когда человек позвонит на номер с которого пришло СМС у вас не загорелся экран смартфона и не заиграла музыка. Упс… Неловкая ситуация. В этой теме мы напишем программу на C++, которая позволит отправить СМС не используя вашего номера, сим-карты и души.

Mr. Robot TV Show


Слово «Анонимность» подразумевает собой то, что кто отправил сообщение на самом деле не узнается, но не всё так хорошо. При разбирательстве этот факт выяснится, так что при особо тяжких приколах я не приду навестить вас на испытательных работах.

Приступим к делу.

Сервис bytehand — это решение для бизнеса, позволяющее делать как массовые рассылки сообщений, так и одиночные. Главная особенность сервиса и почему я его выбрал является доступное со всех платформ API, которое представляет собой HTTP Запрос-Ответ с очень простой системой авторизации.

Вот что нам понадобится:

  • Аккаунт на bytehand
  • 100 рублей на счету (А что вы хотели, СМС не бесплатные)
  • Консольная программа c++
  • Собранные библиотеки Boost.Asio и OpenSSL для https соединения
  • Созданный через OpenSSL сертификат для защищённого обмена данными с сервисом bytehand.


Первым делом регистрируемся на сервисе bytehand. Регистрация представляет собой введённый e-mail и пароль. Этого уже достаточно. После этого создаётся ваш аккаунт и при пополнении счёта (минимум 100р) вы уже можете отправлять сообщения с заголовком SMS-INFO. У большинства операторов эта запись заменяется номером отправления. При желании можно придумать свой собственный текстовый псевдоним.

Далее лезем в API ресурса. И видим, что что бы отправить СМС нужно всего лишь сформировать следующий пакет данных:

POST /v2/sms/messages HTTP/1.1
Host: api.bytehand.com
Connection: close
Content-Length: *
Content-Type: application/json;charset=UTF-8
X-Service-Key: ab4db0b982dcd0ba63e44191e5d71ef8

{
  "sender": "MyShop",
  "receiver": "+79167654321",
  "text": "Today only! 20% off for all goods!!"
}


Обращу ваше внимание на то, что X-Service-Key в заголовке http это и есть вся авторизация. Этот ключ можно посмотреть в настройках на сайте в разделе «безопасность».

Думаю здесь всё понятно и можно приступить к написанию консольной программы на c++

Первым делом представляю вашему вниманию фрагмент кода, который с помощью Boost.Asio устанавливает соединение с сайтом по https протоколу

// Подключение библиотек Boost
#include 
#include 
#include 
// ---------------------------

// ---------- Include OpenSSL Lib ----------
#pragma comment (lib, "libeay32.lib")
#pragma comment (lib, "ssleay32.lib")
// -----------------------------------------

using namespace boost::asio;

// Функция верификации сертификата
bool verify_certificate(bool preverified, boost::asio::ssl::verify_context& ctx)
{
        X509* cert = X509_STORE_CTX_get_current_cert(ctx.native_handle());

        return preverified;
}

int main()
{
        io_service service; // Класс, реализующий сокеты подключения

        /*------------------------------------------------------------
        -          Устанавливаем соединение с сервером             -
        ------------------------------------------------------------*/
        ip::tcp::resolver resolver(service);
        ip::tcp::resolver::query query("api.bytehand.com", "https");
        ip::tcp::resolver::iterator iterator = resolver.resolve(query);

        ssl::context context(boost::asio::ssl::context::sslv23);
        context.load_verify_file("dh2048.pem");

        ssl::stream socket_(service, context);

        socket_.set_verify_mode(ssl::context::verify_none);
        socket_.set_verify_callback(boost::bind(verify_certificate, _1, _2));

        connect(socket_.lowest_layer(), iterator);

        socket_.handshake(boost::asio::ssl::stream_base::client);

        //Здесь мы можем передавать данные серверу через функцию  socket_.write_some()
}


В коде используется ссылка на файл сертификата dh2048.pem. Его вы замените своим.
Так же можно увидеть, что тут в качестве сервера используется доменное имя api.bytehand.com

Далее пример как формируется заголовок и тело http запроса для сервера.

int main()
{
        /* Тут то, что было в предыдущем коде создания https соединения*/

        // Эти переменные заменяются вводом текста с клавиатуры и проверку на ошибки
        // Здесь код упращён для его понимания
        string number     = "+79180000000";
        string signature  = "SMS-INFO";
        string text       = "Today only! 20% off for all goods!!";

        std::stringstream request_; // Хранит запрос к серверу
        char sockBuffer[8192];      // Временное хранилище ответа от сервера

        // Выносим тело в отдельную переменную, что бы посчитать длину для заголовка Content-Length
        string reqTmp = "{\"sender\": \"" + signature + "\",\"receiver\": \"" + number + "\",\"text\": \"" + text + "\"}\r\n";

        request_ << "POST /v2/sms/messages HTTP/1.1\r\n";
        request_ << "Host: api.bytehand.com\r\n";
        request_ << "Connection: close\r\n";
        request_ << "Content-Length: " << reqTmp.length() << "\r\n";
        request_ << "Content-Type: application/json;charset=UTF-8\r\n";
        request_ << "X-Service-Key: ab4db0b982dcd0ba63e44191e5d71ef8\r\n";
        request_ << "\r\n";
        request_ << reqTmp;
        
        // Отправляем пакет на сервер
        socket_.write_some(buffer(request_.str()));
        
        memset(sockBuffer, NULL, 8192);
        
        // Читаем ответ от сервера в буффер
        socket_.read_some(buffer(boost::asio::buffer(sockBuffer)));

        // Выводим ответ на экран
        cout << endl << endl << sockBuffer << endl;
}


Напоминаю, что поле X-Service-Key вы заменяете на ваш ключ.

После выполнения этого кода и если всё прошло как надо, сервер возвращает ответ:

Status Code: 200
Content-Type: application/json;charset=UTF-8
Content-Language: en
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Pragma: no-cache

{
  "result": "created",
  "count": 1
}


На этом моменте с вашего счёта списываются деньги за отправку сообщения. И сообщение идёт к адресату. Когда он его получит, то это будет номер компании или текстовый идентификатор и вряд ли человек поймёт от кого было это сообщение.

Вот что вышло у меня при написании этой программы:

MyProgram


Получилось коряво, но что есть. Всем удачи, возможно эта тема вам чем то помогла.

Это была моя вторая статья тут. Спасибо за прочтение. Удачи в разработке ваших приложений.

© Habrahabr.ru