Jump to content
Nytro

Extending Task Manager with DLL Injection

Recommended Posts

Extending Task Manager with DLL Injection

By rocky_pulley | 19 May 2005

Cod sursa:

http://www.codeproject.com/KB/threads/taskex/taskex.zip

Introduction

This 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:

TaskExApp

This is an application that sits in the background waiting for instances of Windows Task Manager to popup. It loops through the top level windows every 1 second looking for instances. When an instance is detected, it will inject the InstallTaskHook DLL into the process. This application has a system tray icon that will show and hide the application dialog box when double-clicked. To end the process, just click the "Exit" button.

InstallTaskHook

This is a DLL that is injected into the Windows Task Manager application. On injection, it creates an extra menu on the application's main menu called "Extensions". In this menu there is a sub menu "Get Extended Info" which will display a dialog box of extended data for the application that is selected in the processes list. You must select an item in the processes list and the PID field must be visible for this to work correctly.

TaskExHook

This DLL is injected into the application by the Task Manager hook to get the extended information. Currently the only extra information that it gets is the command line parameter that the application was started with.

The following extended information is given on the display dialog:

Command Line

The command line parameters that the application was started with.

File

The full path of the executable file.

Modules

All modules loaded by the application.

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.

Background

I 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 CreateRemoteThread to inject a DLL into a process. I decided to use this method both for a learning exercise and because this is only intended to work on Windows 2000 and XP anyway. The main reason that I created this application was that I constantly need to know the command line parameters of an application, especially java.exe. There are applications out there that show this, but I would like to just have it work from within Windows Task Manager.

Screen shots

This is the main application window, it's very simple. You can double click the system tray icon to hide it without exiting:

mainapp.jpg

Here are the menu items that are added to the Windows Task Manager application:

menu.jpg

Here is the dialog box that is used to display the extended information:

exinfo.jpg

A look at the code

The code is fairly light-weight, here are some of the more interesting aspects of the code.

From TaskExApp, here is how it installs the InstallTaskHook into the Windows Task Manager:

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 InstallTaskHook to inject the TaskExHook is fairly similar, except that it also un-injects the DLL as well, the DLL is only there during the load process:

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 InstallTaskHook DLL actually creates the menu items and subclasses the main window to capture the menu events:

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;
}

Issues

For 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.

Conclusion

I 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 CreateRemoteThread method of DLL injection.

Sursa: Extending Task Manager with DLL Injection - CodeProject

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.



×
×
  • Create New...