테스트 환경 : windows 10 x64 build 19041

이 방식은 DRIVER_OBJECT -> OBJECT_HEADER_NAME_INFO ->  OBJECT_DIRECTORY -> OBJECT_DIRECTORY_ENTRY 순서대로 구조체를 얻어온 뒤 ENTRY 체인을 끊어 목록에서 제거하는 방식입니다.

이를 위해 먼저 최상위 OBJECT_DIRECTORY 부터 살펴봅니다.

lkd> !object ffffcb83e84023c0
Object: ffffcb83e84023c0  Type: (ffffdc8a4aa9c4e0) Directory
    ObjectHeader: ffffcb83e8402390 (new version)
    HandleCount: 0  PointerCount: 58
    Directory Object: 00000000  Name: \

    Hash Address          Type                      Name
    ---- -------          ----                      ----
     01  ffffdc8a4ccfe450 Mutant                    PendingRenameMutex
         ffffcb83e8451ad0 Directory                 ObjectTypes
     02  ffffdc8a4f6ec6e0 FilterConnectionPort      storqosfltport
     04  ffffdc8a55ba1c20 FilterConnectionPort      TsFltScanPort_V3LITE40
     05  ffffdc8a55ba1670 FilterConnectionPort      TsFltCheckPort_V3LITE40
         ffffcb83e84b6520 SymbolicLink              SystemRoot
     06  ffffcb83e8cfba20 Directory                 Sessions
     08  ffffcb83e848fb80 Directory                 ArcName
     09  ffffdc8a4f6ec9a0 FilterConnectionPort      WcifsPort
         ffffcb83e84ec060 Directory                 NLS
     10  ffffdc8a4fa27760 Event                     LanmanServerAnnounceEvent
         ffffdc8a4f86baa0 ALPC Port                 ThemeApiPort
         ffffdc8a4ce59d40 Device                    UdfsCdRom
         ffffcb83e8ba5380 Directory                 Windows
         ffffcb83e8467c50 Directory                 GLOBAL??
     11  ffffcb83e8cfb2a0 Directory                 RPC Control
         ffffdc8a4c3596a0 ALPC Port                 PdcPort
     13  ffffdc8a55b87400 FilterConnectionPort      MEDSRVPOSTPORT_V3LITE40_2.13.1.63
         ffffdc8a4cd7a4e0 Event                     EFSInitEvent
     14  ffffcb83e8c68930 SymbolicLink              Dfs
         ffffdc8a4c53c870 Device                    clfs
     15  ffffdc8a4c22dc90 Event                     CsrSbSyncEvent
         ffffdc8a4c62a790 ALPC Port                 SeRmCommandPort
     16  ffffcb83e8445830 SymbolicLink              DosDevices
     17  ffffdc8a55b92450 FilterConnectionPort      MEDSRVPENDINGPORT_V3LITE40_2.13.1.63
         ffffcb83e8cfbc00 Directory                 KnownDlls32
     18  ffffdc8a55b88fa0 FilterConnectionPort      MEDSRVSENDPORT_V3LITE40_2.13.1.63
         ffffcb83e849ad20 Key                       \REGISTRY
     19  ffffcb83e8836c00 Directory                 BaseNamedObjects
     20  ffffcb83e8ec49d0 Section                   Win32kCrossSessionGlobals
         ffffdc8a4ab13df0 ALPC Port                 PowerPort
     21  ffffdc8a4f412a10 ALPC Port                 SmSsWinStationApiPort
         ffffdc8a4c22b7b0 Event                     UniqueInteractiveSessionIdEvent
         ffffcb83e84ec920 Directory                 UMDFCommunicationPorts
     22  ffffcb83e8cfb840 Directory                 KnownDlls
         ffffdc8a4cc52d40 Device                    FatCdrom
         ffffdc8a4cc53d40 Device                    Fat
         ffffdc8a4ab46df0 ALPC Port                 PowerMonitorPort
     23  ffffdc8a4c626b50 Device                    Ntfs
         ffffcb83e84ec3e0 Directory                 FileSystem
         ffffcb83e8441cc0 Directory                 KernelObjects
     26  ffffdc8a4ebebd40 ALPC Port                 SeLsaCommandPort
         ffffcb83e8451ca0 Directory                 Callback
     28  ffffdc8a4f6ec580 FilterConnectionPort      BindFltPort
         ffffdc8a4c23dc30 Event                     DSYSDBG.Debug.Trace.Memory.2bc
         ffffcb83e84588d0 Directory                 Security
     29  ffffdc8a4ce31e00 Device                    UdfsDisk
     30  ffffcb83e8490060 Directory                 Device
     32  ffffcb83e84f8190 SymbolicLink              DriverData
     34  ffffcb83ebcfe610 Section                   LsaPerformance
         ffffdc8a4c8aec70 ALPC Port                 SmApiPort
     35  ffffdc8a4f6ec4d0 FilterConnectionPort      CLDMSGPORT
         ffffcb83e84b66d0 SymbolicLink              OSDataRoot
     36  ffffdc8a4c23e9f0 Event                     SAM_SERVICE_STARTED
         ffffcb83e84ec220 Directory                 Driver
         ffffcb83e8489820 Directory                 DriverStores

저의 windows의 windbg 화면으로, OBJECT_DIRECTORY 구조체는 타입과 이름을 가지고 있습니다. 최상위 구조체라서 타입은 HANDLE을 가지고 있습니다.

우리에게 필요한 것은 드라이버 목록인데, 이는 각각 23번, 36번 인덱스 2번째에 속해 있습니다. (FileSystem, Driver) 

일반적으로 드라이버를 로딩하면 Driver의 OBJECT_DIRECTORY에 연결되므로, 36번 인덱스의 Driver만 보도록 하겠습니다. 

위 주소를 다시 구조체로 표현해봅니다.

lkd> dt !_OBJECT_DIRECTORY  ffffcb83e84023c0
nt!_OBJECT_DIRECTORY
   +0x000 HashBuckets      : [37] (null) 
   +0x128 Lock             : _EX_PUSH_LOCK
   +0x130 DeviceMap        : (null) 
   +0x138 ShadowDirectory  : (null) 
   +0x140 NamespaceEntry   : (null) 
   +0x148 SessionObject    : (null) 
   +0x150 Flags            : 0
   +0x154 SessionId        : 0xffffffff

HashBucket은 37개의 배열로 구성되어 있으며, 각각 OBJECT_DIRECTORY_ENTRY로 표현됩니다. 각 OBJECT_DIRECTORY_ENTRY체인으로 연결되어 있습니다. 

운영체제는 각각의 Name에서 Hash Index 를 계산해 각 배열에 삽입하는 방식입니다. 따라서 연결된 Entry의 갯수는 일정하지 않습니다. 

보시면 00, 03번 인덱스는 존재하지 않고, 10번의 경우 5개의 오브젝트가 존재하는데 Name에서 동일한 Hash Index가 계산된 결과입니다. (Hash인덱스를 어떻게 구하는지는 모르겠습니다. 만약 알게되면 기술하도록 하겠습니다.)

HashBucket을 눌러보면 아래와 같이 나옵니다.

lkd> dx -id 0,0,ffffdc8a4aa96040 -r1 (*((ntkrnlmp!_OBJECT_DIRECTORY_ENTRY * (*)[37])0xffffcb83e84023c0))
(*((ntkrnlmp!_OBJECT_DIRECTORY_ENTRY * (*)[37])0xffffcb83e84023c0))                 [Type: _OBJECT_DIRECTORY_ENTRY * [37]]
    [0]              : 0x0 [Type: _OBJECT_DIRECTORY_ENTRY *]
    [1]              : 0xffffcb83e8ca8b10 [Type: _OBJECT_DIRECTORY_ENTRY *]
    [2]              : 0xffffcb83ec36c2e0 [Type: _OBJECT_DIRECTORY_ENTRY *]
    [3]              : 0x0 [Type: _OBJECT_DIRECTORY_ENTRY *]
    [4]              : 0xffffcb83f4a17c00 [Type: _OBJECT_DIRECTORY_ENTRY *]
    [5]              : 0xffffcb83f4a17b70 [Type: _OBJECT_DIRECTORY_ENTRY *]
    [6]              : 0xffffcb83e8caca10 [Type: _OBJECT_DIRECTORY_ENTRY *]
    [7]              : 0x0 [Type: _OBJECT_DIRECTORY_ENTRY *]
    [8]              : 0xffffcb83e84b5060 [Type: _OBJECT_DIRECTORY_ENTRY *]
    [9]              : 0xffffcb83ebf53e70 [Type: _OBJECT_DIRECTORY_ENTRY *]
    [10]             : 0xffffcb83ec371200 [Type: _OBJECT_DIRECTORY_ENTRY *]
    [11]             : 0xffffcb83e8ca8d20 [Type: _OBJECT_DIRECTORY_ENTRY *]
    [12]             : 0x0 [Type: _OBJECT_DIRECTORY_ENTRY *]
    [13]             : 0xffffcb83ece2c4c0 [Type: _OBJECT_DIRECTORY_ENTRY *]
    [14]             : 0xffffcb83e8b80690 [Type: _OBJECT_DIRECTORY_ENTRY *]
    [15]             : 0xffffcb83e8caec90 [Type: _OBJECT_DIRECTORY_ENTRY *]
    [16]             : 0xffffcb83e84af0c0 [Type: _OBJECT_DIRECTORY_ENTRY *]
    [17]             : 0xffffcb83ece2c430 [Type: _OBJECT_DIRECTORY_ENTRY *]
    [18]             : 0xffffcb83ece2c400 [Type: _OBJECT_DIRECTORY_ENTRY *]
    [19]             : 0xffffcb83e854c2e0 [Type: _OBJECT_DIRECTORY_ENTRY *]
    [20]             : 0xffffcb83e85439d0 [Type: _OBJECT_DIRECTORY_ENTRY *]
    [21]             : 0xffffcb83e8845930 [Type: _OBJECT_DIRECTORY_ENTRY *]
    [22]             : 0xffffcb83e8ca8d80 [Type: _OBJECT_DIRECTORY_ENTRY *]
    [23]             : 0xffffcb83e855f600 [Type: _OBJECT_DIRECTORY_ENTRY *]
    [24]             : 0x0 [Type: _OBJECT_DIRECTORY_ENTRY *]
    [25]             : 0x0 [Type: _OBJECT_DIRECTORY_ENTRY *]
    [26]             : 0xffffcb83e8841160 [Type: _OBJECT_DIRECTORY_ENTRY *]
    [27]             : 0x0 [Type: _OBJECT_DIRECTORY_ENTRY *]
    [28]             : 0xffffcb83ec36cca0 [Type: _OBJECT_DIRECTORY_ENTRY *]
    [29]             : 0xffffcb83e8cad460 [Type: _OBJECT_DIRECTORY_ENTRY *]
    [30]             : 0xffffcb83e84b5630 [Type: _OBJECT_DIRECTORY_ENTRY *]
    [31]             : 0x0 [Type: _OBJECT_DIRECTORY_ENTRY *]
    [32]             : 0xffffcb83e8545a00 [Type: _OBJECT_DIRECTORY_ENTRY *]
    [33]             : 0x0 [Type: _OBJECT_DIRECTORY_ENTRY *]
    [34]             : 0xffffcb83e8841250 [Type: _OBJECT_DIRECTORY_ENTRY *]
    [35]             : 0xffffcb83ec36c430 [Type: _OBJECT_DIRECTORY_ENTRY *]
    [36]             : 0xffffcb83e8842420 [Type: _OBJECT_DIRECTORY_ENTRY *]

36번 인덱스의 주소를 구조체로 확인해봅니다.

lkd> dt _OBJECT_DIRECTORY_ENTRY 0xffffcb83e8842420
nt!_OBJECT_DIRECTORY_ENTRY
   +0x000 ChainLink        : 0xffffcb83`e8568920 _OBJECT_DIRECTORY_ENTRY
   +0x008 Object           : 0xffffdc8a`4c23e9f0 Void
   +0x010 HashValue        : 0x9b5074d

2번째에 위치해있으니 ChainLink를 따라가봅니다.

lkd> dt _OBJECT_DIRECTORY_ENTRY 0xffffcb83e8568920
nt!_OBJECT_DIRECTORY_ENTRY
   +0x000 ChainLink        : 0xffffcb83`e84b5b10 _OBJECT_DIRECTORY_ENTRY
   +0x008 Object           : 0xffffcb83`e84ec220 Void
   +0x010 HashValue        : 0x80a0801

해당 OBJECT_DIRECTORY_ENTRY에 0xffffcb83e84ec220 오브젝트가 있음을 확인할 수 있습니다. (!object 한 것과 값을 비교해보세요) 이 주소는 OBJECT_DIRECTORY 구조체로 표현됩니다.(그래서 Type명이 Directory입니다.) 이를 다시 !object로 확인해봅니다.

lkd> !object 0xffffcb83e84ec220
Object: ffffcb83e84ec220  Type: (ffffdc8a4aa9c4e0) Directory
    ObjectHeader: ffffcb83e84ec1f0 (new version)
    HandleCount: 0  PointerCount: 124
    Directory Object: ffffcb83e84023c0  Name: Driver

    Hash Address          Type                      Name
    ---- -------          ----                      ----
     00  ffffdc8a50e1eb20 Driver                    kldbgdrv
         ffffdc8a4c9a2e20 Driver                    fvevol
         ffffdc8a4c356d70 Driver                    vdrvroot
     01  ffffdc8a4cd2ee00 Driver                    usbuhci
         ffffdc8a4cc9dd40 Driver                    GpuEnergyDrv
         ffffdc8a4ca4b9e0 Driver                    NetBT
         ffffdc8a4aa3fd00 Driver                    acpiex
         ffffdc8a4aa8bde0 Driver                    Wdf01000
     02  ffffdc8a4faabb70 Driver                    mpsdrv
         ffffdc8a4c53a060 Driver                    storahci
     03  ffffdc8a51c56540 Driver                    BthEnum
         ffffdc8a4fd73e20 Driver                    MMCSS
         ffffdc8a4f924e30 Driver                    lltdio
         ffffdc8a4cbdeb40 Driver                    bam
         ffffdc8a4cc63d80 Driver                    Psched
         ffffdc8a4cb8ae40 Driver                    BasicRender
         ffffdc8a4c9c28f0 Driver                    disk
     04  ffffdc8a4facadf0 Driver                    HTTP
         ffffdc8a4c382d80 Driver                    stornvme
     05  ffffdc8a4cdbe5b0 Driver                    e1i65x64
         ffffdc8a4cb9acb0 Driver                    WscVReg
     06  ffffdc8a4f641a70 Driver                    monitor
         ffffdc8a4cdb7b50 Driver                    usbehci
         ffffdc8a4cb9a6c0 Driver                    ahcache
         ffffdc8a4cafae40 Driver                    vmrawdsk
         ffffdc8a4c9c1dc0 Driver                    iorate
         ffffdc8a4c53b640 Driver                    pcw
     07  ffffdc8a4fcd4df0 Driver                    AMonCDW8
         ffffdc8a4cde8060 Driver                    Ucx01000
         ffffdc8a4cde7060 Driver                    USBXHCI
         ffffdc8a4c359dc0 Driver                    partmgr
     08  ffffdc8a52b98e50 Driver                    AntiStealth_V3LITE40
         ffffdc8a4fd83a10 Driver                    PEAUTH
         ffffdc8a4ab88e40 Driver                    MsLldp
         ffffdc8a4cc6fa30 Driver                    Vid
         ffffdc8a4ab0cd80 Driver                    ACPI_HAL
     09  ffffdc8a4c372850 Driver                    spaceport
     10  ffffdc8a4cf1ae00 Driver                    HidUsb
         ffffdc8a4cc62dd0 Driver                    vwififlt
     11  ffffdc8a50ea0e10 Driver                    condrv
         ffffdc8a4cb9be40 Driver                    DXGKrnl
         ffffdc8a4ab35e20 Driver                    PnpManager
     12  ffffdc8a4c9c9740 Driver                    Null
         ffffdc8a4c35ca80 Driver                    vsock
         ffffdc8a4ab3be20 Driver                    intelpep
     13  ffffdc8a506c4e30 Driver                    MeDCoreD_V3LITE40
         ffffdc8a4aa81e20 Driver                    Telemetry
         ffffdc8a4aae6de0 Driver                    SoftwareDevice
     14  ffffdc8a52e98a70 Driver                    RFCOMM
         ffffdc8a4ca57e10 Driver                    Serenum
         ffffdc8a4c8ae0a0 Driver                    CLFS
         ffffdc8a4ab28e20 Driver                    WindowsTrustedRTProxy
     15  ffffdc8a4ccdae20 Driver                    Serial
         ffffdc8a4cc59d40 Driver                    NdisCap
         ffffdc8a4c8b3d30 Driver                    KSecDD
         ffffdc8a4c35bda0 Driver                    volmgr
         ffffdc8a4aaced80 Driver                    DeviceApi
     16  ffffdc8a4fcd3c90 Driver                    VMMemCtl
         ffffdc8a4ccd6e20 Driver                    umbus
         ffffdc8a4aad9c10 Driver                    MsSecFlt
         ffffdc8a4abd8cc0 Driver                    CNG
     17  ffffdc8a4ce72e20 Driver                    Win32k
         ffffdc8a4cce0dc0 Driver                    i8042prt
         ffffdc8a4cc96d70 Driver                    npsvctrig
         ffffdc8a4c9bed90 Driver                    volume
         ffffdc8a4c8b6e00 Driver                    KSecPkg
     18  ffffdc8a4cca25b0 Driver                    mouclass
     19  ffffdc8a4ea59e00 Driver                    X58a84jzGG36Q
         ffffdc8a4c53d350 Driver                    msisadrv
     20  ffffdc8a4fd79e10 Driver                    Ndu
         ffffdc8a4ccdddb0 Driver                    kbdclass
     21  ffffdc8a4c8b8e00 Driver                    mouhid
         ffffdc8a4c9bf8f0 Driver                    volsnap
     22  ffffdc8a567efe30 Driver                    MeDVpDrv_V3LITE40
         ffffdc8a4cc71dd0 Driver                    nsiproxy
         ffffdc8a4c944bd0 Driver                    AhnRghNt
         ffffdc8a4aaddd80 Driver                    WMIxWDM
     23  ffffdc8a528188f0 Driver                    BthPan
         ffffdc8a4fac3e30 Driver                    MsQuic
         ffffdc8a4cb6f9a0 Driver                    tdx
         ffffdc8a4c360a90 Driver                    vmci
     24  ffffdc8a5102ae30 Driver                    AntiStealth_V3LITE40F
         ffffdc8a52f8b570 Driver                    BTHUSB
         ffffdc8a4ab32e20 Driver                    WindowsTrustedRT
     25  ffffdc8a4cd2fde0 Driver                    HDAudBus
         ffffdc8a4cbbde40 Driver                    BasicDisplay
     26  ffffdc8a4cd62e00 Driver                    rdpbus
     27  ffffdc8a50eaca70 Driver                    Cdm2DrNt
         ffffdc8a4fcd3a70 Driver                    DBGV
         ffffdc8a4c358dc0 Driver                    pdc
     28  ffffdc8a4f92de20 Driver                    rspndr
         ffffdc8a4e14fe00 Driver                    vmusbmouse
     29  ffffdc8a4ce59670 Driver                    HdAudAddService
         ffffdc8a4cc98d60 Driver                    mssmbios
         ffffdc8a4cc97de0 Driver                    CSC
         ffffdc8a4c372d90 Driver                    volmgrx
         ffffdc8a4c536060 Driver                    pci
     30  ffffdc8a545d5e50 Driver                    ArtDrv
         ffffdc8a4cd67ce0 Driver                    NdisVirtualBus
         ffffdc8a4cdeb300 Driver                    CmBatt
         ffffdc8a4cce1e00 Driver                    vm3dmp_loader
         ffffdc8a4ccd8e20 Driver                    kdnic
         ffffdc8a4c9c1ba0 Driver                    cdrom
         ffffdc8a4c8b54e0 Driver                    NDIS
     31  ffffdc8a4cd65dc0 Driver                    swenum
     32  ffffdc8a4ce6ee30 Driver                    usbhub
         ffffdc8a4c9bfb00 Driver                    rdyboost
         ffffdc8a4c997e30 Driver                    WFPLWFS
         ffffdc8a4c8b7e00 Driver                    Tcpip
         ffffdc8a4aad9e20 Driver                    SgrmAgent
     33  ffffdc8a543a7750 Driver                    TSFltDrv_V3LITE40
         ffffdc8a4ce66cb0 Driver                    USBHUB3
         ffffdc8a4cdec940 Driver                    intelppm
         ffffdc8a4cd2fb20 Driver                    gencounter
         ffffdc8a4c162e40 Driver                    Beep
         ffffdc8a4c374410 Driver                    atapi
     34  ffffdc8a4cf18e00 Driver                    usbccgp
         ffffdc8a4cb6b9a0 Driver                    AFD
         ffffdc8a4c373c40 Driver                    mountmgr
         ffffdc8a4c365e30 Driver                    intelide
     35  ffffdc8a4e156410 Driver                    ATamptNt_V3LITE40
         ffffdc8a52bb1b70 Driver                    BTHPORT
         ffffdc8a4fd83e30 Driver                    tcpipreg
         ffffdc8a4ce32060 Driver                    ksthunk
         ffffdc8a4ccd9e30 Driver                    vmmouse
         ffffdc8a4cb6c9a0 Driver                    afunix
     36  ffffdc8a55296750 Driver                    asc_kbc_V3LITE40
         ffffdc8a4ca547b0 Driver                    vm3dmp
         ffffdc8a4cca4db0 Driver                    CompositeBus
         ffffdc8a4caf99a0 Driver                    ws2ifsl
         ffffdc8a4c64edd0 Driver                    EhStorClass
         ffffdc8a4aa954c0 Driver                    ACPI

로딩된 드라이버 목록이 나오는 것을 확인할 수 있습니다. 

위에서 언급했듯이, 각각의 Entry(1줄당 하나의 Entry, 여기서는 드라이버를 의미)는 체인으로 연결되어 있습니다. 아래 그림처럼 특정 Entry를 제거한 후 체인을 이을 수 있습니다.

33번 인덱스의 2번째인 USBHUB3를 목록에서 숨겨본다고 가정하겠습니다. 

우선 위 주소를 구조체로 표현해봅니다.

lkd> dt _OBJECT_DIRECTORY 0xffffcb83e84ec220
nt!_OBJECT_DIRECTORY
   +0x000 HashBuckets      : [37] 0xffffcb83`f16ee960 _OBJECT_DIRECTORY_ENTRY
   +0x128 Lock             : _EX_PUSH_LOCK
   +0x130 DeviceMap        : (null) 
   +0x138 ShadowDirectory  : (null) 
   +0x140 NamespaceEntry   : (null) 
   +0x148 SessionObject    : (null) 
   +0x150 Flags            : 0
   +0x154 SessionId        : 0xffffffff

HashBucket을 눌러보면 아래와 같이 나옵니다.

lkd> dx -id 0,0,ffffdc8a4aa96040 -r1 (*((ntkrnlmp!_OBJECT_DIRECTORY_ENTRY * (*)[37])0xffffcb83e84ec220))
(*((ntkrnlmp!_OBJECT_DIRECTORY_ENTRY * (*)[37])0xffffcb83e84ec220))                 [Type: _OBJECT_DIRECTORY_ENTRY * [37]]
    [0]              : 0xffffcb83f16ee960 [Type: _OBJECT_DIRECTORY_ENTRY *]
    [1]              : 0xffffcb83e8ca9a10 [Type: _OBJECT_DIRECTORY_ENTRY *]
    [2]              : 0xffffcb83ec3710b0 [Type: _OBJECT_DIRECTORY_ENTRY *]
    [3]              : 0xffffcb83f2246b20 [Type: _OBJECT_DIRECTORY_ENTRY *]
    [4]              : 0xffffcb83ec370900 [Type: _OBJECT_DIRECTORY_ENTRY *]
    [5]              : 0xffffcb83e8ca9e30 [Type: _OBJECT_DIRECTORY_ENTRY *]
    [6]              : 0xffffcb83f66bb380 [Type: _OBJECT_DIRECTORY_ENTRY *]
    [7]              : 0xffffcb83edd0bf70 [Type: _OBJECT_DIRECTORY_ENTRY *]
    [8]              : 0xffffcb83edd081f0 [Type: _OBJECT_DIRECTORY_ENTRY *]
    [9]              : 0xffffcb83e8545490 [Type: _OBJECT_DIRECTORY_ENTRY *]
    [10]             : 0xffffcb83e8568860 [Type: _OBJECT_DIRECTORY_ENTRY *]
    [11]             : 0xffffcb83efa5efd0 [Type: _OBJECT_DIRECTORY_ENTRY *]
    [12]             : 0xffffcb83e854c820 [Type: _OBJECT_DIRECTORY_ENTRY *]
    [13]             : 0xffffcb83edd05790 [Type: _OBJECT_DIRECTORY_ENTRY *]
    [14]             : 0xffffcb83f2246ac0 [Type: _OBJECT_DIRECTORY_ENTRY *]
    [15]             : 0xffffcb83e8ca8c30 [Type: _OBJECT_DIRECTORY_ENTRY *]
    [16]             : 0xffffcb83ec373fc0 [Type: _OBJECT_DIRECTORY_ENTRY *]
    [17]             : 0xffffcb83e8b809c0 [Type: _OBJECT_DIRECTORY_ENTRY *]
    [18]             : 0xffffcb83e8ca8a50 [Type: _OBJECT_DIRECTORY_ENTRY *]
    [19]             : 0xffffcb83f2245590 [Type: _OBJECT_DIRECTORY_ENTRY *]
    [20]             : 0xffffcb83ece2d4b0 [Type: _OBJECT_DIRECTORY_ENTRY *]
    [21]             : 0xffffcb83e8cae4e0 [Type: _OBJECT_DIRECTORY_ENTRY *]
    [22]             : 0xffffcb83edd05c10 [Type: _OBJECT_DIRECTORY_ENTRY *]
    [23]             : 0xffffcb83f2246eb0 [Type: _OBJECT_DIRECTORY_ENTRY *]
    [24]             : 0xffffcb83edd08c70 [Type: _OBJECT_DIRECTORY_ENTRY *]
    [25]             : 0xffffcb83e8ca9a40 [Type: _OBJECT_DIRECTORY_ENTRY *]
    [26]             : 0xffffcb83e8cab330 [Type: _OBJECT_DIRECTORY_ENTRY *]
    [27]             : 0xffffcb83edd08be0 [Type: _OBJECT_DIRECTORY_ENTRY *]
    [28]             : 0xffffcb83ec36f310 [Type: _OBJECT_DIRECTORY_ENTRY *]
    [29]             : 0xffffcb83e8cad760 [Type: _OBJECT_DIRECTORY_ENTRY *]
    [30]             : 0xffffcb83edd0cb10 [Type: _OBJECT_DIRECTORY_ENTRY *]
    [31]             : 0xffffcb83e8cab180 [Type: _OBJECT_DIRECTORY_ENTRY *]
    [32]             : 0xffffcb83e8cacda0 [Type: _OBJECT_DIRECTORY_ENTRY *]
    [33]             : 0xffffcb83edd0ced0 [Type: _OBJECT_DIRECTORY_ENTRY *]
    [34]             : 0xffffcb83e85686b0 [Type: _OBJECT_DIRECTORY_ENTRY *]
    [35]             : 0xffffcb83edd087c0 [Type: _OBJECT_DIRECTORY_ENTRY *]
    [36]             : 0xffffcb83edd0cf30 [Type: _OBJECT_DIRECTORY_ENTRY *]

33번 인덱스의 주소를 구조체로 확인해봅니다.

lkd>  dt _OBJECT_DIRECTORY_ENTRY 0xffffcb83edd0ced0
nt!_OBJECT_DIRECTORY_ENTRY
   +0x000 ChainLink        : 0xffffcb83`e8cadac0 _OBJECT_DIRECTORY_ENTRY
   +0x008 Object           : 0xffffdc8a`543a7750 Void // TSFltDrv_V3LITE40 오브젝트
   +0x010 HashValue        : 0x602bada7

2번째에 위치해있으니 ChainLink주소를 따라가봅니다.

lkd> dt _OBJECT_DIRECTORY_ENTRY 0xffffcb83`e8cadac0
nt!_OBJECT_DIRECTORY_ENTRY
   +0x000 ChainLink        : 0xffffcb83`e8caa730 _OBJECT_DIRECTORY_ENTRY
   +0x008 Object           : 0xffffdc8a`4ce66cb0 Void // USBHUB3 오브젝트
   +0x010 HashValue        : 0x19f5be6d

