delphi如何屏蔽CTRL+ALT+DEL热键,怎么写

解决方案 »

  1.   

    以前的操作系统,可以远程注入winlogon.exe并子类化SAS window class的消息处理函数实现屏蔽ctrl+alt+del不过vista和win7这个方法已经失效了
      

  2.   

    此題我來解吧:在WINDOWS 9X环境中我们可以使用SystemParametersInfo (SPI_SCREENSAVERRUNNING, 1,NULL, 0);来屏蔽CTRL+ALT+DEL,但在NT/2000/xp等环境下却行不通,即使使用WH_KEYBOARD_LL这个低级的键盘hook也无法拦截!但我通过替换GINA DLL的方式很好地实现了在NT/2000/xp下屏蔽CTRL+ALT+DEL的功能...一、原理在NT/2000中交互式的登陆支持是由WinLogon调用GINA DLL实现的,GINA DLL提供了一个交互式的界面为用户登陆提供认证请求。在WinLogon初始化时,就向系统注册截获CTRL+ALT+DEL消息,所以其他程序就无法得到CTRL+ALT+DEL的消息。WinLogon会和GINA DLL进行交互,缺省是MSGINA.DLL(在System32目录下)。微软同时也为我们提供的接口,自己可以编GINA DLL来代替MSGINA.DLL。WinLogon初始化时会创建3个桌面:(1)、winlogon桌面:主要显示window 安全等界面,如你按下CTRL+ALT+DEL,登陆的界面等(2)、应用程序桌面:我们平时见到的那个有我的电脑的界面(3)、屏幕保护桌面:屏幕保护显示界面。在用户登陆以后,按下CTRL+ALT+DEL键的时候,WinLogon回调用GINA DLL的输出函数:WlxLoggedOnSAS,这时正处于winlogon桌面,我们只要直接将他转向应用程序桌面,系统就不会显示Windows安全那个界面,换一种说法也就是用户按下CTRL+ALT+DEL后,不会起什么作用。当是我们在切换桌面的时候会出现屏幕闪动!二、程序实现GINA DLL要输出下列函数(winlogon会调用)WlxActivateUserShellWlxDisplayLockedNoticeWlxDisplaySASNoticeWlxDisplayStatusMessageWlxGetStatusMessageWlxInitializeWlxIsLockOkWlxIsLogoffOkWlxLoggedOnSASWlxLoggedOutSASWlxLogoffWlxNegotiateWlxNetworkProviderLoadWlxRemoveStatusMessageWlxScreenSaverNotifyWlxShutdownWlxStartApplicationWlxWkstaLockedSAS为了简化编程,我们从MSGINA.DLL中动态获取上诉函数,在自定义的DLL中(以下称为NoReboot.DLL)中直接调用MSGINA.DLL的函数即可。现在我们要处理的就是WlxLoggedOnSAS函数:int WINAPI WlxLoggedOnSAS (PVOID pWlxContext,DWORD dwSasType,PVOID pReserved){ HANDLE hMutex;WriteInfo("WlxLoggedOnSAS 
    "); //用于记录信息if (dwSasType == WLX_SAS_TYPE_CTRL_ALT_DEL){ //屏蔽CTRL_ALT_DEL,也可以根据特定条件来决定是否要屏蔽//我采用了Mutex来控制是否屏蔽,(注意:要用unicode)hMutex = OpenMutex(MUTEX_ALL_ACCESS, FALSE, L"_ac952_z_cn_CTRL_ALT_DEL");if (hMutex){CloseHandle(hMutex);WriteInfo("disble CTRL+ALT+DEL 
    ");return WLX_SAS_ACTION_NONE; //将屏幕切换到应用程序桌面,屏蔽掉CTRL+ALT+DEL}elseWriteInfo("not disble CTRL+ALT+DEL 
    ");}return prcWlxLoggedOnSAS ( //这是我从MSGINA.DLL中获取的函数。pWlxContext,dwSasType,pReserved);}我们要在自己的程序中调用hMutex = CreateMutex(NULL, FALSE, "_ac952_z_cn_CTRL_ALT_DEL");就可屏蔽CTRL+ALT+DEL。三、安装和注意事项:在编写GIAN DLL中要注意,GINA DLL使用的是unicode。GINA DLL的安装:键名 : HKEY_LOCAL_MACHINESoftwareMicrosoftWindows NTCurrentVersionWinlogon 变量名 : GinaDLL 变量类型 : [REG_SZ] 内容 : "你的GINA DLL的名称" 如:"NoReboot.DLL:将你的GINA DLL(NoReboot.dll)拷贝到系统目录下(system32),重启机器,你的GINA DLL(NoReboot.dll)就会运行。如果出现进不了你的系统,那你进入DOS后,将msgina.dll拷贝成你的GINA DLL(NoReboot.dll)就可进入了,或者进入安全模式,删除掉那个键值。
      

  3.   

    LZ留下一個地址,我把源碼發給你吧(源碼太長,系統提示“回覆內容過長”)implementation
    procedure GetDebugPrivs;  //提升到Debug权限
    var
     hToken: THandle;
     tkp: TTokenPrivileges;
     retval: dword;
    begin
     If (OpenProcessToken(GetCurrentProcess, TOKEN_ADJUST_PRIVILEGES or TOKEN_QUERY, hToken)) then
     begin
       LookupPrivilegeValue(nil, 'SeDebugPrivilege'  , tkp.Privileges[0].Luid);
       tkp.PrivilegeCount := 1;
       tkp.Privileges[0].Attributes := SE_PRIVILEGE_ENABLED;
       AdjustTokenPrivileges(hToken, False, tkp, 0, nil, retval);
     end;
    end;function NameToPID(ExeName:pchar):longword;
    //通过进程文件名返回一个Pid,如果多个同名进程返回第一个进程的Pid
     var
       hSnap:longword;
       ProcessEntry: TProcessEntry32;
       c:boolean;
     begin
       result:=0;
       hSnap:= CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0);
       ProcessEntry.dwSize:= Sizeof(TProcessEntry32);
       c:= Process32First(hSnap,ProcessEntry);
       While c  do
         begin
           if LstrcmpiA(ExeName,ProcessEntry.szExeFile)= 0 then
              begin
                result:=ProcessEntry.th32ProcessID;
                break;
              end;
           c:=Process32Next(hSnap,ProcessEntry);
         end;
       CloseHandle(hSnap);
     end;function GetSysPath:pchar;  //最后没加'/'
     var
      a:pchar;
     begin
      GetMem(a,255);
      GetSystemDirectory(a,255);
      Result:=a;
     end;
    procedure DelKernel;
     begin
       DeleteFile(pchar(string(GetSysPath)+'\'+string(MyKernel))) ;
     end;function CreateKernelFile(SaveFile:String):Boolean;
     var
       hFile:THandle;
       BytesWrite: dword;
     begin
       Result:=False;
       hFile := CreateFile(Pchar(SaveFile),GENERIC_READ or GENERIC_WRITE,FILE_SHARE_READ,nil,CREATE_ALWAYS,0,0);
       if hFile = INVALID_HANDLE_VALUE then Exit;
       if WriteFile(hFile,MyKernelBuf,MyKernelSize, BytesWrite, nil) then Result:=True;
       CloseHandle(hFile);
     end;Function  GetModule(ProcessName,ModuleName:Pchar):longword;
    //This is a function written by Hke.
    //检查进程是否加载DLL,是返回指针,否返回0
     var
       PID:longword;
       hModuleSnap:longword;
       ModuleEntry: TModuleEntry32;
     begin
       Pid:=NameToPID(ProcessName);
       GetDebugPrivs;
       hModuleSnap:=CreateToolhelp32Snapshot(TH32CS_SNAPMODULE,Pid);
       ModuleEntry.dwSize:=SizeOf(TModuleEntry32);
       result:=0;
       if Module32First(hModuleSnap,ModuleEntry) then
         if  (LstrcmpiA(ModuleEntry.szModule,ModuleName)=0) then
           Result:=ModuleEntry.hModule
         else
           begin
             while  Module32Next(hModuleSnap,ModuleEntry) do
                begin
                  if LstrcmpiA(ModuleEntry.szModule,ModuleName)=0 then
                    begin
                      Result:=ModuleEntry.hModule;
                      break;
                    end;
                end;
           end;
       CloseHandle(hModuleSnap);
     end;procedure InjectKernelModule(ProcessName ,DllName: Pchar);
    //This is a function written by Hke.
    //利用远程线程讲把Dll注入进程
     var
       tmp:longword;//这个专门来占格式收集垃圾
       Mysize:longword;//放字符串长度
       Parameter:pointer;//放那个参数的指针(位置在目标进程内)
       hThread:longword;
       MyHandle,PID:longword;
       Tkernel:pchar;//为了取得指针
     begin
       if GetModule(ProcessName , DllName)=0 then  //如果已经注入就不重复了
         begin
           Tkernel:= DllName;
           Pid:=NameToPID(ProcessName);
           GetDebugPrivs;
           Myhandle:=OpenProcess(PROCESS_ALL_ACCESS, False, Pid);
           Mysize:=strlen(MyKernel)+1;
           Parameter:= VirtualAllocEx(Myhandle, nil, Mysize, MEM_COMMIT, PAGE_READWRITE);
           WriteProcessMemory(Myhandle, Parameter, Pointer(Tkernel), MySize, tmp);
           hThread:= CreateRemoteThread(Myhandle,nil,  0, GetProcAddress(GetModuleHandle('KERNEL32.DLL'), 'LoadLibraryA'), Parameter, 0 , tmp);
           if  hThread <> 0 then
             begin
               WaitForSingleObject(hThread, INFINITE); //等待线程运行完
               CloseHandle(hThread);
             end;
           VirtualFreeEx(MyHandle, Parameter, 0, MEM_RELEASE); //把用完的内存释放掉
           CloseHandle(MyHandle);
         end;
     end;procedure UnInjectKernelModule(ProcessName ,DllName: Pchar);
    //This is a function written by Hke.
    //从目标进程卸载一个DLL
     var
       tmp:longword;//这个专门来占格式收集垃圾
       hThread:longword;
       MyHandle,PID:longword;
       ModuleEntry:longword;
     begin
      Pid:=NameToPID(ProcessName);
      GetDebugPrivs;
      Myhandle:=OpenProcess(PROCESS_ALL_ACCESS, False, Pid);
      ModuleEntry:=GetModule(ProcessName ,DllName);
      if ModuleEntry<>0 then //没加载就不卸载了
        begin
          hThread:= CreateRemoteThread(Myhandle,nil,  0, GetProcAddress(GetModuleHandle('KERNEL32.DLL'), 'FreeLibrary'), pointer(ModuleEntry), 0 , tmp);
          WaitForSingleObject(hThread, INFINITE);   //等待线程运行完
          CloseHandle(hThread);
        end;
      CloseHandle(MyHandle);
     end;procedure RunFuckCAD;  //导出函数调用后屏蔽Ctrl+Alt+Del
     begin
       CreateKernelFile(string(GetSysPath)+'\'+string(MyKernel));
       //释放DLL到系统目录
       InjectKernelModule(Winlogon ,MyKernel);
       //把释放完DLL注入Winlogon进程
     end;procedure StopFuckCAD;  //导出函数取消屏蔽Ctrl+Alt+Del
     begin
       UnInjectKernelModule(Winlogon ,MyKernel);
       //从Winlogon卸载DLL
       DelKernel;
       //把Dll从系统目录删除
     end;end.//然后调用下面两个函数就可以了
    procedure RunFuckCAD;   //屏蔽Ctrl+Alt+Del
    procedure StopFuckCAD;  //取消屏蔽Ctrl+Alt+Del  
      

  4.   

    to kye_jufei  :
    能传我一份么?? 非常谢谢
    [email protected]
      

  5.   

    樓主你好:
      如果讓我傳一份GINA源碼的話,可能你需要另外開貼散分給我,我才能將GINA的源碼發給你!非GINA方法屏蔽Ctrl+Alt+Del的源碼我可以傳給你一份...