我在2013ISCC中学习WINDOWS内核驱动的编写

一、配置

1、下载DDK 点击打开链接,并进行漫长的安装。下载Windbg,这个好下载,并安装完成。

 

2、VM(这里我用的是win2003当实验机)下在Power off的情况下设置setting:Edit virtual machine settings->hardware->add->next->serial port->output to named pipe-next.

 

3、选择:Named pipe   \\.\pipe\com_1      end is the server    the other end is an application

 

4、进入虚拟机修改boot.ini,目的是在进入系统前增加一个选择debug系统的选项。

[boot loader]
timeout=30
default=multi(0)disk(0)rdisk(0)partition(1)\WINDOWS
[operating systems]
multi(0)disk(0)rdisk(0)partition(1)\WINDOWS="Windows Server 2003, Standard" /noexecute=optout /fastdetect
multi(0)disk(0)rdisk(0)partition(1)\WINDOWS="Windows Server 2003, Standard - DEBUG" /noexecute=optout /fastdetect/bootlog /debug /debugport=COM1: /baudrate=115200

 

5、打开windbg,file-> kernel debug->com,Baud Rate设置为“115200”->port设置为“\\.\pipe\com_1”->勾选reconnect ->勾选pipe -> 等虚拟机选择debug系统后确定

连接成功:

Opened \\.\pipe\com_1
Waiting to reconnect...
Connected to Windows Server 2003 3790 x86 compatible target, ptr64 FALSE
Kernel Debugger connection established.

 

6、忽视它所说的 Debuggee not connected,其实Kernel Debugger connection established出现就表示已经连接好了。

 

7、如果没有符号symbol,windbg会出现一堆error,建议配置symbol:

新建文件夹:C:\MyCodesSymbols

运行WinDbg->菜单->File->Symbol File Path

在弹出的框框中:C:\MyCodesSymbols; SRV*C:\MyLocalSymbols*http://msdl.microsoft.com/download/symbols

然后再进行第5步,就会自动下载好。

 

 

二、获取调试信息

1、在第一步中我们已经安装了ddk了,在ddk的\src\general\cancel\sys 文件夹中,有源代码,用Windows XP Checked Build  Envionment 打开,进入到sys文件目录下,运行:build,再去../exe目录下:build,然后把生成的exe文件和sys文件放到VM中。

2、在VM跑起cancel.exe,就可以看到windbg与win2003的互动。

 

三、编写简单的驱动

题目要求:作为入门,请编写一个简易的驱动程序,要求设备驱动的符号链接为ISCC2013Kernel1,每当创建一个该设备的句柄时在DbgView中输出 “create”;每次收到读写等其它控制指令时输出“other”;每当关闭一个该设备的句柄时输出“close”;卸载时输出“unload”。

 

1、驱动的符号链接

RtlInitUnicodeString(&symboliclinkname,L"\\??\\ISCC2013Kernel1");//初始化符号连接名称

//创建驱动设备符号链接
if(STATUS_SUCCESS  == IoCreateSymbolicLink(
    &symboliclinkname,//符号链接名称
    &devicename//设备名称
))
{
   DbgPrint("create a symbolicLink\n");
}

用winobj打开(成功):

我在2013ISCC中学习WINDOWS内核驱动的编写_第1张图片
 

 2、什么是IRP

 驱动程序与I/O管理器通信,使用的是IRP,即I/O请求包。IRP分为2部分:1)IRP首部;2)IRP堆栈。

在入口处声明派遣例程:

 //设置IRP派遣例程  
    theDriverObject->MajorFunction[IRP_MJ_CREATE]= 
    theDriverObject->MajorFunction[IRP_MJ_CLOSE] = 
    theDriverObject->MajorFunction[IRP_MJ_WRITE] = 
    theDriverObject->MajorFunction[IRP_MJ_READ] = 
    theDriverObject->MajorFunction[IRP_MJ_CLOSE] = 
    theDriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = myDispatch;

实现myDispatch例程:

NTSTATUS myDispatch (IN PDEVICE_OBJECT DeviceObject,IN PIRP pIrp)  
{  
    NTSTATUS ntStatus=STATUS_SUCCESS;  
    PIO_STACK_LOCATION IrpStack=NULL;   //IRP堆栈  
    ULONG IoControlCodes=0;             //I/O控制代码  

    //设置IRP状态  
    pIrp->IoStatus.Status=STATUS_SUCCESS;  
    pIrp->IoStatus.Information=0;  


    IrpStack=IoGetCurrentIrpStackLocation(pIrp);    //得到当前调用者的IRP  

    switch (IrpStack->MajorFunction)  
    {  
            case IRP_MJ_CREATE:  
                 #ifdef DEBUGMSG  
                        DbgPrint("create\n");  
                 #endif  
                 break;  

            case IRP_MJ_CLOSE:  
                 #ifdef DEBUGMSG  
                        DbgPrint("close\n");  
                 #endif  
                 break;  

            default:  
                 DbgPrint("other\n");
                 break;  
    }  

    ntStatus=pIrp->IoStatus.Status;  
    IoCompleteRequest(pIrp,IO_NO_INCREMENT);//返回IO管理器IRP报文  

    return ntStatus;  
}  

 

全部代码:

SOURCES:

TARGETNAME=FirstDriver  
TARGETPATH=OBJ              
TARGETTYPE=DRIVER        
SOURCES=mydriver.c

MAKEFILE:

!INCLUDE $(NTMAKEENV)\makefile.def

源代码:

#include <ntddk.h>


NTSTATUS myDispatch (IN PDEVICE_OBJECT DeviceObject,IN PIRP pIrp);
VOID MyUnload(IN PDRIVER_OBJECT DriverObject0);

NTSTATUS DriverEntry(IN PDRIVER_OBJECT theDriverObject,
                     IN PUNICODE_STRING theRegistryPath)
{
		PDEVICE_OBJECT mydevice;//定义设备对象
		UNICODE_STRING devicename;//定义设备名称
		UNICODE_STRING symboliclinkname;//定义符号连接名称
		RtlInitUnicodeString(&devicename,L"\\Device\\mydevice");//初始化设备名称
		RtlInitUnicodeString(&symboliclinkname,L"\\??\\ISCC2013Kernel1");//初始化符号连接名称
		//创建常规的设备对象
		if(STATUS_SUCCESS == IoCreateDevice(
				theDriverObject,//驱动对象
				0,
				&devicename,//设备名称
				FILE_DEVICE_UNKNOWN,//类型
				0,
				FALSE,
				&mydevice//设备对象
		))
		{
				DbgPrint("create a device\n");
		}
		
		//创建驱动设备符号链接
		if(STATUS_SUCCESS  == IoCreateSymbolicLink(
				&symboliclinkname,//符号链接名称
				&devicename//设备名称
		))
		{
				DbgPrint("create a symbolicLink\n");
		}
	
		
    theDriverObject->DriverUnload = MyUnload;
    
    //设置IRP派遣例程和卸载例程  
    theDriverObject->MajorFunction[IRP_MJ_CREATE]= 
    theDriverObject->MajorFunction[IRP_MJ_CLOSE] = 
    theDriverObject->MajorFunction[IRP_MJ_WRITE] = 
    theDriverObject->MajorFunction[IRP_MJ_READ] = 
    theDriverObject->MajorFunction[IRP_MJ_CLOSE] = 
    theDriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = myDispatch;
    

    return STATUS_SUCCESS;
}

NTSTATUS myDispatch (IN PDEVICE_OBJECT DeviceObject,IN PIRP pIrp)  
{  
    NTSTATUS ntStatus=STATUS_SUCCESS;  
    PIO_STACK_LOCATION IrpStack=NULL;   //IRP堆栈  
    ULONG IoControlCodes=0;             //I/O控制代码  

    //设置IRP状态  
    pIrp->IoStatus.Status=STATUS_SUCCESS;  
    pIrp->IoStatus.Information=0;  


    IrpStack=IoGetCurrentIrpStackLocation(pIrp);    //得到当前调用者的IRP  

    switch (IrpStack->MajorFunction)  
    {  
            case IRP_MJ_CREATE:  
                        DbgPrint("create\n");  
                 break;  

            case IRP_MJ_CLOSE:  
                        DbgPrint("close\n");
                 break;  

            default:  
            		 DbgPrint("other\n");
                 break;  
    }  

    ntStatus=pIrp->IoStatus.Status;  
    IoCompleteRequest(pIrp,IO_NO_INCREMENT);  

    return ntStatus;  
}  


VOID MyUnload(IN PDRIVER_OBJECT DriverObject0)
{
		//c语言变量一定要放最前面...
    PDEVICE_OBJECT  temp1;
		PDEVICE_OBJECT  temp2;
		UNICODE_STRING symboliclinkname;//定义符号连接名称
		
    DbgPrint("unload\n");
		RtlInitUnicodeString(&symboliclinkname,L"\\??\\ISCC2013Kernel1");//初始化连接符号
		IoDeleteSymbolicLink(&symboliclinkname);//删除符号连接
		if(DriverObject0)
		{
				temp1=DriverObject0->DeviceObject;
				//删除设备链表
				while(temp1)
				{
					temp2=temp1;
					temp1=temp1->NextDevice;
					IoDeleteDevice(temp2);//删除设备
					DbgPrint("upload a decive...\n");
				}
 		}
}


晕,第一天竟然没过,然后找Danny大神问了下,发现是:

   #ifdef DEBUGMSG  
                        DbgPrint("close\n");  
                 #endif  
出错了,应该把预编译#ifdef DEBUGMSG 和 #endif去掉,哎,我太小白了。

因为#ifdef 是条件编译,只有满足该条件时,才会编译,也就是说,当DEBUGMSG被定义过,这段代码才会被编译。

而我前面没有定义过DEBUGMSG,所以就跪了。

然后就顺利PASS,,,



学习资料:

驱动程序简单入门
菜鸟也写驱动程序
驱动程序简单入门(另一篇)
DriverEntry 派遣函数

 

四、找出隐藏进程

参考资料:
其实不用刻意找,baidu,gooogle下:XPGetKiWaitListHead    检测隐藏进程,出来一大堆,都是对某篇俄罗斯文的译文。
然后俄罗斯文中出现的一些定义,发现TM找不到,在某个机遇巧合下,找到了以下这个driver.c文件,里面就是对俄罗斯文的译文的定义的补充。
http://read.pudn.com/downloads108/sourcecode/unix_linux/446619/src/driver/driver.c__.htm

 驱动牛逼例子,有各种定义

要打印出进程名字,首先得知道PEPROCESS结构中名字是什么吧?本人试了下ProcessName之类都不好使,

只能认真地找一个PEPROCESS数据结构定义,找了半天,感觉上在某个文件中有,但是好难找,不知道哪个文件有。

和内核有关吧,只知道这点。。。

终于在看雪找到了定义:

