• Курсы Академии Кодебай, стартующие в мае - июне, от команды The Codeby

    1. Цифровая криминалистика и реагирование на инциденты
    2. ОС Linux (DFIR) Старт: 16 мая
    3. Анализ фишинговых атак Старт: 16 мая Устройства для тестирования на проникновение Старт: 16 мая

    Скидки до 10%

    Полный список ближайших курсов ...

Статья Получаем информацию о системе с помощью Python. Часть #2

Как я уже писал в первой части статьи, информация — это такая штука, которой желали бы обладать многие. Ее никогда не бывает много. И не зря же есть высказывание одного, всем известного товарища, что информация правит миром. И это на самом деле так. В наш цифровой век умение собирать и анализировать разнообразную информацию цениться очень высоко. Но, это уже не совсем наша тема. По крайней мере пока. Это уже OSINT. А мы продолжим добывать информацию о системе с помощью Питона.

000.jpg

Давайте перейдем к сбору. Я озаботился тем, чтобы поискать способы получения более детальной информации о железе. И более удобным способом мне показался тот, в котором можно было использовать командную строку и команды, которые в ней выполняются, а точнее их вывод. Тем более, что командная строка, как на Windows, так и на Linux это очень мощный инструмент, который стал таким, наверное, в силу того что именно с него все и начиналось. И он, а точнее команды, которые в нем выполняются – это основа всех основ. А графический интерфейс подоспел уже позже.

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


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

Python:
import json
import subprocess

import psutil
from platform import uname

А теперь нужно создать функцию, которая и будет отвечать за сбор дополнительных данных. Я ее так и назвал: def win_dop_info(dict_info). И добавил win, чтобы было понятно, что данная функция будет использоваться только в Windows. Если вы читали первую статью, то там я упоминал о том, что не зря сделал определение операционной системы на старте программы. Оно сделано именно в этих целях, чтобы запускать в разных операционках разные функции.

Да, совсем забыл упомянуть. Тут еще понадобиться небольшая библиотека, а точнее ее часть, которая и будет отвечать за извлечение ключа активации: windows_tools.product_key. Устанавливается она командой:

pip install windows_tools.product_key

Вроде бы ничего необычного. И данная библиотека есть на PyPi. Но вот у меня PyCharm упорно не хотел ее видеть. Я все проклял. Уж так я его и эдак. И пока я не выбрал системный интерпретатор питона, библиотека не была доступна для использования. Тем не менее, ее нужно установить. Да, стоит упомянуть то, что на тестовой машине установка этой библиотеки прошла без сучка и задоринки и программа успешно отработала то, что ей надо. И я грешил на свою машину в первую очередь. Наверное, это мои, локальные глюки. Как говорить, доигрался. Ну да ладно.

Впоследствии я разобрался, что если устанавливать файлы с помощью pip, то они могут быть не доступны в том компиляторе, который вы используете в своем проекте. И в этом случае нужно использовать системный интерпретатор. Но, в этом случае могут стать недоступны библиотеки, которые вы устанавливали с помощью PyCharm и их придется переустанавливать. Решение тут одно. Для этой библиотеки доступна установка с помощью pip, а значит и все остальные модули желательно устанавливать тем же образом. И использовать после установки системный интерпретатор питона в своем проекте.

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

import windows_tools.product_key

И теперь приступаем к сбору информации. Есть такая утилита WMIC. При вызове справки по данной утилите пишется, что она устарела. Но, это не беда. Она работает. Да еще как.

screenshot1.png

Вот ее мы и будем использовать и запускать с помощью subprocess.

Начнем с информации о материнской плате. Я поковырялся в параметрах и пришел к выводу, опытным путем, что получать вывод из всех опций достаточно бесполезно, так как некоторые не особо понятны, да и порою просто выводят пустое значение. Определяем переменную, в которую помещаем значение «WMIC BASEBOARD GET Manufacturer /VALUE» и тут же делим его с помощью split(). Это нужно для того, чтобы поместить значения в subprocess. В теории, можно было бы разделить значения прямо в функции, но, это выглядит совсем уж не эстетично.

И после этого запускаем subprocess.check_output с нужной командой. Тут же и обрезаем вывод. Чтобы то, что мы получаем выглядело хорошо.

Python:
man_moth_com = 'WMIC BASEBOARD GET Manufacturer /VALUE'.split()
    manufacturer = str(subprocess.check_output(man_moth_com, shell=True)).split("\\n")[2].replace("\\r", "").\
        split("=")[1]

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

Python:
man_moth_com = 'WMIC BASEBOARD GET Manufacturer /VALUE'.split()
    manufacturer = str(subprocess.check_output(man_moth_com, shell=True)).split("\\n")[2].replace("\\r", "").\
        split("=")[1]

    prod_com = 'WMIC BASEBOARD GET Product /VALUE'.split()
    product = str(subprocess.check_output(prod_com, shell=True)).split("\\n")[2].split("\\r")[0].split("=")[1]

    # bios
    verb_com = 'WMIC BIOS GET Version /VALUE'.split()
    version_bios = str(subprocess.check_output(verb_com, shell=True)).split("\\n")[2].split("\\r")[0].split("=")[1]

    man_bios_com = 'WMIC BIOS GET Manufacturer /VALUE'.split()
    manufacturer_bios = str(subprocess.check_output(man_bios_com, shell=True)).\
        split("\\n")[2].split("\\r")[0].split("=")[1]

    sn_bios_com = 'WMIC BIOS GET SerialNumber /VALUE'.split()
    serial_num_bios = str(subprocess.check_output(sn_bios_com, shell=True)).split("\\n")[2].split("\\r")[0].split("=")[
        1]

    dv_bios_com = 'WMIC BIOS GET Description /VALUE'.split()
    date_version_bios = str(subprocess.check_output(dv_bios_com, shell=True)).\
        split("\\n")[2].split("\\r")[0].split("=")[1]

    smbios_com = 'WMIC BIOS GET SMBIOSBIOSVersion /VALUE'.split()
    smbios_ver = str(subprocess.check_output(smbios_com, shell=True)).split("\\n")[2].split("\\r")[0].split("=")[1]

    # boot configuration
    boot_dir_com = 'WMIC BOOTCONFIG GET BootDirectory /VALUE'.split()
    boot_directory = str(subprocess.check_output(boot_dir_com, shell=True)).split("\\n")[2].split("\\r")[0].split("=")[
        1]

    lastd_com = 'WMIC BOOTCONFIG GET LastDrive /VALUE'.split()
    last_drive = str(subprocess.check_output(lastd_com, shell=True)).split("\\n")[2].split("\\r")[0].split("=")[1]

    # processor info
    proc_name_com = 'WMIC CPU GET Name /VALUE'.split()
    processor_name = str(subprocess.check_output(proc_name_com, shell=True)).split("\\n")[2].split("\\r")[0].split("=")[
        1]

    proc_id_com = 'WMIC CPU GET ProcessorId /VALUE'.split()
    processor_id = str(subprocess.check_output(proc_id_com, shell=True)).split("\\n")[2].split("\\r")[0].split("=")[1]

    # system info from SMBIOS
    uuid_sys_com = 'WMIC CSPRODUCT GET UUID /VALUE'.split()
    uuid_system = str(subprocess.check_output(uuid_sys_com, shell=True)).split("\\n")[2].split("\\r")[0].split("=")[1]

    # monitor info
    mon_pnp_com = 'WMIC DESKTOPMONITOR GET PNPDeviceID /VALUE'.split()
    pnpdeviceid = str(subprocess.check_output(mon_pnp_com, shell=True)).split("\\n")[2].split("\\r")[0].split("=")[1]

А теперь небольшие пояснения. Первая команда, которую мы рассматривали выше, получает название производителя материнской платы. Команда: «WMIC BASEBOARD GET Product /VALUE» модель материнской платы. Ну и так далее. Вот небольшой список с пояснениями по командам:

Код:
«WMIC BIOS GET Version /VALUE» - версия BIOS;
«WMIC BIOS GET Manufacturer /VALUE» - производитель BIOS;
«WMIC BIOS GET SerialNumber /VALUE» - серийный номер BIOS. Это значение не всегда доступно;
«WMIC BIOS GET Description /VALUE» - информация о дате обновления и версии BIOS;
«WMIC BIOS GET SMBIOSBIOSVersion /VALUE» - версия SMBIOS;
«WMIC BOOTCONFIG GET BootDirectory /VALUE» - директория загрузки Windows;
«WMIC BOOTCONFIG GET LastDrive /VALUE» - последний диск, буква диска, в системе;
«WMIC CPU GET Name /VALUE» - модель процессора;
«WMIC CPU GET ProcessorId /VALUE» - ID процессора;
«WMIC CSPRODUCT GET UUID /VALUE» - UUID системы;
«WMIC DESKTOPMONITOR GET PNPDeviceID /VALUE» - информация о мониторе.

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

Python:
    if 'other_info' not in dict_info['info']:
        dict_info['info']['other_info'] = dict()
        dict_info['info']['other_info'] = {'motherboard_manufacturer': manufacturer,
                                           'motherboard_product': product,
                                           'version_bios': version_bios,
                                           'manufacturer_bios': manufacturer_bios,
                                           'serial_number_bios': serial_num_bios,
                                           'date_version_bios': date_version_bios,
                                           'smbios_version': smbios_ver,
                                           'os_boot_directory': boot_directory,
                                           'last_drive': last_drive,
                                           'processor_name': processor_name,
                                           'processor_id': processor_id,
                                           'uuid_system': uuid_system,
                                           'pnp_device_id': pnpdeviceid}

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

Теперь переходим к дискам. Что меня тут заинтересовало в первую очередь? Название модели. Это, можно сказать, отправная точка, с которой и будем двигаться дальше.

Получаем информацию о модели:

Python:
d_cap_com = 'WMIC DISKDRIVE GET Caption /VALUE'.split()
    disk_caption = str(subprocess.check_output(d_cap_com, shell=True)).strip().split("\\n")
    d_list = []
    for cap in disk_caption:
        if 'Caption=' in cap:
            d_list.append(cap.split("\\r")[0].split("=")[1])

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

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

Python:
ser_dcom = 'WMIC DISKDRIVE GET SerialNumber /VALUE'.split()
    serial_num_disk = str(subprocess.check_output(ser_dcom, shell=True)).strip().split("\\n")
    d_sn_list = []
    for ser in serial_num_disk:
        if 'SerialNumber=' in ser:
            d_sn_list.append(ser.split("\\r")[0].split("=")[1].strip())

Здесь все то же самое, что и в предыдущем коде. Получаем вывод, фильтруем и перебираем. А полученные значения складываем в список.

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

Python:
    for num in range(0, len(d_list)):
        if 'drive_name_serial' not in dict_info['info']['other_info']:
            dict_info['info']['other_info']['drive_name_serial'] = dict()
        if d_list[num] not in dict_info['info']['other_info']['drive_name_serial']:
            dict_info['info']['other_info']['drive_name_serial'][d_list[num]] = dict()
            dict_info['info']['other_info']['drive_name_serial'][d_list[num]] = d_sn_list[num]

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

Python:
firm_rev_com = 'WMIC DISKDRIVE GET FirmwareRevision /VALUE'.split()
    firmvare_revision_disk = str(subprocess.check_output(firm_rev_com, shell=True)).strip().split("\\n")
    fr_list = []
    for num, fm in enumerate(firmvare_revision_disk):
        if 'FirmwareRevision=' in fm:
            fr_list.append(fm.split("\\r")[0].split("=")[1].strip())
    for nf in range(0, len(fr_list)):
        if 'drive_firmware' not in dict_info['info']['other_info']:
            dict_info['info']['other_info']['drive_firmware'] = dict()
        if f'drive_{str(nf)}' not in dict_info['info']['other_info']['drive_firmware']:
            dict_info['info']['other_info']['drive_firmware'][f'drive_{str(nf)}'] = dict()
            dict_info['info']['other_info']['drive_firmware'][f'drive_{str(nf)}'] = fr_list[nf]

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

Python:
disk_sig_com = 'WMIC DISKDRIVE GET Signature /VALUE'.split()
    disk_signature = str(subprocess.check_output(disk_sig_com, shell=True)).strip().split("\\n")
    sig_list = []
    for sig in disk_signature:
        if 'Signature=' in sig:
            sig_list.append(sig.split("\\r")[0].split("=")[1].strip())
    for sgl in range(0, len(sig_list)):
        if 'disk_signature' not in dict_info['info']['other_info']:
            dict_info['info']['other_info']['disk_signature'] = dict()
        if f'sig_{sgl}' not in dict_info['info']['other_info']['disk_signature']:
            dict_info['info']['other_info']['disk_signature'][f'sig_{sgl}'] = sig_list[sgl]

Теперь получаем информацию о разделах. Для начала о их имени. То есть, некоторые пользователи переименовывают разделы, чтобы указать, что на данном диске хранятся, к примеру, фильмы. Вот именно эти значения мы сейчас и получим. Если же значения не будет, а такое тоже может быть, это когда у диска нет названия и в системе он отображается как «Локальный диск…», запишем, что он просто диск. Ну и добавим все в словарь.

Python:
vdn_com = 'WMIC LOGICALDISK GET VolumeName /value'
    disk_volume_name = str(subprocess.check_output(vdn_com, shell=True)).strip().split("\\n")
    vol_name_list = []
    for voln in disk_volume_name:
        if 'VolumeName=' in voln:
            if voln.split("\\r")[0].split("=")[1].strip() == "":
                vol_name_list.append('Drive')
            else:
                vol_name_list.append(voln.split("\\r")[0].split("=")[1].strip())

    for vln in range(0, len(vol_name_list)):
        if 'volum_name' not in dict_info['info']['other_info']:
            dict_info['info']['other_info']['volum_name'] = dict()
        if f'volum_{vln}' not in dict_info['info']['other_info']['volum_name']:
            dict_info['info']['other_info']['volum_name'][f'volum_{vln}'] = dict()
            dict_info['info']['other_info']['volum_name'][f'volum_{vln}'] = vol_name_list[vln]

И последнее, что мы узнаем о разделах, это серийный номер тома. Алгоритм получения тот же. Отличается только команда для получения данных.

Python:
vol_sn_com = 'WMIC LOGICALDISK GET VolumeSerialNumber /value'
    volume_serialnumber = str(subprocess.check_output(vol_sn_com, shell=True)).strip().split("\\n")
    vol_sn_list = []
    for vol_sn in volume_serialnumber:
        if 'VolumeSerialNumber=' in vol_sn:
            vol_sn_list.append(vol_sn.split("\\r")[0].split("=")[1].strip())

    for vsn in range(0, len(vol_sn_list)):
        if 'volume_serial_number' not in dict_info['info']['other_info']:
            dict_info['info']['other_info']['volume_serial_number'] = dict()
        if f'volume_serial_{vsn}' not in dict_info['info']['other_info']['volume_serial_number']:
            dict_info['info']['other_info']['volume_serial_number'][f'volume_serial_{vsn}'] = dict()
            dict_info['info']['other_info']['volume_serial_number'][f'volume_serial_{vsn}'] = vol_sn_list[vsn]

А теперь пришла очередь оперативной памяти. Получим ее форм-фактор. То есть, сколько слотов задействовано и какого объема. Ну, это насколько я понял. Тут я могу ошибаться, конечно. Потому, надо по этой команде еще поковыряться. Тем не менее, получаем его и записываем в словарь. Информации мало не бывает.

Python:
formf_com = 'WMIC MEMORYCHIP GET FormFactor /value'.split()
    ram_form_factor = str(subprocess.check_output(formf_com, shell=True)).strip().split("\\n")
    for num, ffm in enumerate(ram_form_factor):
        if 'FormFactor=8' in ffm:
            if 'memory_form_factor' not in dict_info['info']['other_info']:
                dict_info['info']['other_info']['memory_form_factor'] = dict()
            if f'memory_{num}' not in dict_info['info']['other_info']['memory_form_factor']:
                dict_info['info']['other_info']['memory_form_factor'][f'memory_{num}'] = dict()
                dict_info['info']['other_info']['memory_form_factor'][f'memory_{num}'] = \
                    ffm.split("\\r")[0].split("=")[1].strip()

Теперь выдергиваем производителя оперативки. Скажем так, тут не особо много информации удалось получить. Но, хоть что-то. Думаю, что есть другой способ получения данной информации. Возможно, из реестра. Тут надо разобраться. А может быть с помощью другой команды. Эта же команда показывает какие-то отрывочные сведения, но тем не менее, понять кто производитель можно. По крайней мере у меня одна планка показала производителя. А вторая тоже показала. Но какой-то цифровой набор. Может быть потому, что она от AMD? )

Python:
ram_man_com = 'WMIC MEMORYCHIP GET Manufacturer /value'.split()
    ram_manufacturer = str(subprocess.check_output(ram_man_com, shell=True)).strip().split("\\n")
    for num, ram_m in enumerate(ram_manufacturer):
        if 'Manufacturer=' in ram_m:
            if 'memory_manufacturer' not in dict_info['info']['other_info']:
                dict_info['info']['other_info']['memory_manufacturer'] = dict()
            if f'manufacturer_{num}' not in dict_info['info']['other_info']['memory_manufacturer']:
                dict_info['info']['other_info']['memory_manufacturer'][f'manufacturer_{num}'] = dict()
                dict_info['info']['other_info']['memory_manufacturer'][f'manufacturer_{num}'] = \
                    ram_m.split("\\r")[0].split("=")[1].strip()

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

Python:
ram_pn_com = 'WMIC MEMORYCHIP GET PartNumber /value'.split()
    ram_part_number = str(subprocess.check_output(ram_pn_com, shell=True)).strip().split("\\n")
    for num, rpn in enumerate(ram_part_number):
        if 'PartNumber=' in rpn:
            if 'memory_part_number' not in dict_info['info']['other_info']:
                dict_info['info']['other_info']['memory_part_number'] = dict()
            if f'part_number_{num}' not in dict_info['info']['other_info']['memory_part_number']:
                dict_info['info']['other_info']['memory_part_number'][f'part_number_{num}'] = dict()
                dict_info['info']['other_info']['memory_part_number'][f'part_number_{num}'] = \
                    rpn.split("\\r")[0].split("=")[1].strip()

А вот теперь получаем серийный номер планок или планки оперативки. Кстати, похоже, что инвентарный и серийный номер, это именно те циферки, набрав которые в поисковике можно получить информацию о планке оперативной памяти.

Python:
ram_sn_com = 'WMIC MEMORYCHIP GET SerialNumber /value'.split()
    serial_number_ram = str(subprocess.check_output(ram_sn_com, shell=True)).strip().split("\\n")
    for num, sn_ram in enumerate(serial_number_ram):
        if 'SerialNumber=' in sn_ram:
            if 'memory_serial_number' not in dict_info['info']['other_info']:
                dict_info['info']['other_info']['memory_serial_number'] = dict()
            if f'serial_number_{num}' not in dict_info['info']['other_info']['memory_serial_number']:
                dict_info['info']['other_info']['memory_serial_number'][f'serial_number_{num}'] = dict()
                dict_info['info']['other_info']['memory_serial_number'][f'serial_number_{num}'] = \
                    sn_ram.split("\\r")[0].split("=")[1].strip()

Теперь пришла очередь узнать частоту оперативной памяти. Кстати, это будет именно так частота, которую максимально поддерживает чипсет. А не та, что поддерживает планка оперативки.

Python:
ram_spf_com = 'WMIC MEMORYCHIP GET Speed /value'.split()
    ram_speed_frequency = str(subprocess.check_output(ram_spf_com, shell=True)).strip().split("\\n")
    for num, rsf in enumerate(ram_speed_frequency):
        if 'Speed=' in rsf:
            if 'memory_frequency' not in dict_info['info']['other_info']:
                dict_info['info']['other_info']['memory_frequency'] = dict()
            if f'frequency_{num}' not in dict_info['info']['other_info']['memory_frequency']:
                dict_info['info']['other_info']['memory_frequency'][f'frequency_{num}'] = dict()
                dict_info['info']['other_info']['memory_frequency'][f'frequency_{num}'] = \
                    rsf.split("\\r")[0].split("=")[1].strip()

Ну вот, пришла очередь сетевых адаптеров. С помощью этой команды мы узнаем название модели адаптера. Но, тут нужно понимать, что в выдачу попадают как реальные, так и виртуальные адаптеры, которые созданы системой для различных взаимодействий с сетью и различными устройствами. Ну и адаптеры виртуальных машин.

Python:
cap_net_com = 'WMIC NIC get Caption /value'.split()
    caption_net_adapter = str(subprocess.check_output(cap_net_com, shell=True)).strip().split("\\n")
    for num, capnad in enumerate(caption_net_adapter):
        if 'Caption=' in capnad:
            if 'net_adapter_caption' not in dict_info['info']['other_info']:
                dict_info['info']['other_info']['net_adapter_caption'] = dict()
            if f'net_adapter_{num}' not in dict_info['info']['other_info']['net_adapter_caption']:
                dict_info['info']['other_info']['net_adapter_caption'][f'net_adapter_{num}'] = dict()
                dict_info['info']['other_info']['net_adapter_caption'][f'net_adapter_{num}'] = \
                    capnad.split("\\r")[0].split("=")[1].strip().split("]")[1].strip()

Теперь получаем GUID сетевых адаптеров. Это глобальный уникальный идентификатор. То есть, он жестко привязан к конкретному устройству, а следовательно, представляет собой важный элемент в цифровом следе пользователя.

Python:
net_giud_com = 'WMIC NIC get GUID /value'.split()
    guid_network_adapter = str(subprocess.check_output(net_giud_com, shell=True)).strip().split("\\n")
    for num, guid in enumerate(guid_network_adapter):
        if 'GUID=' in guid:
            if guid.split("\\r")[0].split("=")[1].strip():
                if 'guid_net_adapter' not in dict_info['info']['other_info']:
                    dict_info['info']['other_info']['guid_net_adapter'] = dict()
                if f'guid_{num}' not in dict_info['info']['other_info']['guid_net_adapter']:
                    dict_info['info']['other_info']['guid_net_adapter'][f'guid_{num}'] = dict()
                    dict_info['info']['other_info']['guid_net_adapter'][f'guid_{num}'] = \
                        guid.split("\\r")[0].split("=")[1].strip()

