这是我在http://www.codeproject.com/学习时看到的一个驱动程序,学习后对其整理的笔记.
下面这个驱动程序的作用:监控准备运行的可执行文件。(由用户决定是不是让它运行)
所以我们要做以下工作:
首先是修改(NtCreateSection)SSDT索引号,(索引号从用户程序中得到)HOOK NtCreateSection()这个函数,然后通过文件句柄获得文件名,判断它是不是可执行文件,检测其属性与判断用户是否允许它执行,如果允许就运行原来NtCreateSection这个函数,否则返回STATUS_ACCESS_DENIED。
如果我们截获一个NtCreateSection()的请求,该请求要求映射可执行文件作为SEC_IMAGE属性,通过结合页保护属性,我们能够知道进程将要执行了,因此我们在这个时候作出决定:是否让其执行。如果不想让它执行,EAX 返回值为STATUS_ACCESS_DENIED。
因为调用是从ntdll. dll 以一条 MOV EAX, ServiceIndex五字节指令开始的,第一个字节是MOV EAX,后四字节是索引号,所以我们可以得到索引号(后四字节)然后将它进行修改成我们自己的函数索引。当然在修改之前要将原服务函数地址保存在全局变量中。
if(loc->Parameters.DeviceIoControl.IoControlCode==1000)
{
buff=(UCHAR*)Irp->AssociatedIrp.SystemBuffer;
// hook service dispatch table
memmove(&Index,buff,4);//所有的调用都是从ntdll.dll以一条五字节指令MOV EAX, ServiceIndex开始,四字节是索引号
a=4*Index+(ULONG)KeServiceDescriptorTable->ServiceTable;//从用户程序中得到索引号,a指向服务函数地址
base=(ULONG)MmMapIoSpace(MmGetPhysicalAddress((void*)a),4,0);//将物理地址映射到非分页池,因此可以进行读写,减少读写服务表保护属性的麻烦
a=(ULONG)&Proxy;//a指向Proxy函数的地址
_asm
{
mov eax,base
mov ebx,dword ptr[eax]
mov RealCallee,ebx//将原服务函数地址保存在全局变量中
mov ebx,a
mov dword ptr[eax],ebx//Proxy函数地址写进服务函数表中
}
memmove(&a,&buff[4],4);
output=(char*)MmMapIoSpace(MmGetPhysicalAddress((void*)a),256,0);
}
下面是我们自己函数的实现:
//这个函数决定是否 NtCreateSection() 被成功调用
ULONG __stdcall check(PULONG arg)//获得指向服务参数指针
{
HANDLE hand=0;PFILE_OBJECT file=0;
POBJECT_HANDLE_INFORMATION info=0;ULONG a;char*buff;
ANSI_STRING str; LARGE_INTEGER li;li.QuadPart=-10000;
if((arg[4]&0xf0)==0)return 1;//检测标志
if((arg[5]&0x01000000)==0)return 1;//检测属性
//通过文件句柄获得文件名
hand=(HANDLE)arg[6];//获得执行文件句柄
ObReferenceObjectByHandle(hand,0,0,KernelMode,&file,info);//&file获得对象体指针
if(!file)return 1;
RtlUnicodeStringToAnsiString(&str,&file->FileName,1);
a=str.Length;buff=str.Buffer;
while(1)//通过循环判断是不是有". "标志
{
if(buff[a]=='.'){a++;break;}
a--;
}
ObDereferenceObject(file);
if(_stricmp(&buff[a],"exe")){RtlFreeAnsiString(&str);return 1;}//判断是否为可执行文件
KeWaitForSingleObject(&event,Executive,KernelMode,0,0);//将当前线程置于等待状态知道信号态
strcpy(&output[8],buff);//将string复制进buff
RtlFreeAnsiString(&str);
a=1;//用户的决定通过a的制来反映
memmove(&output[0],&a,4);
while(1)
{
KeDelayExecutionThread(KernelMode,0,&li);//在一个固定时间间隔内当前线程处于等待状态
memmove(&a,&output[0],4);
if(!a)break;
}
memmove(&a,&output[4],4);
KeSetEvent(&event,0,0);
return a;
}
//保存执行文件上下文,调用check()函数
_declspec(naked) Proxy()
{
_asm{
pushfd
pushad
mov ebx,esp
add ebx,40
push ebx
call check
cmp eax,1//由check()的返回值判断是否让可执行文件继续执行
jne block
popad
popfd
jmp RealCallee//通过,调用ntcreatesection
block:popad
mov ebx, dword ptr[esp+8]
mov dword ptr[ebx],0
mov eax,0xC0000022L//不让其通过,返回STATUS_ACCESS_DENIED
popfd
ret 32
}
}
到此,驱动程序的工作基本完成,在用户程序中用到一个线程来等待驱动的判断结果。
char*name=(char*)&outputbuff[8];
for(x=0;x<stringcount;x++)
{
if(!stricmp(name,strings[x])){a=1;goto skip;}
}
strcpy(msgbuff, "Do you want to run ");
strcat(msgbuff,&outputbuff[8]);
if(IDYES==MessageBox(0, msgbuff,"WARNING",
MB_YESNO|MB_ICONQUESTION|0x00200000L))
{a=1; strings[stringcount]=_strdup(name);stringcount++;}
else a=0;
// write response to the buffer, and driver will get it
skip:memmove(&outputbuff[4],&a,4);
//让驱动继续
a=0;
memmove(&outputbuff[0],&a,4);
}}
MY BLOG: http://hi.baidu.com/hljleo
tlhelen
- 粉丝: 1
- 资源: 11
最新资源
- 基于Java实现的MapReduce分布式计算框架设计源码
- Qwen2.5 Technical Report 详细技术报告
- 基于ThinkGms v2.0.1框架的旧快马配送系统设计源码
- 基于Java编程语言的俄罗斯方块游戏设计源码
- 套膜封切机工程图机械结构设计图纸和其它技术资料和技术方案非常好100%好用.zip
- 小麦联合收割机工程图机械结构设计图纸和其它技术资料和技术方案非常好100%好用.zip
- 小型全自动卷烟机构图纸工程图机械结构设计图纸和其它技术资料和技术方案非常好100%好用.zip
- 线体牵引力测试机(含bom)sw17可编辑工程图机械结构设计图纸和其它技术资料和技术方案非常好100%好用.zip
- 前端入门day1的文件记录
- 型钢校正机矫直机工程图机械结构设计图纸和其它技术资料和技术方案非常好100%好用.zip
- 旋转停车系统工程图机械结构设计图纸和其它技术资料和技术方案非常好100%好用.zip
- 数仓构造与多维分析大作业
- 【图像融合】基于matlab结合contourlet与压缩感知图像融合【含Matlab源码 9741期】.zip
- 【坐标转换】基于matlab GUI大地坐标和空间直角坐标相互转换【含Matlab源码 9227期】.zip
- 【迷宫路径规划】基于matlab SARSA和强化学习迷宫路径规划解决迷宫问题【含Matlab源码 8857期】.mp4
- 【语音去噪】基于matlab GUI切比雪夫+椭圆形低通滤波器语音去噪【含Matlab源码 2198期】.mp4
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