typedef struct _EPROCESS
{
  KPROCESS Pcb;  //+0x000 Pcb              : _KPROCESS
  DWORD ProcessLock;    //+0x06c ProcessLock      : _EX_PUSH_LOCK
  LARGE_INTEGER CreateTime;    //+0x070 CreateTime       : _LARGE_INTEGER
  LARGE_INTEGER ExitTime;      //+0x078 ExitTime         : _LARGE_INTEGER
  DWORD RundownProtect;  //+0x080 RundownProtect   : _EX_RUNDOWN_REF
  DWORD UniqueProcessId;  //+0x084 UniqueProcessId  : Ptr32 Void
  LIST_ENTRY  ActiveProcessLinks;  //+0x088 ActiveProcessLinks : _LIST_ENTRY
  DWORD QuotaUsage[3];  //+0x090 QuotaUsage       : [3] Uint4B
  DWORD QuotaPeak[3];    //+0x09c QuotaPeak        : [3] Uint4B
  DWORD CommitCharge;    //+0x0a8 CommitCharge     : Uint4B
  DWORD PeakVirtualSize;  //+0x0ac PeakVirtualSize  : Uint4B
  DWORD VirtualSize;    //+0x0b0 VirtualSize      : Uint4B
  LIST_ENTRY  SessionProcessLinks;  //+0x0b4 SessionProcessLinks : _LIST_ENTRY
  PVOID DebugPort;    //+0x0bc DebugPort        : Ptr32 Void
  PVOID ExceptionPort;  //+0x0c0 ExceptionPort    : Ptr32 Void
  DWORD ObjectTable;    //+0x0c4 ObjectTable      : Ptr32 _HANDLE_TABLE
  DWORD Token;      //+0x0c8 Token            : _EX_FAST_REF
  DWORD WorkingSetLock[8];//+0x0cc WorkingSetLock   : _FAST_MUTEX
  DWORD WorkingSetPage;  //+0x0ec WorkingSetPage   : Uint4B
  DWORD AddressCreationLock[8];  //+0x0f0 AddressCreationLock : _FAST_MUTEX
  DWORD HyperSpaceLock;  //+0x110 HyperSpaceLock   : Uint4B
  PVOID ForkInProgress;  //+0x114 ForkInProgress   : Ptr32 _ETHREAD
  DWORD HardwareTrigger;  //+0x118 HardwareTrigger  : Uint4B
  PVOID VadRoot;      //+0x11c VadRoot          : Ptr32 Void
  PVOID VadHint;      //+0x120 VadHint          : Ptr32 Void
  PVOID CloneRoot;    //+0x124 CloneRoot        : Ptr32 Void
  DWORD NumberOfPrivatePages;  //+0x128 NumberOfPrivatePages : Uint4B
  DWORD NumberOfLockedPages;  //+0x12c NumberOfLockedPages : Uint4B
  PVOID Win32Process;      //+0x130 Win32Process     : Ptr32 Void
  PVOID Job;          //+0x134 Job              : Ptr32 _EJOB
  PVOID SectionObject;    //+0x138 SectionObject    : Ptr32 Void
  PVOID SectionBaseAddress;  //+0x13c SectionBaseAddress : Ptr32 Void
  PVOID QuotaBlock;      //+0x140 QuotaBlock       : Ptr32 _EPROCESS_QUOTA_BLOCK
  PVOID WorkingSetWatch;    //+0x144 WorkingSetWatch  : Ptr32 _PAGEFAULT_HISTORY
  PVOID Win32WindowStation;  //+0x148 Win32WindowStation : Ptr32 Void
  PVOID InheritedFromUniqueProcessId;  // +0x14c InheritedFromUniqueProcessId : Ptr32 Void
  PVOID LdtInformation;    // +0x150 LdtInformation   : Ptr32 Void
  PVOID VadFreeHint;      // +0x154 VadFreeHint      : Ptr32 Void
  PVOID VdmObjects;      // +0x158 VdmObjects       : Ptr32 Void
  PVOID DeviceMap;      // +0x15c DeviceMap        : Ptr32 Void
  LIST_ENTRY PhysicalVadList;  // +0x160 PhysicalVadList  : _LIST_ENTRY
  QWORD PageDirectoryPte;    // +0x168 PageDirectoryPte : _HARDWARE_PTE
  PVOID Session;        //+0x170 Session          : Ptr32 Void
  char ImageFileName[16];    //+0x174 ImageFileName    : [16] UChar
  LIST_ENTRY JobLinks;  //+0x184 JobLinks         : _LIST_ENTRY
  PVOID LockedPagesList;    //+0x18c LockedPagesList  : Ptr32 Void
  LIST_ENTRY  ThreadListHead;  //+0x190 ThreadListHead   : _LIST_ENTRY
  PVOID SecurityPort;      //+0x198 SecurityPort     : Ptr32 Void
  PVOID PaeTop;        //+0x19c PaeTop           : Ptr32 Void
  DWORD ActiveThreads;    //+0x1a0 ActiveThreads    : Uint4B
  DWORD GrantedAccess;    //+0x1a4 GrantedAccess    : Uint4B
  DWORD DefaultHardErrorProcessing;  //+0x1a8 DefaultHardErrorProcessing : Uint4B
  DWORD LastThreadExitStatus;  //+0x1ac LastThreadExitStatus : Int4B
  PPEB Peb;          //+0x1b0 Peb              : Ptr32 _PEB
  PVOID PrefetchTrace;    //+0x1b4 PrefetchTrace    : _EX_FAST_REF
  LARGE_INTEGER ReadOperationCount;  //+0x1b8 ReadOperationCount : _LARGE_INTEGER
  LARGE_INTEGER WriteOperationCount;  //+0x1c0 WriteOperationCount : _LARGE_INTEGER
  LARGE_INTEGER OtherOperationCount;  //+0x1c8 OtherOperationCount : _LARGE_INTEGER
  LARGE_INTEGER ReadTransferCount;  //+0x1d0 ReadTransferCount : _LARGE_INTEGER
  LARGE_INTEGER WriteTransferCount;  //+0x1d8 WriteTransferCount : _LARGE_INTEGER
  LARGE_INTEGER OtherTransferCount;  //+0x1e0 OtherTransferCount : _LARGE_INTEGER
  DWORD CommitChargeLimit;  //+0x1e8 CommitChargeLimit : Uint4B
  DWORD CommitChargePeak;    //+0x1ec CommitChargePeak : Uint4B
  PVOID AweInfo;        //+0x1f0 AweInfo          : Ptr32 Void
  DWORD SeAuditProcessCreationInfo;  //+0x1f4 SeAuditProcessCreationInfo : _SE_AUDIT_PROCESS_CREATION_INFO
  DWORD Vm[16];        //+0x1f8 Vm               : _MMSUPPORT
  DWORD LastFaultCount;    //+0x238 LastFaultCount   : Uint4B
  DWORD ModifiedPageCount;  //+0x23c ModifiedPageCount : Uint4B
  DWORD NumberOfVads;      //+0x240 NumberOfVads     : Uint4B
  DWORD JobStatus;      //+0x244 JobStatus        : Uint4B
  DWORD Flags;        //+0x248 Flags            : Uint4B
  DWORD ExitStatus;      //+0x24c ExitStatus       : Int4B
  WORD NextPageColor;      //+0x250 NextPageColor    : Uint2B
  //BYTE SubSystemMinorVersion;  //+0x252 SubSystemMinorVersion : UChar
  //BYTE SubSystemMajorVersion;  //+0x253 SubSystemMajorVersion : UChar
  WORD SubSystemVersion;      //+0x252 SubSystemVersion : Uint2B
  BYTE PriorityClass;        //+0x254 PriorityClass    : UChar
  BYTE WorkingSetAcquiredUnsafe;  //+0x255 WorkingSetAcquiredUnsafe : UChar
  DWORD Cookie;          //+0x258 Cookie           : Uint4B
} EPROCESS,*PEPROCESS;

找到了这个PEPROCESS定义后,发现要用ImageFileName。

在打印ImageFileName的时候,失败了:1>mydriver.c(123) : error C2037: left of 'ImageFileName' specifies undefined struct/union '_EPROCESS'

苦逼啊,据说是MS很多细节没公开,导致只好硬编码啦(以下是xp pro sp2编译通过):

VOID PrintCurrentProcess()
{
  char szImageFileName[16] = {0};    // EPROCESS的UCHAR ImageFileName[ 16 ]含结束符
  PEPROCESS pCurrentProcess = PsGetCurrentProcess();
  memcpy(szImageFileName, (char *)pCurrentProcess + 0x174, 16);
  KdPrint(("%s EPROCESS: %08x\n", szImageFileName, pCurrentProcess));
}


查表得:UniqueProcessId 是+0x84,因为是DWORD,取出来的内存,我把它放到UCHAR[4]中,要逆序以下,然后再转成DWORD。。

这里要有大端小端的注意点!!!搞了本人半天的。。

int chars2ULONG(UCHAR* a)
{
	 return a[0]+a[1]*(1<<8)+a[2]*(1<<16)+a[3]*(1<<24);
}



MAKEFILE:

!INCLUDE $(NTMAKEENV)\makefile.def

SOURCES:

TARGETNAME=ThirdDriver  
TARGETPATH=OBJ              
TARGETTYPE=DRIVER        
SOURCES=mydriver.c\
           ldasm.c\

其中引入了ldasm.c 和 ldasm.h 和list.h 文件

贴出来代码太长了,下载吧,少年:点击打开链接



代码:

其实主要就是:

XPGetKiWaitListHead();

XPGetKiDispatcherReadyListHead();

ProcessListHead(KiWaitInListHead);

PrintList(KiWaitInListHead);

#include <ntddk.h>
#include <ldasm.h>
#include <list.h>
#include <stdio.h>
#include <winkernel.h>
#include <NTSTATUS.H>

VOID MyUnload(IN PDRIVER_OBJECT DriverObject0);


PLIST_ENTRY KiWaitInListHead;
PLIST_ENTRY KiDispatcherReadyListHead;
void XPGetKiWaitListHead();
void XPGetKiDispatcherReadyListHead();

ULONG  WaitProcOffset = 0x1C0;   
void _stdcall CollectProcess(PEPROCESS pEPROCESS);
void ProcessListHead(PLIST_ENTRY ListHead);
void PrintList();
ULONG flag[1024];
int isExist(ULONG *flag,ULONG x);

PProcessList wLastItem = NULL; 



NTSTATUS DriverEntry(IN PDRIVER_OBJECT theDriverObject,
                     IN PUNICODE_STRING theRegistryPath)
{	
    theDriverObject->DriverUnload = MyUnload;
    
   	XPGetKiWaitListHead();
   	XPGetKiDispatcherReadyListHead();
   	ProcessListHead(KiWaitInListHead);
   	ProcessListHead(KiDispatcherReadyListHead);
   	
   	PrintList();
   	
    return STATUS_SUCCESS;
}

VOID MyUnload(IN PDRIVER_OBJECT DriverObject0)
{
    return;
}


void XPGetKiWaitListHead()
{
   PUCHAR cPtr, pOpcode;
   ULONG Length;

   for (cPtr = (PUCHAR)KeDelayExecutionThread;
        cPtr < (PUCHAR)KeDelayExecutionThread + PAGE_SIZE;
             cPtr += Length)
   {
      Length = SizeOfCode(cPtr, &pOpcode);

      if (!Length) break;

      if (*(PUSHORT)cPtr == 0x03C7 && *(PUSHORT)(pOpcode + 6) == 0x4389)
      {
         KiWaitInListHead = *(PLIST_ENTRY *)(pOpcode + 2);
         break;
      }
   }

   return;
}

void XPGetKiDispatcherReadyListHead()
{
   PUCHAR cPtr, pOpcode;
   PUCHAR CallAddr = NULL;
   ULONG Length;
   for (cPtr = (PUCHAR)KiDispatchInterrupt;
        cPtr < (PUCHAR)KiDispatchInterrupt + PAGE_SIZE;
             cPtr += Length)
   {
      Length = SizeOfCode(cPtr, &pOpcode);
      if (!Length) return;
      if (*pOpcode == 0xE8 && *(PUSHORT)(pOpcode + 5) == 0x01B1)
      {
         CallAddr = (PUCHAR)(*(PULONG)(pOpcode + 1) + (ULONG)cPtr + Length);
         break;
      }
   }
   if (!CallAddr || !MmIsAddressValid(CallAddr)) return;
   for (cPtr = CallAddr; cPtr < CallAddr + PAGE_SIZE; cPtr += Length)
   {
      Length = SizeOfCode(cPtr, &pOpcode);
      if (!Length) return;
      if (*(PUSHORT)pOpcode == 0x148D && *(pOpcode + 2) == 0xCD && IsRelativeCmd(pOpcode + 7))
      {
         KiDispatcherReadyListHead = *(PLIST_ENTRY *)(pOpcode + 3);
         break;
      }
   }
   return;
}

void ProcessListHead(PLIST_ENTRY ListHead)
{	 
   PLIST_ENTRY Item;
	  
   if (ListHead)
   {
      Item = ListHead->Flink;

      while (Item != ListHead)
      {
         CollectProcess(*(PEPROCESS *)((ULONG)Item + WaitProcOffset));
         Item = Item->Flink;         
      }
   }
   return;
}

int isExist(ULONG *flag,ULONG x)
{
		int i=0;
		for(i=0;i<1024;i++)
		{
				if(flag[i] == x)
					return 1;
		}
		return 0;
}


int chars2ULONG(UCHAR* a)
{
	 return a[0]+a[1]*(1<<8)+a[2]*(1<<16)+a[3]*(1<<24);
}

void PrintList()
{
	  PProcessList temp = wLastItem;
	  PEPROCESS p;
	  PUCHAR szImageFileName;
	  ULONG UniqueProcessId;
	  UCHAR TMP[4]={0};
		int count = 0;
		memset(flag,0,sizeof(flag));
		
		while (temp)     //遍历链表
		{  
			  if (temp->pEPROCESS)
				{
				    szImageFileName = (PUCHAR)((unsigned int)(temp->pEPROCESS) + 0x174);
				    memcpy(TMP,(PUCHAR)((unsigned int)(temp->pEPROCESS) + 0x084),4);
	          UniqueProcessId = chars2ULONG(TMP);
				    //if(0 == isExist(flag,UniqueProcessId))
	         	{
	         			flag[count++] = UniqueProcessId;
	         			DbgPrint("ProcessName = %s ,ProcessID = %ld\n",szImageFileName,UniqueProcessId);
 					 	}				   
				}
				temp = temp->NextItem;
		}
		DbgPrint("Count is :%d\n",count);
}

