sarekhl
Goto Top

Benutzerdefiniertes Update mit Windows SteadyState

Hallo zusammen,

kennt sich hier noch jemand mit SteadyState aus? Das war das Programm von Microsoft, mit dem man unter Windows XP einen PC in den "Kiosk-Modus" versetzen konnte, und mit dem auch ein Festplattenschutz à la HD-Guard, Drive.Keeper usw. möglich war.

Wenn man so einen Festplattenschutz aktiv hat, ist natürlich das Problem, daß Software-Updates (z.B. von Anti-Virus-Programmen) nicht möglich waren bzw. nach dem nächsten Neustart wieder entfernt wurden. SteadyState konnte die Windows-Updates von Haus aus einspielen, für andere Updates konnte man ein Update-Script erstellen und dieses durch SteadyState aufrufen lassen. Dazu startete SteadyState den Rechner zu einem bestimmten Zeitpunkt neu (nur bis zum Anmeldemaske), spielte dann die Updates ein und übernahme die Änderungen dauerhaft.

Ich habe nun einen Präsentationsrechner unter Windows XP laufen, der mit SteadyState geschützt wird. Auf diesem Rechner soll nun auch Avira Professional Security installiert werden. Der Rechner selbst ist zwar durch den Festplattenschutz schon weitgehend gegen Malware geschützt, aber zur Laufzeit könnte natürlich durchaus ein Wurm den Rechner befallen und von dort aus andere Rechner im Netzwerk attackieren.

Nun habe ich ein Update-Script (in VB6) geschrieben und dies als EXE-Datei compiliert, auf dem Rechner hinterlegt und in SteadyState eingebunden, so daß es täglich um 6 Uhr aufgerufen wird. Das Script ruft die Update-Funktion von Avira als Administrator auf und wartet dann, bis die update.exe wieder beendet ist:


Formularmodul
Private Sub Form_Load()


Dim AdminName As String
Dim AdminPassword As String
Dim AdminDomain As String
Dim ExecCommand As String
Dim ExecDirectory As String
Dim ExecOptions As String
Dim CheckEXE As String

AdminName = "Administrator"  
AdminPassword = "anzeige"  
AdminDomain = "Display"  
ExecDirectory = "c:\programme\avira\antivir desktop\"  
ExecCommand = "avcenter.exe"  
ExecOptions = "/STARTSILENTUPDATE"  
CheckEXE = "update.exe"  


' Kontrolleintrag ins Log schreiben  
Open "d:\avira.log" For Append As 1  
Print #1, Format(Now(), "yyyy.mm.dd-HH:MM:SS") & ";Programm gestartet" 
Close 1


' Aufruf des Avira Updates als Administrator  
Dummy = W2KRunAsUser(AdminName, AdminPassword, AdminDomain, Chr(34) & ExecDirectory & ExecCommand & Chr(34) & " " & ExecOptions, ExecDirectory)  


' Kontrolleintrag ins Log schreiben  
Open "d:\avira.log" For Append As 1  
Print #1, Format(Now(), "yyyy.mm.dd-HH:MM:SS") & ";Aufruf " 
Close 1


' Warten bis avcenter.exe die update.exe aufgerufen hat  
Do
DoEvents
Loop Until IsEXERunning(CheckEXE) = -1


' Kontrolleintrag ins Log schreiben  
Open "d:\avira.log" For Append As 1  
Print #1, Format(Now(), "yyyy.mm.dd-HH:MM:SS") & ";update.exe läuft" 
Close 1


' Warten bis update.exe durchgelaufen ist  
Do
DoEvents
Loop Until IsEXERunning(CheckEXE) <> -1


' Kontrolleintrag ins Log schreiben  
Open "d:\avira.log" For Append As 1  
Print #1, Format(Now(), "yyyy.mm.dd-HH:MM:SS") & ";Update finished" 
Close 1


' Fünf Minuten zuwarten  
Start = Timer
Do While Timer < Start + 300
DoEvents
Loop


' Kontrolleintrag ins Log schreiben  
Open "d:\avira.log" For Append As 1  
Print #1, Format(Now(), "yyyy.mm.dd-HH:MM:SS") & ";Pause finished" 
Close 1


' Programm schließen  
Dim oForm As Form
For Each oForm In VB.Forms
    Unload oForm
  Next
  

End Sub


Modul "Funktionen"
' zunächst die benötigten API-Deklarationen  
Private Declare Function CreateToolhelpSnapshot Lib "Kernel32" _  
  Alias "CreateToolhelp32Snapshot" ( _  
  ByVal lFlgas As Long, _
  ByVal lProcessID As Long) As Long
 
Private Declare Function ProcessFirst Lib "Kernel32" _  
  Alias "Process32First" ( _  
  ByVal hSnapshot As Long, _
  uProcess As PROCESSENTRY32) As Long
 
Private Declare Function ProcessNext Lib "Kernel32" _  
  Alias "Process32Next" ( _  
  ByVal hSnapshot As Long, _
  uProcess As PROCESSENTRY32) As Long
 
Private Declare Function LogonUser Lib "advapi32.dll" Alias _  
        "LogonUserA" _  
        (ByVal lpszUsername As String, _
        ByVal lpszDomain As String, _
        ByVal lpszPassword As String, _
        ByVal dwLogonType As Long, _
        ByVal dwLogonProvider As Long, _
        phToken As Long) As Long

Private Declare Function CreateProcessAsUser Lib "advapi32.dll" _  
        Alias "CreateProcessAsUserA" _  
        (ByVal hToken As Long, _
        ByVal lpApplicationName As Long, _
        ByVal lpCommandLine As String, _
        ByVal lpProcessAttributes As Long, _
        ByVal lpThreadAttributes As Long, _
        ByVal bInheritHandles As Long, _
        ByVal dwCreationFlags As Long, _
        ByVal lpEnvironment As Long, _
        ByVal lpCurrentDirectory As String, _
        lpStartupInfo As STARTUPINFO, _
        lpProcessInformation As PROCESS_INFORMATION) As Long

Private Declare Function CreateProcessWithLogonW Lib "advapi32.dll" _  
        (ByVal lpUsername As String, _
        ByVal lpDomain As String, _
        ByVal lpPassword As String, _
        ByVal dwLogonFlags As Long, _
        ByVal lpApplicationName As Long, _
        ByVal lpCommandLine As String, _
        ByVal dwCreationFlags As Long, _
        ByVal lpEnvironment As Long, _
        ByVal lpCurrentDirectory As String, _
        ByRef lpStartupInfo As STARTUPINFO, _
        ByRef lpProcessInformation As PROCESS_INFORMATION) As Long
      
Private Declare Function CloseHandle Lib "kernel32.dll" _  
        (ByVal hObject As Long) As Long
                             
Private Declare Function SetErrorMode Lib "kernel32.dll" _  
        (ByVal uMode As Long) As Long
        
Private Declare Function GetVersionExA Lib "kernel32.dll" _  
    (lpVersionInformation As OSVERSIONINFO) As Integer


Private Type PROCESSENTRY32
  dwSize As Long
  cntUsage As Long
  th32ProcessID As Long
  th32DefaultHeapID As Long
  th32ModuleID As Long
  cntThreads As Long
  th32ParentProcessID As Long
  pcPriClassBase As Long
  dwflags As Long
  szexeFile As String * MAX_PATH
End Type

Private Type STARTUPINFO
    cb As Long
    lpReserved As Long ' !!! must be Long for Unicode string  
    lpDesktop As Long  ' !!! must be Long for Unicode string  
    lpTitle As Long    ' !!! must be Long for Unicode string  
    dwX As Long
    dwY As Long
    dwXSize As Long
    dwYSize As Long
    dwXCountChars As Long
    dwYCountChars As Long
    dwFillAttribute As Long
    dwflags As Long
    wShowWindow As Integer
    cbReserved2 As Integer
    lpReserved2 As Long
    hStdInput As Long
    hStdOutput As Long
    hStdError As Long
End Type

Private Type PROCESS_INFORMATION
    hProcess As Long
    hThread As Long
    dwProcessId As Long
    dwThreadId As Long
End Type

Private Type OSVERSIONINFO
    dwOSVersionInfoSize As Long
    dwMajorVersion As Long
    dwMinorVersion As Long
    dwBuildNumber As Long
    dwPlatformId As Long
    szCSDVersion As String * 128
End Type
                             

Private Const TH32CS_SNAPPROCESS As Long = 2&
Private Const MAX_PATH As Long = 260
 
Private Const CREATE_DEFAULT_ERROR_MODE = &H4000000

Private Const LOGON_WITH_PROFILE = &H1
Private Const LOGON_NETCREDENTIALS_ONLY = &H2

Private Const LOGON32_LOGON_INTERACTIVE = 2
Private Const LOGON32_PROVIDER_DEFAULT = 0
   
Private Const VER_PLATFORM_WIN32_NT = &H2

'  CreateProcessAsUser() requires that the caller has the following permissions  
'  Permission                        Display Name  
'  ---------------------------------------------------------------  
'  SE_ASSIGNPRIMARYTOKEN_NAME       Replace a process level token  
'  SE_INCREASE_QUOTA_NAME           Increase quotas  
  

Public Function W2KRunAsUser(ByVal UserName As String, _
        ByVal Password As String, _
        ByVal DomainName As String, _
        ByVal CommandLine As String, _
        ByVal CurrentDirectory As String) As Long
 
    Dim si As STARTUPINFO
    Dim pi As PROCESS_INFORMATION
 
    Dim wUser As String
    Dim wDomain As String
    Dim wPassword As String
    Dim wCommandLine As String
    Dim wCurrentDir As String
 
    Dim Result As Long
 
    si.cb = Len(si)
 
    wUser = StrConv(UserName + Chr$(0), vbUnicode)
    wDomain = StrConv(DomainName + Chr$(0), vbUnicode)
    wPassword = StrConv(Password + Chr$(0), vbUnicode)
    wCommandLine = StrConv(CommandLine + Chr$(0), vbUnicode)
    wCurrentDir = StrConv(CurrentDirectory + Chr$(0), vbUnicode)
 
    Result = CreateProcessWithLogonW(wUser, wDomain, wPassword, _
          LOGON_WITH_PROFILE, 0&, wCommandLine, _
          CREATE_DEFAULT_ERROR_MODE, 0&, wCurrentDir, si, pi)
    ' CreateProcessWithLogonW() does not  
    If Result <> 0 Then   'Result ist bool Wert.  
        CloseHandle pi.hThread
        CloseHandle pi.hProcess
        W2KRunAsUser = 0
    Else
        W2KRunAsUser = Err.LastDllError
        MsgBox "CreateProcessWithLogonW() failed with error " & _  
          Err.LastDllError, vbExclamation
    End If
 
End Function


' Prüft, ob eine EXE-Datei bereits ausgeführt wird  
Public Function IsEXERunning(ByVal sFilename As String) As Long
 
  Dim lSnapshot As Long
  Dim uProcess As PROCESSENTRY32
  Dim nResult As Long
 
  ' "Snapshot" des aktuellen Prozess ermitteln  
  lSnapshot = CreateToolhelpSnapshot(TH32CS_SNAPPROCESS, 0&)
  If lSnapshot <> 0 Then
    uProcess.dwSize = Len(uProcess)
 
    ' Ersten Prozess ermitteln  
    nResult = ProcessFirst(lSnapshot, uProcess)
 
    Do Until nResult = 0
      ' Prozessliste durchlaufen  
      If InStr(LCase$(uProcess.szexeFile), LCase$(sFilename)) > 0 Then
        ' Jepp - EXE gefunden  
        IsEXERunning = True
        Exit Do
      End If
 
      ' nächster Prozess  
      nResult = ProcessNext(lSnapshot, uProcess)
    Loop
 
    ' Handle schliessen  
    CloseHandle lSnapshot
  End If
End Function


Das klappt hervorragend, wenn ich an dem PC angemeldet bin und das Programm manuell starte. Das Update wird dann ordnungsgemäß durchgeführt, ist aber natürlich beim nächsten Reboot wieder weg.

Beim Aufruf über SteadyState schlägt das Script aber fehl. Da ich an verschiedenen Stellen eine Kontrollzeile in eine Protokolldatei (auf eine nicht durch den Festplattenschutz geschützte Partition) schreiben lasse, weiß ich auch wo, nämlich beim Aufruf der Funktion W2KRunAsUser. Die Kontrollzeile, die direkt nach diesem Aufruf geschrieben werden sollte, fehlt bereits.


Hat jemand eine Idee, warum das nicht klappt?


Danke im Voraus,
Sarek

Content-Key: 220819

Url: https://administrator.de/contentid/220819

Printed on: April 24, 2024 at 02:04 o'clock

Member: DerWoWusste
DerWoWusste Oct 30, 2013 at 19:02:06 (UTC)
Goto Top
Moin.

Kann es wohl sein, dass das ausführende Konto (vermutlich System) gar nicht für runas genutzt werden kann?
Lass die Impersonation doch einmal weg und führ es einfach aus, ohne den Admin anzugeben.

BItte antworte auch noch in dem Update-Thread Konzept für Updates von Firefox, Flash Player usw. unter Benutzerrechten
Member: SarekHL
SarekHL Oct 30, 2013 updated at 20:15:31 (UTC)
Goto Top
Zitat von @DerWoWusste:
Kann es wohl sein, dass das ausführende Konto (vermutlich System) gar nicht für runas genutzt werden kann?
Lass die Impersonation doch einmal weg und führ es einfach aus, ohne den Admin anzugeben.

Das habe ich mir vorhin auch schon überlegt. Ich habe das Programm inzwischen angepaßt und verwende jetzt einen normalen Shell-Aufruf. Ich kann aber veraussichtlich erst am Freitag ausprobieren, ob es klappt face-sad

Edit: Ich konnte es doch via VPN und RDP jetzt noch testen. Es funktioniert ;)



Da bin ich noch nicht weiter zu gekommen, und da das eher ein allgemeines und nicht dringend anstehendes Thema ist, muß das leider erst mal warten.