用HOOK來修改API函數的功能(5)-EXE和WDM驅動通信
2007-07-15 03:55:31
原創作品,允許轉載,轉載時請務必以超鏈接形式標明文章 原始出處 、作者信息和本聲明。否則將追究法律責任。http://fxh7622.blog.51cto.com/63841/34136
今天我來寫關於HOOK修改API函數的最後一篇文章"EXE和WDM驅動通信"。
在上面的幾篇文章中,大家看到了被保護的文件名或者註冊表鍵值名等等都是事先指定好的。
但是在實際應用中,可能遇到的是被保護的文件名、註冊表的鍵值名需要動態來指定的情況。
這個時候就需要編寫一個上層EXE程序來和WDM驅動通信。
通常EXE和WDM驅動通信有2種方法:
1:使用DeviceIOControl函數。
2:使用自定義事件。
在這裏我簡述一下使用DeviceIOControl函數的實現方法。
首先在WDM驅動的.C文件中加入以下的宏定義代碼:
#define IOCTL_EVENT_MSG CTL_CODE(FILE_DEVICE_UNKNOWN, 0x966, METHOD_BUFFERED , FILE_ANY_ACCESS)
在DriverEntry例程中寫入:
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = MydrvDispatchIoctl;
//例程MydrvDispatchIoctl的實現如下
static NTSTATUS MydrvDispatchIoctl(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
{
PIO_STACK_LOCATION IrpStack;
NTSTATUS status,status1;
ULONG ControlCode;
ULONG InputLength,OutputLength;
TCHAR wInputBuffer[256];
TCHAR OutMsg[] = "Mess";
UNICODE_STRING *TempInstallDir=NULL;
PVOID pvIOBuffer;
char *Test;
OutputLength=sizeof(OutMsg);
// 得到當前IRP (IO請求包)
IrpStack = IoGetCurrentIrpStackLocation(Irp);
// 得到DeviceIoControl傳來的功能調用號
ControlCode = IrpStack->Parameters.DeviceIoControl.IoControlCode;
// 得到DeviceIoControl傳來的輸入緩衝區長度
InputLength = IrpStack->Parameters.DeviceIoControl.InputBufferLength;
// 得到DeviceIoControl的輸出緩衝區長度
OutputLength = IrpStack->Parameters.DeviceIoControl.OutputBufferLength;
Test=(char *)Irp->AssociatedIrp.SystemBuffer;
//使用函數DbgPrint函數將外界EXE函數傳入的信息答應出來
DbgPrint("Test=%s\n",Test);
switch (ControlCode)
{
case IOCTL_EVENT_MSG:
//得到應用程序給的參數信息。
RtlCopyMemory(Irp->AssociatedIrp.SystemBuffer, OutMsg, sizeof(OutMsg));
Irp->IoStatus.Status = STATUS_SUCCESS;
//設置返回的信息長度
OutputLength = sizeof(OutMsg);
//設置返回的信息。
Irp->IoStatus.Information = OutputLength;
break;
}
status = Irp->IoStatus.Status;
IoCompleteRequest(Irp, 0);
return status;
}
通過以上的處理,WDM驅動就具有了接收EXE傳入信息的能力。
下面我們再來看看上層EXE部分是如何編寫的:
在我的項目中,我使用VC把與WDM通信的部分寫成了一個DLL。
#include "stdafx.h"
#include "VCDll.h"
#include <Winsvc.h>
#include "winioctl.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
//注意這裏必須和WDM的宏定義部分相同
#define IOCTL_EVENT_MSG CTL_CODE(FILE_DEVICE_UNKNOWN, 0x966, METHOD_BUFFERED , FILE_ANY_ACCESS)
//參數char * SendInfo是需要傳入WDM驅動的信息
int SendToDriver(char * SendInfo)
{
hcomm=CreateFile("\\\\.\\MyDriver",GENERIC_WRITE,0,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED,NULL);
if(hcomm!=INVALID_HANDLE_VALUE)
{
char m_dwOptions[255]={'\0'};
DWORD bytesWrite;
memset(m_dwOptions,0,sizeof(m_dwOptions));
memcpy(m_dwOptions,SendInfo,strlen(SendInfo));
if(DeviceIoControl(hcomm
,IOCTL_EVENT_MSG,( char * )m_dwOptions,strlen(SendInfo)+1,( char *
)m_dwOptions, 5, &bytesWrite, NULL ))
{
CloseHandle(hcomm);
return 1;
}
else
{
CloseHandle(hcomm);
return 0;
}
}
else
{
CloseHandle(hcomm);
return -1;
}
}
通過以上的處理,WDM就和上層的EXE具有了通信的能力。
以上的5篇文章就是我在使用DDK來編寫保護文件、註冊表等等功能項目時使用到的方法。
我在這裏全寫出來就是想讓更多對這方面感興趣的朋友參與進來,和我一起交流,大家共同進步。
以上代碼通過了測試並已經長期應用到實踐中。