Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Win32/Win64 API (native code) (https://www.delphipraxis.net/17-win32-win64-api-native-code/)
-   -   Probleme mit RtlRunEncodeUnicodeString (https://www.delphipraxis.net/186682-probleme-mit-rtlrunencodeunicodestring.html)

slemke76 22. Sep 2015 17:57

Probleme mit RtlRunEncodeUnicodeString
 
Hallo zusammen,

ich muss (leider) auf RtlRunEncodeUnicodeString und RtlRunDecodeUnicodeString zurückgreifen (andocken an dritt-Software). Ich dachte mir, ich baue mal einen Prototypen, um nicht gleich mit der ganz grossen Aufgabe anzufangen. Leider sind das ja undokumentierte Befehle, so daß ich echt auf dem Schlauch stehe.

Was mir fehlt, ist das grundsätzliche Verständnis, wofür ich vorher "RtlInitUnicodeString" brauche und wie ich die Funktionen sauber anspreche. Ich habe ein kleines Beispiel zusammengestellt, dass aber schon bei RtlRunEncodeUnicodeString eine Zugriffsverletzung verursacht.

Kann mir jemand zum einen für das Verständnis weiter helfen und zum anderen zu dem korrekten ansprechen von RtlRunEncodeUnicodeString/RtlRunDecodeUnicodeString?

Hier der Code:
Delphi-Quellcode:
{...]
type
  PUnicodeString = ^TUnicodeString;
  TUnicodeString = packed record
    Length: Word;
    MaximumLength: Word;
    Buffer: PWideChar;
  end;

  procedure RtlInitUnicodeString(DestinationString: PUnicodeString; SourceString: LPWSTR); stdcall; external 'ntdll.dll';
  procedure RtlRunEncodeUnicodeString(bKey : PBYTE; Str : PUnicodeString); stdcall; external 'ntdll.dll';
[...]

procedure TForm1.Button1Click(Sender: TObject);
var
   Seed: DWORD;
   UnicodeStringBuffer: WideString;
   UnicodeString: TUnicodeString;
begin
  UnicodeStringBuffer := 'TestString';
  UnicodeString.Buffer := PWideChar(UnicodeStringBuffer);
  UnicodeString.Length := Length(UnicodeStringBuffer) * SizeOf(WideChar);
  RtlInitUnicodeString(@UnicodeString, @UnicodeStringBuffer);
  Seed := Byte(GetTickCount);
//  RtlRunEncodeUnicodeString(@Seed, @UnicodeString);
end;
lg
Sebastian

TiGü 23. Sep 2015 09:38

AW: Probleme mit RtlRunEncodeUnicodeString
 
Zitat:

Zitat von slemke76 (Beitrag 1316647)
ich muss (leider) auf RtlRunEncodeUnicodeString und RtlRunDecodeUnicodeString zurückgreifen (andocken an dritt-Software).

Wie sieht denn ganz konkret die Andock-Schnittstelle der Dritt-Software aus?
Vielleicht gibt es auch einen alternativen Weg?

slemke76 23. Sep 2015 10:31

AW: Probleme mit RtlRunEncodeUnicodeString
 
Liste der Anhänge anzeigen (Anzahl: 1)
Hallo,

leider nicht - um die dritt-Software geht es ja auch zunächst gar nicht. Ich würde mir selber gerne ein Beispiel schreiben (naja, genau genommen bekomme ich das ja nicht hin :-D), um die Funktionen zu verstehen und benutzen zu können.

Ich habe also zwei Probleme:
- Verständnisproblem zusammenspiel RtlInitUnicodeString & RtlRunEncodeUnicodeString
- Variablen / Pointerhandling

Kann mich jemand unterstützen?

Ich habe auch mal mein Sample als komplettes Projekt (Delphi 7) als ZIP angehängt.

DANKE!

TiGü 23. Sep 2015 11:03

AW: Probleme mit RtlRunEncodeUnicodeString
 
Du benutzt schon die Init-Funktion nicht richtig.
Hast du dir die Doku in der MSDN dazu angeschaut?
Beachte, was die Ausgabe und was die (optionalen) Eingabeparameter sind.

Delphi-Quellcode:
 
...
var
  Source : string;
  UnicodeString: TUnicodeString;
begin
 Source := 'TestString';
  FillChar(UnicodeString, SizeOf(UnicodeString), 0);
  RtlInitUnicodeString(@UnicodeString, PWideChar(Source));
end;

TiGü 23. Sep 2015 11:56

AW: Probleme mit RtlRunEncodeUnicodeString
 
Schau dir nochmal den ersten Link an, den du in deinen Beispielprojekt hast.
Die werkeln da mit CopyAndSkipString rum. Wenn man diese Procedure verwendet geht es:
Delphi-Quellcode:
...
type
  UNICODE_STRING = packed record
    Length: Word;
    MaximumLength: Word;
    Buffer: PWideChar;
  end;
 PUNICODE_STRING = ^UNICODE_STRING;


procedure RtlInitUnicodeString(DestinationString: PUNICODE_STRING; SourceString: LPWSTR); stdcall; external 'ntdll.dll';
procedure RtlRunEncodeUnicodeString(Hash: PUCHAR; Str: PUNICODE_STRING); stdcall; external 'ntdll.dll';

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure CopyAndSkipString(var P : Pointer; var Str : PWideChar);
var
  Len : Cardinal;
begin
  Len := (Length(Str) + 1) * SizeOf(Str[0]);
  CopyMemory(P, Str, Len);
  Str := P;
  Inc(Cardinal(P), Len);
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  Source: PWideChar;
  UnicodeString: UNICODE_STRING;
  Hash : UCHAR;
  P : Pointer;
begin
  {
    http://www.remkoweijnen.nl/blog/2008/11/26/executing-a-fast-user-switch-programmatically-part-2/
    http://doxygen.reactos.org/dc/d4b/lib_2rtl_2encode_8c_source.html
    http://forums.codeguru.com/showthread.php?322941-problem-using-RtlRunDecodeUnicodeString
  }
  Source := 'TestString';
  GetMem(P, SizeOf(UnicodeString));
  CopyAndSkipString(P, Source);

  RtlInitUnicodeString(@UnicodeString, Source);
  Hash := Byte(GetTickCount);
  RtlRunEncodeUnicodeString(@Hash, @UnicodeString);
end;

slemke76 23. Sep 2015 12:29

AW: Probleme mit RtlRunEncodeUnicodeString
 
Hallo,

1000 Dank - tiefste Dankbarkeit - wenn du nicht aus Berlin kommen würdest (zu weit weg) würde ich mit ner Kiste Bier vorbeikommen :cheers:.

Ich werde dann mal als nächstes das Decode selber probieren zu implementieren ;-) Ich habe erstmal einen kräftigen Schubser in die richtige Richtung bekommen.

lg
Sebastian

TiGü 23. Sep 2015 12:34

AW: Probleme mit RtlRunEncodeUnicodeString
 
Zitat:

Zitat von slemke76 (Beitrag 1316747)
1000 Dank - tiefste Dankbarkeit - wenn du nicht aus Berlin kommen würdest (zu weit weg) würde ich mit ner Kiste Bier vorbeikommen :cheers:.

Gibt es bei euch keine Post? :mrgreen:

slemke76 24. Sep 2015 01:17

AW: Probleme mit RtlRunEncodeUnicodeString
 
Liste der Anhänge anzeigen (Anzahl: 1)
Hallo,

darüber lässt sich reden ;-)

