Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Win32/Win64 API (native code) (https://www.delphipraxis.net/17-win32-win64-api-native-code/)
-   -   AV bei LookupAccountSidW (https://www.delphipraxis.net/97078-av-bei-lookupaccountsidw.html)

Luckie 4. Aug 2007 02:43


AV bei LookupAccountSidW
 
Liste der Anhänge anzeigen (Anzahl: 2)
Ich bin am verzweifeln. Folgender Code:
Delphi-Quellcode:
function StrSIDToName(const StrSID: Widestring; var Name: WideString; var SIDType: DWORD): Boolean;
var
  SID              : PSID;
  Buffer           : PWideChar;
  NameLen, TempLen : Cardinal;
  succes           : Boolean;
begin
  SID := nil;
  succes := ConvertStringSIDToSID(PWideChar(StrSID), SID);
  if succes then
  begin
    NameLen := 0;
    TempLen := 0;
    LookupAccountSidW(nil, SID, nil, NameLen, nil, TempLen, SIDType);
    GetMem(Buffer, NameLen * sizeOf(WideChar));
    try
      succes := LookupAccountSidW(nil, SID, Buffer, NameLen, nil, TempLen, SIDType);
      if succes then
        SetString(Name, Buffer, Namelen);
    finally
      FreeMem(Buffer);
    end;
  end;
  if Assigned(SID) then
    LocalFree(Cardinal(SID));
  result := succes;
end;
Ich bekomme beim zweiten Aufruf von LookupAccountSidW eine AV. Das verrückte ist, in einem anderen Projekt benutze ich exakt den selben Code und da funktioniert er. :wall:
Nehme ich LookupAccountSIDA geht alles. Ich will aber die Unicode Version nutzen.

Im Anhang mal beide Projekte. Ich weiß nicht, was ich in dem einen Projekt anders mache.

marabu 4. Aug 2007 07:15

Re: AV bei LookupAccountSidW
 
Moin Michael,

in deinem älteren Thread zu diesem Thema hatten wir doch schon geklärt: In der Unicode-Version darf für ReferencedDomainName kein NIL übergeben werden.

Freundliche Grüße

Luckie 4. Aug 2007 10:54

Re: AV bei LookupAccountSidW
 
Ja, aber warumn funktioniert es in dem einem Projekt trotzdem? Aber auch wenn ich in dem Projekt mit der AV einen Buffer für einen ReferenceName übergebe, bekomme ich eine AV.

Ich vermute, ich reserviere den Speicher in beiden Projekten nicht richtig und habe in dem einem nur Glück, dass es irgendwie passt. Ihc habe gestern schon mit VirtaulAlloc und HeapAlloc rumgespielt, aber es hat nicht geklappt.

Verdammt jetzt gehts, wenn ich einen Buffer für die RefernceDomain angebe. Es ar gestern wohl doch etwas spät. :wall:

Dezipaitor 4. Aug 2007 12:39

Re: AV bei LookupAccountSidW
 
Ok nochmal zum mitschreiben.

Delphi-Quellcode:
BOOL WINAPI LookupAccountSid(
  LPCTSTR lpSystemName,
  PSID lpSid,
  LPTSTR lpName,
  LPDWORD cchName,
  LPTSTR lpReferencedDomainName,
  LPDWORD cchReferencedDomainName,
  PSID_NAME_USE peUse
);
Der Parameter lpReferencedDomainName darf nicht nil sein.
In der MSDN steht nichts davon, dass er NULL sein darf. Normalerweise steht sowas dran, oder?
Ok, dann muss man davon ausgehen, wenn nichts davon dransteht, dass darf der Parameter auch nicht nil sein.

Verwirrend.

Ich verwende übrigens LocalAlloc für den SidName und die -domain. Hatte vorher schon einige Probleme bei Funktionen, die mit GetMem nicht funktioniert haben. Leider geht das LocalAlloc am Speichermanager vorbei (soweit ich weiß).

Luckie 4. Aug 2007 12:52

Re: AV bei LookupAccountSidW
 
Zitat:

Zitat von Dezipaitor
Der Parameter lpReferencedDomainName darf nicht nil sein.
In der MSDN steht nichts davon, dass er NULL sein darf. Normalerweise steht sowas dran, oder?
Ok, dann muss man davon ausgehen, wenn nichts davon dransteht, dass darf der Parameter auch nicht nil sein.

OK, aber warum funktioniert der Code in dem einem Projekt, aber nicht in dem anderen?

Btw. bei dem ersten Aufruf sind beide Parameter nil und es geht.

Christian Seehase 4. Aug 2007 13:13

Re: AV bei LookupAccountSidW
 
Moin Zusammen,

doch, ReferencedDomainName darf sehr wohl nil sein.

Zitat:

cchReferencedDomainName
[in, out] On input, specifies the size, in TCHARs, of the lpReferencedDomainName buffer. If the function fails because the buffer is too small or if cchReferencedDomainName is zero, cchReferencedDomainName receives the required buffer size, including the terminating null character.
Die bei API-Funktionen häufig anzutreffende Vorgehensweise, um die erforderliche Bufferlänge zu ermitteln.
Der Zielbuffer wird auf nil gesetzt (und ggf. die Bufferlänge auf 0), damit einem die Funktion die benötigte Grösse zurückliefert.

Dezipaitor 4. Aug 2007 13:41

Re: AV bei LookupAccountSidW
 
Also ich habe es mal getestet.

Delphi-Quellcode:
BOOL WINAPI LookupAccountSid(
  LPCTSTR lpSystemName,
  PSID lpSid,
  LPTSTR lpName,
  LPDWORD cchName,
  LPTSTR lpReferencedDomainName,
  LPDWORD cchReferencedDomainName,
  PSID_NAME_USE peUse
);
Der Parameter darf wirklich NIL sein, jedoch nur dann, wenn folgende Vorbedingung erfüllt ist :
  • Der Parameter cchName muss kleiner sein, als die tatsächliche Länge des SID-Namens.
    ODER
  • (
    Der Parameter cchReferencedDomainName muss kleiner sein, als die tatsächliche Länge des Domainnamens.
    UND
    Der Parameter cchName muss größer oder größer gleich sein, als die tatsächliche Länge des SID-Namens.
    )

@Luckie: Dein Quellcode wäre demnach semantisch inkorrekt.
Warum es mal so funktioniert und mal anders nicht, kann ich dir nicht sagen. Zumindest auf meinem XP SP2 ergibt der obige Quellcode immer eine Exception in "ntdll.dll".

Ich habe mal dein "WindowsStations.dpr" Programm ausprobiert und musste feststellen, dass StrSIDToName funktioniert, weil die Variable TempLen immer 0 war. Ich habe garkein SID Name bekommen. Dann isses auch kein Wunder, dass es funktioniert :D

Die Ansi Variante funktionier übrigens immer. Vermutlich ein Bug in der W-Variante? Oder Kompatibilitätsgründe?

marabu 4. Aug 2007 15:34

Re: AV bei LookupAccountSidW
 
Hallo Chris,

Zitat:

Zitat von Christian Seehase
doch, ReferencedDomainName darf sehr wohl nil sein.

das ist schon klar und wurde alles hier schon einmal durchgekaut. Statt "darf nicht NIL sein" hätte ich ausführlicher schreiben können "darf beim zweiten Mal nicht mehr NIL sein, damit nicht BUFFER_TOO_SMALL gemeldet wird", aber ich hatte als Beteiligter den anderen Thread zum Kontext gerechnet und mich deshalb verkürzt ausgedrückt, sorry.

Die AV könnte eventuell hier herrühren:

Delphi-Quellcode:
// ...
      if succes then
        SetString(Name, Buffer, Namelen);
// ...
Je nachdem wie die Variable vor dem Aufruf initialisiert wird - oder nicht - könnte es zu einer AV kommen.

Freundliche Grüße

Luckie 4. Aug 2007 17:00

Re: AV bei LookupAccountSidW
 
Name wird als var Parameter übergeben.

Dezipaitor 4. Aug 2007 17:51

Re: AV bei LookupAccountSidW
 
Hallo?
hat jemand überhaupt mein Post gelesen??????

marabu 4. Aug 2007 18:10

Re: AV bei LookupAccountSidW
 
Hallo,

ich habe von deinen Tests gelesen.

Ist dabei verwertbarer Code entstanden, den du hier veröffentlichen möchtest?

Freundliche Grüße

Dezipaitor 4. Aug 2007 18:29

Re: AV bei LookupAccountSidW
 
Zitat:

Zitat von marabu
Hallo,

ich habe von deinen Tests gelesen.

Ist dabei verwertbarer Code entstanden, den du hier veröffentlichen möchtest?

Freundliche Grüße

Ich hab Luckies Code genommen und ausgeführt und dabei festgestellt, dass der Puffer für den Domainname immer mit angegeben werden muss. Sobald man den SID-Name in den Puffer kopieren will, darf der Domainpuffer NICHT nil sein.
Ich habe es nicht hinbekommen, dass die Funktion TRUE geliefert hat, wenn der Domainpuffer nil war (und dessen Längen-Begleiter).
ODER: Die Funktion scheitert zwar nicht mit einer AV, jedoch gibt sie eben auch kein TRUE zurück.

Delphi-Quellcode:

uses
  JclDebug,
  jwaWindows,
  jwaSddl,
  Windows;

function StrSIDToName(const StrSID: widestring; var Name: wideString; var SIDType: DWORD): Boolean;
var
  SID              : PSID;
  Buffer,B2            : PwideChar;
  NameLen, TempLen : Cardinal;
  success           : Boolean;
  TS : TSecurityID;
  res : Integer;
begin
  SID := nil;
  success := true;

  success := ConvertStringSidToSidW(PWideChar(StrSID), jwaWindows.PSID(SID));
  if success then
  begin
    NameLen := 0;
    TempLen := 0;
    SetLastError(0);
    if not LookupAccountSidW(nil, SID, nil, NameLen, nil, TempLen, SIDType) and
       (GetLastError() = ERROR_INSUFFICIENT_BUFFER) then
    begin
      GetMem(Buffer, NameLen * sizeOf(wideChar));
      GetMem(B2, TempLen * sizeOf(wideChar));


      if (Buffer <> nil) then
      try
        SetLastError(0);
        success := LookupAccountSidW(nil, SID, Buffer, NameLen, B2, TempLen, SIDType);
        if not success then
          RaiseLastOSError;
        if success then
          SetString(Name, Buffer, Namelen);
      finally
        FreeMem(Buffer);
        FreeMem(B2);
      end;
    end
    else
      RaiseLastOSError;
  end
  else
    RaiseLastOSError;

  LocalFree(HLOCAL(SID));
  result := success;
end;
In meiner Security Library habe ich übrigens diesen Code in etwa auch so drin. Und den verwende ich ständig :D, besonders auch, da SIDs eigentlich überall gebraucht werden.

marabu 4. Aug 2007 19:05

Re: AV bei LookupAccountSidW
 
Hallo,

ich kann leider momentan nicht testen, aber nach Aktenlage würde die Funktion bei mir etwa so aussehen:

Delphi-Quellcode:
function StrSIDToName(const StrSID: WideString; var Name: WideString; var SIDType: DWORD): Boolean;
var
  SID: PSID;
  bufName, bufDomain: PWideChar;
  sizeName, sizeDomain: Cardinal;
begin
  SID := nil;
  if ConvertStringSidToSidW(PWideChar(StrSID), SID) then
  begin
    sizeName := 0;
    sizeDomain := 0;
    SetLastError(0);
    Result := LookupAccountSidW(nil, SID, nil, sizeName, nil, sizeDomain, SIDType);
    if not Result and (GetLastError() = ERROR_INSUFFICIENT_BUFFER) then
    begin
      GetMem(bufName, sizeName * SizeOf(WideChar));
      GetMem(bufDomain, sizeDomain * SizeOf(WideChar));
      SetLastError(0);
      Result := LookupAccountSidW(nil, SID, bufName, sizeName, bufDomain, sizeDomain, SIDType);
      if Result
        then Name := WideString(bufName)
        else Name := '';
      FreeMem(bufName);
      FreeMem(bufDomain);
    end;
  end;
  LocalFree(HLOCAL(SID));
  Result := True;
end;
GetLastError() würde ich außerhalb verwenden, sonst macht Result keinen Sinn mehr und man könnte gleich eine Prozedur verwenden.

Freundliche Grüße

Dezipaitor 4. Aug 2007 19:23

Re: AV bei LookupAccountSidW
 
Zitat:

Zitat von marabu
Hallo,

GetLastError() würde ich außerhalb verwenden, sonst macht Result keinen Sinn mehr und man könnte gleich eine Prozedur verwenden.

hä?

Christian Seehase 4. Aug 2007 19:48

Re: AV bei LookupAccountSidW
 
Moin Zusammen,

ich hab' mir das Ganze gerade mal im CPU-Fenster angesehen.
Einmal mit LookupAccountSidA, einmal mit LookupAccountSidW.
In beiden Fällen war die Länge für ReferencedDomainName ermittelt, als Buffer aber nil übergeben worden.
(Also der zweite Aufruf)

Der Witz ist:
Nachdem die Funktionen den Stack mit Parametern gefüllt haben, laufen sie an der gleichen Stelle weiter (so etwas passiert ja öfter, bei Funktionen, die es in beiden Varianten gibt).
Beim Aufruf von RtlCopyUnicodeString schlägt dann die Unicode-Version fehl, die andere läuft durch. :gruebel:
Ich hatte jetzt allerdings nicht den Nerv mir herauszusuchen, wie nil für ReferencedDomainName nach Unicode umgewandelt wird, so dass der Aufruf nicht fehlschlägt, obwohl kein Buffer angegeben wird.

Luckie 4. Aug 2007 22:20

Re: AV bei LookupAccountSidW
 
Mann. Das ist ja ein Krampf mit der Funktion. Wer hat denn da jetzt Mist gebaut? Borland oder Microsoft?

Dezipaitor 4. Aug 2007 22:38

Re: AV bei LookupAccountSidW
 
Ich tippe auf MS. Das scheint entweder nicht dokumentiert zu sein - keiner hat die KB durchgesucht danach - oder es weiß einfach keiner :D

Wenn ich ne LiveID hätte, dann würde ich nen Kommentar zum MSDN Eintrag schreiben und warnen :D

Christian Seehase 5. Aug 2007 01:59

Re: AV bei LookupAccountSidW
 
Moin Dezipaitor,

Zitat:

Zitat von Dezipaitor
Ich tippe auf MS.

Da tippst Du richtig.
Ich habe das Ganze mal im Visual Studio 2005 Express nachgebaut:
LookupAccountSidW mit dem Parameter Domain auf nil (bzw. NULL) schlägt, wie gehabt, fehl (AV: Zugriff verweigert beim Zugriff auf Adresse 0), wohingegen LookupAccountSidA klaglos ausgeführt wird. Das ist dann auch daran zu sehen, dass der Name korrekt gefüllt ist.

Dezipaitor 5. Aug 2007 13:36

Re: AV bei LookupAccountSidW
 
Liste der Anhänge anzeigen (Anzahl: 1)
Hu, gewonnen!

Man daran hab ich garnet gedacht. Also das Zeugs in C++ zu machen :D - oder ich war einfach zu faul dafür.

---

Ich mach mal ne Konklusion/Schlussfolgerung:

Verwende niemals nil in der Unicodevariante von LookupAccountSid (=LookupAccountSidW) für den Parameter lpReferencedDomainName alleine. Entweder du setzt den Parameter lpName UND lpReferencedDomainName auf nil und übergibst über eine Variable 0 an
cchReferencedDomainName und cchName, oder du erstellst einen Puffer (mit GetMem) mit der korrekten Größe für beide Parameter.

Ein funktionierendes Beispiel findest du entweder von marabu oder von meiner Wenigkeit.

Alles andere ist schlecht :D


Ich würde ja einen Kommentar in die MSDN für LookupAccountSid schreiben, wenn ich eine LiveID hätte oder mich einschreiben könnte. Da jedoch derzeit jedesmal "We're unable to complete your request Windows Live ID is experiencing technical difficulties. Please try again later." geht es nicht. Also freiwillige vor?

P.S.
Hat das jemand mal unter Vista probiert?

Anbei ein Testprogramm nebst Quelltext zum Testen.

---
Delphi-Quellcode:
zweiter Aufruf von RtlCopyUnicodeString
--------------------------------
movzx  eax, word ptr [eax]
cmp    ax, cx
push   edi
mov    edi, [edx+$04]
mov    [ebp+$08], edi
jnbe   +$0000FC37
mov    ecx, eax
mov    ebx, ecx
shr    ecx, $02
mov    [edx], ax
rep    movsd                 ; hier EXCEPTION

mov    ecx, ebx
and    ecx, +$03
rep
movsb
mov    cx, word ptr [edx]
cmp    cx, word ptr [edx+$02]
pop    edi
pop    esi
pop    ebx
Vor der Exception wird versucht an Speicherposition [EDI] zu schreiben. Da dies jedoch 0 ist, schlägt der Zugriff fehl. Ich hab das Register mal umgebogen auf ne andere Adresse und schon hatte ich die Exception mit genau der Adresse von EDI - also liegt es daran.


Hier das Problem mit RtlCopyUnicodeString

Delphi-Quellcode:
var us,u2 : TUnicodeString;
begin
  us.Length := 4; //Pufferlänge! nicht Stringlänge
  us.MaximumLength := 4;
  us.Buffer := WideString('a1'#0#0);

  u2.Length := 0;
  u2.MaximumLength := 2;
  GetMem(u2.Buffer,4*sizeof(WideChar));
 

  RtlCopyUnicodeString(@u2,@us); //ok

  p := nil;

  try
    RtlCopyUnicodeString(p,@us); // Exception
  except
    on E : EAccessViolation do
     Writeln(E.Message);
  end;

Dezipaitor 6. Aug 2007 18:02

Re: AV bei LookupAccountSidW
 
*push*

Olli 9. Aug 2007 02:18

Re: AV bei LookupAccountSidW
 
Hier mal etwas menschenlesbarer
Code:
.text:7C924CE1 ; int __stdcall RtlCopyUnicodeString(PUNICODE_STRING DestinationString,PUNICODE_STRING SourceString)
.text:7C924CE1                 public _RtlCopyUnicodeString@8
.text:7C924CE1 _RtlCopyUnicodeString@8 proc near      ; CODE XREF: RtlConvertSidToUnicodeString(x,x,x)+158p
.text:7C924CE1                                         ; LdrLoadAlternateResourceModule(x,x)+34A22p ...
.text:7C924CE1
.text:7C924CE1 DestinationString= dword ptr 8
.text:7C924CE1 SourceString   = dword ptr 0Ch
.text:7C924CE1
.text:7C924CE1 ; FUNCTION CHUNK AT .text:7C934947 SIZE 00000014 BYTES
.text:7C924CE1
.text:7C924CE1                 mov    edi, edi
.text:7C924CE3                 push   ebp
.text:7C924CE4                 mov    ebp, esp
.text:7C924CE6                 mov    eax, [ebp+SourceString]
.text:7C924CE9                 test   eax, eax       ; Test pointer
.text:7C924CEB                jz     BailOut01
.text:7C924CF1                 mov    edx, [ebp+DestinationString]
.text:7C924CF4 ; CX = DestinationString.MaximumLength
[color=blue].text:7C924CF4                 mov    cx, [edx+UNICODE_STRING.MaximumLength][/color]
.text:7C924CF8                 push   ebx
.text:7C924CF9                 push   esi
.text:7C924CFA ; ESI = SourceString.Buffer
.text:7C924CFA                mov    esi, [eax+UNICODE_STRING.Buffer]
.text:7C924CFD ; EAX = SourceString.Length
.text:7C924CFD                movzx  eax, [eax+UNICODE_STRING.Length]
.text:7C924D00 ; if(AX > CX) ...
.text:7C924D00                 cmp    ax, cx         ; Does it fit?
.text:7C924D03                 push   edi
[color=red].text:7C924D04                 mov    edi, [edx+UNICODE_STRING.Buffer][/color]
.text:7C924D07                 mov    [ebp+DestinationString], edi ; "Misuse" the stack location ;)
.text:7C924D0A                ja     TruncateToMaxLength
.text:7C924D10
.text:7C924D10 BackFromTruncate:                      ; CODE XREF: RtlCopyUnicodeString(x,x)+FC69j
.text:7C924D10                 mov    ecx, eax       ; EAX contains number of bytes
.text:7C924D12                 mov    ebx, ecx       ; Save for later (ECX gets decremented)
.text:7C924D14                 shr    ecx, 2          ; Divide by sizeof(DWORD)
.text:7C924D17 ; Now store either the Length of SourceString or MaxLength
.text:7C924D17 ; of DestinationString into DestinationString.Length
[color=darkgreen].text:7C924D17                 mov    [edx+UNICODE_STRING.Length], ax[/color]
[color=red].text:7C924D1A                rep movsd              ; Copy DWORD-wise into buffer @EDI[/color]
.text:7C924D1C                mov    ecx, ebx       ; Restore size in Bytes into ECX
.text:7C924D1E                and    ecx, 3          ; Remainder from SHR
.text:7C924D21                 rep movsb              ; Copy remaining Bytes (byte-wise)
.text:7C924D23                 mov    cx, [edx+UNICODE_STRING.Length]
.text:7C924D26                 cmp    cx, [edx+UNICODE_STRING.MaximumLength]
.text:7C924D2A                pop    edi            ; Restore from 7C924D03
.text:7C924D2B                pop    esi            ; Restore from 7C924CF9
.text:7C924D2C                pop    ebx            ; Restore from 7C924CF8
.text:7C924D2D                jnb    short ExitThis
.text:7C924D2F ; Zero-terminate DestinationString only if we have
.text:7C924D2F ; enough space. Otherwise get out.
.text:7C924D2F                mov    ecx, [ebp+DestinationString]
.text:7C924D32                 shr    eax, 1          ; Divide by 2 (== sizeof WCHAR)
.text:7C924D34                 and    word ptr [ecx+eax*2], 0 ; Zero-terminate
.text:7C924D39
.text:7C924D39 ExitThis:                              ; CODE XREF: RtlCopyUnicodeString(x,x)+4Cj
.text:7C924D39                                         ; RtlCopyUnicodeString(x,x)+FC75j
.text:7C924D39                 pop    ebp
.text:7C924D3A                retn   8
.text:7C924D3A _RtlCopyUnicodeString@8 endp
An 7C924D1A wird EDI gesetzt also der Zielpuffer. Die Stackposition des übergebenen Parameters wird dazu temporär "mißbraucht", nicht wundern, das ist normal (macht der Compiler).

Ich bitte festzuhalten, daß in der blau markierten Zeile bei dem 2ten Aufruf von Dezi's Testprogramm bereits einmal von Adresse 2 (nil+2) gelesen wird (formal PUNICODE_STRING(p)^.MaximumLength, also 2 Bytes/1 Word). In der ersten roten Zeile wird von Adresse 4 (nil+4) gelesen (formal PUNICODE_STRING(p)^.Buffer, also 4 Bytes/1 DWORD).

Und jetzt kommt der wunde Punkt. Wieso knallt's in der zweiten roten Zeile und nicht bereits in der Zeile davor (grün), wo ja bereits an 0 (nil) geschrieben wird (formal PUNICODE_STRING(p)^.Length, also 2 Bytes)? Könnte was mit Speicheralignment zu tun haben, vielleicht ist aber einfach die Beobachtung von Dezi falsch oder falsch interpretiert?!

Da (p == nil), folgt:

Delphi-Quellcode:
PUNICODE_STRING(nil)^.Length := Irgendwas;
... das kann man in Delphi, soweit ich mich entsinne, auch exakt so ausdrücken und kompilieren!!!

Das würde in jeder Hinsicht knallen. Am Anfang der Funktion wird auch nur SourceString überprüft, jedoch nicht DestinationString - was theoretisch bereits in Bailout01 schiefgehen sollte!

Code:
.text:7C93494F BailOut01:                             ; CODE XREF: RtlCopyUnicodeString(x,x)+Aj
.text:7C93494F                mov    eax, [ebp+DestinationString]
[color=red].text:7C934952                 and    [eax+UNICODE_STRING.Length], 0[/color]
.text:7C934956                 jmp    ExitThis
.text:7C934956 ; END OF FUNCTION CHUNK FOR _RtlCopyUnicodeString@8
Eine Übergabe von nil für beide Parameter sollte also genauso zum Absturz führen, da hier wiederum an Adresse 0 (nil) geschrieben wird (rote Zeile, zwei Bytes, entsrpricht der grünen Zeile von oben).

Luckie 9. Aug 2007 09:26

Re: AV bei LookupAccountSidW
 
Aber hätte das Microsoft nicht bei der Qualitätskontrolle auffallen müssen? ;)

Dezipaitor 9. Aug 2007 11:17

Re: AV bei LookupAccountSidW
 
Welche QM ? :D

Christian Seehase 9. Aug 2007 22:01

Re: AV bei LookupAccountSidW
 
Moin Zusammen,

also ich sehe es jetzt nicht gerade als ein Problem an, dass die W-Funktion nicht sauber durchläuft, wenn sie mit ungültigen Parametern aufgerufen wird, sondern dass die A-Variante es tut.
Die W-Variante müsste natürlich, sinnvoller Weise, 87 zurückmelden, statt auf eine AV aufzulaufen, aber den eigentlichen Fehler sehe ich in der anderen Version, da die Parameter, zumindest gemäss Doku, so nicht nicht zulässig sind.

Olli 10. Aug 2007 08:47

Re: AV bei LookupAccountSidW
 
Christian, das sehe ich ganz ähnlich. Zumal es sinnlos ist RtlCopyUnicodeString mit nur einem (gültigen) Parameter aufzurufen. Die einzige Sache welche mich daran stört ist, daß der eine Parameter (nämlich SourceString) durchaus überprüft wird (siehe 7C924CE9), so daß es irgendwie auch wieder inkonsequent ist den zweiten Parameter nicht auch zu überprüfen.

Auf der anderen Seite muß man es abwägen, da zuviel Fehlerüberprüfung Performance kostet. Formal müßte man zum komplettieren ja auch überprüfen ob der Pointer gültig ist (nicht nur ob er ungleich nil ist) und ob man mindestens sizeof(UNICODE_STRING) lesen/schreiben kann und ob das auch für den Pointer in us.Buffer gilt.

Christian Seehase 13. Aug 2007 15:42

Re: AV bei LookupAccountSidW
 
Moin Olli,

Zitat:

Zitat von Olli
Auf der anderen Seite muß man es abwägen, da zuviel Fehlerüberprüfung Performance kostet.

Wobei mangelnde Fehlerprüfung zu Sicherheitslücken führen kann.
Da ist mir die Vorabprüfung aber lieber ;-)