А теперь получаем информацию о дате установки операционной системы. Надо сказать, что в выводе у нее не особо удобный формат. Но достаточно легко читаемый. Поэтому я просто вывел с помощью срезов дату и время установки. То есть, дату в формате, к примеру, 20220424 надо читать справа налево. То есть, 24 апреля 2022 года. А вот время, 092804, уже слева направо. Просто надо делить все по два символа. То есть, в примере 09 часов, 28 минут и 04 секунды.

Python:
os_inst_date_com = 'WMIC OS get InstallDate /value'.split()
    os_install_date = str(subprocess.check_output(os_inst_date_com, shell=True)).strip().split("\\n")[2].\
        split("\\r")[0].split("=")[1]
    if 'os_install_date_time' not in dict_info['info']['other_info']:
        dict_info['info']['other_info']['os_install_date_time'] = dict()
        dict_info['info']['other_info']['os_install_date_time'] = f'{os_install_date[0:8]}, {os_install_date[8:14]}'

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

Python:
os_sn_com = 'WMIC OS get SerialNumber /value'.split()
    os_serial_number = str(subprocess.check_output(os_sn_com, shell=True)).strip().split("\\n")[2].split("\\r")[0].\
        split("=")[1]

    if 'os_serial_number' not in dict_info['info']['other_info']:
        dict_info['info']['other_info']['os_serial_number'] = dict()
        dict_info['info']['other_info']['os_serial_number'] = os_serial_number

Дальше идет идентификатор клиентской машины. Он тоже пригодиться, так сказать для фингерпринта.

Python:
lic_clid_com = 'wmic path softwarelicensingservice get ClientMachineID /value'
    client_machine_id_lic = \
        str(subprocess.check_output(lic_clid_com, shell=True)).strip().split("\\n")[2].split("\\r")[0].split("=")[1]
    if 'client_machine_id_lic' not in dict_info['info']['other_info']:
        dict_info['info']['other_info']['client_machine_id_lic'] = dict()
        dict_info['info']['other_info']['client_machine_id_lic'] = client_machine_id_lic

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

Python:
serial_num_com = 'wmic path softwarelicensingservice get OA3xOriginalProductKey /value'.split()
    key_activate_win_uefi = \
        str(subprocess.check_output(serial_num_com, shell=True)).strip().split("\\n")[2].split("\\r")[0].split("=")[
                1]
    if key_activate_win_uefi == '':
        pkey = windows_tools.product_key.get_windows_product_key_from_reg()
        if 'key_activate_win' not in dict_info['info']['other_info']:
            dict_info['info']['other_info']['key_activate_win'] = dict()
            dict_info['info']['other_info']['key_activate_win'] = pkey
    else:
        if 'key_activate_win' not in dict_info['info']['other_info']:
            dict_info['info']['other_info']['key_activate_win'] = dict()
            dict_info['info']['other_info']['key_activate_win'] = key_activate_win_uefi

Но, если вы подумали, что это все, то нет, это не так. Просто мне попались команды именно в этом порядке. И я подумал, что какая разница то? ) Получим информацию о принтерах. Узнаем их количество, в том числе и те, которые используются для сохранения документов в PDF, то есть виртуальные. А также название.

Python:
prn_cap_com = 'WMIC PRINTER get Caption /value'.split()
    printer_caption = str(subprocess.check_output(prn_cap_com, shell=True)).strip().split("\\n")
    for num, prn in enumerate(printer_caption):
        if 'Caption=' in prn:
            if 'printer_caption' not in dict_info['info']['other_info']:
                dict_info['info']['other_info']['printer_caption'] = dict()
            if f'printer_{num}' not in dict_info['info']['other_info']['printer_caption']:
                dict_info['info']['other_info']['printer_caption'][f'printer_{num}'] = dict()
                dict_info['info']['other_info']['printer_caption'][f'printer_{num}'] = prn.split("\\r")[0].\
                    split("=")[1].strip()

А вот теперь, последнее значение, которое мы получим с помощью команд. Это значение временной зоны. То есть, смещение времени от Гринвича на компьютере, а также название города, в котором данная зона идентифицирована.

Python:
time_z_com = 'WMIC TIMEZONE get Caption /value'.split()
    time_zone = str(subprocess.check_output(time_z_com, shell=True)).strip().split("\\n")[2].split("\\r")[0].\
        split("=")[1]
    if 'time_zone' not in dict_info['info']['other_info']:
        dict_info['info']['other_info']['time_zone'] = dict()
        dict_info['info']['other_info']['time_zone'] = time_zone

После возвращаем уже дополненный словарь для дальнейшей работы.

return dict_info

Вы еще не устали? Если нет, то давайте продолжим. Осталось уже совсем немного. И добьем скрипт до текущего логического завершения. Что нам еще осталось сделать? Вывести полученные значения в терминал. Это, конечно, не обязательно, а потому я вынес все это дело в отдельную функцию, как и предыдущую функцию печати получаемых общих значений. Для того, чтобы можно было исполнение данных функций просто закомментировать.

Создадим функцию печати новых значений: print_dop_info(dict_info_dop). На вход она получает словарь с новыми значениями. Для того, чтобы вытащить из него новые и распечатать в терминал. Ну буду подробно ее описывать, так как тут все более-менее понятно. В цикле получаются значения и с помощью условий производиться выборка нужных и их вывод в терминал. На выходе функция ничего не возвращает. Да и нечего, собственно.

Python:
def print_dop_info(dict_info_dop):
    for item in dict_info_dop['info']:
        if item == "other_info":
            print(f'[+] Дополнительная информация\n{"-"*33}')
            for elem in dict_info_dop['info'][item]:
                if elem == 'drive_name_serial':
                    print(f"\n[+] Диски: модель, серийный номер")
                    for drive in dict_info_dop['info'][item][elem]:
                        print(f"\t- {drive}: {dict_info_dop['info'][item][elem][drive]}")
                elif elem == 'drive_firmware':
                    print(f"\n[+] Версия прошивки:")
                    for firmware in dict_info_dop['info'][item][elem]:
                        print(f"\t- {firmware}: {dict_info_dop['info'][item][elem][firmware]}")
                elif elem == 'disk_signature':
                    print(f"\n[+] Цифровая подпись:")
                    for signature in dict_info_dop['info'][item][elem]:
                        print(f"\t- {signature}: {dict_info_dop['info'][item][elem][signature]}")
                elif elem == 'volum_name':
                    print(f"\n[+] Имя тома:")
                    for vol_n in dict_info_dop['info'][item][elem]:
                        print(f"\t- {vol_n}: {dict_info_dop['info'][item][elem][vol_n]}")
                elif elem == 'volume_serial_number':
                    print(f"\n[+] Серийный номер тома:")
                    for volume_serial in dict_info_dop['info'][item][elem]:
                        print(f"\t- {volume_serial}: {dict_info_dop['info'][item][elem][volume_serial]}")
                elif elem == 'memory_form_factor':
                    print(f"\n[+] RAM форм-фактор:")
                    for memory_ff in dict_info_dop['info'][item][elem]:
                        print(f"\t- {memory_ff}: {dict_info_dop['info'][item][elem][memory_ff]}")
                elif elem == 'memory_manufacturer':
                    print(f"\n[+] Производитель RAM:")
                    for memory_man in dict_info_dop['info'][item][elem]:
                        print(f"\t- {memory_man}: {dict_info_dop['info'][item][elem][memory_man]}")
                elif elem == 'memory_part_number':
                    print(f"\n[+] Инвентарный номер RAM:")
                    for memory_part in dict_info_dop['info'][item][elem]:
                        print(f"\t- {memory_part}: {dict_info_dop['info'][item][elem][memory_part]}")
                elif elem == 'memory_serial_number':
                    print(f"\n[+] Серийный номер RAM:")
                    for memory_serial in dict_info_dop['info'][item][elem]:
                        print(f"\t- {memory_serial}: {dict_info_dop['info'][item][elem][memory_serial]}")
                elif elem == 'memory_frequency':
                    print(f"\n[+] Частота RAM:")
                    for memory_fr in dict_info_dop['info'][item][elem]:
                        print(f"\t- {memory_fr}: {dict_info_dop['info'][item][elem][memory_fr]}")
                elif elem == 'net_adapter_caption':
                    print(f"\n[+] Название сетевого адаптера:")
                    for adapter_caption in dict_info_dop['info'][item][elem]:
                        print(f"\t- {adapter_caption}: {dict_info_dop['info'][item][elem][adapter_caption]}")
                elif elem == 'guid_net_adapter':
                    print(f"\n[+] GUID сетевого адаптера:")
                    for guid_net in dict_info_dop['info'][item][elem]:
                        print(f"\t- {guid_net}: {dict_info_dop['info'][item][elem][guid_net]}")
                elif elem == 'printer_caption':
                    print(f"\n[+] Название принтера:")
                    for prn_caption in dict_info_dop['info'][item][elem]:
                        print(f"\t- {prn_caption}: {dict_info_dop['info'][item][elem][prn_caption]}")
                else:
                    print(f"[+] {elem.upper()}: {dict_info_dop['info'][item][elem]}")

Здесь я не стал заморачиваться с выводом описаний, так как по выводимым значениям и так все понятно. Но, при необходимости данный код можно дополнить, дописав туда описание.

И наконец функция main(). Она тоже притерпела небольшие изменения. В нее было добавлено сохранение данных из собранного словаря в JSON, а также раздельная функция печати. Причем, данные сначала сохраняются, а уже потом выводятся в терминал. Ну так, на всякий случай.

Python:
def main():
    if uname().system == "Windows":
        dict_info = creating_file()
        dict_info_dop = win_dop_info(dict_info)
        with open(f'info_{uname().node}.json', 'w', encoding='utf-8') as file:
            json.dump(dict_info_dop, file, indent=4, ensure_ascii=False)
        print_info(dict_info)
        print_dop_info(dict_info_dop)
    elif uname().system == "Linux":
        dict_info = creating_file()
        with open(f'info_{uname().node}.json', 'w', encoding='utf-8') as file:
            json.dump(dict_info, file, indent=4, ensure_ascii=False)
        print_info(dict_info)

И да, изменения здесь коснулись и блока с вызовом функций для Linux. В частности, запись значений в файл. Она была убрана из функции получения данных и перенесена сюда.

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

screenshot2.png

Python:
import json
import subprocess

import psutil
from platform import uname


def correct_size(bts, ending='iB'):
    size = 1024
    for item in ["", "K", "M", "G", "T", "P"]:
        if bts < size:
            return f"{bts:.2f}{item}{ending}"
        bts /= size


def creating_file():
    collect_info_dict = dict()
    if 'info' not in collect_info_dict:
        collect_info_dict['info'] = dict()
        collect_info_dict['info']['system_info'] = dict()
        collect_info_dict['info']['system_info'] = {'system': {'comp_name': uname().node,
                                                               'os_name': f"{uname().system} {uname().release}",
                                                               'version': uname().version,
                                                               'machine': uname().machine},
                                                    'processor': {'name': uname().processor,
                                                                  'phisycal_core': psutil.cpu_count(logical=False),
                                                                  'all_core': psutil.cpu_count(logical=True),
                                                                  'freq_max': f"{psutil.cpu_freq().max:.2f}Мгц"},
                                                    'ram': {'volume': correct_size(psutil.virtual_memory().total),
                                                            'aviable': correct_size(psutil.virtual_memory().available),
                                                            'used': correct_size(psutil.virtual_memory().used)}}

    for partition in psutil.disk_partitions():
        try:
            partition_usage = psutil.disk_usage(partition.mountpoint)
        except PermissionError:
            continue
        if 'disk_info' not in collect_info_dict['info']:
            collect_info_dict['info']['disk_info'] = dict()
        if f"'device': {partition.device}" not in collect_info_dict['info']['disk_info']:
            collect_info_dict['info']['disk_info'][partition.device] = dict()
            collect_info_dict['info']['disk_info'][partition.device] = {'file_system': partition.fstype,
                                                                        'size_total': correct_size(
                                                                            partition_usage.total),
                                                                        'size_used': correct_size(
                                                                            partition_usage.used),
                                                                        'size_free': correct_size(
                                                                            partition_usage.free),
                                                                        'percent':
                                                                            f'{partition_usage.percent}'}

    for interface_name, interface_address in psutil.net_if_addrs().items():
        if interface_name == 'Loopback Pseudo-Interface 1':
            continue
        else:
            if 'net_info' not in collect_info_dict['info']:
                collect_info_dict['info']['net_info'] = dict()
            if interface_name not in collect_info_dict['info']['net_info']:
                collect_info_dict['info']['net_info'][interface_name] = dict()
                collect_info_dict['info']['net_info'][interface_name] = {
                    'mac': interface_address[0].address.replace("-", ":"),
                    'ipv4': interface_address[1].address,
                    'ipv6': interface_address[2].address}

    return collect_info_dict