해당 OBJECT_DIRECTORY_ENTRY에 USBHUB3인 0xffffdc8a4ce66cb0 오브젝트에 도달한 것을 확인할 수 있습니다. 여기서 이전 Entry의 ChainLink를 USBHUB3 Entry가 가리키는 ChainLink로 변경하면 됩니다. 

이제 중요한 것은 해당 OBJECT_DIRECTORY_ENTRY에 어떻게 도달하느냐인데, DriverEntry함수의 PDRIVER_OBJECT는 Directory 타입의 "Driver"에 속해있는 유형입니다. "Driver"에 속해있는 드라이버라면 OBJECT_DIRECTORY(일종의 부모)가 동일합니다. 따라서 타 드라이버의 DRIVER_OBJECT 등을 구할 필요없이 자신의 드라이버 모듈을 Head로 사용하면 됩니다.

"Driver" 의 OBJECT_DIRECTORY에 접근하기 위해서 우선 ObQueryNameInfo함수로 OBJECT_HEADER_NAME_INFO 구조체 주소를 구해야 합니다. 해당 구조체에 OBJECT_DIRECTORY를 가리키는 필드가 있습니다.

POBJECT_HEADER_NAME_INFO pObjectHeaderNameInfo = ObQueryNameInfo(pDriverObject);
POBJECT_DIRECTORY pObjectDirectory = pObjectHeaderNameInfo->Directory;

OBJECT_DIRECTORY를 구했으면 각각의 ENTRY를 순회한 뒤 이름이 일치하면 ChainLink를 변경하는 코드를 작성합니다.

UNICODE_STRING DriverName = RTL_CONSTANT_STRING(L"USBHUB3");
for (int i = 0; i < 37; i++)
{
	POBJECT_DIRECTORY_ENTRY pBlinkObjectDirectoryEntry = NULL; // 이전 노드 저장
	POBJECT_DIRECTORY_ENTRY pObjectDirectoryEntry = pObjectDirectory->HashBuckets[i];

	while (pObjectDirectoryEntry)
	{        
		// 일치하면
		if (RtlEqualUnicodeString(DriverName, &pObjectHeaderNameInfo->Name, TRUE))
		{
			// 체인의 0번째(=헤드)가 자신의 Entry일때
			if (pObjectDirectory->HashBuckets[p] == pObjectDirectoryEntry)
			{			
				pObjectDirectory->HashBuckets[p] = pObjectDirectoryEntry->ChainLink; // 내 Entry의 다음 Entry를 헤드로 만든다.
				pObjectDirectoryEntry->ChainLink = NULL;
			}
			else // 1번째부터
			{			
				pBlinkObjectDirectoryEntry->ChainLink = pObjectDirectoryEntry->ChainLink; // 이전 Entry의 다음 Entry를 내 다음 Entry로 가리킨다.
				pObjectDirectoryEntry->ChainLink = NULL;
			}
		}
	        pBlinkObjectDirectoryEntry = pObjectDirectoryEntry;
		pObjectDirectoryEntry = pObjectDirectoryEntry->ChainLink;
	}
}

코드를 실행하여 체인 연결을 끊은 후 windbg로 확인해보면 TSFltDrv_V3LITE40의 ChainLink가 USBHUB3가 아닌 intelppm을 가리키는 것을 확인할 수 있습니다.

    33  ffffdc8a543a7750 Driver                    TSFltDrv_V3LITE40
        ffffdc8a4cdec940 Driver                    intelppm
        ffffdc8a4cd2fb20 Driver                    gencounter
        ffffdc8a4c162e40 Driver                    Beep
        ffffdc8a4c374410 Driver                    atapi
lkd> dt _OBJECT_DIRECTORY_ENTRY 0xffffcb83edd0ced0 // TSFltDrv_V3LITE40 엔트리
nt!_OBJECT_DIRECTORY_ENTRY
   +0x000 ChainLink        : 0xffffcb83`e8caa730 _OBJECT_DIRECTORY_ENTRY // intelpm 엔트리
   +0x008 Object           : 0xffffdc8a`543a7750 Void // TSFltDrv_V3LITE40 오브젝트
   +0x010 HashValue        : 0x602bada7
lkd> dt _OBJECT_DIRECTORY_ENTRY 0xffffcb83`e8cadac0
nt!_OBJECT_DIRECTORY_ENTRY
   +0x000 ChainLink        : (null) // 체인이 끊어짐
   +0x008 Object           : 0xffffdc8a`4ce66cb0 Void // USBHUB3 오브젝트
   +0x010 HashValue        : 0x19f5be6d
lkd> dt _OBJECT_DIRECTORY_ENTRY 0xffffcb83e8caa730 // intelppm 엔트리
nt!_OBJECT_DIRECTORY_ENTRY
   +0x000 ChainLink        : 0xffffcb83`e8caaa30 _OBJECT_DIRECTORY_ENTRY
   +0x008 Object           : 0xffffdc8a`4cdec940 Void // intelppm 오브젝트
   +0x010 HashValue        : 0x29f82c1

 

테스트환경 : windows 10 x64 build 19041

OBJECT_HEADER에서 OBJECT_HEADER_NAME_INFO를 어떻게 얻을까 다양한 방법으로 구글링해보다가 ObQueryNameInfo(PVOID pObject) 함수가 있다는 것을 발견했습니다. 이 함수를 쓰면 POBJECT_HEADER_NAME_INFO 주소를 리턴하더군요. 어떻게 얻나 궁금해서 windbg로 까봤습니다.

0: kd> u ObQueryNameInfo
nt!ObQueryNameInfo:
fffff803`6987b920 0fb641ea        movzx   eax,byte ptr [rcx-16h]
fffff803`6987b924 4883c1d0        add     rcx,0FFFFFFFFFFFFFFD0h
fffff803`6987b928 a802            test    al,2
fffff803`6987b92a 7416            je      nt!ObQueryNameInfo+0x22 (fffff803`6987b942)
fffff803`6987b92c 83e003          and     eax,3
fffff803`6987b92f 488d154aa55a00  lea     rdx,[nt!ObpInfoMaskToOffset (fffff803`69e25e80)]
fffff803`6987b936 0fb60410        movzx   eax,byte ptr [rax+rdx]
fffff803`6987b93a 482bc8          sub     rcx,rax
fffff803`6987b93d 488bc1          mov     rax,rcx
fffff803`6987b940 c3              ret

먼저 인자에서 0x16을 뺀것을 포인터 참조해서 저장하고, 그 다음은 0x30만큼 빼고 주소를 저장하네요. (인자로는 DRIVER_OBJECT 0xffffc28f1318ce30 를 줘봤습니다. )

일단 0x30만큼 뺀 것은 OBJECT_HADER 구조체였습니다. (대충 감으로 때려맞춤...)

kd> dt _OBJECT_HEADER 0xffffc28f1318ce30-0x30
nt!_OBJECT_HEADER
   +0x000 PointerCount     : 0n3
   +0x008 HandleCount      : 0n0
   +0x008 NextToFree       : (null) 
   +0x010 Lock             : _EX_PUSH_LOCK
   +0x018 TypeIndex        : 0x13 ''
   +0x019 TraceFlags       : 0 ''
   +0x019 DbgRefTrace      : 0y0
   +0x019 DbgTracePermanent : 0y0
   +0x01a InfoMask         : 0x2 ''
   +0x01b Flags            : 0x12 ''
   +0x01b NewObject        : 0y0
   +0x01b KernelObject     : 0y1
   +0x01b KernelOnlyAccess : 0y0
   +0x01b ExclusiveObject  : 0y0
   +0x01b PermanentObject  : 0y1
   +0x01b DefaultSecurityQuota : 0y0
   +0x01b SingleHandleEntry : 0y0
   +0x01b DeletedInline    : 0y0
   +0x01c Reserved         : 0xffffc28f
   +0x020 ObjectCreateInfo : 0x00000000`00000001 _OBJECT_CREATE_INFORMATION
   +0x020 QuotaBlockCharged : 0x00000000`00000001 Void
   +0x028 SecurityDescriptor : 0xffffb20d`a6735cee Void
   +0x030 Body             : _QUAD

0x16만큼 뺀것은 +0x1A에 위치해 있는 InfoMask 필드네요. InfoMask & 2 가 참이면 InfoMask & 3을 하여 index로 사용합니다. (예제에서는 2 & 3 = 2(index))

그 다음으로 ObpInfoMaskToOffset 에서 index를 사용하여 오프셋을 꺼내옵니다.

(BYTE*)ObpInfoMaskToOffset(0xfffff803`69e25e80) + index(2) (예제는 fffff803`69e25e82가 되겠군요.)

2: kd> db fffff803`69e25e80
fffff803`69e25e80  00 20 20 40 10 30 30 50-20 40 40 60 30 50 50 70  .  @.00P @@`0PPp
fffff803`69e25e90  10 30 30 50 20 40 40 60-30 50 50 70 40 60 60 80  .00P @@`0PPp@``.
fffff803`69e25ea0  10 30 30 50 20 40 40 60-30 50 50 70 40 60 60 80  .00P @@`0PPp@``.
fffff803`69e25eb0  20 40 40 60 30 50 50 70-40 60 60 80 50 70 70 90   @@`0PPp@``.Ppp.
fffff803`69e25ec0  10 30 30 50 20 40 40 60-30 50 50 70 40 60 60 80  .00P @@`0PPp@``.
fffff803`69e25ed0  20 40 40 60 30 50 50 70-40 60 60 80 50 70 70 90   @@`0PPp@``.Ppp.
fffff803`69e25ee0  20 40 40 60 30 50 50 70-40 60 60 80 50 70 70 90   @@`0PPp@``.Ppp.
fffff803`69e25ef0  30 50 50 70 40 60 60 80-50 70 70 90 60 80 80 a0  0PPp@``.Ppp.`...

OBJECT_HEADER 주소에서 꺼내온 0x20(OBJECT_HEADER_NAME_INFO 구조체 사이즈)만큼 빼고 해당 주소를 리턴합니다.

예제는 0xffffc28f1318ce00 - 0x20 = 0xffffc28f1318cde0

kd> dt _OBJECT_HEADER_NAME_INFO 0xffffc28f1318cde0
nt!_OBJECT_HEADER_NAME_INFO
   +0x000 Directory        : 0xffffb20d`a66ec5a0 _OBJECT_DIRECTORY
   +0x008 Name             : _UNICODE_STRING "KernelV"
   +0x018 ReferenceCount   : 0n0
   +0x01c Reserved         : 0

잘 얻어졌습니다.

ObpInfoMaskToOffset는 0x100개의 배열이며, 직접 생성할 수도 있습니다. (아래의 소스에 자세히 나와있습니다.)

github.com/hfiref0x/WinObjEx64/blob/master/Source/WinObjEx64/kldbg.c

 

 

드라이버를 서비스 형태로 등록한 경우 DRIVER_OBJECT가 할당되며, 이 구조체로부터 드라이버 정보가 담긴 LDR_DATA_TABLE_ENTRY 구조체에 다다를 수 있다.

hidusb.sys를 샘플로 잡고 windbg에서 DRIVER_OBJECT 구조체를 살펴보면 0x28 오프셋에 DriverSection이 있는데 이는 LDR_DATA_TABLE_ENTRY 구조체를 가리킨다.

0x0 오프셋 구조체에 다음&이전 드라이버의 구조체 주소가 담겨있다.

다음&이전 구조체를 가리키는 Flink, Blink는 LDR_DATA_TABLE_ENTRY로 표현된다.

아래와 같이 Flink 값의 구조체를 살펴보면 다음 드라이버를 가리키는 것을 확인할 수 있다.

여기서, 숨기고자 하는 드라이버의 Flink와 Blink를 자신의 LDR_DATA_ENTRY를 가리키게 하고, 이전 드라이버 구조체의 Flink 를 다음 드라이버 구조체의 Blink와 이으면 LDR_DATA_TABLE_ENTRY 트레버싱이나 ZwQuerySystemInformation()의 드라이버 목록에서 사라지게 된다.

PLDR_DATA_TABLE_ENTRY PsLoadedModuleList;
void GetPsLoadedModuleList(PLDR_DATA_TABLE_ENTRY currentEntry)
{
	while (TRUE)
	{
		if (NULL == currentEntry->DllBase)
		{		
			PsLoadedModuleList = currentEntry;
			break;
		}
		currentEntry = (PLDR_DATA_TABLE_ENTRY)currentEntry->InLoadOrderLinks.Flink;
	}
}
void HideDriver(PCWSTR szFileName)
{
	PLDR_DATA_TABLE_ENTRY prevEntry, nextEntry, Entry;
	Entry = (PLDR_DATA_TABLE_ENTRY)PsLoadedModuleList->InLoadOrderLinks.Flink;
	
	while (Entry != PsLoadedModuleList)
	{
		if (0 == wcscmp((PCWSTR)Entry->BaseDllName.Buffer, szFileName))
		{
			prevEntry = (PLDR_DATA_TABLE_ENTRY)Entry->InLoadOrderLinks.Blink; // 이전 노드
			nextEntry = (PLDR_DATA_TABLE_ENTRY)Entry->InLoadOrderLinks.Flink; // 다음 노드
			prevEntry->InLoadOrderLinks.Flink = Entry->InLoadOrderLinks.Flink; // 이전 노드의 다음을 내 다음으로 바꿈
			nextEntry->InLoadOrderLinks.Blink = Entry->InLoadOrderLinks.Blink; // 다음 노드의 이전을 내 이전로 바꿈 
			// 내 노드의 앞, 뒤를 나 자신으로 바꿈
			// 바꾸지 않는다면 드라이버 서비스를 stop할때 BSOD발생 (KERNEL SECURITY CHECK FAILURE)
			Entry->InLoadOrderLinks.Flink = (PLIST_ENTRY)Entry;
			Entry->InLoadOrderLinks.Blink = (PLIST_ENTRY)Entry;
			break;
		}	
		
		Entry = (PLDR_DATA_TABLE_ENTRY)Entry->InLoadOrderLinks.Flink;
	}
}
NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObject, PUNICODE_STRING pRegistryPath)
{
	UNREFERENCED_PARAMETER(pRegistryPath);
	pDriverObject->DriverUnload = DriverUnload;
	PLDR_DATA_TABLE_ENTRY pCurrentTableEntry = (PLDR_DATA_TABLE_ENTRY)pDriverObject->DriverSection;
	GetPsLoadedModuleList(pCurrentTableEntry);
	HideDriver(L"hidusb.sys");
 }

보통 64비트에서 드라이버를 로드하려면 코드서명을 하거나 TEST모드(bcdedit.exe를 이용한)로의 부팅이 필요합니다.

하지만 DSE을 익스플로잇 함으로서 코드서명 없이 드라이버를 로드할 수 있습니다.

소개 및 다운로드 :: https://github.com/hfiref0x/DSEFix

필자 테스트 환경 : Windows 10 Pro (10.0.18363) 64비트 / Visual Studio 2019 + WDK version 1903

1. 프로젝트 속성 페이지에서 드라이버 서명 모드를 Off로 합니다.

2. 관리자 권한으로 DSEFix.exe를 실행합니다.

3. OSRLOADER로 드라이버를 로드합니다. (Browse -> Register Service -> Start Service)

다운로드 : http://www.osronline.com/article.cfm%5Earticle=157.htm

DebugView에서 로그가 잘 찍혔습니다.

만약 DSEFix가 정상적으로 실행되지 않았다면, 드라이버 로드 시 아래와 같은 에러 메시지가 발생합니다.

익스플로잇 이후 블루스크린이 발생할 수 있습니다.

 

 

본 포스팅을 따라하시면 손쉽게 VS2010에서 64비트 WDK를 개발하실 수 있습니다.

시스템 변수를 추가하는데 1,2,3 순서대로 클릭한 후 그림과 같이 새 시스템 변수를 입력합니다. (자신의 경로명에 맞게)

지금부터 프로젝트를 생성하여 빌드를 할건데 귀찮으신 분은 아래 프로젝트 파일로 테스트 해 보시길 바랍니다. 

sample 프로젝트 다운로드  

sample.zip

 

Visual Studio 2010을 실행하여 메이크파일 프로젝트를 생성합니다.

 

빌드 명령줄을 화면과 같이 입력합니다.

 

속성 페이지에서 포함 디렉토리에 그림과 같은 경로를 추가합니다. (자신의 경로에 맞게)

라이브러리 디렉토리도 추가해야 하는데 c:\WinDDK\7600.16385.1\lib\win7\i386 한 줄 추가합니다.

이제 빌드를 위해 필수 3가지 파일을 준비합니다.

ddkbuild.cmd

MAKEFILE

SOURCES

 

파일들을 자신의 프로젝트의 sample.vcxproj가 있는 디렉토리에 복사 후 SOURCES 파일을 열어 TARGETNAME과 SOURCES를 자신의 환경에 맞게 설정합니다.

빌드가 잘 되는지 테스트 합니다.

이제 asm을 추가할 차례입니다.

프로젝트 디렉토리에 AMD64 디렉토리를 생성합니다.

(필자의 경로 : D:\source\sample\sample\amd64)

SOURCES 파일에 아래 한 줄을 추가합니다.

AMD64_SOURCES=func.asm

프로젝트에서 func.asm을 생성 후 다음과 같이 입력합니다.

작성한 asm을 C에서 연동해봅니다.

빌드가 잘 되는지 테스트 합니다. 

 

이제 실제 머신에서 잘 동작하는지 테스트합니다.

드라이버 서명

원칙적으로는 64비트에서는 서명되지 않은 드라이버를 서비스에 등록할 수 없습니다.

하지만 OSR Loader + Driver Signature Enforcement Overrider (이하 DSEO) 툴 조합으로 이를 해결할 수 있습니다.

OSR Loader (AMD64 용) 다운로드OSRLOADER.exe

DSEO 다운로드dseo13b.exe

DSEO의 Sign a System File을 이용하여 sys를 서명합니다.

서명한 파일을 OSRLOADER로 실행하면 됩니다.

(만약 동작하지 않는다면 DSEO에서 Enable Test Mode로 설정하시기 바랍니다.)

 VC++에서는 문자열을 다룰 때 char나 wchar_t 로 선언합니다.

그러나 드라이버 개발을 하다보면 STRING이나 UNICODE_STRING 로 선언된 것을 많이 볼 수 있는데요.

특이하게도 문자열을 구조체로 표현합니다.

각각 길이, 최대 길이(NULL을 포함하는), 문자열 포인터를 표현합니다.

DbgPrint에서 구조체를 직접 출력할 수 있는 특이점이 있습니다. 아래 %wZ 출력을 확인해 주세요.

문자열의 초기화는 RtlInitUnicodeString()를 사용하며, 아래와 같이 PSEUDO 코드를 작성할 수 있습니다.

UnicodeString->Buffer = 초기화 문자열;

UnicodeString->Length = wcslen(초기화 문자열) ;
UnicodeString->MaximumLength = UnicodeString->Length + sizeof(UNICODE_NULL) ;

아래 코드는 동적으로 할당 및 해제 하는 방법입니다. Buffer만 동적으로 할당하니 결국 malloc()과 같다고 볼 수 있습니다.

이번에는 메모리 동적 할당에 대해 알아보겠습니다.

Ring3에서는 동적으로 메모리를 할당할 때 malloc이나 HeapAlloc 같은 함수를 사용해보셨을겁니다.

그러나 드라이버에서는 이 함수를 사용할 수 없습니다.

그럼 어떻게 동적 메모리를 생성할 수 있을까요?

커널엔 메모리 풀이라는 것이 있는데 이것이 커널모드 힙입니다.

커널에서 힙을 할당하기 위해선 ExAllocatePool 이라는 함수를 사용합니다.

주목해볼만한건 인자로 NonPagedPool을 주었는데요. 인자 값으로 아래 두가지가 있습니다.

NonPagedPool : 항상 메모리에 존재

PagedPool : 페이지 아웃 혹은 인이 될 수 있음

페이지 아웃이 되면 공포의 BSoD가 뜨겠죠? 그것을 방지하기 위해서 NonPagedPool을 인자로 주어야 합니다.

 

잘 뜹니다~

주의하실 점은 동적 메모리를 반드시 해제해 주어야 합니다. 안그러면 커널 메모리에서 둥둥 떠다닙니다~

저는 WDK를 처음 접하고 코딩을 했을때, Ring3 어플리케이션에서 쓰이는 printf, malloc 같은 함수들을 사용하지 못해서 적잖이 당황한 기억이 있습니다.

그래서 WDK관련 책들을 샀는데, 입문자가 보기엔 너무 생소하고 난해한 용어들이 많아 바로 책을 덮어버렸습니다.

책을 덮고.. 독자적으로 여러 소스들을 분석하여 얻은 결론 하나, 내부 동작 원리에 대해 잘 몰라도 개발할 수 있다는 것입니다.

물론 심도있는 개발을 위해 전부 필요한 내용이지만, 일단 진입장벽부터 넘어야 하지 않겠습니까?

우선 들어가기 전에 이 글을 읽는 대상은..

1. Ring3 에서 c/c++ 기반 시스템 프로그래밍 개발 가능한 분

2. 윈도우즈 동작 메커니즘에 대해 어느정도 이해하고 계신 분

3. 위의 두가지 조건에 충족하며 드라이버 제작을 처음으로 해보시려는 분

따라서 아주 기초적이고 구구절절한 내용은 생략합니다.

그럼, 아주 심플한 제작부터 시작해보겠습니다.

드라이버 제작에 앞서 필수적인 파일 2가지가 있습니다. 아래 두가지 파일을 작성 후 프로젝트 폴더에 저장하면 됩니다.

MAKEFILE

!INCLUDE $(NTMAKEENV)\makefile.def

SOURCES

TARGETNAME=simple
TARGETPATH=.\sys
TARGETTYPE=DRIVER
SOURCES=simple.c

그 다음, simple.c를 작성합니다.

 

정말로 이렇게 심플한 코드가 실행이 될까요? 책에선 드라이버 스택이 어쩌고 저쩌고.. 익스텐션이 어쩌고저쩌고..

뭐 일단, 빌드를 해 봅니다.

 

 

빌드된 sys는 \sys\i386 경로에 있을 것 입니다. (xp로 빌드한 경우) 그럼 이 드라이버를 커널에 올려 봅시다.

드라이버를 상주시키는 파일은 구글에서 instdrv로 검색하시면 나옵니다. 로깅 뷰어는 DebugView를 사용하면 됩니다.

 

 

짜잔~ 실행이 되었군요. VC++ 로 작성하였던 내용과 별반 다르지 않군요.

이제부터 이 내용을 뼈대삼아 살을 붙여나갈 예정입니다.

 

+ Recent posts