[{"data":1,"prerenderedAt":518},["ShallowReactive",2],{"page-\u002Fsystem\u002Fwindows\u002Fdkom开发":3},{"id":4,"title":5,"body":6,"description":506,"extension":507,"meta":508,"navigation":314,"path":514,"seo":515,"stem":516,"__hash__":517},"content\u002Fsystem\u002Fwindows\u002FDKOM开发.md","DKOM开发",{"type":7,"value":8,"toc":500},"minimark",[9,18,25,29,40,67,107,136,139,201,211,255,258,367,383,393,403,406,437,440,490,493,496],[10,11,12,13,17],"p",{},"DKOM 的全称是 ",[14,15,16],"strong",{},"Direct Kernel Object Manipulation","（直接内核对象操作）。它是 Windows 内核级 Rootkit（木马\u002F后门）最核心的底层技术之一",[10,19,20,21,24],{},"简单来说，",[14,22,23],{},"DKOM 就是利用内核驱动（Ring 0 权限），绕过操作系统的标准 API，直接潜入内存，对内核里的数据结构"," 进行操作",[26,27,28],"h2",{"id":28},"数据类型",[10,30,31,32,35,36],{},"Uchar是Windows 内核（以及 Windows 底层开发）中特有的数据类型。它其实就是一个 ",[14,33,34],{},"8位无符号字符（Unsigned Character）","，在底层完全等价于 ",[37,38,39],"code",{},"unsigned char",[10,41,42,45,46,51,52,55,56,58,59,62,63,66],{},[37,43,44],{},"PUCHAR"," 里的 ",[14,47,48],{},[37,49,50],{},"P"," 代表 ",[14,53,54],{},"Pointer（指针）"," ，所以，",[37,57,44],{}," 的全称是 ",[14,60,61],{},"Pointer to Unsigned Character","，即 ",[14,64,65],{},"“指向无符号字符的指针”","。",[68,69,74],"pre",{"className":70,"code":71,"language":72,"meta":73,"style":73},"language-C shiki shiki-themes github-light github-dark","HANDLE pid = *(HANDLE*)((PUCHAR)pCurrent + OFFSET_UNIQUE_PROCESS_ID);\n","C","",[37,75,76],{"__ignoreMap":73},[77,78,81,85,89,92,95,98,101,104],"span",{"class":79,"line":80},"line",1,[77,82,84],{"class":83},"sVt8B","HANDLE pid ",[77,86,88],{"class":87},"szBVR","=",[77,90,91],{"class":87}," *",[77,93,94],{"class":83},"(HANDLE",[77,96,97],{"class":87},"*",[77,99,100],{"class":83},")((PUCHAR)pCurrent ",[77,102,103],{"class":87},"+",[77,105,106],{"class":83}," OFFSET_UNIQUE_PROCESS_ID);\n",[10,108,109,112,113,116,117,120,121,123,124,127,128,131,132,135],{},[37,110,111],{},"pCurrent"," 是一个 ",[37,114,115],{},"PEPROCESS"," 类型的指针（指向 ",[37,118,119],{},"_EPROCESS"," 这个巨型结构体的开头），这里强转成无符号字节指针，然后再加上偏移值后，刚好精准地停在 ",[37,122,119],{}," 结构体里 ",[37,125,126],{},"UniqueProcessId"," 字段的",[14,129,130],{},"起始位置","。这里再让编译器把这个地址当成一个",[14,133,134],{},"指向 8 字节句柄（HANDLE）的指针","”。最后再解引用去刚才算出来的那个 8 字节内存地址里，把真实的数据（也就是 PID 的值）掏出来。",[10,137,138],{},"PLIST_ENTRY 是windows内核里的双向链表的指针，p 是指针，list_entry是链表条目，是windows内核定义的一个极简结构体。它的底层定义极其简单，就两个指针：",[68,140,144],{"className":141,"code":142,"language":143,"meta":73,"style":73},"language-c shiki shiki-themes github-light github-dark","typedef struct _LIST_ENTRY {\n    struct _LIST_ENTRY *Flink; \u002F\u002F 指向下一个节点 (Forward Link)\n    struct _LIST_ENTRY *Blink; \u002F\u002F 指向上一个节点 (Backward Link)\n} LIST_ENTRY, *PLIST_ENTRY;\n","c",[37,145,146,157,175,190],{"__ignoreMap":73},[77,147,148,151,154],{"class":79,"line":80},[77,149,150],{"class":87},"typedef",[77,152,153],{"class":87}," struct",[77,155,156],{"class":83}," _LIST_ENTRY {\n",[77,158,160,163,166,168,171],{"class":79,"line":159},2,[77,161,162],{"class":87},"    struct",[77,164,165],{"class":83}," _LIST_ENTRY ",[77,167,97],{"class":87},[77,169,170],{"class":83},"Flink;",[77,172,174],{"class":173},"sJ8bj"," \u002F\u002F 指向下一个节点 (Forward Link)\n",[77,176,178,180,182,184,187],{"class":79,"line":177},3,[77,179,162],{"class":87},[77,181,165],{"class":83},[77,183,97],{"class":87},[77,185,186],{"class":83},"Blink;",[77,188,189],{"class":173}," \u002F\u002F 指向上一个节点 (Backward Link)\n",[77,191,193,196,198],{"class":79,"line":192},4,[77,194,195],{"class":83},"} LIST_ENTRY, ",[77,197,97],{"class":87},[77,199,200],{"class":83},"PLIST_ENTRY;\n",[10,202,203,204,206,207,210],{},"我们可以利用它拿当前进程的基址（",[37,205,111],{},"）加上偏移量，找到了它里面那个叫 ",[37,208,209],{},"ActiveProcessLinks"," 的字段。",[68,212,214],{"className":141,"code":213,"language":143,"meta":73,"style":73},"\u002F\u002F move\nPLIST_ENTRY pListEntry = (PLIST_ENTRY)((PUCHAR)pCurrent +\n      OFFSET_ACTIVE_PROCESS_LINKS);\nPLIST_ENTRY pNextEntry = pListEntry->Flink;\n\n",[37,215,216,221,234,239],{"__ignoreMap":73},[77,217,218],{"class":79,"line":80},[77,219,220],{"class":173},"\u002F\u002F move\n",[77,222,223,226,228,231],{"class":79,"line":159},[77,224,225],{"class":83},"PLIST_ENTRY pListEntry ",[77,227,88],{"class":87},[77,229,230],{"class":83}," (PLIST_ENTRY)((PUCHAR)pCurrent ",[77,232,233],{"class":87},"+\n",[77,235,236],{"class":79,"line":177},[77,237,238],{"class":83},"      OFFSET_ACTIVE_PROCESS_LINKS);\n",[77,240,241,244,246,249,252],{"class":79,"line":192},[77,242,243],{"class":83},"PLIST_ENTRY pNextEntry ",[77,245,88],{"class":87},[77,247,248],{"class":83}," pListEntry",[77,250,251],{"class":87},"->",[77,253,254],{"class":83},"Flink;\n",[26,256,257],{"id":257},"驱动入口",[68,259,261],{"className":141,"code":260,"language":143,"meta":73,"style":73},"extern \"C\" NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObject, PUNICODE_STRING pRegistryPath) {\n    UNREFERENCED_PARAMETER(pDriverObject);\n    UNREFERENCED_PARAMETER(pRegistryPath);\n\n    DbgPrint(\"[DKOM] Driver loaded!\\n\");\n    MyListProcesses();\n\n    return STATUS_SUCCESS;\n}\n",[37,262,263,295,303,310,316,338,347,352,361],{"__ignoreMap":73},[77,264,265,268,272,275,279,282,286,289,292],{"class":79,"line":80},[77,266,267],{"class":87},"extern",[77,269,271],{"class":270},"sZZnC"," \"C\"",[77,273,274],{"class":83}," NTSTATUS ",[77,276,278],{"class":277},"sScJk","DriverEntry",[77,280,281],{"class":83},"(PDRIVER_OBJECT ",[77,283,285],{"class":284},"s4XuR","pDriverObject",[77,287,288],{"class":83},", PUNICODE_STRING ",[77,290,291],{"class":284},"pRegistryPath",[77,293,294],{"class":83},") {\n",[77,296,297,300],{"class":79,"line":159},[77,298,299],{"class":277},"    UNREFERENCED_PARAMETER",[77,301,302],{"class":83},"(pDriverObject);\n",[77,304,305,307],{"class":79,"line":177},[77,306,299],{"class":277},[77,308,309],{"class":83},"(pRegistryPath);\n",[77,311,312],{"class":79,"line":192},[77,313,315],{"emptyLinePlaceholder":314},true,"\n",[77,317,319,322,325,328,332,335],{"class":79,"line":318},5,[77,320,321],{"class":277},"    DbgPrint",[77,323,324],{"class":83},"(",[77,326,327],{"class":270},"\"[DKOM] Driver loaded!",[77,329,331],{"class":330},"sj4cs","\\n",[77,333,334],{"class":270},"\"",[77,336,337],{"class":83},");\n",[77,339,341,344],{"class":79,"line":340},6,[77,342,343],{"class":277},"    MyListProcesses",[77,345,346],{"class":83},"();\n",[77,348,350],{"class":79,"line":349},7,[77,351,315],{"emptyLinePlaceholder":314},[77,353,355,358],{"class":79,"line":354},8,[77,356,357],{"class":87},"    return",[77,359,360],{"class":83}," STATUS_SUCCESS;\n",[77,362,364],{"class":79,"line":363},9,[77,365,366],{"class":83},"}\n",[10,368,369,371,372,375,376,379,380,66],{},[37,370,278],{}," 是 ",[14,373,374],{},"Windows NT 内核驱动在加载时的标准、固定的入口点（Entry Point）","，等同于用户态应用程序的 ",[37,377,378],{},"main"," 或 ",[37,381,382],{},"WinMain",[10,384,385,386,389,390,392],{},"操作系统的映像加载器（Image Loader）和 I\u002FO 管理器（I\u002FO Manager）在将 ",[37,387,388],{},".sys"," 文件映射到内核内存后，会硬编码查找名为 ",[37,391,278],{}," 的导出符号，并将其作为执行起点。",[10,394,395,396,399,400,66],{},"定义在 ",[37,397,398],{},"ntddk.h"," 中，其标准签名固定为 ",[37,401,402],{},"NTSTATUS DriverEntry(PDRIVER_OBJECT, PUNICODE_STRING)",[26,404,405],{"id":405},"内核函数",[10,407,408,409,412,413,416,417,420,421,428,429,432,433,436],{},"RltCopyMemory，这是微软 WDK 提供的一个极其重要的内核函数（类似用户态 C 语言的 ",[37,410,411],{},"memcpy","）。",[37,414,415],{},"ImageFileName"," 这个 ",[37,418,419],{},"UChar"," 数组（15字节）",[14,422,423,424,427],{},"没有 ",[37,425,426],{},"\\0"," 结束符","！如果你用 ",[37,430,431],{},"strcpy","，它会一直往后读，读到不属于这个进程的内存，导致系统直接蓝屏。",[37,434,435],{},"RtlCopyMemory"," 是“不管里面是什么数据，我只按指定的长度（字节数）强拷”，绝对安全。",[10,438,439],{},"我们使用起来类似这样：",[68,441,443],{"className":70,"code":442,"language":72,"meta":73,"style":73},"CHAR szName[16] = { 0 };\nRtlCopyMemory(szName, (PUCHAR)pCurrent + OFFSET_IMAGE_FILE_NAME, 15);\n",[37,444,445,473],{"__ignoreMap":73},[77,446,447,450,453,456,459,462,464,467,470],{"class":79,"line":80},[77,448,449],{"class":83},"CHAR ",[77,451,452],{"class":284},"szName",[77,454,455],{"class":83},"[",[77,457,458],{"class":330},"16",[77,460,461],{"class":83},"] ",[77,463,88],{"class":87},[77,465,466],{"class":83}," { ",[77,468,469],{"class":330},"0",[77,471,472],{"class":83}," };\n",[77,474,475,477,480,482,485,488],{"class":79,"line":159},[77,476,435],{"class":277},[77,478,479],{"class":83},"(szName, (PUCHAR)pCurrent ",[77,481,103],{"class":87},[77,483,484],{"class":83}," OFFSET_IMAGE_FILE_NAME, ",[77,486,487],{"class":330},"15",[77,489,337],{"class":83},[26,491,492],{"id":492},"读取进程",[10,494,495],{},"我们都知道windbg有个命令!process 0 0，这个我们经常用来查看所有会话里的进程，要实现这个功能，我们也可以使用dkom里的开发。每个windows版本的偏移量不同，所以开发前务必知道偏移量大小，才能操作链表。",[497,498,499],"style",{},"html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sJ8bj, html code.shiki .sJ8bj{--shiki-default:#6A737D;--shiki-dark:#6A737D}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .s4XuR, html code.shiki .s4XuR{--shiki-default:#E36209;--shiki-dark:#FFAB70}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}",{"title":73,"searchDepth":159,"depth":159,"links":501},[502,503,504,505],{"id":28,"depth":159,"text":28},{"id":257,"depth":159,"text":257},{"id":405,"depth":159,"text":405},{"id":492,"depth":159,"text":492},"DKOM 的全称是 Direct Kernel Object Manipulation（直接内核对象操作）。它是 Windows 内核级 Rootkit（木马\u002F后门）最核心的底层技术之一","md",{"date":509,"tags":510},"2026-10-02",[511,512,513],"windows","dkom","system","\u002Fsystem\u002Fwindows\u002Fdkom开发",{"description":506},"system\u002Fwindows\u002FDKOM开发","aJdgQYbQH71BnmE2drjyfsCCc0Hqy-IhU_Jzmk3g_E8",1792775418055]