def win_dop_info(dict_info):
    import windows_tools.product_key

    # motherboard
    man_moth_com = 'WMIC BASEBOARD GET Manufacturer /VALUE'.split()
    manufacturer = str(subprocess.check_output(man_moth_com, shell=True)).split("\\n")[2].replace("\\r", "").\
        split("=")[1]

    prod_com = 'WMIC BASEBOARD GET Product /VALUE'.split()
    product = str(subprocess.check_output(prod_com, shell=True)).split("\\n")[2].split("\\r")[0].split("=")[1]

    # bios
    verb_com = 'WMIC BIOS GET Version /VALUE'.split()
    version_bios = str(subprocess.check_output(verb_com, shell=True)).split("\\n")[2].split("\\r")[0].split("=")[1]

    man_bios_com = 'WMIC BIOS GET Manufacturer /VALUE'.split()
    manufacturer_bios = str(subprocess.check_output(man_bios_com, shell=True)).\
        split("\\n")[2].split("\\r")[0].split("=")[1]

    sn_bios_com = 'WMIC BIOS GET SerialNumber /VALUE'.split()
    serial_num_bios = str(subprocess.check_output(sn_bios_com, shell=True)).split("\\n")[2].split("\\r")[0].split("=")[
        1]

    dv_bios_com = 'WMIC BIOS GET Description /VALUE'.split()
    date_version_bios = str(subprocess.check_output(dv_bios_com, shell=True)).\
        split("\\n")[2].split("\\r")[0].split("=")[1]

    smbios_com = 'WMIC BIOS GET SMBIOSBIOSVersion /VALUE'.split()
    smbios_ver = str(subprocess.check_output(smbios_com, shell=True)).split("\\n")[2].split("\\r")[0].split("=")[1]

    # boot configuration
    boot_dir_com = 'WMIC BOOTCONFIG GET BootDirectory /VALUE'.split()
    boot_directory = str(subprocess.check_output(boot_dir_com, shell=True)).split("\\n")[2].split("\\r")[0].split("=")[
        1]

    lastd_com = 'WMIC BOOTCONFIG GET LastDrive /VALUE'.split()
    last_drive = str(subprocess.check_output(lastd_com, shell=True)).split("\\n")[2].split("\\r")[0].split("=")[1]

    # processor info
    proc_name_com = 'WMIC CPU GET Name /VALUE'.split()
    processor_name = str(subprocess.check_output(proc_name_com, shell=True)).split("\\n")[2].split("\\r")[0].split("=")[
        1]

    proc_id_com = 'WMIC CPU GET ProcessorId /VALUE'.split()
    processor_id = str(subprocess.check_output(proc_id_com, shell=True)).split("\\n")[2].split("\\r")[0].split("=")[1]

    # system info from SMBIOS
    uuid_sys_com = 'WMIC CSPRODUCT GET UUID /VALUE'.split()
    uuid_system = str(subprocess.check_output(uuid_sys_com, shell=True)).split("\\n")[2].split("\\r")[0].split("=")[1]

    # monitor info
    mon_pnp_com = 'WMIC DESKTOPMONITOR GET PNPDeviceID /VALUE'.split()
    pnpdeviceid = str(subprocess.check_output(mon_pnp_com, shell=True)).split("\\n")[2].split("\\r")[0].split("=")[1]

    if 'other_info' not in dict_info['info']:
        dict_info['info']['other_info'] = dict()
        dict_info['info']['other_info'] = {'motherboard_manufacturer': manufacturer,
                                           'motherboard_product': product,
                                           'version_bios': version_bios,
                                           'manufacturer_bios': manufacturer_bios,
                                           'serial_number_bios': serial_num_bios,
                                           'date_version_bios': date_version_bios,
                                           'smbios_version': smbios_ver,
                                           'os_boot_directory': boot_directory,
                                           'last_drive': last_drive,
                                           'processor_name': processor_name,
                                           'processor_id': processor_id,
                                           'uuid_system': uuid_system,
                                           'pnp_device_id': pnpdeviceid}

    # disk info
    d_cap_com = 'WMIC DISKDRIVE GET Caption /VALUE'.split()
    disk_caption = str(subprocess.check_output(d_cap_com, shell=True)).strip().split("\\n")
    d_list = []
    for cap in disk_caption:
        if 'Caption=' in cap:
            d_list.append(cap.split("\\r")[0].split("=")[1])

    ser_dcom = 'WMIC DISKDRIVE GET SerialNumber /VALUE'.split()
    serial_num_disk = str(subprocess.check_output(ser_dcom, shell=True)).strip().split("\\n")
    d_sn_list = []
    for ser in serial_num_disk:
        if 'SerialNumber=' in ser:
            d_sn_list.append(ser.split("\\r")[0].split("=")[1].strip())

    for num in range(0, len(d_list)):
        if 'drive_name_serial' not in dict_info['info']['other_info']:
            dict_info['info']['other_info']['drive_name_serial'] = dict()
        if d_list[num] not in dict_info['info']['other_info']['drive_name_serial']:
            dict_info['info']['other_info']['drive_name_serial'][d_list[num]] = dict()
            dict_info['info']['other_info']['drive_name_serial'][d_list[num]] = d_sn_list[num]

    firm_rev_com = 'WMIC DISKDRIVE GET FirmwareRevision /VALUE'.split()
    firmvare_revision_disk = str(subprocess.check_output(firm_rev_com, shell=True)).strip().split("\\n")
    fr_list = []
    for num, fm in enumerate(firmvare_revision_disk):
        if 'FirmwareRevision=' in fm:
            fr_list.append(fm.split("\\r")[0].split("=")[1].strip())
    for nf in range(0, len(fr_list)):
        if 'drive_firmware' not in dict_info['info']['other_info']:
            dict_info['info']['other_info']['drive_firmware'] = dict()
        if f'drive_{str(nf)}' not in dict_info['info']['other_info']['drive_firmware']:
            dict_info['info']['other_info']['drive_firmware'][f'drive_{str(nf)}'] = dict()
            dict_info['info']['other_info']['drive_firmware'][f'drive_{str(nf)}'] = fr_list[nf]

    disk_sig_com = 'WMIC DISKDRIVE GET Signature /VALUE'.split()
    disk_signature = str(subprocess.check_output(disk_sig_com, shell=True)).strip().split("\\n")
    sig_list = []
    for sig in disk_signature:
        if 'Signature=' in sig:
            sig_list.append(sig.split("\\r")[0].split("=")[1].strip())
    for sgl in range(0, len(sig_list)):
        if 'disk_signature' not in dict_info['info']['other_info']:
            dict_info['info']['other_info']['disk_signature'] = dict()
        if f'sig_{sgl}' not in dict_info['info']['other_info']['disk_signature']:
            dict_info['info']['other_info']['disk_signature'][f'sig_{sgl}'] = sig_list[sgl]

    # volume disk info
    vdn_com = 'WMIC LOGICALDISK GET VolumeName /value'
    disk_volume_name = str(subprocess.check_output(vdn_com, shell=True)).strip().split("\\n")
    vol_name_list = []
    for voln in disk_volume_name:
        if 'VolumeName=' in voln:
            if voln.split("\\r")[0].split("=")[1].strip() == "":
                vol_name_list.append('Drive')
            else:
                vol_name_list.append(voln.split("\\r")[0].split("=")[1].strip())

    for vln in range(0, len(vol_name_list)):
        if 'volum_name' not in dict_info['info']['other_info']:
            dict_info['info']['other_info']['volum_name'] = dict()
        if f'volum_{vln}' not in dict_info['info']['other_info']['volum_name']:
            dict_info['info']['other_info']['volum_name'][f'volum_{vln}'] = dict()
            dict_info['info']['other_info']['volum_name'][f'volum_{vln}'] = vol_name_list[vln]

    vol_sn_com = 'WMIC LOGICALDISK GET VolumeSerialNumber /value'
    volume_serialnumber = str(subprocess.check_output(vol_sn_com, shell=True)).strip().split("\\n")
    vol_sn_list = []
    for vol_sn in volume_serialnumber:
        if 'VolumeSerialNumber=' in vol_sn:
            vol_sn_list.append(vol_sn.split("\\r")[0].split("=")[1].strip())

    for vsn in range(0, len(vol_sn_list)):
        if 'volume_serial_number' not in dict_info['info']['other_info']:
            dict_info['info']['other_info']['volume_serial_number'] = dict()
        if f'volume_serial_{vsn}' not in dict_info['info']['other_info']['volume_serial_number']:
            dict_info['info']['other_info']['volume_serial_number'][f'volume_serial_{vsn}'] = dict()
            dict_info['info']['other_info']['volume_serial_number'][f'volume_serial_{vsn}'] = vol_sn_list[vsn]

    # ram info
    formf_com = 'WMIC MEMORYCHIP GET FormFactor /value'.split()
    ram_form_factor = str(subprocess.check_output(formf_com, shell=True)).strip().split("\\n")
    for num, ffm in enumerate(ram_form_factor):
        if 'FormFactor=8' in ffm:
            if 'memory_form_factor' not in dict_info['info']['other_info']:
                dict_info['info']['other_info']['memory_form_factor'] = dict()
            if f'memory_{num}' not in dict_info['info']['other_info']['memory_form_factor']:
                dict_info['info']['other_info']['memory_form_factor'][f'memory_{num}'] = dict()
                dict_info['info']['other_info']['memory_form_factor'][f'memory_{num}'] = \
                    ffm.split("\\r")[0].split("=")[1].strip()

    ram_man_com = 'WMIC MEMORYCHIP GET Manufacturer /value'.split()
    ram_manufacturer = str(subprocess.check_output(ram_man_com, shell=True)).strip().split("\\n")
    for num, ram_m in enumerate(ram_manufacturer):
        if 'Manufacturer=' in ram_m:
            if 'memory_manufacturer' not in dict_info['info']['other_info']:
                dict_info['info']['other_info']['memory_manufacturer'] = dict()
            if f'manufacturer_{num}' not in dict_info['info']['other_info']['memory_manufacturer']:
                dict_info['info']['other_info']['memory_manufacturer'][f'manufacturer_{num}'] = dict()
                dict_info['info']['other_info']['memory_manufacturer'][f'manufacturer_{num}'] = \
                    ram_m.split("\\r")[0].split("=")[1].strip()

    ram_pn_com = 'WMIC MEMORYCHIP GET PartNumber /value'.split()
    ram_part_number = str(subprocess.check_output(ram_pn_com, shell=True)).strip().split("\\n")
    for num, rpn in enumerate(ram_part_number):
        if 'PartNumber=' in rpn:
            if 'memory_part_number' not in dict_info['info']['other_info']:
                dict_info['info']['other_info']['memory_part_number'] = dict()
            if f'part_number_{num}' not in dict_info['info']['other_info']['memory_part_number']:
                dict_info['info']['other_info']['memory_part_number'][f'part_number_{num}'] = dict()
                dict_info['info']['other_info']['memory_part_number'][f'part_number_{num}'] = \
                    rpn.split("\\r")[0].split("=")[1].strip()

    ram_sn_com = 'WMIC MEMORYCHIP GET SerialNumber /value'.split()
    serial_number_ram = str(subprocess.check_output(ram_sn_com, shell=True)).strip().split("\\n")
    for num, sn_ram in enumerate(serial_number_ram):
        if 'SerialNumber=' in sn_ram:
            if 'memory_serial_number' not in dict_info['info']['other_info']:
                dict_info['info']['other_info']['memory_serial_number'] = dict()
            if f'serial_number_{num}' not in dict_info['info']['other_info']['memory_serial_number']:
                dict_info['info']['other_info']['memory_serial_number'][f'serial_number_{num}'] = dict()
                dict_info['info']['other_info']['memory_serial_number'][f'serial_number_{num}'] = \
                    sn_ram.split("\\r")[0].split("=")[1].strip()

    ram_spf_com = 'WMIC MEMORYCHIP GET Speed /value'.split()
    ram_speed_frequency = str(subprocess.check_output(ram_spf_com, shell=True)).strip().split("\\n")
    for num, rsf in enumerate(ram_speed_frequency):
        if 'Speed=' in rsf:
            if 'memory_frequency' not in dict_info['info']['other_info']:
                dict_info['info']['other_info']['memory_frequency'] = dict()
            if f'frequency_{num}' not in dict_info['info']['other_info']['memory_frequency']:
                dict_info['info']['other_info']['memory_frequency'][f'frequency_{num}'] = dict()
                dict_info['info']['other_info']['memory_frequency'][f'frequency_{num}'] = \
                    rsf.split("\\r")[0].split("=")[1].strip()

    ram_mdev_com = 'WMIC MEMPHYSICAL get MemoryDevices /value'.split()
    ram_count_memory = str(subprocess.check_output(ram_mdev_com, shell=True)).strip().split("\\n")[2].split("\\r")[0].\
        split("=")[1]
    if 'count_memory' not in dict_info['info']['other_info']:
        dict_info['info']['other_info']['count_memory'] = dict()
        dict_info['info']['other_info']['count_memory'] = ram_count_memory

    # network adapter info
    cap_net_com = 'WMIC NIC get Caption /value'.split()
    caption_net_adapter = str(subprocess.check_output(cap_net_com, shell=True)).strip().split("\\n")
    for num, capnad in enumerate(caption_net_adapter):
        if 'Caption=' in capnad:
            if 'net_adapter_caption' not in dict_info['info']['other_info']:
                dict_info['info']['other_info']['net_adapter_caption'] = dict()
            if f'net_adapter_{num}' not in dict_info['info']['other_info']['net_adapter_caption']:
                dict_info['info']['other_info']['net_adapter_caption'][f'net_adapter_{num}'] = dict()
                dict_info['info']['other_info']['net_adapter_caption'][f'net_adapter_{num}'] = \
                    capnad.split("\\r")[0].split("=")[1].strip().split("]")[1].strip()

    net_giud_com = 'WMIC NIC get GUID /value'.split()
    guid_network_adapter = str(subprocess.check_output(net_giud_com, shell=True)).strip().split("\\n")
    for num, guid in enumerate(guid_network_adapter):
        if 'GUID=' in guid:
            if guid.split("\\r")[0].split("=")[1].strip():
                if 'guid_net_adapter' not in dict_info['info']['other_info']:
                    dict_info['info']['other_info']['guid_net_adapter'] = dict()
                if f'guid_{num}' not in dict_info['info']['other_info']['guid_net_adapter']:
                    dict_info['info']['other_info']['guid_net_adapter'][f'guid_{num}'] = dict()
                    dict_info['info']['other_info']['guid_net_adapter'][f'guid_{num}'] = \
                        guid.split("\\r")[0].split("=")[1].strip()

    # os information
    os_inst_date_com = 'WMIC OS get InstallDate /value'.split()
    os_install_date = str(subprocess.check_output(os_inst_date_com, shell=True)).strip().split("\\n")[2].\
        split("\\r")[0].split("=")[1]
    if 'os_install_date_time' not in dict_info['info']['other_info']:
        dict_info['info']['other_info']['os_install_date_time'] = dict()
        dict_info['info']['other_info']['os_install_date_time'] = f'{os_install_date[0:8]}, {os_install_date[8:14]}'

    os_sn_com = 'WMIC OS get SerialNumber /value'.split()
    os_serial_number = str(subprocess.check_output(os_sn_com, shell=True)).strip().split("\\n")[2].split("\\r")[0].\
        split("=")[1]

    if 'os_serial_number' not in dict_info['info']['other_info']:
        dict_info['info']['other_info']['os_serial_number'] = dict()
        dict_info['info']['other_info']['os_serial_number'] = os_serial_number

    # license cliendID
    lic_clid_com = 'wmic path softwarelicensingservice get ClientMachineID /value'
    client_machine_id_lic = \
        str(subprocess.check_output(lic_clid_com, shell=True)).strip().split("\\n")[2].split("\\r")[0].split("=")[1]
    if 'client_machine_id_lic' not in dict_info['info']['other_info']:
        dict_info['info']['other_info']['client_machine_id_lic'] = dict()
        dict_info['info']['other_info']['client_machine_id_lic'] = client_machine_id_lic

    serial_num_com = 'wmic path softwarelicensingservice get OA3xOriginalProductKey /value'.split()
    key_activate_win_uefi = \
        str(subprocess.check_output(serial_num_com, shell=True)).strip().split("\\n")[2].split("\\r")[0].split("=")[
                1]
    if key_activate_win_uefi == '':
        pkey = windows_tools.product_key.get_windows_product_key_from_reg()
        if 'key_activate_win' not in dict_info['info']['other_info']:
            dict_info['info']['other_info']['key_activate_win'] = dict()
            dict_info['info']['other_info']['key_activate_win'] = pkey
    else:
        if 'key_activate_win' not in dict_info['info']['other_info']:
            dict_info['info']['other_info']['key_activate_win'] = dict()
            dict_info['info']['other_info']['key_activate_win'] = key_activate_win_uefi

    # printer info
    prn_cap_com = 'WMIC PRINTER get Caption /value'.split()
    printer_caption = str(subprocess.check_output(prn_cap_com, shell=True)).strip().split("\\n")
    for num, prn in enumerate(printer_caption):
        if 'Caption=' in prn:
            if 'printer_caption' not in dict_info['info']['other_info']:
                dict_info['info']['other_info']['printer_caption'] = dict()
            if f'printer_{num}' not in dict_info['info']['other_info']['printer_caption']:
                dict_info['info']['other_info']['printer_caption'][f'printer_{num}'] = dict()
                dict_info['info']['other_info']['printer_caption'][f'printer_{num}'] = prn.split("\\r")[0].\
                    split("=")[1].strip()

    # time zone info
    time_z_com = 'WMIC TIMEZONE get Caption /value'.split()
    time_zone = str(subprocess.check_output(time_z_com, shell=True)).strip().split("\\n")[2].split("\\r")[0].\
        split("=")[1]
    if 'time_zone' not in dict_info['info']['other_info']:
        dict_info['info']['other_info']['time_zone'] = dict()
        dict_info['info']['other_info']['time_zone'] = time_zone

    return dict_info


