Давненько я ничего не постил в блог. Причины разные, это и проблема отыскать интересный материал для блога и лень. Но сегодня нашёл что написать. Это портированный скрипт с VBS для извлечения установочного ключа Windows и других продуктов, как Microsoft Office.

итак, исходный вариант на VBS, который был найден на просторах интернета:

Set WshShell = WScript.CreateObject("WScript.Shell")
strDigitalProductId="HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\DigitalProductId"
strXPKey=GetKey(WshShell.RegRead(strDigitalProductId))
MsgBox "Key:"&strXPKey
Function GetKey(rpk)
    Const rpkOffset=52:i=28
    szPossibleChars="BCDFGHJKMPQRTVWXY2346789"
    Do 'Rep1
        dwAccumulator=0 : j=14
        Do 
            dwAccumulator=dwAccumulator*256 
            dwAccumulator=rpk(j+rpkOffset)+dwAccumulator
            rpk(j+rpkOffset)=(dwAccumulator\24) and 255
            dwAccumulator=dwAccumulator Mod 24
            j=j-1
        Loop While j>=0
    i=i-1 : szProductKey=mid(szPossibleChars,dwAccumulator+1,1)&szProductKey
    if (((29-i) Mod 6)=0) and (i<>-1) then 
    i=i-1 : szProductKey="-"&szProductKey
    End If
    Loop While i>=0 'Goto Rep1
GetKey=szProductKey
End Function

Учитывая мои почти нулевые познания в VBS пришлось сильно повозиться, чтобы понять его работу в VBS и активно сотрудничать с гуглом.

И столкнулся с некоторыми трудностями:

rpk(j+rpkOffset)=(dwAccumulator\24) and 255

вот здесь происходит деление. Но не простое деление, а деление с получением целого числа от частного с отрезанием десятичной части без округления. Возможно в VBS правила округления стандартные, но в PowerShell округление происходит несколько иначе, если у нас число с половинкой, например: 1,5; 5,5; 67,5. В таких случаях PowerShell округляет число до ближайшего чётного числа. Примеры:

[vPodans] [math]::Round(0.5) 0 [vPodans] [math]::Round(1.5) 2 [vPodans] [math]::Round(2.5) 2 [vPodans] [math]::Round(3.5) 4 [vPodans] [math]::Round(4.5) 4 [vPodans] [math]::Round(5.5) 6 [vPodans] [math]::Round(6.5) 6 [vPodans] [math]::Round(7.5) 8 [vPodans] [math]::Round(8.5) 8 [vPodans]

Как видите с использованием математической функции округления вы никогда не получите нечётное число, если округлять такие числа. Есть ещё вариант форматирования строки. Но он при отбрасывании дробной части округляет половинки до бОльшего целого числа (хотя нужно до меньшего, что и делает VBS в данном случае):

[vPodans] (0.5).tostring("F00") 1 [vPodans] (1.5).tostring("F00") 2 [vPodans] (2.5).tostring("F00") 3 [vPodans] (3.5).tostring("F00") 4 [vPodans] (4.5).tostring("F00") 5 [vPodans] (5.5).tostring("F00") 6 [vPodans]

ну и я не нашёл ничего лучше, как написать простенький регексп и им отрезать ненужный хвостик. Суть регекспа будет заключаться в извлечении из строки только цифр начиная от начала строки до первого нечислового символа. Как я уже писал в предыдущем блоге в регулярных выражениях начало строки обозначается знаком возведения в степень – ^. Только числа - \d. Т.к. число может состоять из множества цифр, то я добавил символ умножения – *, чтобы сказать: от нуля и более символов. Получилось вот так:

[vPodans] 3456.356345 -match "^\d*" True [vPodans] $matches Name Value ---- ----- 0 3456 [vPodans] $matches[0] 3456 [vPodans]

я применил свой шаблон к произвольному дробному числу и оно попало под шаблон. Используя особую переменную $matches, которая в виде массива хранит все совпадения оператора –match, я могу извлекать ту часть сроки, которая попала под шаблон. Т.к. $matches у нас массив, то для вставки совпавшей части в код я буду обращаться к нужному элементу этого массива. В моём случае совпадение только одно, поэтому $matches будет массивом из единственного элемента и обращаться к его значению нужно по первому индексу, т.е. $matches[0].

Далее, мы видим оператор And. Здесь я тоже попал в засаду, поскольку подумал, что это аналог –AND в PowerShell. Однако после чтения документации выяснилось, что это Bitwise AND, т.е. побитовый “И”. Следовательно при портировании необходимо использовать не –AND, а –BAND. Разница у них в том, что оба числа преобразовываются в двоичный формат и побитово выполняется операция логического умножения. Подробности здесь: http://msdn.microsoft.com/en-us/library/z0zec0b2(VS.71).aspx.

szProductKey=mid(szPossibleChars,dwAccumulator+1,1)&szProductKey

оператор MID в VBS (как и в древнем досовском бейсике) вырезает часть строки и является аналогом метода Substring(), который есть в PowerShell. Однако тут я жестоко попался на следующее: в PowerShell любая нумерация индексов и символов начиная с нуля. Т.е. чтобы извлечь только первый символ из строки мне нужно указать стартовый индекс ноль - 0:

[vPodans] "here string".substring(0,1) h [vPodans]

но в VBS символы в строках нумеруются начиная с единицы – 1. Те. для моего примера чтобы вырезать первый символ строки в качестве стартовой позиции нужно было указывать не 0, а 1:

