Win64 驱动内核编程-8.内核里的其他常用
内核里的其他常用
1.遍历链表。内核里有很多数据结构,但它们并不是孤立的,内核使用双向链表把它们像糖
葫芦一样给串了起来。所以遍历双向链表能获得很多重要的内核数据。举个简单的例子,驱
动对象 DriverObject 就是使用双向链表给串起来的,遍历这个链表就可以枚举内核里所有的驱动。示例代码如下
//传入驱动自身的 DriverObject
VOID EnumDriver(PDRIVER_OBJECT pDriverObject)
{
PKLDR_DATA_TABLE_ENTRY entry = (PKLDR_DATA_TABLE_ENTRY)pDriverObject->DriverSection;
PKLDR_DATA_TABLE_ENTRY firstentry;
ULONG64 pDrvBase = 0;
KIRQL OldIrql;
firstentry = entry;
//当发现又找到自己时跳出循环,否则成了死循环。
while ((PKLDR_DATA_TABLE_ENTRY)entry->InLoadOrderLinks.Flink != firstentry)
{
DbgPrint("BASE=%p\tPATH=%wZ", entry->DllBase, entry->FullDllName);
entry = (PKLDR_DATA_TABLE_ENTRY)entry->InLoadOrderLinks.Flink;
}
}
2.等待。这个等于 RING3 的 Sleep 函数了。
#define DELAY_ONE_MICROSECOND (-10)
#define DELAY_ONE_MILLISECOND (DELAY_ONE_MICROSECOND*1000)
VOID MySleep(LONG msec)
{
LARGE_INTEGER my_interval;
my_interval.QuadPart = DELAY_ONE_MILLISECOND;
my_interval.QuadPart *= msec;
KeDelayExecutionThread(KernelMode, 0, &my_interval);
}
3.同步。这个可以理解成是“条件等待”。常用的是 KeWaitForSingleObject、KeInitializeEvent、
KeSetEvent 这几个函数。为了方便讲解,这个的示例代码与“内核线程”放在一起。先把这
几个函数的原型贴出来。
NTSTATUS KeWaitForSingleObject
(
_In_ PVOID Object,
_In_ KWAIT_REASON WaitReason,
_In_ KPROCESSOR_MODE WaitMode,
_In_ BOOLEAN Alertable,
_In_opt_ PLARGE_INTEGER Timeout
);
VOID KeInitializeEvent
(
_Out_ PRKEVENT Event,
_In_ EVENT_TYPE Type,
_In_ BOOLEAN State
);
LONG KeSetEvent
(
_Inout_ PRKEVENT Event,
_In_ KPRIORITY Increment,
_In_ BOOLEAN Wait
);
4.获得系统版本号。内核编程难免使用硬编码,以及使用一些高版本系统才出现的函数。为
了使得驱动能在低版本的系统上正常运行,就需要根据不同系统做不同处理了。
VOID GetVersion()
{
ULONG NtBuildNumber;
RTL_OSVERSIONINFOW osi;
osi.dwOSVersionInfoSize = sizeof(RTL_OSVERSIONINFOW);
RtlFillMemory(&osi, sizeof(RTL_OSVERSIONINFOW), 0);
RtlGetVersion(&osi);
NtBuildNumber = osi.dwBuildNumber;
DbgPrint("NtBuildNumber: %ld\n", NtBuildNumber);
return NtBuildNumber;
}
5.获得系统时间。在内核里获得系统时间的是标准时间(GMT+0),转换成本地时间还需要进
行转换。此功能在发布测试版软件的时候特别有用,限制人们只能在指定时间之前使用。
VOID MyGetCurrentTime()
{
LARGE_INTEGER CurrentTime;
LARGE_INTEGER LocalTime;
TIME_FIELDS TimeFiled;
// 这里得到的其实是格林威治时间
KeQuerySystemTime(&CurrentTime);
// 转换成本地时间
ExSystemTimeToLocalTime(&CurrentTime, &LocalTime);
// 把时间转换为容易理解的形式
RtlTimeToTimeFields(&LocalTime, &TimeFiled);
DbgPrint("[TimeTest] NowTime : %4d-%2d-%2d %2d:%2d:%2d",
TimeFiled.Year, TimeFiled.Month, TimeFiled.Day,
TimeFiled.Hour, TimeFiled.Minute, TimeFiled.Second);
}
6.内核线程。内核线程就是名义上属于 SYSTEM 进程的线程。比如说你要做坏事,却让 SYSTEM
进程背黑锅,是一件很爽的事情。内核线程还有几个特点:1. PreviousMode 是 KernelMode,
可以直接调用 Nt 开头的内核函数(Nt 开头的内核函数会检查 PreviousMode,如果
PreviousMode 不是 KernelMode,就会拒绝服务。有些人喜欢直接修改 ETHREAD 里的这个值,
但我个人觉得这么改不妥当)。2.内核线程不会自己结束,必须调用 PsTerminateSystemThread
才能被动结束。以下是例子, 同时演示了 等待 、同步和内核线程的使用。
KEVENT kEvent; //事件
//线程函数
VOID MyThreadFunc(IN PVOID context)
{
PUNICODE_STRING str = (PUNICODE_STRING)context;
DbgPrint("Kernel thread running: %wZ\n", str);
DbgPrint("Wait 3s!\n");
MySleep(3000);
DbgPrint("Kernel thread exit!\n");
KeSetEvent(&kEvent, 0, TRUE);
PsTerminateSystemThread(STATUS_SUCCESS);
}
//创建线程的函数
VOID CreateThreadTest()
{
HANDLE hThread;
UNICODE_STRING ustrTest = RTL_CONSTANT_STRING(L"This is a string for test!");
NTSTATUS status;
// 初始化事件
KeInitializeEvent(&kEvent, SynchronizationEvent, FALSE);
status = PsCreateSystemThread(&hThread, 0, NULL, NULL, NULL, MyThreadFunc,
(PVOID)&ustrTest);
if (!NT_SUCCESS(status))
{
DbgPrint("PsCreateSystemThread failed!");
return;
}
ZwClose(hThread);
// 等待事件
KeWaitForSingleObject(&kEvent, Executive, KernelMode, FALSE, NULL);
DbgPrint("CreateThreadTest OVER!\n");
}
7.强制重启计算机。在内核里直接使用 OUT 指令就能强制重启计算机而不可能被任何钩子
拦截。此代码可以用在反调试里。
VOID ForceReboot()
{
typedef void(__fastcall *FCRB)(void);
/*
mov al, 0FEh
out 64h, al
ret
*/
FCRB fcrb = NULL;
UCHAR shellcode[6] = "\xB0\xFE\xE6\x64\xC3";
fcrb = ExAllocatePool(NonPagedPool, 5);
memcpy(fcrb, shellcode, 5);
fcrb();
}
8.强制关闭计算机。在内核里直接使用 OUT 指令就能强制关闭计算机而不可能被任何钩子
拦截。此代码可以用在反调试里。
VOID ForceShutdown()
{
typedef void(__fastcall *FCRB)(void);
/*
mov ax,2001h
mov dx,1004h
out dx,ax
ret
*/
FCRB fcrb = NULL;
UCHAR shellcode[12] = "\x66\xB8\x01\x20\x66\xBA\x04\x10\x66\xEF\xC3";
fcrb = ExAllocatePool(NonPagedPool, 11);
memcpy(fcrb, shellcode, 11);
fcrb();
}
Win64 驱动内核编程-8.内核里的其他常用的更多相关文章
- Win64 驱动内核编程-3.内核里使用内存
内核里使用内存 内存使用,无非就是申请.复制.设置.释放.在 C 语言里,它们对应的函数是:malloc.memcpy.memset.free:在内核编程里,他们分别对应 ExAllocatePool ...
- Win64 驱动内核编程-7.内核里操作进程
在内核里操作进程 在内核里操作进程,相信是很多对 WINDOWS 内核编程感兴趣的朋友第一个学习的知识点.但在这里,我要让大家失望了,在内核里操作进程没什么特别的,就标准方法而言,还是调用那几个和进程 ...
- Win64 驱动内核编程-5.内核里操作文件
内核里操作文件 RING0 操作文件和 RING3 操作文件在流程上没什么大的区别,也是"获得文件句柄->读/写/删/改->关闭文件句柄"的模式.当然了,只能用内核 A ...
- Win64 驱动内核编程-6.内核里操作注册表
内核里操作注册表 RING0 操作注册表和 RING3 的区别也不大,同样是"获得句柄->执行操作->关闭句柄"的模式,同样也只能使用内核 API 不能使用 WIN32 ...
- Win64 驱动内核编程-4.内核里操作字符串
内核里操作字符串 字符串本质上就是一段内存,之所以和内存使用分开讲,是因为内核里的字符串太有花 样了,细数下来竟然有 4 种字符串!这四种字符串,分别是:CHAR*.WCHAR*.ANSI_STRIN ...
- WIN64内核编程-的基础知识
WIN64内核编程基础班(作者:胡文亮) https://www.dbgpro.com/x64driver 我们先从一份"简历"说起: 姓名:X86或80x86 性别:? 出生 ...
- Win64 驱动内核编程-2.基本框架(安装.通讯.HelloWorld)
驱动安装,通讯,Hello World 开发驱动的简单流程是这样,开发驱动安装程序,开发驱动程序,然后安装程序(或者其他程序)通过通讯给驱动传命令,驱动接到之后进行解析并且执行,然后把执行结果返回. ...
- Win64 驱动内核编程-18.SSDT
SSDT 学习资料:http://blog.csdn.net/zfdyq0/article/details/26515019 学习资料:WIN64内核编程基础 胡文亮 SSDT(系统服务描述表),刚开 ...
- Win64 驱动内核编程-22.SHADOW SSDT HOOK(宋孖健)
SHADOW SSDT HOOK HOOK 和 UNHOOK SHADOW SSDT 跟之前的 HOOK/UNHOOK SSDT 类似,区别是查找SSSDT的特征码,以及根据索引计算函数地址的公式,还 ...
随机推荐
- 使用jsoup十分钟内掌握爬虫技术
对,就是十分钟,没有接触过爬虫的你,肯定一脸懵逼,感觉好高深的样子,一开始我也有点懵,但用了以后发现还是很简单的,java爬虫框架有很多,让我有种选择困难症,通过权衡比较还是感觉jsoup比较好用些, ...
- GNS3通过“云”连接到虚拟机实验
GNS3通过"云"连接到虚拟机实验并使用wireshark工具对数据分析 观看本文之前注意!!!!! 做这次实验,我所遇到的问题,会全部写在文章结尾,如果读者们遇到问题,可查看. ...
- rest framework Views
基于类的意见 Django的基于类的意见是从旧式的观点颇受欢迎. - Reinout面包车里斯 REST框架提供了一个APIView类,它的子类Django的View类. APIView类是从正规不同 ...
- 解决新版谷歌浏览器在http请求下无法开启麦克风问题
1.在浏览器地址栏中输入"chrome://flags/#unsafely-treat-insecure-origin-as-secure", 2.将该选项置为Enabled, 3 ...
- sqlmap在https下的一种错误 - ssl连接失败
在昨天与师傅的交流中师傅考了我一个问题,在用sqlmap跑的时候遇到ssl爆红该怎么办,因为在实战中并没有遇到过这种情况,所以今天补一下知识. 首先查询了ssl的概念,通俗来说,如果一个网站没有安装s ...
- 【LeetCode】52. N-Queens II(位运算)
[题意] 输出N皇后问题的解法个数. [题解] 解法一:传统dfs回溯,模拟Q放置的位置即可,应该不难,虽然能通过,但是时间复杂度很高. 解法二:位运算大法好! 首先要明白这道题里两个核心的位运算 1 ...
- IT培训有哪些坑(一)?
IT行业资薪很高,每年都有很多同学冲着高薪去,去各个培训机构学习,期望将来能找个高薪的工作,有个好的出路.我们先不说你选多好,多靠谱的机构,我先来告诉大家有哪些不靠谱,不能选,选了就入坑了的. IT培 ...
- 抗DDOS应急预案实践-生产环境总结-建议必看
一.首先摸清楚环境与资源 为DDoS应急预案提供支撑 所在的网络环境中,有多少条互联网出口?每一条带宽多少? 每一条互联网出口的运营商是否支持DDoS攻击清洗,我们是否购买,或可以紧急试用?当发生DD ...
- 百度地图一套JS API,非常实用
百度地图一套JS API,非常实用 import mapStyleJson from "./mapStyleJson"; import $ from "jquery&qu ...
- ES 分页方案
ES 中,存在三种常见的分页方案: FROM, SIZE Search-After Scroll 下面将依次比较三种方案之间的 trede-off,并给出相应建议的应用场景. 常见分页,FROM, S ...