?? processinfo.cpp
字號:
///////////////////////////////////////////////////////////////////////////////
PVOID GetModulePreferredBaseAddr(DWORD dwProcessId, PVOID pvModuleRemote) {
PVOID pvModulePreferredBaseAddr = NULL;
IMAGE_DOS_HEADER idh;
IMAGE_NT_HEADERS inth;
// Read the remote module's DOS header
Toolhelp32ReadProcessMemory(dwProcessId,
pvModuleRemote, &idh, sizeof(idh), NULL);
// Verify the DOS image header
if (idh.e_magic == IMAGE_DOS_SIGNATURE) {
// Read the remote module's NT header
Toolhelp32ReadProcessMemory(dwProcessId,
(PBYTE) pvModuleRemote + idh.e_lfanew, &inth, sizeof(inth), NULL);
// Verify the NT image header
if (inth.Signature == IMAGE_NT_SIGNATURE) {
// This is valid NT header, get the image's preferred base address
pvModulePreferredBaseAddr = (PVOID) inth.OptionalHeader.ImageBase;
}
}
return(pvModulePreferredBaseAddr);
}
///////////////////////////////////////////////////////////////////////////////
/*
from http://msdn.microsoft.com/msdnmag/issues/02/06/debug/
Escape from DLL Hell with Custom Debugging and
Instrumentation Tools and Utilities
The PEB (Process Environment Block) is an undocumented structure
which varies from version to version of Windows.
However, WinDbg
(from http://www.microsoft.com/whdc/devtools/debugging/default.mspx)
provides a command that list the "documented" fields of a structure.
dt nt!_PEB
dt nt!_RTL_USER_PROCESS_PARAMETERS
*/
typedef struct
{
DWORD Filler[4];
DWORD InfoBlockAddress;
} __PEB;
typedef struct
{
DWORD Filler[17];
DWORD wszCmdLineAddress;
} __INFOBLOCK;
// NtQueryInformationProcess is declared in winternl.h
typedef NTSTATUS (CALLBACK *PFN_NTQUERYINFORMATIONPROCESS)(
HANDLE ProcessHandle,
PROCESSINFOCLASS ProcessInformationClass,
PVOID ProcessInformation,
ULONG ProcessInformationLength,
PULONG ReturnLength OPTIONAL
);
NTSTATUS _NtQueryInformationProcess(
HANDLE hProcess,
PROCESSINFOCLASS pic,
PVOID pPI,
ULONG cbSize,
PULONG pLength
) {
HMODULE hNtDll = LoadLibrary(TEXT("ntdll.dll"));
if (hNtDll == NULL) {
return(-1);
}
NTSTATUS lStatus = -1; // error by default.
// Note that function name is not UNICODE
PFN_NTQUERYINFORMATIONPROCESS pfnNtQIP =
(PFN_NTQUERYINFORMATIONPROCESS)GetProcAddress(
hNtDll, "NtQueryInformationProcess");
if (pfnNtQIP != NULL) {
lStatus = pfnNtQIP(hProcess, pic, pPI, cbSize, pLength);
}
FreeLibrary(hNtDll);
return(lStatus);
}
BOOL GetProcessCmdLine(HANDLE hProcess, LPTSTR szCmdLine, DWORD Size) {
// Sanity checks
if ((hProcess == NULL) || (szCmdLine == NULL) || (Size == 0))
return(FALSE);
// 0. Get the Process Environment Block address
int iReturn = 1;
DWORD dwSize;
SIZE_T size;
PROCESS_BASIC_INFORMATION pbi;
// The PEB was supposed to always be at address 0x7ffdf000 in XP...
// ... but, here is the "right" way to get it now in Vista.
iReturn =
_NtQueryInformationProcess(
hProcess, ProcessBasicInformation, &pbi, sizeof(pbi), &dwSize);
// NtQueryInformationProcess returns a negative value if it fails
if (iReturn >= 0) {
// 1. Find the Process Environment Block
__PEB PEB;
size = dwSize;
if (!ReadProcessMemory(hProcess, pbi.PebBaseAddress, &PEB,
sizeof(PEB), &size)) {
// Call GetLastError() if you need to know why
return(FALSE);
}
// 2. From this PEB, get the address of the block containing
// a pointer to the CmdLine
__INFOBLOCK Block;
if (!ReadProcessMemory(hProcess, (LPVOID)PEB.InfoBlockAddress,
&Block, sizeof(Block), &size)) {
// Call GetLastError() if you need to know why
return(FALSE);
}
// 3. Get the CmdLine
wchar_t wszCmdLine[MAX_PATH+1];
if (!ReadProcessMemory(hProcess, (LPVOID)Block.wszCmdLineAddress,
wszCmdLine, MAX_PATH*sizeof(wchar_t), &size)) {
// Call GetLastError() if you need to know why
return(FALSE);
}
// 4. Skip the application pathname
// it can be empty, "c:\...\app.exe" or c:\...\app.exe
wchar_t* pPos = wszCmdLine;
if (*pPos != L'\0') {
if (*pPos == L'"') {
// Find the next " character
pPos = wcschr(&pPos[1], L'"');
} else {
// Find the next SPACE character
pPos = wcschr(&pPos[1], L' ');
}
// Skip it
if (pPos != NULL)
pPos++;
}
// Copy it back
if (pPos != NULL) {
if (*pPos != L'\0') {
#ifdef UNICODE
// Both strings are in UNICODE.
_tcscpy_s(szCmdLine, Size, pPos);
#else
// from UNICODE to ANSI
MultiByteToWideChar(CP_ACP, 0, szCmdLine, Size,
pPos, wcslen(pPos));
#endif
}
else
szCmdLine[0] = TEXT('\0');
}
else
szCmdLine[0] = TEXT('\0');
}
else {
return(FALSE);
}
return(TRUE);
}
BOOL GetProcessCmdLine(DWORD PID, LPTSTR szCmdLine, DWORD Size) {
// Sanity checks
if ((PID <= 0) || (szCmdLine == NULL))
return(FALSE);
// Check if we can get information for this process
HANDLE hProcess =
OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, PID);
if (hProcess == NULL)
return(FALSE);
BOOL bReturn = GetProcessCmdLine(hProcess, szCmdLine, Size);
// Don't forget to release the process handle
CloseHandle(hProcess);
return(bReturn);
}
BOOL GetProcessOwner(HANDLE hProcess, LPTSTR szOwner, size_t cchSize) {
// Sanity checks
if ((szOwner == NULL) || (cchSize == 0))
return(FALSE);
// Default value
szOwner[0] = TEXT('\0');
// Gget process token
HANDLE hToken = NULL;
CToolhelp::EnablePrivilege(SE_TCB_NAME, TRUE);
if (!OpenProcessToken(hProcess, TOKEN_QUERY, &hToken)) {
CToolhelp::EnablePrivilege(SE_TCB_NAME, FALSE);
return(FALSE);
}
// Obtain the size of the user information in the token.
DWORD cbti = 0;
GetTokenInformation(hToken, TokenUser, NULL, 0, &cbti);
// Call should have failed due to zero-length buffer.
if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
// Allocate buffer for user information in the token.
PTOKEN_USER ptiUser =
(PTOKEN_USER)HeapAlloc(GetProcessHeap(), 0, cbti);
if (ptiUser != NULL) {
// Retrieve the user information from the token.
if (GetTokenInformation(hToken, TokenUser, ptiUser, cbti, &cbti)) {
SID_NAME_USE snu;
TCHAR szUser[MAX_PATH];
DWORD chUser = MAX_PATH;
PDWORD pcchUser = &chUser;
TCHAR szDomain[MAX_PATH];
DWORD chDomain = MAX_PATH;
PDWORD pcchDomain = &chDomain;
// Retrieve user name and domain name based on user's SID.
if (
LookupAccountSid(
NULL,
ptiUser->User.Sid,
szUser,
pcchUser,
szDomain,
pcchDomain,
&snu
)
) {
// build the owner string as \\DomainName\UserName
_tcscpy_s(szOwner, cchSize, TEXT("\\\\"));
_tcscat_s(szOwner, cchSize, szDomain);
_tcscat_s(szOwner, cchSize, TEXT("\\"));
_tcscat_s(szOwner, cchSize, szUser);
}
}
// Don't forget to free memory buffer
HeapFree(GetProcessHeap(), 0, ptiUser);
}
}
// Don't forget to free process token
CloseHandle(hToken);
// Restore privileges
CToolhelp::EnablePrivilege(SE_TCB_NAME, TRUE);
return(TRUE);
}
BOOL GetProcessOwner(DWORD PID, LPTSTR szOwner, DWORD cchSize) {
// Sanity checks
if ((PID <= 0) || (szOwner == NULL))
return(FALSE);
// Check if we can get information for this process
HANDLE hProcess =
OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, PID);
if (hProcess == NULL)
return(FALSE);
BOOL bReturn = GetProcessOwner(hProcess, szOwner, cchSize);
// Don't forget to release the process handle
CloseHandle(hProcess);
return(bReturn);
}
VOID FormatSizeInKB(DWORD dwSize, DWORD nCharacters,
LPTSTR szSize, size_t cchSize) {
TCHAR szFormattedSize[64];
if (StrFormatKBSize(dwSize, szFormattedSize,
_countof(szFormattedSize)) == NULL) {
StringCchPrintf(szFormattedSize, _countof(szFormattedSize), TEXT("%8u"), dwSize);
}
// Format to the right nCharacter width if needed.
if (_tcslen(szFormattedSize) < nCharacters) {
DWORD current = 0;
for(current = 0;
current < (nCharacters - _tcslen(szFormattedSize));
current++) {
szSize[current] = TEXT(' ');
}
szSize[current] = TEXT('\0');
_tcscat_s(szSize, cchSize - current, szFormattedSize);
}
}
VOID ShowProcessInfo(HWND hwnd, DWORD dwProcessID) {
SetWindowText(hwnd, TEXT("")); // Clear the output box
CToolhelp th(TH32CS_SNAPALL, dwProcessID);
// Show Process details
PROCESSENTRY32 pe = { sizeof(pe) };
BOOL fOk = th.ProcessFirst(&pe);
for (; fOk; fOk = th.ProcessNext(&pe)) {
if (pe.th32ProcessID == dwProcessID) {
TCHAR szCmdLine[1024];
if (GetProcessCmdLine(dwProcessID, szCmdLine, _countof(szCmdLine))) {
AddText(hwnd,
TEXT("Command line: %s %s\r\n"), pe.szExeFile, szCmdLine);
} else {
AddText(hwnd, TEXT("Filename: %s\r\n"), pe.szExeFile);
}
AddText(hwnd, TEXT(" PID=%08X, ParentPID=%08X, ")
TEXT("PriorityClass=%d, Threads=%d, Heaps=%d\r\n"),
pe.th32ProcessID, pe.th32ParentProcessID,
pe.pcPriClassBase, pe.cntThreads,
th.HowManyHeaps());
TCHAR szOwner[MAX_PATH+1];
if (GetProcessOwner(dwProcessID, szOwner, MAX_PATH)) {
AddText(hwnd, TEXT("Owner: %s\r\n"), szOwner);
}
break; // No need to continue looping
}
}
// Show Modules in the Process
// Number of characters to display an address
AddText(hwnd, TEXT("\r\nModules Information:\r\n")
TEXT(" Usage %-*s(%-*s) %10s Module\r\n"),
s_cchAddress, TEXT("BaseAddr"),
s_cchAddress, TEXT("ImagAddr"), TEXT("Size"));
MODULEENTRY32 me = { sizeof(me) };
fOk = th.ModuleFirst(&me);
for (; fOk; fOk = th.ModuleNext(&me)) {
if (me.ProccntUsage == 65535) {
// Module was implicitly loaded and cannot be unloaded
AddText(hwnd, TEXT(" Fixed"));
} else {
AddText(hwnd, TEXT(" %5d"), me.ProccntUsage);
}
// Try to format the size in kb.
TCHAR szFormattedSize[64];
if (StrFormatKBSize(me.modBaseSize, szFormattedSize,
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -