如果下面说的存在错误之处,恳请大家指正。希望能帮助遇到同样问题的童鞋~
昨天调试了这个函数好长时间,就是模仿了书上的例子,调试了很多遍都得不到想要得效果,最后才发现问题出现在一个
类型运算上的错误,自己的C语言基础不太好,是看WinDBG中对应的汇编代码才发现的。
书上的例子函数如下:
BOOLEAN MyTimerSet(PMY_TIMER timer,ULONG msec,PVOID context)
{
LARGE_INTERGE due;
due.QuadPart = -10000 * msec; [B][COLOR="Red"]//这是问题代码,msec是ULONG型的,这是无符号运算,结果为正数[/COLOR][/B]
timer->Private_context = context;
return KeSetTimer(&timer->timer,due,&timer->dpc);
};
自己模仿的代码:
BOOLEAN MyTimerSet(PMYTIMER pMyTimer)
{
LARGE_INTEGER DueTime;
DueTime.QuadPart = -10000 * pMyTimer->WaitTime; [COLOR="Red"][B]//WaitTime是ULONG型的,也存在同样的问题[/B][/COLOR]
return KeSetTimer(&pMyTimer->KTimer,DueTime,&pMyTimer->KDpc);
}
下面从汇编发现问题:
fad45266 8b4508 mov eax,dword ptr [ebp+8] ss:0010:fadefc24={MyDriverTest!MyTimer (fad47000)}
fad45269 8b484c mov ecx,dword ptr [eax+4Ch]
fad4526c 69c9f0d8ffff imul ecx,ecx,0FFFFD8F0h ;-10000 * pMyTimer->WaitTime
fad45272 33d2 xor edx,edx ;运算高32位清0
fad45274 894df8 mov dword ptr [ebp-8],ecx ;运算低32位存放在DueTime.LowPart
fad45277 8955fc mov dword ptr [ebp-4],edx ;DueTime.HighPart = 0,很明显结果总是正数
参数2中,如果是正数的话,表示指定的时间于1061/01/01期经过的纳秒数,单位为100NS,负数才是我们要求的。
昨天真是头晕了,调试了很久才发现问题,解决方法很简单,在运算时使用LONG做强制类型转换就可以了。
BOOLEAN MyTimerSet(PMYTIMER pMyTimer)
{
LARGE_INTEGER DueTime;
[COLOR="Red"]DueTime.QuadPart = -10000 * (LONG)pMyTimer->WaitTime;[/COLOR]
return KeSetTimer(&pMyTimer->KTimer,DueTime,&pMyTimer->KDpc);
}
强制类型转换后对应的结果:
fad3d286 8b4508 mov eax,dword ptr [ebp+8]
fad3d289 8b404c mov eax,dword ptr [eax+4Ch]
fad3d28c 69c0f0d8ffff imul eax,eax,0FFFFD8F0h
fad3d292 99 cdq ; 强制类型转换后的符号扩展,
fad3d293 8945f8 mov dword ptr [ebp-8],eax
fad3d296 8955fc mov dword ptr [ebp-4],edx ;扩展符号位后存放,
从来没有觉得CDQ指令这么美丽~~~
****************************************************************************************************************************************
对于书上的例子封装的还不够傻瓜化(要实现反复执行,用户自己需要在回调函数中再次调用KeSetTimer),因此自己封装了
一遍,比较傻瓜化,效果还算可以,用法如下:
定义一个全局结构MYTIMER,然后调用函数MySetTimer就可以实现反复周期运行了,参数意义在文件中有说明。
[课程]Linux pwn 探索篇!
上传的附件: