# 用 Powershell 做 Windows 作業系統自動稽核檢查驗證 AutoAudit ## 使用情境 因應各種資安規範,常常需要針對個人電腦進行檢測,這邊整理了使用 cmd 或 powershell 方式取得電腦所有設定,減少要手動進去看設定的時間,也減少人員操作教學的繁瑣 ## 適用環境 Windows 10, Windows Server 2012R或其他有支援愛Powershell的作業系統 ## 使用方式 1. 點擊 windows 開始工具列的放大鏡圖案 輸入 powershell 點擊後開啟應用程式 ![](https://i.imgur.com/mAfJnqI.png) 2. 直接複製以下內文全文,貼到 powershell,觀看執行結果 ```powershell= function Auto-Audit { ## 取得電腦基本資訊 (電腦名稱、作業系統版本、CPU、記憶體、Bios、硬碟) function Get-ComputerInfo_Custom { $ComputerInfo = Get-ComputerInfo | Select-Object BiosSeralNumber,CsModel,CsName,CsPrimaryOwnerName,CsProcessors,OsName,CsPhyicallyInstalledMemory $PhysicalDisks = Get-PhysicalDisk | Select-Object DeviceId,FriendlyName,Size $ComputerInfoObject = [PSCustomObject]@{ 'Name' = $ComputerInfo.CsName 'OS' = $ComputerInfo.OsName 'Model' = $ComputerInfo.CsModel 'Owner' = $ComputerInfo.CsPrimaryOwnerName 'CPU' = $ComputerInfo.CsProcessors.Name 'RAM' = $ComputerInfo.CsPhyicallyInstalledMemory 'S/N' = $ComputerInfo.BiosSeralNumber } foreach ($Disk in $PhysicalDisks) { $ComputerInfoObject | Add-Member -NotePropertyName "Disk $($Disk.DeviceId)" -NotePropertyValue "$($Disk.FriendlyName), Size: $([int]($Disk.Size/1e9))GB" } $ComputerInfoObject } ## 取得所有磁碟目前容量和總容量 function Get-AllHardDiskSize { $alldisk = Get-WmiObject Win32_LogicalDisk | Select-Object DeviceID, Size, FreeSpace foreach ($disk in $alldisk){ try{ Write-Host ("DeviceID: " + $disk.DeviceID +"/ {0}GB free" -f [math]::truncate($disk.FreeSpace / 1GB) +"/" +"{0}GB total" -f [math]::truncate($disk.Size / 1GB)) } catch{} } } ## 取得管理者帳號與描述 function Get-Administrators { Get-LocalGroupMember -Group "Administrators" } ## 只取管理者帳號名稱 function Get-Administrators-OnlyAccountName{ (net localgroup administrators).where({$_ -match '-{79}'},'skipuntil') -notmatch '-{79}|The command completed' -notmatch '命令已經成功完成。' } ## 取得管理者帳號密碼原則與上次登入時間 function Get-Administrators-PasswordPolicy_LogonTime{ $ng = Get-Administrators-OnlyAccountName foreach ($i in $ng){ net user $i } } ## 取得管理者帳號密碼原則與上次登入時間 function Get-win32_quickfixengineering{ get-wmiobject -class win32_quickfixengineering } function Get-Banner { Write-Host "|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||" Write-Host "\ Auto-Audit 20220624 /" Write-Host " \ 自動稽核工具 20220624 /" Write-Host " \ https://hackmd.io/@Not/autoaudit / " Write-Host " \===========================================================/ " } <#-----------------------------------------------------------[Execution]------------------------------------------------------------#> Get-Banner Write-Host "===================================================================" Write-Host 'AutoAudit自動稽核開始' Write-Host "===================================================================" Write-Host '檢查電腦基本資訊 (電腦名稱、作業系統版本、 CPU、記憶體' Write-Host "===================================================================" Get-ComputerInfo_Custom Write-Host "" Write-Host "===================================================================" Write-Host '取得所有磁碟目前容量和總容量' Write-Host "===================================================================" Get-WmiObject -Class win32_logicaldisk | Format-Table DeviceId, @{n="Size (GB)";e={[math]::Round($_.Size/1GB,2)}},@{n="FreeSpace (GB)";e={[math]::Round($_.FreeSpace/1GB,2)}} Write-Host "" Write-Host "===================================================================" Write-Host '取得 Windows 更新安裝時間' Write-Host "===================================================================" Get-win32_quickfixengineering Write-Host "" Write-Host "===================================================================" Write-Host '取得時間伺服器 NTP 設定' Write-Host '如果顯示服務尚未啟動。則先到「服務」中,將 Windows Time 啟動,並將啟動類型設定為「自動(延遲開始)」(沒設定延遲開始,重開機似乎會無法啟動)' Write-Host "===================================================================" w32tm /query /peers Write-Host "" Write-Host "===================================================================" Write-Host '取得管理者帳號密碼原則與上次登入時間' Write-Host "===================================================================" Get-Administrators-PasswordPolicy_LogonTime Write-Host "" Write-Host "===================================================================" Write-Host '檢查防毒軟體是否保持開啟' Write-Host 'AntivirusEnabled 為防毒軟體啟動狀態,True 為有開啟' Write-Host 'RealTimeProtectionEnabled 為防毒軟體即時掃描保護狀態,True 為有開啟' Write-Host 'AntivirusSignatureLastUpdated 為病毒特徵碼最後更新時間' Write-Host 'AntispywareSignatureVersion 為病毒特徵碼更新版本號碼' Write-Host "===================================================================" Get-MpComputerStatus | Select AntivirusEnabled,RealTimeProtectionEnabled,AntivirusSignatureLastUpdated,AntispywareSignatureVersion Write-Host "" Write-Host "===================================================================" Write-Host '檢查螢幕保護程式設定狀態' Write-Host 'ScreenSaverActive 為有設定閒置後須開啟螢幕保護程式, True 為有開啟' Write-Host 'ScreenSaverSecure 為解除螢幕鎖定後需要輸入密碼, True 為有開啟' Write-Host 'ScreenSaverTimeout 為閒置多少秒數會進入螢幕保護程式' Write-Host "===================================================================" Get-CimInstance win32_desktop Write-Host "" Write-Host "===================================================================" Write-Host '取得目前電腦 IP 與 IPv4 Gateway IP,檢查目前使用的網路名稱' Write-Host "===================================================================" Write-Host "電腦IP:" Get-NetIPAddress -AddressFamily IPv4 -InterfaceIndex (Get-NetConnectionProfile | Select -expand InterfaceIndex) | Select -expand IPAddress Write-Host "IPv4 Gateway IP:" Get-NetIPConfiguration | Foreach IPv4DefaultGateway | Select -expand NextHop Get-NetConnectionProfile | Select Name,NetworkCategory,IPv4Connectivity,IPv6Connectivity Write-Host "" Write-Host "===================================================================" Write-Host '檢查 Windows 防火牆設定' Write-Host 'NotifyOnListen 為 主動通知有服務(程式)嘗試連線, True 每當程序或服務開始偵聽入站連接時,Windows 都會通知用戶' Write-Host "===================================================================" Get-NetFirewallProfile(Get-NetConnectionProfile | Select -expand NetworkCategory) | Select Name,Profile,Enabled,LogFileName,NotifyOnListen Write-Host "" Write-Host 'AutoAudit Finish 自動稽核完成' } Auto-Audit ``` --- ## 以下是網站憑證專用的稽核項目 ```=script function Auto-Audit { ## 取得 https 網站憑證簽發者資訊與憑證起訖日 function GetWebsiteCertificateInfo{ $url = "https://www.microsoft.com/:443" $WebRequest = [Net.WebRequest]::CreateHttp($url) $WebRequest.AllowAutoRedirect = $true $chain = New-Object -TypeName System.Security.Cryptography.X509Certificates.X509Chain #Request website try {$Response = $WebRequest.GetResponse()} catch {} #Creates Certificate $Certificate = $WebRequest.ServicePoint.Certificate.Handle $Issuer = $WebRequest.ServicePoint.Certificate.Issuer $Subject = $WebRequest.ServicePoint.Certificate.Subject $EffectiveDate = $WebRequest.ServicePoint.Certificate.GetEffectiveDateString() $ExpirationDate = $WebRequest.ServicePoint.Certificate.GetExpirationDateString() ### Build chain $chain.Build($Certificate) write-host "憑證串鍊數量" $chain.ChainElements.Count #This returns "1" meaning none of the CA certs are included. write-host "憑證網站名稱" $Subject write-host "憑證簽發者" $chain.ChainElements.Certificate.Issuer write-host "憑證啟用日" $EffectiveDate write-host "憑證失效日" $ExpirationDate } <#-----------------------------------------------------------[Execution]------------------------------------------------------------#> Write-Host '取得網站憑證資訊與憑證串鍊' Write-Host "===================================================================" GetWebsiteCertificateInfo Write-Host "" Write-Host "===================================================================" } Auto-Audit ``` --- ## 時間伺服器 NTP 參考用伺服器 https://www.stdtime.gov.tw/chinese/bulletin/NTP%20promo.txt 開啟 cmd 使用以下指令觀看時間伺服器 ```w32tm /query /peers``` 如果正常會顯示網址,請比對網址是否與稽核要求之時間伺服器相同 ``` 對等: time.stdtime.gov.tw,0x9 ``` ### 更改時間伺服器 NTP time.windows.com,0x1 https://suntargets.com/windows-%E8%A8%AD%E5%AE%9A%E7%82%BAntp-server/ ### 故障排除 如果顯示服務尚未啟動。則先到「服務」中,將 Windows Time 啟動,並將啟動類型設定為「自動(延遲開始)」(沒設定延遲開始,重開機似乎會無法啟動)。 ``` C:\Windows\system32>w32tm /query /peers 發生下列錯誤: 服務尚未啟動。 (0x80070426) ``` 服務的內的位置 ![](https://i.imgur.com/BaRWvIJ.png) ## cmd取得硬碟總容量 ``` for /f "tokens=1-3" %a in ('WMIC LOGICALDISK GET FreeSpace^,Name^,Size ^|FINDSTR /I /V "Name"') do @echo wsh.echo "%b" ^& " free=" ^& FormatNumber^(cdbl^(%a^)/1024/1024/1024, 2^)^& " GiB"^& " size=" ^& FormatNumber^(cdbl^(%c^)/1024/1024/1024, 2^)^& " GiB" > %temp%\tmp.vbs & @if not "%c"=="" @echo( & @cscript //nologo %temp%\tmp.vbs & del %temp%\tmp.vbs ``` ## powershell 取得C磁碟目前容量與總容量 ``` $disk = Get-WmiObject Win32_LogicalDisk -Filter "DeviceID='C:'" | Select-Object Size, FreeSpace Write-Host ("{0}GB free" -f [math]::truncate($disk.FreeSpace / 1GB) +"/" +"{0}GB total" -f [math]::truncate($disk.Size / 1GB)) ``` ## 取得 Windows 所有使用者帳號 使用 powershell 或 cmd都可以 開啟 powershell 視窗,輸入 ```Get-LocalUser``` 可以看到所有帳號 ``` PS C:\Users\User1\Desktop> Get-LocalUser Name Enabled Description ---- ------- ----------- Administrator False 管理電腦/網域的內建帳戶 DefaultAccount False 由系統管理的使用者帳戶。 Guest True 供來賓存取電腦/網域之用的內建帳戶 User1 True WDAGUtilityAccount False 系統針對 Windows Defender 應用程式防護案例所管理及使用的使用者帳戶。 ``` 如果要看欄位可以用 select * ``` get-localuser | select * ``` 如果要看單一使用者,可以用 -name "帳號名稱" ``` get-localuser -name "administrator" | select * ``` 開啟cmd視窗,輸入net user可以看到帳號 輸入 net user > filename.txt 可以將檔案存到filename.txt ```=cmd C:\Windows\System32>net user \\DESKTOP-User1 的使用者帳戶 ------------------------------------------------------------------------------- Administrator DefaultAccount Guest User1 WDAGUtilityAccount 命令已經成功完成。 ``` ## 取得 Windows 管理者帳號 開啟 powershell 視窗,輸入 net localgroup Administrators 可以看到管理者群組的特權帳號 ```=cmd net localgroup Administrators ``` 結果範例如下 ``` PS C:\Users\User1> net localgroup Administrators 別名 Administrators 註解 Administrators 可以完全不受限制地存取電腦/網域 成員 ------------------------------------------------------------------------------- Administrator User1 命令已經成功完成。 ``` ## 取得管理者帳號密碼原則與上次登入時間 ```=cmd $ng = (net localgroup administrators).where({$_ -match '-{79}'},'skipuntil') -notmatch '-{79}|The command completed' -notmatch '命令已經成功完成。' foreach ($i in $ng){ net user $i } ``` ## 取得事件檢視器事件列表 ```Get-EventLog -List``` 可以看到事件列表 ``` PS C:\WINDOWS\system32> Get-EventLog -List Max(K) Retain OverflowAction Entries Log ------ ------ -------------- ------- --- 20,480 0 OverwriteAsNeeded 16,936 Application 3,906 0 OverwriteAsNeeded 0 Cisco AnyConnect Secure Mobility Client 20,480 0 OverwriteAsNeeded 0 HardwareEvents 512 7 OverwriteOlder 0 Internet Explorer 20,480 0 OverwriteAsNeeded 0 Key Management Service 128 0 OverwriteAsNeeded 59 OAlerts 20,480 0 OverwriteAsNeeded 30,156 Security 8,192 0 OverwriteAsNeeded 525 Symantec Endpoint Protection Client 20,480 0 OverwriteAsNeeded 20,104 System 15,360 0 OverwriteAsNeeded 358 Windows PowerShell ``` ## 取得事件檢視器指定類別(特定編號) 事件 這項功能可能要讀取安全性較高的Log(如 Security),需要管理者權限,因此要在開啟powershell前按右鍵,以系統管理者身分執行 ![](https://i.imgur.com/fQPYCjS.png) 以下為取得 4720 建立使用者帳戶的 Log ```=script Get-EventLog -LogName Security -InstanceID 4720 ``` 結果範例如下 ``` Index Time EntryType Source InstanceID Message ----- ---- --------- ------ ---------- ------- 132626 十月 25 11:33 SuccessA... Microsoft-Windows... 4720 已建立使用者帳戶。... ``` ``` Get-EventLog -LogName Security | ?{$_.InstanceID -eq 4720 -or $_.InstanceID -eq 4624} ``` ## 取得事件檢視器中隨身碟的存取紀錄 預設沒有,想要有的話,需要先去事件檢視器開啟 追蹤紀錄 位置在 Application and Services Logs > Microsoft > Windows > DriverFrameworks-UserMode > Operational ![](https://i.imgur.com/iulJkwA.png) ![](https://i.imgur.com/s9o3jF2.png) 之後在搜尋相關編號,usb連線有這些 * 2003 * 2004 * 2006 * 2010 * 2100 * 2101 * 2105 * 2106 拔除usb有這些 * 2100 * 2102 參考來源: https://www.techrepublic.com/article/how-to-track-down-usb-flash-drive-usage-in-windows-10s-event-viewer/ ## 取得所有 SQL Server 資料庫可以使用SQL登入的使用者 ```=sql select * from master.sys.server_principals where type_desc= 'SQL_LOGIN' and is_disabled = 0 ``` https://stackoverflow.com/a/18867117/4893973 ## 取得單一 sql 資料庫的使用者帳號 ``` use [DatabaseName] select name as username, create_date, modify_date, type_desc as type, authentication_type_desc as authentication_type from sys.database_principals where type not in ('A', 'G', 'R', 'X') and sid is not null and name != 'guest' and name != 'dbo' order by username; ``` https://dataedo.com/kb/query/sql-server/list-users-in-database ## 用 Powershell 執行 sql 指令 需要安裝 SQLPS 模組後,才能使用 Powershel 執行 sql 指令 (invoke sql cmd),安裝模組的指令是 ``` Import-Module``` 但 windows 預設會允許不執行 Import-Module 指令,直接執行的話會看到這樣的錯誤訊息 ```=script PS C:\Windows\System32\WindowsPowerShell\v1.0> Import-Module SQLPS Import-Module : 因為這個系統上已停用指令碼執行,所以無法載入 C:\Program Files (x86)\Microsoft SQL Server\150\Tools\Powe rShell\Modules\SQLPS\SqlPsPostScript.ps1 檔案。如需詳細資訊,請參閱 about_Execution_Policies,網址為 https:/go.microsof t.com/fwlink/?LinkID=135170。 位於 線路:1 字元:1 + Import-Module SQLPS + ~~~~~~~~~~~~~~~~~~~ + CategoryInfo : SecurityError: (:) [Import-Module], PSSecurityException + FullyQualifiedErrorId : UnauthorizedAccess,Microsoft.PowerShell.Commands.ImportModuleCommand + ``` 所以需要先調整指令碼權限,輸入 ```Get-ExecutionPolicy -list``` 可以查看目前的權限設定 ``` Scope ExecutionPolicy ----- --------------- MachinePolicy Undefined UserPolicy Undefined Process Undefined CurrentUser Undefined LocalMachine Undefined ``` 如果單獨輸入 ```Get-ExecutionPolicy```,則可以收到 Restricted (受限制的) 的訊息,因此目前無法Import 模組 我們期望的是能夠在本機電腦上執行未簽署的腳本,從網路上或其他使用者取得的腳本需要簽署,可以使用 [以系統管理員身分執行] 選項啟動 PowerShell,然後使用下列命令將電腦上的執行原則變更為 RemoteSigned: ``` Set-ExecutionPolicy RemoteSigned -Scope CurrentUser ``` 這句指令就是說 將目前的使用者 (CurrentUser) 的腳本執行權限調整成 **自己開發的或電腦上已經有的腳本不用數位簽署,但網路上抓來的就需要簽署了** ``` Set-ExecutionPolicy RemoteSigned -Scope CurrentUser 執行原則變更 執行原則有助於防範您不信任的指令碼。如果變更執行原則,可能會使您接觸到 about_Execution_Policies 說明主題 (網址為 https:/go.microsoft.com/fwlink/?LinkID=135170) 中所述的安全性風險。您要變更執行原則嗎? [Y] 是(Y) [A] 全部皆是(A) [N] 否(N) [L] 全部皆否(L) [S] 暫停(S) [?] 說明 (預設值為 "N"): ``` > 以上請輸入 Y 完成後,可以再次輸入 Get-ExecutionPolicy -list,會看到變成了 CurrentUser RemoteSigned,其他沒有變更,就是完成了 ``` Scope ExecutionPolicy ----- --------------- MachinePolicy Undefined UserPolicy Undefined Process Undefined CurrentUser RemoteSigned LocalMachine Undefined ``` 如果稍後安裝完 SQLPS 模組,覺得有風險想要關掉,可以再次輸入指令改成原本的 ```script= Set-ExecutionPolicy Undefined -Scope CurrentUser ``` 或是明確告知禁止執行 Restricted ```script= Set-ExecutionPolicy Restricted -Scope CurrentUser ``` 參考文件:about_Signing 關於簽署 受限制的執行原則不允許執行任何腳本。 AllSigned和RemoteSigned執行原則可防止 PowerShell 執行沒有數位簽章的腳本。 https://docs.microsoft.com/zh-tw/powershell/module/microsoft.powershell.core/about/about_signing?view=powershell-7.2 安裝 SQLPS 模組 ```sql= Import-Module SQLPS ``` 安裝後不會有其他訊息 ```script= PS C:\Windows\System32\WindowsPowerShell\v1.0> Import-Module SQLPS PS C:\Windows\System32\WindowsPowerShell\v1.0> ``` 模組安裝說明 https://www.powershellgallery.com/packages/Sqlserver/21.1.18256 官方文件 https://docs.microsoft.com/zh-tw/sql/powershell/download-sql-server-ps-module?view=sql-server-ver16 檢測是否能用 powershell 對 sql server 資料庫 執行 sql 語法 這邊使用 windows 驗證,所以無需另外登入,只要把資料庫連線路徑改成自己的即可,路徑可以透過成功連線過的 sql server 資料庫圖形介面工具直接看,以這邊來說就是伺服器名稱 ![](https://i.imgur.com/6rYbUlY.png) 範例語法如下 ```sql= Invoke-Sqlcmd -Query "SELECT GETDATE() AS TimeOfQuery" -ServerInstance "ServerIP\DBServerInstance" ``` 我實際執行的如下 ```sql= Invoke-Sqlcmd -Query "SELECT GETDATE() AS TimeOfQuery" -ServerInstance "localhost\sqlexpress" ``` 收到的回應範例,這樣就能確定指令執行成功了 ```script= PS C:\Windows\System32\WindowsPowerShell\v1.0> Invoke-Sqlcmd -Query "SELECT GETDATE() AS TimeOfQuery" -ServerInstance "localhost\sqlexpress" TimeOfQuery ----------- 2022/8/19 下午 08:48:36 ``` 結合我們其他實務的例子,我們希望直接用 powershell 取得資料庫所有帳號,而不透過圖形工具,可以利用以下語法 ```sql= Invoke-Sqlcmd -Query "select * from master.sys.server_principals where type_desc= 'SQL_LOGIN' and is_disabled = 0" -ServerInstance "localhost\sqlexpress" ``` 執行後的結果如下 ``` PS C:\Windows\System32\WindowsPowerShell\v1.0> Invoke-Sqlcmd -Query "select * from master.sys.server_principals where type_desc= 'SQL_LOGIN' and is_disabled = 0" -ServerInstance "localhost\sqlexpress" name : MyDataBaseManagerAccount principal_id : 266 sid : {55, 67, 221, 248...} type : S type_desc : SQL_LOGIN is_disabled : False create_date : 2021/6/19 下午 07:59:55 modify_date : 2022/7/17 下午 02:20:02 default_database_name : master default_language_name : 繁體中文 credential_id : owning_principal_id : is_fixed_role : False ``` ## https憑證序號 從網頁上方按憑證 ![](https://i.imgur.com/HozwjeK.png) ![](https://i.imgur.com/wqKYzDX.png) ## 取得 https 網站憑證簽發者資訊與憑證起訖日 ```=cmd $url = "https://www.microsoft.com/:443" $WebRequest = [Net.WebRequest]::CreateHttp($url) $WebRequest.AllowAutoRedirect = $true $chain = New-Object -TypeName System.Security.Cryptography.X509Certificates.X509Chain #Request website try {$Response = $WebRequest.GetResponse()} catch {} #Creates Certificate $Certificate = $WebRequest.ServicePoint.Certificate.Handle $Issuer = $WebRequest.ServicePoint.Certificate.Issuer $Subject = $WebRequest.ServicePoint.Certificate.Subject $EffectiveDate = $WebRequest.ServicePoint.Certificate.GetEffectiveDateString() $ExpirationDate = $WebRequest.ServicePoint.Certificate.GetExpirationDateString() ### Build chain $chain.Build($Certificate) write-host "憑證串鍊數量" $chain.ChainElements.Count #This returns "1" meaning none of the CA certs are included. write-host "憑證網站名稱" $Subject write-host "憑證簽發者" $chain.ChainElements.Certificate.Issuer write-host "憑證啟用日" $EffectiveDate write-host "憑證失效日" $ExpirationDate ``` ## 取得電腦所有安裝的軟體(照名稱排序) 語法較長但速度比較快 ```=cmd $registry_paths = 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall', 'HKLM:\Software\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall' Write-Verbose "Reading installed software from registry." @( foreach ($registry_path in $registry_paths) { $subkeys = Get-ChildItem -Path $registry_path -ErrorAction SilentlyContinue if ($subkeys) { ForEach ($key in $subkeys) { $DisplayName = $key.getValue('DisplayName') if ($null -notlike $DisplayName) { $DisplayVersion = $key.GetValue('DisplayVersion') [PSCustomObject]@{ PSTypeName = 'System.Software.Inventory' DisplayName = $DisplayName.Trim() DisplayVersion = $DisplayVersion NameVersionPair = $DisplayName.Trim() + $DisplayVersion } } } } } ) | Sort-Object NameVersionPair -Unique ``` ![](https://i.imgur.com/Dr1wNEB.png) ## 取得電腦所有安裝的軟體 開啟 powershell輸入以下指令,可觀看所有安裝的軟體,語法較短但也跑比較久 ```=cmd Get-WmiObject -Class Win32_Product ``` ```=cmd Get-WmiObject -Class Win32_Product | select Name, Version ``` ![](https://i.imgur.com/UATBMGo.png) 參考來源 https://www.codetwo.com/admins-blog/how-to-check-installed-software-version/ ## 將 powershell 的結果輸出到純文字文件 先寫上指令,在指令後面加上 ```=cmd | Out-File -FilePath software.txt``` 完整範例如下 ```=cmd Get-WmiObject -Class Win32_Product | Out-File -FilePath software.txt ``` 匯出成 csv的範例 ```=cmd Get-WmiObject Win32_Product | Sort-Object Name | Select Name,version,Vendor |export-csv myprogramlist.csv ``` 參考來源 https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.utility/out-file?view=powershell-7.1 ## 檢查電腦狀態 Get-MpComputerStatus ## 檢查防毒軟體是否正常運作 Get-MpComputerStatus | Select AntivirusEnabled,RealTimeProtectionEnabled,AntivirusSignatureLastUpdated,AntispywareSignatureVersion ## 查詢使用者上次密碼變更情形及上次登入時間 net user Myaccount帳號名稱 ``` C:\Users\帳號> net user Myaccount帳號名稱 使用者名稱 Myaccount帳號名稱 全名 註解 使用者的註解 國家/區域碼 000 (系統預設值) 帳戶使用中 Yes 帳戶到期 從不 上次設定密碼 2016/11/16 下午 05:31:13 密碼到期 從不 可變更密碼 2016/11/16 下午 05:31:13 請輸入密碼 No 使用者可以變更密碼 Yes 容許的工作站 全部 登入指令檔 使用者設定檔 主目錄 上次登入時間 2021/10/21 下午 03:54:18 可容許的登入時數 全部 本機群組會員 *Administrators *Remote Desktop Users *Users 全域群組會員 *None 命令已經成功完成。 ``` ## 參考文件 https://xyz.cinc.biz/2015/04/windows-w32tm.html --- ## 取得Windows Update 最近更新資訊 ```cmd= ## Convert Wua History ResultCode to a Name # 0, and 5 are not used for history # See https://msdn.microsoft.com/en-us/library/windows/desktop/aa387095(v=vs.85).aspx function Convert-WuaResultCodeToName { param( [Parameter(Mandatory=$true)] [int] $ResultCode ) $Result = $ResultCode switch($ResultCode) { 2{$Result = "Succeeded"} 3{$Result = "Succeeded With Errors"} 4{$Result = "Failed"} } return $Result } function Get-WuaHistory { # Get a WUA Session $session = (New-Object -ComObject 'Microsoft.Update.Session') # Query the latest 1000 History starting with the first recordp $history = $session.QueryHistory("",0,50) | ForEach-Object { $Result = Convert-WuaResultCodeToName -ResultCode $_.ResultCode # Make the properties hidden in com properties visible. $_ | Add-Member -MemberType NoteProperty -Value $Result -Name Result $Product = $_.Categories | Where-Object {$_.Type -eq 'Product'} | Select-Object -First 1 -ExpandProperty Name $_ | Add-Member -MemberType NoteProperty -Value $_.UpdateIdentity.UpdateId -Name UpdateId $_ | Add-Member -MemberType NoteProperty -Value $_.UpdateIdentity.RevisionNumber -Name RevisionNumber $_ | Add-Member -MemberType NoteProperty -Value $Product -Name Product -PassThru Write-Output $_ } #Remove null records and only return the fields we want $history | Where-Object {![String]::IsNullOrWhiteSpace($_.title)} | Select-Object Result, Date, Title, SupportUrl, Product, UpdateId, RevisionNumber } Get-WuaHistory | Format-Table ``` --- ## 單次允許執行 powershell 的批次檔 powershell -ExecutionPolicy Bypass -File C:\pw\ps.ps1 ### 在工作排程器的設定位置 ![](https://i.imgur.com/da7CDee.png) ## 比較兩個資料夾檔案差異 robocopy C:\fso C:\fso_BackUp /MIR 第一版,缺點是如果來源資料夾有多 or 目的資料夾有少 無法辨識 ``` $SourceDocs = Get-ChildItem -Path C:\fso | foreach {Get-FileHash -Path $_.FullName} $DestDocs = Get-ChildItem -Path C:\fso_BackUp | foreach {Get-FileHash -Path $_.FullName} $LogPath = ("C:\pw\log.txt") Get-Date | Add-Content $LogPath (Compare-Object -ReferenceObject $SourceDocs -DifferenceObject $DestDocs -Property hash -PassThru).Path | Add-Content -encoding utf8 -Path $LogPath "---------End-----------------" | Add-Content C:\pw\log.txt ``` --- How To Compare the Contents of Two Folders with PowerShell https://mcpmag.com/articles/2016/04/14/contents-of-two-folders-with-powershell.aspx 附加文字 How to Append Data to a Text File Using PowerShell https://www.faqforge.com/powershell/append-data-text-file-using-powershell/ 寫入檔案(覆蓋) Out-File Module:Microsoft.PowerShell.Utility https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.utility/out-file?view=powershell-7.1 ## 查詢這台電腦目前有哪些使用者登入 ```quser``` ``` PS C:\Users\Not> quser 使用者名稱 工作階段名稱 識別碼 狀態 閒置時間 登入時間 >Not console 1 使用中 無 2022/8/18 下午 03:09 ``` ## 待開發的新需求 檢查 iis session timeout 以及自動設定 https://serverfault.com/questions/829320/set-iis-website-classic-asp-session-timeout-using-powershell 檢查 windows 事件檢視器 容量、保存多久、超過是覆蓋還是封存 https://www.thelazyitadmin.com/archive-windows-security-event-log/ ## 利用檔案檔頭 file header 查詢檔案格式 使用方式:先 copy 底下的powershell指令執行,之後再輸入 ``` Check-Header 檔名``` 例如有一個不知道檔案副檔名的 1.xxx,只要輸入 ``` Check-Header .\1.xxx```,會看到回傳 pdf 的文字訊息 看檔案 header 16進位編碼可參考這個網站 [Digital Forensics Magic Numbersnumber](https://asecuritysite.com/forensics/magic) 以下為辨識用的powershell ```=ps # fixed by not 20230616 # from https://github.com/gangstanthony/PowerShell/blob/master/Check-Header.ps1 # http://learningpcs.blogspot.com/2012/07/powershell-v3-check-file-headers.html # https://en.wikipedia.org/wiki/List_of_file_signatures # http://www.garykessler.net/library/file_sigs.html function Check-Header { param ( $path ) $path = Resolve-Path $path # Hexidecimal signatures for expected files $known = @' "Extension","Header" "3gp","66 74 79 70 33 67" "7z","37 7A BC AF 27 1C" "8sv","38 53 56 58" "8svx","46 4F 52 4D nn nn nn nn" "acbm","46 4F 52 4D nn nn nn nn" "aif","41 49 46 46" "aiff","46 4F 52 4D nn nn nn nn" "anbm","46 4F 52 4D nn nn nn nn" "anim","46 4F 52 4D nn nn nn nn " "asf","30 26 B2 75 8E 66 CF 11" "avi","52 49 46 46 nn nn nn nn " "bac","42 41 43 4B 4D 49 4B 45" "bpg","42 50 47 FB" "cab","4D 53 43 46" "cin","80 2A 5F D7" "class","CA FE BA BE" "cmus","46 4F 52 4D nn nn nn nn" "cr2","49 49 2A 00 10 00 00 00" "crx","43 72 32 34" "cwk","05 07 00 00 42 4F 42 4F" "cwk","06 07 E1 00 42 4F 42 4F" "dat","50 4D 4F 43 43 4D 4F 43" "DBA","BE BA FE CA" "DBA","00 01 42 44" "dex","64 65 78 0A 30 33 35 00" "djvu","41 54 26 54 46 4F 52 4D nn nn nn nn 44 4A 56" "dmg","78 01 73 0D 62 62 60" "doc","D0 CF 11 E0 A1 B1 1A E1" "dpx","53 44 50 58" "exr","76 2F 31 01" "fax","46 41 58 58" "faxx","46 4F 52 4D nn nn nn nn" "fh8","41 47 44 33" "fits","53 49 4D 50 4C 45 20 20" "flac","66 4C 61 43" "flif","46 4C 49 46" "ftxt","46 4F 52 4D nn nn nn nn" "gif","47 49 46 38 37 61" "ico","00 00 01 00" "idx","49 4E 44 58" "iff","41 43 42 4D" "iff","41 4E 42 4D" "iff","41 4E 49 4D" "iff","46 4F 52 4D nn nn nn nn" "ilbm","46 4F 52 4D nn nn nn nn" "iso","43 44 30 30 31" "jpg","FF D8 FF DB" "lbm","49 4C 42 4D" "lz","4C 5A 49 50" "lz4","04 22 4D 18" "mid","4D 54 68 64" "mkv","1A 45 DF A3" "MLV","4D 4C 56 49" "mus","43 4D 55 53" "nes","4E 45 53 1A" "ods","50 4B 05 06" "ogg","4F 67 67 53" "PDB","00 00 00 00 00 00 00 00" "pdf","25 50 44 46" "png","89 50 4E 47 0D 0A 1A 0A" "ps","25 21 50 53" "psd","38 42 50 53" "rar","52 61 72 21 1A 07 00" "rar","52 61 72 21 1A 07 01 00" "smu","53 4D 55 53" "smus","46 4F 52 4D nn nn nn nn" "stg","4D 49 4C 20" "tar","75 73 74 61 72 00 30 30" "TDA","00 01 44 54" "tif","49 49 2A 00" "toast","45 52 02 00 00 00" "tox","74 6F 78 33" "txt","46 54 58 54" "vsdx","50 4B 07 08" "wav","52 49 46 46 nn nn nn nn" "wma","A6 D9 00 AA 00 62 CE 6C" "xar","78 61 72 21" "yuv","59 55 56 4E" "yuvn","46 4F 52 4D nn nn nn nn" "zip","50 4B 03 04" '@ | ConvertFrom-Csv | sort {$_.header.length} -Descending $known | % {$_.header = $_.header -replace '\s'} try { # Get content of each file (up to 4 bytes) for analysis $HeaderAsHexString = New-Object System.Text.StringBuilder [Byte[]](Get-Content -Path $path -TotalCount 4 -Encoding Byte -ea Stop) | % { if (("{0:X}" -f $_).length -eq 1) { $null = $HeaderAsHexString.Append('0{0:X}' -f $_) } else { $null = $HeaderAsHexString.Append('{0:X}' -f $_) } } # Validate file header # might change .startswith() to -match. # might remove 'select -f 1' to get all possible matching extensions, or just somehow make it a better match. $known | ? {$_.header.startswith($HeaderAsHexString.ToString())} | select -f 1 | % {$_.extension} } catch {} } ``` ###### tags: `資安`