Dezipaitor 13. Aug 2007 16:01

Re: AV bei LookupAccountSidW
 
wobei man hätte die Überprüfung auch bei
LookupAccountSidW
einbauen können.

Olli 2. Sep 2007 03:15

Re: AV bei LookupAccountSidW
 
Frage noch immer offen?

Dezipaitor 2. Sep 2007 12:13

Re: AV bei LookupAccountSidW
 
Die Frage ist offener als ein Scheunentor groß sein kann.

Ich darf mal das Szenario nachstellen :

Microsoft macht in etwa das:
Code:
CSidData::InternalLookUpSids(..., ISecurityInformation2 pS2, ...);
{
  ..
  ..
  LPDataObject lpDO = NULL;
  ...
  HRESULT hr = pS2->LookUpSids(..., lpDO); //mein Aufruf OK
  if (hr <> S_OK)
    FAIL

  hr = lpDO->GetData(....);  //exception hier ( call dword ptr [ecx+$0c] )
  if (hr <> S_OK)
    FAIL
  ...
}
Es sieht so aus, als ob die Speicherstelle bei [ecx+$0c] garnicht mein GetData ist.
Der Vergleich von @GetData mit der Stelle ergibt über $300-$1000 Bytes Unterschied.

Ich bin echt ratlos, besonders da eine reine C++ Implementierung einwandfrei funktioniert.
Auch eine komplette neue Implementation des SecurityDialogs unter Delphi mit
sowenig Code wie möglich, läuft auf dasselbe hinaus.

Es scheint als hätte Borland einen totalen Sc*****d**** gemacht - oder es liegt an was anderes.
Auf jeden Fall bin ich verzweifelt - soetwas hab ich noch nie erlebt.

---

EDIT: Fehler im Code korrigiert.

Christian Seehase 2. Sep 2007 12:44

Re: AV bei LookupAccountSidW
 
Moin Dezipaitor,

hast Du mal in Erwägung gezogen, die benötigten Funktionen (und ggf. Strukturen) selber zu deklarieren?

Im Gegensatz zu Borland, importiere ich die Funktionen immer so, dass ich alle Parameter als const deklariere, und dann, bei den var Parametern gezielt Pointer übergebe, da diese Vorgehensweise eher dem entspricht, was man dann auch in Beispielen findet.
Ausserdem kann man bei einem var-Parameter auch nicht nil übergeben, was ja bei vielen Funktionen durchaus zulässig ist.


Alle Zeitangaben in WEZ +1. Es ist jetzt 17:19 Uhr.

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