Einzelnen Beitrag anzeigen

Benutzerbild von Zacherl
Zacherl

Registriert seit: 3. Sep 2004
4.629 Beiträge
 
Delphi 10.2 Tokyo Starter
 
#10

AW: Probleme mit RtlRunEncodeUnicodeString

  Alt 24. Sep 2015, 07:58
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 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.
Projekte:
- GitHub (Profil, zyantific)
- zYan Disassembler Engine ( Zydis Online, Zydis GitHub)

Geändert von Zacherl (24. Sep 2015 um 08:04 Uhr)
  Mit Zitat antworten Zitat