-
-
[求助]关于《寒江独钓》键盘过滤的一个困扰
-
发表于: 2012-10-16 09:41 5615
-
最近在看寒江独钓键盘过滤章节,刚涉入内核编程领域。各种困惑 ,很是无奈....
刚看到书上说当发生按键时,触发0x93号中断例程,在该中断例程会调用i8042prt驱动中的I8042keyboardInterruptService,在该函数中最终会调用 kbdclass驱动的读回调函数procA ,从而将数据读到kbdclass队列中。过程就是如此。而且照书上的是:,
接下来就是在I8042prt或kbdhid驱动的设备的扩展体中搜索kbdclass的一个设备对象和那个回调函数(ProcA)地址。书上没给出完整的源码,我就试着照书上的思路写了份测试的代码:
1.这是找开I8042prt或kbdhid 和kbdclass驱动对象的函数,结果从参数中返回:
NTSTATUS _OpenKeyBdDriver(OUT PDRIVER_OBJECT* ppDriverUsing ,OUT PDRIVER_OBJECT* ppDriKbdclass){
UNICODE_STRING UszDriverName;
PDRIVER_OBJECT pDriKbdhid = NULL;
PDRIVER_OBJECT pDriI8024prt = NULL;
PDRIVER_OBJECT pDriverKbd = NULL;
NTSTATUS status = STATUS_SUCCESS;
//Reference Driver Kbdhid
RtlInitUnicodeString(&UszDriverName ,L"\\Driver\\Kbdhid");
status = ObReferenceObjectByName(&UszDriverName ,OBJ_CASE_INSENSITIVE ,NULL ,FILE_ALL_ACCESS,
*IoDriverObjectType ,KernelMode ,NULL ,(PVOID*)&pDriKbdhid);
if (!NT_SUCCESS(status))
DbgPrint("Fail To Reference Driver Kbdhid\r\n");
else
ObDereferenceObject(pDriKbdhid);
//Reference Driver I8024prt
RtlInitUnicodeString(&UszDriverName ,L"\\Driver\\i8042prt");
status = ObReferenceObjectByName(&UszDriverName ,OBJ_CASE_INSENSITIVE ,NULL ,FILE_ALL_ACCESS,
*IoDriverObjectType ,KernelMode ,NULL ,(PVOID*)&pDriI8024prt);
if (!NT_SUCCESS(status))
DbgPrint("Fail To Reference Driver I8042prt\r\n");
else
ObDereferenceObject(pDriI8024prt);
//Open Driver Kbdclass
RtlInitUnicodeString(&UszDriverName ,L"\\Driver\\Kbdclass");
status = ObReferenceObjectByName(&UszDriverName ,OBJ_CASE_INSENSITIVE ,NULL ,FILE_ALL_ACCESS,
*IoDriverObjectType ,KernelMode ,NULL ,(PVOID*)&pDriverKbd);
if (!NT_SUCCESS(status)){
DbgPrint("Fail To Reference Driver Kbdclass\r\n");
return status;
}
else
ObDereferenceObject(pDriverKbd);
//Both failed
if (!pDriI8024prt && !pDriI8024prt){
DbgPrint("Haven't Found Keyboard Device In your Machine\r\n");
return STATUS_INVALID_THREAD;
}
//Both Keyboard device
if (pDriI8024prt && pDriKbdhid){
DbgPrint("Found Two Keyboard In You Machine\r\n");
return STATUS_INVALID_THREAD;
}
*ppDriverUsing = (pDriI8024prt? pDriI8024prt : pDriKbdhid);
*ppDriKbdclass = pDriverKbd;
return STATUS_SUCCESS;
}
2.接下来得到了端口驱动对象与类驱动对象之后,就开开始在端口驱动的设备扩展体中搜索那个为类驱动的一个设备指针与回调函数ProcA;
pDriUsing是端口驱动对象指针(I8042prt或kbdhid),pDriKbdclass为类驱动对象指针。
DriParamSt是
//To store searched data
typedef struct _PARAM_OBJ_PROC{
PDEVICE_OBJECT pKbdclassDevice;
PKDBCLASSREADCALLBACKPROC pProcAddrInKbdclass;
PKDBCLASSREADCALLBACKPROC pProcAddrInUsingkbd;
}PARAM_OBJ_PROC ,*PPARAM_OBJ_PROC;
的一个全局变量;
函数如下:
NTSTATUS _ToSearch(IN PDRIVER_OBJECT pDriverUsing ,IN PDRIVER_OBJECT pDriKbdclass ,OUT PPARAM_OBJ_PROC pParamSt){
int nAddrStart = (int)pDriKbdclass->DriverStart;
int nAddrSize = (int)pDriKbdclass->DriverSize;
PDEVICE_OBJECT pDevUsing = pDriverUsing->DeviceObject;
PDEVICE_OBJECT pDevTarget = pDriKbdclass->DeviceObject;
//init var
pParamSt->pProcAddrInKbdclass = pParamSt->pProcAddrInUsingkbd = NULL;
pParamSt->pKbdclassDevice = NULL;
int* pDevExtUsing = NULL;
while(pDevTarget)
{
pDevExtUsing = (int*)pDevUsing->DeviceExtension;
for (int i = 0 ;i < 4096 ;i++ , pDevExtUsing++)
{
//address flow
if (!MmIsAddressValid(pDevExtUsing))
break;
//searched ok
if (pParamSt->pKbdclassDevice && pParamSt->pProcAddrInKbdclass){
DbgPrint("pDevTarget : %x\r\n" ,(int)pParamSt->pKbdclassDevice);
DbgPrint("pReadCallback in Kbdclass: %x\r\n" ,(int)pParamSt->pProcAddrInKbdclass);
DbgPrint("pReadCallback in DevKbdExtUsing : %x\r\n" ,(int)pParamSt->pProcAddrInUsingkbd);
return STATUS_SUCCESS;
}
//found Kdbclass Device
if (*pDevExtUsing == (int)pDevTarget){
DbgPrint("Found DevKbdclass In DevKbdUing Extension\r\n");
pParamSt->pKbdclassDevice = pDevTarget;
}
//found Kbdclass read Callback proc
if (*pDevExtUsing > nAddrStart && *pDevExtUsing < nAddrStart + nAddrSize &&
MmIsAddressValid((PVOID)*pDevExtUsing)){
DbgPrint("Found Kbdclass Read Callback Proc In DevKbdUing Extension\r\n");
pParamSt->pProcAddrInKbdclass = (PKDBCLASSREADCALLBACKPROC)*pDevExtUsing;
pParamSt->pProcAddrInUsingkbd = (PKDBCLASSREADCALLBACKPROC)pDevExtUsing;
}
DbgPrint("i : %d\r\n" ,i);
}
pDevTarget = pDevTarget->NextDevice;
}
return STATUS_INVALID_THREAD;
}
下面是DriverEntry:
#pragma INITCODE
extern "C"
NTSTATUS DriverEntry(IN PDRIVER_OBJECT pDriver ,IN PUNICODE_STRING pRegPath){
#ifdef DBG
__asm int 3
#endif
PDRIVER_OBJECT pDriverUsing = NULL;
PDRIVER_OBJECT pDriKbdclass = NULL;
NTSTATUS status = STATUS_SUCCESS;
int* pProcAddr = NULL;
pDriver->DriverUnload = DriverUnload;
status = _OpenKeyBdDriver(&pDriverUsing ,&pDriKbdclass);
if (!NT_SUCCESS(status))
return status;
status = _ToSearch(pDriverUsing ,pDriKbdclass ,&DriParamSt);
if (!NT_SUCCESS(status)){
DbgPrint("Fail to search Kbdclass read callback proc\r\n");
return status;
}
pProcAddr = (int*)DriParamSt.pProcAddrInUsingkbd;
*pProcAddr = (int)_ReadCallbackNew;
return STATUS_SUCCESS;
}
其中_ReadCallbackNew是自己写的用来替换那个回调函数的函数,很简单,如下:
void _ReadCallbackNew(IN PDEVICE_OBJECT pDevice ,IN PKEYBOARD_INPUT_DATA pDataBeg,
IN PKEYBOARD_INPUT_DATA pDataEnd ,OUT PULONG nDataConsumed){
PKDBCLASSREADCALLBACKPROC pProcOld = DriParamSt.pProcAddrInKbdclass;
PKEYBOARD_INPUT_DATA pQueueBeg = pDataBeg;
while (pQueueBeg != pDataEnd){
DbgPrint("Scancode : %x\r\n" ,pQueueBeg->MakeCode);
pQueueBeg++;
}
pProcOld(pDevice ,pDataBeg ,pDataEnd ,nDataConsumed);
}
代码大致就是上面这些了,但拷到VM上发现总是测试不成功,问题是搜索不到kbdclass类驱动的那个设备对象指针与那个回调函数,很无奈,真心知道错在哪,,代码和书上都差不多了,觉得应该不会错,那就是错在思路上了,还是说书上的这种方法已经不适用了,我是在win7下测试的。不知道还有谁去实践尝试过书上这个例子,可以的话分享下心得,一直被这个问题困扰着,找了很多资料也没有找到答案,看雪的各位大侠,能否给个建议或思路啊,谢谢谢谢
刚看到书上说当发生按键时,触发0x93号中断例程,在该中断例程会调用i8042prt驱动中的I8042keyboardInterruptService,在该函数中最终会调用 kbdclass驱动的读回调函数procA ,从而将数据读到kbdclass队列中。过程就是如此。而且照书上的是:,
接下来就是在I8042prt或kbdhid驱动的设备的扩展体中搜索kbdclass的一个设备对象和那个回调函数(ProcA)地址。书上没给出完整的源码,我就试着照书上的思路写了份测试的代码:
1.这是找开I8042prt或kbdhid 和kbdclass驱动对象的函数,结果从参数中返回:
NTSTATUS _OpenKeyBdDriver(OUT PDRIVER_OBJECT* ppDriverUsing ,OUT PDRIVER_OBJECT* ppDriKbdclass){
UNICODE_STRING UszDriverName;
PDRIVER_OBJECT pDriKbdhid = NULL;
PDRIVER_OBJECT pDriI8024prt = NULL;
PDRIVER_OBJECT pDriverKbd = NULL;
NTSTATUS status = STATUS_SUCCESS;
//Reference Driver Kbdhid
RtlInitUnicodeString(&UszDriverName ,L"\\Driver\\Kbdhid");
status = ObReferenceObjectByName(&UszDriverName ,OBJ_CASE_INSENSITIVE ,NULL ,FILE_ALL_ACCESS,
*IoDriverObjectType ,KernelMode ,NULL ,(PVOID*)&pDriKbdhid);
if (!NT_SUCCESS(status))
DbgPrint("Fail To Reference Driver Kbdhid\r\n");
else
ObDereferenceObject(pDriKbdhid);
//Reference Driver I8024prt
RtlInitUnicodeString(&UszDriverName ,L"\\Driver\\i8042prt");
status = ObReferenceObjectByName(&UszDriverName ,OBJ_CASE_INSENSITIVE ,NULL ,FILE_ALL_ACCESS,
*IoDriverObjectType ,KernelMode ,NULL ,(PVOID*)&pDriI8024prt);
if (!NT_SUCCESS(status))
DbgPrint("Fail To Reference Driver I8042prt\r\n");
else
ObDereferenceObject(pDriI8024prt);
//Open Driver Kbdclass
RtlInitUnicodeString(&UszDriverName ,L"\\Driver\\Kbdclass");
status = ObReferenceObjectByName(&UszDriverName ,OBJ_CASE_INSENSITIVE ,NULL ,FILE_ALL_ACCESS,
*IoDriverObjectType ,KernelMode ,NULL ,(PVOID*)&pDriverKbd);
if (!NT_SUCCESS(status)){
DbgPrint("Fail To Reference Driver Kbdclass\r\n");
return status;
}
else
ObDereferenceObject(pDriverKbd);
//Both failed
if (!pDriI8024prt && !pDriI8024prt){
DbgPrint("Haven't Found Keyboard Device In your Machine\r\n");
return STATUS_INVALID_THREAD;
}
//Both Keyboard device
if (pDriI8024prt && pDriKbdhid){
DbgPrint("Found Two Keyboard In You Machine\r\n");
return STATUS_INVALID_THREAD;
}
*ppDriverUsing = (pDriI8024prt? pDriI8024prt : pDriKbdhid);
*ppDriKbdclass = pDriverKbd;
return STATUS_SUCCESS;
}
2.接下来得到了端口驱动对象与类驱动对象之后,就开开始在端口驱动的设备扩展体中搜索那个为类驱动的一个设备指针与回调函数ProcA;
pDriUsing是端口驱动对象指针(I8042prt或kbdhid),pDriKbdclass为类驱动对象指针。
DriParamSt是
//To store searched data
typedef struct _PARAM_OBJ_PROC{
PDEVICE_OBJECT pKbdclassDevice;
PKDBCLASSREADCALLBACKPROC pProcAddrInKbdclass;
PKDBCLASSREADCALLBACKPROC pProcAddrInUsingkbd;
}PARAM_OBJ_PROC ,*PPARAM_OBJ_PROC;
的一个全局变量;
函数如下:
NTSTATUS _ToSearch(IN PDRIVER_OBJECT pDriverUsing ,IN PDRIVER_OBJECT pDriKbdclass ,OUT PPARAM_OBJ_PROC pParamSt){
int nAddrStart = (int)pDriKbdclass->DriverStart;
int nAddrSize = (int)pDriKbdclass->DriverSize;
PDEVICE_OBJECT pDevUsing = pDriverUsing->DeviceObject;
PDEVICE_OBJECT pDevTarget = pDriKbdclass->DeviceObject;
//init var
pParamSt->pProcAddrInKbdclass = pParamSt->pProcAddrInUsingkbd = NULL;
pParamSt->pKbdclassDevice = NULL;
int* pDevExtUsing = NULL;
while(pDevTarget)
{
pDevExtUsing = (int*)pDevUsing->DeviceExtension;
for (int i = 0 ;i < 4096 ;i++ , pDevExtUsing++)
{
//address flow
if (!MmIsAddressValid(pDevExtUsing))
break;
//searched ok
if (pParamSt->pKbdclassDevice && pParamSt->pProcAddrInKbdclass){
DbgPrint("pDevTarget : %x\r\n" ,(int)pParamSt->pKbdclassDevice);
DbgPrint("pReadCallback in Kbdclass: %x\r\n" ,(int)pParamSt->pProcAddrInKbdclass);
DbgPrint("pReadCallback in DevKbdExtUsing : %x\r\n" ,(int)pParamSt->pProcAddrInUsingkbd);
return STATUS_SUCCESS;
}
//found Kdbclass Device
if (*pDevExtUsing == (int)pDevTarget){
DbgPrint("Found DevKbdclass In DevKbdUing Extension\r\n");
pParamSt->pKbdclassDevice = pDevTarget;
}
//found Kbdclass read Callback proc
if (*pDevExtUsing > nAddrStart && *pDevExtUsing < nAddrStart + nAddrSize &&
MmIsAddressValid((PVOID)*pDevExtUsing)){
DbgPrint("Found Kbdclass Read Callback Proc In DevKbdUing Extension\r\n");
pParamSt->pProcAddrInKbdclass = (PKDBCLASSREADCALLBACKPROC)*pDevExtUsing;
pParamSt->pProcAddrInUsingkbd = (PKDBCLASSREADCALLBACKPROC)pDevExtUsing;
}
DbgPrint("i : %d\r\n" ,i);
}
pDevTarget = pDevTarget->NextDevice;
}
return STATUS_INVALID_THREAD;
}
下面是DriverEntry:
#pragma INITCODE
extern "C"
NTSTATUS DriverEntry(IN PDRIVER_OBJECT pDriver ,IN PUNICODE_STRING pRegPath){
#ifdef DBG
__asm int 3
#endif
PDRIVER_OBJECT pDriverUsing = NULL;
PDRIVER_OBJECT pDriKbdclass = NULL;
NTSTATUS status = STATUS_SUCCESS;
int* pProcAddr = NULL;
pDriver->DriverUnload = DriverUnload;
status = _OpenKeyBdDriver(&pDriverUsing ,&pDriKbdclass);
if (!NT_SUCCESS(status))
return status;
status = _ToSearch(pDriverUsing ,pDriKbdclass ,&DriParamSt);
if (!NT_SUCCESS(status)){
DbgPrint("Fail to search Kbdclass read callback proc\r\n");
return status;
}
pProcAddr = (int*)DriParamSt.pProcAddrInUsingkbd;
*pProcAddr = (int)_ReadCallbackNew;
return STATUS_SUCCESS;
}
其中_ReadCallbackNew是自己写的用来替换那个回调函数的函数,很简单,如下:
void _ReadCallbackNew(IN PDEVICE_OBJECT pDevice ,IN PKEYBOARD_INPUT_DATA pDataBeg,
IN PKEYBOARD_INPUT_DATA pDataEnd ,OUT PULONG nDataConsumed){
PKDBCLASSREADCALLBACKPROC pProcOld = DriParamSt.pProcAddrInKbdclass;
PKEYBOARD_INPUT_DATA pQueueBeg = pDataBeg;
while (pQueueBeg != pDataEnd){
DbgPrint("Scancode : %x\r\n" ,pQueueBeg->MakeCode);
pQueueBeg++;
}
pProcOld(pDevice ,pDataBeg ,pDataEnd ,nDataConsumed);
}
代码大致就是上面这些了,但拷到VM上发现总是测试不成功,问题是搜索不到kbdclass类驱动的那个设备对象指针与那个回调函数,很无奈,真心知道错在哪,,代码和书上都差不多了,觉得应该不会错,那就是错在思路上了,还是说书上的这种方法已经不适用了,我是在win7下测试的。不知道还有谁去实践尝试过书上这个例子,可以的话分享下心得,一直被这个问题困扰着,找了很多资料也没有找到答案,看雪的各位大侠,能否给个建议或思路啊,谢谢谢谢
赞赏
他的文章
谁下载
kanxue
wangbeng
惊电
yzslly
xss
waruqi
albeta
fangbingyu
落叶随风
红色神话
nevergone
peowner
exile
孙海鸥
vfdn
liushijie
cwind
lfhack
风有影
leeone
囧囧
skeay
Dvsz
leyyer
weare
elianmeng
Ella
sheepotter
kangcin
atompure
fghsina
timeboxls
tarena
zhaohtao
莫灰灰
xouou
virusest
tokiii
wyufei
金叶
evanpw
ReleaseLag
jikefeng
高级小白
rub
tyson
Nermor
wrgg
月月h
zhouws
BoyXiao
xxffv
cosfy
abcgoodwei
CoolSec
fishyuule
邋遢鬼
heartnet
Vsbat
mfcjck
uncletwo
tydef
jsjnwms
紫夜星纱
何健hj
ahaqcyl
viphack
gloomyle
lm李明
rainlovef
西川
forlovefor
洪武
xuyunfeixu
打狗棒
淡定疯着
lifestill
tooryidep
JasonGama
青v云
逆帅
又迟到了
蜗牛会飞
IamHuskar
我是小三
funnyy
乌鸦l
汉潮画室
大爨
zsmj
看原图
赞赏
雪币:
留言: