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

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

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

Mr. Robot TV Show

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

Предупреждение. Поставленную задачу можно было решить более лёгкими путями. В данной теме приведено одно из решений именно на языке c++.

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

Сервис 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 <boost/asio.hpp>
#include <boost/asio/ssl.hpp>
#include <boost/bind.hpp>
// ---------------------------

// ---------- 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<ip::tcp::socket> 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

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

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

Подробнее
Реклама

Комментарии 21

    +1
    Может быть, кто-то подскажет обратный сервис (в какой-то мере), на который наоборот можно всякий спам скидывать и при всяких регистрациях вводить?
      0
      SMS-REG и подобные
        0
        ищите по словам «виртуальный номер телефона для приема смс»
        их сотни бесплатных и не очень
        +1
        request_ << «POS /v2/sms/messages HTTP/1.1\r\n»;

        POS?
          0
          Ух, ошибочка вышла. Подправим. Спасибо
            +1
            А оно даже так работает или в рабочем коде другой запрос был?
              0
              В рабочем коде был POST. Так оно бы не работало.
          +2

          В названии ошибка. Какая анонимность, если надо зарегистрироваться и закинуть деньги на счёт?

            0
            И там есть дальше предупреждение. Узнать кто на самом деле стоит за отправкой можно будет только сделав запрос к сайту. А кому понравится, когда к вам лезут за выяснениями каких-либо сообщений, запрос будет отклонён, до официального решения высказать личность индивидума. Так что я вижу тут некую анонимность. Но как бы там ни было, я пересмотрю свои взгляды на тему и сделаю выводы
            +7
            Лабораторная работа да?

            — json формируется руками. Что простите? Любая ошибка и добро пожаловать в отладку. Я уже не говорю про отсутствие экранирования для переменных. Что программа сделает если пользователь введет номер с кавычкой?
            — Можно подробностей как работает verify_certificate? Насколько я вижу он всегда возвращает одно значение которое ему передали, а сам сертификат вроде и не проверяет даже. Впрочем допускаю что там какая-то магия внутри происходит, поэтому и спрашиваю.
            — socket_.read_some может вернуть не все данные а только часть — tcp же. Чтобы получить все данные нужно читать до упора ( до закрытия коннекта в вашем случае ).

            — и наконец последняя, самая серьезная придирка.
            ЗАЧЕМ?
            Зачем нужно писать кривую программу на си++ когда можно было выполнить
            curl адрес -d '{тут-ваша-мега-жсон}'
              0
              Зачем нужно писать кривую программу на си++ когда можно было выполнить curl…
              Судя по использованию boost::asio, можно предположить, что планируется работа под большой нагрузкой. Но это лишь предположение — в том виде, как написано, действительно похоже на эксперимент или лабораторную работу.
                0
                boost.asio имел бы смысл на сервере, а для клиента с трудом представляю как его нужно нагружать чтобы это имело смысл. Ну и уж тогда начать с переиспользования коннектов, асинхронности и тд
                  0
                  Полностью согласен, но по приведенным фрагментам кода ясно же видно, что это всего лишь попытка попробовать. Конечную свою цель автор, увы, не посчитал нужным озвучить.
                0
                Спасибо за критичный отзыв. Всё действительно так. Эту задачу можно было решить куда легче. Возможно даже я переосмыслю то, что в попыхах было написано и под корень исправлю. Но пусть пока это будет одним из возможных вариантов решения задачи. Главное думаю тут, не сама программа, а смысл того, как можно было отправить СМС без напряга. И ещё, эта программа была частью большого проекта, так что от туда и осталось решение создания соединения. И я хотел ещё второй темой в данном разделе показать применение именно на C++, так что я тут особо проблем не вижу (кроме корявого кода). Будем исправляться
                0
                (ошибся веткой )
                  0
                  Почему не использовать curl или что-то подобное? Обычно http-запрос можно сформировать одной командой в консоли. К тому же, у Bytehand есть интерфейс для отправки сообщений.
                    0
                    Да, всё верно. Решение было бы куда легче. Но а вдруг приложение обрастёт интерфейсом, сложными функциями и т.п. маловероятно, но ведь вполне возможно (именно такое приложение у меня получилось в итоге), тогда было бы кстати контролировать весь процесс. И второй темой в разделе у меня было показать как именно это сделать на C++. Спасибо за комментарий. Есть о чём подумать.
                  • НЛО прилетело и опубликовало эту надпись здесь
                      0
                      Сервер сообщает об успешной отправке, но сообщение не дойдёт до адресата, т.к. сообщение будет отклонено внутри сервиса.
                      +1
                      А зачем вам было это нужно? ;)
                        +1

                        Проверять сертификат надо согласно rfc2818, и использовать tls. А ssl::context::verify_none как бы намекает что у вас чего то не хватает.

                        Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

                        Самое читаемое