//读卸载返回值
dwRet =ReadProcessMemory(hRemoteProcess,pRemoteParam,(LPVOID)&InjectLibInfo,sizeof(INJECTLIBINFO),&dwWriten);
if(dwRet == 0)
{
MessageBox(NULL,_T(“Unable to read load return value.Err=”) + SysErrorMessage(GetLastError()),
NULL,MB_OK | MB_APPLMODAL | MB_ICONWARNING);
}
else
{
if(InjectLibInfo.dwReturnValue == 0)
{
;
}
else
{
MessageBox(NULL,_T(“Failed to load library to Winlogon.Err=”) +SysErrorMessage(InjectLibInfo.dwReturnValue),NULL,MB_OK | MB_APPLMODAL | MB_ICONWARNING);
}
}
//恢复权限
EnablePrivilege(SE_DEBUG_NAME,false);
CloseHandle(hRemoteProcess);
}
//—————————————————————————
// 卸载线程
//—————————————————————————
//DeinjectFunc
void __fastcall DeinjectFunc()
{
HANDLE hRemoteProcess=NULL;
DWORD dwRemoteProcess=0;
DWORD dwThreadSize=0;
DEINJECTLIBINFO DeinjectLibInfo;
PVOID pRemoteThread=NULL;
PVOID pRemoteParam=NULL;
DWORD dwWriten=0;
DWORD Ret=0;
//提升本进程权限然后打开目的进程
EnablePrivilege(SE_DEBUG_NAME,true);
dwRemoteProcess = GetPIDFromName(szRemoteProcessName);
if(dwRemoteProcess == (DWORD)-1)
{
MessageBox(NULL,_T(“Failed to Query Process ID.”),NULL,MB_OK | MB_APPLMODAL | MB_ICONWARNING);
return;
}
hRemoteProcess = OpenProcess(PROCESS_ALL_ACCESS,false,dwRemoteProcess);
if(hRemoteProcess == NULL)
{
MessageBox(NULL,_T(“Failed to Open Process. Err = “) + SysErrorMessage(GetLastError()),
NULL,MB_OK | MB_APPLMODAL | MB_ICONWARNING);
return;
}
//初始化参数
ZeroMemory(&DeinjectLibInfo,sizeof(DEINJECTLIBINFO ));
DeinjectLibInfo.pfnFreeLibrary = (PFREELIBRARY)GetProcAddress(GetModuleHandle(“Kernel32.dll”),FreeLibraryFuncStr);
DeinjectLibInfo.pfnGetModuleHandle = (PGETMODULEHANDLE)GetProcAddress(GetModuleHandle(“Kernel32.dll”),GetModuleHandleFuncStr);
DeinjectLibInfo.pfnGetLastError = (PGETLASTERROR)GetProcAddress(GetModuleHandle(“Kernel32.dll”),GetLastErrorFuncStr);
lstrcpyn(DeinjectLibInfo.szDllName,CTaskKeyMgr::strRemoteDllName,CTaskKeyMgr::strRemoteDllName.GetLength()+1);
//在远程线程分配内存来存放参数
pRemoteParam = VirtualAllocEx(hRemoteProcess,NULL,sizeof(DEINJECTLIBINFO),MEM_COMMIT,PAGE_READWRITE);
if(pRemoteParam == NULL)
{
MessageBox(NULL,_T(“Failed to Allocate Memory at Remote Process.Err = “) + SysErrorMessage(GetLastError()),
NULL,MB_OK | MB_APPLMODAL | MB_ICONWARNING);
}
Ret = WriteProcessMemory(hRemoteProcess,pRemoteParam,(LPVOID)&DeinjectLibInfo,sizeof(DEINJECTLIBINFO),&dwWriten);
if(Ret == 0)
{
MessageBox(NULL,_T(“Failed to Write Param to Remote Process.Err = “) + SysErrorMessage(GetLastError()),
NULL,MB_OK | MB_APPLMODAL | MB_ICONWARNING);
return;
}
//拷贝线程体
dwThreadSize = (int)AfterThreadFuncDetach – (int)ThreadFuncDetach + 1024 + sizeof(DEINJECTLIBINFO);
pRemoteThread = VirtualAllocEx(hRemoteProcess,NULL,dwThreadSize,MEM_COMMIT,PAGE_READWRITE);
if(pRemoteThread == NULL)
{
MessageBox(NULL,_T(“Failed to Allocate Memory at Remote Process for Thread Code.Err = “) + SysErrorMessage(GetLastError()),
NULL,MB_OK | MB_APPLMODAL | MB_ICONWARNING);
return;
}
Ret = WriteProcessMemory(hRemoteProcess,pRemoteThread,(LPVOID)ThreadFuncDetach,dwThreadSize,&dwWriten);
if(Ret == 0)
{
MessageBox(NULL,_T(“Failed to Write Thread Code to Remote Process.Err = “) + SysErrorMessage(GetLastError()),
NULL,MB_OK | MB_APPLMODAL | MB_ICONWARNING);
return;
}
//启动远程线程
HANDLE hRemoteThread;
hRemoteThread = CreateRemoteThread(hRemoteProcess ,0,0,(DWORD(__stdcall *)(VOID*))pRemoteThread,(DEINJECTLIBINFO*)pRemoteParam,0,&dwWriten);
if(hRemoteThread == NULL)
{
MessageBox(NULL,_T(“Failed to create remote unload thread.Err=”) + SysErrorMessage(GetLastError()),NULL,MB_OK | MB_APPLMODAL | MB_ICONWARNING);
}
else
{
CloseHandle(hRemoteThread);
}
//读卸载返回值
Ret = ReadProcessMemory(hRemoteProcess,pRemoteParam,(LPVOID)&DeinjectLibInfo,sizeof(DEINJECTLIBINFO),&dwWriten);
if(Ret == 0)
{
MessageBox(NULL,_T(“Unable to read unload return value.Err=”) + SysErrorMessage(GetLastError()),
NULL,MB_OK | MB_APPLMODAL | MB_ICONWARNING);
}
else
{
if(DeinjectLibInfo.dwReturnValue == 0)
{
}
else
{
MessageBox(NULL,_T(“Failed to unload .Err=”)+ SysErrorMessage(DeinjectLibInfo.dwReturnValue),NULL,MB_OK | MB_APPLMODAL | MB_ICONWARNING);
}
}
//恢复权限
CloseHandle(hRemoteProcess);
EnablePrivilege(SE_DEBUG_NAME,false);
}
//—————————————————————————
//使用方法
BOOL CTaskKeyMgr::IsCtrlAltDeleteDisabled(){return bInjectFuncLoaded;}
if (dwFlags & CTRLALTDEL) {
if(bDisable&&!IsCtrlAltDeleteDisabled()){
InjectFunc();
bInjectFuncLoaded=TRUE;
}
if(!bDisable&&IsCtrlAltDeleteDisabled()){
DeinjectFunc();
bInjectFuncLoaded=FALSE;
}
}
注意
如果Windows的后续版本更改了Ctrl+Alt+Delete的处理,本文所提供的技术可能不再工作。如果你在你的代码中使用了本文的技术,请注意你可能必须在未来修改你的代码。
已知问题
尚无Unicode版本
VirtualAllocEx分配的内存没有用VirtualFreeEx释放
在Debug方式下运行会造成Winlogon出错(出错后请不要确认或取消那个出错对话框,然后保存打开的所有文档,关闭所有程序,通过正常的途径关机,否则Windows会立刻关机)
参考
如果需要更多信息,单击下面的连接查看CSDN论坛中的讨论
在NT/2000中怎么禁用Ctrl+Alt+Delete?(不能用gina,键盘驱动) 。
单击这里下载本文的代码。
MSDN文档库中的文章
Q226359 HOWTO: Disable Task Switching on Win32 Platforms
Q195027 STOP 0xC000021A in Winlogon Caused by PCAnywhere
Q229033 Programs That Replace Msgina.dll May Cause “STOP 0x0000001E” Error Message
Q192298 Third Party GINAs May Fail with Service Pack 4 Causing STOP 0x21A in WINLOGON
Q164486 Winlogon May Fail if the Third-Party Gina.dll File is Missing or Corrupted
Q180854 Access Violation in Winlogon with Third-Party Gina.dll
Q193361 MSGINA.DLL does not Reset WINLOGON Structure
MSDN杂志中的文章
MSDN Magazine > September 2002 > Typename, Disabling Keys in Windows XP with TrapKeys(Paul DiLascia)
MSDN Magazine > June 2002 > Windows XP Escape from DLL Hell with Custom Debugging and Instrumentation Tools and Utilities
VC知识库中的文章
Windows XP系统中如何屏蔽 Ctrl+Alt+Del、Alt+Tab以及Ctrl+Esc键序列