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/)
-   -   Delphi Security_Descriptor ändern (https://www.delphipraxis.net/98954-security_descriptor-aendern.html)

Apollonius 4. Sep 2007 15:20


Security_Descriptor ändern
 
Ich habe mir kürzlich mal Gedanken gemacht, wie man verhindern könnte, dass ein anderer Prozess mit WriteProcessMemory Variablen meines Programms verändert. Da bietet sich natürlich an, zu verhindern, dass ein Handle meines Prozesses mit den nötigen Rechten PROCESS_VM_WRITE und PROCESS_VM_OPERATION geöffnet wird. Da ließe sich ja etwas mit dem Security-Descriptor meines Prozesses drehen. Kann man denn den eigenen Security-Descriptor verändern, oder ist das (zum Beispiel für Debugging etc.) verboten? Wenn ja - wie geht es? Ich habe die MSDN durchforstet, da ist zu dem Thema auch viel zu finden, aber auf eine Funktion zum Setzen eines neuen Descriptors bin ich nicht gestoßen.

Olli 4. Sep 2007 21:24

Re: Security_Descriptor ändern
 
Aehnliches Problem: http://assarbad.net/de/stuff/temp/KillMeSoftly/
Ansonsten frage "Dezipaitor" zum Thema :zwinker:

Dezipaitor 4. Sep 2007 21:36

Re: Security_Descriptor ändern
 
Du kannst die Prozess DACL mit SetSecurityInfo mit ObjectType =
SE_KERNEL_OBJECT setzen.
Theoretisch, da ich es selbst nicht probiert habe.

ABER: Der Besitzer eines Security Descriptor kann immer die ACL ändern! Besitzer kann jeder werden dem es über die ACL erlaubt ist.
Zudem können bestimmte Gruppen, auch ohne diese ACL Rechte, Besitzer übernehmen. Administratoren können dies z.B. RestoreOperatoren (auch Administratoren)
ist es auch erlaubt, den Besitzer beliebig zu wählen.
Das gilt übrigens natürlich auch für DIENSTE.

Debuggerbenutzer haben da jedoch nicht viel zu sagen, was den Security Descriptor angeht.

Einen Security kann man auf verschiedene Arten bauen..
Die einfachste Art mit Win32API Mitteln ist ConvertStringSecurityDescriptorToSecurityDescripto r

Am einfachsten wird es sowieso mit meiner Bibliothek.

Apollonius 5. Sep 2007 17:34

Re: Security_Descriptor ändern
 
Zitat:

ABER: Der Besitzer eines Security Descriptor kann immer die ACL ändern! Besitzer kann jeder werden dem es über die ACL erlaubt ist.
Zudem können bestimmte Gruppen, auch ohne diese ACL Rechte, Besitzer übernehmen. Administratoren können dies z.B. RestoreOperatoren (auch Administratoren)
Soll das heißen, dass Administratoren unabhängig von Descriptor den Prozess mit Process_All_Access öffnen können? Das wäre ja nochmal ein dicker Grund, nicht als Admin zu arbeiten.
Danke schonmal für eure Hilfe.

Dezipaitor 5. Sep 2007 18:03

Re: Security_Descriptor ändern
 
Zitat:

Zitat von Apollonius
Zitat:

ABER: Der Besitzer eines Security Descriptor kann immer die ACL ändern! Besitzer kann jeder werden dem es über die ACL erlaubt ist.
Zudem können bestimmte Gruppen, auch ohne diese ACL Rechte, Besitzer übernehmen. Administratoren können dies z.B. RestoreOperatoren (auch Administratoren)
Soll das heißen, dass Administratoren unabhängig von Descriptor den Prozess mit Process_All_Access öffnen können? Das wäre ja nochmal ein dicker Grund, nicht als Admin zu arbeiten.
Danke schonmal für eure Hilfe.

Können sie nicht unbedingt. Administratoren unterliegen wie alle anderen Nutzer auch dem Rechtesystem. Sie haben bloß den Vorteil, sich das Recht (wie auch immer) verschaffen zu können.
Man sieht es gut an dem Ordner "System Volume Information". Ein Admin kann es sich per default nicht ansehen. Er kann jedoch die DACL anpassen und dann sich den Inhalt ansehen.

Das hemmt schonmal einige Programme, die normal auf etwas zugreifen wollen. Die meisten Programme geben dann auf.

Apollonius 5. Sep 2007 18:09

Re: Security_Descriptor ändern
 
Hm. Irgendwo in meinem Code ist noch ein Fehler, denn auch als Gast kriege ich ein gültiges Handle...
Programm 1:
Delphi-Quellcode:
program Project2;

uses
  Forms,
  Windows,
  AclAPI,
  AccCtrl,
  sysutils,
  dialogs,
  Unit1 in 'Unit1.pas' {Form1};

{$R *.res}
const PROTECTED_DACL_SECURITY_INFORMATION = $80000000; //DACLs werden nicht vererbt
var desc: SECURITY_DESCRIPTOR;
begin
  InitializeSecurityDescriptor(@desc, SECURITY_DESCRIPTOR_REVISION);
  SetSecurityDescriptorDACL(@desc, false, nil, false);
  Showmessage(SysErrorMessage(SetSecurityInfo(getCurrentProcess, SE_KERNEL_OBJECT, DACL_SECURITY_INFORMATION or PROTECTED_DACL_SECURITY_INFORMATION, nil, nil, desc.Dacl, nil)));
  Application.Initialize;
  Application.CreateForm(TForm1, Form1);
  Application.Run;
end.
Ich hoffe mal, dass ich da mit der Api nicht ganz falsch liege. Auf Buttonklick wird eine Nachricht an ein zweites Programm mit geschickt, dabei wird die Adresse einer Variablen im WParam und das Hauptfensterhandle im LParam mitgeliefert.
Delphi-Quellcode:

procedure TForm1.rec(var Message:TMessage);
var ProcId, ProcHandle: Cardinal; buffer, dummy: cardinal;
begin
getWindowThreadProcessId(Message.LParam, ProcId);
ProcHandle:=OpenProcess(PROCESS_VM_WRITE or PROCESS_VM_OPERATION, false, ProcID);
if ProcHandle=0 then
 begin
  showmessage('Prozess-Handle ist Null!');
  exit;
 end;
showmessage('Gueltiges Prozess-Handle');
try
 buffer:=5;
 WriteProcessMemory(ProcHandle, Pointer(Message.WParam), @buffer, 4, dummy);
finally
 closeHandle(ProcHandle);
end;
end;
Und ich kriege immer ein gültiges Handle. Wo steckt der Fehler?

Dezipaitor 5. Sep 2007 19:02

Re: Security_Descriptor ändern
 
Zitat:

Zitat von Apollonius
Hm. Irgendwo in meinem Code ist noch ein Fehler, denn auch als Gast kriege ich ein gültiges Handle...
Programm 1:
[/delphi]
Und ich kriege immer ein gültiges Handle. Wo steckt der Fehler?

Du setzt nil für die DACL ein. Das bedeutet, dass JEDER (damit auch Gast) vollen Zugriff auf das Objekt hat. Du musst schon einen DACL erzeugen und auch Benutzer einfügen. Wenn du die DACL leer lässt, dann darf niemand mehr auf das Objekt zugreifen. Dann kommt wieder, wie oben schon geschrieben, der Besitzer ins Spiel.

Die DACL zu ändern ist etwas aufwendig in C. Deshalb meinte ich ja, dass du ConvertStringTo... verwenden sollst.

Apollonius 5. Sep 2007 19:31

Re: Security_Descriptor ändern
 
Hm. Ich zitiere mal aus SetSecurityDescriptorDACL:
Zitat:

When the pDacl parameter does not point to a DACL and the bDaclPresent flag is FALSE, a DACL can be provided for the object through an inheritance or default mechanism.
Ich habe das so interpretiert, dass dann niemand Zugriff hat. Tja, falsch gedacht...


Ich habe mir auch vorher schonmal diese tolle "Sprache" für die Descriptors angeschaut, aber das sieht einfach nur furchtbar aus. Und ich verstehe nicht ganz, wie ich zum Beispiel die Rechte, die es nur für Prozesse gibt, geben oder nehmen kann.

Apollonius 6. Sep 2007 20:33

Re: Security_Descriptor ändern
 
So richtig geklärt haben wir das ja nicht. Was für einen String brauche ich denn beispielsweise, wenn ich den Prozess-Handle-Öffnern das Recht PROCESS_VM_READ verwehren will, er aber alles andere bekommen soll? Diese Beschreibungen der Descriptor-Sprache sind für mich absolut kryptisch...
Danke im Vorraus
Apollonius

Dezipaitor 6. Sep 2007 23:43

Re: Security_Descriptor ändern
 
Liste der Anhänge anzeigen (Anzahl: 1)
Ich habe mal schnell ein Progrämmchen geschrieben, dass Strings in einen Security Descriptor und zurück verwandelt.

Man kann den String ins Memo schreiben und dann den Button drücken - oder es einfach leer lassen und im ACL Editor die Einstellungen vornehmen und dann ins Memo schreiben lassen.
Mit der ComboBox kann man bestimmen, welche Art Objekt umgegangen werden soll - ich habe sie nicht alle getestet, daher kann es noch zu Merkwürdigkeiten kommen.

Ich hab das Programm sehr schnell runter-gehackt und daher nicht großartig getestet. Mit Fehlern müssen wir daher Leben.

Apollonius 7. Sep 2007 16:34

Re: Security_Descriptor ändern
 
Dein Programm funktioniert bei mir nicht, das einzige, was erscheint, ist ein Eintrag in der Taskleiste.

Ich habe mittlerweile mal versucht, mich selbst mit dem Thema auseinanderzusetzen, allerdings schmeißt mir der Aufruf der Convert-Funktion immer einen ERROR_INVALID_SID. :(
Delphi-Quellcode:
program Project2;

uses
  Forms,
  Windows,
  AclAPI,
  AccCtrl,
  sysutils,
  dialogs,
  zuVeraendern in 'zuVeraendern.pas' {Form1};

{$R *.res}
type PPSECURITY_DESCRIPTOR=^PSECURITY_DESCRIPTOR;
     SecDescToStrFunc=function(StringSecurityDescriptor: PChar; StringSDRevision: DWORD; var SecurityDescriptor: PSECURITY_DESCRIPTOR; var SecurityDescriptorSize: ULONG): boolean; stdcall;

const PROTECTED_DACL_SECURITY_INFORMATION = $80000000;
      SDDL_REVISION_1=1; //Konstanten muss man sich wohl selbst deklarieren
      DLLName='Advapi32.dll';
var desc: PSECURITY_DESCRIPTOR; SecDescStr: ansistring; Size: ULong;
    func: SecDescToStrFunc; lib: hModule;
begin
  lib:=loadLibrary(DLLName);
  showmessage(inttostr(lib));
  func:=getProcAddress(lib, 'ConvertStringSecurityDescriptorToSecurityDescriptorA');
  showmessage(inttostr(integer(@func)));
  SecDescStr:='D:P(A;;0x'+inttohex(Process_All_Access xor Process_VM_Read, 8)+';;;WD)';//Ich hoffe mal, das ist nicht zu falsch...
  func(PChar(SecDescStr), SDDL_REVISION_1, Desc, size);
  showmessage(SysErrorMessage(getLastError)); //Fehler
  showmessage(inttostr(size)); //null
  Showmessage(SysErrorMessage(SetSecurityInfo(getCurrentProcess, SE_KERNEL_OBJECT, DACL_SECURITY_INFORMATION or PROTECTED_DACL_SECURITY_INFORMATION, nil, nil, SECURITY_DESCRIPTOR(desc^).Dacl, nil)));//Folgefehler Zugriffsverletzung
  Application.Initialize;
  Application.CreateForm(TForm1, Form1);
  Application.Run;
  LocalFree(Cardinal(desc));
  FreeLibrary(lib);
end.
Irgendjemand Vorschläge? Bestürzenderweise bekomme ich selbst dann einen "invalid sid", wenn ich die Strings aus den Microsoft-Beispielen nehme...

Apollonius

Dezipaitor 7. Sep 2007 16:52

Re: Security_Descriptor ändern
 
Das Programm funktioniert. Nur hast du keinen zweite Bildschirm :D
Das Fenster ist deshalb außerhalb des sichtbaren Bereichs und man muss es über die Taskleiste verschieben.

Delphi setzt standardmäßig die Designkoordinaten für die Fensterposition.

Ich habe erneut hinaufgeladen.

Apollonius 7. Sep 2007 18:07

Re: Security_Descriptor ändern
 
:firejump: :party: ES FUNKTIONIERT!!! :dancer: :dp:
Wenn man auf die DACL-Falgs verzichtet, glückt der Aufruf der Convert-Funktion. Danach ist es nur noch eine Frage der Zeit, bis man darauf kommt, dass man mit MakeAbsoluteSD den Security-Descriptor wandeln muss, damit SetSecurityInfo die DACL akzeptiert und man darüber hinwegkommen ist, dass MakeAbsoluteSD streikt, wenn man für Parameter, die man nicht braucht, einfach nil eizusetzen versucht. Zuguterletzt ist es mir aber gelungen, meine Prozesshandles nur mit ganz spezifischen Rechten öffnen zu lassen. Ich werde das ganze jetzt in eine Funktion packen und in der Codelibrary posten.

:dp: und ein RIESEN-DANKE an Dezipaitor!

Dezipaitor 7. Sep 2007 18:42

Re: Security_Descriptor ändern
 
GetLastError ruft man nur dann auf, wenn eine API Funktion einen Fehler über den Rückgabewert meldet.
Es ist nämlich nicht definiert, dass LastError auf 0 gesetzt wird im Erfolgsfall.
Daher kann es auch im Erfolgsfall einen Wert ungleich 0 von GetLastError zurückgegeben werden.

Self-Relative SDs ist ein SD, der aus einem Stück Speicher besteht, der alles notwendige enthält. Diese Art wird
von API Funktionen zurückgegeben. Manche API Funktionen melden einen Fehler, wenn man so einen angibt.

Absolute SD ist ein SD, der zwar auch ein Speicherblock ist, aber nur Zeiger auf den Inhalt enthält. So zeigen
Owner, Group, DACL und SACL alle auf anderen Speicher. Diese Art von SD wird nur durch den Benutzer erstellt
und an API Funktionen übergeben.



Wie sieht denn nun dein String aus?
Meinst du mit DACL-Flags diese?: DACL_SECURITY_INFORMATION or PROTECTED_DACL_SECURITY_INFORMATION

PROTECTED_DACL_SECURITY_INFORMATION verwendet man, wenn übergeordnete Objekte ihre SD nicht ins aktuelle Objekt einbringen/vererben sollen. Soweit ich weiß unterstützt MS automatische Vererung nur bei Datei und Registry.
Wenn GetSecurityInfo bei einem Objekt UNPROTECTED_DACL_SECURITY_INFORMATION findet und es unterstützt Vererbund, dann sucht es beim Vorgänger rekursiv nach der DACL, bis es eine findet, die nicht vererbt ist. Dann wird die vererbte DACL zurückgegeben.

Man kann dieses System auf eigene Objekte übernehmen.

Apollonius 7. Sep 2007 19:01

Re: Security_Descriptor ändern
 
Ja, das mit getLastError ist mir bekannt, das war ja auch nur Quick&Dirty.
Mit DACL-Flags meine ich den einen Bestandteil des Strings, der nach 'D:', aber vor dem ersten ACE-String steht:
Delphi-Quellcode:
'D:P'{Dieses P!}+'(A;;0x'+inttohex(Process_All_Access xor Process_VM_Read, 8)+';;;WD)';
Meine derzeitige Version für die Codelibrary (etwas verschönert :-D ), sieht so aus:
Delphi-Quellcode:
uses Sysutils,
     AclApi, //Für SetSecurityInfo
     AccCtrl; //Für SE_KERNEL_OBJECT als Wert einer Aufzählung
function ConvertStringSecurityDescriptorToSecurityDescriptorA(StringSecurityDescriptor: PChar; StringSDRevision: DWORD; var SecurityDescriptor: PSECURITY_DESCRIPTOR; SecurityDescriptorSize: PULONG): boolean; stdcall; external 'Advapi32.dll';
//Der letzte Parameter wird nicht als var deklariert, damit nil eingesetzt werden kann

procedure SetProcessHandleRights(Rights: Cardinal);
const PROTECTED_DACL_SECURITY_INFORMATION = $80000000;
      SDDL_REVISION_1=1;
var Desc: PSECURITY_DESCRIPTOR; SDDLString: ansistring;
    DACL: pACL; err: cardinal;
    d1, d2: LongBool; //Dummies
begin
SDDLString:='D:(A;;0x'+inttohex(Rights, 8)+';;;WD)'; //Näheres im PSDK unter SDDL
if not ConvertStringSecurityDescriptorToSecurityDescriptorA(PChar(SDDLString), SDDL_REVISION_1, Desc, nil) then
 raise EOSError.CreateFmt('Error in function ConverStringSecurityDescriptorToSecurityDescriptorA: %s', [syserrormessage(getLastError)]);
if not getSecurityDescriptorDACL(desc, d1, DACL, d2) then
 raise EOSError.CreateFmt('Error in function getSecurityDescriptorDACL: %s', [syserrormessage(getLastError)]);
err:=SetSecurityInfo(getCurrentProcess, SE_KERNEL_OBJECT, DACL_SECURITY_INFORMATION or PROTECTED_DACL_SECURITY_INFORMATION, nil, nil, DACL, nil);
if err<>0 then
 raise EOSError.CreateFmt('Error in function setSecurityInfo: %s', [syserrormessage(err)]);
end;
Es funktioniert auf jeden Fall schonmal. Falls du keine Einwände hast, werde ich das dann mal für die Library posten.
Du kriegst natürlich eine Erwähnung, schließlich hast du einen großen Teil dazu beigetragen.
Apollonius

[edit] Dank Dezipaitor noch einen Lapsus behoben. [/edit]

Dezipaitor 7. Sep 2007 19:27

Re: Security_Descriptor ändern
 
Warum konvertierst du den SD überhaupt? Die Arbeit kannst du dir sparen, da du den neuen SD sowieso nicht verwendest.
Benutze stattdessen GetSecurityDescriptorDacl. Dann haste die DACL sofort.

Apollonius 7. Sep 2007 21:45

Re: Security_Descriptor ändern
 
Zitat:

Warum konvertierst du den SD überhaupt?
Irgendwie geht mir das mit der WinAPI oft so: ich finde eine Lösung, aber längst nicht die beste.
Irgendeine Idee wegen den DACL-Flags? Ist für die spezielle Aufgabe nicht von Belang, aber interessieren würde es mich trotzdem.

Dezipaitor 7. Sep 2007 22:18

Re: Security_Descriptor ändern
 
Zitat:

Zitat von Apollonius
Zitat:

Warum konvertierst du den SD überhaupt?
Irgendwie geht mir das mit der WinAPI oft so: ich finde eine Lösung, aber längst nicht die beste.
Irgendeine Idee wegen den DACL-Flags? Ist für die spezielle Aufgabe nicht von Belang, aber interessieren würde es mich trotzdem.

Sorry, ich verstehe nicht genau was du wissen willst, wegen den DACL-Flags.
Meinst du die SD ControlFlags oder
die SecurityInformationFlags.
Das erste gibt Information über den SD. Das zweite gibt einer API Funktion den Befehl, welche Art von Information
(DACL, Group, usw + Protected, Unprotected) im SD des Objekts geändert werden soll.

Die Grundlagen über Window Security Programming kannst du hier nachlesen. Davon hab ichs auch gelernt, wenn auch von der Buchversion.

Warnung:
Das Thema kann sehr aufregend, aber auch frustrierend sein. Bei der Implementierung der Security API hab ich das immer wieder durch gemacht. Aus Fehlern lernt man aber unglaublich viel :D

Apollonius 8. Sep 2007 12:02

Re: Security_Descriptor ändern
 
Ich meine mit DACL-Flags einen Bestandteil des Strings, der in die Control-Flags übersetzt wird. Wenn ich jedoch an der vorgesehenen Stelle den erlaubten string 'P' einsetze, ist das Format ungültig, wie getLastError sagt.
Zitat:

Aus Fehlern lernt man aber unglaublich viel :-D
Wie könnte ich das bestreiten?

Dezipaitor 8. Sep 2007 12:12

Re: Security_Descriptor ändern
 
also ich hab man dein Beitrag zur Codelib übersetzt
und konnte den String "D:P(..." damit ohne Probs ausführen.

Apollonius 8. Sep 2007 12:36

Re: Security_Descriptor ändern
 
Bei mir gehts jetzt auch, da habe ich wohl irgendwo anders einen Fehler provoziert. :roll: Ist ja auch egal.

Dann werde ich den Code mal für die Library posten.


Alle Zeitangaben in WEZ +1. Es ist jetzt 05:35 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