веб-сокет и сканер

Python рептилия WebSocket

Оригинал извеб-сокет и сканер

задний план

Целью написания краулера должно быть получение данных или имитация определенной операции. Если он использует протокол http(s) для передачи данных, то мы моделируем протокол http для отправки данных Если он использует протокол websocket для передачи данных, Затем мы считаем само собой разумеющимся, что имитируем веб-сокет для отправки данных ~

Во-первых, нам нужно понять, что такое websocket

Введение в веб-сокеты

WebSocket — это протокол для полнодуплексной связи по одному TCP-соединению. Протокол связи WebSocket был установлен IETF в качестве стандарта RFC 6455 в 2011 году и дополнен RFC7936. WebSocket API также является стандартом W3C.

WebSocket упрощает обмен данными между клиентом и сервером, позволяя серверу активно передавать данные клиенту. В API WebSocket браузеру и серверу нужно выполнить только одно рукопожатие, и между ними может быть создано постоянное соединение, и может выполняться двусторонняя передача данных.

Выше приведено введение Википедии. Проще говоря, websocket, как и http, — это сетевой протокол передачи

Какие адреса лучше протокола http?

  • Меньше затрат на контроль. Заголовки пакетов, используемые для управления протоколом, относительно малы при обмене данными между сервером и клиентом после создания соединения. Без расширений этот заголовок имеет размер всего от 2 до 10 байт (в зависимости от длины пакета) для содержимого «сервер-клиент»; для содержимого «клиент-сервер» этот заголовок требует дополнительной 4-байтовой маски. Эти накладные расходы значительно снижены по сравнению с HTTP-запросом, каждый раз содержащим полный заголовок.
  • Более высокая производительность в реальном времени. Поскольку протокол является полнодуплексным, сервер может активно отправлять данные клиенту в любое время. По сравнению с HTTP-запросами, которые должны ждать, пока клиент инициирует запрос для ответа сервера, задержка значительно меньше; даже по сравнению с длительным опросом, таким как Comet, он может доставлять данные больше раз за короткий период времени.
  • Оставайся на связи. В отличие от HTTP, Websocket необходимо сначала создать соединение, что делает его протоколом с отслеживанием состояния, а затем некоторая информация о состоянии может быть опущена во время связи. И HTTP-запросам может потребоваться нести информацию о состоянии (например, аутентификацию и т. д.) в каждом запросе.
  • Лучшая поддержка двоичного кода. Websocket определяет бинарные фреймы, которые упрощают обработку бинарного контента, чем HTTP.
  • Расширения могут поддерживаться. Websocket определяет расширения, и пользователи могут расширять протокол и реализовывать некоторые пользовательские подпротоколы. Например, некоторые браузеры поддерживают сжатие и т. д.
  • лучшее сжатие. По сравнению со сжатием HTTP, при надлежащей поддержке расширений Websocket может продолжать использовать контекст предыдущего контента и может значительно улучшить степень сжатия при передаче аналогичных данных.

Сценарии применения вебсокета

  • Шквал платформы прямой трансляции
  • Живой чат
  • и т.д

протокол веб-сокета

WebSocket — это независимый протокол, построенный поверх TCP.

Рукопожатия Websocket через код состояния 101 протокола HTTP/1.1.

Чтобы создать соединение Websocket, через браузер делается запрос, и сервер отвечает, процесс, обычно называемый «рукопожатием».

Так как же рукопожатие протокола веб-сокета?

рукопожатие через веб-сокет

Ниже приведен процесс рукопожатия через веб-сокет.запрос клиента

GET / HTTP/1.1
Upgrade: websocket
Connection: Upgrade
Host: example.com
Origin: http://example.com
Sec-WebSocket-Key: sN9cRrP/n9NdMgdcy2VJFQ==
Sec-WebSocket-Version: 13

ответ сервера

HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: fFBooB7FAkLlXgRSz0BT3v4hq5s=
Sec-WebSocket-Location: ws://example.com/