def print_dop_info(dict_info_dop):
    for item in dict_info_dop['info']:
        if item == "other_info":
            print(f'[+] Дополнительная информация\n{"-"*33}')
            for elem in dict_info_dop['info'][item]:
                if elem == 'drive_name_serial':
                    print(f"\n[+] Диски: модель, серийный номер")
                    for drive in dict_info_dop['info'][item][elem]:
                        print(f"\t- {drive}: {dict_info_dop['info'][item][elem][drive]}")
                elif elem == 'drive_firmware':
                    print(f"\n[+] Версия прошивки:")
                    for firmware in dict_info_dop['info'][item][elem]:
                        print(f"\t- {firmware}: {dict_info_dop['info'][item][elem][firmware]}")
                elif elem == 'disk_signature':
                    print(f"\n[+] Цифровая подпись:")
                    for signature in dict_info_dop['info'][item][elem]:
                        print(f"\t- {signature}: {dict_info_dop['info'][item][elem][signature]}")
                elif elem == 'volum_name':
                    print(f"\n[+] Имя тома:")
                    for vol_n in dict_info_dop['info'][item][elem]:
                        print(f"\t- {vol_n}: {dict_info_dop['info'][item][elem][vol_n]}")
                elif elem == 'volume_serial_number':
                    print(f"\n[+] Серийный номер тома:")
                    for volume_serial in dict_info_dop['info'][item][elem]:
                        print(f"\t- {volume_serial}: {dict_info_dop['info'][item][elem][volume_serial]}")
                elif elem == 'memory_form_factor':
                    print(f"\n[+] RAM форм-фактор:")
                    for memory_ff in dict_info_dop['info'][item][elem]:
                        print(f"\t- {memory_ff}: {dict_info_dop['info'][item][elem][memory_ff]}")
                elif elem == 'memory_manufacturer':
                    print(f"\n[+] Производитель RAM:")
                    for memory_man in dict_info_dop['info'][item][elem]:
                        print(f"\t- {memory_man}: {dict_info_dop['info'][item][elem][memory_man]}")
                elif elem == 'memory_part_number':
                    print(f"\n[+] Инвентарный номер RAM:")
                    for memory_part in dict_info_dop['info'][item][elem]:
                        print(f"\t- {memory_part}: {dict_info_dop['info'][item][elem][memory_part]}")
                elif elem == 'memory_serial_number':
                    print(f"\n[+] Серийный номер RAM:")
                    for memory_serial in dict_info_dop['info'][item][elem]:
                        print(f"\t- {memory_serial}: {dict_info_dop['info'][item][elem][memory_serial]}")
                elif elem == 'memory_frequency':
                    print(f"\n[+] Частота RAM:")
                    for memory_fr in dict_info_dop['info'][item][elem]:
                        print(f"\t- {memory_fr}: {dict_info_dop['info'][item][elem][memory_fr]}")
                elif elem == 'net_adapter_caption':
                    print(f"\n[+] Название сетевого адаптера:")
                    for adapter_caption in dict_info_dop['info'][item][elem]:
                        print(f"\t- {adapter_caption}: {dict_info_dop['info'][item][elem][adapter_caption]}")
                elif elem == 'guid_net_adapter':
                    print(f"\n[+] GUID сетевого адаптера:")
                    for guid_net in dict_info_dop['info'][item][elem]:
                        print(f"\t- {guid_net}: {dict_info_dop['info'][item][elem][guid_net]}")
                elif elem == 'printer_caption':
                    print(f"\n[+] Название принтера:")
                    for prn_caption in dict_info_dop['info'][item][elem]:
                        print(f"\t- {prn_caption}: {dict_info_dop['info'][item][elem][prn_caption]}")
                else:
                    print(f"[+] {elem.upper()}: {dict_info_dop['info'][item][elem]}")


