c# - 在 C# 中使用 ObRegisterCallbacks
问题描述
因此,我尝试使用 C# 和ObRegisterCallbacks函数来获取有关对OpenProcess
.
这是我到目前为止的代码:
internal static class Win32SelfProtection
{
[DllImport("NtosKrnl.exe", SetLastError = true, PreserveSig = false)]
private static extern uint ObRegisterCallbacks(IntPtr callbackRegistration, out IntPtr registrationHandle);
[DllImport("NtosKrnl.exe", SetLastError = true, PreserveSig = false)]
private static extern void ObUnRegisterCallbacks(IntPtr registrationHandle);
[DllImport("kernel32.dll")]
internal static extern bool VirtualProtect(IntPtr lpAddress, uint dwSize, uint flNewProtect, out uint lpflOldProtect);
private const uint OB_OPERATION_HANDLE_CREATE = 0x00000001;
private const uint OB_OPERATION_HANDLE_DUPLICATE = 0x00000002;
private const uint PAGE_READWRITE = 0x04;
[StructLayout(LayoutKind.Sequential)]
internal struct OB_CALLBACK_REGISTRATION
{
internal ushort Version;
internal ushort OperationRegistrationCount; // 1
internal IntPtr Altitude;
internal IntPtr RegistrationContext; // NULL, probably
internal IntPtr OperationRegistration; // OB_OPERATION_REGISTRATION*
}
[StructLayout(LayoutKind.Sequential)]
internal struct OB_OPERATION_REGISTRATION
{
internal IntPtr ObjectType; // PsProcessType
internal uint Operations; // OB_OPERATION_HANDLE_CREATE
internal IntPtr PreOperation; // POB_PRE_OPERATION_CALLBACK
internal IntPtr PostOperation; // POB_POST_OPERATION_CALLBACK
}
[StructLayout(LayoutKind.Sequential)]
internal unsafe struct UNICODE_STRING
{
internal ushort Length;
internal ushort MaximumLength;
internal IntPtr Buffer;
}
internal static unsafe void Protect()
{
PobPreOperationCallback preOperationCallback = PreOperationCallback;
IntPtr pPreOperationCallback = Marshal.GetFunctionPointerForDelegate(preOperationCallback);
PobPostOperationCallback postOperationCallback = PostOperationCallback;
IntPtr pPostOperationCallback = Marshal.GetFunctionPointerForDelegate(postOperationCallback);
OB_OPERATION_REGISTRATION operationRegistration = new OB_OPERATION_REGISTRATION
{
ObjectType = IntPtr.Zero, // I have no idea ... <-- Need pointer to PsProcessType
Operations = OB_OPERATION_HANDLE_CREATE,
PreOperation = pPreOperationCallback,
PostOperation = pPostOperationCallback
};
IntPtr pOperationRegistration = Marshal.AllocHGlobal(sizeof(OB_OPERATION_REGISTRATION));
Marshal.StructureToPtr(operationRegistration, pOperationRegistration, false);
const ushort buffersize = sizeof(ushort) * 64;
IntPtr buffer = Marshal.AllocHGlobal(buffersize);
// No idea what kind of string I should put in here :C just zero it for now ...
Marshal.Copy(new byte[buffersize], 0, buffer, buffersize);
UNICODE_STRING unicodeString = new UNICODE_STRING
{
Length = buffersize,
MaximumLength = buffersize,
Buffer = buffer
};
IntPtr pUnicodeString = Marshal.AllocHGlobal(sizeof(UNICODE_STRING));
Marshal.StructureToPtr(unicodeString, pUnicodeString, false);
OB_CALLBACK_REGISTRATION callbackRegistration = new OB_CALLBACK_REGISTRATION
{
Version = 0x0100,
OperationRegistrationCount = 1,
Altitude = pUnicodeString,
RegistrationContext = IntPtr.Zero,
OperationRegistration = pOperationRegistration
};
IntPtr pCallbackRegistration = Marshal.AllocHGlobal(sizeof(OB_CALLBACK_REGISTRATION));
Marshal.StructureToPtr(callbackRegistration, pCallbackRegistration, false);
uint status = ObRegisterCallbacks(pCallbackRegistration, out IntPtr hRegistration); // FAILS WITH: AccessViolationException
// yeah, yeah I'll remember to call Marshal.FreeHGlobal() later ... :D
}
public delegate uint PobPreOperationCallback(IntPtr registrationContext, IntPtr operationInformation);
// dummy method for now
internal static uint PreOperationCallback(IntPtr registrationContext, IntPtr operationInformation)
{
Console.WriteLine("PreOperationCallback!");
return 0x0;
}
public delegate void PobPostOperationCallback(IntPtr registrationContext, IntPtr operationInformation);
// dummy method for now
internal static void PostOperationCallback(IntPtr registrationContext, IntPtr operationInformation)
{
Console.WriteLine("PostOperationCallback!");
}
}
该ObRegisterCallbacks
函数将OB_CALLBACK_REGISTRATION
结构(此处的文档)作为参数,该结构本身由结构数组OB_OPERATION_REGISTRATION
(此处的文档)组成。
这就是我卡住的地方: 的OB_OPERATION_REGISTRATION
第一个成员“ObjectType”记录如下
ObjectType
指向触发回调例程的对象类型的指针。指定以下值之一:
- PsProcessType用于进程句柄操作
- PsThreadType用于线程句柄操作
- ExDesktopObjectType用于桌面句柄操作。此值在 Windows 10 中受支持,而在早期版本的操作系统中不受支持。
经过几个小时的搜索,我仍然不知道应该如何指定PsProcessType
和初始化我的结构。PsProcessType
似乎process.c
在第 20 行中定义。然而它实际上只是说
POBJECT_TYPE PsProcessType = NULL;
这并不是特别有用,因为IntPtr.Zero
当初始化OB_OPERATION_REGISTRATION
结构时将 ObjectType 字段设置为时System.AccessViolationException
,调用ObRegisterCallbacks
. (在被调用UNICODE_STRING
的OB_OPERATION_REGISTRATION
结构Altitude
中还有一个必须设置为某个值(但目前不是lol :D),但是该字符串已被初始化和分配,因此它不应该对访问冲突负责......对?)
这是我第一次深入研究 Windows 内核的东西,所以如果有人能帮我解决这个问题或者指出一些我没有设法挖掘的隐藏资源,那就太好了:)
有一篇文章用于ObRegisterCallbacks
类似的事情(尽管在 C++ 中),但是它们并没有真正指定它们的PsProcessType
来源或定义方式。因此,如果他们可以成功使用该“ObjectType”字段,则必须在某个地方有文档,对吗?
解决方案
PsProcessType
在 ntoskrnl.exe 导出,和 一样ObRegisterCallbacks
,区别是一个是导出的全局变量,一个是导出的函数。
在 C 中,这些全局变量在 wdm.h 中声明:
extern POBJECT_TYPE *CmKeyObjectType;
extern POBJECT_TYPE *IoFileObjectType;
extern POBJECT_TYPE *ExEventObjectType;
extern POBJECT_TYPE *ExSemaphoreObjectType;
extern POBJECT_TYPE *TmTransactionManagerObjectType;
extern POBJECT_TYPE *TmResourceManagerObjectType;
extern POBJECT_TYPE *TmEnlistmentObjectType;
extern POBJECT_TYPE *TmTransactionObjectType;
extern POBJECT_TYPE *PsProcessType;
extern POBJECT_TYPE *PsThreadType;
extern POBJECT_TYPE *PsJobType;
extern POBJECT_TYPE *SeTokenObjectType;
#if (NTDDI_VERSION >= NTDDI_THRESHOLD)
extern POBJECT_TYPE *ExDesktopObjectType;
#endif
因此,您可以只使用这些变量而无需执行任何其他操作。
但是我不擅长C#,我什至不确定C#模块是否可以加载到内核中。
最推荐的方法是使用 C/C++ 进行内核编程,而我从未听说有人使用 C# 这样做。
推荐阅读
- adobe-illustrator - Adobe Illustrator 变量和脚本 - 有可能吗?
- javascript - isset($_POST['value']) 数据没有被 php 接收
- reactjs - 不要重新加载子组件传入的useCallback参数
- python - 使用 Python IPAddress 模块增加给定 IP 地址的网络地址
- javascript - 检查 HTML 文件是直接访问还是被重定向
- c++ - 从另一个类中调用以 void* 作为参数的函数
- jboss - 在 RHEL 上重命名 JBoss 主机后“无法打开 PID 文件”
- google-apps-script - Google Workspace Business Starter 帐户上 GmailApp.SendEmail 的配额限制
- flutter - 在 Flutter 中使用键盘时防止背景滚动
- sql - 更新查询以返回上一年/季度日期/值之前的最新收入日期/值(雪花)