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

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

    Скидки до 10%

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

Статья Попытка активации операционной системы от MS с помощью Python

Активация операционной системы Windows, дело сугубо индивидуальное. Кто-то активирует ее с помощью купленных ключей, кто-то, как придется. Есть такое мнение, что политика Microsoft в отношении пиратства довольно лояльна еще и потому, что используя ее продукты у человека появляется привычка. И рано или поздно, он все равно купит лицензионный ключ. А значит, здесь просто коммерческий интерес. Но, речь сейчас не об этом, а о том, как попробовать активировать ОС с помощью Python.

000.jpg


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

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


Что потребуется?

Так как мы не будем хранить в самом скрипте ключи активации, следовательно, их нужно где-то получить. И самым достоверным и надежным источником будет, конечно же, сайт Microsoft. Поэтому, нам нужно будет выполнить запросы к странице, получить ее содержимое, выполнить парсинг и сохранить полученные значения. Для этого нам понадобиться библиотека requests, bs4 и lxml.

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

pip install requests bs4 lxml ping3

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

Python:
from ctypes import windll
from json import dump, load
from os import system
from subprocess import check_output
from sys import executable
from pathlib import Path
from winreg import OpenKey, ConnectRegistry, QueryValueEx, HKEY_LOCAL_MACHINE

from requests import get
from bs4 import BeautifulSoup
from ping3 import ping

Создадим словарь из заголовков для запросов, чтобы сайты, к которым выполняются запросы хотя бы номинально не считали запросы автоматическими.

Python:
headers = {
    'user-agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.160 '
                  'YaBrowser/22.5.3.673 Yowser/2.5 Safari/537.36',
    'referer': 'https://russianblogs.com/',
    'accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,'
              'application/signed-exchange;v=b3;q=0.9 '
}


Получение ключей с сайта MS

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

Python:
    if Path(Path.cwd() / 'keys.json').exists():
        with open('keys.json', 'r', encoding='utf-8') as key:
            return dict(load(key))

    url_list = ['https://docs.microsoft.com/en-us/windows-server/get-started/kms-client-activation-keys',
                'https://docs.microsoft.com/ru-ru/windows-server/get-started/kms-client-activation-keys',
                'https://docs.microsoft.com/en-us/previous-versions/windows/it-pro/windows-server-2012-R2-and-2012/'
                'jj612867(v=ws.11)']

Создадим словарь, куда будем добавлять полученные ключи. Запускаем цикл по страницам, получаем html-код и отправляем в функцию exctract для парсинга. Декодируем весь код, который мы получили в запросе в utf-8. Это нужно для того, чтобы полученные значения отображались корректно. Дело в том, что на некоторых страницах, в ячейках таблиц содержаться сразу же два значения. Название на английском языке, а также кириллицей. В итоге, то, что написано латинскими буквами отображается корректно, а то, что кириллицей — крякозябрами. Именно для этого выполним явную перекодировку. А затем добавим полученные значения в словарь.

Python:
    keys = dict()
    for url in url_list:
        req = get(url=url, headers=headers)
        req.encoding = 'utf-8'
        keys.update(key_exctract(req.text))

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

Python:
    keys.update(dop_key())
    with open('keys.json', 'w', encoding='utf-8') as key:
        dump(keys, key, indent=4, ensure_ascii=False)
    return keys

Python:
def get_kms_key():
    """
    Поверка на наличие файла с ключами. Если есть, возвращаем
    словарь. Если нет, продолжаем код дальше.
    Получение кода страниц по трем адерсам с сайта MS.
    Отправка на обработку, добавление обработанных ключей
    в словарь, получение дополнительных ключей, добавление
    в словарь. Сохранение полученных ключей с json.
    :return: возвращает полученные ключи в словаре.
    """
    if Path(Path.cwd() / 'keys.json').exists():
        with open('keys.json', 'r', encoding='utf-8') as key:
            return dict(load(key))

    url_list = ['https://docs.microsoft.com/en-us/windows-server/get-started/kms-client-activation-keys',
                'https://docs.microsoft.com/ru-ru/windows-server/get-started/kms-client-activation-keys',
                'https://docs.microsoft.com/en-us/previous-versions/windows/it-pro/windows-server-2012-R2-and-2012/'
                'jj612867(v=ws.11)']

    keys = dict()
    for url in url_list:
        req = get(url=url, headers=headers)
        req.encoding = 'utf-8'
        keys.update(key_exctract(req.text))

    keys.update(dop_key())
    with open('keys.json', 'w', encoding='utf-8') as key:
        dump(keys, key, indent=4, ensure_ascii=False)
    return keys


