Как я уже писал в первой части статьи, информация — это такая штука, которой желали бы обладать многие. Ее никогда не бывает много. И не зря же есть высказывание одного, всем известного товарища, что информация правит миром. И это на самом деле так. В наш цифровой век умение собирать и анализировать разнообразную информацию цениться очень высоко. Но, это уже не совсем наша тема. По крайней мере пока. Это уже OSINT. А мы продолжим добывать информацию о системе с помощью Питона.
Давайте перейдем к сбору. Я озаботился тем, чтобы поискать способы получения более детальной информации о железе. И более удобным способом мне показался тот, в котором можно было использовать командную строку и команды, которые в ней выполняются, а точнее их вывод. Тем более, что командная строка, как на Windows, так и на Linux это очень мощный инструмент, который стал таким, наверное, в силу того что именно с него все и начиналось. И он, а точнее команды, которые в нем выполняются – это основа всех основ. А графический интерфейс подоспел уже позже.
Да и то, когда системы из разряда гиковских стали переходить в массовый сектор, где пользователям важна была не эффективность, а удобство использования. Но, тем не менее, командная строка еще живет и, думаю, что в ближайшем будущем на покой не уйдет точно. Да, она будет видоизменяться, одеваться в новые оболочки, но суть ее останется прежней – мощь и скорость. Тут главное уметь этим всем пользоваться. Но, все это лирика. Давайте приступать к делу.
Допишем код из предыдущей статьи. В этот раз нам понадобиться дополнить секцию импорта еще одной библиотекой: subprocess. Давайте ее импортируем с помощью import subprocess. В полном виде, теперь, блок импорта будет выглядеть так:
А теперь нужно создать функцию, которая и будет отвечать за сбор дополнительных данных. Я ее так и назвал: def win_dop_info(dict_info). И добавил win, чтобы было понятно, что данная функция будет использоваться только в Windows. Если вы читали первую статью, то там я упоминал о том, что не зря сделал определение операционной системы на старте программы. Оно сделано именно в этих целях, чтобы запускать в разных операционках разные функции.
Да, совсем забыл упомянуть. Тут еще понадобиться небольшая библиотека, а точнее ее часть, которая и будет отвечать за извлечение ключа активации: windows_tools.product_key. Устанавливается она командой:
Вроде бы ничего необычного. И данная библиотека есть на PyPi. Но вот у меня PyCharm упорно не хотел ее видеть. Я все проклял. Уж так я его и эдак. И пока я не выбрал системный интерпретатор питона, библиотека не была доступна для использования. Тем не менее, ее нужно установить. Да, стоит упомянуть то, что на тестовой машине установка этой библиотеки прошла без сучка и задоринки и программа успешно отработала то, что ей надо. И я грешил на свою машину в первую очередь. Наверное, это мои, локальные глюки. Как говорить, доигрался. Ну да ладно.
Впоследствии я разобрался, что если устанавливать файлы с помощью pip, то они могут быть не доступны в том компиляторе, который вы используете в своем проекте. И в этом случае нужно использовать системный интерпретатор. Но, в этом случае могут стать недоступны библиотеки, которые вы устанавливали с помощью PyCharm и их придется переустанавливать. Решение тут одно. Для этой библиотеки доступна установка с помощью pip, а значит и все остальные модули желательно устанавливать тем же образом. И использовать после установки системный интерпретатор питона в своем проекте.
Импортируем эту библиотеку прямо в функции. Сделано это для того, чтобы она оставалась невидимой для Linux.
И теперь приступаем к сбору информации. Есть такая утилита WMIC. При вызове справки по данной утилите пишется, что она устарела. Но, это не беда. Она работает. Да еще как.
Вот ее мы и будем использовать и запускать с помощью subprocess.
Начнем с информации о материнской плате. Я поковырялся в параметрах и пришел к выводу, опытным путем, что получать вывод из всех опций достаточно бесполезно, так как некоторые не особо понятны, да и порою просто выводят пустое значение. Определяем переменную, в которую помещаем значение «WMIC BASEBOARD GET Manufacturer /VALUE» и тут же делим его с помощью split(). Это нужно для того, чтобы поместить значения в subprocess. В теории, можно было бы разделить значения прямо в функции, но, это выглядит совсем уж не эстетично.
И после этого запускаем subprocess.check_output с нужной командой. Тут же и обрезаем вывод. Чтобы то, что мы получаем выглядело хорошо.
Пока что добавлять значения в словарь мы не будем, до определенного этапа. После добавим все разом и будем двигаться дальше. А пока вот код запускаемых команд:
А теперь небольшие пояснения. Первая команда, которую мы рассматривали выше, получает название производителя материнской платы. Команда: «WMIC BASEBOARD GET Product /VALUE» модель материнской платы. Ну и так далее. Вот небольшой список с пояснениями по командам:
Тут можно покопаться и при желании получить информации намного больше. Но, это нужно тщательно фильтровать и разобраться в каждом параметре. А теперь добавим данную часть в словарь. Для этого снова выполним проверку есть ли тот ключ, который мы хотим добавить в словаре. Если его нет, то добавляем. И уже в этот ключ, также с проверками, добавляем собранную ранее информацию.
Итак, уже что-то есть. И тут информации по железу гораздо больше, а можно сказать даже намного, чем в той функции, что мы сделали в прошлой статье. Но, тем не менее, обе они нужны и важны. Так как дополняют друг друга. А нам нужно двигаться дальше. И собрать еще информации.
Теперь переходим к дискам. Что меня тут заинтересовало в первую очередь? Название модели. Это, можно сказать, отправная точка, с которой и будем двигаться дальше.
Получаем информацию о модели:
Здесь мы создаем словарь, в который будем складывать названия, для дальнейшего использования. После чего в цикле перебираем вывод, чтобы с помощью условий отфильтровать только нужные значения и записываем в словарь. Цикл нужен для фильтрации и перебора, так как дисков может быть несколько. Да и функция возвращает много мусора, который приходиться пилить на списки и после их перебирать. Но, тем не менее, результат получается.
А дальше получаем информацию о серийном номере жесткого диска. Именно к нему привязываются лицензии некоторых программ. Я помню, когда пытался заниматься трейдингом, то покупал лицензию эмулятора торгового терминала, уж не помню его названия. Так вот там лицензия привязывалась к серийному номеру жесткого. И перенести прогу на другой комп было той еще задачей. Нужно было повторно запрашивать лицензию, что занимало некоторое время. И тогда мне приходилось клонировать систему и разворачивать в VirtualBox, чтобы пользоваться программой на другом компьютере.
Здесь все то же самое, что и в предыдущем коде. Получаем вывод, фильтруем и перебираем. А полученные значения складываем в список.
Теперь, когда значения получены, а именно модель и серийный номер, нужно эти данные объединить и поместить в словарь. Это мы и делаем с помощью простого цикла, в котором перебираем значения словаря по длине одного из них, так как их длина одинакова. По количеству дисков в системе. Создаем словарь и записываем значения.
Дальше получаем версию прошивки. Здесь тоже значения складываются в список, так как их может быть больше одного. А после перебираются и записываются в словарь. Хотя, я подумал, что можно было бы пропустить финт с укладывание значений в список и сразу же добавить из в словарь еще на этапе получения. Просто эта «гениальная» мысль пришла мне несколько позже, при получении других значений. А данный код я оставил так как есть. Ибо он тоже имеет право на существование, хотя бы в качестве «индийского» кода.
Дальше выдергиваем цифровую подпись дисков. И алгоритм действий такой же, как и при получении предыдущих значений.
Теперь получаем информацию о разделах. Для начала о их имени. То есть, некоторые пользователи переименовывают разделы, чтобы указать, что на данном диске хранятся, к примеру, фильмы. Вот именно эти значения мы сейчас и получим. Если же значения не будет, а такое тоже может быть, это когда у диска нет названия и в системе он отображается как «Локальный диск…», запишем, что он просто диск. Ну и добавим все в словарь.
И последнее, что мы узнаем о разделах, это серийный номер тома. Алгоритм получения тот же. Отличается только команда для получения данных.
А теперь пришла очередь оперативной памяти. Получим ее форм-фактор. То есть, сколько слотов задействовано и какого объема. Ну, это насколько я понял. Тут я могу ошибаться, конечно. Потому, надо по этой команде еще поковыряться. Тем не менее, получаем его и записываем в словарь. Информации мало не бывает.
Теперь выдергиваем производителя оперативки. Скажем так, тут не особо много информации удалось получить. Но, хоть что-то. Думаю, что есть другой способ получения данной информации. Возможно, из реестра. Тут надо разобраться. А может быть с помощью другой команды. Эта же команда показывает какие-то отрывочные сведения, но тем не менее, понять кто производитель можно. По крайней мере у меня одна планка показала производителя. А вторая тоже показала. Но какой-то цифровой набор. Может быть потому, что она от AMD? )
Получаем инвентарный номер. По крайней мере я перевел это так. И нет, это не серийный номер. Так как он получается далее. Тем не менее, мы его забираем. Пригодиться.
А вот теперь получаем серийный номер планок или планки оперативки. Кстати, похоже, что инвентарный и серийный номер, это именно те циферки, набрав которые в поисковике можно получить информацию о планке оперативной памяти.
Теперь пришла очередь узнать частоту оперативной памяти. Кстати, это будет именно так частота, которую максимально поддерживает чипсет. А не та, что поддерживает планка оперативки.
Ну вот, пришла очередь сетевых адаптеров. С помощью этой команды мы узнаем название модели адаптера. Но, тут нужно понимать, что в выдачу попадают как реальные, так и виртуальные адаптеры, которые созданы системой для различных взаимодействий с сетью и различными устройствами. Ну и адаптеры виртуальных машин.
Теперь получаем GUID сетевых адаптеров. Это глобальный уникальный идентификатор. То есть, он жестко привязан к конкретному устройству, а следовательно, представляет собой важный элемент в цифровом следе пользователя.
А теперь получаем информацию о дате установки операционной системы. Надо сказать, что в выводе у нее не особо удобный формат. Но достаточно легко читаемый. Поэтому я просто вывел с помощью срезов дату и время установки. То есть, дату в формате, к примеру, 20220424 надо читать справа налево. То есть, 24 апреля 2022 года. А вот время, 092804, уже слева направо. Просто надо делить все по два символа. То есть, в примере 09 часов, 28 минут и 04 секунды.
Теперь получаем серийный номер системы. Серийный номер и номер лицензии это не одной и то же. Вот код для его получения.
Дальше идет идентификатор клиентской машины. Он тоже пригодиться, так сказать для фингерпринта.
А вот теперь получаем лицензию Windows. В данном коде считывается значение из UEFI, если оно в нем есть. И выводиться в терминал. А также записывается в словарь. Если значения в UEFI нет, считываем ключ из реестра с помощью библиотеки. В принципе, можно было бы его получить из реестра самостоятельно и после расшифровать. Благо инструкций для этого полно. Но, зачем изобретать велосипед, если его уже изобрели до меня. А потому, вот:
Но, если вы подумали, что это все, то нет, это не так. Просто мне попались команды именно в этом порядке. И я подумал, что какая разница то? ) Получим информацию о принтерах. Узнаем их количество, в том числе и те, которые используются для сохранения документов в PDF, то есть виртуальные. А также название.
А вот теперь, последнее значение, которое мы получим с помощью команд. Это значение временной зоны. То есть, смещение времени от Гринвича на компьютере, а также название города, в котором данная зона идентифицирована.
После возвращаем уже дополненный словарь для дальнейшей работы.
Вы еще не устали? Если нет, то давайте продолжим. Осталось уже совсем немного. И добьем скрипт до текущего логического завершения. Что нам еще осталось сделать? Вывести полученные значения в терминал. Это, конечно, не обязательно, а потому я вынес все это дело в отдельную функцию, как и предыдущую функцию печати получаемых общих значений. Для того, чтобы можно было исполнение данных функций просто закомментировать.
Создадим функцию печати новых значений: print_dop_info(dict_info_dop). На вход она получает словарь с новыми значениями. Для того, чтобы вытащить из него новые и распечатать в терминал. Ну буду подробно ее описывать, так как тут все более-менее понятно. В цикле получаются значения и с помощью условий производиться выборка нужных и их вывод в терминал. На выходе функция ничего не возвращает. Да и нечего, собственно.
Здесь я не стал заморачиваться с выводом описаний, так как по выводимым значениям и так все понятно. Но, при необходимости данный код можно дополнить, дописав туда описание.
И наконец функция main(). Она тоже притерпела небольшие изменения. В нее было добавлено сохранение данных из собранного словаря в JSON, а также раздельная функция печати. Причем, данные сначала сохраняются, а уже потом выводятся в терминал. Ну так, на всякий случай.
И да, изменения здесь коснулись и блока с вызовом функций для Linux. В частности, запись значений в файл. Она была убрана из функции получения данных и перенесена сюда.
Ну и на этом этапе можно завершить данную часть получения данных. В следующих статьях я постараюсь расширить функционал сборщика. А теперь вывод из командной строки Windows. Код для Linux не изменился. И потому, вывод у него будет такой же, как и в предыдущей статье.
Кстати, как и раньше для запуска данного кода не требуются права администратора. Все команды выполняются из-под обычного пользователя без повышения привилегий.
Спасибо за внимание. Надеюсь, что данная статья будет кому-то полезной
Давайте перейдем к сбору. Я озаботился тем, чтобы поискать способы получения более детальной информации о железе. И более удобным способом мне показался тот, в котором можно было использовать командную строку и команды, которые в ней выполняются, а точнее их вывод. Тем более, что командная строка, как на 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. При вызове справки по данной утилите пишется, что она устарела. Но, это не беда. Она работает. Да еще как.
Вот ее мы и будем использовать и запускать с помощью 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 не изменился. И потому, вывод у него будет такой же, как и в предыдущей статье.
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()
Кстати, как и раньше для запуска данного кода не требуются права администратора. Все команды выполняются из-под обычного пользователя без повышения привилегий.
Спасибо за внимание. Надеюсь, что данная статья будет кому-то полезной
Последнее редактирование: