kmodule.c
上传用户:nobole
上传日期:2013-04-01
资源大小:481k
文件大小:21k
源码类别:

进程与线程

开发平台:

Visual C++

  1. // This module hooks the internals r thread's swapcontext 
  2. // in order to enumerate all running threads (and processes)
  3. // in the system. This is intended to detect some hidden processes
  4. // by rootkits (like fu), etc.
  5. //
  6. // This is proof-of-concept software, and no warranty is given
  7. // Use at your own risk.
  8. //
  9. // wowocock, there@citiz.net, 2005
  10. //
  11. #ifdef ALLOC_DATA_PRAGMA
  12.   #pragma data_seg("PAGE")
  13. #endif
  14. #include <ntddk.h>
  15. #include <windef.h>
  16. typedef PVOID *PPVOID;
  17. #include "w2k_def_jr.h"
  18. const WCHAR devLink[]  = L"\??\Myklister";
  19. const WCHAR devName[]  = L"\Device\Myklister";
  20. #include "kmodule.h"
  21. ServiceTableInfo SrvTables[MAX_SERVICETABLES];//kmodule.h
  22. DWORD nSrvTables = 0;
  23. KLISTER_PROCINFO procs[MAX_PROCS];//kmodule.h
  24. ULONG gOsMajorVersion = 0;
  25. ULONG gOsMinorVersion = 0;
  26. /*线程所在进程
  27. lkd>dt _ETHREAD
  28. +000 struct _KTHREAD Tcb
  29. +034 struct _KAPC_STATE ApcState
  30. +044 struct _KPROCESS *Process
  31. +22c struct _EPROCESS *ThreadsProcess
  32. KTHREAD 偏移 +044 处的 KPROCESS *Process ,是指向线程所在进程的 KPROCESS 结构的指针。
  33. KTHREAD 偏移 +22c 处的 EPROCESS *ThreadsProcess ,是指向线程所在进程的 EPROCESS 结构的指针。
  34. 我们 KPROCESS 结构在 EPROCESS 结构中,并且位于 EPROCESS 结构开始处。+044 *Process 和 
  35. +22c *ThreadsProcess 指向的是同一地址。
  36. */
  37. DWORD gThreadsProcessOffset =0x44;//
  38. DWORD gCidOffset =0;
  39. DWORD gNprocs = 0;
  40. PEPROCESS gDeletedEProcess = NULL;//typedef struct _EPROCESS  w2k_def_jr.h
  41. PEPROCESS gBakDeletedEProcess = NULL;
  42. #define SYSNAME "System"
  43. #define IS_WINDOWS2000() 
  44. ((gOsMajorVersion == 5) && (gOsMinorVersion == 0))//??
  45. #define IS_WINDOWSXP() 
  46. ((gOsMajorVersion == 5) && (gOsMinorVersion == 1))
  47. #define IS_WINDOWSXP_OR_LATER() 
  48. (((gOsMajorVersion == 5) && (gOsMinorVersion >= 1)) || 
  49. (gOsMajorVersion > 5))
  50. #define IS_WINDOWSDOTNET_OR_LATER() 
  51. (((gOsMajorVersion == 5) && (gOsMinorVersion >= 2)) || 
  52. (gOsMajorVersion > 5))
  53. NTKERNELAPI//?????????????????
  54. NTSTATUS
  55. NTAPI
  56. PsLookupThreadByThreadId (
  57.         IN PVOID        UniqueThreadId,
  58.         OUT PETHREAD    *Thread
  59.         );
  60. NTSTATUS PsLookupProcessByProcessId(IN ULONG ulProcId, OUT PEPROCESS * pEProcess);
  61. void insertProc (PKLISTER_PROCINFO obAddr);
  62. void deleteProc (PEPROCESS obAddr);
  63. ULONG ProcessNameOffset = 0;///////////////////?????
  64. ULONG GetProcessNameOffset()// 得到进程名位 <<内核级HOOK的几种实现与应用>>
  65. {
  66. PEPROCESS curproc;
  67. int i;
  68. curproc = PsGetCurrentProcess();//PsGetCurrentProcess returns a pointer to the process of the current thread
  69. //
  70. // Scan for 12KB, hopping the KPEB never grows that big!
  71. //
  72. for( i = 0; i < 3*PAGE_SIZE; i++ ) {
  73.   if( !strncmp( SYSNAME, (PCHAR) curproc + i, strlen(SYSNAME) )) {//#define SYSNAME "System"
  74.    return i;//返回
  75.   }
  76. }
  77. //
  78. // Name not found - oh, well
  79. //
  80. return 0;
  81. }
  82. ///////////////////////////////////////////////////////////////////
  83. //说明:
  84. //ProcessData is the function that gets the required data from the _KTHREAD, _ETHREAD and _EPROCESS structures and stores the data in a separate chaining hash table. 
  85. //I am using the threads virtual memory address as the key to the hash table (first I used the thread ID, however in theory one could modify a malicious thread to have the same ID as some non-malicious thread) and a thread is only inserted once during its lifetime. Because I use the threads memory address as the key I have to make sure that the entry is removed from the table when the thread is terminated since a new thread can be allocated to the same memory address. When a thread is terminating it signals this by setting the Terminated flag in the CrossThreadFlags entry which is part of the _ETHREAD structure. The ProcessData function looks like this:
  86. void __stdcall ProcessData(DWORD * pEthread)//请查看xfocus:<<Detecting Hidden Processes by Hooking the SwapContext Function>>
  87. {
  88. // NOTICE: WinDbg gives offsets in BYTEs, we use DWORDS
  89. DWORD * pEprocess = (DWORD *)*(DWORD *)((PUCHAR)pEthread+gThreadsProcessOffset);//(pEthread->ThreadsProcess);
  90. DWORD * pCid = (DWORD *)((PUCHAR)pEthread+gCidOffset);//&(pEthread->Cid);
  91. DWORD key;
  92. KLISTER_PROCINFO data;
  93. DbgPrint("ProcessDatan");//jution
  94.     /*PETHREAD pethread = (PETHREAD)pEthread;
  95. DWORD * ServiceTable =(DWORD *)pethread->Tcb.pServiceDescriptorTable->ntoskrnl.ServiceTable;
  96. DWORD nServiceLimit = pethread->Tcb.pServiceDescriptorTable->ntoskrnl.ServiceLimit;*/
  97. /*insertServTable ((int)*(pCid+1);,
  98.   (int)pEthread->Tcb.pServiceDescriptorTable->ntoskrnl.ServiceTable,
  99.   (int)pEthread->Tcb.pServiceDescriptorTable->ntoskrnl.ServiceLimit);*/
  100.     if(gDeletedEProcess!= NULL)
  101. {
  102.   gBakDeletedEProcess = gDeletedEProcess;
  103.   deleteProc(gDeletedEProcess);
  104.   gDeletedEProcess = NULL;
  105.   return;
  106. }
  107. if((DWORD*)gBakDeletedEProcess == pEprocess) return;
  108. // FIXME: A thread could be hidden by setting threadsProcess or CID
  109. // field as NULL!
  110. if (pEprocess != NULL && pCid != NULL)
  111. {
  112.   data.obAddr =  (DWORD)pEprocess;
  113.   data.pid = *(pCid);
  114.   data.tid = *(pCid+1);
  115.   //data.imageName = (pEprocess->ImageFileName);
  116.   //strncpy(data.imageName,pEprocess->ImageFileName,16);
  117.   strncpy(data.name,((PUCHAR)pEprocess+ProcessNameOffset),16);
  118.   DbgPrint("pID:%08x tID:%8x %sn",data.pid,data.tid,data.name);
  119.   insertProc(&data);
  120.   // The thread is terminated so remove it from the
  121.   // hashtable.
  122.   /*if (*(pEthread + offsets.crossThreadFlags) & 1)
  123.   {
  124.   Remove(key, pHashTable);
  125.   }
  126.   else
  127.   {
  128.   Insert(key, &data, pHashTable);
  129.   }*/
  130. }
  131. }
  132. PBYTE GoBackAddr = NULL;
  133. PBYTE ChangAddr = NULL;
  134. PBYTE CallContextAddr = NULL;
  135. DWORD CallContextOffset = 0;
  136. __declspec(naked) VOID HookSwap()/////请查看pjf的《线程调度的监视》
  137. { DbgPrint("HookSwap()n");//jution ok
  138. _asm 
  139. {
  140.   pushad
  141.    pushfd
  142.    cli
  143. }
  144. DbgPrint("Switch out!n");//jution  ????????????
  145. _asm
  146. {
  147.   // EDI holds the thread whose context we will switch out.
  148.   push edi
  149.    call ProcessData
  150. }
  151. DbgPrint("Switch in!n");//jution
  152. _asm
  153. {
  154.   // ESI holds the thread whose context we will switch in.
  155.   push esi
  156.    call ProcessData
  157. }
  158. _asm 
  159. {  
  160.   sti
  161.    popfd
  162.    popad
  163. }
  164. _asm jmp DWORD PTR[GoBackAddr]
  165. }
  166. NTSYSAPI WORD NtBuildNumber;
  167. PCHAR GetSwapAddr()
  168. {
  169. PCHAR res = 0;
  170. NTSTATUS  Status;
  171. PETHREAD Thread;
  172. if (NtBuildNumber <= 2195)
  173. Status = PsLookupThreadByThreadId((PVOID)4, &(PETHREAD)Thread);
  174. else
  175. Status = PsLookupThreadByThreadId((PVOID)8, &(PETHREAD)Thread);
  176. if (NT_SUCCESS(Status))
  177. {
  178. if (MmIsAddressValid(Thread))
  179. {
  180. res = (PCHAR)(Thread->Tcb.KernelStack);
  181.  if(IS_WINDOWSDOTNET_OR_LATER())
  182.  res = (PCHAR)*(DWORD*)((PCHAR)Thread+0x20);//add for win2003 Tcb.KernelStack
  183. }
  184. if (MmIsAddressValid(res+8))
  185. //res = *(PULONG(res+8));
  186. {
  187. _asm
  188. {
  189. mov eax,res
  190. add eax,8
  191. mov eax,[eax]
  192. mov res,eax
  193. }
  194. }
  195. else
  196. {
  197. res = 0;
  198. return NULL;
  199. }
  200. }
  201.    
  202. _asm
  203. {
  204. mov eax,res
  205. sub eax,5
  206. mov ChangAddr,eax
  207. mov edx,[eax+1]
  208. mov CallContextOffset,edx
  209. add eax,edx
  210. add eax,5
  211. mov GoBackAddr,eax
  212. mov res,eax
  213. }
  214. return res;
  215. }
  216. BOOL  HookSwapFunction(BOOL flag)
  217. {DbgPrint("HookSwapFunction()n");//jution
  218. if (flag == TRUE)/////////////////
  219. KIRQL OldIrql=0;
  220. DWORD NewOffset;//HookSwap-ChangAddr-5;
  221. _asm
  222. {
  223. mov eax,HookSwap
  224.     mov edx,ChangAddr
  225.     sub eax,edx
  226.     sub eax,5
  227.     mov NewOffset,eax
  228.   }
  229.   DbgPrint("HookSwapFunction333");//jution
  230. PAGED_CODE()
  231. ASSERT(KeGetCurrentIrql()<=DISPATCH_LEVEL);
  232. KeRaiseIrql(2,&OldIrql);//HIGH_LEVEL
  233.  //Bug Check 0x50: PAGE_FAULT_IN_NONPAGED_AREA
  234. //The PAGE_FAULT_IN_NONPAGED_AREA bug check has a value of 0x00000050. This indicates that invalid system memory has been referenced.
  235. //驱动程序通过调用ExAllocatePool获得的非页式系统空间内存
  236.  _asm
  237.   {
  238.    mov eax,ChangAddr
  239.   push NewOffset//??????????????????????????????????????????????????????????????????????
  240.  pop dword ptr[eax+1]//??????????????????????????????????????????????????????????????????????
  241. //mov edx,NewOffset
  242. // mov dword ptr[eax+1],edx//????????????????????????????
  243.  }
  244. KeLowerIrql(OldIrql);
  245. }
  246. //Bug Check 0xD1: DRIVER_IRQL_NOT_LESS_OR_EQUAL
  247. else
  248.   KIRQL OldIrql=0;
  249.   KeRaiseIrql(2,&OldIrql);///HIGH_LEVEL
  250.   _asm
  251.   {
  252.    mov eax,ChangAddr
  253.     push CallContextOffset
  254.     pop dword ptr[eax+1]
  255.   }
  256.   KeLowerIrql(OldIrql);
  257.   DbgPrint("HookSwapFunctionFALSE");//jution
  258. }
  259. }
  260. void insertProc (PKLISTER_PROCINFO pdata)
  261. {
  262. DWORD i;
  263. KIRQL OldIrql=0;
  264. if( gNprocs >= MAX_PROCS)
  265.   return;
  266. KeRaiseIrql(2,&OldIrql);////提升当前IRQL,防止被中断;
  267. DbgPrint("insertProc");//jution
  268. for (i = 0; i < gNprocs; i++)
  269.   if (procs[i].obAddr == pdata->obAddr) return;
  270. procs [gNprocs].pid = pdata->pid;
  271. procs [gNprocs].tid = pdata->tid;
  272. procs [gNprocs].obAddr = pdata->obAddr;
  273. strncpy (procs [gNprocs].name, pdata->name, 16);
  274. gNprocs++;
  275. KeLowerIrql(OldIrql);
  276. }
  277. void deleteProc (PEPROCESS obAddr)
  278. {
  279. DWORD i;
  280. KIRQL OldIrql=0;
  281. if( gNprocs == 0)
  282.   return;
  283. DbgPrint("deleteProc");//jution
  284. KeRaiseIrql(2,&OldIrql);
  285. for (i = 0; i < gNprocs; i++)
  286.   if (procs[i].obAddr == (int)obAddr) 
  287.   {
  288.    procs [i].pid = 0;
  289.    procs [i].tid = 0;
  290.    procs [i].obAddr = 0;
  291.    RtlZeroMemory (procs [i].name, 16);
  292.    break;
  293.   }
  294.   if(i == gNprocs) return;
  295.     memmove(&procs[i],&procs[i+1],(gNprocs-i-1)*sizeof(KLISTER_PROCINFO));
  296. procs [gNprocs-1].pid = 0;
  297. procs [gNprocs-1].tid = 0;
  298. procs [gNprocs-1].obAddr = 0;
  299. RtlZeroMemory (procs [gNprocs-1].name, 16);
  300. gNprocs--;
  301. KeLowerIrql(OldIrql);
  302. }
  303. void insertServTable (int tid, int addr, int n) {// DWORD addr jution change
  304. DWORD i;
  305. DbgPrint("insertServTable");//jution
  306. for (i = 0; i < nSrvTables; i++)
  307.   if (SrvTables[i].addr==addr) {///d:ntddkjutionkilsterkmodule.c(328) : warning C4018: '==' : signed/unsigned mismatch
  308.   
  309.   // we ignore buffer overflow here ;)
  310. //   if (SrvTables[i].nthreads < MAX_THREADS)
  311. //    SrvTables[i].threads[SrvTables[i].nthreads] = tid;
  312.    
  313.    SrvTables[i].n = n;
  314.    SrvTables[i].nthreads++;
  315.    return;
  316.   }
  317. SrvTables[nSrvTables].addr = addr;
  318. SrvTables[i].n = n;
  319. //SrvTables[nSrvTables].threads[0] = tid;
  320. SrvTables[nSrvTables].nthreads = 1;
  321. nSrvTables++;
  322. }
  323. PEPROCESS processObject (PETHREAD ethread) {
  324. return  (PEPROCESS)(ethread->Tcb.ApcState.Process);
  325. }
  326. /*
  327. char* processName (PEPROCESS eprocess) {
  328. return &eprocess->ImageFileName[0];
  329. }
  330. */ 
  331. void createProcList () {
  332. int i;
  333.     PVOID obj;
  334. PETHREAD pethread;
  335. gNprocs = 0;
  336. nSrvTables = 0;
  337. DbgPrint("createProcList");//jution
  338. /*for (obj = pKiWaitInListHead->Flink;
  339.   obj && obj != pKiWaitInListHead; obj = ((PLIST_ENTRY)obj)->Flink) {
  340.    pethread = (PETHREAD) ((char*)obj - WAITLIST_OFFSET);
  341.    insertServTable ((int)pethread->Cid.UniqueThread,
  342.     (int)pethread->Tcb.pServiceDescriptorTable->ntoskrnl.ServiceTable,
  343.     (int)pethread->Tcb.pServiceDescriptorTable->ntoskrnl.ServiceLimit);
  344.    insertProc (processObject (pethread));
  345. }
  346. for (obj = pKiWaitOutListHead->Flink;
  347.   obj && obj != pKiWaitOutListHead; obj = ((PLIST_ENTRY)obj)->Flink) {
  348.    pethread = (PETHREAD) ((char*)obj - WAITLIST_OFFSET);
  349.    insertServTable ((int)pethread->Cid.UniqueThread,
  350.     (int)pethread->Tcb.pServiceDescriptorTable->ntoskrnl.ServiceTable,
  351.     (int)pethread->Tcb.pServiceDescriptorTable->ntoskrnl.ServiceLimit);
  352.    insertProc (processObject (pethread));
  353. }
  354. for (i = 0; i < 32; i++) 
  355.    for (obj = pKiDispatcherReadyListHead[i].Flink;
  356.      obj != &pKiDispatcherReadyListHead[i];
  357.      obj = ((PLIST_ENTRY)obj)->Flink) {
  358.       
  359.      pethread = (PETHREAD) ((char*)obj - WAITLIST_OFFSET);
  360.      insertServTable ((int)pethread->Cid.UniqueThread,
  361.       (int)pethread->Tcb.pServiceDescriptorTable->ntoskrnl.ServiceTable,
  362.       (int)pethread->Tcb.pServiceDescriptorTable->ntoskrnl.ServiceLimit);
  363.      insertProc (processObject (pethread));
  364.            
  365.     
  366.      }*/
  367.   
  368. }
  369. PIDTGATE readIDT() {
  370. IDTR idtr;
  371. __asm {
  372.   sidt idtr;
  373. }
  374. return(PIDTGATE) idtr.base;
  375. }
  376. NTSTATUS klisterDeviceControl(
  377.     IN PDEVICE_OBJECT pDeviceObject,
  378.     IN ULONG IoControlCode, 
  379.     IN PVOID pInputBuffer, 
  380.     IN ULONG InputBufferLength, 
  381.     OUT PVOID pOutputBuffer, 
  382.     IN ULONG OutputBufferLength, 
  383.     OUT PIO_STATUS_BLOCK IoStatus
  384.     
  385.     ) 
  386. {
  387.     DWORD maxnproc, maxTbls, n, i, STn;
  388. PKLISTER_INIT pkl_init;
  389. IoStatus->Status = STATUS_SUCCESS;
  390.     IoStatus->Information = 0;
  391.     switch ( IoControlCode ) 
  392. {
  393. case IOCTL_KLISTER_INIT:
  394.   if ((InputBufferLength != sizeof(KLISTER_INIT) ) || (pInputBuffer == NULL))
  395.   {
  396.    IoStatus->Status = STATUS_INVALID_BUFFER_SIZE;
  397.    break;
  398.   }
  399.   
  400.   pkl_init = (PKLISTER_INIT) pInputBuffer;
  401.   /*pKiWaitInListHead  = (PLIST_ENTRY) pkl_init->pKiWaitInListHead_addr;
  402.   pKiWaitOutListHead  = (PLIST_ENTRY) pkl_init->pKiWaitOutListHead_addr;
  403.   pKiDispatcherReadyListHead  = (PLIST_ENTRY) pkl_init->pKiDispatcherReadyListHead_addr;
  404.   KdPrint ((" pKiWaitInListHead: %#xn", pKiWaitInListHead));
  405.   KdPrint ((" pKiWaitOutListHead: %#xn", pKiWaitOutListHead));
  406.   KdPrint ((" pKiDispatcherReadyListHead: %#xn", pKiDispatcherReadyListHead));*/
  407.   /*for (i = 0; i < MAX_PROCS; i++)
  408.    procs[i].pid = 0;*/
  409.      //RtlZeroMemory(procs,sizeof(KLISTER_PROCINFO)*MAX_PROCS);
  410.   for (i = 0; i < MAX_SERVICETABLES; i++)
  411.    SrvTables[i].addr = 0;
  412. DbgPrint("IOCTL_KLISTER_INITn");//jution
  413. break;
  414. case IOCTL_KLISTER_LISTPROC:
  415.   
  416.   if ((OutputBufferLength < sizeof (KLISTER_PROCINFO)) || (pOutputBuffer == NULL))
  417.   {
  418.    IoStatus->Status = STATUS_INVALID_BUFFER_SIZE;
  419.    break;
  420.   
  421.   }
  422.  DbgPrint("IOCTL_KLISTER_LISTPROCn");//jution
  423.           
  424.   maxnproc = OutputBufferLength/sizeof (KLISTER_PROCINFO);
  425.   //createProcList();
  426.   if (gNprocs > maxnproc)
  427.    n = maxnproc*sizeof (KLISTER_PROCINFO);
  428.   else 
  429.    n = gNprocs * sizeof (KLISTER_PROCINFO);
  430.   if (OutputBufferLength < n)
  431.   {
  432.    IoStatus->Status = STATUS_INVALID_BUFFER_SIZE;
  433.    break;
  434.   }
  435.   memcpy (pOutputBuffer, (PVOID) &procs, n);
  436.   
  437.   IoStatus->Information = n;
  438. break; 
  439. case IOCTL_KLISTER_DUMP_IDT:
  440.   if ((OutputBufferLength < sizeof (IDTGATE)*IDT_NGATES)
  441.    || (pOutputBuffer == NULL))
  442.   {
  443.    IoStatus->Status = STATUS_INVALID_BUFFER_SIZE;
  444.    break;
  445.   
  446.   }
  447.   
  448.   n = sizeof (IDTGATE) * IDT_NGATES;
  449.   memcpy (pOutputBuffer, (PVOID) readIDT(), n);
  450.   
  451.   IoStatus->Information = n;  
  452. break;
  453. case IOCTL_KLISTER_FIND_ST:
  454.   if ((OutputBufferLength < sizeof (ServiceTableInfo))
  455.    || (pOutputBuffer == NULL))
  456.   {
  457.    IoStatus->Status = STATUS_INVALID_BUFFER_SIZE;
  458.    break;
  459.   
  460.   }
  461.     
  462.   maxTbls = OutputBufferLength/sizeof(ServiceTableInfo);
  463.   createProcList();
  464.   if (nSrvTables > maxTbls) n = maxTbls*sizeof (ServiceTableInfo);
  465.   else n = nSrvTables * sizeof (ServiceTableInfo);
  466.   
  467.   memcpy (pOutputBuffer, (PVOID) SrvTables, n);
  468.   
  469.   IoStatus->Information = n;
  470. break;
  471. case IOCTL_KLISTER_DUMP_ST:
  472.   if ((InputBufferLength != sizeof(int) ) || (pInputBuffer == NULL))
  473.   {
  474.    IoStatus->Status = STATUS_INVALID_BUFFER_SIZE;
  475.    break;
  476.   }
  477.   if ((OutputBufferLength < sizeof (int))
  478.    || (pOutputBuffer == NULL))
  479.   {
  480.    IoStatus->Status = STATUS_INVALID_BUFFER_SIZE;
  481.    break;
  482.   
  483.   }
  484.   
  485.   STn = *(int*)pInputBuffer; // no of ST to dump
  486.   //KdPrint ((" STn: %#xn", STn));
  487. DbgPrint(" STn: %#xn");  //jution add
  488.   n = sizeof (int) * (SrvTables[STn].n);
  489.   KdPrint(("klister: n = %dn", n));
  490.   
  491.   n = (n > OutputBufferLength) ? OutputBufferLength : n;
  492.   KdPrint(("klister: n = %dn", n));
  493.   memcpy (pOutputBuffer, (PVOID) SrvTables[STn].addr, n);
  494.   KdPrint (("memcpy (pOutputBuffer, (PVOID) SrvTables[STn].addr, n)"));
  495.   KdPrint (("pOutputBuffer = %#xn", pOutputBuffer));
  496.   KdPrint (("SrvTables[STn].addr = %#xn", SrvTables[STn].addr));
  497.   IoStatus->Information = n;  
  498. break;
  499. default:
  500.   IoStatus->Status = STATUS_INVALID_DEVICE_REQUEST;
  501.   break;
  502. }
  503.     return IoStatus->Status;
  504. }
  505. NTSTATUS klisterDispatch(
  506.     IN PDEVICE_OBJECT pDeviceObject, 
  507.     IN PIRP pIrp 
  508.     )
  509. {
  510.     PIO_STACK_LOCATION      irpStack;
  511.     PVOID                   pInputBuffer;
  512.     PVOID                   pOutputBuffer;
  513.     ULONG                   inputBufferLength;
  514.     ULONG                   outputBufferLength;
  515.     ULONG                   ioControlCode;
  516. NTSTATUS    ntstatus;
  517.     
  518.     irpStack = IoGetCurrentIrpStackLocation (pIrp);
  519.     pInputBuffer             = pIrp->AssociatedIrp.SystemBuffer;
  520.     inputBufferLength       = irpStack->Parameters.DeviceIoControl.InputBufferLength;
  521.     pOutputBuffer            = pIrp->AssociatedIrp.SystemBuffer;
  522.     outputBufferLength      = irpStack->Parameters.DeviceIoControl.OutputBufferLength;
  523.     ioControlCode           = irpStack->Parameters.DeviceIoControl.IoControlCode;
  524.     ntstatus = pIrp->IoStatus.Status = STATUS_SUCCESS;
  525.     pIrp->IoStatus.Information = 0;
  526.     switch (irpStack->MajorFunction) {
  527.     case IRP_MJ_CREATE:
  528.         break;
  529.     case IRP_MJ_SHUTDOWN:
  530.         break;
  531.     case IRP_MJ_CLOSE:
  532.         break;
  533.     case IRP_MJ_DEVICE_CONTROL:
  534.        
  535.         ntstatus = klisterDeviceControl(
  536.    pDeviceObject, ioControlCode,
  537.    pInputBuffer, inputBufferLength, 
  538.    pOutputBuffer, outputBufferLength,
  539.    &pIrp->IoStatus);
  540.         break;
  541.     }
  542. IoCompleteRequest( pIrp, IO_NO_INCREMENT );
  543.     return ntstatus;   
  544. }
  545. VOID ProcessCreateMon ( IN HANDLE hParentId, IN HANDLE PId,IN BOOLEAN bCreate )
  546. {
  547. PEPROCESS EProcess;
  548. ULONG   ulCurrentProcessId;
  549. LPTSTR    lpCurProc;
  550. NTSTATUS  status;
  551. status = PsLookupProcessByProcessId( (ULONG)PId, &EProcess);
  552. if (!NT_SUCCESS( status ))
  553. {
  554.   DbgPrint("PsLookupProcessByProcessId()n");////根据PID得到进程名
  555.   return ;
  556. }
  557. if ( bCreate )
  558. {
  559.   lpCurProc = (LPTSTR)EProcess;
  560.   lpCurProc = lpCurProc + ProcessNameOffset;
  561.   DbgPrint( "CREATE PROCESS = PROCESS NAME: %s , PROCESS PARENTID: %d, PROCESS ID: %d, PROCESS ADDRESS %x:n", 
  562.    lpCurProc,
  563.    hParentId,
  564.    PId,
  565.    EProcess );
  566. }
  567. else
  568. {
  569.   DbgPrint( "TERMINATED == PROCESS ID: %dn", PId);
  570.   gDeletedEProcess = EProcess;
  571. }
  572. }
  573. NTSTATUS klisterUnload(IN PDRIVER_OBJECT pDriverObject)
  574. {
  575.     UNICODE_STRING          devLinkUnicd;
  576. PDEVICE_OBJECT   pObj;
  577. pObj = pDriverObject->DeviceObject;
  578. if (GoBackAddr)//PBYTE GoBackAddr = NULL;
  579.   HookSwapFunction(FALSE);
  580.      PsSetCreateProcessNotifyRoutine(ProcessCreateMon, TRUE);
  581. if (pObj != NULL)
  582. {
  583.         RtlInitUnicodeString( &devLinkUnicd, devLink );
  584.   IoDeleteSymbolicLink( &devLinkUnicd );
  585.   IoDeleteDevice( pDriverObject->DeviceObject );
  586.   return STATUS_SUCCESS;
  587. }
  588. return STATUS_SUCCESS;
  589. }
  590. NTSTATUS DriverEntry(
  591.        IN PDRIVER_OBJECT  pDriverObject,
  592.        IN PUNICODE_STRING pRegistryPath
  593.      )
  594. {
  595.     NTSTATUS                ntStatus;
  596.     UNICODE_STRING          devNameUnicd;
  597.     UNICODE_STRING          devLinkUnicd;        
  598. PDEVICE_OBJECT   pDevice;
  599.     RtlInitUnicodeString (&devNameUnicd,
  600.                           devName );//const WCHAR devName[]  = L"\Device\Myklister";
  601.     RtlInitUnicodeString (&devLinkUnicd,
  602.                           devLink );//const WCHAR devLink[]  = L"\??\Myklister";
  603. //WDM驱动程序可以调用IoCreateDevice函数创建设备对象,但设备对象的管理则由I/O管理器负责。
  604. //DriverObject(PDRIVER_OBJECT)指向与该设备对象相关的驱动程序对象,通常就是调用IoCreateDevice函数创建该设备对象的驱动程序对象。过滤器驱动程序有时需要用这个指针来寻找被过滤设备的驱动程序对象,然后查看其MajorFunction表项。
  605. ntStatus = IoCreateDevice ( pDriverObject,
  606.                                 0, 
  607.                                 &devNameUnicd,
  608.                                 FILE_DEVICE_KLISTER,//?????????
  609.                                 0,
  610.                                 TRUE,
  611.                                 &pDevice );
  612.     if( !NT_SUCCESS(ntStatus)) {
  613.   DbgPrint(("klister: cannot create device.n"));
  614.         return ntStatus;
  615. }
  616.     ntStatus = IoCreateSymbolicLink (&devLinkUnicd, &devNameUnicd);//在WDM驱动程序中创建一个符号连接,可以调用IoCreateSymbolicLink函数
  617. if( !NT_SUCCESS(ntStatus)) {
  618.   DbgPrint(("klister: cannot create symlink to device.n"));
  619.  
  620.         return ntStatus;
  621. }
  622. // else  DbgPrint(("klister:create symlink to device.n"));////////////////jution add
  623.  DbgPrint("klister:create symlink to device()n");
  624. pDriverObject->MajorFunction[IRP_MJ_SHUTDOWN]=
  625.     pDriverObject->MajorFunction[IRP_MJ_CREATE]=
  626.     pDriverObject->MajorFunction[IRP_MJ_CLOSE]=
  627.     pDriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL]  = klisterDispatch;
  628. pDriverObject->DriverUnload=klisterUnload;
  629.     //add by sjl
  630. PsGetVersion( &gOsMajorVersion,
  631.   &gOsMinorVersion,
  632.   NULL,
  633.   NULL );
  634. if(IS_WINDOWS2000())
  635. {
  636.   gThreadsProcessOffset = 0x22c;
  637.   gCidOffset = 0x1e0;
  638.   DbgPrint("IS_WINDOWS2000n");
  639. }
  640. else if(IS_WINDOWSXP())
  641. {
  642.   gThreadsProcessOffset =0x220;//////////
  643.   gCidOffset = 0x1ec;
  644. }
  645. else if(IS_WINDOWSDOTNET_OR_LATER())
  646. {
  647.   gThreadsProcessOffset =0x228;
  648.   gCidOffset = 0x1f4;
  649. }
  650. ProcessNameOffset=GetProcessNameOffset();//// 得到进程名位移
  651. GetSwapAddr();//1111111111111111
  652. DbgPrint("oooooooooooooo");
  653. if (GoBackAddr){
  654. DbgPrint("uuuuuuuu");
  655.   HookSwapFunction(TRUE);//2222222222222222
  656. }
  657. //HookSwap();
  658. else DbgPrint("jjjjjjjjjjjjjjjjjjjj");
  659. ntStatus = PsSetCreateProcessNotifyRoutine(ProcessCreateMon, FALSE);
  660. //让用户注册系统建立与删除进程或线程时调用回调函数的Fully Documented例程,
  661. //知道它们就是Mark Russinovich的NTPMON的实现的最主要的两个函数吧
  662. if (!NT_SUCCESS( ntStatus ))
  663. {
  664.   DbgPrint("PsSetCreateProcessNotifyRoutine()n");
  665.   return ntStatus;
  666. }
  667. DbgPrint("klister load succesfully1111n");
  668. KdPrint (("klister load succesfullyn"));
  669. return STATUS_SUCCESS;
  670. }
  671. //修改自KLISTER所以相关的头文件从KLISTER里找吧