Ich habe das ganze jetzt durchgearbeitet und (hoffentlich) auch verstanden (ein paar Fragen sind noch unten ;-).
Mein nächster Schritt wäre jetzt, die RtlRunDecodeUniCodeString einzuführen; die Parametertypen sind gleich, ein "RtlRunDecodeUniCodeString(@Hash, @UnicodeString);" sollte im o.g. Source also gehen (?).

Was ich getan habe: Ein Breakpoint _vor_ dem RtlRunEncodeUniCodeStringsetzen, Inhalt von UnicodeString in den überwachten Ausdrücken einsetzen, diesen Aufklappen und in UnicodeString.Buffer liegt der Wert "TestString", wie erwartet.

Dann Einzelschritt für Encode & Decode machen - leider steht dann _nicht_ wieder der "TestString" im UnicodeString.Buffer (bei gleichem Hash)?

Ich habe auch noch paar "untergeordnete" Fragen (ich möchte nicht Dumm sterben ;-):

1. mit GetMem wird Speicher an der Adresse "P" in Größe der Struktur UNICODE_STRING bereit gestellt, mit CopyAndSkipString der Inhalt von Source an die Speicheradresse P kopiert. Richtig? Wird dann mit Str := P; die Adresse der Variable "Source" ebenfalls auf P gesetzt? Ich vermute, damit man auf das Ergebnis später einfach über die Variable source zugreifen kann? Was passiert mit der alten Speicheradresse von source? Leck?

2. Wenn ich "ShowMessage(WideCharLenToString(UnicodeString.Buf fer, UnicodeString.Length div 2));" oder auch einfach "ShowMessage(source);" zum Anzeigen des Inhaltes der Variable benutze, funktioniert das im ersten Durchlauf, im zweiten bekomme ich eine Exception - warum?

