//open device
device=CreateFile("\\\\.\\PROTECTOR",GENERIC_READ|GENERIC_WRITE,
0,0,OPEN_EXISTING, FILE_ATTRIBUTE_SYSTEM,0);
// get index of NtCreateSection, and pass it to the driver, along with the
//address of output buffer
DWORD * addr=(DWORD *)
(1+(DWORD)GetProcAddress(GetModuleHandle("ntdll.dll"),
"NtCreateSection"));
ZeroMemory(outputbuff,256);
controlbuff[0]=addr[0];
controlbuff[1]=(DWORD)&outputbuff[0];
DeviceIoControl(device,1000,controlbuff,256,controlbuff,256,&dw,0);
//this function decides whether we should
//allow NtCreateSection() call to be successfull
ULONG __stdcall check(PULONG arg)
{
HANDLE hand=0;PFILE_OBJECT file=0;
POBJECT_HANDLE_INFORMATION info;ULONG a;char*buff;
ANSI_STRING str; LARGE_INTEGER li;li.QuadPart=-10000;
//check the flags. If PAGE_EXECUTE access to the section is not requested,
//it does not make sense to be bothered about it
if((arg[4]&0xf0)==0)return 1;
if((arg[5]&0x01000000)==0)return 1;
//get the file name via the file handle
hand=(HANDLE)arg[6];
ObReferenceObjectByHandle(hand,0,0,KernelMode,&file,&info);
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 it is not executable, it does not make sense to be bothered about it
//return 1
if(_stricmp(&buff[a],"exe")){RtlFreeAnsiString(&str);return 1;}
//now we are going to ask user's opinion.
//Write file name to the buffer, and wait until
//the user indicates the response
//(1 as a first DWORD means we can proceed)
//synchronize access to the buffer
KeWaitForSingleObject(&event,Executive,KernelMode,0,0);
// set first 2 DWORD of a buffer to zero,
// copy the string into the buffer, and loop
// until the user sets first DWORD to 1.
// The value of the second DWORD indicates user's
//response
strcpy(&output[8],buff);
RtlFreeAnsiString(&str);
a=1;
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;
}
//just saves execution contect and calls check()
_declspec(naked) Proxy()
{
_asm{
//save execution contect and calls check()
//-the rest depends upon the value check() returns
// if it is 1, proceed to the actual callee.
//Otherwise,return STATUS_ACCESS_DENIED
pushfd
pushad
mov ebx,esp
add ebx,40
push ebx
call check
cmp eax,1
jne block
//proceed to the actual callee
popad
popfd
jmp RealCallee
//return STATUS_ACCESS_DENIED
block:popad
mov ebx, dword ptr[esp+8]
mov dword ptr[ebx],0
mov eax,0xC0000022L
popfd
ret 32
}
}
void thread()
{
DWORD a,x; char msgbuff[512];
while(1)
{
memmove(&a,&outputbuff[0],4);
//if nothing is there, Sleep() 10 ms and check again
if(!a){Sleep(10);continue;}
// looks like our permission is asked. If the file
// in question is already in the white list,
// give a positive response
char*name=(char*)&outputbuff[8];
for(x=0;x<stringcount;x++)
{
if(!stricmp(name,strings[x])){a=1;goto skip;}
}
// ask user's permission to run the program
strcpy(msgbuff, "Do you want to run ");
strcat(msgbuff,&outputbuff[8]);
// if user's reply is positive, add the program to the white list
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);
//tell the driver to go ahead
a=0;
memmove(&outputbuff[0],&a,4);
}
}
这个例子已经在windows XP SP2的一些机器上测试成功.尽管我还没有在其他环境下做测试,我相信它在哪里都会运行正常的(这句话有点吹牛了,我直接下载的代码,直接运行就有问题)--毕竟,它没有用到任何可能和系统相关的结构.要运行这个例子,你需要做的就是把protector.exe和protector.sys放到同一个目录下面,然后运行protector.exe.在protector.exe的应用程序窗口关闭前,你每次试图运行任何的可执行文件时都会被提示(已经被允许运行的从第二次开始就不会再被提示,这点老外没表达清楚).