//这个函数用来确定是否我们应该允许NtCreateSection()调用成功 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; //检查标志。如果所要求的存取方式不是PAGE_EXECUTE, //这并不要紧 if((arg&0xf0)==0)return 1; if((arg&0x01000000)==0)return 1; //经由文件句柄得到文件名 hand=(HANDLE)arg; 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); //如果它是不可执行的,这也不要紧 //返回1 if(_stricmp(&buff[a],"exe")){RtlFreeAnsiString(&str);return 1;} //现在,我们要询问用户的选择。 //把文件名写入缓冲区,并等待直到用户显示响应 //(第一个DWORD为1意味着我们可以继续) //同步存取该缓冲区 KeWaitForSingleObject(&event,Executive,KernelMode,0,0); //把缓冲区的前两个DWORD置为0, //把字符串复制到该缓冲区中,并循环下去,直到用户把每一个 //DWORD置为1. //第二个DWORD的值指明用户的响应 strcpy(&output,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); KeSetEvent(&event,0,0); return a; } //仅保存执行上下文并调用check() _declspec(naked) Proxy() { _asm{ //保存执行上下文并调用check() //-后面的依赖于check()所返回的值 // 如果返回值是1,继续实际的调用。 //否则,返回STATUS_ACCESS_DENIED pushfd pushad mov ebx,esp add ebx,40 push ebx call check cmp eax,1 jne block //继续实际的调用 popad popfd jmp RealCallee //返回STATUS_ACCESS_DENIED block:popad mov ebx, dword ptr[esp+8] mov dword ptr[ebx],0 mov eax,0xC0000022L popfd ret 32 } } |