void _stdcall CollectProcess(PEPROCESS pEPROCESS)   
{   
    if (!IsAdded(wLastItem, pEPROCESS)) 
    	AddItem(&wLastItem, pEPROCESS);  
    return;   
}   
    

这个被驳回了,理由是无法列举全部进程,原因是这样子,我的代码只检查了两个状态的链:等待、就绪,实际上进程还有转换啊,备用啊等状态,比如说你打开一个记事本,但是什么不要动它,只要保证它没运行任何代码,那么它就不会被检测出来,而隐藏进程一定运行着代码,所以一定会被检测出来。

看来只能换个思路了:HandleTable枚举进程!

#include <ntddk.h>
#include <ldasm.h>
#include <list.h>
#include <stdio.h>
#include <winkernel.h>
#include <NTSTATUS.H>

VOID MyUnload(IN PDRIVER_OBJECT DriverObject0);


PLIST_ENTRY HandleTableListHead;



ULONG  WaitProcOffset = 0x1C0;   
void _stdcall CollectProcess(PEPROCESS pEPROCESS);
void ProcessListHead(PLIST_ENTRY ListHead);

void PrintList();
ULONG flag[1024];
int isExist(ULONG *flag,ULONG x);

PProcessList wLastItem = NULL; 

void GetHandleTableListHead();
PVOID GetInfoTable(ULONG ATableType);
void ScanHandleTablesList();

ULONG HandleTableOffset=0xc4;
ULONG HandleTableListOffset=0x01C;//win2000为0x054
ULONG QuotaProcessOffset = 0x04;//win2000为0x00c



NTSTATUS DriverEntry(IN PDRIVER_OBJECT theDriverObject,
                     IN PUNICODE_STRING theRegistryPath)
{	
    theDriverObject->DriverUnload = MyUnload;
    
    GetHandleTableListHead();
    ScanHandleTablesList();
    PrintList();
   	
    return STATUS_SUCCESS;
}

VOID MyUnload(IN PDRIVER_OBJECT DriverObject0)
{
    return;
}

PVOID GetInfoTable(ULONG ATableType)
{
   ULONG mSize = 0x4000;
   PVOID mPtr = NULL;
   NTSTATUS St;
   do
   {
      mPtr = ExAllocatePool(PagedPool, mSize);
      memset(mPtr, 0, mSize);
      if (mPtr)
      {
         St = ZwQuerySystemInformation(ATableType, mPtr, mSize, NULL);
      } else return NULL;
      if (St == STATUS_INFO_LENGTH_MISMATCH)
      {
         ExFreePool(mPtr);
         mSize = mSize * 2;
      }
   } while (St == STATUS_INFO_LENGTH_MISMATCH);
   if (St == STATUS_SUCCESS) return mPtr;
   ExFreePool(mPtr);
   return NULL;
}

void GetHandleTableListHead()
{
   PSYSTEM_MODULE_INFORMATION_EX Info = GetInfoTable(SystemModuleInformation);
   ULONG NtoskrnlBase = (ULONG)Info->Modules[0].Base;
   ULONG NtoskrnlSize = Info->Modules[0].Size;
   PHANDLE_TABLE HandleTable = *(PHANDLE_TABLE *)((ULONG)PsGetCurrentProcess() + HandleTableOffset);
   PLIST_ENTRY HandleTableList = (PLIST_ENTRY)((ULONG)HandleTable + HandleTableListOffset);
   PLIST_ENTRY CurrTable;

   ExFreePool(Info);

   for (CurrTable = HandleTableList->Flink;
        CurrTable != HandleTableList;
        CurrTable = CurrTable->Flink)
   {
      if ((ULONG)CurrTable > NtoskrnlBase && (ULONG)CurrTable < NtoskrnlBase + NtoskrnlSize)
      {
         HandleTableListHead = CurrTable;
         break;
      }
   }   
}

void ScanHandleTablesList()
{
   PLIST_ENTRY CurrTable;
   PEPROCESS QuotaProcess;
	   
   if (HandleTableListHead)
   {
      CurrTable = HandleTableListHead->Flink;;;

      while (CurrTable != HandleTableListHead)
      {
         QuotaProcess = *(PEPROCESS *)((PUCHAR)CurrTable - HandleTableListOffset + QuotaProcessOffset);
      	 if (QuotaProcess) CollectProcess(QuotaProcess);
         CurrTable = CurrTable->Flink;         
      }
   }
   return;
}


