sinsizer
Goto Top

Base24 Algorithmus decodieren mit Batch?

Hallo,

wie der Titel schon sagt habe ich ein Verständnissproblem mit dem Base24 Algorithmus.
Ziel ist es, mit reinem Batch, den Microsoft Product Key zu decodieren.

Es gibt schon genügend Programme die das machen und auch Codes in Powershell und VBScript.

Hier mal ein Beispiel in VBScript:

 
Set WshShell = CreateObject("WScript.Shell")  
msgbox ConvertToKey(WshShell.RegRead("HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\DigitalProductId")), 64, "Windows Product Key"  
 
Function ConvertToKey(Key)
    Const KeyOffset = 52
    i = 28
    Chars = "BCDFGHJKMPQRTVWXY2346789"  
    Do
        Cur = 0
        x = 14
        Do
            Cur = Cur * 256
            Cur = Key(x + KeyOffset) + Cur
            Key(x + KeyOffset) = (Cur \ 24) And 255
            Cur = Cur Mod 24
            x = x -1
        Loop While x >= 0
        i = i -1
        KeyOutput = Mid(Chars, Cur + 1, 1) & KeyOutput
        If (((29 - i) Mod 6) = 0) And (i <> -1) Then
            i = i -1
            KeyOutput = "-" & KeyOutput  
        End If
    Loop While i >= 0
    ConvertToKey = KeyOutput
End Function

Leider verstehe ich die Funktion nicht und würde mich freuen wenn mir die jemand etwas genauer erklären könnte.
Kenne mich mit VBScript noch nicht aus. (Kämpfe noch mit Batch face-wink)

Auf Wunsch kann ich noch ein alternatives VBScript und ein Powershell Script posten wenn das weiter hilft.

So siehts in Batch bis jetzt aus um den Key aus der Registry zu lesen :

for /f "tokens=3 delims= " %%a in ('reg query "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion" /v DigitalProductId') do set keyhex=%%a  
set keyhex=%keyhex:~104,30%

Danke

Content-Key: 178418

Url: https://administrator.de/contentid/178418

Printed on: April 20, 2024 at 03:04 o'clock

Member: pieh-ejdsch
pieh-ejdsch Jan 05, 2012 at 09:44:21 (UTC)
Goto Top
moin sinsizer,

meiner Ansicht nach hat es gar keinen Sinn den Algorithmus aus einer VBS 1:1 in eine Batch zu übertragen.

Das auslesen des Keys erfolgt ja auf eine Art wie es in "Base24" (wobei die 24 nur die Anzahl der zu verwendeten Zeichen beschreibt) gemacht wird. In den Dokumentationen über "Base16"; "Base 32"; "Base 32hex" oder "Base 64" etc. wird die genaue Vorgehensweise beschrieben.
Rechnen in Batch ist auch schon etwas anders als in VBS.
Auf jeden Fall musst Du erst den Base... Algorithmus kennen um den Batch entwerfen zu können.

Gruß Phil
Member: sinsizer
sinsizer Jan 05, 2012 at 10:52:05 (UTC)
Goto Top
Also kann ich, nach verstandenem Base16 oder/und Base32, das Wissen auf Base 24 übertragen? Oder findet dort noch irgendetwas anderes statt?
Aufgrund meiner fehlenden VBS Kenntnisse hab ich Probleme die Funktion zu verstehen.
Die Rechnung wird in Batch bestimmt etwas anders aussehen. Dort stehen aber auch Bitweise Operatoren und Modulo zur Verfügung.

Es ist wohl Sinnvoll wenn ich mich nach Batch mal mit VBS beschäftige. face-smile
Member: rubberman
rubberman Jan 05, 2012 at 22:14:31 (UTC)
Goto Top
Hallo zusammen.

Ich habe mich zwar nie mit einem Base24 Algorithmus oder Ähnlichem beschäftig, die "Übersetzung" nach Batch ist aber relativ simpel. Vielleicht hilft es beim Verständnis.

@echo off &setlocal
if "%~1"==":doWhile" call :doWhile  

setlocal EnableDelayedExpansion
:: HEX String lesen
for /f "tokens=3" %%i in ('reg query "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion" /v "DigitalProductId"') do set "hex=%%i"  

:: Länge des HEX Strings
set "str=A%hex%"  
set "len=0"  
for /l %%i in (12,-1,0) do (
    set /a "len |= 1 << %%i"  
    for %%j in (!len!) do if "!str:~%%j,1!"=="" set /a "len &= ~1 << %%i"  
)

:: Pseudo-Array anlegen
set /a "len -= 2"  
for /l %%i in (0,2,%len%) do (
  set /a "n = %%i / 2"  
  set /a "Key_!n! = 0x!hex:~%%i,2!"  
)

:: Do While simulieren
for /f %%K in ('cmd /c "%~f0" :doWhile') do (endlocal &set "WinProdKey=%%K")  

echo Windows Product Key: %WinProdKey%
echo(
pause
goto :eof

:doWhile
setlocal EnableDelayedExpansion
set "KeyOffset=52"  
set "Chars=BCDFGHJKMPQRTVWXY2346789"  
set "i=28"  
for /l %%# in (0) do (
  set "Cur=0"  
  for /l %%x in (14,-1,0) do (
    set /a "Cur *= 256 , el = KeyOffset + %%x"  
    for %%j in (!el!) do (
      set /a "Cur = !Key_%%j! + Cur , Key_%%j = (Cur / 24) & 255 , Cur %%= 24"  
    )
  )
  set /a "i -= 1 , z = (29 - i) %% 6"  
  for %%j in (!Cur!) do set "KeyOutput=!Chars:~%%j,1!!KeyOutput!"  
  if !z!==0 if !i! neq -1 (
    set /a "i -= 1"  
    set "KeyOutput=-!KeyOutput!"  
  )
  if !i! lss 0 (echo !KeyOutput!&exit)
)

Grüße
rubberman
Member: sinsizer
sinsizer Jan 06, 2012 at 09:45:59 (UTC)
Goto Top
Super! Vielen Dank für die Übersetztung.

Auf dem Papier teile ich den Wert durch die gewünschte Basis, also 24, und erhalte einen Rest. Der Rest gibt den Wert im neuen Zahlensystem an.
Das Ergebniss teile ich solang bis der Rest 0 ist. So erhält man zum Schluss das Ergebniss mit neuer Basis.
(Wenn ich das richtig verstanden hab face-smile)

Leider blick ich bei der Schleife trotzdem noch nicht ganz durch.

for /l %%# in (0) do (==============================================unendliche Schleife bis exit ausgelöst wird
set "Cur=0" =====================================================aktuelle Position vielleicht ????
for /l %%x in (14,-1,0) do ( ==========================================Schleife um die 15 Byte einzeln zu durchlaufen
set /a "Cur *= 256 , el = KeyOffset + %%x"==============================?????? 0*256 ??????, el = Position des entsprechenden Byte
for %%j in (!el!) do (===============================================Schleife für einzel Byte umrechnung
set /a "Cur = !Key_%%j! + Cur , Key_%%j = (Cur / 24) & 255 , Cur %%= 24" ==== ???????? "Key_%%j" ist 1 Byte in hex an Pos. %el% aber warum + Cur
cur ist doch 0 und 0*256 ist immer noch 0? Wozu das Bitweise und?

Hier steig ich aus, und versteh den Rest leider nicht mehr.

Wäre nett wenn mir den restlichen Code noch jemand erklären könnte.

mfg sinsizer
Mitglied: 76109
76109 Jan 06, 2012 at 15:57:34 (UTC)
Goto Top
Hallo @all!

Der Vollständigkeit halber noch eine etwas vereinfachte VBS-Version:
Const sKeyChar = "BCDFGHJKMPQRTVWXY2346789"  
Const sRegKey = "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\DigitalProductId"  

MsgBox GetProductKey(CreateObject("WScript.Shell").RegRead(sRegKey)), 64, "Windows Product Key"  

Function GetProductKey(ByRef aRegValue)
    Dim sProductKey, b, c, i
    
    For b = 24 To 0 Step -1
        c = 0
        For i = 66 To 52 Step -1
            c = c * 256 + aRegValue(i)
            aRegValue(i) = CByte(c \ 24)
            c = c Mod 24
        Next
        
        sProductKey = Mid(sKeyChar, c + 1, 1) & sProductKey
        
        If b And b Mod 5 = 0 Then sProductKey = "-" & sProductKey  
    Next
    
    GetProductKey = sProductKey
End Function

Gruß Dieter

[edit] Codezeile 12 geändert (XOR durch + ersetzt) [/edit]
Member: rubberman
rubberman Jan 06, 2012 at 19:48:09 (UTC)
Goto Top
Hallo Zusammen.

@Dieter,
nachdem ich vorher nur stupide VBS zu Batch konvertiert habe, ist mir die Funktionsweise dank deines Scripts nun auch klar.

@sinsizer,
Cur (bzw. c) bezeichnet die Position des Zeichens im String BCDFGHJKMPQRTVWXY2346789. Der Wert der Variablen startet zwar mit 0, wird aber sofort in der inneren Schleife neu berechnet.

Dieters VBS 2 Batch:
@echo off &setlocal
call :GetProductKey sWinProdKey
echo Windows Product Key: %sWinProdKey%
echo(
pause
goto :eof

:GetProductKey outVarName
setlocal EnableDelayedExpansion
set "sKeyChar=BCDFGHJKMPQRTVWXY2346789"  
set "sRegKey=HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion"  
set "sRegVal=DigitalProductId"  

for /f "tokens=3" %%i in ('reg query "%sRegKey%" /v "%sRegVal%"') do set "sHex=%%i"  

set /a "n = 52"  
for /l %%i in (104,2,132) do set /a "aRegValue_!n! = 0x!sHex:~%%i,2! , n += 1"  

for /l %%b in (24,-1,0) do (
  set /a "c = 0 , n = %%b %% 5"  
  for /l %%i in (66,-1,52) do set /a "c = c * 256 ^^ !aRegValue_%%i! , aRegValue_%%i = c / 24 , c %%= 24"  
  for %%j in (!c!) do set "sProductKey=!sKeyChar:~%%j,1!!sProductKey!"  
  if %%b neq 0 if !n!==0 set "sProductKey=-!sProductKey!"  
)
endlocal &set "%~1=%sProductKey%" &goto :eof  

Grüße
rubberman
Member: sinsizer
sinsizer Jan 07, 2012 at 07:49:59 (UTC)
Goto Top
Hallo,

tut mir wirklich leid das ich so schwer von Begriff bin, aber könnte mir jemand erklären was hier mathematisch passiert?

for /l %%i in (66,-1,52) do set /a "c = c * 256 ^^ !aRegValue_%%i! , aRegValue_%%i = c / 24 , c %%= 24"

Werde es mal als gelöst markieren. Sind ja nun schon mehrere Übersetzungen vorhanden.

Vielen Dank an alle.

mfg sinsizer
Mitglied: 76109
76109 Jan 07, 2012 at 11:04:01 (UTC)
Goto Top
Hallo sinsizer!

Na dann, versuche ich es mal zu erklärenface-wink
For b = 24 To 0 Step -1
Schleife entsprechend der Anzahl Charakter im Produkt-Key (25-Zeichen)

c = 0
Position im String "BCDFGHJKMPQRTVWXY2346789" pro Produkt-Key-Zeichen auf 0 setzen

For i = 66 To 52 Step -1
Schleife entsprechend der Positonen von den auszulesenden 15 Byte-Werten aus dem Reg-Byte-Array (164 Byte)

c = c * 256 + aRegValue(i)
aRegValue(i) = CByte(c \ 24)
c = c Mod 24
for /l %%i in (66,-1,52) do set /a "c = c * 256 ^^ !aRegValue_%%i! , aRegValue_%%i = c / 24 , c %%= 24"
Den aktuellen Wert in c (c * 256) auf ein WORD (16-Bit) erweitern sprich in's High-Byte (Bit 8-15) schieben + Low-Byte (Bit 0-7) aus dem Reg-Byte-Array

Beispiel:
Position (i) = 66 und c enthält den Startwert 0:
c = 0 und Wert im Reg-Byte-Array an Position 66 = 5:
c = 0 * 256 (0000 hex) + 5 ergibt 5 (0005 hex)
aRegValue(66) = Ganzahl 5 / 24 (aRegValue(i) = CByte(c \ 24)) ergibt 0 (00 hex)

Position (i) = 65 und c enthält aktuell von Position 66 den Restwert aus 5 / 24 (c = c Mod 24):
c = 5 und Wert im Reg-Byte-Array an Position 65 = 60:
c = 5 * 256 (0500hex) + 60 (003C hex) ergibt 1340 (053C hex)
aRegValue(65) = Ganzahl 1340 / 24 (aRegValue(i) = CByte(c \ 24)) ergibt 55 (37 hex)

Position (i) = 64 und c enthält aktuell von Position 65 den Restwert aus 20 / 24 (c = c Mod 24):
c = 20 und Wert im Reg-Byte-Array an Position 64 = 147:
c = 20 * 256 (1400hex) + 147 (0093 hex) ergibt 5267 (1493 hex)
aRegValue(64) = Ganzahl 5267 / 24 (aRegValue(i) = CByte(c \ 24)) ergibt 219 (DB hex)
...........

Hoffe, ich hab's einigermaßen verständlich erklärt?face-wink

@rubberman
@Dieter,
nachdem ich vorher nur stupide VBS zu Batch konvertiert habe, ist mir die Funktionsweise dank deines Scripts nun auch klar.
Freut mich zu hören und der Erfolg läßt sich nun ja auch an der Kürze des neuen Batch-Scripts erkennenface-wink

Gruß Dieter

PS. Codezeile 12 geändert:
c = c * 256 + aRegValue(i)
XOR durch (+) ersetzt
Member: sinsizer
sinsizer Jan 07, 2012 at 20:41:49 (UTC)
Goto Top
Danke für die ausführliche Erklärung. Jetzt hat es "KLICK!" gemacht. face-smile

Muss mich nur noch mit der High-Byte, Low-Byte Sache, dem Erweitern von BYTE auf WORD mit *256(evtl. auch DWORD *4096? usw.) und dem Unterschied von XOR und + in der Funktion auseinandersetzten.
Als nächstes bastel ich dann eine eigene kleine Ver- und Entschlüsselungs-Batch mit individueller Basis und Zeichensatz.face-wink

mfg sinsizer
Member: rubberman
rubberman Jan 07, 2012 at 22:53:51 (UTC)
Goto Top
Hallo sinsizer.

Vielleicht wird es einfacher, wenn du dir die binären Entsprechungen ansiehst.
Ein Byte hat eine Breite von 8 Bit. Das WORD hat eine Breite von 2 Byte = 16 Bit. Das linke Byte wird High-Byte genannt, das rechte Low-Byte.

Nehmen wir noch einmal das Beispiel von Dieter:
c = 5 * 256 (0500hex) + 60 (003C hex) ergibt 1340 (053C hex)
          High-Byte Low-Byte
5         00000000  00000101
* 256     00000101  00000000
+ 60      00000101  00111100

Statt der Multiplikation mit 256 könntest du auch ein Left-Shift um 8 Bit anwenden:
5         00000000  00000101
<< 8      00000101  00000000

Was nun den Unterschied zwischen Addition und XOR ausmacht ist einfach erklärt: Es sind 2 völlig unterschiedliche Operationen, die allerdings in diesem Fall exakt das gleiche Ergebnis liefern.
Die Addition muss ich sicher nicht erklären. Zum XOR:
0 XOR 0 = 0
1 XOR 0 = 1
0 XOR 1 = 1
1 XOR 1 = 0

Da alle Bits des Low-Bytes nach der Multiplikation mit 256 den Wert 0 haben, ist klar dass die Bits nach der XOR Operation nur dann den Wert 1 haben, wenn der 2. Operand an dieser Stelle 1 ist.

Grüße
rubberman
Member: sinsizer
sinsizer Jan 07, 2012 at 23:22:22 (UTC)
Goto Top
Hier kann man ja noch richtig was lernen. face-smile

Soweit hab ich glaub ich alles verstanden. Ohne die Verschiebung ins High-Byte wäre die Rechnung nicht möglich, da der Wert für eine Breite von 1 Byte zu groß wird.
Da 255 (dec) der größte wert für 1 Byte also 1111 1111 ist wird bei 256 auf WORD verschoben 0000 0001 0000 0000.
Das heißt um so größer der umzurechnende Wert, um so weiter bzw. öfter muss man verschieben?

Edit: Muss man Byteweise umrechnen, oder ginge das auch in einem "Rutsch"?

An dieser Stelle nochmal ein herzliches Dankeschön, an rubberman und Dieter, für die tollen Ausführungen und Erklärungen.
Mitglied: 76109
76109 Jan 07, 2012 at 23:26:48 (UTC)
Goto Top
Hallo rubberman!

Das hast Du sehr schön erklärtface-wink


Gruß Dieter
Member: rubberman
rubberman Jan 07, 2012 at 23:35:51 (UTC)
Goto Top
Hallo sinsizer,

kommt darauf an was du damit vorhast. Die Breite von 16 Bit wird zur Dekodierung gebraucht. Das heist, dieser Algorithmus verlangt es so. Wenn du ein Array Byte für Byte abarbeitest, reicht die Breite von 2 Byte in diesem Fall. Kreierst du deinen eigenen Kodierungs-/Dekodierungsalgorithmus, kann das anders sein.
Deine Frage lässt sich also nicht so einfach mit Ja oder Nein beantworten.

Grüße
rubberman

<EDIT: @Dieter - Danke für die Blumen face-wink />
Member: rubberman
rubberman Jan 08, 2012 at 00:02:02 (UTC)
Goto Top
Was dein Edit anbetrifft:
Dieser Algorithmus verlangt eine byteweise Abarbeitung. Davon abgesehen ist sie sinnvoll. Mit einer Breite von 4 Byte wärst du bereits an der Grenze angelangt, die die Kommandozeile noch als Zahl interpretieren kann.

Grüße
rubberman
Mitglied: 76109
76109 Jan 08, 2012 at 10:30:16 (UTC)
Goto Top
Hallo sinsizer!

Dieser Algorithmus verlangt eine byteweise Abarbeitung. Davon abgesehen ist sie sinnvoll. Mit einer Breite von 4 Byte
wärst du bereits an der Grenze angelangt, die die Kommandozeile noch als Zahl interpretieren kann.
Mal davon abgesehen, werden die Bytes im RegValue-Array für jeden Buchstaben neu geschrieben, also 25 mal alle 15 Bytes verändertface-wink

Ergänzend noch die Grenzwerte der Bases für die Byte-Decodierung:
Base Formel Binär Dez Hex Anzahl Bits
16 15 * 256 + 255 0000 1111 1111 1111 4095 0FFF 12
24 23 * 256 + 255 0001 0111 1111 1111 6143 17FF 13
32 31 * 256 + 255 0001 1111 1111 1111 8191 1FFF 13
64 63 * 256 + 255 0011 1111 1111 1111 16383 3FFF 14
128 127 * 256 + 255 0111 1111 1111 1111 32767 7FFF 15


Gruß Dieter