首页
论坛
课程
招聘
[原创]驱动监控进程的创建
2008-5-31 12:32 23151

[原创]驱动监控进程的创建

2008-5-31 12:32
23151
这是我在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

看雪招聘平台创建简历并且简历完整度达到90%及以上可获得500看雪币~

上传的附件:
收藏
点赞0
打赏
分享
最新回复 (23)
雪    币: 273
活跃值: 活跃值 (18)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
天外来客 活跃值 2008-5-31 13:23
2
0
呵呵,楼主分析得不错,不过论坛上已经有了这个代码
雪    币: 211
活跃值: 活跃值 (14)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
guolijie 活跃值 1 2008-5-31 17:21
3
0
强!  学习! 谢谢提供源码
雪    币: 109
活跃值: 活跃值 (197)
能力值: ( LV13,RANK:1050 )
在线值:
发帖
回帖
粉丝
combojiang 活跃值 26 2008-5-31 23:19
4
0
good job
雪    币: 207
活跃值: 活跃值 (37)
能力值: ( LV9,RANK:290 )
在线值:
发帖
回帖
粉丝
sislcb 活跃值 7 2008-6-2 22:03
5
0
呵呵,我记得这个源码在2003会蓝。。
雪    币: 519
活跃值: 活跃值 (27)
能力值: ( LV12,RANK:230 )
在线值:
发帖
回帖
粉丝
hljleo 活跃值 5 2008-6-2 22:08
6
0
2003我没有试过
雪    币: 27
活跃值: 活跃值 (26)
能力值: ( LV9,RANK:970 )
在线值:
发帖
回帖
粉丝
wynney 活跃值 24 2008-6-3 00:26
7
0
我记得这个源码早就在我的硬盘里了
雪    币: 519
活跃值: 活跃值 (27)
能力值: ( LV12,RANK:230 )
在线值:
发帖
回帖
粉丝
hljleo 活跃值 5 2008-6-3 09:02
8
0
我是菜菜鸟,,所以很多东西对我来说都是新的
雪    币: 207
活跃值: 活跃值 (37)
能力值: ( LV9,RANK:290 )
在线值:
发帖
回帖
粉丝
sislcb 活跃值 7 2008-6-3 09:05
9
0
恩,还是要支持的,分享的精神很好。
雪    币: 215
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
future 活跃值 2008-6-3 09:28
10
0
正在学习这方面的东西,支持楼主这种精神!!!
雪    币: 103
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
shdow浅蓝 活跃值 2008-6-4 16:14
11
0
不太明白check(PULONG arg)这个函数的参数是什么意思,Proxy()调用check传进去的是ebx吧,它指向的是个什么东西?LZ能不能讲解下,偶很懵懂~~
雪    币: 519
活跃值: 活跃值 (27)
能力值: ( LV12,RANK:230 )
在线值:
发帖
回帖
粉丝
hljleo 活跃值 5 2008-6-4 17:33
12
0
获得指向服务参数指针

struct SYS_SERVICE_TABLE {
        void **ServiceTable;
        unsigned long CounterTable;
        unsigned long ServiceLimit;
        void **ArgumentsTable;
};
注意**ArgumentsTable就应该明白了
雪    币: 519
活跃值: 活跃值 (27)
能力值: ( LV12,RANK:230 )
在线值:
发帖
回帖
粉丝
hljleo 活跃值 5 2008-6-4 19:15
13
0
Proxy()调用check是得到check的返回值,,存在EAX中
雪    币: 200
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
火炎焱康 活跃值 2008-6-4 19:21
14
0
看的头晕..
雪    币: 103
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
shdow浅蓝 活跃值 2008-6-4 21:42
15
0
[QUOTE=;]...[/QUOTE]
哦,明白了,没看仔细,把参数给忘了~
雪    币: 519
活跃值: 活跃值 (27)
能力值: ( LV12,RANK:230 )
在线值:
发帖
回帖
粉丝
hljleo 活跃值 5 2008-6-4 22:17
16
0
明白就好
很多东西不是一下子就看懂的
雪    币: 103
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
shdow浅蓝 活跃值 2008-6-5 22:11
17
0
KeWaitForSingleObject(&event,Executive,KernelMode,0,0);
对这个函数的作用有点不太理解,等待超时为什么要设置为0。另外我觉得去掉它也可以啊,楼主能不能再给偶详细讲解下~~~
雪    币: 203
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
reebox 活跃值 2008-9-1 17:15
18
0
学习中,谢谢分享!
雪    币: 217
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
jwtck 活跃值 2008-9-16 09:41
19
0
这代码不会有重入问题吗
雪    币: 201
活跃值: 活跃值 (10)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
junxiong 活跃值 1 2008-9-16 23:05
20
0
下下来学习一下,谢谢分享!
雪    币: 313
活跃值: 活跃值 (22)
能力值: ( LV7,RANK:100 )
在线值:
发帖
回帖
粉丝
better 活跃值 2 2008-12-10 16:54
21
0
好像不是监控所有的吧
雪    币: 32
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
jordanpz 活跃值 2008-12-11 16:34
22
0
驱动开发的集体交流号码67181435。现已经加至140人,上限为200,云集众多高手。
雪    币: 4112
活跃值: 活跃值 (869)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
kagayaki 活跃值 2008-12-18 00:24
23
0
收藏.......
雪    币: 231
活跃值: 活跃值 (12)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
yaolibing 活跃值 2009-3-2 22:07
24
0
lz怎么不把用户层的代码也传上去啊
游客
登录 | 注册 方可回帖
返回