HP Netzwerkdrucker per Remote und Reboot.TXT neu starten – nix klappt aber SNMP bringt die Lösung

10 Juli 2016

Beim Rumspielen mit verschiedenen HP-Druckereigenschaften kommen einem manchmal Zweifel, ob alles noch korrekt reagiert. Aus diesem Grund sollte man den betreffenden Drucker von Zeit zu Zeit neu starten um nach einem Neustart die betreffenden Reaktionen zu testen. Im konkreten Fall handelt es sich um einen “HP LaserJet MFP M426fdw”, also ein recht aktuelles Modell.

Blöd nur, dass Varianten mittels einer reboot.txt, wie hier https://community.spiceworks.com/how_to/122155-how-to-reboot-an-hp-printer-remotely oder hier http://dxpetti.com/blog/?p=706 beschrieben nicht funktionieren. Übrigens, FTP-Druck wurde explizit aktiviert, sonst kann man den Drucker per FTP nicht anfahren. Die kompliziertere Variante für Reboot.TXT sieht übrigens so aus:

%-12345X@PJL COMMENT
@PJL DMINFO ASCIIHEX="040006020501010301040105"
%-12345X

Allerdings muss man wissen, dass vor % noch ein ein ASCII-Zeichen mit Code 27 steht. Man kann die passende Datei mittels Powershell ganz einfach so erzeugen:

# {ESC}%-12345X
$k=[System.Text.Encoding]::ASCII.GetString(@(27,37,45,49,50, 51, 52, 53, 88))
$lf=[System.Text.Encoding]::ASCII.GetString(@(13, 10))
$i=’@PJL COMMENT‘
$c=’@PJL DMINFO ASCIIHEX="040006020501010301040105"‘
#$c=’@PJL DMCMD ASCIIHEX="040006020501010301040105"‘

$k + $i + $lf + $c + $lf + $k | set-content -Encoding Ascii -Path "$($env:USERPROFILE)\Reboot.txt"

Aber auch mit der korrekten Escape-Sequenz am Anfang klappte es nicht!

Auch hier wird wieder die ganz einfache reboot.txt Variante beschrieben: https://www.experts-exchange.com/questions/24432791/Rebooting-HP-Jetdirect-remotley.html. Klappt natürlich nicht, aber es war etwas von einem Reboot mittels SNMP beschrieben. Hier soll set OID .1.3.6.1.2.1.43.5.1.1.3.1 with Integer "4" gesetzt werden.

Aha, SNMP das uralte Protokoll. Selbst HP geht darauf aber noch ein und verwendet es für bestimmte Aufgaben, hier ein aktuelles Dokument aus April 2016: http://h20564.www2.hp.com/hpsc/doc/public/display?docId=c01840676.

Tatsächlich findet man bei der Suche nach der OID und Powershell Scripte, wie hier: http://forum.support.xerox.com/t5/Copying-Faxing-Scanning/Schedule-printer-reboot/m-p/176844#M5393. Das Script ist zwar nicht 1:1 übertragbar aber damit wird der Weg klar.

Selbst in Windows 10 gibt es eine OLE SNMP-Klasse https://msdn.microsoft.com/en-us/library/windows/hardware/ff554433(v=vs.85).aspx, welche man mittels Powershell ganz einfach für diesen Zweck einsetzen kann:

$PrinterIP = "192.168.1.87" # hier die tatsächliche IP des Druckers setzen
$SNMP = New-Object -ComObject olePrn.OleSNMP
$SNMP.Open($PrinterIP, "public")
$SNMP.Set(".1.3.6.1.2.1.43.5.1.1.3.1",4)
$SNMP.Close()

Sofort nach absetzen des Set-Befehls startet der Drucker neu! Und was dabei noch interessant ist, es klappt auch mit anderen Druckerfabrikaten.

Vorsicht mit Get-NetFirewallRule bzw. WMI MSFT_NetFirewallRule-Klasse bei Abfrage der Enabled-Eigenschaft – gilt allgemein bei $True und $False in Powershell

10 Juli 2016

Ein Script welches Windows Firewall Regel-Eigenschaften abfragte funktionierte nicht wie erwartet. Es wurde immer die Enabled Eigenschaft abgefragt aber es kam nicht das erwartete Ergebnis, wurde die Abfrage aber negiert, kam das erwartete Ergebnis heraus! Am Ende stellte es sich heraus, dass die Enabled-Eigenschaften kein klassisches Bool sondern einen String zurückgibt, hier die Story:

Fragen wir zunächst die aktuelle Anzahl von Regeln ab, hier bei einem aktuellen Windows 10:

$r=Get-NetFirewallRule
$r.length
413

Es gibt also 413 Regeln. Nun sollen alle Regeln ermitteln werden, die aktiviert sind:

($r | where enabled -eq $true).length
184

Jetzt sollen alle Regeln ermittelt werden, die nicht aktiviert sind:

($r | where enabled -eq $false).length
0

Die 0 ist jetzt nicht das erwartete Ergebnis, wenn man davon ausgeht, dass es 413 Regeln gibt, davon sind 184 aktiv, dann sollten mehr als 0 inaktiv sein.

Wo liegt das Problem? Das Problem ist, dass bei $True oder $False in Powershell immer True oder False am Bildschirm ausgegeben wird. Man interpretiert einen solchen Wert schnell als Boolean. Aber in diesem Fall hat man es nicht mit einem Boolean zu tun:

$r[0].enabled.pstypenames
Microsoft.PowerShell.Cmdletization.GeneratedTypes.NetSecurity.Enabled
System.Enum
System.ValueType
System.Object

Es ist also ein Aufzählungstyp!

($r | where enabled -eq "True").length
184
($r | where enabled -eq "False").length
229

So macht die Sache mehr Sinn!

Oder man macht die Abfrage über den passenden Typ:

($r| where enabled -eq ([Microsoft.PowerShell.Cmdletization.GeneratedTypes.NetSecurity.Enabled]:
:True)).length
184
($r| where enabled -eq ([Microsoft.PowerShell.Cmdletization.GeneratedTypes.NetSecurity.Enabled]:
:False)).length
229

Übrigens: $true –eq "True" ergibt immer True, auch wenn man $true –eq "irgendwas" setzt! Und $False –eq "False" ergibt immer False, egal mit was verglichen wird, außer $false!

Deutsche Tastaturbelegung bei 16-Bit Programmen unter Windows 10

7 Juni 2016

Noch ein kleiner Nachschlag zum vorherigen Blogeintrag https://newyear2006.wordpress.com/2016/06/06/16-bit-komponenten-unter-windows-10-und-fehlermeldung-ntvdm-angeschlossenes-gert-funktioniert-nicht/. Wer so 16-Bit Programme verwendet, der wird sich wundern wo die Umlaute geblieben sind. Man kann das Problem ganz einfach nachstellen:

Macht man eine Eingabeaufforderung auf, dann handelt es sich um eine 32-Bit Eingabeaufforderung, hier sind die Umlaute noch verfügbar. Gibt man nun COMMAND ein, wird die eigentliche 16-Bit Umgebung geladen, sind auf einmal die Umlaute weg. Selbiges passiert auch beim direkten Laden von 16-Bit Programmen über Verknüpfung oder Namenseingabe.

Microsoft Windows [Version 10.0.10586]
(c) 2015 Microsoft Corporation. Alle Rechte vorbehalten.

C:\Users\Benutzer>öäß
Der Befehl "öäß" ist entweder falsch geschrieben oder
konnte nicht gefunden werden.

C:\Users\Benutzer>command
Microsoft(R) Windows DOS
(C)Copyright Microsoft Corp 1990-2001.

C:\USERS\BENUTZER>;‘-

Dieser Artikel ist zwar alt aber hat auch bei Windows 10 immer noch Gültigkeit https://newyear2006.wordpress.com/2006/09/18/deutsche-tastaturbelegung-fur-16bit-dos-programme-unter-vista-rc1/. D. h. man aktiviert durch einfügen von

LH KB16 GR,,%SystemRoot%\system32\keyboard.sys

in der C:\Windows\System32\AUTOEXEC.NT Datei die deutsche Tastaturunterstützung. Nun muss das Programm oder die Eingabeaufforderung nur nochmal neu gestartet werden, dann ist alles gut.

Noch ein Hinweis: Nicht wundern, wenn man diesen Schritt immer wieder nach jedem größeren Windowsupgrade machen muss, da das Gesamtsystem durch z. B. das kommende Anniversary Update immer wieder zurückgesetzt wird!

16-Bit Komponenten unter Windows 10 und Fehlermeldung NTVDM angeschlossenes Gerät funktioniert nicht

6 Juni 2016

Da nun immer mehr Rechner auf Windows 10 umgestellt werden, wo davor kein Bedarf war, kommt es auch zu dem einen oder anderen Aha-Erlebnis. Eigentlich klappt der Umstieg ganz gut. Wer aber auf eine 32-Bit Windows 10 Version umgestiegen ist und noch 16-Bit DOS- oder Windowsprogramme benutzt, der könnte ganz schnell ins Fluchen geraten.

Hier bin ich schon früher auf das Thema NTVDM und 16-Bit-Programme unter Windows 8 eingegangen: https://newyear2006.wordpress.com/2013/09/15/16-bit-programme-unter-windows-8-es-muss-zuerst-die-16-bit-anwendungsuntersttzung-aktiviert-werden/, hier für Windows 8.1: https://newyear2006.wordpress.com/2013/09/15/nochmal-zum-thema-16-bit-programme-unter-windows-8-1-32-bit-und-wie-verhlt-es-sich-mit-fondue-exe-und-den-legacykomponenten/.

Dieser Dialog ist auch unter Windows 10 verfügbar die Installation der Legacyfeatures funktioniert genauso wie bei 8 und 8.1 beschrieben.

Allerdings laufen unter Windows 10 die meisten 16-Bit-Programme immer noch nicht!! Warum? Weil Microsoft eine zusätzliche Hürde für 16-Bit-Programme eingebaut hat. Es handelt sich dabei um die neue Konsole mit den erweiterten Copy&Paste-Eigenschaften über die Tastatur. Diese sorgt dafür, dass wenn ein altes 16-Bit-Programm mit installierter Legacy-Komponente aufgerufen wird diese Fehlermeldung erscheint:

image

Hier nochmal die reine Textform für die Suchmaschinen:

—————————
16 bit MS-DOS Subsystem
—————————
Eingabeaufforderung – Anwendung
NTVDM has encountered a System Error
Ein an das System angeschlossenes Gerät funktioniert nicht.

Choose ‚Close‘ to terminate the application.
—————————
Schließen   Ignorieren  
—————————

Was tun? Die Ereignisanzeige protokolliert auch nur brav mit, dass ein Problem auftrat:

PS C:\> Get-EventLog -LogName System -Source "Application Popup" -InstanceId 26 | select -First 1 | fl *

EventID            : 26
MachineName        : MeinRechnerName
Data               : {}
Index              : 945
Category           : (0)
CategoryNumber     : 0
EntryType          : Information
Message            : CriticalAppShutdownCleanupTimeout
Source             : Application Popup
ReplacementStrings : {16 bit MS-DOS Subsystem, Eingabeaufforderung – Anwendung                     NTVDM has encountered a System Error                      Ein an das System angeschlossenes Gerät funktioniert nicht.                       Choose ‚Close‘ to terminate the application.}
InstanceId         : 26
TimeGenerated      : 06.06.2016 15:15:47
TimeWritten        : 06.06.2016 15:15:47
UserName           : NT-AUTORITÄT\SYSTEM
Site               :
Container          :

Wenn man googlet, dann könnte man über diesen Thread http://answers.microsoft.com/en-us/insider/forum/insider_wintp-insider_update/16-bits-applications-not-working-at-all/a776a720-ff62-4848-96b1-81b4371cff2c?page=3 stolpern und hier hat MarcelloCapozzi den richtigen Vorschlag:

Einfach die “Legacy Console” aktivieren!

Merke: Nicht nur die Legacy Komponente muss installiert werden, sondern ab Windows 10 auch noch bei den Einstellungen die Legacy Console!

image

Dazu muss man also bei den Eingabeaufforderung oder Programmverknüpfungseigenschaften auf das Register Optionen gehen. Der Hinweis “erfordert Neustart” bezieht sich nicht auf den Rechner sondern auf das jeweilige Programm, bzw. die Eingabeaufforderung.

Wer die Sache skripten muss, der kann sich um HKEY_CURRENT_USER\Console bemühen und dort speziell den Eintrag ForceV2, dieser steuert das Verhalten ob Legacy aktiviert ist oder nicht. Leider fehlt mir gerade die Zeit dies weiter auszuführen. Hier gibt es weitere Infos: https://technet.microsoft.com/en-us/library/mt427362.aspx.

