none
Files kopieren anhand von Magic Numbers

    Frage

  • Hallo

    Ich muss Files von A nach B Kopieren.

    Vorher muss ich sie validieren nach File extention und Magic Numbers.

    Ist das mit Powershell realisierbar?

    Danke im voraus für eure Unterstützung.

    Gruss

    René

    Montag, 9. Juli 2018 09:52

Antworten

  • Da es sehr viele Fileformate gibt (jede Anwendung hat hier eigenes), stehst du wahrlich vor einer Mammutaufgabe, die zudem auch noch unsicher wird.

    Seit Jahren/Jahrzenten ist man eigentlich mit Virenscannern (oder Bitdefender wers mag) gut genug gefahren.

    Zumal ja jeder Softwareupdate eine andere "Signatur" seiner Dokumente erzeugen kann oder diese auch wiederum vom Inhalt abhängt.
    Eine PDF fängt z.B. mit "%PDF" gefolgt von der Version an. Was hindert mich also, in eine Textdatei "%PDF-1.3" reinzuschreiben?

    Ich glaube, diese Aufgabenstellung solltest du vergessen und wie alle, z.B., robocopy verwenden.

    Montag, 9. Juli 2018 13:29
  • Hmmm .... kann sein, dass ich noch nicht alles verstanden habe, aber wenn Du in Deiner Funktion Get-MagicNumber ganze Verzeichnisse verabeitest, solltest Du nicht nur die Magic Numbers in der Ausgabe haben, sondern auch noch die zugehörigen Dateien, oder? Sonst weißt Du ja gar nicht, auf welche Datei sich welche Magic Number bezieht. Wenn man Deiner Funktion nur einen Pfad übergibt (ohne Dateimaske) dann knirscht es auch gewaltig.  Vielleicht schaust Du Dir mal die Hilfe für about_Funtions_advanced_Parameters an.

    Best regards,

    (79,108,97,102|%{[char]$_})-join''

    Montag, 9. Juli 2018 11:44

