DllStruct Funktionen für Autoit

  • Zitat

    Und ist es auch so das es Dll´s gibt, die man nicht mitDdllCall sondern mit DllStruct Funktionen aufrufen muß ?

    eher nicht....obwohl ich langsam ahne, auf was du hinauswillst...
    Man kann im Speicherbereich eines fremden Threads eine Struct an der Position einer geladenen DLL erstellen, in der Struct (und somit der DLL-Funktion) Veränderungen durchführen und somit das "fremde" Programm beeinflussen bzw Daten lesen/umleiten.
    Aber dafür gibts ein extra AutoIt-Forum ;)

  • Nun eine geladene Dll ist vermutlich nur eine Ansammlung von Bit und Bytes oder dezimalen Weten im Memory - irgendwie so.... Und du meinst man konnte mit ner Struct eine Art Rahmen im dortliegenden Speicher drüberziehen, um dann gewisse Werte in der Dll zu verändern. Also das finde ich ja einen sehr interessanten Ansatz, dann bräuchte man ja im Grunde garnicht mehr diese NomadMemory Funktion benutzen, denn die tut doch das selbe dann oder nicht? Außerde das man mit DllStruct noch Speicherplazu reservieren könnte, soweit ich das jetzt verstehe .

    P.S. ja das andere Forum find ich nicht so gut, ich wird da andauernd gemoppt :(

  • wenn ich hier mal dazwischen funken darf :)

    hab auch ne Frage zu den dll strukturen
    in c hatte ich z.b.

    Code
    struct Header{
    int length;
    char string[10];
    }


    und konnte diese nun per TCP und angabe der speicheradresse verschicken

    Code
    struct Header h;
    h.length=5;
    h.string= "Hallo";
    send(socket, &h, sizeof(struct Header));

    Nun meine Frage: Wie kann ich dasselbe mit autoit erreichen?
    Komme nicht weiter:

    [autoit]


    TCPStartup()
    $socket = TCPConnect(ip,port)
    If @error <> 0 Then Exit ; Prüfe ob erfolgreich verbunden

    [/autoit][autoit][/autoit][autoit]

    $struct = DllStructCreate("int length; char string[10]")
    DllStructSetData($struct,1,5)
    DllStructSetData($struct,2,"Hallo")
    $c = TCPSend($socket, $struct)
    MsgBox(0,"nach senden","Error: "&@error&"-Bytes send: "&$c)

    [/autoit]


    ---------------------------
    nach senden
    ---------------------------
    Error: 0-Bytes send: 0
    ---------------------------
    OK
    ---------------------------
    Sollte Senden:
    Ip Header.....Nutzdaten: 00 00 00 05 48 61 6C 6C 6F (lenght=5 und Hallo)

    Warum ich dies hier poste, weil dies ein vorteil in c ist, und dadruch theoretisch auch in autoit :)

    Hoffe mir kann wer helfen


    €dit: Hat sich erledigt danke an ProgAndy

    3 Mal editiert, zuletzt von Death (26. Dezember 2011 um 18:23)

  • Hallo Death,
    war es das was du meinst? Ich habe das mal mit WPE pro überprüft.

    Spoiler anzeigen
    [autoit]

    $binary = Binary("0x05000000") ;Little-Endian weil Send byte für byte schickt?
    TCPStartup()
    $socket = TCPConnect("173.194.69.104", 80) ;google ftw
    If @error Then MsgBox(16, "ERROR Connect", @error)
    TCPSend($socket, $binary)
    TCPSend($socket, "Hallo")
    TCPShutdown()

    [/autoit]


    Erläuterung: Ein Integer ist 4 Bytes lang. Hexadezimal wird er so notiert: 0x00000005. Da ein Integer im Little-Endian Format abgespeichert wird, wird alles gespiegelt.
    Little-Endian: 0x05000000.
    Chars sind nur ein Byte groß, weshalb sie davon nicht betroffen sind.
    Hoffentlich verwechsel ich da nichts ;)
    mfg @night@

    PS: Hier noch eine Funktion zum Umwandeln der Little-Endian-"Struktur".

    Spoiler anzeigen
    [autoit]

    Func LittleEndian($Value)
    $sReturn = ""
    $Value = Hex($Value, 8)
    $aHelp = Stringsplit($Value, "", 3)
    For $i = 1 To 4
    $sReturn &= StringRight($Value, 2)
    $Value = StringTrimRight($Value, 2)
    Next
    return $sReturn
    EndFunc

    [/autoit]


    Bin gerade selber etwas verwirrt, aber sie müsste stimmen. Beispiel:

    [autoit]

    LittleEndian(5)

    [/autoit]

    Einmal editiert, zuletzt von @night@ (25. Dezember 2011 um 23:09)

  • Hi,
    größtenteils ist es sehr sinnvoll, die Hilfe zu den einzelnen Befehlen zu lesen^^

    [autoit]

    $a=dllstructcreate(blablub)

    [/autoit]

    in $a steht nur das "handle" für die folgenden dllstruct()-Funktionen
    Da macht es also wenig Sinn, dieses Handle per TCP zu veschicken....

    Im Deskstream habe ich diese little/big-Endian-Geschichte abgehandelt. Wenn man weiss, wie man die einzelnen Datentypen ineinander umwandelt, ist das auch garkein Problem :D

    Eine extra "Endian"-Funktion ist übrigens völlig unnötig, da die Daten in TCP genau so ankommen, wie sie abgeschickt wurden!
    Nur wenn man einen "int" ( 4 Byte) byteweise ausliest (von "vorne nach hinten") dann ist das relevant.
    Übrigens hat diese "Endianess" schon für reichlich graue Haare bei der Umwandlung von ARGB (Bitmap dword) in die einzelnen Farben gesorgt, stimmts Shadow? :rofl:


  • Hallo Andi, kannst Du mir das bitte genauer erläutern, warum mit float ein String bei rauskommt ?

  • Zitat

    Hallo Andi, kannst Du mir das bitte genauer erläutern, warum mit float ein String bei rauskommt ?


    Ich glaube Andi wollte dir nur damit sagen, dass der Datentyp eigentlich egal ist. Ich würde dir das gerne an dem Beispiel erklären, aber ich habe die Wikipediaerklärung der Floats nicht ganz verstanden.

    Datentypen wie float, int, char sind dem PC prinzipiell egal. Der würde auch ohne Datentypen ausgezeichnet zurechtkommen. Nur wir Programmierer brauchen leider unsere verinfachte und zweckmäßige Welt. Du kannst, wenn du willst, auch ohne Datentypen programmieren. Aber das ist sehr fehleranfällig weil man sehr schnell sehr viel verwechselt. Deswegen wurden die Datentypen eingeführt. Schliesslich bestehen alle Variablen nur aus Bytes. Manche haben mehr, andere weniger Bytes.
    Eine Integer-Variable (Ganzzahl) verbraucht zum Beispiel genauso viel Platz wie 4 Buchstaben. Warum unterscheidet man sie dann eigentlich?
    Der Grund: Beide werden anders im Speicher dargestellt.
    Ein String mit den Buchstaben: a u t o sieht im Speicher so aus: 0x61 0x75 0x74 0x6f (Hexadezimal dargestellt).
    Ein Integer mit der Zahl 1869903201 sieht hexadezimal so aus: 0x61 0x75 0x74 0x6f => 0x6175746f. Merkwürdig, oder? Beides ist doch komplett gleich, oder?
    Wenn wir nun jedes einzelne Byte vergleichen, werden wir feststellen, dass beides das Gleiche ist.

    [autoit]

    $struct_float=dllstructcreate("int");ein integer
    dllstructsetdata($struct_float,1,1869903201);integer
    $struct_char=dllstructcreate("char[4]",dllstructgetptr($struct_float));struct erstellen an Position des Intgers
    Msgbox(0,"",dllstructgetdata($struct_char,1));Speicher auslesen

    [/autoit]


    Mit dem Programm liest man den gleichen Speicherbereich zwei mal aus. Aber jedes mal "interpretieren" wir den Wert anders. Zuerst sagen wir Autoit, dies ist eine Ganzzahl. Und danach definieren wir den selben Speicherbereich als String. Woher soll der PC denn wissen, was du meinst? Ohne Datentypen könnte man alles durcheinandermixen und das wäre fatal. Zum Glück warnt der Compiler von C++ einen, wenn man versucht einen String mit einer Zahl zu vergleichen. Der Computer würde das ohne Probleme hinkriegen, aber es würde keinen Sinn machen und es würde ewig dauern den Fehler zu finden.
    Kapiert?

  • Ja soweit hab ich das in etwa verstanden, letztlich ist die integer ein Dezimalwert,
    welcher umgewandelt zu 0x6175746f wird und wenn ich das in einem HexEditor eingebe, bekomme ich dort das selbe wie aus der Msgbox dabei raus. Nur was ich jetzt nicht verstanden habe -ist wie aus diesen floats (Fließkommazahlen) = "Frohe Weihnachten" wird ?(

    • Offizieller Beitrag

    wie aus diesen floats (Fließkommazahlen) = "Frohe Weihnachten" wird


    Im Speicher wurden Floats mit Werten hinterlegt. Auf diesen Speicherplatz wird mit einem Pointer verwiesen. Nun erstellt man eine Struktur, die Zeichen aufnehmen soll. Dann wird dieser Struktur gesagt, dass die Werte unter dem vorab erstellten Pointer zu finden seien. Die Zeichenstruktur weiß ja nicht, dass der Speicherplatz nicht aus Zeichen befüllt wurde, kann ihr ja auch egal sein. Die Daten werden als Zeichen interpretiert und ergeben in diesem Fall "Frohe Weihnachten". Warum? Natürlich hat Andy den Weg vorher genau andersrum genommen, um den String in die Zahlen zu "verwandeln". :thumbup:

  • Um es nochmal anders zu erklären:

    Der Computer arbeitet nur mit Nullen und Einsen.
    Die Float-Zahl "4.52301424904732e+024" ist 4 Bytes (32Bit) lang und sieht im Speicher so aus: 01000110|01110010|01101111|01101000
    Der Buchstabe "F" ist 1 Byte (8Bit) lang und sieht so aus: 01000110
    "r" = 01110010
    "o" = 01101111
    "h" = 01101000

    Die ersten 4 Buchstaben haben also dieselbe Bitfolge im Speicher wie die erste Float-Zahl...


    Hier noch das Script zum verdeutlichen:

    [autoit]

    Global $aFloat[6] = [5]
    $aFloat[1] = 4.52301424904732E+024
    $aFloat[2] = 6.34941479652706E+022
    $aFloat[3] = 2.74865539637211E+020
    $aFloat[4] = 7.21364385566043E+022
    $aFloat[5] = 1.19923122576918E-041
    For $i = 1 To 5
    ConsoleWrite($aFloat[$i] & " => " & _Float2Bits($aFloat[$i]) & @CRLF)
    Next

    [/autoit][autoit][/autoit][autoit]

    Global $aText = StringSplit("Frohe Weihnachten!", "")
    For $i = 1 To $aText[0]
    ConsoleWrite($aText[$i] & " => " & _Char2Bits($aText[$i]) & @CRLF)
    Next

    [/autoit][autoit][/autoit][autoit][/autoit][autoit]

    Func _Char2Bits($sChar)
    Local $tChar = DllStructCreate("Char;")
    DllStructSetData($tChar, 1, $sChar)
    Local $tByte = DllStructCreate("Byte;", DllStructGetPtr($tChar))
    Return _Byte2Bits(DllStructGetData($tByte, 1))
    EndFunc ;==>_Char2Bits

    [/autoit][autoit][/autoit][autoit]

    Func _Float2Bits($fFloat)
    Local $tFloat = DllStructCreate("Float;")
    DllStructSetData($tFloat, 1, $fFloat)
    Local $tByte = DllStructCreate("Byte[4];", DllStructGetPtr($tFloat))
    Local $sBits = ""
    For $i = 1 To 4
    $sBits &= _Byte2Bits(DllStructGetData($tByte, 1, $i)) & "|"
    Next
    Return $sBits
    EndFunc ;==>_Float2Bits

    [/autoit][autoit][/autoit][autoit]

    Func _Byte2Bits($bByte)
    Local $tBits = DllStructCreate('char[64];')
    DllCall('msvcrt.dll', 'ptr:cdecl', '_i64toa', 'int64', $bByte, 'ptr', DllStructGetPtr($tBits), 'int', 2)
    If @error Then Return SetError(1, 0, "00000000")
    Return StringFormat("%08s", DllStructGetData($tBits, 1))
    EndFunc ;==>_Byte2Bits

    [/autoit]
  • Danke für eure Antworten erstmal, ich wird mehr es demnächst wenn ich Zeit dazu hab genauer anscheuen. Und wenn ich weitere Fragen habe, dann wird ich mich hier melden.