用于向 C# 项目添加 D/Invoke 和间接系统调用方法的源生成器。
将最新的 NuGet 包添加到你的项目,并允许不安全代码。
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net481</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<LangVersion>12</LangVersion>
</PropertyGroup>
<!-- CsWhispers package -->
<ItemGroup>
<PackageReference Include="CsWhispers" Version="0.0.3" />
</ItemGroup>
<!-- Allow unsafe code -->
<PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
</Project>
在你的项目中创建一个名为 CsWhispers.txt 的文件,并将其生成操作属性设置为 AdditionalFiles。
<ItemGroup>
<None Remove="CsWhispers.txt" />
<AdditionalFiles Include="CsWhispers.txt" />
</ItemGroup>
添加每个要包含在项目中的 NT API 以及任何支持的 struct/enum。每一项必须单独占一行,例如:
NtOpenProcess
HANDLE
NTSTATUS
CLIENT_ID
UNICODE_STRING
OBJECT_ATTRIBUTES
PWSTR
PCWSTR
有关受支持 API 的完整列表,请参阅项目 Wiki。
自动添加全局命名空间,以使代码整洁。
public static unsafe void Main()
{
// use self as example
using var self = Process.GetCurrentProcess();
HANDLE hProcess;
OBJECT_ATTRIBUTES oa;
CLIENT_ID cid = new()
{
UniqueProcess = new HANDLE((IntPtr)self.Id)
};
var status = NtOpenProcess(
&hProcess,
PROCESS_ALL_ACCESS,
&oa,
&cid);
Console.WriteLine("Status: {0}", status.SeverityCode);
Console.WriteLine("HANDLE: 0x{0:X}", hProcess.Value.ToInt64());
}
CsWhispers 包含一个精简版的 D/Invoke,因此你也可以调用 Generic.GetLibraryAddress、Generic.DynamicFunctionInvoke 等。
所有生成的代码都会进入一个分部类 CsWhispers.Syscalls,你可以扩展该类来添加自己的 API。例如,创建 MyAPIs.cs 并添加:
namespace CsWhispers;
public static partial class Syscalls
{
public static NTSTATUS NtCreateThreadEx()
{
// whatever
return new NTSTATUS(0);
}
}
这样就可以在主代码中直接调用,而无需添加任何额外的 using 语句。
namespace ConsoleApp1;
internal static class Program
{
public static void Main()
{
var status = NtCreateThreadEx();
}
}
CsWhispers.txt 中声明它们。本项目尤其受到 SysWhipsers 和 SharpWhispers 早期版本的启发。在此向 @Jackson_T、@KlezVirus、@d_glenx 以及所有贡献代码和/或想法的人致敬。