Alle Antworten

  • Hallo René, erstmal Willkommen im deutschen Powershell Forum.

    Ohne eine Vorstellung davon zu haben, was Magic Numbers sind, würde ich sagen, das sollte kein Problem darstellen.

    Vorsorglich möchte ich aber schon mal darauf hinweisen, dass wir hier keinen Code / Scripte auf Bestellung liefern.

    Für die meisten Copy-Jobs eignet sich übrigens robocopy ganz hervorragend - da ist häufig gar kein aufwändiges Script notwendig.


    Best regards,

    (79,108,97,102|%{[char]$_})-join''

    Montag, 9. Juli 2018 10:03
  • Das Windowsfilesystem (NTFS) unterstützt keine Magic Numbers. Dies ist ein Begriff aus dem Linux-/Unix-Filesystem.

    Mittels Magic Numbers wird i.W. der Typ einer Datei (ausführbar, Text, Script, usw.) festgelegt um die passende Anwendung zu starten.

    In Windows wird dafür die Datei-Endung verwendet, wobei eben "exe", "com" als ausführbarer Code gelten und für alles andere eine Anwendung zuständig ist. Diese erkennt dann, ob sie mit dem Inhalt was anfangen kann.

    Eine Umbenennung auf Linux führt nicht zur Änderung der Magic Number, eine Umbenennung der Endung auf Windows kann durchaus auch zu katastrophalen Ergebnissen führen (falls ausführbarer Code enthalten ist).

    • Bearbeitet bfuerchau Montag, 9. Juli 2018 10:33
    Montag, 9. Juli 2018 10:25
  • Hallo BOfH_666

    Dank für die rasche Antwort.

    Mit Magic Numbers meint ich die File Signaturen

    https://en.wikipedia.org/wiki/List_of_file_signatures

    Ich bin der Meinung das das eben robocopy nicht kann.

    Ich kann die File Signaturen abfragen mit:

    $path = "C:\temp\test"

    function Get-MagicNumber ($path)
    { Resolve-Path $path | Foreach-Object {
    $magicnumber = Get-Content -encoding byte $_ -read 4 -total 4
    $hex1 = ("{0:x}" -f ($magicnumber[0] * 256 + $magicnumber[1])).PadLeft(4, "0")
    $hex2 = ("{0:x}" -f ($magicnumber[2] * 256 + $magicnumber[3])).PadLeft(4, "0")
    [string] $chars = $magicnumber| %{ if ([char]::IsLetterOrDigit($_))
    { [char] $_ } else { "." }}
    "{0} {1} '{2}'" -f $hex1, $hex2, $chars }
    }


    cd C:\temp\test
    $path = Get-ChildItem -Path C:\temp\test
    Get-MagicNumber $path

    $ArrayMN = Get-MagicNumber $path
    $ArrayCI = Get-ChildItem -Path C:\temp\test | Select-Object Fullname

    Und habe die Werte dann in Variablen.

    Gibt es eine möglichkeit die Werte in ein PS Array zu Mergen, so dass ich in diesem wieder Selektiren kann um zu kopieren?

    Ich habe es versucht mit:

    $ArrayMN = @(Get-MagicNumber $path)
    $ArrayCI = @(Get-ChildItem -Path C:\temp\test | Select-Object Fullname)
    0..($ArrayCI.Count - 0) | ForEach-Object {$TArray += @("$($ArrayMN[$_]) $($ArrayCI[$_])")}
    $TArray | sort | Get-Unique -AsString

    $RArray = $TArray | Select-String -SimpleMatch "7664 7673 'v d v s'", "4d5a 9000 'M Z . .'", "7361 6661 's a f a'" | sort | Get-Unique -AsString | ft
    $RArray | ft

    Ausgabe:

    PS C:\temp\test> $RArray = $TArray | Select-String -SimpleMatch "7664 7673 'v d v s'", "4d5a 9000 'M Z . .'", "7361 6661 's a f a'" | sort | Get-Unique -AsString | ft
    $RArray | ft

    IgnoreCase LineNumber Line                                                      Filename    Path        Pattern             Context Matche
                                                                                                                                        s     
    ---------- ---------- ----                                                      --------    ----        -------             ------- ------
          True          1 @{FullName=C:\temp\test\cp029814.exe} 4d5a 9000 'M Z . .' InputStream InputStream 4d5a 9000 'M Z . .'         {}    
          True          6 4d5a 9000 'M Z . .' @{FullName=C:\temp\test\cp029814.exe} InputStream InputStream 4d5a 9000 'M Z . .'         {}   

    Danach geht das kopieren nicht.

    Ich denke das der merge nicht richtig ist.

    Gruss

    René

    Montag, 9. Juli 2018 10:42
  • Hallo

    Vielleicht noch was zu unserem Case

    Wir wollen Files von einer unsicheren Umbebung in eine sichere Umgebung kopieren.
    Der User legt die Dateien (.txt,.pdf und .csv) in einen Ordner auf der unsicheren Seite.
    Ein Script soll dann die Dateien auf die Sichere Seite kopieren.
    Damit nicht andere Dateitypen (umbennenen der Extention) auf die sichere Seite gelangen können möchten wir noch die File Signaturen (Magic Numbers) überprüfen.

    Gruss
    René
    Montag, 9. Juli 2018 10:55
  • Hallo BOfH_666

    Dank für die rasche Antwort.

    Mit Magic Numbers meint ich die File Signaturen

    https://en.wikipedia.org/wiki/List_of_file_signatures

    Ich bin der Meinung das das eben robocopy nicht kann.

    Ich kann die File Signaturen abfragen mit:

    $path = "C:\temp\test"

    function Get-MagicNumber ($path)
    { Resolve-Path $path | Foreach-Object {
    $magicnumber = Get-Content -encoding byte $_ -read 4 -total 4
    $hex1 = ("{0:x}" -f ($magicnumber[0] * 256 + $magicnumber[1])).PadLeft(4, "0")
    $hex2 = ("{0:x}" -f ($magicnumber[2] * 256 + $magicnumber[3])).PadLeft(4, "0")
    [string] $chars = $magicnumber| %{ if ([char]::IsLetterOrDigit($_))
    { [char] $_ } else { "." }}
    "{0} {1} '{2}'" -f $hex1, $hex2, $chars }
    }


    cd C:\temp\test
    $path = Get-ChildItem -Path C:\temp\test
    Get-MagicNumber $path

    $ArrayMN = Get-MagicNumber $path
    $ArrayCI = Get-ChildItem -Path C:\temp\test | Select-Object Fullname

    Und habe die Werte dann in Variablen.

    Gibt es eine möglichkeit die Werte in ein PS Array zu Mergen, so dass ich in diesem wieder Selektiren kann um zu kopieren?

    Ich habe es versucht mit:

    $ArrayMN = @(Get-MagicNumber $path)
    $ArrayCI = @(Get-ChildItem -Path C:\temp\test | Select-Object Fullname)
    0..($ArrayCI.Count - 0) | ForEach-Object {$TArray += @("$($ArrayMN[$_]) $($ArrayCI[$_])")}
    $TArray | sort | Get-Unique -AsString

    $RArray = $TArray | Select-String -SimpleMatch "7664 7673 'v d v s'", "4d5a 9000 'M Z . .'", "7361 6661 's a f a'" | sort | Get-Unique -AsString | ft
    $RArray | ft

    Ausgabe:

    PS C:\temp\test> $RArray = $TArray | Select-String -SimpleMatch "7664 7673 'v d v s'", "4d5a 9000 'M Z . .'", "7361 6661 's a f a'" | sort | Get-Unique -AsString | ft
    $RArray | ft

    IgnoreCase LineNumber Line                                                      Filename    Path        Pattern             Context Matche
                                                                                                                                        s     
    ---------- ---------- ----                                                      --------    ----        -------             ------- ------
          True          1 @{FullName=C:\temp\test\cp029814.exe} 4d5a 9000 'M Z . .' InputStream InputStream 4d5a 9000 'M Z . .'         {}    
          True          6 4d5a 9000 'M Z . .' @{FullName=C:\temp\test\cp029814.exe} InputStream InputStream 4d5a 9000 'M Z . .'         {}   

    Danach geht das kopieren nicht.

    Ich denke das der merge nicht richtig ist.

    Gruss

    René

    Mach mal beim "$ArrayCI = Get-ChildItem -Path C:\temp\test | Select-Object Fullname" ein "$ArrayCI = Get-ChildItem -Path C:\temp\test | Select-Object -ExpandProperty Fullname"
    Und poste das nächste mal Code als Code ;-)



    • Bearbeitet BeatYa Montag, 9. Juli 2018 12:26
    Montag, 9. Juli 2018 11:00
  • Da du deine eigene Magic-Number generierst in dem du die ersten 4 Bytes ausliest, hast du keine Magic-Number sondern die ersten 4 Bytes, die in der Datei stehen.
    Wenn ich also eine .TXT erstelle und eine Zeile mit "AA" erfasse, bekommst du 4 Zeichen "AA" + CRLF zurück.
    Durch einfaches Ändern von AA in BB bekommst du bereits eine andere Magic-Number.

    Und dies zieht sich eben durch alle Fileobjekte.
    Ändere ich die Dateiendung, ändert sich nur der Dateiname aber nicht der Inhalt. Deine Magic-Number ändert sich also nicht.

    Ich weiß also nicht, was du dadurch an Sicherheit gewinnen willst.

    Montag, 9. Juli 2018 11:05

  • $path = "C:\temp\test"
    
    function Get-MagicNumber ($path)
    { Resolve-Path $path | Foreach-Object {
    $magicnumber = Get-Content -encoding byte $_ -read 4 -total 4
    $hex1 = ("{0:x}" -f ($magicnumber[0] * 256 + $magicnumber[1])).PadLeft(4, "0")
    $hex2 = ("{0:x}" -f ($magicnumber[2] * 256 + $magicnumber[3])).PadLeft(4, "0")
    [string] $chars = $magicnumber| %{ if ([char]::IsLetterOrDigit($_))
    { [char] $_ } else { "." }}
    "{0} {1} '{2}'" -f $hex1, $hex2, $chars }
    }
    
    
    cd C:\temp\test
    $path = Get-ChildItem -Path C:\temp\test
    Get-MagicNumber $path
    
    $ArrayMN = Get-MagicNumber $path
    $ArrayCI = Get-ChildItem -Path C:\temp\test | Select-Object -ExpandProperty Fullname
    
    
    # Arrays zusammenfügen
    $ArrayMN = @(Get-MagicNumber $path)
    $ArrayCI = @(Get-ChildItem -Path C:\temp\test | Select-Object -ExpandProperty Fullname)
    0..($ArrayCI.Count - 0) | ForEach-Object {$TArray += @("$($ArrayMN[$_]) $($ArrayCI[$_])")}
    $TArray | sort | Get-Unique -AsString
    
    $RArray = $TArray | Select-String -SimpleMatch "7664 7673 'v d v s'", "4d5a 9000 'M Z . .'", "7361 6661 's a f a'" | sort | Get-Unique -AsString | ft
    $RArray | ft

    Ausgabe:

    IgnoreCase LineNumber Line                                                      Filename    Path        Pa
                                                                                                            tt
                                                                                                            er
                                                                                                            n
    ---------- ---------- ----                                                      --------    ----        --
          True          1 @{FullName=C:\temp\test\cp029814.exe} 4d5a 9000 'M Z . .' InputStream InputStream 4d
          True          6 4d5a 9000 'M Z . .' @{FullName=C:\temp\test\cp029814.exe} InputStream InputStream 4d
          True         11 4d5a 9000 'M Z . .' C:\temp\test\cp029814.exe             InputStream InputStream 4d

    Der Filename ist bei der Ausgabe InputSream.

    Montag, 9. Juli 2018 11:21
  • Hmmm .... kann sein, dass ich noch nicht alles verstanden habe, aber wenn Du in Deiner Funktion Get-MagicNumber ganze Verzeichnisse verabeitest, solltest Du nicht nur die Magic Numbers in der Ausgabe haben, sondern auch noch die zugehörigen Dateien, oder? Sonst weißt Du ja gar nicht, auf welche Datei sich welche Magic Number bezieht. Wenn man Deiner Funktion nur einen Pfad übergibt (ohne Dateimaske) dann knirscht es auch gewaltig.  Vielleicht schaust Du Dir mal die Hilfe für about_Funtions_advanced_Parameters an.

    Best regards,

    (79,108,97,102|%{[char]$_})-join''

    Montag, 9. Juli 2018 11:44
  •  Hallo bfuerchau

    Danke für deinen Hinweis.

    Du hast recht, bei txt und csv geht es so nicht.

    Evtl. nüssen wir auf xls gehen oder ein anderes Format mir File Signatur.

    Gruss

    René

    Montag, 9. Juli 2018 13:14
  • Da es sehr viele Fileformate gibt (jede Anwendung hat hier eigenes), stehst du wahrlich vor einer Mammutaufgabe, die zudem auch noch unsicher wird.

    Seit Jahren/Jahrzenten ist man eigentlich mit Virenscannern (oder Bitdefender wers mag) gut genug gefahren.

    Zumal ja jeder Softwareupdate eine andere "Signatur" seiner Dokumente erzeugen kann oder diese auch wiederum vom Inhalt abhängt.
    Eine PDF fängt z.B. mit "%PDF" gefolgt von der Version an. Was hindert mich also, in eine Textdatei "%PDF-1.3" reinzuschreiben?

    Ich glaube, diese Aufgabenstellung solltest du vergessen und wie alle, z.B., robocopy verwenden.

    Montag, 9. Juli 2018 13:29
  • ?? ... ich könnte mir vorstellen, dass Du das Problem noch nicht ganz verstanden hast (oder ich hab es noch nicht verstanden ;-)  ). Willst Du wirklich die "Signaturen" aller erlaubten Datei-Typen manuell in Deinem Script pflegen? Das klingt mir ziemlich aufwändig und fehlerträchtig.


    Best regards,

    (79,108,97,102|%{[char]$_})-join''

    Montag, 9. Juli 2018 13:29
  • Zumal es (außer bie EXE und COM) ja keine Signaturen für Dateiinhalte gibt.
    Nimm nur mal die ganzen ausführbaren Dateien mit Macrocode (bat, vbs, js, wsh, ps1, ...).
    Die 1. 4 Bytes der 1. Zeile dieser Dateien wäre ja im Prinzip die Signatur nach obiger Magic Number-Methode.
    Und dieser Wert wäre aber so was von nicht distinct.
    Montag, 9. Juli 2018 13:47