Jump to content

Sky Slate Blueberry Blackcurrant Watermelon Strawberry Orange Banana Apple Emerald Chocolate
Photo

Wie erzeuge ich eine "Bytefolge der UTF-16LE Codierung"?



  • Please log in to reply
11 replies to this topic
Joe_81
  • Members
  • 14 posts
  • Last active: Dec 30 2013 08:04 PM
  • Joined: 04 Mar 2013
Hallo,

ich versuche, auf meine Fritzbox zuzugreifen. Beim Login muss ein MD5-Hash gebildet werden, wozu ich eine Funktion von Bentschi verwende. Allerdings weiß ich nicht, wie ich diesen Satz in der Anleitung umsetzen soll:

"Der MD5-Hash wird über die Bytefolge der UTF-16LE Codierung dieses Strings gebildet (ohne BOM und ohne abschließende 0-Bytes)."

Hier habe ich ziemlich planlos einiges versucht, bin aber nie auf das benötigte Ergebnis gekommen. Weiß jemand Rat? Und spielen AHK-Version und Zeichensatz des Scriptes eine Rolle?

Besten Dank für Hinweise.
 
 
 
str := "f6040de0-1aaf161d"  ; ein Beispielstring

utf16 := str  ; hier klemmt es, wie erzeuge ich die Bytefolge der UTF-16LE Codierung?

md5hash := MD5(utf16)

MsgBox, % md5hash "`n52715106883af96d0ce92e9a7096b0c3"  ; dies muss rauskommen



; ---------------------------------------------------------------------
; Von Bentschi, http://www.autohotkey.com/de/forum/viewtopic.php?t=8295
; ---------------------------------------------------------------------


MD5(string)
{
  return HashFromString(string, 0x8003)
}

HashFromAddr(pData, len, algid, key=0)
{
  ptr := (A_PtrSize) ? "ptr" : "uint"
  aw := (A_IsUnicode) ? "W" : "A"
  if (DllCall("advapi32\CryptAcquireContext" aw, ptr "*", hProv, ptr, 0, ptr, 0, "uint", 1, "uint", 0xF0000000))
  {
    if (DllCall("advapi32\CryptCreateHash", ptr, hProv, "uint", algid, "uint", key, "uint", 0, ptr "*", hHash))
    {
      if (DllCall("advapi32\CryptHashData", ptr, hHash, ptr, pData, "uint", len, "uint", 0))
      {
        if (DllCall("advapi32\CryptGetHashParam", ptr, hHash, "uint", 2, ptr, 0, "uint*", size, "uint", 0))
        {
          VarSetCapacity(bhash, size, 0)
          DllCall("advapi32\CryptGetHashParam", ptr, hHash, "uint", 2, ptr, &bhash, "uint*", size, "uint", 0)
        }
      }
      DllCall("advapi32\CryptDestroyHash", ptr, hHash)
    }
    DllCall("advapi32\CryptReleaseContext", ptr, hProv, "uint", 0)
  }
  int := A_FormatInteger
  SetFormat, Integer, h
  Loop, % size
  {
    v := substr(NumGet(bhash, A_Index-1, "uchar") "", 3)
    while (strlen(v)<2)
      v := "0" v
    hash .= v
  }
  SetFormat, Integer, % int
  return hash
}

HashFromString(string, algid, key=0)
{
  len := strlen(string)
  if (A_IsUnicode)
  {
    VarSetCapacity(data, len)
    StrPut := "StrPut"
    %StrPut%(string, &data, len, "cp0")
    return HashFromAddr(&data, len, algid, key)
  }
  data := string
  return HashFromAddr(&data, len, algid, key)
}



SAPlayer
  • Members
  • 403 posts
  • Last active: Apr 11 2014 04:45 PM
  • Joined: 06 Nov 2012

Wenn ich deinen String ("f6040de0-1aaf161d") per MD5 hashe (über http://www.md5-creator.com/), kommt bei mir folgendes raus: 2028ba907c30c486af9d5dcec014cd49

 

Das gleiche kommt auch im Script raus, bei mir geht es also.

 

Das Hashen ist nicht von der AHK-Version abhängig (brauchst aber glaube ich mindestens AHK_L) und vom Zeichensatz normalerweise auch nicht (ich habe es mit ANSI probiert).

Du brauchst den String auch nicht in UTF16 umzuwandeln.



jNizM
  • Members
  • 928 posts
  • Last active: Jan 12 2018 09:23 AM
  • Joined: 01 Aug 2012
Ich hab was aus C# gefunden.. allerdings kann ich das nicht in AHK übersetzen ^^
var bytes = Encoding.Unicode.GetBytes("1234567z-äbc");

var hash = new MD5Cng().ComputeHash(bytes);

var result = hash.Aggregate(
    new StringBuilder(), (sb, x) => sb.Append(x.ToString("x2"))).ToString();

// result == "9e224a41eeefa284df7bb0f26c2913e2"
Alternativ in VB
[AHK] 1.1.27.04 x64 Unicode | [WIN] 10 Pro (Version 1709)
My GitHub Profile | Donations are appreciated if I could help you

Joe_81
  • Members
  • 14 posts
  • Last active: Dec 30 2013 08:04 PM
  • Joined: 04 Mar 2013

Wenn ich deinen String ("f6040de0-1aaf161d") per MD5 hashe (über http://www.md5-creator.com/), kommt bei mir folgendes raus: 2028ba907c30c486af9d5dcec014cd49

Es muss aber der oben gepostete String rauskommen, sonst lässt meine Fritzbox mich nicht rein. Und es muss mit dieser Bytesfolge zu tun haben. Den Begriff kenne ich nicht, aber offenbar hat er eine andere Bedeutung als Zeichenfolge bzw String.
 

Ich hab was aus C# gefunden.. allerdings kann ich das nicht in AHK übersetzen ^^

var bytes = Encoding.Unicode.GetBytes("1234567z-äbc");

var hash = new MD5Cng().ComputeHash(bytes);

var result = hash.Aggregate(
    new StringBuilder(), (sb, x) => sb.Append(x.ToString("x2"))).ToString();

// result == "9e224a41eeefa284df7bb0f26c2913e2"
Alternativ in VB


Ja danke, sieht wirklich ziemlich einfach aus. Ich habe auch schon Implementationen in Python und AutoIt gesehen. Vielleicht könnte ich den Hash mit AutoIt in eine Datei schreiben und diese mit AutoHotkey wieder lesen. Oder gibt es bessere Möglichkeiten, mit anderen Programmiersprachen zu kommunizieren? Damit habe ich bisher noch nichts zu tun gehabt. Besser wäre aber natürlich, wenn es auch in AHK ginge.

SAPlayer
  • Members
  • 403 posts
  • Last active: Apr 11 2014 04:45 PM
  • Joined: 06 Nov 2012

Habe es geschafft, auch wenn es sicher nicht die schönste Variante ist:

str := "f6040de0-1aaf161d"  ; ein Beispielstring

FileEncoding, UTF-16-RAW

FileDelete, temp.txt

FileAppend, % str, temp.txt

md5hash := MD5FromFile("temp.txt")

FileDelete, temp.txt

MsgBox, % md5hash "`n52715106883af96d0ce92e9a7096b0c3"  ; dies muss rauskommen



; ---------------------------------------------------------------------
; Von Bentschi, http://www.autohotkey.com/de/forum/viewtopic.php?t=8295
; ---------------------------------------------------------------------


MD5(string)
{
  return HashFromString(string, 0x8003)
}

MD5FromFile(filename)
{
  return HashFromFile(filename, 0x8003)
}

HashFromAddr(pData, len, algid, key=0)
{
  ptr := (A_PtrSize) ? "ptr" : "uint"
  aw := (A_IsUnicode) ? "W" : "A"
  if (DllCall("advapi32\CryptAcquireContext" aw, ptr "*", hProv, ptr, 0, ptr, 0, "uint", 1, "uint", 0xF0000000))
  {
    if (DllCall("advapi32\CryptCreateHash", ptr, hProv, "uint", algid, "uint", key, "uint", 0, ptr "*", hHash))
    {
      if (DllCall("advapi32\CryptHashData", ptr, hHash, ptr, pData, "uint", len, "uint", 0))
      {
        if (DllCall("advapi32\CryptGetHashParam", ptr, hHash, "uint", 2, ptr, 0, "uint*", size, "uint", 0))
        {
          VarSetCapacity(bhash, size, 0)
          DllCall("advapi32\CryptGetHashParam", ptr, hHash, "uint", 2, ptr, &bhash, "uint*", size, "uint", 0)
        }
      }
      DllCall("advapi32\CryptDestroyHash", ptr, hHash)
    }
    DllCall("advapi32\CryptReleaseContext", ptr, hProv, "uint", 0)
  }
  int := A_FormatInteger
  SetFormat, Integer, h
  Loop, % size
  {
    v := substr(NumGet(bhash, A_Index-1, "uchar") "", 3)
    while (strlen(v)<2)
      v := "0" v
    hash .= v
  }
  SetFormat, Integer, % int
  return hash
}

HashFromString(string, algid, key=0)
{
  len := strlen(string)
  if (A_IsUnicode)
  {
    VarSetCapacity(data, len)
    StrPut := "StrPut"
    %StrPut%(string, &data, len, "cp0")
    return HashFromAddr(&data, len, algid, key)
  }
  data := string
  return HashFromAddr(&data, len, algid, key)
}

HashFromFile(filename, algid, key=0)
{
  ptr := (A_PtrSize) ? "ptr" : "uint"
  if ((hFile := DllCall("CreateFile", "str", filename, "uint", 0x80000000, "uint", 1, ptr, 0, "uint", 3, "uint", 0, ptr, 0, ptr))!=0)
  {
    if ((DllCall("GetFileSizeEx", ptr, hFile, "uint64*", size)) && (size>0) && (size<=0xFFFFFFFF))
    {
      VarSetCapacity(data, size)
      if (DllCall("ReadFile", ptr, hFile, ptr, &data, "uint", size, ptr "*", 0, ptr, 0))
        hash := HashFromAddr(&data, size, algid, key)
    }
    DllCall("CloseHandle", ptr, hFile)
  }
  return hash
}


Joe_81
  • Members
  • 14 posts
  • Last active: Dec 30 2013 08:04 PM
  • Joined: 04 Mar 2013
Wow, es geht tatsächlich, vielen Dank! Also doch nur eine Frage der Konvertierung von Codierungen. Daran habe ich lange geknobelt, besten Dank für deine Mühe!

nnnik
  • Members
  • 1625 posts
  • Last active: Jan 24 2019 02:19 PM
  • Joined: 28 Jul 2012

Ist ja nur so ne Idee aber wäre HashfromAddress nicht besser, wenn man über strput arbeitet kann man doch auch auswählen ob Unicode oder nicht.


Visit the new forum ahkscript.org.

http://ahkscript.org


Joe_81
  • Members
  • 14 posts
  • Last active: Dec 30 2013 08:04 PM
  • Joined: 04 Mar 2013
Über StrPut() war ich auch gestolpert, konnte dies aber nicht anwenden. Irritiert hat mich, dass an eine "Speicheradresse" kopiert werden soll und nicht in eine Variable.

nnnik
  • Members
  • 1625 posts
  • Last active: Jan 24 2019 02:19 PM
  • Joined: 28 Jul 2012

Wenn du eine Speicheradresse oder Adresse oder einen Pointer von einer Variable erhalten musst schreibst du anstatt var, &var.

Das übergibt dann die Adresse der Variable.

Hier wäre dann das neue script ohne Festplattennutzung:

wenn strput oder strget UTF-16-RAW unterstützen würden.

Man kann sich jetzt noch über numput was basteln aber das wird ne weile dauern.


Visit the new forum ahkscript.org.

http://ahkscript.org


Joe_81
  • Members
  • 14 posts
  • Last active: Dec 30 2013 08:04 PM
  • Joined: 04 Mar 2013
Ja, danke für die Erklärung, dann hat AutoHotkey hier wohl noch eine Schwäche. Der Schönheitsfehler der Lösung von SAPlayer stört mich aber auch gar nicht, und schnell genug ist es auch.

nnnik
  • Members
  • 1625 posts
  • Last active: Jan 24 2019 02:19 PM
  • Joined: 28 Jul 2012
✓  Best Answer
#NoEnv  ; Recommended for performance and compatibility with future AutoHotkey releases.
#Warn,all,off  ; Recommended for catching common errors.
SendMode Input  ; Recommended for new scripts due to its superior speed and reliability.
SetWorkingDir %A_ScriptDir%  ; Ensures a consistent starting directory.
str := "f6040de0-1aaf161d"
len:=strpututf16raw(str,string)
MsgBox, % MD5FromAddr(&string,len) "`n52715106883af96d0ce92e9a7096b0c3"

StrPutUTF16RAW(Str,byref Var,zeroterminated=1)
{
 zeroterminated:=zeroterminated?2:0
 VarSetCapacity(Var,(var2:=(strlen(str)-1)*2)+zeroterminated,0)
 loop,% var2
 {
  NumPut(Asc(str),Var,(A_Index-1)*2,"UShort")
  StringTrimLeft,str,str,1
 }
  return var2+zeroterminated
}


MD5FromAddr(addr, len)
{
  return HashFromAddr(addr, len, 0x8003)
}


HashFromAddr(pData, len, algid, key=0)
{
  ptr := (A_PtrSize) ? "ptr" : "uint"
  aw := (A_IsUnicode) ? "W" : "A"
  if (DllCall("advapi32\CryptAcquireContext" aw, ptr "*", hProv, ptr, 0, ptr, 0, "uint", 1, "uint", 0xF0000000))
  {
    if (DllCall("advapi32\CryptCreateHash", ptr, hProv, "uint", algid, "uint", key, "uint", 0, ptr "*", hHash))
    {
      if (DllCall("advapi32\CryptHashData", ptr, hHash, ptr, pData, "uint", len, "uint", 0))
      {
        if (DllCall("advapi32\CryptGetHashParam", ptr, hHash, "uint", 2, ptr, 0, "uint*", size, "uint", 0))
        {
          VarSetCapacity(bhash, size, 0)
          DllCall("advapi32\CryptGetHashParam", ptr, hHash, "uint", 2, ptr, &bhash, "uint*", size, "uint", 0)
        }
      }
      DllCall("advapi32\CryptDestroyHash", ptr, hHash)
    }
    DllCall("advapi32\CryptReleaseContext", ptr, hProv, "uint", 0)
  }
  int := A_FormatInteger
  SetFormat, Integer, h
  Loop, % size
  {
    v := substr(NumGet(bhash, A_Index-1, "uchar") "", 3)
    while (strlen(v)<2)
      v := "0" v
    hash .= v
  }
  SetFormat, Integer, % int
  return hash
}

Das hier ist schneller und Ressourcenschonender


Visit the new forum ahkscript.org.

http://ahkscript.org


Joe_81
  • Members
  • 14 posts
  • Last active: Dec 30 2013 08:04 PM
  • Joined: 04 Mar 2013

Das ist tatsächlich etwas schneller und natürlich ungleich eleganter.

Doller Service hier, Danke schön!