繁体   English   中英

如何在以前连接的USB设备上获取时间戳?

[英]How can I get timestamps on previously connected USB devices?

我正在尝试使用旧的PowerShell脚本来显示先前连接的USB设备的时间。 在已经读了几取证博客这样 ,我发现这个剧本这个博客 (杰森沃克的剧本。)

不幸的是,它没有显示有关设备的任何时间戳或任何其他有用的细节。 所以我希望应该有办法实现这一目标 只有我没有看到如何融入这一点。

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代码。)

我该如何使用它来改进脚本?


更新:2017-11-06

按照@ iRon的建议,我尝试直接访问注册表路径: HKLM\\SYSTEM\\CurrentControlSet\\Enum\\USBSTOR\\<drive>\\Propertie‌​s ,使用RegEdit,但后来我得到了一个权限错误,这很奇怪,因为我的用户帐户是管理员。 (这是在Win8.1上)

在此输入图像描述

我发现的其他几个选项是:

  1. 使用Windows内置事件查看器并创建自定义视图。 但是,这需要您启用事件日志。
  2. 类似地,使用带有CMD批处理脚本logparser ,如此此处所示。 (需要启用事件日志。)
  3. 按照这里描述的取证,在那里他们检查各种注册表项和日志文件: ...\\Windows\\inf\\setupapi.dev.log以获得第一个连接日期,但是如何获得最后一个连接更加不清楚。 (据说通过比较\\NTUSER\\<username>\\Software\\Microsoft\\Windows\\Explorer\\MountPoints2数据,但我找不到它。)
  4. 此外,“ Windows注册表取证:Windows注册表的高级数字取证分析 ”一书还提供了一些来自第95页及其后的(3)的其他提示。

一个潜在有用的PS单线程是:

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

这为事件(2003,2102)提供了Message内容的时间戳,可以进一步解析。

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.                                         

这不完整,但应该让你开始?

$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
            }
        }
    }
}

编辑:(通过not2qubit)

这个脚本是内嵌的C#sharp。 当前版本提供以下输出:

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

因此缺少时间戳......

编辑:

除非你研究$result变量。

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#代码示例中的内容。 我不能说这些信息是否足以满足您的需求。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM