# 如何绕过PowerShell访问限制并实现PowerShell代码执行

![](https://image.3001.net/images/20191103/1572780230_5dbeb8c678aeb.jpg!small)

&#x20;**如果你是一名专业的渗透测试人员，那你可能真的离不开PowerShell，但是如果目标系统中的某个策略组织我们访问PowerShel.exe，那我们该怎么办呢？没错，这个问题经常会困扰我们，而且网上也有很多的应对方法。**

&#x20;在这篇文章中，我将跟大家介绍一种快速且狡猾的绕过技术，这项技术需要利用C#编译代码来执行我们的PowerShell脚本。

&#x20;首先，我们为什么不适用powershell.exe来执行我们的.ps1脚本呢？因为PowerShell脚本跟C#一样，它们两个对于.NET框架而言，都只是“前端”方面的东西，它们的本质都只是一种编程语言。不过在C#中，我们需要对程序代码进行编译才可以使用和执行，即编译型语言，这是它和PowerShell这种解释型脚本语言有很大区别。

&#x20;鉴于PowerShell.exe只是.NET程序集“system.management.automation”的解释器，因此它应该可以在C程序中与这个对象进行交互并执行.ps1脚本。

&#x20;**下面给出的就是实例代码：**

```diff
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(); 

      }

     }

    }
```

&#x20;其中的RunScript()方法会创建一个“runspace”对象，我们可以将其视作是PowerShell运行时的一个独立实例。接下来，我们需要将脚本添加到新创建的pipeline中，并对通信信道进行排序，最后通过Invoke()方法执行我们的脚本命令。

&#x20;最终的结果将会被追加到我们的字符串生成器中，然后作为字符串发回给调用函数，以便显示在控制台的输出结果中。这也就是为什么我们要在命令中添加“Out-String”的原因。

&#x20;怎么样，整个过程很简单吧？

&#x20;接下来，我们需要对代码进行编译并完成代码测试。

```
C:\Windows\Microsoft.NET\Framework64\v4.0.30319\csc.exe    /reference:    C:\Windows\Microsoft.NET\assembly\GAC_MSIL\System.Management.Automation\v4.0_3.0.0.0__31bf3856ad364e35\system.management.automation.dll     /out:c:\setup\powerless.exe c:\scripts\powersless.cs
```

&#x20;请记住，具体的执行路径需要取决于目标系统中所安装的框架版本。除此之外，别忘了添加对“system.management.automation.dll”程序集的引用。

&#x20;如果一切正常的话，我们就已经完成了代码的编译。接下来，创建一个简单地测试脚本：

```
test.ps1:    echo "Hello from powershell-less"    echo "PID: $pid"
```

&#x20;**然后运行该脚本：**

![](https://image.3001.net/images/20191103/1572780253_5dbeb8dddb4f9.jpg!small)

&#x20;没错，我们成功了！我们成功地在不直接使用powershell.exe的情况下调用并执行了我们的脚本代码。

&#x20;实际上，这是一个非常简单的脚本，如果加上用户输入等处理机制的话，就会变得比较麻烦和复杂了，但对于大多数需要涉及到PowerShell的渗透活动来说，这应该已经够了吧。当然了，广大研究人员也可以根据自己的需要来修改脚本代码，以实现自己的需求。


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://xu-an.gitbook.io/sec/how/ps/rgce.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