Kann jemand auflösen, warum zum Henker die Decode Funktion nicht laufen will? Ich habe schon alles mögliche probiert (u.a. auch die Variable neu zu initialisieren), aber nichts klappt.

Einen aktuellen Source habe ich nochmal angehängt.
Es gibt keinen Fehler, aber ich bekomme auch meinen Wert nicht zurück...!?

lg
Sebastian

Zacherl 24. Sep 2015 06:36

AW: Probleme mit RtlRunEncodeUnicodeString
 
Die Parameter sind nicht gleich. Bei der Decode Funktion ist der Hash ein UCHAR und kein PUCHAR :P

Bei dem ganzen CopyAndSkipString Kram hast du btw. auf jeden Fall einen Buffer Overflow eingebaut. Der Speicher, den du dir per GetMem holst ist unter 32 Bit immer 8 Byte groß. In der Funktion schreibst du aber im Falle von "TestString" 22 Bytes.

Zacherl 24. Sep 2015 07:58

AW: Probleme mit RtlRunEncodeUnicodeString
 
Habe den Code jetzt nochmal etwas genauer debuggt, weil mir dieser CopyAndSkipString einfach absolut unsinnig vorkam und habe wohl recht gehabt. Das Problem liegt an einer komplett anderen Stelle.

RtlInitUnicode String erstellt keinen neuen Buffer für den String, sondern setzt das entsprechende Feld lediglich auf die Adresse des Source Strings. PAnsiChar/PWideChar Stringkonstanten packt Delphi allerdings scheinbar in eine read-only Section der Anwendung, weshalb jedlicher Schreibversuch zu einer Access Violation führt.
Delphi-Quellcode:
var
  Source: PWideChar;
begin
  Source := 'TestString';
  // Oops, this is read-only memory
  Source[1] := 'x';
RtlRunEncodeUnicodeString für seinen Teil erwartet aber logischerweise einen Buffer, der beschrieben werden kann.

Folgender Code funktioniert, basiert nicht auf irgendwelchen Pseudo-Funktionen :stupid: und erzeugt auch keine Memory-Leaks:
Delphi-Quellcode:
type
  UNICODE_STRING = packed record
    Length: Word;
    MaximumLength: Word;
    Buffer: PWideChar;
  end;
  PUNICODE_STRING = ^UNICODE_STRING;

procedure RtlInitUnicodeString(DestinationString: PUNICODE_STRING; SourceString: LPWSTR); stdcall;
  external 'ntdll.dll';
procedure RtlRunEncodeUnicodeString(Hash: PUCHAR; Str: PUNICODE_STRING); stdcall;
  external 'ntdll.dll';
procedure RtlRunDecodeUnicodeString(Hash: UCHAR; Str: PUNICODE_STRING); stdcall;
  external 'ntdll.dll';

var
  Source: PWideChar;
  UnicodeString: UNICODE_STRING;
  Hash: UCHAR;
  S: array of WideChar;
begin
  Source := 'TestString';

  // Init
  SetLength(S, Length(Source) + 1);
  ZeroMemory(@S[0], Length(S) * SizeOf(S[0]));
  CopyMemory(@S[0], Source, Length(S) * SizeOf(S[0]));
  RtlInitUnicodeString(@UnicodeString, @S[0]);

  // Encode
  // RtlRunEncodeUnicodeString automatically calculates a hash, if the initial value is zero
  // http://doxygen.reactos.org/dc/d4b/lib_2rtl_2encode_8c_a2b44614e96788912d167d7cac4b7b501.html#a2b44614e96788912d167d7cac4b7b501
  Hash := 0;
  RtlRunEncodeUnicodeString(@Hash, @UnicodeString);

  // Decode
  RtlRunDecodeUniCodeString(Hash, @UnicodeString);
end;
Auch gehen würde folgendes (normale Stringkonstanten landen nicht in der read-only Section bzw. werden bei Zuweisung vermutlich umkopiert):
Delphi-Quellcode:
var
  Source: WideString;
  UnicodeString: UNICODE_STRING;
  Hash: UCHAR;
begin
  Source := 'TestString'#0;
  RtlInitUnicodeString(@UnicodeString, @Source[1]);
  Hash := 0;
  RtlRunEncodeUnicodeString(@Hash, @UnicodeString);
Dann aber nicht vergessen vorher per Hand eine #0 an den Source String anzuhängen.


Alle Zeitangaben in WEZ +1. Es ist jetzt 12:06 Uhr.
Seite 1 von 2  1 2      

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz