zeddler0
Goto Top

Cmd,ps: Signaturzeitpunkt einer datei auslesen, unmöglich

hallo,
ich hab ein kleines problem:

ich möchte von einer datei "C:\Windows\explorer.exe"
gewisse zertifikatinformationen herausbekommen.

eigentlich nur eine, und zwar den
"Signaturzeitpunkt/Signature Date/Date signed"-wert.


es ist schwerer als ich gedacht habe.
bei powerschell hab ich & ein kollege mich schon mit 'Get-Certificate' & 'Get-ItemProperty' rumgeprügelt

bei cmd bin ich bei 'certutil' hängengeblieben.

bei 'certutil' gibs zwar haufen schalter, aber da scheind keiner so recht zu passen.
aber mit dem 'dump' befehl konnte ich immerhin meine information finden.

theoretisch könnte ich den string filtern,
zu dumm das das filterwort meiner wahl auf deutsch ist "Signaturzeitpunkt",
was auf einem potenziellen sprach fremden system nicht funktioniert.

in powershell konnte ich leider keinen vergleichbaren 'dump'-befehl nicht finden,
das hätte die interoperabilität gesichert.

es wäre natürlich wunderbar, wenn man den wert irgendwie direkt auslesen könnte...

Content-ID: 3358340273

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

Ausgedruckt am: 17.11.2024 um 23:11 Uhr

Trelane
Trelane 17.07.2022 um 00:27:30 Uhr
Goto Top
Hi.

Hat tatsächlich auch eine Weile gebraucht, es per Google zu finden, aber hier wird genau dein Problem beschrieben und gelöst:

www.sysadmins.lv/blog-en/retrieve-timestamp-attribute-from-digital-signature.aspx
bzw.
www.sysadmins.lv/blog-en/reading-multiple-signatures-from-signed-file-with-powershell.aspx

Hoffe das hilft.

Viele Grüße
Trelane
zeddler0
zeddler0 17.07.2022 um 00:41:52 Uhr
Goto Top
thx.
es ist schön zu sehen, dass es möglich ist.

schade, dass es, für 'nur' einen wert so eskaliert. face-sad
mein ziel ist meist ein einzeiler, den ich via cmd-shell eine powershell-abfrage starte.

ist es möglich die "crypt32.dll" für einen befehl direkt verwenden, um so das script zu kürzen?

scripten kann ich mir meist zusammenreimen,
aber das ist auf programierer-level...
haichen
haichen 17.07.2022 um 09:50:11 Uhr
Goto Top
Sigcheck von Sysinternals zeigt das Signing Date (Signaturzeitpunkt):

sigcheck -i c:\windows\explorer.exe
...
c:\windows\explorer.exe:
        Verified:       Signed
        Link date:      05:36 19.01.1919
        Signing date:   12:51 18.06.2022
        ..
zeddler0
zeddler0 17.07.2022 aktualisiert um 10:43:15 Uhr
Goto Top
haha, you trickt me.

normalerweise verbietet mir meine OOE-mentalität programme nachzuladen,
da ich nicht sicher sein kann, dass ich online bin.

da aber es ja für ein download-script ist
und Sysinternals statische links der programme anbietet,
so wiederspreche ich mich ja selbst.

netter gedanke, ich werde mir es mal anschauen.

ich hoffe nur das die durch ein update die ausgabe nicht ändern.
kann man den wert "Signing date" direkt abfragen?

powershell mit deinen genormten ausgaben wäre aber ein wunschkanidat. :D

---

edit:
ahrg! verdammt funktioniert nicht nach meiner OOE-regel. face-sad
sie genau die formatierung meines zeitstempel an.
die formatierung wird aus den windowseinstellungen ausgelesen,
statt seine eigene zu verwenden.
ich kann nicht sicher sein, dass auf alle sprachversionen die zeit identisch dargestellt wird.
leider unbrauchbar ich wirr auch ungern die einstellungen fremder systeme verstellen,
nur um den wert richtig zu formatieren.
sigsheck_fail
colinardo
colinardo 17.07.2022 aktualisiert um 11:46:58 Uhr
Goto Top
Servus.
Zitat von @zeddler0:
ich kann nicht sicher sein, dass auf alle sprachversionen die zeit identisch dargestellt wird.
leider unbrauchbar ich wirr auch ungern die einstellungen fremder systeme verstellen,
nur um den wert richtig zu formatieren.
Dazu hat die PS doch die passenden DateTime Parse-Methoden mit CultureInfo face-smile
Mit einer lokal liegenden "sigcheck" dann bspw. so in einer CMD
@echo off
set "file=C:\Windows\explorer.exe"  
powershell -EP Bypass -C "[datetime]::Parse(([regex]::match((sigcheck.exe '%file%' -accepteula | out-string),'(?i)(?<=Signing date:\s+).*').Value.trim() -replace '([^\s]+) ([^\s]+)','$2 $1'),[cultureinfo]::CurrentCulture).toString('dd.MM.yyyy HH:mm:ss')"  
Grüße Uwe

p.s. die oben verlinkten PS Funktionen versagen übrigens kläglich bei Signaturen vom Typ "Catalog" im Gegensatz zu sigcheck!

p.s.2 Einzeiler kann man immer bauen indem man den Code in Base64 kodiert und via Invoke-Expression ausführt, ob das aber immer sinnvoll ist ... Dann baue ich mir doch lieber gleich eine eigene exe mit c# oder verlagere die Funktion in eine eigene Bibliothek/dll wenn es mal etwas aufwändiger ist.
zeddler0
zeddler0 17.07.2022 um 12:21:04 Uhr
Goto Top
da ich cmd-werte gern mit FOR ermittel, so kann ich dessen variable einfach in powershell pumpen

beispiel in ps:
"12:51 2022-06-18" | Get-Date -f "<yyyy_MM_dd> [hh=mm=ss]"

powershell kann ziehmlich gut die zeitformatierungen erkennen.
ich weiß aber nicht ob es alle erkennen kann.
in den usa wird gern mal der tag&monat vertauscht.
"2022/18/06"

und das bekommt der nicht erkannt... face-sad

ich weiß aber nicht ob es dort ein windows systemstandard ist,
bzw. in welchen anderen land/region das verwendet wird.
es ist ein risiko, wenn ich nicht irgendwo eine liste bekomme,
wo diese regionalen unterscheide aufgeführt sind.
colinardo
colinardo 17.07.2022 aktualisiert um 12:44:38 Uhr
Goto Top
Zitat von @zeddler0:
powershell kann ziehmlich gut die zeitformatierungen erkennen.
ich weiß aber nicht ob es alle erkennen kann.
in den usa wird gern mal der tag&monat vertauscht.
"2022/18/06"

und das bekommt der nicht erkannt... face-sad

Doch aber man muss das System-Pattern nur auslesen ...
[cultureinfo]::CurrentUICulture.DateTimeFormat.ShortDatePattern
[cultureinfo]::CurrentUICulture.DateTimeFormat.ShortTimePattern
etc. So lässt es sich passend mittels ParseExact() machen. Man muss nur wissen wo es steht face-smile.

Um beim obigen Beispiel zu bleiben dann
@echo off
set "file=C:\Windows\explorer.exe"  
powershell -EP Bypass -C "[datetime]::ParseExact([regex]::match((sigcheck.exe '%file%' -accepteula | out-string),'(?i)(?<=Signing date:\s+).*').Value.trim(),([cultureinfo]::CurrentUICulture.DateTimeFormat.ShortTimePattern,[cultureinfo]::CurrentUICulture.DateTimeFormat.ShortDatePattern) -join ' ',[cultureinfo]::CurrentUICulture).toString('dd.MM.yyyy HH:mm:ss')"  
zeddler0
zeddler0 17.07.2022 um 12:41:31 Uhr
Goto Top
wie integriere ich es in mein beispiel-command?

"12:51 2022-06-18" | Get-Date -f "<yyyy_MM_dd> [hh=mm=ss]"  
colinardo
colinardo 17.07.2022 um 12:46:07 Uhr
Goto Top
s. Beispiel im letzten Post.
zeddler0
zeddler0 17.07.2022 aktualisiert um 12:55:12 Uhr
Goto Top
ich habe schwierigkeiten da zu meinem beispiel umzubauen,
da ich nicht alles verstehe... face-sad

