欢迎来到 嗅灵易学

零基础也能上手的脚本技术课,一对一答疑带你入门

自己的kmd驱动ring0 参考的wowocock前辈的方法,做了一点注释

自己的kmd驱动ring0 参考的wowocock前辈的方法,做了一点注释

为了尊重wowocock前辈 我把wowocock的代码贴在我代码后面。
毕竟是发表我自己的吧.  在看完wowocock大哥的代码后。因为有一些地方
说得不是很明白 所以自己动手测试了一次 并自己写了一个类试的代码。
加上了比较详细的注释 希望大家看起来不费力
废话不多说了。代码开始 大家可以保存为.bat文件.调试是设置了编译器环境变量。
代码分为驱动代码 装载驱动的程序代码 和测试代码
下面为驱动部分。
;@echo off
;goto make

.386
.model flat, stdcall
option casemap:none
;>>>>>>>>>>>>>>>STRUCT>>>>>>>>>>>>>>>>>>>>>>>>>>>>
CALLGATE    STRUCT
OFFSETL    DW    0
SELECTOR    DW    0
DCOUNT    DB    0
GTYPE      DB    0
OFFSETH    DW    0
CALLGATE    ENDS
DESCRIPTOR  STRUCT
LIMITL    DW    0
BASEL      DW    0
BASEM      DB    0
ATTRIBUTES  DW    0
BASEH      DB    0
DESCRIPTOR  ENDS
;>>>>>>>>>>>>>>>>>equ>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
CODES_SEL  =  3E8H
CODE_TYPE  =  0CF9AH
GATE_TYPE  =  0ECH
.code
DriverEntry:
        pushfd
        pushad
        
        push edx
        sgdt [esp-2]
        pop edx        ;全局描述符表基地址
        mov eax,edx      ;存放全局描述符开始地址
        mov BYTE ptr [edx],0C3H 
        ;在全句描述符表开始地址
        ;存放retn指令机器码,全
        ;句描述符表第一个描述符
        ;为空表述符,被保留,没被用
        ;书上说这个描述符应该全为0
        ;这里看出 可以写东西进去。
        mov ecx,3E0h    ;定位自己的门描述符
        add edx,ecx      ;让描述位置在全局描述
        assume edx:ptr CALLGATE;符的3E0这个位置
        cmp [edx].SELECTOR,CODES_SEL
        jz ToEnd
        
        mov [edx].OFFSETL,ax      ;创建门描述符
        mov [edx].SELECTOR,CODES_SEL
        mov [edx].DCOUNT,0
        mov [edx].GTYPE,GATE_TYPE
        shr eax,16
        mov [edx].OFFSETH,ax
        ;描述符的偏移地址其实就是上面说到的
        ;那个retn指令地址,当call 这个门的时候
        ;只从堆栈弹出EIP地址,所以CS寄存器没被
        ;覆盖,所以还是ting0权限
        
        add edx,8
        assume edx:ptr DESCRIPTOR
        mov [edx].LIMITL,0FFFFH   ;创建自己的代码段描述符
        mov [edx].BASEL,0
        mov [edx].BASEM,0
        mov [edx].ATTRIBUTES,CODE_TYPE
        mov [edx].BASEH,0
ToEnd:
        popad
        popfd
        mov eax,0C0000182h
        ret 8 
        end DriverEntry
;如果设置了环境变量 就把代码直接保存为mykmd.bat 然后双击 就OK
;没有设置环境变量的可以按下面方法编译,具体编译方法不用我介绍了吧
        
:make
set drv=mykmd
ml /nologo /c /coff %drv%.bat
link /nologo /driver /base:0x10000 /align:32 /out:%drv%.sys /subsystem:native %drv%.obj
del %drv%.obj
echo.
pause

;这里开始为测试代码部分
;@echo off
;goto make
.386
.model flat, stdcall
option casemap:none
include \masm32\include\windows.inc
include \masm32\include\kernel32.inc
include \masm32\include\user32.inc
includelib \masm32\lib\user32.lib
includelib \masm32\lib\kernel32.lib
.data
szOK        db    '成功访问rc0寄存器',0
szFormat      db    'cr0=%X',0
szBuffer      db    50 dup (?)
CallGate_Sel  dd    0
          dw    03E3H  ;调用门的选择子