В отличие от поля http

  • Соединение должно быть установлено на «Обновить», что указывает на то, что клиент хочет обновить соединение.
  • В поле Upgrade должно быть указано значение Websocket, что указывает на то, что вы хотите перейти на протокол Websocket.
  • Sec-WebSocket-Key — это случайная строка, и сервер будет использовать эти данные для создания дайджеста сообщения SHA-1. Добавьте специальную строку «258EAFA5-E914-47DA-95CA-C5AB0DC85B11» в «Sec-WebSocket-Key», затем вычислите дайджест SHA-1, затем выполните кодирование BASE-64 и используйте результат как «Sec-WebSocket-Accept». " " значение заголовка, возвращенное клиенту. Делая это, вы можете попытаться предотвратить ошибочное принятие обычных HTTP-запросов за протокол Websocket.
  • Sec-WebSocket-Version указывает поддерживаемую версию Websocket. Версия, требуемая RFC6455, — 13, и все предыдущие черновые версии должны быть объявлены устаревшими.
  • Поле Origin является необязательным и обычно используется для указания страницы, на которой это соединение Websocket инициируется в браузере, аналогично Referer. Однако, в отличие от Referer, Origin включает только протокол и имя хоста.
  • Некоторые другие поля, определенные в протоколе HTTP, такие как Cookie, также могут использоваться в Websocket.

Видно, что в http-протокол добавлено лишь несколько жестких правил: user-agent и cookie-файлы http-протокола могут использоваться в процессе рукопожатия websocket.

Меры предосторожности при захвате пакетов: Поскольку веб-сокет имеет только одно рукопожатие, после успешного рукопожатия обе стороны могут отправлять сообщения.Если вы не найдете данные, которые хотите захватить после открытия веб-страницы, вам необходимо обновить веб-страницу и пусть он снова пожмет руку.

события веб-сокета

on_open

Указывает только что подключенный

onmessage

Укажите, что делать при получении сообщения

send

Указывает на отправку сообщения на сервер

on_close

Указывает закрыть соединение

Итак, что нам дает это знание? При поиске js его будет легко найти, эти ключевые слова в основном фиксированы Вы можете напрямую искать по всему миру, и тогда легко найти отправленный код js

То же самое верно и при имитации отправки.

фактический случай

Куча вещей, связанных с протоколом веб-сокетов, была представлена ​​ранее, и, по оценкам, у многих людей закружилась голова. Не беда, сначала посмотрите на пример, а потом вернитесь к вышеприведенному, если есть проблема

Fiddle можно использовать для захвата пакетов, а также можно использовать Chrome.

Сначала воспользуемся хромом

Веб-сайт, который нужно поймать на этот разизбирательный участокВы можете сначала проголосовать случайным образом, взять сумку и посмотреть Узнаю, как не нашел, как подал данные...

Выберите ws, затем обновите веб-страницу, а затем нажмите, чтобы проголосовать, вы найдете запрос

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

Адрес запросаws://v5.10brandchina.com:8008/Кстати, я иногда вижу здесьwss://v5.10brandchina.com:8008/Итак, в чем разница между ними, просто скажем, разница между протоколами http и https, например...

Взгляните на содержание взаимодействия (нажмите «Кадры») Видно, что сообщений уже четыре, но содержимое сообщения бинарное, что нельзя просмотреть в хроме... Тогда давайте попробуем это со скрипкой

Захват и анализ пакетов

открытая скрипка,обновите страницуЕсли вы не обновите его, вы его не увидите, а затем просто проголосуете.

Как найти запрос, это очень просто, достаточно посмотреть на код состояния 101, а затем дважды нажать на строку

Тогда мы еще видим здесь четыре сообщения, нажимаем на первое, а затем используемTextViewПокажи, ты видишь, что сообщения вот эти зачем использоватьTextViewШерстяная ткань? На самом деле, это пробуется один за другим. Если вы обнаружите, что перепробовали все, а символы все еще искажены, это должно быть связано с тем, что он использовал другие методы сжатия или шифрования. Вам нужно проверить js, чтобы увидеть, как он зашифровал Это.

Данные на этом сайте не зашифрованы. Стрелка вверх — это то, что мы отправляем на сервер, а стрелка вниз — это то, что сервер возвращает (данные ниже, с черной точкой впереди? — это то, что мы отправили)

  • {"action":"auth","val":5}

{"action":"auth","msg":"eval(\"\\115\\141\\164\\150\\56\\163\\151\\156\\50\\61\\65\\61\\67\\67\\66\\62\\63\\61\\63\\51\")"}

  • {"action":"auth","val":-0.3241458910493796}

{"action":"wait","msg":95420}

  • {"action":"vote","val":"{\"itemid\":126067,\"catid\":41867,\"captcha\":\"%u7EC7%u65E7%u5F88%u9C7C\",\"auth\":5,\"rnd\":\"4186712606754595\"}"}

{"action":"vote","msg":"ok,231812,2018-02-04 22:32:55"}