string = "here string"
msgbox mid(string,1,1)

Следовательно при портировании скрипта из вышеупомянутой строки убираем  “+1”, который, видимо, был добавлен ввиду особенности нумерации символов строки в VBS. Для кого-то это может показаться пустяком, но для меня это всё было открытием, поскольку я на VBS не написал ни одного скрипта (даже который просто мапит шару при логоне) и его синтаксис для меня достаточно сложен и не всегда понятен.

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

########################################################
# Get-ProductKey.ps1
# Version 1.0
#
# Retrieve Windows XP/2003/Vista/2008 setup key
#
# Note: not works on Windows Vista/2008 activated by KMS Server # Note: translated from VBS script
# #
Vadims Podans (c) 2009 # http://www.sysadmins.lv/ ######################################################## function Get-ProductKey { $rpk = (Get-ItemProperty "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\" -Name DigitalProductId).DigitalProductId $i = 28 $rpkOffset = 52 $PossibleChars = "BCDFGHJKMPQRTVWXY2346789" do { $Accumulator = 0 $j = 14 do { $Accumulator = $Accumulator * 256 $Accumulator = $rpk[$j + $rpkOffset] + $Accumulator $Accumulator / 24 -match "^\d*" | Out-Null $rpk[$j + $rpkOffset] = $matches[0] -band 255 $Accumulator = $Accumulator % 24 $j-- } while ($j -ge 0) $i-- $ProductKey = $PossibleChars.Substring($Accumulator, 1) + $ProductKey if ((29 - $i) % 6 -eq 0 -and $i -ne -1) { $i-- $ProductKey = "-" + $ProductKey } } while ($i -ge 0) $ProductKey }

Примечание: Данный скрипт не будет возвращать установочный ключ для VLK систем Windows Vista и Windows Server 2008, которые были активированы через KMS сервер. Здесь ключ будет показан только для OEM и коробочных версий. На сколько я знаю в данном случае (как у меня на нотебуке с Vista Business) при активации через KMS ключ не хранится в системе и скрипт будет возвращать буквы B:

[vPodans] Get-ProductKey BBBBB-BBBBB-BBBBB-BBBBB-BBBBB [vPodans]

объяснение этому здесь: http://www.rjlsoftware.com/support/faq/sa.cfm?q=289&n=81

з.ы. ссылка не показывается в IE8 RC1, только верхний баннер :'( Поэтому пришлось совершить грех и воспользоваться мозиллой :)

Так же можно получать установочные ключи не только для самой ОС, но и для приложений тоже (разработки Microsoft, разумеется), как Microsoft Office. Для этого достаточно изменить ветку реестра на:

HKLM\Software\Microsoft\Office\11.0\Registration\{GUID}\DigitalProductID

Этот путь будет справедлив для Office 2003. Где хранит этот ProductID Office 2007 я не нашёл у себя. Но вообще мысль понятна, в каком направлении искать :)

Удачи!

Thursday, February 05, 2009 7:31:53 PM (FLE Standard Time, UTC+02:00)   Comments [1]    

 

Saturday, May 30, 2009 10:07:09 PM (FLE Daylight Time, UTC+03:00)
мне сегодня на почту Aleksander Ignatenko прислал вариант скрипта с использованием WMI, который позволяет получать установочные ключи с удалённых машин. Вот сам скрипт:

function Get-ProductKey {
param ($strComputer)

$hklm = 2147483650
$key = "SOFTWARE\Microsoft\Windows NT\CurrentVersion\"
$value = "DigitalProductId"
$wmi2 = "\\"+$strComputer+"\root\default:stdRegProv"
$wmi = [wmiclass]$wmi2
$rpk = ($wmi.GetBinaryValue($hklm,$key,$value)).uValue

# $rpk = (Get-ItemProperty "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\" -Name DigitalProductId).DigitalProductId
$i = 28
$rpkOffset = 52
$PossibleChars = "BCDFGHJKMPQRTVWXY2346789"
do {
$Accumulator = 0
$j = 14
do {
$Accumulator = $Accumulator * 256
$Accumulator = $rpk[$j + $rpkOffset] + $Accumulator
$Accumulator / 24 -match "^\d*" | Out-Null
$rpk[$j + $rpkOffset] = $matches[0] -band 255
$Accumulator = $Accumulator % 24
$j--
} while ($j -ge 0)
$i--
$ProductKey = $PossibleChars.Substring($Accumulator, 1) + $ProductKey
if ((29 - $i) % 6 -eq 0 -and $i -ne -1) {
$i--
$ProductKey = "-" + $ProductKey
}
} while ($i -ge 0)
$ProductKey
}
OpenID
Please login with either your OpenID above, or your details below.
Name
E-mail
(will show your gravatar icon)
Home page

Comment (HTML not allowed)  

Enter the code shown (prevents robots):

Live Comment Preview
 · 

All content © 2008 - 2012, Vadims Podāns
"Spaces" Theme provided by: Vadims Podāns
About


E-mail - Send mail to the author(s)
Live Messenger -
For english language visitors
Библиотека
Календарик
<February 2012>
SunMonTueWedThuFriSat
2930311234
567891011
12131415161718
19202122232425
26272829123
45678910

Карта расположения посетителей
Favorites





Fan list



Disclaimer
Вся информация на сайте предоставляется на условиях «как есть», без предоставления каких-либо гарантий и прав.

При использовании материалов c данного сайта ссылка на оригинальный источник обязательна.
Protected by Copyscape Online Plagiarism Scanner