void ProcessListHead(PLIST_ENTRY ListHead)
{	 
   PLIST_ENTRY Item;
	  
   if (ListHead)
   {
      Item = ListHead->Flink;

      while (Item != ListHead)
      {
         CollectProcess(*(PEPROCESS *)((ULONG)Item + WaitProcOffset));
         Item = Item->Flink;         
      }
   }
   return;
}

int isExist(ULONG *flag,ULONG x)
{
		int i=0;
		for(i=0;i<1024;i++)
		{
				if(flag[i] == x)
					return 1;
		}
		return 0;
}


int chars2ULONG(UCHAR* a)
{
	 return a[0]+a[1]*(1<<8)+a[2]*(1<<16)+a[3]*(1<<24);
}

void PrintList()
{
	  PProcessList temp = wLastItem;
	  PEPROCESS p;
	  PUCHAR szImageFileName;
	  ULONG UniqueProcessId;
	  UCHAR TMP[4]={0};
		int count = 0;
		memset(flag,0,sizeof(flag));
		
		while (temp)     //遍历链表
		{  
			  if (temp->pEPROCESS)
				{
				    szImageFileName = (PUCHAR)((unsigned int)(temp->pEPROCESS) + 0x174);
				    memcpy(TMP,(PUCHAR)((unsigned int)(temp->pEPROCESS) + 0x084),4);
	          UniqueProcessId = chars2ULONG(TMP);
				    //if(0 == isExist(flag,UniqueProcessId))
	         	{
	         			flag[count++] = UniqueProcessId;
	         			DbgPrint("ProcessName = %s ,ProcessID = %ld\n",szImageFileName,UniqueProcessId);
 					 	}				   
				}
				temp = temp->NextItem;
		}
		DbgPrint("Count is :%d\n",count);
}

void _stdcall CollectProcess(PEPROCESS pEPROCESS)   
{   
    if (!IsAdded(wLastItem, pEPROCESS)) 
    	AddItem(&wLastItem, pEPROCESS);  
    return;   
}   
    

但是还是少了两个进程:system 和 system ldle process,理由在某个博客上找到了:空闲进程是无法用HandleTable枚举出来的。。

空闲进程无法检测出来,这个还是达不到要求。。

换种思路:


五、“凭空”出现的指令

题目:SOURCES没搞好,导致出现了以下的指令:

函数头处
.text:00011D7B mov eax, ___security_cookie
.text:00011D80 xor eax, ebp
.text:00011D82 mov [ebp+var_28], eax

函数尾处
.text:000120D9 mov ecx, [ebp+var_28]
.text:000120DC xor ecx, ebp ; cookie
.text:000120DE call @__security_check_cookie@4


.text:0001310F @__security_check_cookie@4 proc near
.text:0001310F
.text:0001310F cookie = ecx
.text:0001310F cmp cookie, ___security_cookie
.text:00013115 jnz short failure
.text:00013117 retn 0

SOURCES文件详解,半点没用!!!详解连这个参数都找不到。。。

BUFFER_OVERFLOW_CHECKS=0 
各种找不到,只能在炮哥的提示下找到:

SOURCES:

# $Id$
TARGETNAME=usbsamp
TARGETTYPE=PROGRAM

_NT_TARGET_VERSION= $(_NT_TARGET_VERSION_WINXP)

USE_MSVCRT=1


UMTYPE=console
UMBASE=0x01000000

# Create browse info
#BROWSER_INFO=1
#BROWSERFILE=<some path>

# Additional defines for the C/C++ preprocessor
C_DEFINES=$(C_DEFINES)

# If you uncomment the following line, the linker will not use buffer overflow
# checking for the entry point and so on. Leave it commented if possible.
#BUFFER_OVERFLOW_CHECKS=0

INCLUDES=$(DDK_INC_PATH);$(CRT_INC_PATH);$(SDK_INC_PATH);$(IFSKIT_INC)	\
		..\..\usbsamp_new\usbsamp_new


TARGETLIBS=D:\WINDDK\7600.16385.1\lib\wxp\i386\usbd.lib	\
          D:\WINDDK\7600.16385.1\lib\wxp\i386\setupapi.lib

SOURCES=      \
        testapp.c  \
        testapp.rc


你可能感兴趣的:(我在2013ISCC中学习WINDOWS内核驱动的编写)