Не раз сталкивался с необходимостью узнать текущий ключ, использованный при установке Windows или MS Office - как правило, когда "по медицинским показаниям" требуется переустановить систему, а OEM-наклейка на корпусе затёрта до полной нечитаемости, а электронный ключ от Office где-то затерялся вместе с телефоном, на который он пришёл в виде СМС (одно время на терминалах Quiwi можно было купить Home-версию по очень привлекательной цене - за давностью лет не помню, но чуть ли не за 300 рублей) - что делать?
Ответ существовал всегда - есть много платного, а можно найти и бесплатный инструментарий, позволяющий помимо прочего, узнать и ключи установленных продуктов, но далеко не всегда оно есть под рукой, а скачивать десятки мегабайт какого-нибудь мультидиагностического пакета ради считывания 25 букв - как-то избыточно, ну а скачивая какой-нибудь маленький "восстановитель ключа" довольно высок риск поймать зловреда...Set WshShell = CreateObject("WScript.Shell")
regKey = "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\"
DigitalProductId = WshShell.RegRead(regKey & "DigitalProductId")
Win8ProductName = "Windows Product Name: " & WshShell.RegRead(regKey & "ProductName") & vbNewLine
Win8ProductID = "Windows Product ID: " & WshShell.RegRead(regKey & "ProductID") & vbNewLine
Win8ProductKey = ConvertToKey(DigitalProductId)
strProductKey ="Windows 8 Key: " & Win8ProductKey
Win8ProductID = Win8ProductName & Win8ProductID & strProductKey
InputBox "Product Key", "Product Key", Win8ProductKey
MsgBox(Win8ProductID)
Function ConvertToKey(regKey)
Const KeyOffset = 52
isWin8 = (regKey(66) \ 8) And 1
regKey(66) = (regKey(66) And &HF7)
j = 24
Chars = "BCDFGHJKMPQRTVWXY2346789"
Do
Cur = 0
y = 14
Do
Cur = Cur * 256
Cur = regKey(y + KeyOffset) + Cur
regKey(y + KeyOffset) = (Cur \ 24)
Cur = Cur Mod 24
y = y -1
Loop While y >= 0
j = j -1
winKeyOutput = Mid(Chars, Cur + 1, 1) & winKeyOutput
Last = Cur
Loop While j >= 0
If (isWin8 = 1) Then
keypart1 = Mid(winKeyOutput, 2, Last)
insert = "N"
winKeyOutput = Replace(winKeyOutput, keypart1, keypart1 & insert, 2, 1, 0)
If Last = 0 Then winKeyOutput = insert & winKeyOutput
End If
a = Mid(winKeyOutput, 1, 5)
b = Mid(winKeyOutput, 6, 5)
c = Mid(winKeyOutput, 11, 5)
d = Mid(winKeyOutput, 16, 5)
e = Mid(winKeyOutput, 21, 5)
ConvertToKey = a & "-" & b & "-" & c & "-" & d & "-" & e
End Function
Источник: http://winitpro.ru/index.php/2012/10/12/kak-uznat-klyuch-windows-8/ (с незначительными доработками)
Достоинства:
- нет необходимости доустанавливать какие-либо пакеты - VBS есть в системе по умолчанию;
- прозрачный, легко проверяемый на отсутствие троянов и т.п. код.
- не читает корпоративные ключи KMS - их никто не читает, т.к. они вроде не хранятся локально, а там, где они используются, не бывает необходимости "восстанавливать" их из реестра;
- не читает ключи, зашитые в UEFI/BIOS - честно говоря, я сам пока недопонимаю как их можно читать.
2. Чтение ключа Office (python):
# http://code.google.com/p/msoffice-product-key-decoder/
# Designed for use with python 2.6+ (not for 3.x)
import sys
import string
import math
import _winreg as wr
#b24chrs = (string.digits + string.ascii_uppercase)[:24]
generic_b24chrs = '0123456789ABCDEFGHIJKLMN'
code_len = 25 # encoded key length (user-readable key)
bin_len = 15 # binary key length
regkey_idx = 52 # start of key in DPID for 2003, 2007
regkey_idx_2010 = 0x328 # start in DPID for 2010
b24chrs = 'BCDFGHJKMPQRTVWXY2346789'
reg_root = r'Software\Microsoft\Office'
def chunks(l, n):
""" Yield successive n-sized chunks from l.
"""
for i in xrange(0, len(l), n):
yield l[i:i+n]
def b24encode(input, outlen=None, chrmap=None):
# The number of coded characters to actually generate can't be
# determined soley from the input length, but we can guess.
if outlen is None:
# each base24 code char takes ~4.585 bits (ln24 / ln2)
outlen = int(math.ceil(8*len(input) / 4.585))
# Use default character mapping [0-9A-N] if none provided
if chrmap is None:
chrmap = generic_b24chrs
input = [ord(i) for i in input[::-1]]
'''
# takes less memory (does it piecewise), but more complex
decoded = []
for i in range(0,encoded_chars + 1)[::-1]:
r = 0
for j in range(0,15)[::-1]:
r = (r * 256) ^ input[j]
input[j] = r / 24
r = r % 24
print b24chrs[r]
decoded = decoded.append(b24chrs[r])
return decoded[::-1]
'''
# simple, but eats a ton of memory and probably time if the
# encoded string is large
enc = 0
for i in input:
enc = enc * 256 + i
dec = []
for i in range(outlen):
dec.append(chrmap[enc % 24])
enc = enc // 24
dec.reverse()
return ''.join(dec)
def b24decode(input, chrmap=None):
# Use default character mapping [0-9A-N] if none provided
if chrmap is None:
chrmap = generic_b24chrs
# clean invalid characters from input (e.g. '-' (dashes) in product key)
# and map to \x00 through \x23.
rmchrs = []
for i in xrange(256):
if not chr(i) in chrmap:
rmchrs.append(chr(i))
tt = string.maketrans(chrmap, ''.join([chr(i) for i in xrange(24)]))
input = input.translate(tt, ''.join(rmchrs))
encnum = 0
for cc in input:
encnum *= 24
encnum += ord(cc)
enc = []
while encnum:
enc.append(encnum % 256)
encnum = encnum // 256
return ''.join([chr(i) for i in enc])
def msoKeyDecode(regkey, version=None):
'''Decodes a registry key value, by extracting product key
from bytes 52-66 and decoding.
Office 2010 (14.0) appears to store the key at 0x328 to 0x337 in
DPID. The "Registration" tree is different (cluttered) versus
other versions, and the DPID value is (exactly) 7 times longer than
before (1148 bytes, up from 164).
Tested with a 2010 full suite and a trial of Visio.
Parameters:
- regkey is a string containing the contents of "DigitalProductID"
- version is the decimal version number given by the key directly
under the "Office" key root
'''
if version is None:
version = 11 # (default 2003, 2007 appears to be compatible.)
if float(version) < 14:
enckey = regkey[regkey_idx:regkey_idx+bin_len]
else:
enckey = regkey[regkey_idx_2010:regkey_idx_2010+bin_len]
deckey = b24encode(enckey, code_len, chrmap=b24chrs)
return '-'.join(list(chunks(deckey,5)))
def SubKeys(key):
i = 0
while True:
try:
subkey = wr.EnumKey(key, i)
yield subkey
except WindowsError: # [Error 259] No more data is available
break
i += 1
def KeyValues(key):
i = 0
while True:
try:
value = wr.EnumValue(key, i)
yield value
except WindowsError: # [Error 259] No more data is available
break
i += 1
def main(argv=None):
'''Scans local Microsoft Office registry keys for DigitalProductID values
and encodes the binary data in base24.
Note: The given "Name:" of Office 2010 products is incorrect
(may just provide a single program name), though the Product Key
should be valid.
'''
if argv is None:
argv = sys.argv
mso_root = wr.OpenKey(wr.HKEY_LOCAL_MACHINE, reg_root)
product_head = "Product Name"
dpid_head = "Digital Product ID (key encoded in base24)"
prod_keys = []
for subkey in SubKeys(mso_root):
# subkey always observed to be a version number (11.0, 12.0, 14.0...)
# where a DPID will be found.
for sub2key in SubKeys(
wr.OpenKey(mso_root, subkey)):
# sub2key always observed to be "Registration" when DPID is found
for sub3key in SubKeys(
wr.OpenKey(wr.OpenKey(mso_root, subkey), sub2key)):
# sub3key often some UUID ending in 0F:F1:CE
dpid_found = False
for keyvalue in KeyValues(
wr.OpenKey(wr.OpenKey(wr.OpenKey(
mso_root,
subkey),
sub2key),
sub3key)):
if keyvalue[0] == 'DigitalProductID':
dpid_found = True
dpid = keyvalue
if keyvalue[0] == 'ProductName':
name = keyvalue
if dpid_found:
#print ("Product Name: %s\n"
# " Key: %s\n") % \
# (name[1],
# msoKeyDecode(dpid[1],subkey))
#print rf.format(name[1], msoKeyDecode(dpid[1],subkey))
prod_keys.append((name[1], msoKeyDecode(dpid[1],subkey)))
rf = "{0:<%i} {1:<}" % (max([len(i[0]) for i in prod_keys]) + 3)
print rf.format(product_head, dpid_head)
print rf.format('-' * len(product_head),'-' * len(dpid_head))
for prod_key in prod_keys:
print rf.format(*prod_key)
if __name__ == "__main__":
sys.exit(main())
Источник: http://code.google.com/p/msoffice-product-key-decoder/
Недостатки:
- необходимо наличие интерпретатора python;
- автор скрипта оставил много лишнего кода (b24decode, закомментированные куски и т.п.).
Достоинства:
- читает ключи Office 2000-2010;
- позволяет лучше понять принцип хранения и извлечения ключей.
Комментариев нет:
Отправить комментарий