Hardware direkt einer virtuellen Maschine im Hyper-V mittels Discrete Device Assignment zuordnen

3 Juni 2016

Microsoft experimentiert viel mit dem Hyper-V und baut ihn in alle Richtungen aus. So gab es ganz zu Beginn von Windows 10 Powershell Cmdlets, welche es erlaubten physische Hardware direkt einer virtuellen Maschine zuzuordnen https://charbelnemnom.com/2015/02/whats-new-in-powershell-for-hyper-v-in-windows-server-technical-preview-hyperv-powershell-vnext/. Dazu gab es die Cmdlets:

Get-Command *assigna*

Name                            Version Source
—-                            ——- ——
Add-VMAssignableDevice          2.0.0.0 Hyper-V
Add-VMHostAssignableDevice      2.0.0.0 Hyper-V
Dismount-VMHostAssignableDevice 2.0.0.0 Hyper-V
Get-VMAssignableDevice          2.0.0.0 Hyper-V
Get-VMHostAssignableDevice      2.0.0.0 Hyper-V
Mount-VMHostAssignableDevice    2.0.0.0 Hyper-V
Remove-VMAssignableDevice       2.0.0.0 Hyper-V
Remove-VMHostAssignableDevice   2.0.0.0 Hyper-V

Allerdings verschwanden diese Cmdlets wieder zum Release von Windows 10, weshalb sie bei diesem Vergleich nicht auftauchten: https://newyear2006.wordpress.com/2015/07/30/umgang-mit-verschiedenen-versionen-von-powershellmodulen-und-ermittlung-von-unterschieden/.

Per Zufall stolperte ich aber über diesen Blogeintrag https://techstronghold.com/blogs/virtualization/pass-through-wired-or-wireless-wi-fi-nic-to-vm-using-hyper-v-discrete-device-assignment-dda-in-windows-server-2016, der komische Dinge vollführte. Tatsächlich hat Microsoft obige Cmdlets mit Release von v1511 bei Windows 10 wieder eingeführt! Wobei die Dokumentation, stand heute, also ein halbes Jahr nach Erscheinen von v1511, absolut erbärmlich ist. Z. B. besteht die Dokumentation von Add-VMAssignableDevice nur aus einem Template. Keine Erklärung nix.

Nun ist das Thema an sich auch recht komplex, aber man könnte ja zumindest ein paar Links für weitergehende Informationen hinterlegen. So muss man sich alles selber ergooglen.

Im Prinzip geht es um Discrete Device Assignment, kurz DDA, auch bekannt als PCI Passthrough. Dies erlaubt einer VM den direkten Zugriff auf Hardware.

Hier findet man einen Hintergrundartikel dazu: https://blogs.technet.microsoft.com/virtualization/2015/11/19/discrete-device-assignment-description-and-background/. Obwohl die Cmdlets unter Windows 10 verfügbar sind, scheint nur unter Windows Server 2016 die Unterstützung aktiviert zu sein! Dies wird in diesem Artikel geschrieben: https://blogs.technet.microsoft.com/virtualization/2015/11/20/discrete-device-assignment-machines-and-devices/.

Selbst wenn man mit dem Server 2016 unterwegs ist, muss die Hardware DDA unterstützen, ein Script welches die Hardware daraufhin überprüft, ist hier zu finden: https://github.com/Microsoft/Virtualization-Documentation/blob/master/hyperv-tools/DiscreteDeviceAssignment/SurveyDDA.ps1.

Probleme mit leeren Bildschirm bei Sichern und Wiederherstellen unter Windows 7 und allgemeines Sicherungsdebugging

30 Mai 2016

Datensicherungen sind wichtig, gerade in Zeiten von Cryptolocker-Malware. Was macht man aber, wenn man mit einer leeren Seite und ohne Fehlermeldung begrüßt wird, wenn man den Sicherungsstatus überprüfen möchte?

In einem Fall unter Windows 7 zeigte der Aufruf der “Sichern und Wiederherstellen”-Seite über die Systemsteuerung einfach nur ein leeres Bild. Schlecht so was. Auch der direkte Aufruf von sdclt.exe brachte die gleiche Darstellung. Hier ist das Problem nochmal mit Bildern beschrieben: http://www.borncity.com/blog/2014/09/29/windows-sichern-und-wiederherstellen-bleibt-leer/.

Gut wenn die Oberfläche nichts anzeigt, dann schaut man halt tiefer und ein Aufruf von wbadmin get versions brachte erschreckendes zu Tage, dass die letzte Sicherung schon ein paar Wochen her ist!

Dann der nächste Blick in die Windows Ereignisanzeige unter Anwendungs- und Dienstprotokolle/Microsoft/Windows/Backup. Oh je, der Eindruck mit denen von wbadmin stimmt überein, keine Backups wurden für die letzten Wochen protokolliert.

An was liegt es? Ist womöglich die Ausführung in der Aufgabenplanung deaktiviert? Witzig: Nein, die scheint immer schön brav jeden Tag durchzulaufen und meldet keine Fehler!

Gibt es hier einen Masterplan? Keine Ahnung, zunächst kann man natürlich die Ressourcenüberprüfung mittels SFC.EXE /SCANNOW drüberjagen, doch die brachte nichts.

Jetzt sollte man sich mal Gedanken machen, welche Dienste für eine Datensicherung benötigt werden. Da gibt es drei:

PS> Get-Service wbengine, SDRSVC, VSS

Status   Name               DisplayName
——   —-               ———–
Stopped  SDRSVC             Windows-Sicherung
Stopped  VSS                Volumeschattenkopie
Stopped  wbengine           Blockebenen-Sicherungsmodul

stellt sich die Frage, lassen die sich starten?

PS> Start-Service wbengine, SDRSVC, VSS
start-Service : Der Dienst "Windows-Sicherung (SDRSVC)" kann aufgrund des folgenden Fehlers nicht gestartet werden:
Der Dienst SDRSVC kann nicht auf dem Computer . gestartet werden.

In Zeile:1 Zeichen:1
+ start-Service wbengine, SDRSVC, VSS
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : OpenError: (System.ServiceProcess.ServiceController:ServiceController) [Start-Service],
   ServiceCommandException
    + FullyQualifiedErrorId : CouldNotStartService,Microsoft.PowerShell.Commands.StartServiceCommand

PS> Get-Service wbengine, SDRSVC, VSS

Status   Name               DisplayName
——   —-               ———–
Stopped  SDRSVC             Windows-Sicherung
Running  VSS                Volumeschattenkopie
Running  wbengine           Blockebenen-Sicherungsmodul

OK, das ist eine Aussage: Der Dienst kann nicht gestartet werden, weil der Dienst nicht gestartet werden kann! Blöd so was, aber warum kann er nicht gestartet werden?

PS> Get-Service SDRSVC | fl *

Name                : SDRSVC
RequiredServices    : {RPCSS}
CanPauseAndContinue : False
CanShutdown         : False
CanStop             : False
DisplayName         : Windows-Sicherung
DependentServices   : {}
MachineName         : .
ServiceName         : SDRSVC
ServicesDependedOn  : {RPCSS}
ServiceHandle       : SafeServiceHandle
Status              : Stopped
ServiceType         : Win32OwnProcess
StartType           : Disabled
Site                :
Container           :

Klar, wenn ein Dienst deaktiviert ist, dann kann er auch nicht gestartet werden!

Also setzen wir den Dienst auf seinen Standardwert:

PS> Set-Service SDRSVC -StartupType Manual

Nun kann man mittels SDClt.EXE oder, wie gewohnt, mit vielen Klicks den Punkt “Sichern und Wiederherstellen” aufrufen und siehe da, es wird wieder alles angezeigt!

Ob dann die Sicherung auch wirklich klappt? Keine Ahnung, aber wer so eine Einstellung hat, der hat vielleicht einen weiteren Dienst deaktiviert, also schauen wir uns noch die anderen Dienste an:

PS> Get-Service wbengine, SDRSVC, VSS| select name, displayname, starttype

Name     DisplayName                 StartType
—-     ———–                 ———
SDRSVC   Windows-Sicherung              Manual
VSS      Volumeschattenkopie            Manual
wbengine Blockebenen-Sicherungsmodul    Manual

Also sieht ja gut aus.

Da wir gerade dabei sind, wenn es schon Probleme gibt, dann helfen diese Abfragen (Powershell 3.0 muss vorhanden sein):

Get-WinEvent -LogName Microsoft-Windows-Backup|select -First 10

Get-ScheduledTask -Recurse | where name -match backup| select name,status,lastruntime,lasttaskresult, nextruntime| ft –AutoSize

Get-Service wbengine, SDRSVC, VSS| select name, displayname, starttype, status

vssadmin list writers

Bei Get-ScheduledTask ist wichtig LastTaskResult mit anzuzeigen, weil dies standardmäßig nicht mit aufgelistet wird aber wertvolle Hinweise geben kann.

Bei vssadmin list writers sind insbesondere die Angaben zum letzten Fehler der einzelnen Writer zu beachten! Eine Idee, wie man mit vssadmin umgeht, geben diese beiden Artikel: https://newyear2006.wordpress.com/2015/12/19/windows-8-1-backup-mit-wbadmin-bricht-mit-fehler-auf-das-bereitgestellte-sicherungsvolume-konnte-nicht-zugegriffen-werden-ab-bzw-fehlercode-0x807800c5/ und https://newyear2006.wordpress.com/2011/09/09/sbs2011-backup-bricht-mit-fehler-2155348129-ab-und-was-hat-das-mit-sharepoint-updates-zu-tun/.

Vorsicht mit dem Start-MPWDOScan Cmdlet bzw. dem Offline überprüfen bei Windows 10

29 Mai 2016

Wer mit seinem Powershell auf aktuellen Windows 10 Versionen herumspielt, der könnte über das neue Cmdlet Start-MPWDOScan stolpern. Ein etwas kryptischer Name. Es gibt bereits eines mit dem Namen Start-MpScan, welches den Windows Defender aufruft und einen Scanlauf startet.

Aber für was steht nun WDO? Ganz einfach für Windows Defender Offline. Also kurz, damit kann man den Windows Defender im Offlinemodus starten. Dazu wird die aktuelle Windows Sitzung heruntergefahren und der Rechner bootet den Windows Defender Offline Scanner. Der führt seinen Scanlauf durch und bootet anschließend wieder das vorhergehend aktive Windows.

Seit der Verison v1511 von Windows 10 gab es nur das Cmdlet aber bei den aktuellen Preview-Versionen, gibt es nun bei den Windows Einstellungen bei “Update und Sicherheit” unter “Windows Defender” die Option “Windows Defender Offline” wo man den Button “Offline überprüfen” anklicken kann.

Soweit so gut und sicher eine prima Sache.

Wenn da nicht wie immer die berühmten Nebenwirkungen wären. Zunächst macht es Sinn, bevor man Start-MPWDOScan aufruft mittels Update-MpSignature die aktuellen Virendefinitionen zu laden, denn der Offline-Scanner legt einfach los und kann kein Update durchführen!

Nach dem Aufruf von Start-MPWDOScan oder anklicken von “Offline prüfen” passiert zunächst einmal nichts. Erst nach ca. einer Minute erscheint auf einmal ein Hinweisfenster, dass nun alle Anwendungen geschlossen werden. Wenn man dies nicht weiß, ist dies ziemlich verwunderlich, weil man einen Befehl absetzt und keine Reaktion bekommt und dann unvermittelt doch. Man kann zwar das Hinweisfenster schließen aber ein Abbruch des Vorgangs ist nicht direkt möglich! Nicht gespeicherte Daten gehen unweigerlich verloren! Wer schnell ist, kann allerdings per Win+R oder per Eingabeaufforderung ein “Shutdown /a” absenden, damit wird der Vorgang zunächst abgebrochen.

Wer nach einem Abbruch mittels “Shutdown /a” später dann versucht den Vorgang kontrolliert nochmal neu zu starten, der kann nach Eingabe von Start-MpWDOScan lange warten, denn es passiert einfach nichts mehr. Erst ein Neustart des Rechners mittels “Restart-Computer” bzw. normalem Neustart führt zur Offline-Prüfung, d. h. nach dem Abbruch macht der Rechner zunächst auf beleidigt.

Nächstes Problem ist die Art des Scanlaufs. Normalerweise kann man mittels “Set-MpPreference –ScanParameters FullScan” festlegen, dass man einen vollständigen Scanlauf machen möchte. Der eingebaute Windows Defender Offline ignoriert diese Einstellung und führt immer nur eine Schnellprüfung durch.

Wenn der Scanlauf beendet ist, stellt sich die Frage, wie man weiß, dass nichts gefunden wurde. Man könnte die Windows Ereignisanzeige mittels

Get-WinEvent -LogName "Microsoft-Windows-Windows Defender/Operational"|select -First 10

bemühen aber dort stehen eher wenig Infos drin. Es wird lediglich vermerkt, wann ein Offlinescan von der Anwendung “%1” initiiert wurde. Dies wird angezeigt durch die Nachricht “%1 hat Windows Defender Offline heruntergeladen und konfiguriert und führt es beim nächsten Neustart aus.”, ID 2030. Danach gibt es noch die Meldung “In der Konfiguration von Windows Defender wurde eine Änderung erkannt. Falls dies unerwartet ist, überprüfen Sie die Einstellungen, da die Änderung möglicherweise von Schadsoftware verursacht wurde…”, ID 5007. Dabei wird noch ein Registrierungskey genannt: HKLM\SOFTWARE\Microsoft\Windows Defender\Scan\OfflineScanRun, der von 0x1 auf 0x0 gesetzt wurde. Wenn es stimmt.

Da wohl niemand am Bildschirm kleben bleibt, wenn der Scan läuft, der fragt sich, wie kann man feststellen, ob der Scan ohne Probleme verlief? Dazu findet man im Verzeichnis C:\Windows\Microsoft Antimalware\Support entsprechende Log-Dateien. Die Kurzfassung steht in MSSSWrapper.LOG. Der Name MSSS steht für Microsoft Standalone System Sweeper, dem früheren Namen des Windows Defender Offline.

Es gibt auch noch Dateien mit Namen MPDetection-Datum-Uhrzeit.LOG und MPLog-Datum-Uhrzeit.LOG, dort stehen auch noch Infos.

In beiden Dateien, MSSSWrapper.LOG und MPDetection*.LOG werden Virenfunde verzeichnet, indem auf “Number of threats from scan: x”, “Found Virus:” und “DETECTION Virs:” darauf hingewiesen wird.

Wer selber die Reaktion des Windows Defender Offline testen möchte, der schaltet einfach mittels “Set-MpPreference –DisableRealtimeScanning $true” den Realtimescan-Modus ab. Danach kann man Problemlos mittels “New-Eicar –Path C:\Windows” ein Test-Virus pflanzen, der dann vom anschließenden Offline Scanlauf erkannt werden sollte. New-Eicar bekommt man hier: https://github.com/obscuresec/PowerShell/blob/master/New-Eicar.

Bleibt noch am Ende die Frage, wie sicher die Offline Methode ist. Denn wenn ein System bereits infiziert ist, könnte eine Malware auch nach dem Start des Offline-Scanners aktiv sein. Leider gibt es keine verwertbaren Infos wie dieser Vorgang vonstatten geht, so dass man hier nur spekulieren kann. Scheinbar wird ein WinPE hochgefahren, aber es wird dabei scheinbar auf Dateien aus dem bestehenden System zurückgegriffen…

Wobei es aber auch klappen könnte, wenn man Confirm-SecureUEFIBoot mit $true bestätigt bekommt, dann könnte theoretisch geprüft werden, ob das System sauber ist. Aber ob das stattfindet?

Übermittlungsoptimierung frisst die gesamte Bandbreite

28 Mai 2016

Eigentlich ist die Idee von Peer2Peer Protokollen reizvoll. So ermöglicht Windows 10 z. B. Updates über Peer2Peer von anderen Rechnern im Internet anstatt von Microsoft direkt zu laden. Leider hapert es an der Umsetzung.

Das Problem trat massiv bei einer aktuellen Windows 10 Preview mit Build 14295 auf. Als gerade eine neuere Buildversion verfügbar wurde, konnte man mit anderen Rechnern im selben Netzwerk nicht mehr vernünftig ins Internet. Die massiven Downloads, mehrere Verbindungen vom selben Rechner des neuen Builds, sorgten auf den anderen Rechnern für Stillstand.

Am Anfang war dies gar nicht klar, denn Windows Updates hatten früher noch nie Probleme gemacht. Diese laufen normalerweise über den Intelligenten Hintergrundübertragungsdienst (BITS). Erst Windows 10 führte die Möglichkeit der Peer2Peer Updates ein. Als das Problem dem Windowsrechner zugeordnet war, ging es an die Ursachenforschung.

Ein Get-Bitstransfer –AllUsers brachte gähnende Leere. Also war der BITS nicht Schuld, aber was war es dann, wo die Bandbreite fraß? Also den Windows Ressourcenmonitor angeworfen und beim Netzwerkverkehr nach den Downloads geschaut. Tatsächlich war hier der SVCHOST.EXE netsvcs mit einem fetten Download beteiligt. Nachdem zuerst der BITS-Dienst ausgeschaltet wurde, vielleicht hat er ja eine geheime Übertragung am Laufen, gab es immer noch keine Besserung.

Dann mal geschaut, was alles hinter netsvcs steckt:

$netsvcs= (Get-ItemProperty ‚registry::HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\SvcHost\‘ -Name netsvcs).netsvcs

$netsvcs
CertPropSvc
SCPolicySvc
lanmanserver
gpsvc
IKEEXT
iphlpsvc
seclogon
AppInfo
msiscsi
EapHost
schedule
winmgmt
browser
ProfSvc
SessionEnv
wercplsupport
dosvc
DcpSvc
wlidsvc
NcaSvc
NetSetupSvc
Themes
RetailDemo
lfsvc
FastUserSwitchingCompatibility
Ias
Irmon
Nla
Ntmssvc
NWCWorkstation
Nwsapagent
Rasauto
Rasman
Remoteaccess
SENS
Sharedaccess
SRService
Tapisrv
Wmi
WmdmPmSp
wuauserv
BITS
ShellHWDetection
LogonHours
PCAudit
helpsvc
uploadmgr
dmwappushservice
BDESVC
XboxNetApiSvc
UsoSvc
XblGameSave
DmEnrollmentSvc
DsmSvc
UserManager
XblAuthManager
AppMgmt

Na super da kommt richtig Freude auf. Um mehr Infos zu bekommen, könnte man nun

$netsvcs | Get-Service

aufrufen, da aber sicher nicht alle Dienste laufen, macht es mehr Sinn gleich mal die nicht vorhandenen und nicht laufenden auszunehmen:

($sr=$netsvcs | Get-Service | where status -eq running) 2> $null

Status   Name               DisplayName
——   —-               ———–
Running  CertPropSvc        Zertifikatverteilung
Running  lanmanserver       Server
Running  iphlpsvc           IP-Hilfsdienst
Running  AppInfo            Anwendungsinformationen
Running  schedule           Aufgabenplanung
Running  winmgmt            Windows-Verwaltungsinstrumentation
Running  browser            Computerbrowser
Running  ProfSvc            Benutzerprofildienst
Running  SessionEnv         Konfiguration für Remotedesktops
Running  dosvc              Übermittlungsoptimierung
Running  Themes             Designs
Running  lfsvc              Geolocation-Dienst
Running  SENS               Benachrichtigungsdienst für Systeme…
Running  ShellHWDetection   Shellhardwareerkennung
Running  UserManager        Benutzer-Manager
Running  AppMgmt            Anwendungsverwaltung

Damit wird die Sache schon übersichtlicher und man hat nähere Infos zum Geschehen.

Und so kann man sich dann die Frage stellen, was ist ein Übermittlungsoptimierungs-Dienst dosvc? Genauer gesagt handelt es sich dabei um die Windows Update Übermittlungsoptimierung. Also offizielle Infos dazu: http://windows.microsoft.com/de-de/windows-10/windows-update-delivery-optimization-faq.

Dann werden auch schnell die Probleme offensichtlich: https://social.technet.microsoft.com/Forums/en-US/b94d8e74-58de-451a-b137-7ec2028adc27/delivery-optimization-service-downloading-something-and-using-all-my-bandwidth?forum=win10itprogeneral

Get-ItemProperty registry::HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\dosvc -Name ServiceDLL| select servicedll

ServiceDll
———-
C:\WINDOWS\system32\dosvc.dll

Also ist die dosvc.dll die DLL, die es zu beachten gibt.

Nachdem das nun geklärt ist, so dann sollten wir mal wieder mit Mythen aufräumen, die sich leider immer wieder ergeben und ohne jeden Beweis behauptet werden.

Hier https://social.technet.microsoft.com/Forums/forefront/en-US/074181bc-1e1f-4b06-b816-6d9e1dac3da4/wudo-clarification-can-it-tunnel-out-through-the-fireall-protecting-my-network?forum=win10itprosecurity und hier http://www.wintotal.de/windows-10-p2p-update-verteilung-deaktivieren/ behauptet jemand, das für TCP und UDP vom Übertragungsoptimierungs-Dienst zwei unterschiedliche Ports benutzt werden. Einmal 7680 bei TCP und 3544 UDP. Dem ist aber nicht so.

Schauen wir uns zunächst die Regel in der Firewall an, ob es da was passendes gibt:

Get-NetFirewallServiceFilter -Service dosvc|Get-NetFirewallRule

Name                  : DeliveryOptimization-TCP-In
DisplayName           : Übermittlungsoptimierung (TCP eingehend)
Description           : Eingehende Regel, die der Übermittlungsoptimierung die Verbindung mit Remoteendpunkten erlaubt.
DisplayGroup          : Übermittlungsoptimierung
Group                 : @%systemroot%\system32\dosvc.dll,-100
Enabled               : True
Profile               : Any
Platform              : {}
Direction             : Inbound
Action                : Allow
EdgeTraversalPolicy   : Allow
LooseSourceMapping    : False
LocalOnlyMapping      : False
Owner                 :
PrimaryStatus         : OK
Status                : Die Regel wurde erfolgreich vom Speicher aus analysiert. (65536)
EnforcementStatus     : NotApplicable
PolicyStoreSource     : PersistentStore
PolicyStoreSourceType : Local

Name                  : DeliveryOptimization-UDP-In
DisplayName           : Übermittlungsoptimierung (UDP eingehend)
Description           : Eingehende Regel, die der Übermittlungsoptimierung die Verbindung mit Remoteendpunkten erlaubt.
DisplayGroup          : Übermittlungsoptimierung
Group                 : @%systemroot%\system32\dosvc.dll,-100
Enabled               : True
Profile               : Any
Platform              : {}
Direction             : Inbound
Action                : Allow
EdgeTraversalPolicy   : Allow
LooseSourceMapping    : False
LocalOnlyMapping      : False
Owner                 :
PrimaryStatus         : OK
Status                : Die Regel wurde erfolgreich vom Speicher aus analysiert. (65536)
EnforcementStatus     : NotApplicable
PolicyStoreSource     : PersistentStore
PolicyStoreSourceType : Local

Also es gibt eine Regel für TCP und UDP und welche Ports werden nun benutzt?

Get-NetFirewallServiceFilter -Service dosvc|Get-NetFirewallRule|Get-NetFirewallPortFilter

Protocol      : TCP
LocalPort     : 7680
RemotePort    : Any
IcmpType      : Any
DynamicTarget : Any

Protocol      : UDP
LocalPort     : 7680
RemotePort    : Any
IcmpType      : Any
DynamicTarget : Any

Ergo, nix UDP auf 3544. Übrigens Port 3544 wäre Teredo, wahrscheinlich hat da jemand nicht genau genug geschaut und die Leute übernehmen immer alles ohne es zu prüfen. http://www.iana.org/assignments/service-names-port-numbers/service-names-port-numbers.xhtml?search=3544

Nützliche Powershellfunktionen zum Hin- und Herkonvertieren in Base64 und Splitten einer Zeichenkette

27 Mai 2016

Ohne viel blabla:

Function ConvertTo-Base64 {

    [CmdletBinding()]
    [OutputType([string])]
    Param (
        [string]$String
    )
    [System.Convert]::ToBase64String([System.Text.Encoding]::Unicode.GetBytes($String))

}

Function ConvertFrom-Base64 {
 
    [CmdletBinding()]
    [OutputType([string])]
    Param (
        [string]$String
    )
    [System.Text.Encoding]::Unicode.GetString([System.Convert]::FromBase64String($String))

}

Function Split-String {

# splittet einen String in Blöcke mit einer bestimmten Länge

    [CmdletBinding()]
    Param (
        [parameter(Mandatory=$true)]
        [string]$String,
        [int]$BlockLength=60
    )
   
    $blocks = [System.Math]::Floor($String.Length / $BlockLength)
    $newString = ""

    for ($line = 0; $line -lt $blocks; $line++) {
        $newString += $String.Substring($line * $BlockLength, $BlockLength) + [System.Environment]::NewLine
    }

    If ($blocks * $BlockLength -lt $String.Length) {
        $newString += $String.Substring($blocks * $BlockLength)
    }

    $newString
}

Damit kann man eine Datei einlesen und in einen Base64-String umwandeln, etwas bearbeiten und wieder zurückwandeln:

$c=get-content -Raw C:\windows\win.ini
$b=ConvertTo-Base64 $c
# Split-String bricht den String nach 60 Zeichen um
$s=Split-String $b
$nc=ConvertFrom-Base64 (Split-String $s)
# Trotz Konvertierung und Splitten ist der konvertierte String identisch
$c -eq $nc

Die mysteriöse Windows 10 App mit Namen “App-Verbindung” bzw. “App connector” oder wie bekommen ich mehr Infos über unbekannte installierte Apps?

13 Mai 2016

Wer bei seinem Windows 10 aufmerksam seine Einstellungen für den Datenschutz studiert, dem wird die App “App-Verbindung” auffallen. Sie taucht z. B. bei Position, Kamera, Kontakte und Kalender auf.

Schon seit letztem Jahr wird spekuliert, was es mit der App auf sich hat: http://www.howtogeek.com/247661/nobody-knows-what-windows-10s-app-connector-is-and-microsoft-wont-explain-it/. Oder http://superuser.com/questions/1003207/windows-10-what-is-the-microsoft-app-connector-and-why-would-it-want-need-acc. Die Officehilfe erwähnt die App sogar im Zusammenhang mit Synchronisationsproblemen mit Windows Mail oder Windows Kalender: https://support.office.com/de-de/article/Beheben-von-Synchronisierungsproblemen-in-den-Mail-und-Kalender-Apps-in-Windows-10-0dd86c69-18f3-4f73-9d3d-375bdc9c3e34. Wie so oft gibt es keine ordentliche Beschreibung von Microsoft oder vernünftige Quellenangaben.

Also versuchen wir mal die nötigen Infos selber zusammen zu tragen. Dabei kann man die prinzipielle Vorgehensweise hier für beliebige Apps unter Windows 10 verwenden.

Man kann sich mittels Powershell nähere Infos zur App holen, indem man

Get-AppxPackage -AllUsers |where name -eq "Microsoft.Appconnector"

eingibt, erhält man z. B.

Name                   : Microsoft.Appconnector
Publisher              : CN=Microsoft Corporation, O=Microsoft Corporation, L=Redmond, S=Washington, C=US
Architecture           : Neutral
ResourceId             :
Version                : 1.3.3.0
PackageFullName        : Microsoft.Appconnector_1.3.3.0_neutral__8wekyb3d8bbwe
InstallLocation        : C:\Program Files\WindowsApps\Microsoft.Appconnector_1.3.3.0_neutral__8wekyb3d8bbwe
IsFramework            : False
PackageFamilyName      : Microsoft.Appconnector_8wekyb3d8bbwe
PublisherId            : 8wekyb3d8bbwe
PackageUserInformation : {S-1-5-21-XXXXXXXXXX-YYYYYYYYYY-ZZZZZZZZZZ-1001 [WIN\user]: Installed}
IsResourcePackage      : False
IsBundle               : False
IsDevelopmentMode      : False

Von Interesse dabei ist der Installationspfad. Da kann man dann selber nachschauen, was die App so kann und macht. Jede App unter Windows hat eine Manifest-Datei, in welcher festgelegt ist, welche Zugriffsrechte die App möchte.

Also holen wir uns einfach doch mal diese Manifest-Datei:

$app=Get-AppxPackage -AllUsers |where name -eq "Microsoft.Appconnector"
$mf=[xml](Get-content "$($app.InstallLocation)\AppxManifest.xml")

In $mf steht nun der komplette Manifest-Dateiinhalt zur Verfügung. Durch die Verwendung des Typkonverters [xml] auch noch leicht verwertbar. Schauen wir uns mal einen Eintrag an:

$mf.Package.Applications.Application.VisualElements

DisplayName       : ms-resource:ConnectorStubTitle
Description       : ms-resource:ConnectorStubTitle
BackgroundColor   : transparent
AppListEntry      : none
Square150x150Logo : images\Logo.png
Square44x44Logo   : images\AppConnectorAppList.png
SplashScreen      : SplashScreen

Nicht sehr ergiebig oder? Allerdings ist ein Eintrag interessant, nämlich AppListEntry. Dieser ist mit None definiert und genau dieser ist es, warum die App nicht im Startmenü oder bei der Suche mittels Cortana auftaucht! Weitere Infos zu VisualElements bzw AppListEntry: https://msdn.microsoft.com/en-us/library/windows/apps/dn934817.aspx.

Neben VisualElements ist dann noch das Element Capabilities von Bedeutung:

($mf.Package.Capabilities).Capability

Name
—-
internetClient
picturesLibrary
videosLibrary
removableStorage
appointments
contacts
phoneCall

Es definiert, worauf die App Zugriff haben möchte. Also unsere unbekannte App möchte ins Internet, unsere Bilder und Videos anschauen können, auf Wechseldatenträger zugreifen, Kontakte und Termine sehen und zu guter Letzt noch die Anruferliste sehen. Also eine ganze Menge!

Aber das war noch nicht alles, sie will auch noch auf die Webcam zugreifen und Positionen abfragen:

($mf.Package.Capabilities).DeviceCapability

Name
—-
webcam
location

Zum Themenkomplex Capabilities findet man hier noch weitere Infos: https://msdn.microsoft.com/en-us/library/windows/apps/dn934741.aspx.

Für die Frage aber, was die App denn nun macht ist folgender Eintrag relevant:

$mf.Package.Applications.Application

Id  StartPage    VisualElements
–  ———    ————–
App default.html VisualElements

Der sagt nichts anderes aus, dass wenn App-Verbindung gestartet wird, dass dann default.html aufgerufen wird. Also eine lokale Internetseite. Deren Inhalt kann man sich auch ganz einfach wieder anschauen:

Get-Content "$($app.InstallLocation)\$($mf.Package.Applications.Application.StartPage)"

und erhält:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title id="applicationName"></title>

    <!– Connector.StubApplication references –>
    <link href="/css/default.css" rel="stylesheet" />
    /js/font%20style=
</head>
<body>
</body>
</html>

Also da passiert jetzt nicht so wahnsinnig viel. Allerdings könnte ja nun mittels default.js die Party abgehen. Also holen wir uns den Inhalt auch noch:

$html=[xml](get-content "$($app.InstallLocation)\$($mf.Package.Applications.Application.StartPage)")

Wir nutzen wieder den Typekonverter um das gewünschte Ziel schneller auslesen zu können. Denn wir sind an

$html.html.head.script

src

/js/default.js

interessiert, denn damit bekommen wir den Inhalt des Javascripts mittels

get-content "$($app.InstallLocation)\$($html.html.head.script.src)"

ausgelesen:

(function () {
    "use strict";
    function setTextContent(elementId, stringId) {
        var resources = new Windows.ApplicationModel.Resources.ResourceLoader();
        document.getElementById(elementId).textContent = resources.getString(stringId);
    }

    function updateUserInterface() {
        setTextContent("applicationName", "ConnectorStubTitle");
    }

    document.addEventListener("DOMContentLoaded", function domContentLoaded() {

        MSApp.terminateApp(new Error("This app should never load"));

    }.bind(this));
})();

Das Javascript definiert eine anonyme Funktion und fügt dem Application-DOM einen EventListener hinzu, der darauf reagiert, wenn DOMContentLoaded ausgelöst wird. Aber jetzt kommt das Highlight, falls dies der Fall sein sollte, dann wird die App mit einer Fehlermeldung “This app should never load” abgebrochen!!

Ja was den nun? Für was gibt es eine App, wenn sie nicht geladen werden soll?

OK, manchmal gibt es ja Apps die sind für etwas Besonderes zuständig und haben gar keine UI, wie z. B. Dienste oder Proxys. Ist dies hier vielleicht der Fall?

$mf.Package.Extensions -eq $null
True

Also nix mit Extensions, nada niente.

Übrigens die fürs Wohlergehen zuständige Bing Health und Fitness App liefert z. B. so etwas:

$mfb.Package.Extensions

Extension
———
{Extension, Extension, Extension, Extension…}

$mfb.Package.Extensions.Extension

Category                                 ProxyStub
——–                                 ———
windows.activatableClass.proxyStub       ProxyStub
windows.activatableClass.inProcessServer
windows.activatableClass.inProcessServer
windows.activatableClass.inProcessServer
windows.activatableClass.inProcessServer
windows.activatableClass.inProcessServer

Hier die Beschreibung zu den Extensions und was da möglich ist: https://msdn.microsoft.com/en-us/library/windows/apps/dn934750.aspx. Um es gleich zu sagen, das ist eine Menge! Aber davon, wie gesagt, ist hier nichts gegeben.

Schauen wir noch auf einen weiteren interessanten Parameter, welche Versionsanforderungen die App hat:

$mf.Package.Dependencies.TargetDeviceFamily

Name              MinVersion   MaxVersionTested
—-              ———-   —————-
Windows.Universal 10.0.10069.0 10.0.10069.0

So so, hier wird also eine Buildnummer 10069 als Minimum genannt. Übrigens 10069 war eine Beta vor dem April 2015! Nun gut, bei Top-Programmen kann man das so stehen lassen. Witzig wird aber der Parameter MaxVersionTested. Der besagt, dass 10069 die neueste Version ist, mit welcher die App getestet wurde, was irgendwie null Sinn ergibt, denn es sind ja mittlerweile viele andere Versionen herausgekommen?!?!? Ist das aktives Qualitätsmanagement ala Microsoft?
Noch Infos zu den Dependencies: https://msdn.microsoft.com/en-us/library/windows/apps/dn986903.aspx.

Sei es wie es will, die App macht absolut keinen Sinn.

Übrigens taucht sie wieder an weiterer Stelle auf, wo man nicht unmittelbar mit ihr rechnet. In der Windows Firewall. Dort ist jede App registriert die mit dem Internet kommuniziert:

Get-NetFirewallRule | where DisplayName -eq "App-Verbindung"

Name                  : {F9CB7621-DFB0-4F00-BDB1-8D54D0D53710}
DisplayName           : App-Verbindung
Description           : App-Verbindung
DisplayGroup          : App-Verbindung
Group                 : @{Microsoft.Appconnector_1.3.3.0_neutral__8wekyb3d8bbwe?ms-resource://Microsoft.Appconnector/Resources
                        /ConnectorStubTitle}
Enabled               : True
Profile               : Domain, Private, Public
Platform              : {6.2+}
Direction             : Outbound
Action                : Allow
EdgeTraversalPolicy   : Block
LooseSourceMapping    : False
LocalOnlyMapping      : False
Owner                 : S-1-5-21-XXXXXXXXXX-YYYYYYYYYY-ZZZZZZZZZZ-1001
PrimaryStatus         : OK
Status                : Die Regel wurde erfolgreich vom Speicher aus analysiert. (65536)
EnforcementStatus     : NotApplicable
PolicyStoreSource     : PersistentStore
PolicyStoreSourceType : Local

Wie kann man nun diese Ominöse App loswerden, ohne dass man jedes einzelne Einstellungsmenü durchgehen muss? Man verwendet einfach Remove-AppXPackage:

Remove-AppXPackage –Package $app.PackageFullName

Dadurch verschwindet die App aus allen Menüs wie bei den Datenschutz-Einstellungen. Schaut man sich aber den Installationspfad an, dann ist sie immer noch vorhanden, könnte also potentiell irgendeinen Blödsinn ausrichten. Also am besten entsorgt man das komplette Paket von der Platte:

$pro=Get-AppxProvisionedPackage -Online | where Displayname -eq $app.name
$pro

DisplayName  : Microsoft.Appconnector
Version      : 2015.707.550.0
Architecture : neutral
ResourceId   : ~
PackageName  : Microsoft.Appconnector_2015.707.550.0_neutral_~_8wekyb3d8bbwe

 

Remove-AppxProvisionedPackage -Online -PackageName $pro.PackageName

Path          :
Online        : True
RestartNeeded : False

So jetzt ist endlich Schluss mit dem Schrott. Zum Abschluss muss ich noch einen Ablassen über die Officesupport-Artikel…


Folgen

Erhalte jeden neuen Beitrag in deinen Posteingang.