# 用 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: `資安`