我有一个线程用于某些操作,它需要保持活动状态,直到标志另有说明为止。
我使用PsCreateSystemThread创建线程,然后使用ObReferenceObjectByHandle获取ETHREAD对象引用,以在使用KeWaitForSingleObject卸载驱动程序之前等待线程终止。
创建线程并检索对它的引用的函数:
ntStatus = PsCreateSystemThread(
&hThread,
(ACCESS_MASK)0, NULL,
(HANDLE)0, NULL,
ThreadRoutine,
(PVOID)pThreadData
);
if (!NT_SUCCESS(ntStatus))
{
return ntStatus;
}
ntStatus = ObReferenceObjectByHandle(
hThread,
THREAD_ALL_ACCESS,
NULL,
KernelMode,
(PVOID*)&ptThreadObject,
NULL
);
if (!NT_SUCCESS(ntStatus))
{
bStopThread = TRUE;
ptThreadObject = NULL;
return ntStatus;
}
Run Code Online (Sandbox Code Playgroud)
线程例程:
LARGE_INTEGER liSleepTime;
while (FALSE == bThread)
{
liSleepTime.QuadPart = 1000 * RELATIVE_MILLISECOND;
KeDelayExecutionThread(KernelMode, FALSE, (&liSleepTime));
ExAcquireFastMutex(&fmMutex);
//DO SOMTHING
ExReleaseFastMutex(&fmMutex);
}
PsTerminateSystemThread(STATUS_SUCCESS);
Run Code Online (Sandbox Code Playgroud)
卸载驱动函数:
if (NULL != ptThreadObject)
{
bStopThread = …Run Code Online (Sandbox Code Playgroud) 我一直在研究 Windows 内部,最近刚刚了解了系统调用,我想知道是否可以像函数一样使用这些系统调用?我知道它们并不是真的要从外部访问。
例如:NtUserEmptyClipboard是 Win32k.sys 中的系统调用,其地址为0x117f
如果我想像函数一样使用这个调用,我该怎么做?
我看到一些关于WinDBG的commnads的参考和教程.他们中的一些人喜欢这个lm,这个.echo,这个!running和这个nt!_PDB.
这些类别之间有什么区别
?
他们看起来很困惑.
当我在VMWare Workstation虚拟机中运行的Windows 7 x64的内核模式下运行以下汇编序列时:
xor eax, eax
mov ax, gs
mov gs, ax ; this instruction
Run Code Online (Sandbox Code Playgroud)
最后一条mov gs, ax指令会立即导致该VM崩溃(或可能是错误检查),并显示以下弹出消息:
发生故障导致虚拟CPU进入关闭状态.如果此故障发生在虚拟机之外,则会导致物理计算机重新启动.通过错误配置虚拟机,客户机操作系统中的错误或VMWare Workstation中的问题可以达到关闭状态.
重新加载gs寄存器会导致内核中的问题,还是虚拟化问题?
我没有看到mov英特尔手册中有关该指令的任何异常.
PS.顺便说一句,更换gs寄存器fs不会导致此错误.
编辑:回答有关GDT中段描述符状态的问题.这里是:
0: kd> r gs
gs=002b
0: kd> dg 28
P Si Gr Pr Lo
Sel Base Limit Type l ze an es ng Flags
---- ----------------- ----------------- ---------- - -- -- -- -- --------
0028 00000000`00000000 00000000`ffffffff Data RW Ac 3 Bg Pg P …Run Code Online (Sandbox Code Playgroud) 我熟悉任务优先级寄存器cr8(Windows 上的 IRQL),当然我知道如何使用 和 来启用和禁用cli中断sti。不过,我对两者有几个疑问。
首先,清除中断标志是否会cli“覆盖”TPR 中存储的当前值?例如:TPR 是PASSIVE_LEVEL (0)。如果中断被禁用,TPR 中的值就不再重要了吗?第二:我是从维基百科上读到的:
将 TPR 加载为 0 会启用所有外部中断。用 15 (1111b) 加载 TPR 将禁用所有外部中断。
这是否意味着将 TPR 设置为0xF KzRaiseIrql(HIGH_LEVEL)相当于cli?如果我的 TPR 是0xF并且中断标志被清除,会发生什么情况?如果中断标志使能怎么办?
我目前正在尝试使用Windows 驱动程序示例中的 NDIS 筛选器驱动程序发送我自己的数据包。
我认为我必须使用该功能发送数据包FilterSendNetBufferLists。但我不知道如何创建这些数据包,也不知道是否应该将它们添加到现有的 NetBufferList 中或创建自己的数据包。
我还需要修改功能吗FilterSendNetBufferListsComplete?
如果我有一个Win32线程,我通过句柄引用它,也可以获取它的线程ID.
在我关闭手柄之前,手柄仍然有效且可用,即使线程已经终止.(否则,无法使用例如GetExitCodeThread
然而,似乎文档未能一致地提及线程终止后线程ID的"发生",但只要任何人仍然拥有终止线程的线程句柄.
线程句柄和标识符表明了这一点
标识符从创建线程到线程终止之间有效.
然后,当我们查看GetThreadId API时,如果ID在线程终止之前只有效,我们可能想知道对于终止线程应该返回什么.(并且还有一个用户评论这个网站:"不正确.只要有一个打开的句柄线程,它的线程ID仍然有效且唯一."这确实回答了这个问题,是的,但没有更多上下文我很谨慎.)
另外,我在SO上的答案中找到了这个片段:
ID是系统中运行的线程的唯一数字标识符.与任何内核对象句柄一样,线程句柄可以看作是指向内核对象的特殊类型的引用计数指针.
如果这是正确的并且线程ID确实是内核对象的ID,那么只要任何句柄打开(因为内核对象需要保留在那里进行查询),似乎必须使该ID保持有效.
我的推理是否合理?只要任何句柄打开,线程ID是否有效?是否有任何 MS文档或权威的书,明确规定一个或其他?
我希望从 Windows 10 内核模式驱动程序 (C) 进行一些日志记录。我在驱动程序内部有很多日志记录,但是在这种情况下,我无法附加内核调试器,因此我想将调试字符串转储到 txt 文件(甚至事件日志)。
例如,这是一个例子
#include <stdio.h>
#include <stdlib.h>
VOID Log(char * text) {
FILE *f = fopen("c:\\temp\\logger.txt", "a+");
if (f == NULL) return;
fprintf(f, "%s\n", text);
fclose(f);
}
Run Code Online (Sandbox Code Playgroud)
不过我得到
Run Code Online (Sandbox Code Playgroud)driver.obj : error LNK2019: unresolved external symbol fclose referenced in function Log driver.obj : error LNK2019: unresolved external symbol fopen referenced in function Log tdriver.obj : error LNK2019: unresolved external symbol fprintf referenced in function Log
我已经包含了 stdio.h,我还需要做些什么才能链接到它吗?
或者是因为这是一个内核驱动程序,我无法使用这些库,并且必须执行不同的低级过程才能写入日志文件?
编辑:看来我无法从内核驱动程序使用 fopen 。
我尝试了这个,但是没有任何内容写入文件。我基于这个例子编写了代码:
我所做的更改是将标志设置为 FILE_OPEN_IF …
我目前正在试验NDIS 驱动程序示例。我正在尝试打印数据包内容(包括 MAC 地址、以太网类型和数据)。
我的第一个猜测是在函数中实现它FilterReceiveNetBufferLists。不幸的是,我不确定如何从NetBufferLists.
我将我的 Visual Studio 从 2017 年升级到 2019 年,似乎他们在最新版本中对 Visual Studio 做了一些奇妙的更改,因为我在 VS 2017 中没有这个问题,甚至编译了你可以在任何地方找到的简单的 hello world 驱动程序更长的编译时间,它们给出以下错误:
Device driver does not install on any devices, use primitive driver if this is intended
Run Code Online (Sandbox Code Playgroud)
看起来它与默认的 INF 文件有关:
https://github.com/MicrosoftDocs/windows-driver-docs/issues/2067
但那里的答案毫无用处,并且对 INF 文件提到的更改都没有帮助,这是我的 INF 文件,它是 VS 2019 上的默认 INF :
;
; HelloWorld.inf
;
[Version]
Signature="$WINDOWS NT$"
Class=System
ClassGuid={4d36e97d-e325-11ce-bfc1-08002be10318}
Provider=%ManufacturerName%
DriverVer=
CatalogFile=HelloWorld.cat
PnpLockDown=1
[DestinationDirs]
DefaultDestDir = 12
[SourceDisksNames]
1 = %DiskName%,,,""
[SourceDisksFiles]
[Manufacturer]
%ManufacturerName%=Standard,NT$ARCH$
[Standard.NT$ARCH$]
[Strings]
ManufacturerName="<Your manufacturer name>" ;TODO: Replace with your manufacturer …Run Code Online (Sandbox Code Playgroud) 似乎在Windows 32位上,内核将从完全4G用户虚拟内存空间中保留1G虚拟内存,并将一些内核空间映射到此1G空间.
所以我的问题是:
我认为
cat /proc/pid/map
Run Code Online (Sandbox Code Playgroud)
只能看到某些进程的用户空间布局..
谢谢!
我在64位Windows 10上运行以下32位进程:
#ifndef _DEBUG
WCHAR buffPath[MAX_PATH] = {0};
FARPROC pfn = (FARPROC)::GetModuleHandleEx;
HMODULE hMod = NULL;
::GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS |
GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT,
(LPCTSTR)pfn, &hMod);
PVOID pOldVal = NULL;
if(::Wow64DisableWow64FsRedirection(&pOldVal))
{
::GetModuleFileNameEx(::GetCurrentProcess(), hMod, buffPath, _countof(buffPath));
::Wow64RevertWow64FsRedirection(pOldVal);
wprintf(L"Path=%s\n", buffPath);
}
#else
#error run_in_release_mode
#endif
Run Code Online (Sandbox Code Playgroud)
而且我期待收到路径c:\windows\syswow64\KERNEL32.DLL,但它给了我:
Path=C:\Windows\System32\KERNEL32.DLL
Run Code Online (Sandbox Code Playgroud)
知道为什么吗?
我有C应用程序,可以确定我的笔记本电脑上何时打开电源.它仅在我打开此.exe文件时才有效
有没有办法让它在内核模式下工作?这意味着我不想运行.exe,只需打开笔记本电脑,并在电量不足时接收有关电源的消息.
这是我的.exe:
#include <windows.h>
const char g_szClassName[] = "myWindowClass";
// Step 4: the Window Procedure
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
short x ;
SYSTEM_POWER_STATUS status;
switch(msg)
{
case WM_CLOSE:
DestroyWindow(hwnd);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
case WM_POWERBROADCAST:
switch (wParam)
{
case PBT_APMPOWERSTATUSCHANGE :
x = GetSystemPowerStatus(&status);
if (x > 0) // function succeeded
{
if (status.ACLineStatus == 1)
{
printf("power is off");
MessageBox(NULL, "power is on" , "NOTICE" ,MB_OK );
}
else if …Run Code Online (Sandbox Code Playgroud)