更新时间:2021-07-06 11:13:12
//--------------------------------------------------------------------------- //作者 :韦覃武 //网上呢称:BCB_FANS(四大名捕之追杀令)(此为CSDN和www.driverdevelop.com之帐号) //E-Mail :slwqw@163.com //日期 :2002-10-20 // //功能 :在2000下屏蔽Ctrl + Alt + Del组合键。(在Windows 2000 Professional SP3 // 中文版平台下面测试通过) //原理 :采用远程线程注入技术,装载一个DLL到Winlogon进程,然后截获SAS窗口的窗 // 口过程,接管WM_HOTKEY消息,以达到屏蔽Ctrl + Alt + Del之目的。 //开发语言:Borland C++Builder 5.0 Patch2 //技术比较:关于在2000下面如何屏蔽Ctrl + Alt + Del组合键,一种常被提到的解决方法就 // 是使用自己写的GINA去替换MSGINA.DLL,然后在WlxLoggedOnSAS里边直接返回 // WLX_SAS_ACTION_NONE。嘿嘿,说到底这并不是真正地屏蔽了这个组合键,只是 // 直接返回WLX_SAS_ACTION_NONE时,Winlogon进程又自动从"Winlogon"桌面切换 // 回原来的"Default"桌面了,而不是显示安全对话框,所以看起来被屏蔽了:), // 使用那种方法明显地看到桌面在闪烁!但是使用本文的方法时,你不会看到任 // 何闪烁! //鸣谢 :www.driverdevelop.com上的icube和lu0。 //版权 :转载请注明原作者:) //--------------------------------------------------------------------------- #include "stdafx.h" #include using namespace std; //--------------------------------------------------------------------------- HWND hSASWnd; FARPROC FOldProc; LRESULT CALLBACK SASWindowProc(HWND hwnd,UINT uMsg,WPARAM wParam,LPARAM lParam); BOOL CALLBACK EnumWindowsProc(HWND hwnd,LPARAM lParam); //--------------------------------------------------------------------------- HANDLE hThread = NULL; DWORD dwThreadId; DWORD WINAPI ThreadFunc(); //--------------------------------------------------------------------------- BOOL APIENTRY DllMain( HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) { switch(ul_reason_for_call) { case DLL_PROCESS_ATTACH : hThread = CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)ThreadFunc,NULL,0,&dwThreadId); break; case DLL_PROCESS_DETACH : if(FOldProc != NULL) { SetWindowLong(hSASWnd,GWL_WNDPROC,long(FOldProc)); } CloseHandle(hThread); break; } return TRUE; } //--------------------------------------------------------------------------- DWORD WINAPI ThreadFunc() { HDESK hDesk; hDesk = OpenDesktop("Winlogon",0,false,MAXIMUM_ALLOWED); FOldProc = NULL; hSASWnd = NULL; EnumDesktopWindows(hDesk,(WNDENUMPROC)EnumWindowsProc,0); if(hSASWnd != NULL) { FOldProc = (FARPROC)SetWindowLong(hSASWnd,GWL_WNDPROC,long(SASWindowProc)); } CloseHandle(hDesk); return 1; } //--------------------------------------------------------------------------- //查找"Winlogon"桌面的窗口 BOOL CALLBACK EnumWindowsProc(HWND hwnd,LPARAM lParam) { char ClassBuf[128]; GetWindowText(hwnd,ClassBuf,sizeof(ClassBuf)); //我自己写了一个系统服务,然后在里边查询"Winlogon"桌面上的窗口,发现桌面上存在 //窗口"SAS window"。 string ClassName(ClassBuf); if(ClassName.find("SAS window") != -1) { hSASWnd = hwnd; return false; } return true; } //--------------------------------------------------------------------------- //SAS窗口的窗口过程 LRESULT CALLBACK SASWindowProc(HWND hwnd,UINT uMsg,WPARAM wParam,LPARAM lParam) { //屏蔽Ctrl + Alt + Del if(uMsg == WM_HOTKEY) { WORD wKey = HIWORD(lParam); WORD wModifier = LOWORD(lParam); bool IsCtrlDown = ((wModifier & VK_CONTROL) != 0); bool IsAltDown = ((wModifier & VK_MENU) != 0); bool IsShiftDown = ((wModifier & VK_SHIFT) != 0); //按下Ctrl + Alt + Del组合键 if(IsCtrlDown && IsAltDown && wKey == VK_DELETE) { return 1; } //按下Ctrl + Shift + Esc组合键,这个组合键将显示任务管理器,可根据需要是否屏蔽。 else if(IsCtrlDown && IsShiftDown && wKey == VK_ESCAPE) { // Do nothing } } return CallWindowProc((WNDPROC)FOldProc,hwnd,uMsg,wParam,lParam); } //---------------------------------------------------------------------------这样,如果Winlogon加载了这个动态连接库,那么就替换了SAS窗口的窗口过程。如果Winlogon卸载了这个动态连接库,则恢复了SAS窗口的窗口过程。
//--------------------------------------------------------------------------- //作者 :韦覃武,jiangsheng //网上呢称:BCB_FANS(四大名捕之追杀令)(此为CSDN和www.driverdevelop.com之帐号)jiangsheng(此为CSDN帐号) //E-Mail :slwqw@163.com //日期 :2002-10-20 //2002-11-5 jingsheng修改 //功能 :在2000下屏蔽Ctrl + Alt + Del组合键。(在Windows 2000 Professional SP3 // 中文版平台下面测试通过) //原理 :采用远程线程注入技术,装载一个DLL到Winlogon进程,然后截获SAS窗口的窗 // 口过程,接管WM_HOTKEY消息,以达到屏蔽Ctrl + Alt + Del之目的。 //开发语言:Borland C++Builder 5.0 Patch2,Visual C++ 6.0 SP5 //技术比较:关于在2000下面如何屏蔽Ctrl + Alt + Del组合键,一种常被提到的解决方法就 // 是使用自己写的GINA去替换MSGINA.DLL,然后在WlxLoggedOnSAS里边直接返回 // WLX_SAS_ACTION_NONE。嘿嘿,说到底这并不是真正地屏蔽了这个组合键,只是 // 直接返回WLX_SAS_ACTION_NONE时,Winlogon进程又自动从"Winlogon"桌面切换 // 回原来的"Default"桌面了,而不是显示安全对话框,所以看起来被屏蔽了:), // 使用那种方法明显地看到桌面在闪烁!但是使用本文的方法时,你不会看到任 // 何闪烁! //鸣谢 :www.driverdevelop.com上的icube和lu0。 //版权 :转载请注明原作者:) //--------------------------------------------------------------------------- #include "stdafx.h" #include #include #include "Hook.h" //add by jiangsheng 2002-11-5 #include "TaskKeyMgr.h" #include "Wrappers.h"// 复制自MSDN杂志 Windows XP Escape from DLL Hell with Custom Debugging and Instru****tion Tools and Utilities 的代码 extern BOOL Is_Terminal_Services () ;//复制自Platform SDK文档: Windows System Information /Verifying the System Version //end add by jiangsheng 2002-11-5 //--------------------------------------------------------------------------- //错误代码格式化函数 //replaced by jiangsheng 2002-11-5 //from Q149409 HOWTO: Get Message Text from Networking Error Codes CString __fastcall SysErrorMessage(DWORD dwLastError ) { CString strRet(_T("Unknown error")); HMODULE hModule = NULL; // default to system source LPSTR MessageBuffer; DWORD dwBufferLength; DWORD dwFormatFlags = FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_SYSTEM ; // // If dwLastError is in the network range, // load the message source. // if(dwLastError >= NERR_BASE && dwLastError <= MAX_NERR) { hModule = LoadLibraryEx(TEXT("netmsg.dll"),NULL,LOAD_LIBRARY_AS_DATAFILE); if(hModule != NULL) dwFormatFlags |= FORMAT_MESSAGE_FROM_HMODULE; } // // Call FormatMessage() to allow for message // text to be acquired from the system // or from the supplied module handle. // if(dwBufferLength = FormatMessageA( dwFormatFlags, hModule, // module to get message from (NULL == system) dwLastError, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // default language (LPSTR) &MessageBuffer, 0, NULL )) { // // Output message string on stderr. // strRet=CString(MessageBuffer,dwBufferLength); // // Free the buffer allocated by the system. // LocalFree(MessageBuffer); } // // If we loaded a message source, unload it. // if(hModule != NULL) FreeLibrary(hModule); return strRet; } //end replaced by jiangsheng 2002-11-5 //--------------------------------------------------------------------------- #ifdef UNICODE LPCSTR LoadLibraryFuncStr = "LoadLibraryW"; LPCSTR GetModuleHandleFuncStr = "GetModuleHandleW"; #else LPCSTR LoadLibraryFuncStr = "LoadLibraryA"; LPCSTR GetModuleHandleFuncStr = "GetModuleHandleA"; #endif LPCSTR FreeLibraryFuncStr = "FreeLibrary"; LPCSTR GetProcAddressFuncStr = "GetProcAddress"; LPCSTR GetLastErrorFuncStr = "GetLastError"; //--------------------------------------------------------------------------- //removed by jiangsheng 2002-11-5 //const char* const RemoteDllName = "RemoteDll.Dll"; //end removed by jiangsheng 2002-11-5 LPCTSTR szRemoteProcessName = "Winlogon.exe"; typedef HINSTANCE (WINAPI *PLOADLIBRARY)(LPCTSTR ); typedef BOOL (WINAPI *PFREELIBRARY)(HINSTANCE); typedef HMODULE (WINAPI* PGETMODULEHANDLE)(LPCTSTR ); typedef PVOID (WINAPI* PGETPROCADDRESS)(HINSTANCE,LPCSTR); typedef DWORD (WINAPI* PGETLASTERROR)(VOID); BOOL __fastcall EnablePrivilege(LPCTSTR lpszPrivilegeName,BOOL bEnable); DWORD __fastcall GetPIDFromName(LPCTSTR lpszProcName); //--------------------------------------------------------------------------- typedef struct { PLOADLIBRARY pfnLoadLibrary; PGETLASTERROR pfnGetLastError; TCHAR szDllName[1024]; DWORD dwReturnValue; } INJECTLIBINFO; typedef struct { PFREELIBRARY pfnFreeLibrary; PGETMODULEHANDLE pfnGetModuleHandle; PGETLASTERROR pfnGetLastError; DWORD dwReturnValue; TCHAR szDllName[1024]; } DEINJECTLIBINFO; //--------------------------------------------------------------------------- //远程线程,用来装载DLL static DWORD WINAPI ThreadFuncAttach(INJECTLIBINFO *pInfo) { HINSTANCE hDll=NULL; pInfo->dwReturnValue = 0; hDll = (HINSTANCE)pInfo->pfnLoadLibrary(pInfo->szDllName); if(hDll == NULL) pInfo->dwReturnValue = pInfo->pfnGetLastError(); return((DWORD)hDll); } //--------------------------------------------------------------------------- //占位函数,用来计算ThreadFuncAttach的大小 static void AfterThreadFuncAttach(void) { } //--------------------------------------------------------------------------- //远程线程,用来卸载DLL static DWORD WINAPI ThreadFuncDetach(DEINJECTLIBINFO *pInfo) { HINSTANCE hDll = NULL; BOOL bResult=FALSE; BOOL bHasFoundModule = FALSE; pInfo->dwReturnValue = 0;//意味成功,如果这个值不是0,则是一个错误代码。 while((hDll = pInfo->pfnGetModuleHandle(pInfo->szDllName)) != NULL) { bHasFoundModule = TRUE; bResult = pInfo->pfnFreeLibrary(hDll); if(bResult == FALSE) { pInfo->dwReturnValue = pInfo->pfnGetLastError(); break; } } if(pInfo->dwReturnValue == 0 && !bHasFoundModule) { pInfo->dwReturnValue = pInfo->pfnGetLastError(); } return 1; } //--------------------------------------------------------------------------- //占位函数,用来计算ThreadFuncDetach的大小 static void AfterThreadFuncDetach(void) { } //--------------------------------------------------------------------------- //修改本进程的权限 BOOL __fastcall EnablePrivilege(LPCTSTR lpszPrivilegeName,BOOL bEnable) { HANDLE hToken; TOKEN_PRIVILEGES tp; LUID luid; if(!OpenProcessToken(GetCurrentProcess(),TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY | TOKEN_READ,&hToken)) return FALSE; if(!LookupPrivilegeValue(NULL, lpszPrivilegeName, &luid)) return TRUE; tp.PrivilegeCount = 1; tp.Privileges[0].Luid = luid; tp.Privileges[0].Attributes = (bEnable) ? SE_PRIVILEGE_ENABLED : 0; AdjustTokenPrivileges(hToken,FALSE,&tp,NULL,NULL,NULL); CloseHandle(hToken); return (GetLastError() == ERROR_SUCCESS); } //--------------------------------------------------------------------------- //通过进程名称得到进程的ID(这里使用方法Toolhelp函数,也可使用PSAPI) DWORD __fastcall GetPIDFromName(LPCTSTR lpszProcName) { HANDLE hSnapshot; PROCESSENTRY32 ProcStruct; DWORD dwProcessID = -1; //added by jiangsheng 2002-11-8 BOOL bIsTerminalServices=Is_Terminal_Services(); if(bIsTerminalServices){ //复制自MSDN杂志Windows XP Escape from DLL Hell with Custom Debugging and Instru****tion Tools and Utilities的代码 //get current session ID CWTSWrapper WTS; if (WTS.IsValid()) { DWORD dwCurSessionID = -1; LPTSTR pSessionInfo=NULL; DWORD dwBytes; if(WTS.WTSQuerySessionInformation(WTS_CURRENT_SERVER_HANDLE,WTS_CURRENT_SESSION, WTSSessionId, (LPTSTR*)&pSessionInfo, &dwBytes)){ dwCurSessionID =*((DWORD*)pSessionInfo); // enumerate processes PWTS_PROCESS_INFO pProcessInfo = NULL; DWORD ProcessCount = 0; BOOL bFound; if (WTS.WTSEnumerateProcesses(WTS_CURRENT_SERVER_HANDLE, 0, 1, &pProcessInfo, &ProcessCount)){ for (DWORD CurrentProcess = 0; CurrentProcess < ProcessCount; CurrentProcess++){ CString strCurExePath(pProcessInfo[CurrentProcess].pProcessName); CString strRemoteProc(lpszProcName); strCurExePath.MakeLower(); strRemoteProc.MakeLower(); bFound = (strCurExePath.Find(strRemoteProc) != -1); if(bFound && dwCurSessionID==pProcessInfo[CurrentProcess].SessionId) { dwProcessID = pProcessInfo[CurrentProcess].ProcessId; break; } } } WTS.WTSFreeMemory(pSessionInfo); } } } else{ //end added by jiangsheng 2002-11-8 BOOL bResult; hSnapshot = CreateToolhelp32Snapshot((DWORD)TH32CS_SNAPPROCESS,0); ProcStruct.dwSize = sizeof(PROCESSENTRY32); bResult = Process32First(hSnapshot,&ProcStruct); while(bResult) { BOOL bFound; CString strCurExePath(ProcStruct.szExeFile); CString strRemoteProc(lpszProcName); strCurExePath.MakeLower(); strRemoteProc.MakeLower(); bFound = (strCurExePath.Find(strRemoteProc) != -1); if(bFound) { dwProcessID = ProcStruct.th32ProcessID; break; } bResult = Process32Next(hSnapshot,&ProcStruct); } CloseHandle(hSnapshot); } return dwProcessID; } //--------------------------------------------------------------------------- // 插入代码 //--------------------------------------------------------------------------- //InjectFunc void __fastcall InjectFunc() { HANDLE hRemoteProcess=NULL; DWORD dwRemoteProcess=NULL; DWORD dwThreadSize=0; INJECTLIBINFO InjectLibInfo; PVOID pRemoteThread=NULL; PVOID pRemoteParam=NULL; DWORD dwWriten=0; DWORD dwRet=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(&InjectLibInfo,sizeof(INJECTLIBINFO )); InjectLibInfo.pfnLoadLibrary = (PLOADLIBRARY)GetProcAddress(GetModuleHandle("Kernel32.dll"),LoadLibraryFuncStr); InjectLibInfo.pfnGetLastError = (PGETLASTERROR)GetProcAddress(GetModuleHandle("Kernel32.dll"),GetLastErrorFuncStr); lstrcpyn(InjectLibInfo.szDllName,CTaskKeyMgr::strRemoteDllName,CTaskKeyMgr::strRemoteDllName.GetLength()+1); //在远程线程分配内存来存放参数 pRemoteParam = VirtualAllocEx(hRemoteProcess,NULL,sizeof(INJECTLIBINFO),MEM_COMMIT,PAGE_READWRITE); if(pRemoteParam == NULL) { MessageBox(NULL,_T("Failed to Allocate Memory at Remote Process for Param.Err = ") + SysErrorMessage(GetLastError()), NULL,MB_OK | MB_APPLMODAL | MB_ICONWARNING); return; } dwRet = WriteProcessMemory(hRemoteProcess,pRemoteParam,(LPVOID)&InjectLibInfo,sizeof(INJECTLIBINFO),&dwWriten); if(dwRet == 0) { MessageBox(NULL,_T("Failed to Write Param to Remote Process.Err = ") + SysErrorMessage(GetLastError()), NULL,MB_OK | MB_APPLMODAL | MB_ICONWARNING); return; } //拷贝线程体 dwThreadSize = (int)AfterThreadFuncAttach - (int)ThreadFuncAttach + 1024 + sizeof(INJECTLIBINFO); 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; } dwRet = WriteProcessMemory(hRemoteProcess,pRemoteThread,(LPVOID)ThreadFuncAttach,dwThreadSize,&dwWriten); if(dwRet == 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,(INJECTLIBINFO*)pRemoteParam,0,&dwWriten); ::WaitForSingleObject(hRemoteThread,INFINITE); if(hRemoteThread == NULL) { MessageBox(NULL,_T("Failed to create unload thread.Err=") + SysErrorMessage(GetLastError()),NULL,MB_OK |MB_APPLMODAL | MB_ICONWARNING); } else { ; } //读卸载返回值 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; } }注意
HWND FindWindow( LPCTSTR lpClassName, // pointer to class name LPCTSTR lpWindowName // pointer to window name );2.采用GetProcAddress得到窗口相对应的进程ID,函数用法如下:
FARPROC GetProcAddress( HMODULE hModule, // handle to DLL module LPCSTR lpProcName // function name );3.得到进程ID后,接下来的事是要以最高权限打开进程,所用到的函数OpenProcess的具体使用方法如下:
HANDLE OpenProcess( DWORD dwDesiredAccess, // access flag BOOL bInheritHandle, // handle inheritance flag DWORD dwProcessId // process identifier );在DwDesiredAccess之处就是设存取方式的地方,可设的权限很多,这里只使用PROCESS_ALL_ACCESS来打开进程就可以,更详细可查阅MSDN。
BOOL WriteProcessMemory( HANDLE hProcess, // handle to process whose memory is written to LPVOID lpBaseAddress, // address to start writing to LPVOID lpBuffer, // pointer to buffer to write data to DWORD nSize, // number of bytes to write LPDWORD lpNumberOfBytesWritten // actual number of bytes written );5.创建远程线程以运行所嵌入的代码。
HANDLE CreateRemoteThread( HANDLE hProcess, // handle to process LPSECURITY_ATTRIBUTES lpThreadAttributes, // SD DWORD dwStackSize, // initial stack size LPTHREAD_START_ROUTINE lpStartAddress, // thread function LPVOID lpParameter, // thread argument DWORD dwCreationFlags, // creation option LPDWORD lpThreadId // thread identifier );6.CloseHandle(HANDLE hObject)关闭进程句柄。
BOOL EnablePrivilege(LPCTSTR lpszPrivilegeName, BOOL bEnable) { HANDLE hToken; TOKEN_PRIVILEGES tp; LUID luid; BOOL ret; if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY | TOKEN_READ, &hToken)) return FALSE; if (!LookupPrivilegeValue(NULL, lpszPrivilegeName, &luid)) return FALSE; tp.PrivilegeCount = 1; tp.Privileges[0].Luid = luid; tp.Privileges[0].Attributes = bEnable ? SE_PRIVILEGE_ENABLED : 0; ret = AdjustTokenPrivileges(hToken, FALSE, &tp, 0, NULL, NULL); CloseHandle(hToken); return ret; } DWORD GetPIDFromName(char *szProcessName) { DWORD dwPID; OSVERSIONINFO info; info.dwOSVersionInfoSize = sizeof(info); GetVersionEx(&info); // 根据Windows操作系统版本的不同选择不同函数进行处理 if (info.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS) dwPID = GetPIDFromNameToolhelp(szProcessName); else if (info.dwPlatformId == VER_PLATFORM_WIN32_NT) dwPID = GetPIDFromNamePSAPI(szProcessName); else dwPID = -1; return dwPID; }2. 定义全局数据变量,准备线程的参数结构
char *szProcessName = "winlogon.exe"; #pragma comment(linker, "/INCRE****L:NO") // 关闭增量链接模式 // 全局变量定义 DWORD PID; // 代码嵌入进程的PID BYTE *pDataRemote; // INJECTDATA 数据结构在远程线程的地址 BYTE *pSASWinProcRemote; // 函数SASWindowProc()在远程线程的地址 #define DUMMY_ADDR 0x12345678 // INJECTDATA 数据结构的动态地址 // INJECTDATA: 每个远程代码嵌入函数所存贮的内存块,传递每个嵌入函数的地址或字符数据 typedef LONG (WINAPI *SETWINDOWLONG) (HWND, int, LONG); typedef LRESULT (WINAPI *CALLWINDOWPROC) (WNDPROC, HWND, UINT, WPARAM, LPARAM); typedef HWND (WINAPI *FINDWINDOW) (LPCTSTR, LPCTSTR);定义线程所嵌入代码的地址结构:
typedef struct { SETWINDOWLONG fnSetWindowLong; // SetWindowLong()函数地址 CALLWINDOWPROC fnCallWindowProc; // CallWindowProc()函数地址 FINDWINDOW fnFindWindow; // FindWindow()函数地址 char szClassName[50]; // 类名称为"SAS Window class" char szWindowName[50]; // 窗口名称为"SAS window" HWND hwnd; // 进程所嵌入的窗口句柄 WNDPROC fnSASWndProc; // 远程SASWindowProc 地址 WNDPROC fnOldSASWndProc; // 原始SASWindowProc 地址 } INJECTDATA, *PINJECTDATA;3. 定义嵌入代码的功能函数
#pragma optimize("", off) #pragma check_stack(off) static LRESULT CALLBACK SASWindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { // INJECTDATA 结构指针必须在运行时处理 INJECTDATA* pData = (INJECTDATA *)DUMMY_ADDR; if (uMsg == WM_HOTKEY) { // Ctrl+Alt+Del if (lParam == MAKELONG(MOD_CONTROL | MOD_ALT, VK_DELETE)) return 1; // Ctrl+Shift+Esc if (lParam == MAKELONG(MOD_CONTROL | MOD_SHIFT, VK_ESCAPE)) return 1; } // 缺省处理 return pData->fnCallWindowProc(pData->fnOldSASWndProc, hwnd, uMsg, wParam, lParam); } static int AfterSASWindowProc(void) { return 1; } Socket:假如这两个函数是上述排列,下面语句可得到嵌入线程代码的长度: DWORD size = (PBYTE)AfterSASWindowProc - (PBYTE)SASWindowProc;4. 远程线程嵌入代码实现
// 在远程线程内分配内存并存放函数InjectFunc()的拷贝 size = (PBYTE)AfterInjectFunc - (PBYTE)InjectFunc; pCodeRemote = (PBYTE) VirtualAllocEx(hProcess, 0, size, MEM_COMMIT, PAGE_EXECUTE_READWRITE); if (!pCodeRemote) __leave; if (!WriteProcessMemory(hProcess, pCodeRemote, &InjectFunc, size, &dwNumBytesCopied) || dwNumBytesCopied != size) __leave; // 远程调用函数InjectFunc()的代码 hThread = CreateRemoteThread(hProcess, NULL, 0, (LPTHREAD_START_ROUTINE) pCodeRemote, pDataRemote, 0 , &dwThreadId); if (!hThread) __leave; // 等待函数InjectFunc() 执行结束并得到返回码 WaitForSingleObject(hThread, INFINITE); GetExitCodeThread(hThread, (PDWORD) &nSuccess); // 成功 if (nSuccess) MessageBeep(MB_OK);5. 复原系统设置
// 释放结构INJECTDATA和函数SASWindowProc()所占内存 if (pDataRemote) VirtualFreeEx(hProcess, pDataRemote, 0, MEM_RELEASE); if (pSASWinProcRemote) VirtualFreeEx(hProcess, pSASWinProcRemote, 0, MEM_RELEASE); pDataRemote = NULL; pSASWinProcRemote = NULL; MessageBeep(MB_OK); // 成功 END: // 如果API调用出错,程序转向此进行清除处理 if (hThread) CloseHandle(hThread); // 释放函数EjectFunc() 所占用的内存 if (pCodeRemote) VirtualFreeEx(hProcess, pCodeRemote, 0, MEM_RELEASE); CloseHandle(hProcess); // 恢复原先权限,禁止调试权限 EnablePrivilege(SE_DEBUG_NAME, FALSE); return nSuccess; // 0 = failure; 1 = success演 示程序在Windows2K+SP4平台上用VC6.0+SP6调试通过,在NT/XP平台上测试正常。程序代码中根据需要实时对编译器环境作了调整,关 闭了增量链接模式、优化和堆栈检查功能。由于DEBUG开发环境的设置出现了编译警告,但在RELEASE环境中编译正常。代码经过优化修改后已被某商用 项目采用,较圆满实现了锁定NT/2K/XP的特殊组合键Ctrl+Del+Alt,最后感谢《黑客防线》编程类文章给予作者的灵感!