def print_info(dict_info):
    for item in dict_info['info']:
        if item == "system_info":
            for elem in dict_info['info'][item]:
                if elem == 'system':
                    print(f"[+] Информация о системе\n"
                          f"\t- Имя компьютера: {dict_info['info'][item][elem]['comp_name']}\n"
                          f"\t- Опереционная система: {dict_info['info'][item][elem]['os_name']}\n"
                          f"\t- Сборка: {dict_info['info'][item][elem]['version']}\n"
                          f"\t- Архитектура: {dict_info['info'][item][elem]['machine']}\n")
                if elem == 'processor':
                    print(f"[+] Информация о процессоре\n"
                          f"\t- Семейство: {dict_info['info'][item][elem]['name']}\n"
                          f"\t- Физические ядра: {dict_info['info'][item][elem]['phisycal_core']}\n"
                          f"\t- Всего ядер: {dict_info['info'][item][elem]['all_core']}\n"
                          f"\t- Максимальная частота: {dict_info['info'][item][elem]['freq_max']}\n")
                if elem == 'ram':
                    print(f"[+] Оперативная память\n"
                          f"\t- Объем: {dict_info['info'][item][elem]['volume']}\n"
                          f"\t- Доступно: {dict_info['info'][item][elem]['aviable']}\n"
                          f"\t- Используется: {dict_info['info'][item][elem]['used']}\n")
        if item == "disk_info":
            for elem in dict_info['info'][item]:
                print(f"[+] Информация о дисках\n"
                      f"\t- Имя диска: {elem}\n"
                      f"\t- Файловая система: {dict_info['info'][item][elem]['file_system']}\n"
                      f"\t- Объем диска: {dict_info['info'][item][elem]['size_total']}\n"
                      f"\t- Занято: {dict_info['info'][item][elem]['size_used']}\n"
                      f"\t- Свободно: {dict_info['info'][item][elem]['size_free']}\n"
                      f"\t- Заполненность: {dict_info['info'][item][elem]['percent']}%\n")
        if item == "net_info":
            for elem in dict_info['info'][item]:
                print(f"[+] Информация о сети\n"
                      f"\t- Имя интерфейса: {elem}\n"
                      f"\t- MAC-адрес: {dict_info['info'][item][elem]['mac']}\n"
                      f"\t- IPv4: {dict_info['info'][item][elem]['ipv4']}\n"
                      f"\t- IPv6: {dict_info['info'][item][elem]['ipv6']}\n")


def main():
    if uname().system == "Windows":
        dict_info = creating_file()
        dict_info_dop = win_dop_info(dict_info)
        with open(f'info_{uname().node}.json', 'w', encoding='utf-8') as file:
            json.dump(dict_info_dop, file, indent=4, ensure_ascii=False)
        print_info(dict_info)
        print_dop_info(dict_info_dop)
    elif uname().system == "Linux":
        dict_info = creating_file()
        with open(f'info_{uname().node}.json', 'w', encoding='utf-8') as file:
            json.dump(dict_info, file, indent=4, ensure_ascii=False)
        print_info(dict_info)


if __name__ == "__main__":
    main()

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

Спасибо за внимание. Надеюсь, что данная статья будет кому-то полезной
 
Последнее редактирование:
Мы в соцсетях:

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