如何繞過PowerShell訪問限制並實現PowerShell程式碼執行
- 2019 年 12 月 10 日
- 筆記

如果你是一名專業的滲透測試人員,那你可能真的離不開PowerShell,但是如果目標系統中的某個策略組織我們訪問PowerShel.exe,那我們該怎麼辦呢?沒錯,這個問題經常會困擾我們,而且網上也有很多的應對方法。
在這篇文章中,我將跟大家介紹一種快速且狡猾的繞過技術,這項技術需要利用C#編譯程式碼來執行我們的PowerShell腳本。
首先,我們為什麼不適用powershell.exe來執行我們的.ps1腳本呢?因為PowerShell腳本跟C#一樣,它們兩個對於.NET框架而言,都只是「前端」方面的東西,它們的本質都只是一種程式語言。不過在C#中,我們需要對程式程式碼進行編譯才可以使用和執行,即編譯型語言,這是它和PowerShell這種解釋型腳本語言有很大區別。
鑒於PowerShell.exe只是.NET程式集「system.management.automation」的解釋器,因此它應該可以在C程式中與這個對象進行交互並執行.ps1腳本。
下面給出的就是實例程式碼:
using System.Collections.ObjectModel; using System.Management.Automation; using System.Management.Automation.Runspaces; using System.IO; using System; using System.Text; namespace PSLess { class PSLess { static void Main(string[] args) { if(args.Length ==0) Environment.Exit(1); string script=LoadScript(args[0]); string s=RunScript(script); Console.WriteLine(s); Console.ReadKey(); } private static string LoadScript(string filename) { string buffer =""; try { buffer = File.ReadAllText(filename); } catch (Exception e) { Console.WriteLine(e.Message); Environment.Exit(2); } return buffer; } private static string RunScript(string script) { Runspace MyRunspace = RunspaceFactory.CreateRunspace(); MyRunspace.Open(); Pipeline MyPipeline = MyRunspace.CreatePipeline(); MyPipeline.Commands.AddScript(script); MyPipeline.Commands.Add("Out-String"); Collection<PSObject> outputs = MyPipeline.Invoke(); MyRunspace.Close(); StringBuilder sb = new StringBuilder(); foreach (PSObject pobject in outputs) { sb.AppendLine(pobject.ToString()); } return sb.ToString(); } } }
其中的RunScript()方法會創建一個「runspace」對象,我們可以將其視作是PowerShell運行時的一個獨立實例。接下來,我們需要將腳本添加到新創建的pipeline中,並對通訊信道進行排序,最後通過Invoke()方法執行我們的腳本命令。
最終的結果將會被追加到我們的字元串生成器中,然後作為字元串發回給調用函數,以便顯示在控制台的輸出結果中。這也就是為什麼我們要在命令中添加「Out-String」的原因。
怎麼樣,整個過程很簡單吧?
接下來,我們需要對程式碼進行編譯並完成程式碼測試。
C:WindowsMicrosoft.NETFramework64v4.0.30319csc.exe /reference: C:WindowsMicrosoft.NETassemblyGAC_MSILSystem.Management.Automationv4.0_3.0.0.0__31bf3856ad364e35system.management.automation.dll /out:c:setuppowerless.exe c:scriptspowersless.cs
請記住,具體的執行路徑需要取決於目標系統中所安裝的框架版本。除此之外,別忘了添加對「system.management.automation.dll」程式集的引用。
如果一切正常的話,我們就已經完成了程式碼的編譯。接下來,創建一個簡單地測試腳本:
test.ps1: echo "Hello from powershell-less" echo "PID: $pid"
然後運行該腳本:

沒錯,我們成功了!我們成功地在不直接使用powershell.exe的情況下調用並執行了我們的腳本程式碼。
實際上,這是一個非常簡單的腳本,如果加上用戶輸入等處理機制的話,就會變得比較麻煩和複雜了,但對於大多數需要涉及到PowerShell的滲透活動來說,這應該已經夠了吧。當然了,廣大研究人員也可以根據自己的需要來修改腳本程式碼,以實現自己的需求。
*參考來源:decoder,FB小編Alpha_h4ck編譯,轉載請註明來自FreeBuf.COM