Получение дополнительных ключей

Получение дополнительных ключей ничем особым не отличается. Только лишь значения получаются с GitHub, добавляются в словарь и возвращаются их функции.

Python:
def dop_key():
    """
    Получение дополнительный ключей с GitHub, для ОС
    не найденных на сайте MS. Поиск, добавление в словарь.
    :return: Возвращает словарь с ключами.
    """
    dop_dict = dict()
    url = 'https://raw.githubusercontent.com/SuryaKarmakar/Windows10-ActivationKey/main/win10Active.txt'
    req = get(url=url, headers=headers).text.split("\n")
    for tx in req:
        if 'Home' in tx:
            dop_dict.update({f'Windows 10 {tx.split(":")[0].strip()}': tx.split(":")[1].strip()})
    return dop_dict


Сбор ключей из кода страницы

Создадим функцию key_exctract(html: str). На вход здесь прилетает html-код страницы. Создадим временный словарь, куда будем добавлять полученные ключи. Создадим объект супа, куда передадим полученный код, а также имя парсера, с помощью которого будет строиться dom. Затем выполним поиск необходимых тегов, воспользовавшись функцией find_all.

Python:
    key_temp = dict()
    soup = BeautifulSoup(html, 'lxml')
    find_tables = soup.find('div', class_='content').find_all('table')

Запускаем цикл по полученным тегам. Так как на некоторых страницах в ячейке таблицы два значения, а значит нам как-то нужно их разделить. Между текстом есть тег переноса строки <br/>. Будем делить по этому тегу. Для этого, преобразуем код в строку, удаляем теги таблицы, делим по переносу строки. Так как в таблицах на странице есть посторонний текст, делаем проверку на начало строки, чтобы она начиналась с текста «Windows. И добавляем полученные значения во временный словарь. Если тега переноса строки в ячейке нет, просто забираем значения из таблицы и добавляем в словарь, после чего возвращаем словарь из функции.

Python:
    for table in find_tables:
        tbody = table.find('tbody').find_all('tr')
        for tr in tbody:
            tds = tr.find_all('td')
            if "<br/>" in str(tds[0]):
                name_sys = str(tds[0]).replace("<td>", '').replace("</td>", '').replace(" ", ' '). \
                    replace("\xa0", ' ').split("<br/>")
                key_sys = tds[1].text
                if name_sys[0].startswith("Windows"):
                    key_temp.update({name_sys[0]: key_sys})
                if name_sys[1].startswith("Windows"):
                    key_temp.update({name_sys[1]: key_sys})
            else:
                name_sys = tds[0].text.replace(" ", ' ')
                key_sys = tds[1].text
                if name_sys.startswith("Windows"):
                    key_temp.update({name_sys: key_sys})
    return key_temp

Python:
def key_exctract(html: str):
    """
    Обработка html полученного с сайта и поиск названий ОС,
    которые являюься ключами, а также ключей-активации, которые
    являются значениями ключей.
    :param html: принимает html-текст, полученный с сайта
    :return: возвращает полученный словарь с ключами
    """
    key_temp = dict()
    soup = BeautifulSoup(html, 'lxml')
    find_tables = soup.find('div', class_='content').find_all('table')

    for table in find_tables:
        tbody = table.find('tbody').find_all('tr')
        for tr in tbody:
            tds = tr.find_all('td')
            if "<br/>" in str(tds[0]):
                name_sys = str(tds[0]).replace("<td>", '').replace("</td>", '').replace(" ", ' '). \
                    replace("\xa0", ' ').split("<br/>")
                key_sys = tds[1].text
                if name_sys[0].startswith("Windows"):
                    key_temp.update({name_sys[0]: key_sys})
                if name_sys[1].startswith("Windows"):
                    key_temp.update({name_sys[1]: key_sys})
            else:
                name_sys = tds[0].text.replace(" ", ' ')
                key_sys = tds[1].text
                if name_sys.startswith("Windows"):
                    key_temp.update({name_sys: key_sys})
    return key_temp


Получение списка kms-серверов

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

Для начала делаем запрос на Github, получаем список и делим его по символу переноса каретки на строки. Так как в списке много постороннего текста, выполняем проверку, на начало строки. KMS-сервера отмечены в списке звездочкой в начале. Забираем значение, выполняем пинг, и если он проходит, возвращаем адрес сервера из функции. Если нет, повторяем все снова с другим сервером.

Python:
def kms_load():
    """
    Получение с GitHub списка неофициальных kms-серверов.
    Проверка на работоспособность с помощью ping.
    :return: возвращает первый работоспособный сервер, если серверов
    не найдено, возвращает False.
    """
    url = 'https://gist.githubusercontent.com/mokoshalb/b87326bbb62805e94da72f8d0f73f563/raw/' \
          '3241a530902c63059c6434b38d1c7ade22ba100d/kms.md'
    req = get(url=url, headers=headers)
    for tx in req.text.split("\n"):
        if tx.startswith("*"):
            p = ping(tx[1:].strip(), timeout=2)
            if p != False or p != None:
                return tx[1:].strip()
    return False


Завершение процесса cmd или powershell

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

Выполним поиск процессов с именем «cmd.exe» или «powershell.exe». Если данные процессы будут найдены, получаем их PID и завершаем с помощью команды taskkill.

Python:
def kill_proc():
    """
     Получение списка запущенных процессов. Поиск среди них
     процессов "cmd.exe" или "powershell.exe". Если такие процессы будут найдены,
     они будут автоматически завершены по полученному PID.
    """
    for num, pr in enumerate(check_output('tasklist').decode('cp866').split("\n")):
        if num == 0 or num == 1 or num == 2:
            continue
        try:
            proc_name = pr.split()[0]
            proc_pid = pr.split()[1]
            if 'powershell.exe' in proc_name or 'cmd.exe' in proc_name:
                check_output(f'taskkill /PID {proc_pid} /f', shell=False)
                break
        except IndexError:
            continue


Получение названия операционной системы из реестра

Создадим функцию get_win_name(). Прочитаем название операционной системы из реестра и вернем полученное значение из функции. Для этого откроем необходимую ветку, перейдем к ключу в котором содержится название и получим его значение.

Получение названия из реестра:

Python:
def get_win_name():
    """
    Получение названия ОС из реестра.
    :return: возвращает полученное название.
    """
    return QueryValueEx(OpenKey(ConnectRegistry(None, HKEY_LOCAL_MACHINE),
                                r"SOFTWARE\Microsoft\Windows NT\CurrentVersion"), "ProductName")[0]


Запуск функций активации

Создадим функцию main(). Получаем название операционной системы, а также список ключей. Находим по названию необходимый ключ. Составляем команду для активации, с помощью os.system выполняем ее с полученным ключом. С помощью данной команды мы записываем значение ключа в реестр.

Python:
    print('\nВыполняю попытку активации операционной системы...\n')
    key = get_kms_key()[get_win_name()]
    set_key = r'cscript %windir%\system32\slmgr.vbs /ipk'
    system(f'{set_key} {key}')

Составляем следующую команду. С ее помощью мы запишем значение сервера kms-активации, на который будет обращаться система. Для этого мы получаем сервер, проверяем, не является ли полученное значение False. Если да, выходим из скрипта. Если нет, запускаем команду.

Python:
    set_kms = r'cscript %windir%\system32\slmgr.vbs /skms'
    kms = kms_load()
    if not kms:
        print('Сервера активации не отвечают')
        exit(0)
    system(f'{set_kms} {kms}')

И наконец, выполняем команду активации системы. После чего сразу же не закрываем окно командной строки, а выводим сообщение с просьбой нажать на клавишу Enter.

Python:
    system(r'cscript %windir%\system32\slmgr.vbs /ato')
    input('Нажмите Enter для выхода…')