.code
start:
    call FWORD ptr CallGate_Sel
    
    ;进入ring0
    ;有兴趣自己也可以创建一个0级堆栈 呵呵。。
    ;我这里就用ring3的堆栈吧
    mov eax,esp  ;保存ring0堆栈
    mov esp,[esp+4] ;装入ring3堆栈地址
    ;解释下这里为什么是+4 因为call 调用门会把
    ;ss esp cs eip分别放入堆栈 在驱动程序里面
    ;已经有一句retn指令把eip弹出来了。所以这里
    ;就是加4 得到ring3堆栈地址
    
    push eax
    
    mov eax,cr0  ;ring0下才可以访问的寄存器
    
    pop esp
    ;;;开发返回ring3
    push offset ring3
    ;正如刚刚所说 已经弹出了eip地址。
    ;用retf返回肯定出错。所以还是手
    ;动帮忙来恢复堆栈 压入ring3下的
    ;代码地址吧
    retf
ring3:
    invoke  wsprintf,addr szBuffer,addr szFormat,eax
    invoke  MessageBox,0,addr szBuffer,addr szOK,0
    invoke  ExitProcess,0
    end start
:make
set drv=s
ml /nologo /c /coff %drv%.bat
link /nologo /subsystem:windows %drv%.obj
del %drv%.obj
echo.
pause
最后 前辈这里没有提到的。.装载驱动的程序。
;@echo off
;goto make
.386
.model flat, stdcall
option casemap:none
include windows.inc
include kernel32.inc
include user32.inc
include advapi32.inc
includelib kernel32.lib
includelib user32.lib
includelib advapi32.lib
.data
szError      db      '装载驱动失败',0
szOK1        db      '驱动安装成功',0
szOK        db      'OH YEAH.~~!',0
szMyWdm      db      'mykmd.sys',0
szMyWdnName    db      'mykmd',0
szBuffer      db      MAX_PATH dup (0)
hSCManager    dd      ?
hService      dd      ?
.code
start:
    invoke  OpenSCManager,NULL,NULL,SC_MANAGER_CREATE_SERVICE
    .if !eax
      invoke  MessageBox,0,addr szError,0,MB_ICONERROR or MB_OK
      jmp Err
    .endif
    mov hSCManager,eax
    push ecx
    invoke  GetFullPathName,addr szMyWdm,sizeof szBuffer,addr szBuffer,esp
    pop ecx
    invoke  CreateService,hSCManager,addr szMyWdnName,addr szMyWdm,SERVICE_START or DELETE,SERVICE_KERNEL_DRIVER,SERVICE_DEMAND_START,SERVICE_ERROR_IGNORE,addr szBuffer,0,0,0,0,0
    .if !eax
      invoke  MessageBox,0,addr szError,0,MB_ICONERROR
      jmp Err
    .endif
    mov hService,eax
    invoke  StartService, hService, 0, NULL
    invoke  DeleteService, hService
    invoke  CloseServiceHandle, hService
    invoke  CloseServiceHandle, hSCManager
    invoke  MessageBox,0,addr szOK1,addr szOK,0
Err:
    invoke  ExitProcess,0
    end start
;如果设置了环境变量 就把代码直接保存为LoadDriver.bat 然后双击 就OK
;没有设置环境变量的可以按下面方法编译,具体编译方法不用我介绍了吧
        
:make
set drv=LoadDriver
ml /nologo /c /coff %drv%.bat
link /nologo /subsystem:windows %drv%.obj
del %drv%.obj
echo.
pause
;说明下 如果用bat文件自动编译  把驱动代码改成mykmd.bat 测试代码改为s.bat  装载驱动程序代码改为LoadDriver.bat 分别双击就OK

注意:上传附件及图片大小不得大于30M。

⚠️ 版权声明:
本博客所有内容(含教程、源码、工具)仅供个人技术学习与研究交流使用,严禁商用、倒卖、二次分发及非法用途
未经作者书面授权,任何组织或个人不得转载、复制或用于其他平台,违者将追究相关责任。

0 0 0 举报
复制成功