用 Powershell 做 Windows 作業系統自動稽核檢查驗證 AutoAudit
使用情境
因應各種資安規範,常常需要針對個人電腦進行檢測,這邊整理了使用 cmd 或 powershell 方式取得電腦所有設定,減少要手動進去看設定的時間,也減少人員操作教學的繁瑣
適用環境
Windows 10, Windows Server 2012R或其他有支援愛Powershell的作業系統
使用方式
- 點擊 windows 開始工具列的放大鏡圖案 輸入 powershell 點擊後開啟應用程式

- 直接複製以下內文全文,貼到 powershell,觀看執行結果
以下是網站憑證專用的稽核項目
時間伺服器 NTP
參考用伺服器
https://www.stdtime.gov.tw/chinese/bulletin/NTP promo.txt
開啟 cmd 使用以下指令觀看時間伺服器
w32tm /query /peers
如果正常會顯示網址,請比對網址是否與稽核要求之時間伺服器相同
更改時間伺服器 NTP
time.windows.com,0x1
https://suntargets.com/windows-設定為ntp-server/
故障排除
如果顯示服務尚未啟動。則先到「服務」中,將 Windows Time 啟動,並將啟動類型設定為「自動(延遲開始)」(沒設定延遲開始,重開機似乎會無法啟動)。
服務的內的位置

cmd取得硬碟總容量
powershell 取得C磁碟目前容量與總容量
取得 Windows 所有使用者帳號
使用 powershell 或 cmd都可以
開啟 powershell 視窗,輸入 Get-LocalUser
可以看到所有帳號
如果要看欄位可以用 select *
如果要看單一使用者,可以用 -name "帳號名稱"
開啟cmd視窗,輸入net user可以看到帳號
輸入 net user > filename.txt 可以將檔案存到filename.txt
取得 Windows 管理者帳號
開啟 powershell 視窗,輸入 net localgroup Administrators 可以看到管理者群組的特權帳號
結果範例如下
取得管理者帳號密碼原則與上次登入時間
取得事件檢視器事件列表
Get-EventLog -List
可以看到事件列表
取得事件檢視器指定類別(特定編號) 事件
這項功能可能要讀取安全性較高的Log(如 Security),需要管理者權限,因此要在開啟powershell前按右鍵,以系統管理者身分執行

以下為取得 4720 建立使用者帳戶的 Log
結果範例如下
取得事件檢視器中隨身碟的存取紀錄
預設沒有,想要有的話,需要先去事件檢視器開啟 追蹤紀錄 位置在 Application and Services Logs > Microsoft > Windows > DriverFrameworks-UserMode > Operational


之後在搜尋相關編號,usb連線有這些
- 2003
- 2004
- 2006
- 2010
- 2100
- 2101
- 2105
- 2106
拔除usb有這些
參考來源:
https://www.techrepublic.com/article/how-to-track-down-usb-flash-drive-usage-in-windows-10s-event-viewer/
取得所有 SQL Server 資料庫可以使用SQL登入的使用者
https://stackoverflow.com/a/18867117/4893973
取得單一 sql 資料庫的使用者帳號
https://dataedo.com/kb/query/sql-server/list-users-in-database
用 Powershell 執行 sql 指令
需要安裝 SQLPS 模組後,才能使用 Powershel 執行 sql 指令 (invoke sql cmd),安裝模組的指令是 Import-Module
但 windows 預設會允許不執行 Import-Module 指令,直接執行的話會看到這樣的錯誤訊息
所以需要先調整指令碼權限,輸入 Get-ExecutionPolicy -list
可以查看目前的權限設定
如果單獨輸入 Get-ExecutionPolicy
,則可以收到 Restricted (受限制的) 的訊息,因此目前無法Import 模組
我們期望的是能夠在本機電腦上執行未簽署的腳本,從網路上或其他使用者取得的腳本需要簽署,可以使用 [以系統管理員身分執行] 選項啟動 PowerShell,然後使用下列命令將電腦上的執行原則變更為 RemoteSigned:
這句指令就是說 將目前的使用者 (CurrentUser) 的腳本執行權限調整成 自己開發的或電腦上已經有的腳本不用數位簽署,但網路上抓來的就需要簽署了
以上請輸入 Y
完成後,可以再次輸入 Get-ExecutionPolicy -list,會看到變成了 CurrentUser RemoteSigned,其他沒有變更,就是完成了
如果稍後安裝完 SQLPS 模組,覺得有風險想要關掉,可以再次輸入指令改成原本的
或是明確告知禁止執行 Restricted
參考文件:about_Signing 關於簽署
受限制的執行原則不允許執行任何腳本。 AllSigned和RemoteSigned執行原則可防止 PowerShell 執行沒有數位簽章的腳本。
https://docs.microsoft.com/zh-tw/powershell/module/microsoft.powershell.core/about/about_signing?view=powershell-7.2
安裝 SQLPS 模組
安裝後不會有其他訊息
模組安裝說明
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 資料庫圖形介面工具直接看,以這邊來說就是伺服器名稱

範例語法如下
我實際執行的如下
收到的回應範例,這樣就能確定指令執行成功了
結合我們其他實務的例子,我們希望直接用 powershell 取得資料庫所有帳號,而不透過圖形工具,可以利用以下語法
執行後的結果如下
https憑證序號
從網頁上方按憑證


取得 https 網站憑證簽發者資訊與憑證起訖日
取得電腦所有安裝的軟體(照名稱排序)
語法較長但速度比較快

取得電腦所有安裝的軟體
開啟 powershell輸入以下指令,可觀看所有安裝的軟體,語法較短但也跑比較久

參考來源
https://www.codetwo.com/admins-blog/how-to-check-installed-software-version/
將 powershell 的結果輸出到純文字文件
先寫上指令,在指令後面加上
=cmd | Out-File -FilePath software.txt
完整範例如下
匯出成 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帳號名稱
參考文件
https://xyz.cinc.biz/2015/04/windows-w32tm.html
取得Windows Update 最近更新資訊
單次允許執行 powershell 的批次檔
powershell -ExecutionPolicy Bypass -File C:\pw\ps.ps1
在工作排程器的設定位置

比較兩個資料夾檔案差異
robocopy C:\fso C:\fso_BackUp /MIR
第一版,缺點是如果來源資料夾有多 or 目的資料夾有少 無法辨識
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
待開發的新需求
檢查 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/
使用方式:先 copy 底下的powershell指令執行,之後再輸入 Check-Header 檔名
例如有一個不知道檔案副檔名的 1.xxx,只要輸入 Check-Header .\1.xxx
,會看到回傳 pdf 的文字訊息
看檔案 header 16進位編碼可參考這個網站 Digital Forensics Magic Numbersnumber
以下為辨識用的powershell
# fixed by not 20230616
# from https:
# http:
# https:
# http:
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 {}
}