|
|||||||||||||||||||||||
|
|||||||||||||||||||||||
|
Announcements
Chapters
Services
Feature Zones
|
IntroductionThis article shows how to extend the Windows Task Manager application by using DLL injection. There are plenty of articles already that show how to use DLL injection but this article is intended to show you what you can do with it. It also gives you some nice features for Task Manager. This application consists of three separate projects:
The following extended information is given on the display dialog:
It's important to note that when this application builds, the DLLs are copied to the System32 directory, this is so that they can be found by the Task Manager application. If they are not copied there then the application won't work correctly, so if it doesn't work, first check to see if these DLLs were copied correctly by the build process. BackgroundI have done extensive work in the past with Windows hooks on many projects, that was my intent when I started this project as well. Then I found the method of using Screen shotsThis is the main application window, it's very simple. You can double click the system tray icon to hide it without exiting:
Here are the menu items that are added to the Windows Task Manager application:
Here is the dialog box that is used to display the extended information:
A look at the codeThe code is fairly light-weight, here are some of the more interesting aspects of the code. From TaskExApp, here is how it installs the void TaskExDlg::Install(HWND hWnd, DWORD pid) { m_taskManagers.insert(pid); HANDLE hProcess = OpenProcess(PROCESS_CREATE_THREAD | PROCESS_QUERY_INFORMATION | PROCESS_VM_OPERATION | PROCESS_VM_WRITE | PROCESS_VM_READ, FALSE, pid); if (hProcess != NULL) { HANDLE hThread; char szLibPath [_MAX_PATH]; void* pLibRemote = 0; DWORD hLibModule = 0; HMODULE hKernel32 = ::GetModuleHandle("Kernel32"); if( !::GetSystemDirectory(szLibPath, _MAX_PATH)) return; strcat(szLibPath, "\\InstallTaskHook.dll"); pLibRemote = ::VirtualAllocEx( hProcess, NULL, sizeof(szLibPath), MEM_COMMIT, PAGE_READWRITE ); if( pLibRemote == NULL ) return; ::WriteProcessMemory(hProcess, pLibRemote, (void*)szLibPath,sizeof(szLibPath),NULL); hThread = ::CreateRemoteThread( hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)::GetProcAddress(hKernel32, "LoadLibraryA"), pLibRemote, 0, NULL ); if( hThread != NULL ) { ::WaitForSingleObject( hThread, INFINITE ); ::GetExitCodeThread( hThread, &hLibModule ); ::CloseHandle( hThread ); } } } The code for the std::string GetCmdLineData(DWORD pid) { HANDLE hProcess = OpenProcess(PROCESS_CREATE_THREAD | PROCESS_QUERY_INFORMATION | PROCESS_VM_OPERATION | PROCESS_VM_WRITE | PROCESS_VM_READ, FALSE, pid); if (hProcess != NULL) { HANDLE hThread; char szLibPath [_MAX_PATH]; void* pLibRemote = 0; DWORD hLibModule = 0; HMODULE hKernel32 = ::GetModuleHandle("Kernel32"); ::GetSystemDirectory(szLibPath, _MAX_PATH); strcat(szLibPath, "\\TaskExHook.dll"); pLibRemote = ::VirtualAllocEx( hProcess, NULL, sizeof(szLibPath), MEM_COMMIT, PAGE_READWRITE ); if( pLibRemote == NULL ) return "Failed to get command line information...\r\n\r\n"; ::WriteProcessMemory(hProcess, pLibRemote, (void*)szLibPath,sizeof(szLibPath),NULL); hThread = ::CreateRemoteThread( hProcess, NULL, 0, (LPTHREAD_START_ROUTINE) ::GetProcAddress(hKernel32, "LoadLibraryA"), pLibRemote, 0, NULL ); if( hThread != NULL ) { ::WaitForSingleObject( hThread, INFINITE ); ::GetExitCodeThread( hThread, &hLibModule ); ::CloseHandle( hThread ); //Now uninject the DLL using FreeLibrary... ::VirtualFreeEx( hProcess, pLibRemote, sizeof(szLibPath), MEM_RELEASE ); if( hLibModule != NULL ) { hThread = ::CreateRemoteThread( hProcess, NULL, 0, (LPTHREAD_START_ROUTINE) ::GetProcAddress(hKernel32, "FreeLibrary"), (void*)hLibModule, 0, NULL ); if( hThread != NULL ) { ::WaitForSingleObject( hThread, INFINITE ); ::GetExitCodeThread( hThread, &hLibModule ); ::CloseHandle( hThread ); } } } CloseHandle(hProcess); return "Command Line:\r\n\t" + std::string(g_szCmdLine); } return "Failed to get command line information...\r\n\r\n"; } This code sets the debug privileges so that the application can inject in all other applications: void GetDebugPrivs() { HANDLE hToken; LUID sedebugnameValue; TOKEN_PRIVILEGES tp; if (::OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken)) { if ( !::LookupPrivilegeValue( NULL, SE_DEBUG_NAME, &sedebugnameValue ) ) { ::CloseHandle( hToken ); } tp.PrivilegeCount = 1; tp.Privileges[0].Luid = sedebugnameValue; tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; if ( !::AdjustTokenPrivileges( hToken, FALSE, &tp, sizeof(tp), NULL, NULL ) ) { ::CloseHandle( hToken ); } ::CloseHandle( hToken ); } } Here is where the BOOL APIENTRY DllMain(HANDLE hModule,
DWORD ul_reason_for_call, LPVOID lpReserved)
{
if( (ul_reason_for_call == DLL_PROCESS_ATTACH) )
{
EnumWindows(EnumProc, GetCurrentProcessId());
if (g_hWnd)
{
char sz[256];
SetWindowText(g_hWnd, "Extended Task Manager");
HMENU hMenu = GetMenu(g_hWnd);
int numMenus = GetMenuItemCount(hMenu);
HMENU hCheck = GetSubMenu(hMenu, numMenus - 1);
GetMenuString(hMenu, numMenus - 1, sz,
sizeof(sz), MF_BYPOSITION);
if (strcmp(sz, "Extensions"))
{
HMENU hPopup = CreatePopupMenu();
AppendMenu(hPopup, MF_STRING, 2112, "Get Extended Info");
AppendMenu(hMenu, MF_STRING | MF_ENABLED | MF_POPUP,
(UINT_PTR)hPopup, "Extensions");
//Subclass the window with our own window procedure.
wndProcOriginal = (WNDPROC)SetWindowLong(g_hWnd,
GWL_WNDPROC, (LONG)(WNDPROC)FilterProc);
DrawMenuBar(g_hWnd);
GetDebugPrivs();
}
}
}
return TRUE;
}
IssuesFor some reason, some times the Windows Task Manager application will freeze during the injection process. It doesn't happen very often so it's hard to debug. When this does happen, just bring up another instance of Task Manager and kill the previous instance. If anyone can figure out why this happens, please let me know. Also, the application was only tested on Windows XP, but it should work on 2000/XP/2003. ConclusionI hope that this article gave you a good idea on how you can use DLL injection to your advantage. Being able to control another application can give you a lot of power on the system and allow you to make simple modifications to a large application without needing the code for that application. I would also like to acknowledge the Winspy article for introducing me to the
|
||||||||||||||||||||||