Taskbar Modfication to Kill Windows NT/2000 Processes
1) modifying Task Manager,
2) through a popup menu that comes up by right clicking on a tray icon. By selecting a process from the menu, the process will be terminated. By selecting "Task Manager..." from the menu, a new Task Manager will be spawned, if one is not running yet. Then, Task Manager will be modified so that it allows the user to use "End Process" (right click on the process name in the list box) to terminate services.
There are 2 binaries involved in the operation:
killer.exe: main application
privi.dll: process privilege manipulator dll
Here is how it works:
1. First the application creates a tray icon for itself. For this, I
used
Chris Maunder's CSystemTray class. Thanks Chris!
(Unfortunately, couldn't find the link to his submission.)
2. On Right click on the icon, the running processes are collected and
their
3. Afterwards, the the vector is sorted and used to create the popup menu.
4. On clicking on process names, the KillProcess function is activated:
5. If the user select "Task Manager...", first there is a test for running
instance. If running TaskMgr is found, the process ID is obtained, if not,
a new instance is spawnd using CreateProcess(), then the process ID is stored.
After this, LoadDllForRemoteThread() is called:
This
function was published by
Zoltan Csizmadia. Thanks Zoltan!
Minor modification was made to his code. If debug code is compiled, function
pointer point to a relative jump instruction (E9), and the real function code
starts from where the jump is made to. Between the two addresses, variable
amount of "other stuff" is present. If MAXINJECTSIZE (the size of memory that
is allocated in the remote process to hold the code copied from our process) is
not big enough, problems arise. By testing for the relative jump in debug mode,
MAXINJECTSIZE can be reduced to the size of the function code. The following
simple function is the implementation:
Then it is used as follows:
What the Func() does in privi.dll is merely enables the
DEBUG process privilege:
Here is how SetPrivilege works:
The same adjustment of privileges takes place in the killer process to
allow the termination of services.
int CKillerDlg::UpdateProcessList()
{
typedef DWORD (WINAPI *PEnumProcesses)( DWORD*, \
UINT, \
DWORD* );
typedef DWORD (WINAPI *PEnumProcessModules)( HANDLE, \
HMODULE*, \
UINT, \
DWORD* );
typedef DWORD (WINAPI *PGetModuleBaseName)( HANDLE, \
HMODULE, \
LPTSTR, \
UINT );
_TCHAR szProcessName[MAX_PATH] = _T("unknown");
DWORD processID[1024], cbNeeded, cProcesses;
UINT i;
int result = -1;
HINSTANCE hPsApi = LoadLibrary( _T("PSAPI.DLL") );
if ( hPsApi == NULL )
return result;
PEnumProcessModules EnumProcessModules =
(PEnumProcessModules)GetProcAddress( hPsApi,
"EnumProcessModules" );
#ifdef UNICODE
PGetModuleBaseName GetModuleBaseName =
(PGetModuleBaseName)GetProcAddress( hPsApi,
"GetModuleBaseNameW" );
#else
PGetModuleBaseName GetModuleBaseName =
(PGetModuleBaseName)GetProcAddress( hPsApi,
"GetModuleBaseNameA" );
#endif
PEnumProcesses EnumProcesses =
(PEnumProcesses)GetProcAddress( hPsApi,
"EnumProcesses" );
if ( EnumProcessModules == NULL
|| GetModuleBaseName == NULL
|| EnumProcesses == NULL )
return result;
// Get the list of process identifiers.
if ( !EnumProcesses( processID,
sizeof(processID),
&cbNeeded ) )
return result;
// Calculate how many process identifiers were returned.
cProcesses = cbNeeded / sizeof(DWORD);
// Print the name and process identifier for each process.
ClearProcessList();
for ( i = 0; i < cProcesses; i++ )
{
// Get a handle to the process.
HANDLE hProcess = OpenProcess( PROCESS_QUERY_INFORMATION
| PROCESS_VM_READ,
FALSE,
processID[i] );
if ( hProcess )
{
HMODULE hMod;
if ( EnumProcessModules( hProcess, &hMod,
sizeof(hMod), &cbNeeded) )
{
GetModuleBaseName( hProcess, hMod, szProcessName,
sizeof(szProcessName) );
ProcItemStruct *procItem = new ProcItemStruct;
procItem->name = szProcessName;
procItem->id = processID[i];
this->m_processList.push_back(procItem);
}
}
CloseHandle( hProcess );
}
return result;
}
void CKillerDlg::ShowTrayPopupMenu( CWnd* pWnd, CPoint pt )
{
CMenu menu;
CMenu* pSubMenu = NULL;
menu.LoadMenu( IDR_TRAYPOPUPMENU );
pSubMenu = menu.GetSubMenu(0);
if ( pSubMenu != NULL )
{
UpdateMenu( pSubMenu );
::SetMenuDefaultItem( pSubMenu->m_hMenu, 0, TRUE );
UpdateProcessList();
// Function object for sorting
ProcItemLess pl;
std::sort(m_processList.begin(), m_processList.end(), pl);
for (UINT i = 0; i < m_processList.size(); i++)
{
// arrange items into columns
if (i%20 == 0)
pSubMenu->AppendMenu( MF_MENUBARBREAK | MF_STRING,
KILLER_WINDOWID_FIRST + i ,
m_processList[i]->name );
else
pSubMenu->AppendMenu( MF_STRING,
KILLER_WINDOWID_FIRST + i ,
m_processList[i]->name );
}
if ( pWnd != NULL )
pWnd->SetForegroundWindow();
pSubMenu->TrackPopupMenu( TPM_LEFTALIGN,
pt.x, pt.y,
pWnd );
if ( pWnd != NULL )
pWnd->SetForegroundWindow();
}
}
void CKillerDlg::OnKillProcess( UINT nID )
{
ProcItemStruct *procItem;
procItem = m_processList[nID - KILLER_WINDOWID_FIRST];
// Below, 3 lines are commented out, so that no
// annoying "Are you sure?" messagebox is shown.
//CString str(procItem->name);
//str.Format(_T("Name: %s \nPID: %d"),
// str,
// procItem->id);
//if (IDOK == ::MessageBox(NULL,
// str,
// _T("Kill?"),
// MB_OKCANCEL))
theApp.KillProcess(procItem->id, 9);
}
if (pId != 0)
LoadDllForRemoteThread( pId,
TRUE,
TRUE,
L"privi.dll",
L"Func" );
PVOID GetFuncAddress(PVOID addr)
{
#ifdef _DEBUG
//check if instruction is relative jump (E9)
if (0xE9 != *((UCHAR*)addr))
return addr;
// calculate base of relative jump
ULONG base = (ULONG)((UCHAR*)addr + 5);
// calculate offset
ULONG *offset = (ULONG*)((UCHAR*)addr + 1);
return (PVOID)(base + *offset);
#else
// in release, don't have to mess with jumps
return addr;
#endif
}
WriteProcessMemory( hProcess,
p,
GetFuncAddress(RemoteThread),
MAXINJECTSIZE,
0 );
// Set SE_DEBUG privilige for TaskMgr process
// This will make it able to kill services as well
ULONG Func()
{
HANDLE hToken;
if ( ! OpenProcessToken( GetCurrentProcess(),
TOKEN_ADJUST_PRIVILEGES
| TOKEN_QUERY,
&hToken ))
return 1;
if ( ! SetPrivilege( hToken, SE_DEBUG_NAME, TRUE ))
{
CloseHandle(hToken);
return 2;
}
CloseHandle(hToken);
return 0;
}
// Set/Unset specified privilige for given handle
BOOL SetPrivilege(HANDLE hToken, // token handle
LPCTSTR Privilege, // Privilege to enable/disable
BOOL bEnablePrivilege // TRUE to enable. FALSE to disable)
{
TOKEN_PRIVILEGES tp;
LUID luid;
TOKEN_PRIVILEGES tpPrevious;
DWORD cbPrevious=sizeof(TOKEN_PRIVILEGES);
if(!LookupPrivilegeValue( NULL, Privilege, &luid ))
return FALSE;
//
// first pass. get current privilege setting
//
tp.PrivilegeCount = 1;
tp.Privileges[0].Luid = luid;
tp.Privileges[0].Attributes = 0;
AdjustTokenPrivileges(hToken,
FALSE,
tp,
sizeof(TOKEN_PRIVILEGES),
&tpPrevious,
&cbPrevious);
if (GetLastError() != ERROR_SUCCESS)
return FALSE;
//
// second pass. set privilege based on previous setting
//
tpPrevious.PrivilegeCount = 1;
tpPrevious.Privileges[0].Luid = luid;
if(bEnablePrivilege)
{
tpPrevious.Privileges[0].Attributes |= (SE_PRIVILEGE_ENABLED);
}
else
{
tpPrevious.Privileges[0].Attributes ^= (SE_PRIVILEGE_ENABLED &
tpPrevious.Privileges[0].Attributes);
}
AdjustTokenPrivileges(hToken,
FALSE,
&tpPrevious,
cbPrevious,
NULL,
NULL);
if (GetLastError() != ERROR_SUCCESS)
return FALSE;
return TRUE;
}
Downloads
Download executables - 12 Kb
Download source - 26 Kb

Comments
Taskbar Modification to Kill Windows NT/2000 Processes
Posted by Legacy on 01/30/2004 12:00amOriginally posted by: yogesh
hi,
The task mananger Concept is related to my project,
but here u are only showing the processes which currently
running on to the sys.
ple. suggest me, how to get following parameter
along with perticular process.
- physical memory
- virtual memory
- page memory
- non-paged mem.
- CPU Usage
- thread Count
I am Waiting for replay..
thank U
Replyyogesh
Process Status
Posted by Legacy on 01/08/2004 12:00amOriginally posted by: Wahaj Khan
How can I get the CPU Usage at any instant or to know about any specific process that is not running but in the Ready state. Ready state is one when CPU Usage is 00.
ReplyThanks
Forbidden Task Manager
Posted by Legacy on 09/30/2003 12:00amOriginally posted by: Vrbcik
Hi, I would like to ask - At client's site we have forbidden access to task manager (by some windows security? I don't really know - the menu item is disabled).
I wanted to use Your programme, but it didn't run at all. Do You have an idea? Is it because of missing psapi.dll?
Thanx for advice.
Martin Vrbovsky
Replyhttp://codeguru.earthweb.com/system/killer.html
Posted by Legacy on 09/04/2003 12:00amOriginally posted by: stefanocri
Excellent code, very simple to undestand
ReplyHow to detect whether an application has crashed
Posted by Legacy on 10/22/2002 12:00amOriginally posted by: R
The application also lists an application if it has crashed.
How can we differentiate between the working and the crashed application.
If any one could tell me............
I need to know if an application has crashed so that the crashed instance may be killed and a fresh instance started.
I'll be grateful if i could be informed about this soon......
Regards
R
Reply
How I Can End the Explorer proccess in w2k
Posted by Legacy on 09/19/2002 12:00amOriginally posted by: Luis Joel Almanzar
I noticed that this program terminated the explorer process but it restarted it and I would to like to finish it completely. How can I do that? Thanks for any help.
Luis
Replycanot adjust the priviledge!!NT, please help
Posted by Legacy on 07/09/2002 12:00amOriginally posted by: ese3897
ff
ReplyHow to prevent a process be killed?
Posted by Legacy on 06/20/2002 12:00amOriginally posted by: zeuss
Hello:
ReplyWe can use this function to kill running process,but,how to prevent a running process to be killed manually in the TaskMageger?
Can't kill termsrv.exe
Posted by Legacy on 11/01/2001 12:00amOriginally posted by: Samen
I login as Administrator in Windows 2000,
Replyand want to kill termsrv(terminal server
service), but it was still there.
Why it don't work?