es ist ziehmlich lang... o.O
colinardo
colinardo 17.07.2022 aktualisiert um 13:03:55 Uhr
Goto Top
Zitat von @zeddler0:
es ist ziehmlich lang... o.O

Hmpf, Sonntag ... du scheinst allgemein Probleme mit "Länge" zu haben face-wink ...
$c = [cultureinfo]::CurrentUICulture
[datetime]::ParseExact("12:51 2022-06-18",($c.DateTimeFormat.ShortTimePattern,$c.DateTimeFormat.ShortDatePattern) -join ' ',$c).toString('<yyyy_MM_dd> [hh=mm=ss]')  
Wie gesagt, richtet sich nach der aktuell konfigurierten UI Culture und der hiesigen automatischen Formatierung von sigcheck!
Für das Beispiel muss dein Culture-DateTimeFormat also wie der Beispiel String konfiguriert sein (der ja für die Ausgabe von sigcheck steht).
zeddler0
zeddler0 17.07.2022 um 13:05:20 Uhr
Goto Top
kann man $c direkt in den befehl einbauen?

klar ich könnte es mit ";" ketten,
aber dann würde ich die integration nicht verstehen...
colinardo
colinardo 17.07.2022 aktualisiert um 13:23:16 Uhr
Goto Top
Zitat von @zeddler0:

kann man $c direkt in den befehl einbauen?

Sicher, einfach überall das $c durch [cultureinfo]::CurrentUICulture ersetzen, versteht sich doch eigentlich von selbst, du wolltest es doch "kurz" face-smile und so hätte es einige Wiederholungen durch die Verwendung der Variablen gespart. Entscheide dich mal ... 🖖

Grüße Uwe
zeddler0
zeddler0 17.07.2022 aktualisiert um 13:12:37 Uhr
Goto Top
muss das irgendwie abgegrenzt werden "" () '' oder so?
oder einfach ersetzen?

ja ich habs gesehen, wenn sich das 3x wiederholt, dann ergibt das auch sinn mit den variablen.
colinardo
colinardo 17.07.2022 um 13:15:41 Uhr
Goto Top
Zitat von @zeddler0:

muss das irgendwie abgegrenzt werden "" () '' oder so?
Nein einfach nur ersetzen [cultureinfo]::CurrentUICulture ist ein Object, und von diesem wird per folgendem Punkt die Property DateTimeFormat.ShortTimePattern etc. abgerufen

Ergo ist bspw.
$c = [cultureinfo]::CurrentUICulture
$c.DateTimeFormat.ShortTimePattern
gleich das
[cultureinfo]::CurrentUICulture.DateTimeFormat.ShortTimePattern
zeddler0
zeddler0 17.07.2022 um 13:17:50 Uhr
Goto Top
hmm... klappt irgendwie nicht?
err
colinardo
colinardo 17.07.2022 aktualisiert um 13:23:58 Uhr
Goto Top
Ich habe doch oben schon gesagt das dafür das Format in den Regionsoptionen umgestellt werden muss wenn man es mit einem plain string eines anderen Formats testet!! Das klappt sonst nur wenn der String direkt von sigcheck kommt weil diese das hinterlegte Format aus den Regionsoptionen benutzt!!!!

Von Copy und Paste lernst du nichts mein Freund du musst die Posts schon komplett lesen und verstehen was da passiert!

Also als erstes mal Doku lesen
https://docs.microsoft.com/de-de/dotnet/api/system.datetime.parseexact?v ...

Und als Wochenend-Lektüre
Powershell Leitfaden für Anfänger
zeddler0
zeddler0 17.07.2022 um 13:32:27 Uhr
Goto Top
"Das klappt sonst nur wenn der String direkt von sigcheck"

dann kann ich es so nicht immer verwenden,
da diese werte nicht immer von einer anwendung kommen.

ich leg das erstmal ins archiv, bis ich wieder auf so ein problem stoße.

trozdem danke. und ein schönen WE noch...
colinardo
colinardo 17.07.2022 aktualisiert um 13:46:53 Uhr
Goto Top
Zitat von @zeddler0:
dann kann ich es so nicht immer verwenden,
da diese werte nicht immer von einer anwendung kommen.
Du kannst auch mit TryParseExact verschiedene Format-Varianten einer Liste durchprüfen bis eine davon matcht und das Datum als DateTime zurückgeben, das wäre auch kein Problem.

Beispiel
<#
    Check if string can be parsed from multiple valid datetime formats 
#>

function Check-ValidDate {
    [OutputType([datetime])]
    param(
        [parameter(mandatory=$true,ValueFromPipeline=$true)][string[]]$datestring,
        [parameter(mandatory=$true)][string[]]$dateformats
    )
    $dt = [datetime]0
    $dateformats | %{
        if([datetime]::TryParseExact($datestring,$_,[cultureinfo]'','None',[ref]$dt)){  
            return $dt
            break
        }
    }
}
Check-ValidDate -datestring '10/21/2010' -dateformats 'yyyy/MM/dd','yyyy-MM-dd','dd.MM.yyyy','MM/dd/yyyy'  
Aber wenn du nicht weist welche Anwendung seine Ausgaben wie formatiert kann es nie immer 100% eindeutig sein!
Wie sollte also ein Programm 2022/04/03 zu 100% interpretieren? Die 04 könnten der Monat oder auch der Tag sein, du must also zwingend eine Definition oder Referenz haben ...
zeddler0
zeddler0 17.07.2022 um 13:46:51 Uhr
Goto Top
"Anonsten eben eine kleine KI schreiben"

na wenn ich dann soweit wäre,
dann hätte ich ein gerät, dass für mich lebt...

XD
haichen
haichen 17.07.2022 aktualisiert um 18:08:24 Uhr
Goto Top
Das Beispiel von Colinardo ist wirklich toll. Schreib doch einfach mal den ganzen Code in
sigcheck.bat (pass die zweite Zeile an deinen Pfad zur sigcheck.exe an)

@echo off
set "file=C:\Windows\explorer.exe"  
set "sigcheckpath=C:\Path\to\sigcheck.exe"  
set "timeformat=dd.MM.yyyy HH:mm:ss"  

powershell -EP Bypass -C "$c = [cultureinfo]::CurrentUICulture;[datetime]::ParseExact([regex]::match((%sigcheckpath% '%file%' -accepteula | out-string),'(?i)(?<=Signing date:\s+).*').Value.trim(),($c.DateTimeFormat.ShortTimePattern,$c.DateTimeFormat.ShortDatePattern) -join ' ',$c).toString('%timeformat%')"  
pause
=>
18.06.2022 12:51:00
Drücken Sie eine beliebige Taste . . .
zeddler0
zeddler0 18.07.2022 um 20:29:20 Uhr
Goto Top
ich muss nochmal nachfragen...

bei mir kann cultureinfo nicht gehen,
da ich mein datumsformat von (de) dd.MM.yyyy eigenmächtig zu yyyy-MM-dd geändert habe.

damit ist es ein weiterer theoretischer fehlerpunkt.
ist es möglich das pattern auszulesen und anzuzeigen?
colinardo
colinardo 18.07.2022 aktualisiert um 20:42:08 Uhr
Goto Top
Zitat von @zeddler0:
bei mir kann cultureinfo nicht gehen,
da ich mein datumsformat von (de) dd.MM.yyyy eigenmächtig zu yyyy-MM-dd geändert habe.
Doch denn das Skript liest diesen Pattern aus.
damit ist es ein weiterer theoretischer fehlerpunkt.
Nö denn das Skript liest den selbst angepassten Pattern ja aus automatisch !
ist es möglich das pattern auszulesen und anzuzeigen?
Macht das Skript bereits hiermit 😉
[cultureinfo]::CurrentUICulture.DateTimeFormat.ShortTimePattern

[cultureinfo]::CurrentUICulture.DateTimeFormat.ShortDatePattern
Deswegen sage ich ja immer, Leute lest den Code und versteht ihn bevor ihr ihn nutzt! Hättest du das zumindest mal getan, was man hier in einem Admin-Forum eigentlich erwarten kann, wäre die Frage jetzt überflüssig.


Bitte dann auch den Thread hier zu einem Ende bringen und schließen nicht vergessen.
Merci.

So long.
Grüße Uwe
zeddler0
zeddler0 19.07.2022 um 00:38:17 Uhr
Goto Top
ich weiß nicht, ob es ein bug in powershell ist, aber
"[cultureinfo]::CurrentUICulture.DateTimeFormat.ShortDatePattern" gibt mir das deutsche format "dd.MM.yyyy" aus.
mein geändertes format ist aber "yyyy-MM-dd"

am ende bin ich darauf gekommen, ich les den spaß einfach aus der registry aus... :P
aber der ps-befehl soll der richtige sein?
colinardo
colinardo 19.07.2022 aktualisiert um 07:49:05 Uhr
Goto Top
Zitat von @zeddler0:
aber der ps-befehl soll der richtige sein?

Definitiv

back-to-topUmgestellt

screenshot

back-to-topErneute Umstellung zurück mit anschließendem erneuten Aufruf

screenshot
haichen
haichen 21.07.2022 um 08:03:48 Uhr
Goto Top
Hallo zeddler0,
es ist (so wie ich den Code/Microsoft verstehe) schnuppe, wie Du das Datumformat eingestellt hast.
Falls Du aber als Ausgabe lieber - hast, ändere doch das Skript (Zeile 4):
@echo off
set "file=C:\Windows\explorer.exe"  
set "sigcheckpath=C:\Path\to\sigcheck.exe"  
set "timeformat=dd-MM-yyyy HH:mm:ss"  

powershell -EP Bypass -C "$c = [cultureinfo]::CurrentUICulture;[datetime]::ParseExact([regex]::match((%sigcheckpath% '%file%' -accepteula | out-string),'(?i)(?<=Signing date:\s+).*').Value.trim(),($c.DateTimeFormat.ShortTimePattern,$c.DateTimeFormat.ShortDatePattern) -join ' ',$c).toString('%timeformat%')"  
pause
Ich habe, wie Colinardo, auch mal das Datumformat umgestellt. Läuft.
zeddler0
zeddler0 22.07.2022 um 14:01:59 Uhr
Goto Top
hab ich irgendwas übersehen?
eigendlich hab ich den code nur 1:1 kopiert & ausgefüllt... o.O

$c = [cultureinfo]::CurrentUICulture;[datetime]::ParseExact([regex]::match((\\live.sysinternals.com\tools\sigcheck64.exe 'C:\Windows\explorer.exe' -accepteula | out-string),'(?i)(?<=Signing date:\s+).*').Value.trim(),($c.DateTimeFormat.ShortTimePattern,$c.DateTimeFormat.ShortDatePattern) -join ' ',$c).toString('dd_MM_yyyy HH-mm-ss')  
greenshot - 20220722-140029 - windows powershell [mic-ws]
colinardo
colinardo 22.07.2022 aktualisiert um 14:38:03 Uhr
Goto Top
hab ich irgendwas übersehen?
Remote über das sysinternals repo funktioniert das in der Regel wegen den Sicherheitszonen nicht. Leg die exe in einen lokalen Pfad. Klappt hier von W7 über W10/11 bis Server 2022 überall fehlerfrei.
zeddler0
zeddler0 22.07.2022 aktualisiert um 14:58:37 Uhr
Goto Top
irgendwas stimmt da nicht.
könnt ihr das mal gegen prüfen?

[CurrentUICulture_Test.cmd]
@echo off

:CurrentUICulture_Test
	FOR /f "tokens=1 delims=," %%a  IN (' PowerShell  " [cultureinfo]::CurrentUICulture.DateTimeFormat.ShortDatePattern " ')  DO (set "xPSDateF=%%a")  
	FOR /f "tokens=1 delims=," %%a  IN (' PowerShell  " [cultureinfo]::CurrentUICulture.DateTimeFormat.ShortTimePattern " ')  DO (set "xPSTimeF=%%a")  
	echo. PS:[%xPSDateF%][%xPSTimeF%]

	FOR /f "tokens=1 delims=," %%a  IN (' PowerShell  " (Get-ItemProperty -Path 'HKCU:\Control Panel\International').sShortDate " ')  DO (set "xDateF=%%a")  
	FOR /f "tokens=1 delims=," %%a  IN (' PowerShell  " (Get-ItemProperty -Path 'HKCU:\Control Panel\International').sShortTime " ')  DO (set "xTimeF=%%a")  
	echo.REG:[%xDateF%][%xTimeF%]