можно увидеть Сначала мы отправляем{"action":"auth","val":5}Затем сервер возвращает нам строку информации, Затем мы вычисляем значение на основе того, что возвращает сервер, т.е.{"action":"auth","val":-0.3241458910493796}и отправить на сервер. сервер возвращает{"action":"wait","msg":95420}, что означает, что проверка пройдена Затем мы голосуем и отправляем некоторую информацию о голосовании в сервис Сервер сообщает нам, что голосование прошло успешно.

Выше описан весь процесс общения.

Итак, если мы хотим имитировать отправку, какую информацию нам нужно знать?

  1. {"action":"auth","val":5}внутриval:5, это 5 исправлено? Если нет, то как он был создан
  2. Что возвращает сервер и как его разобрать
  3. Как сгенерировать новый val на основе того, что возвращает сервер
  4. Отправить информацию о голосовании внутри{"action":"vote","val":"{\"itemid\":126067,\"catid\":41867,\"captcha\":\"%u7EC7%u65E7%u5F88%u9C7C\",\"auth\":5,\"rnd\":\"4186712606754595\"}"}Как сгенерировать itemid, catid, capthc, auth, rnd

найти параметры

Или используйте хром, напрямую используйтеctrl + shift +f, а затем введите websocket (или on_open, on_message и т. д. для поиска упомянутых выше событий)

удачи, вступайwebsocketЯ нашел js напрямую, но путаницы нет

Сначала найдите, что адрес веб-сокета изменен в соответствии с catId.Если catId делится на 2, адрес равен xxx, иначе это xxx. Итак, что такое catId, отладка обнаружила, что это идентификатор в URL-адресе, наш текущий URL-адресhttp://www.10brandchina.com/vote/startin.php?id=41867Тогда catId41867

Затем его увидел и onmessage, что, вероятно, означает, что после получения информации используйте парсинг json, если действие auth, вызовите метод sendData, а если действие голосование, используйте метод voice_resule.

Когда вы увидите метод onopen, вызовите sendData и отправьте('auth',authType), Это данные, которые мы отправили в первый раз?{"action":"auth","val":5}, это то же самое

Я не буду говорить о методе close, мы все равно не можем его использовать.

Посмотрите еще раз на метод sendData,

Вот как это реализовано в питоне

Посмотрите на метод voice_result, который, вероятно, используется для оценки результатов голосования.

Мы нашли все методы, далее проходим по параметрам, которые искали ранее.

  1. {"action":"auth","val":5}внутриval:5, это 5 исправлено? Если нет, то как он был создан

Это 5 и есть authType в onopen.Что касается того, исправлен ли authType, можно узнать поиском.

  1. Что возвращает сервер и как его разобрать
  2. Как сгенерировать новый val на основе того, что возвращает сервер

Вы можете узнать данные json, возвращаемые методом onmessage, просто проанализируйте файл json. Вал внутри выполняетсяeval(val)принадлежит Таким образом, вы также можете выполнить это напрямую или реализовать на python.

  1. Отправить информацию о голосовании внутри{"action":"vote","val":"{\"itemid\":126067,\"catid\":41867,\"captcha\":\"%u7EC7%u65E7%u5F88%u9C7C\",\"auth\":5,\"rnd\":\"4186712606754595\"}"}Как сгенерировать itemid, catid, capthc, auth, rnd

itemid — это идентификатор компании, за которую вы проголосовали, catid уже говорил ранее, captcha — это код подтверждения, auth такой же, как authtype выше rnd был найден путем поиска js.

Давайте посмотрим, как генерируется проверочный код.

Проверьте правильность кода подтверждения

У нас есть все, что нужно, просто программно смоделируйте отправку.

аналоговый посыл

Используемый пакетwebsocket

Официальная демоверсия

import websocket
try:
    import thread
except ImportError:
    import _thread as thread
import time

def on_message(ws, message):
    print(message)

def on_error(ws, error):
    print(error)

def on_close(ws):
    print("### closed ###")

def on_open(ws):
    def run(*args):
        for i in range(3):
            time.sleep(1)
            ws.send("Hello %d" % i)
        time.sleep(1)
        ws.close()
        print("thread terminating...")
    thread.start_new_thread(run, ())


if __name__ == "__main__":
    websocket.enableTrace(True)
    ws = websocket.WebSocketApp("ws://echo.websocket.org/",
                              on_message = on_message,
                              on_error = on_error,
                              on_close = on_close)
    ws.on_open = on_open
    ws.run_forever()

Видно, что он очень прост в использовании.onopen,onmessage,send

Поэтому нам просто нужно использовать информацию, которую мы получили выше, для имитации отправки.

Поскольку это сайт для голосования, код не предоставляется... Если у вас есть какие-либо вопросы, оставьте сообщение~