| |
|
|
| Vor etwa einem Jahr habe ich in einem Delphiforum mal eine Interessante Fage gelesen, die mich seitdem nicht mehr losgelassen hat: Ist der Access Token, der Personalausweis eines Users der jedem Prozess zugeordnet wird, direkt änderbar? Normalerweise ist der Token nur über das mit OpenPocessToken zu erlangende Handle und die API zugänglich, d.h. man kann auch nur die Bereiche des Tokens ändern, auf die Winows über das Handle Zugriff erlaubt. Wie aber, wenn man herausfinden könnte wie und wo der dem eigenen Prozess zugeordnete Token sich im Speicher aufhält - wäre ein direkter Zugriff möglich, wären die Möglichkeiten und Auswirkungen unvorstellbar! Vor einer Zeit habe ich diese Suche begonnen und in diesem Thread soll es in der nächsten Zeit um diese Suche gehen. Leider habe ich heute zu wenig Zeit, um hier mehr zu Schreiben (Geld ist alle ), aber ich kann achon mal sagen, das ich bereits ein paar interessante Sachen gefunden habe. |
|
|
| |
|
|
|
| Bevor man etwas sucht ist es sinnvoll sich zu überlegen, wie das was man sucht in etwa aussehen könnte. Ein wichtiger Bestandteil eines Tokens ist die Userkennung (also der SID) des Users, dessen Ausweis der Token verkörpert. Wenn ich mich als Andreas mit meinem Kennwort in den Rechner einlogge, dürfte in jedem Token jedes Programms das ich starte also die Bytefolge des SIDs von Andreas stehen - eigentlich logisch.
Als Prozess, den ich untersuchen wollte, habe ich Notepad ausgewählt. Notepad ist ein einfacher Texteditor ohne viel Beiwerk - der Umfang des zugewiesenen Prozessspeichers dürfte also nicht sehr groß sein - eine Untersuchung des Prozessspeichers also nicht besonders lange dauern und nicht allzuviele Fundstellen liefern, die nicht zum Token gehören. TNT bietet eine ganze Menge Möglichkeiten, einen Accountnamen in eine hexadezimale SID-Bytefolge umzuwandeln - eine davon habe ich genützt und damit den SID in die Zwischenablage und später in die Funktion Speicher durchsuchen übertragen. Die Startadresse der Suche habe ich auf die Adresse 0. Gefunden habe ich dann genau das hier...
[...]
...nämlich gar nicht. Ein Token scheint sich also nicht im Userspeicher des jeweiligen Prozesses zu befinden - aber wo sucht man dann? In den Artikeln, die ich über den Token gelesen habe, war von einer Zuordnung zu den einzelnen Prozessen gesprochen worden - so eine Zuordnung muß ja nicht zwingendermaßen nur im Speicher des zugeordneten Prozesses stattfinden. Ich habe mich also dann dazu entschlossen, mir den Speicher anderer Prozesse mal etwas näher anzusehen. Als erstes habe ich den Service LSASS.EXE ausgewählt. Warum gerade diesen Prozess? Das hat etwas mit der Namensgebung zu tun... Da LSASS.EXE ein Service im Sytem-Account ist, mußte ich TNT zuerst einmal als Service starten, was über das Menü von TNT recht einfach möglich ist. Danach habe ich mir die Heaps des Prozesses listen lassen. Auch hier habe ich die Startadresse der Suche wieder auf 0 gesetzt - dann ging’s los. Bingo! Da haben wir ja schon mal was...
[...]
Weitere wichtige Bestandteile eines Tokens sind die LUIDs (64-Bit Kennzahlen) der Privilegien und deren jetziger Status (Attribute). Ein LUID läßt sich relativ einfach als hexadezimale Bytefolge aus der Token-Infos-Registrierkarte herauskopieren - also machen wir das mal. Das Privileg SeChangeNotifyPrivilege ist in jedem Account vorhanden, es bietet sich für eine Suche also an.
[...]
LUIDs von Privilegien stehen im Token immer in Verbindung mit ihren Attributen, also ihrem derzeitigen Status - wir brauchen also noch den Status des Privilegs SeChangeNotifyPrivilege => Standardmäßig aktiviert = SE_PRIVILEGE_ENABLED_BY_DEFAULT = $1 Aktiviert = SE_PRIVILEGE_ENABLED = $2 Zusammen wäre das dann $3, was einer hexadezimalen Bytefolge von 03000000 entspricht. Das, was ich bei mir zu suchen hätte, wäre also das hier:
[...]
Und das hier habe ich gefunden:
[...]
Jetzt schauen wir mal, ob es im Prozess LSASS.EXE einen Heapblock gibt, der beides enthält - den SID und das Privileg. Bei mir ist das der 592 Bytes große Heapblock mit der Adresse 750992, dessen Inhalt ich mir dann als hexadezimale Bytefolge darstellen lassen habe.
[...]
Um mir das ganze etwas näher ansehen zu können, habe ich dann den ganzen Block als hexadezimale Bytefolge in die Zwischenablage und danach in ein Wordpad-Dokument kopiert. Mal schauen, was ich da habe... [box:bc6ba1a7d2] 00000000FFFFFF7FFC750B0000000000B8750B0018760B00D8760B0040760B0098760B00000000000800000018760B000700000034760B000700000040760B000F00000050760B000700000060760B00070000C074760B000700000080760B00070000008C760B00070000000105000000000005150000000D7A5A338AA7323FF89FB474E80300000105000000000005150000000D7A5A338AA7323FF89FB474010200000101000000000001000000000102000000000005200000002002000001020000000000052000000021020000010300000000000505000000000000006B62000001010000000000020000000001010000000000050400000001010000000000050B00000002003400020000000000180000000010010200000000000520000000200200000000140000000010010100000000000512000000000000000000000000000000110000001700000000000000030000000800000000000000000000001100000000000000000000001200000000000000000000000C00000000000000000000001300000000000000000000001800000000000000000000001400000000000000000000001600000000000000000000000B00000000000000000000000D00000000000000000000000E00000000000000000000000A00000000000000000000000F0000000000000000000000050000000000000000000000190000000000000000000000090000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000500490000010C00 [/box:bc6ba1a7d2] Danach habe ich den Schrott etwas Strukturiert... [box:bc6ba1a7d2] 00000000FFFFFF7FFC750B0000000000B8750B0018760B00D8760B0040760B0098760B00000000000800000018760B000700000034760B000700000040760B000F00000050760B000700000060760B00070000C074760B000700000080760B00070000008C760B0007000000
0105000000000005150000000D7A5A338AA7323FF89FB474E8030000 => SID des ausführenden Users (Andreas)
Gruppen im Token 0105000000000005150000000D7A5A338AA7323FF89FB47401020000 => SID der Gruppe Kein 010100000000000100000000 => SID der Gruppe Jeder 01020000000000052000000020020000 => SID der Gruppe Administratoren 01020000000000052000000021020000 => SID der Gruppe Benutzer 010300000000000505000000000000006B620000 010100000000000200000000 => SID der Gruppe LOKAL 010100000000000504000000 => SID der Gruppe Interaktiv 01010000000000050B000000 => SID der Gruppe Authentifizierte Benutzer
Standard DACL 02 => Typ der Zugriffskontrollliste (ACL_REVISION) 00 => Zwei Nullbytes zur Anpassung 3400 => Größe des ACLs (= 52 Bytes) 0200 => Anzahl der ACEs in der Zugriffskontrollliste (= 2) 0000 => Zwei Nullbytes zur Anpassung 00 => Typ des 1.ACEs, ACE = Zugriffskontrolleintrag (= ACCESS_ALLOWED_ACE_TYPE) 00 => Flags (u.a.Vererbung) des 1.Zugriffskontrolleintrags 1800 => Größe des 1.Zugriffskontrolleintrags (=24 Bytes) 00000010 => Zugriffsmaske des 1.ACEs (GENERIC_ALL) 01020000000000052000000020020000 => SID der Gruppe Administratoren 00 => Typ des 2.Zugriffskontrolleintrags (= ACCESS_ALLOWED_ACE_TYPE) 00 => Flags (u.a.Vererbung) des 2.Zugriffskontrolleintrags 1400 => Größe des 2.Zugriffskontrolleintrags (=20 Bytes) 00000010 => Zugriffsmaske des 1.ACEs (GENERIC_ALL) 010100000000000512000000 => SID der Gruppe System
00000000000000000000000011000000
Privilegien im Token 1700000000000000 => Bei mir LUID des Privilegs SeChangeNotifyPrivilege 03000000 => Aktiviert und standardmäßig aktiviert 0800000000000000 => Bei mir LUID des Privilegs SeSecurityPrivilege 00000000 => deaktiviert 1100000000000000 => Bei mir LUID des Privilegs SeBackupPrivilege 00000000 => deaktiviert 1200000000000000 => Bei mir LUID des Privilegs SeRestorePrivilege 00000000 => deaktiviert 0C00000000000000 => Bei mir LUID des Privilegs SeSystemtimePrivilege 00000000 => deaktiviert 1300000000000000 => Bei mir LUID des Privilegs SeShutdownPrivilege 00000000 => deaktiviert 1800000000000000 => Bei mir LUID des Privilegs SeRemoteShutdownPrivilege 00000000 => deaktiviert 1400000000000000 => Bei mir LUID des Privilegs SeDebugPrivilege 00000000 => deaktiviert 1600000000000000 => Bei mir LUID des Privilegs SeSystemEnvironmentPrivilege 00000000 => deaktiviert 0B00000000000000 => Bei mir LUID des Privilegs SeSystemProfilePrivilege 00000000 => deaktiviert 0D00000000000000 => Bei mir LUID des Privilegs SeProfileSingleProcessPrivilege 00000000 => deaktiviert 0E00000000000000 => Bei mir LUID des Privilegs SeIncreaseBasePriorityPrivilege 00000000 => deaktiviert 0A00000000000000 => Bei mir LUID des Privilegs SeLoadDriverPrivilege 00000000 => deaktiviert 0F00000000000000 => Bei mir LUID des Privilegs SeCreatePagefilePrivilege 00000000 => deaktiviert 0500000000000000 => Bei mir LUID des Privilegs SeIncreaseQuotaPrivilege 00000000 => deaktiviert 1900000000000000 => Bei mir LUID des Privilegs SeUndockPrivilege 00000000 => deaktiviert 0900000000000000 => Bei mir LUID des Privilegs SeTakeOwnershipPrivilege 00000000 => deaktiviert
000000000000000000000000000000000000000000000000000000000000000000000000000000000500490000010C00 [/box:bc6ba1a7d2] Und das hier zeigt TNT in der dazugehörigen Registrierkarte bei mir an:
[...]
[...]
[...]
Was da steht sind also zweifelsfrei Tokenstrukturen eines fremden Prozesses (also nicht von LSASS.EXE selbst, der ja im System-Account läuft)! Aber ist es auch das, was einem Prozess wirklich aktuell im Augenblick zugeordnet ist? Mal schauen... Zum Testen habe ich bei jedem laufenden Prozess das Privileg SeSystemtimePrivilege aktiviert und mir dann angesehen, ob sich an den hier gefundenen Strukturen etwas verändert - es tat sich nichts. Was dort steht, ist also nicht ein im Augenblick einem Prozess zugeordneter Token - aber was dann? Mit PrivAktivate kann ich recht einfach in einer laufenden Session einen Prozess mit dem Token eines nicht eingeloggten Users starten. Auch diesen Token habe ich dann im Service LSASS.EXE gefunden. In der gefundenen Struktur habe ich dann den Status eines Privilegs auf den Wert 02000000 gesetzt (= aktiviert). Danach habe ich mir den Token mit TNT angesehen - auch hier hatte sich nichts geändert, das Privileg war weiterhin deaktiviert. Nachdem ich den Login über PrivAktivate aber wiederholt hatte, war der im Heapblock vorher von mir auf 02000000 gesetzte Wert wieder auf 00000000 (= deaktiviert) zurückgesetzt worden! Der Service LSASS.EXE erzeugt also definitiv beim Login den Token und weist ihn dem gestarteten Prozess zu!
Aber wo befindet sich der Token nach der Zuweisung? Folgender Abschnitt der WIN32.HLP gibt da evtl. etwas nähere Auskunft: [box:bc6ba1a7d2] In the Microsoft® Win32® application programming interface (API), each process has its own 32-bit virtual address space that enables addressing up to 4 gigabytes (GB) of memory. The 2 GB in low memory (0x00 to 0x7FFFFFFF) are available to the user, and the 2 GB in high memory (0x80000000 to 0xFFFFFFFF) are reserved for the kernel. [/box:bc6ba1a7d2]. Es gibt also scheinbar oberhalb von 2GB (oberhalb der Adresse $7FFFFFFF) einen weiteren Adressbereich, der nicht für den User bestimmt ist und demnach auch nicht ohne weiteres ausgelesen werden kann. Im Augenblick vermute ich, daß sich der Token dort befinden - zusammen mit den Sicherheitsbeschreibungen des aktuellen Prozesses und dessen Threads (sowie weiteren Objekte des Kernels). Wenn ich recht habe, dürfte man nicht ohne weiteres an diesen Speicherbereich herankommen - vielleicht gibt es aber auch hier eine Möglichkeit, mit sehr, sehr viel Trickserei................................. |
|
|
| |
|
|