2017-05-29 7 views
2

私は古いPowerShellスクリプトを取得して、以前に接続したUSBデバイスの時刻を表示しようとしています。いくつかの法医学blogsthisのように読んだ後、私はthis scriptthis blogから見つけました。 (Script by Jason Walker)以前に接続されたUSBデバイスでタイムスタンプを取得するにはどうすればよいですか?

残念ながら、タイムスタンプやその他のデバイスに関する有用な詳細は表示されません。だから私はthere should be a way to get that tooを望んでいた。私はこれをどのように組み込むかを見落とすだけです。

Function Get-USBHistory { 
[CmdletBinding()] 
Param 
( 
[parameter(ValueFromPipeline=$True,ValueFromPipelinebyPropertyName=$True)] 
    [alias("CN","Computer")] 
    [String[]]$ComputerName=$Env:COMPUTERNAME, 
    [Switch]$Ping  
) 

Begin { 
    $TempErrorAction = $ErrorActionPreference 
    $ErrorActionPreference = "Stop" 
    $Hive = "LocalMachine" 
    $Key = "SYSTEM\CurrentControlSet\Enum\USBSTOR" 
    } 

    Process 
    {    
    $USBDevices  = @() 
    $ComputerCounter = 0   

    ForEach($Computer in $ComputerName) 
    { 
     $USBSTORSubKeys1 = @() 
     $ChildSubkeys = @() 
     $ChildSubkeys1 = @() 

     $ComputerCounter++   
     $Computer = $Computer.Trim().ToUpper() 
     Write-Progress -Activity "Collecting USB history" -Status "Retrieving USB history from $Computer" -PercentComplete (($ComputerCounter/($ComputerName.Count)*100)) 


     If($Ping) 
     { 
      If(-not (Test-Connection -ComputerName $Computer -Count 1 -Quiet)) 
      { 
       Write-Warning "Ping failed on $Computer" 
       Continue 
      } 
     }#end if ping 

     Try 
     { 
      $Reg = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey($Hive,$Computer) 
      $USBSTORKey = $Reg.OpenSubKey($Key) 
      $USBSTORSubKeys1 = $USBSTORKey.GetSubKeyNames() 
     }#end try    
     Catch 
     { 
      Write-Warning "There was an error connecting to the registry on $Computer or USBSTOR key not found. Ensure the remote registry service is running on the remote machine." 
     }#end catch 

     ForEach($SubKey1 in $USBSTORSubKeys1) 
     {  
      $ErrorActionPreference = "Continue" 
      $Key2 = "SYSTEM\CurrentControlSet\Enum\USBSTOR\$SubKey1" 
      $RegSubKey2 = $Reg.OpenSubKey($Key2) 
      $SubkeyName2 = $RegSubKey2.GetSubKeyNames() 

      $ChildSubkeys += "$Key2\$SubKeyName2" 
      $RegSubKey2.Close()   
     }#end foreach SubKey1 

     ForEach($Child in $ChildSubkeys) 
     { 

      If($Child -match " ") 
      { 
       $BabySubkey = $null 
       $ChildSubkey1 = ($Child.split(" "))[0] 

       $SplitChildSubkey1 = $ChildSubkey1.split("\") 

       0..4 | Foreach{ [String]$BabySubkey += ($SplitChildSubkey1[$_]) + "\"} 

       $ChildSubkeys1 += $BabySubkey + ($Child.split(" ")[-1]) 
       $ChildSubkeys1 += $ChildSubkey1 

      } 
      Else 
      { 
       $ChildSubkeys1 += $Child 
      } 
       $ChildSubKeys1.count 
     }#end foreach ChildSubkeys 

     ForEach($ChildSubkey1 in $ChildSubkeys1) 
     {  
      $USBKey  = $Reg.OpenSubKey($ChildSubkey1) 
      $USBDevice = $USBKey.GetValue('FriendlyName') 
      If($USBDevice) 
      {  
       $USBDevices += New-Object -TypeName PSObject -Property @{ 
        USBDevice = $USBDevice 
        Computer = $Computer 
        Serial = $ChildSubkey1.Split("\")[-1] 
         } 
      } 
       $USBKey.Close()           
      }#end foreach ChildSubKey2 

       $USBSTORKey.Close()    
     #Display results   
    $USBDevices | Select Computer,USBDevice,Serial 
    }#end foreach computer 

    }#end process 

    End 
    {   
    #Set error action preference back to original setting   
    $ErrorActionPreference = $TempErrorAction   
    } 

}#end function 

そして、C#コード:

using System; 
using System.Diagnostics; 
using System.Linq; 
using System.Runtime.InteropServices; 
using Microsoft.Win32; 
using Microsoft.Win32.SafeHandles; 
class Program 
{ 
    static void Main(string[] args) 
    { 
     string usbStor = @"SYSTEM\ControlSet001\Enum\USBSTOR"; 
     using (var keyUsbStor = Registry.LocalMachine.OpenSubKey(usbStor)) 
     { 
      var usbDevices = from className in keyUsbStor.GetSubKeyNames() 
          let keyUsbClass = keyUsbStor.OpenSubKey(className) 
          from instanceName in keyUsbClass.GetSubKeyNames() 
          let keyUsbInstance = new RegistryKeyEx(keyUsbClass.OpenSubKey(instanceName)) 
          select new 
          { 
           UsbName = keyUsbInstance.Key.GetValue("FriendlyName"), 
           ConnectTime = keyUsbInstance.LastWriteTime 
          }; 
      foreach (var usbDevice in usbDevices.OrderBy(x => x.ConnectTime)) 
      { 
       Console.WriteLine("({0}) -- '{1}'", usbDevice.ConnectTime, usbDevice.UsbName); 
      } 
     } 
    } 
} 
/// <summary> 
/// Wraps a RegistryKey object and corresponding last write time. 
/// </summary> 
/// <remarks> 
/// .NET doesn't expose the last write time for a registry key 
/// in the RegistryKey class, so P/Invoke is required. 
/// </remarks> 
public class RegistryKeyEx 
{ 
    #region P/Invoke Declarations 
    // This declaration is intended to be used for the last write time only. int is used 
    // instead of more convenient types so that dummy values of 0 reduce verbosity. 
    [DllImport("advapi32.dll", EntryPoint = "RegQueryInfoKey", CallingConvention = CallingConvention.Winapi, SetLastError = true)] 
    extern private static int RegQueryInfoKey(
     SafeRegistryHandle hkey, 
     int lpClass, 
     int lpcbClass, 
     int lpReserved, 
     int lpcSubKeys, 
     int lpcbMaxSubKeyLen, 
     int lpcbMaxClassLen, 
     int lpcValues, 
     int lpcbMaxValueNameLen, 
     int lpcbMaxValueLen, 
     int lpcbSecurityDescriptor, 
     IntPtr lpftLastWriteTime); 
    #endregion 
    #region Public Poperties 
    /// <summary> 
    /// Gets the registry key owned by the info object. 
    /// </summary> 
    public RegistryKey Key { get; private set; } 
    /// <summary> 
    /// Gets the last write time for the corresponding registry key. 
    /// </summary> 
    public DateTime LastWriteTime { get; private set; } 
    #endregion 
    /// <summary> 
    /// Creates and initializes a new RegistryKeyInfo object from the provided RegistryKey object. 
    /// </summary> 
    /// <param name="key">RegistryKey component providing a handle to the key.</param> 
    public RegistryKeyEx(RegistryKey key) 
    { 
     Key = key; 
     SetLastWriteTime(); 
    } 
    /// <summary> 
    /// Creates and initializes a new RegistryKeyInfo object from a registry key path string. 
    /// </summary> 
    /// <param name="parent">Parent key for the key being loaded.</param> 
    /// <param name="keyName">Path to the registry key.</param> 
    public RegistryKeyEx(RegistryKey parent, string keyName) 
     : this(parent.OpenSubKey(keyName)) 
    { } 
    /// <summary> 
    /// Queries the currently set registry key through P/Invoke for the last write time. 
    /// </summary> 
    private void SetLastWriteTime() 
    { 
     Debug.Assert(Key != null, "RegistryKey component must be initialized"); 
     GCHandle pin = new GCHandle(); 
     long lastWriteTime = 0; 
     try 
     { 
      pin = GCHandle.Alloc(lastWriteTime, GCHandleType.Pinned); 
      if (RegQueryInfoKey(Key.Handle, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, pin.AddrOfPinnedObject()) == 0) 
      { 
       LastWriteTime = DateTime.FromFileTime((long)pin.Target); 
      } 
      else 
      { 
       LastWriteTime = DateTime.MinValue; 
      } 
     } 
     finally 
     { 
      if (pin.IsAllocated) 
      { 
       pin.Free(); 
      } 
     } 
    } 
} 

(申し訳ありませんが、私はPSHコードが正しく強調表示することができません。)

どのように改善するためにこれを使用することができますスクリプト?


更新:、Regeditを使用して、HKLM\SYSTEM\CurrentControlSet\Enum\USBSTOR\<drive>\Propertie‌​s、その後私は奇妙なアクセス権のエラーを得た:鉄の提案@に続いて2017年11月6日

、私が直接レジストリパスにアクセスしようとしました私のユーザーアカウントは管理者です。

  1. Event Viewerに内蔵され、Windowsが使用してカスタムビューを作成するには:私が見つけ

    enter image description here

    他のいくつかのオプションがあります(これはWin8.1です)。ただし、これでは、イベントログを有効にする必要があります。

  2. 同様にをCMDバッチscriptと表示すると、herehereのようになります。 (有効なイベントログが必要です)
  3. hereというフォレンジックに従い、さまざまなレジストリエントリとログファイル(...\Windows\inf\setupapi.dev.log)を調べて最初の接続日を取得しますが、最後の接続方法は不明です。 (おそらく\NTUSER\<username>\Software\Microsoft\Windows\Explorer\MountPoints2のデータを比較しても、わかりませんでした)
  4. また、本 "Windows Registry Forensics: Advanced Digital Forensic Analysis of the Windows Registry"には、(3)ページの95ページ以降の追加ヒントもあります。

潜在的に有用なPSワンライナーである:これはさらに解析される可能性がメッセージ内容のイベント(2003、2102)のためのタイムスタンプを

Get-WinEvent -LogName Microsoft-Windows-DriverFrameworks-UserMode/Operational | where {$_.Id -eq "2003" -or $_.Id -eq "2102"} | Format-Table –Property TimeCreated, Id, Message -AutoSize -Wrap 

与えます。

TimeCreated   Id Message                                                     
-----------   -- -------                                                     
2017-11-09 13:37:04 2102 Forwarded a finished Pnp or Power operation (27, 2) to the lower driver for device                                  
         SWD\WPDBUSENUM\_??_USBSTOR#DISK&VEN_KINGSTON&PROD_DATATRAVELER_G2&REV_PMAP#YYYYY&0#{XXXXX} with status 0x0.                
2017-11-09 13:37:04 2102 Forwarded a finished Pnp or Power operation (27, 23) to the lower driver for device                                  
         SWD\WPDBUSENUM\_??_USBSTOR#DISK&VEN_KINGSTON&PROD_DATATRAVELER_G2&REV_PMAP#YYYYY&0#{XXXXX} with status 0x0.                
2017-11-09 13:34:38 2003 The UMDF Host Process ({XXXXX}) has been asked to load drivers for device                             
         SWD\WPDBUSENUM\_??_USBSTOR#DISK&VEN_KINGSTON&PROD_DATATRAVELER_G2&REV_PMAP#YYYYY&0#{XXXXX}.                    
2017-11-06 15:18:41 2102 Forwarded a finished Pnp or Power operation (27, 2) to the lower driver for device SWD\WPDBUSENUM\{XXXXX}#0000000000007E00 with status 0x0.            
2017-11-06 15:18:41 2102 Forwarded a finished Pnp or Power operation (27, 23) to the lower driver for device SWD\WPDBUSENUM\{XXXXX}#0000000000007E00 with status 0x0.            
2017-11-06 15:18:13 2003 The UMDF Host Process ({XXXXX}) has been asked to load drivers for device SWD\WPDBUSENUM\{XXXXX}#0000000000007E00.           
+0

システムアカウントで実行していますか?どうやら、 'HKLM \ SYSTEM \ CurrentControlSet \ Enum \ USBSTOR \ \ Properties \'のように深く覗くには 'nt authority \ system'アクセス権が必要です。あなたはあなたの情報をたとえば'RegEdit.exe'? – iRon

+0

@iRon面白いですが、私は管理者ですが、アクセスできません。 – not2qubit

+0

[PSEXEC -i -s -d PowerShell.exe](https://blogs.technet.microsoft.com/askds/2008/10/22/getting-a-cmd-prompt-as-system-in-windows)を試してください。 -vista-and-windows-server-2008 /)を開き、RegEditまたはスクリプトを実行します。 – iRon

答えて

1

これは完全ではありませんが、開始する必要がありますか?

$code = @" 
using System; 
using System.Diagnostics; 
using System.Linq; 
using System.Runtime.InteropServices; 
using Microsoft.Win32; 
using Microsoft.Win32.SafeHandles; 

/// <summary> 
/// Wraps a RegistryKey object and corresponding last write time. 
/// </summary> 
/// <remarks> 
/// .NET doesn't expose the last write time for a registry key 
/// in the RegistryKey class, so P/Invoke is required. 
/// </remarks> 
public class RegistryKeyEx 
{ 
    #region P/Invoke Declarations 
    // This declaration is intended to be used for the last write time only. int is used 
    // instead of more convenient types so that dummy values of 0 reduce verbosity. 
    [DllImport("advapi32.dll", EntryPoint = "RegQueryInfoKey", CallingConvention = CallingConvention.Winapi, SetLastError = true)] 
    extern private static int RegQueryInfoKey(
     SafeRegistryHandle hkey, 
     int lpClass, 
     int lpcbClass, 
     int lpReserved, 
     int lpcSubKeys, 
     int lpcbMaxSubKeyLen, 
     int lpcbMaxClassLen, 
     int lpcValues, 
     int lpcbMaxValueNameLen, 
     int lpcbMaxValueLen, 
     int lpcbSecurityDescriptor, 
     IntPtr lpftLastWriteTime); 
    #endregion 
    #region Public Poperties 
    /// <summary> 
    /// Gets the registry key owned by the info object. 
    /// </summary> 
    public RegistryKey Key { get; private set; } 
    /// <summary> 
    /// Gets the last write time for the corresponding registry key. 
    /// </summary> 
    public DateTime LastWriteTime { get; private set; } 
    #endregion 
    /// <summary> 
    /// Creates and initializes a new RegistryKeyInfo object from the provided RegistryKey object. 
    /// </summary> 
    /// <param name="key">RegistryKey component providing a handle to the key.</param> 
    public RegistryKeyEx(RegistryKey key) 
    { 
     Key = key; 
     SetLastWriteTime(); 
    } 
    /// <summary> 
    /// Creates and initializes a new RegistryKeyInfo object from a registry key path string. 
    /// </summary> 
    /// <param name="parent">Parent key for the key being loaded.</param> 
    /// <param name="keyName">Path to the registry key.</param> 
    public RegistryKeyEx(RegistryKey parent, string keyName) 
     : this(parent.OpenSubKey(keyName)) 
    { } 
    /// <summary> 
    /// Queries the currently set registry key through P/Invoke for the last write time. 
    /// </summary> 
    private void SetLastWriteTime() 
    { 
     Debug.Assert(Key != null, "RegistryKey component must be initialized"); 
     GCHandle pin = new GCHandle(); 
     long lastWriteTime = 0; 
     try 
     { 
      pin = GCHandle.Alloc(lastWriteTime, GCHandleType.Pinned); 
      if (RegQueryInfoKey(Key.Handle, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, pin.AddrOfPinnedObject()) == 0) 
      { 
       LastWriteTime = DateTime.FromFileTime((long)pin.Target); 
      } 
      else 
      { 
       LastWriteTime = DateTime.MinValue; 
      } 
     } 
     finally 
     { 
      if (pin.IsAllocated) 
      { 
       pin.Free(); 
      } 
     } 
    } 
} 
"@ 

$type = Add-Type -TypeDefinition $code -Language CSharp 

$devices = Get-Item HKLM:\SYSTEM\ControlSet001\Enum\USBSTOR\* 

$result = foreach($device in $devices) { 
    Write-Verbose -Verbose "New device: $($device.PSPath)" 

    Write-Verbose -Verbose "GetClass" 
    foreach($classname in $device.GetSubKeyNames()) { 
     $class = $device.OpenSubKey($class) 

     if($class -eq $null) { 
      Write-Verbose -Verbose "Class is null" 
      continue 
     } 

     Write-Verbose -Verbose "GetInstance" 
     foreach($instancename in $class.GetSubKeyNames()) { 
      $instance = $class.OpenSubKey($instancename) 

      if($instance -eq $null) { 
       Write-Verbose -Verbose "Instance is null" 
       continue 
      } 

      Write-Verbose -Verbose "RegistryKeyEx" 
      $keyEx = New-Object RegistryKeyEx $instance 

      [pscustomobject]@{ 
       FriendlyName = $keyEx.key.GetValue('FriendlyName') 
       DevicePath = $device.PSPath 
       LastWriteTime = $keyEx.LastWriteTime 
      } 
     } 
    } 
} 

EDIT:(not2qubitによって)

このスクリプトは、鋭いインラインC#です。あなたは$result変数に見ていない限り

VERBOSE: New device: Microsoft.PowerShell.Core\Registry::HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Enum\USBSTOR\Disk&Ven_Kingston&Prod_DataTraveler_G2&Rev_PMAP 
VERBOSE: GetClass 
VERBOSE: GetInstance 
VERBOSE: RegistryKeyEx 
VERBOSE: New device: Microsoft.PowerShell.Core\Registry::HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Enum\USBSTOR\Disk&Ven_WD&Prod_My_Passport_0730&Rev_1015 
VERBOSE: GetClass 
VERBOSE: Class is null 
VERBOSE: New device: Microsoft.PowerShell.Core\Registry::HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Enum\USBSTOR\Other&Ven_WD&Prod_SES_Device&Rev_1015 
VERBOSE: GetClass 
VERBOSE: GetInstance 
VERBOSE: RegistryKeyEx 

このように欠落しているタイムスタンプ...

編集:現在のバージョンは次の出力を与えます。

PS C:\> $result 

FriendlyName     DevicePath                               LastWriteTime  
------------     ----------                               -------------  
Corsair Survivor 3.0 USB Device Microsoft.PowerShell.Core\Registry::HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Enum\USBSTOR\Disk&Ven_Corsair&Prod_Survivor_3.0&Rev_1.00 2017-11-05 21:08:25 

PS C:\> get-date 

November 11, 2017 17:02:09 

これは、男があなたのC#コードの例で持っているものを提供します。この情報があなたのニーズに十分に正確であるかどうか、私は言うことができません。

+0

私はあなたの答えを落としていませんでしたが、私がすでに投稿したものとはあなたが何をしているかについてもっと知っていただければ幸いです。また、PSをC#と混在させているように見えます。 – not2qubit

+0

あなたが提供したスクリプトはタイムスタンプを与えていません。あなたの答えに出力を加えました。間違っていると、あなたが得たものを表示するように編集してください。 – not2qubit

+1

ああ、私はすべてを '$ result'に入れるという事実を忘れているようだ。 – mtnielsen

関連する問題