在软件开发中,经常会遇到需要在没有源代码的情况下,对其他进程进行操作的需求。例如,可能需要在Microsoft Word、Excel或其他应用程序中改变样式对话框。这种情况下,可以通过内核模式来实现对系统进程的访问。
内核模式是指在操作系统中,具有最高权限的执行模式。在这种模式下,可以访问系统的任何进程,包括内核系统进程。要实现这种访问,可以使用一些未公开的函数,这些函数通常存在于coredll.dll中。
C++
extern
"
C"
{
BOOL SetKMode(BOOL fMode);
DWORD SetProcPermissions(DWORD);
LPVOID MapPtrToProcess (LPVOID lpv, HANDLE hProc);
DWORD PerformCallBack4(PCALLBACKINFO pcbi, ...);
//execute function
//inside process
}
首先,需要通过SetKMode函数来启用内核模式,然后通过SetProcPermissions函数来设置进程权限。这样,就可以访问其他进程了。
C++
BOOL bMode = SetKMode(TRUE);
DWORD dwPerm = SetProcPermissions(0xFFFFFFFF);
假设想在note.exe进程中加载一个DLL,但是没有note.exe的源代码。在这种情况下,可以使用PerformCallBack函数来实现。
C++
HANDLE hProcess=GetProcessHandle(L"notes.exe");
CALLBACKINFO cbi;
cbi.hProc = hProcess;
cbi.pfn = (FARPROC)MapPtrToProcess(GetProcAddress(GetModuleHandle(L"COREDLL"), L"LoadLibraryW"), hProcess);
cbi.pvArg0 = (LPVOID)MapPtrToProcess(L"\\windows\\mydll.dll", GetCurrentProcess());
HINSTANCE hInst = (HINSTANCE)PerformCallBack4(&cbi, 0, 0, 0);
这段代码首先获取了note.exe进程的句柄,然后通过PerformCallBack函数将mydll.dll加载到note.exe进程的地址空间中。
接下来,需要检查mydll.dll是否已经成功加载到note.exe进程中。可以通过远程进程视图来检查。
现在,mydll.dll已经加载到note.exe进程中,任务是子类化编辑控件。为了获取句柄,需要打开note.exe,并使用RemoteSpy工具。
C++
HWND m_hWnd=::GetForegroundWindow();
m_hWnd=::GetWindow(m_hWnd,GW_CHILD);
m_hWnd=::GetWindow(m_hWnd,GW_CHILD);
cbi.hProc = hProcess;
cbi.pfn = (FARPROC)MapPtrToProcess(GetProcAddress(hInst, L"SubClassEdit"), hProcess);
cbi.pvArg0 = m_hWnd;
hInst = (HINSTANCE)PerformCallBack4(&cbi, 0, 0, 0);
这段代码首先获取了note.exe的窗口句柄,然后通过PerformCallBack函数调用子类化函数SubClassEdit。
子类化是一种技术,它允许一个应用程序拦截发送到另一个窗口的消息。通过子类化,可以增强、监控或修改窗口的默认行为,而无需重新开发窗口。子类化默认的控件窗口类(按钮控件、编辑控件、列表控件、组合框控件、静态控件和滚动条控件)是一种方便的方式来获取控件的功能并修改其行为。例如,如果一个对话框中包含一个多行编辑控件,并且用户按下了ENTER键,对话框将关闭。通过子类化编辑控件,应用程序可以使编辑控件在文本中插入一个回车符和换行符,而不退出对话框。
在子类化理论中,应该获取并保存旧的进程句柄,以便在需要时使用它。
C++
g_pOldWndProc = (WNDPROC)GetWindowLong(m_editHandle, GWL_WNDPROC);
SetWindowLong(m_editHandle, GWL_WNDPROC, (LONG)EditTopmostProc);
在EditTopmostProc函数中,想要替换WM_KILLFOCUS消息,否则将调用原始的进程。
C++
if (uMsgs == WM_KILLFOCUS)
{
GetWindowText(hWnd,buffer,1025);
MessageBox(hWnd,buffer,L"you saved",MB_OK);
return CallWindowProc(g_pOldWndProc, hWnd, uMsgs, wParam, lParam);
}
return CallWindowProc(g_pOldWndProc, hWnd, uMsgs, wParam, lParam);
在这段代码中,首先获取了编辑控件的旧窗口过程句柄,然后设置了自己的窗口过程。在EditTopmostProc函数中,替换了WM_KILLFOCUS消息,否则将调用原始的进程。