Python:
def main():
    """
    Запускаются функции, необходимые для активации ОС.
    1. Получение имени ОС, получение ключа по имени;
    2. Установка ключа в систему;
    3. Получение работоспособного kms-сервера;
    4. Установка сервера в систему;
    5. Активация ОС.
    """
    print('\nВыполняю попытку активации операционной системы...\n')   
    key = get_kms_key()[get_win_name()]
    set_key = r'cscript %windir%\system32\slmgr.vbs /ipk'
    system(f'{set_key} {key}')
    set_kms = r'cscript %windir%\system32\slmgr.vbs /skms'
    kms = kms_load()
    if not kms:
        print('Сервера активации не отвечают')
        exit(0)
    system(f'{set_kms} {kms}')
    system(r'cscript %windir%\system32\slmgr.vbs /ato')
    input('Нажмите Enter для выхода…')


Проверка на запуск от имени администратора

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

Python:
if windll.shell32.IsUserAnAdmin():
    """
    Проверка, запущен ли процесс от имени администратора.
    Если нет, перезапуск в cmd.
    Если включен UAC, потребуется подтверждение запуска.
    """
    if __name__ == "__main__":
        main()
else:
    windll.shell32.ShellExecuteW(None, "runas", executable, __file__, None, 1)
    kill_proc()

В данном случае, если у вас включен UAC, потребуется подтвердить запуск.

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

Python:
"""
Небольшой скрипт, который предназначен для обучения активации
операционной системы с помощью Python.
Данный скрипт выполнен в учебных целях и использует данные
полученные из открытых источников.
Требует установки следующих библиотек: pip install requests bs4 lxml ping3
"""

from ctypes import windll
from json import dump, load
from os import system
import subprocess
from sys import executable
from pathlib import Path
from winreg import OpenKey, ConnectRegistry, QueryValueEx, HKEY_LOCAL_MACHINE

from requests import get
from bs4 import BeautifulSoup
from ping3 import ping

headers = {
    'user-agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.160 '
                  'YaBrowser/22.5.3.673 Yowser/2.5 Safari/537.36',
    'referer': 'https://russianblogs.com/',
    'accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,'
              'application/signed-exchange;v=b3;q=0.9 '
}


def key_exctract(html: str):
    """
    Обработка html полученного с сайта и поиск названий ОС,
    которые являюься ключами, а также ключей-активации, которые
    являются значениями ключей.
    :param html: принимает html-текст, полученный с сайта
    :return: возвращает полученный словарь с ключами
    """
    key_temp = dict()
    soup = BeautifulSoup(html, 'lxml')
    find_tables = soup.find('div', class_='content').find_all('table')

    for table in find_tables:
        tbody = table.find('tbody').find_all('tr')
        for tr in tbody:
            tds = tr.find_all('td')
            if "<br/>" in str(tds[0]):
                name_sys = str(tds[0]).replace("<td>", '').replace("</td>", '').replace(" ", ' '). \
                    replace("\xa0", ' ').split("<br/>")
                key_sys = tds[1].text
                if name_sys[0].startswith("Windows"):
                    key_temp.update({name_sys[0]: key_sys})
                if name_sys[1].startswith("Windows"):
                    key_temp.update({name_sys[1]: key_sys})
            else:
                name_sys = tds[0].text.replace(" ", ' ')
                key_sys = tds[1].text
                if name_sys.startswith("Windows"):
                    key_temp.update({name_sys: key_sys})
    return key_temp


def dop_key():
    """
    Получение дополнительный ключей с GitHub, для ОС
    не найденных на сайте MS. Поиск, добавление в словарь.
    :return: Возвращает словарь с ключами.
    """
    dop_dict = dict()
    url = 'https://raw.githubusercontent.com/SuryaKarmakar/Windows10-ActivationKey/main/win10Active.txt'
    req = get(url=url, headers=headers).text.split("\n")
    for tx in req:
        if 'Home' in tx:
            dop_dict.update({f'Windows 10 {tx.split(":")[0].strip()}': tx.split(":")[1].strip()})
    return dop_dict


def get_kms_key():
    """
    Поверка на наличие файла с ключами. Если есть, возвращаем
    словарь. Если нет, продолжаем код дальше.
    Получение кода страниц по трем адерсам с сайта MS.
    Отправка на обработку, добавление обработанных ключей
    в словарь, получение дополнительных ключей, добавление
    в словарь. Сохранение полученных ключей с json.
    :return: возвращает полученные ключи в словаре.
    """
    if Path(Path.cwd() / 'keys.json').exists():
        with open('keys.json', 'r', encoding='utf-8') as key:
            return dict(load(key))

    url_list = ['https://docs.microsoft.com/en-us/windows-server/get-started/kms-client-activation-keys',
                'https://docs.microsoft.com/ru-ru/windows-server/get-started/kms-client-activation-keys',
                'https://docs.microsoft.com/en-us/previous-versions/windows/it-pro/windows-server-2012-R2-and-2012/'
                'jj612867(v=ws.11)']

    keys = dict()
    for url in url_list:
        req = get(url=url, headers=headers)
        req.encoding = 'utf-8'
        keys.update(key_exctract(req.text))

    keys.update(dop_key())
    with open('keys.json', 'w', encoding='utf-8') as key:
        dump(keys, key, indent=4, ensure_ascii=False)
    return keys


def get_win_name():
    """
    Получение названия ОС из реестра.
    :return: возвращает полученное название.
    """
    return QueryValueEx(OpenKey(ConnectRegistry(None, HKEY_LOCAL_MACHINE),
                                r"SOFTWARE\Microsoft\Windows NT\CurrentVersion"), "ProductName")[0]


def kill_proc():
    """
     Получение списка запущенных процессов. Поиск среди них
     процессов "cmd.exe" или "powershell.exe". Если такие процессы будут найдены,
     они будут автоматически завершены по полученному PID.
    """
    for num, pr in enumerate(subprocess.check_output('tasklist').decode('cp866').split("\n")):
        if num == 0 or num == 1 or num == 2:
            continue
        try:
            proc_name = pr.split()[0]
            proc_pid = pr.split()[1]
            if 'powershell.exe' in proc_name or 'cmd.exe' in proc_name:
                subprocess.check_output(f'taskkill /PID {proc_pid} /f', shell=False)
                break
        except IndexError:
            continue


def kms_load():
    """
    Получение с GitHub списка неофициальных kms-серверов.
    Проверка на работоспособность с помощью ping.
    :return: возвращает первый работоспособный сервер, если серверов
    не найдено, возвращает False.
    """
    url = 'https://gist.githubusercontent.com/mokoshalb/b87326bbb62805e94da72f8d0f73f563/raw/' \
          '3241a530902c63059c6434b38d1c7ade22ba100d/kms.md'
    req = get(url=url, headers=headers)
    for tx in req.text.split("\n"):
        if tx.startswith("*"):
            p = ping(tx[1:].strip(), timeout=2)
            if p != False or p != None:
                return tx[1:].strip()
    return False


def main():
    """
    Запускаются функции, необходимые для активации ОС.
    1. Запускается функция поиска и закрытия cmd или powershell;
    2. Получение имени ОС, получение ключа по имени;
    3. Установка ключа в систему;
    4. Получение работоспособного kms-сервера;
    5. Установка сервера в систему;
    6. Активация ОС.
    """
    print('\nВыполняю попытку активации операционной системы...\n')
    key = get_kms_key()[get_win_name()]
    set_key = r'cscript %windir%\system32\slmgr.vbs /ipk'
    system(f'{set_key} {key}')
    set_kms = r'cscript %windir%\system32\slmgr.vbs /skms'
    kms = kms_load()
    if not kms:
        print('Сервера активации не отвечают')
        exit(0)
    system(f'{set_kms} {kms}')
    system(r'cscript %windir%\system32\slmgr.vbs /ato')
    input('Нажмите Enter для выхода...')


if windll.shell32.IsUserAnAdmin():
    """
    Проверка, запущен ли процесс от имени администратора.
    Если нет, перезапуск в cmd.
    Если включен UAC, потребуется подтверждение запуска.
    """
    if __name__ == "__main__":
        main()
else:
    windll.shell32.ShellExecuteW(None, "runas", executable, __file__, None, 1)
    kill_proc()

А на этом, пожалуй, все.

Спасибо за внимание. Надеюсь, что данная информация будет вам полезна
 

Вложения

  • win_akt.py.zip
    3,2 КБ · Просмотры: 200

Maksim_K

One Level
04.03.2022
6
1
BIT
0
😃 Блин! Реально круто!!!
Спасибо огромное за твою статью!!! 🔥👍
 
Мы в соцсетях:

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