@echo.
@pause

ausgabe bei mir:
 PS:[dd.MM.yyyy][HH:mm]
REG:[yyyy-MM-dd][HH:mm]

---

meine gedanken:
wenn ich es schaffe mein system zu verhunzen,
dann ist das auslesen dieser werte über die registry akkurater,
als über die powerschell...

ich würd gern die registry-kommandos in deinen code-string inegrieren
colinardo
Lösung colinardo 22.07.2022 aktualisiert um 15:46:58 Uhr
Goto Top
Auch das stimmt hier überall überein.
ich würd gern die registry-kommandos in deinen code-string inegrieren
Dann mach doch, hindert dich keiner dran.
[datetime]::ParseExact([regex]::match((sigcheck64 'C:\Windows\explorer.exe' -accepteula | out-string),'(?i)(?<=Signing date:\s+).*').Value.trim(),((gpv 'HKCU:\Control Panel\International' -Name sShortTime),(gpv 'HKCU:\Control Panel\International' -Name sShortDate)) -join ' ',$c).toString('dd_MM_yyyy HH-mm-ss')  
zeddler0
zeddler0 22.07.2022 um 15:44:08 Uhr
Goto Top
ja hatte es probiert, hatte mir wieder fehlermeldungen eingehandelt... egal.
beim direkten vergleich waren ein paar (klammern) anders...

für [cultureinfo]::CurrentUICulture ist die variable nicht mehr nötig.

was mich an powershell stört:
[regex]::match((sigcheck64.exe 'C:\Windows\explorer.exe' -accepteula  
[regex]::match(('sigcheck mit leerzeichen 64.exe' 'C:\Windows\explorer.exe' -accepteula  

der befehl für sigcheck lässt sich nicht mit " oder ' einklammern.
es kommt bei mir schonmal vor, dass ein absolute pfad generiert wird, der leerzeichen & sonderzeichen beinhaltet.

auch hat powershell es verweigert, wenn ich den wert für explorer.exe als variable voranstellen wollte,
dann gab es auch eine fehlermeldung.

nunja, da es eh ein ps/cmd-hybried wird, so wird es mich erst mal nicht stören...
colinardo
colinardo 22.07.2022 aktualisiert um 15:52:49 Uhr
Goto Top
Zitat von @zeddler0:
der befehl für sigcheck lässt sich nicht mit " oder ' einklammern.
Doch, das geht problemlos, es muss dann aber ein Punkt (.) oder ein und (&) vorangestellt werden damit es als ausführbarer Befehl erkannt wird.
.'C:\pfad\sigcheck.exe'  
Nennt sich dot-sourcing
& 'C:\pfad\sigcheck.exe'  
Der Unterschied zwischen beiden ist das beim Dot-Sourcing aktuelle Variablen mit in das Environment des Befehls übernommen werden, wohingegen beim "&" das nicht passiert.

Einfach mal hier durcharbeiten da steht das alles wunderbar erklärt und man muss sich nicht unnötig wundern warum und wieso face-smile:
Powershell Leitfaden für Anfänger
haichen
haichen 23.07.2022 um 09:42:17 Uhr
Goto Top
Hallo zeddler0,
colinardo hat das wichtigste schon zusammengefasst. Da ich auch noch nicht sehr viel mit Powershell zu tun hatte, habe ich mir das auch zusammen suchen müssen. Da habe ich dank Dir und colinardo eine ganze Menge gelernt. face-smile

Ich habe seine zusammengefassten Befehle mal ein wenig aufgedröselt:

$sigcheckpath='\\live.sysinternals.com\tools\sigcheck64.exe'  
$file='C:\Windows\explorer.exe'  
$timeformat='yyyy_MM_dd hh=mm=ss'  
$sigcheckresult = & $sigcheckpath $file -accepteula | out-string
$sigcheckresult
$regexresult=[regex]::match($sigcheckresult,'(?i)(?<=Signing date:\s+).*').Value.trim()  
$regexresult
$result=[datetime]::ParseExact($regexresult,($c.DateTimeFormat.ShortTimePattern,$c.DateTimeFormat.ShortDatePattern) -join ' ',$c).toString($timeformat)  
$result