对 HOOK SSDT Hide Process (四) 的code改进了一下,支持Display Process's Owner
在 XP 下进行测试没发现问题,但在 Win7 下只能显示当前用户的 Process, 其它用户还有一些 NETWORK SERVICE
的进程无法显示出来
Code:
在 XP 下进行测试没发现问题,但在 Win7 下只能显示当前用户的 Process, 其它用户还有一些 NETWORK SERVICE
的进程无法显示出来
Code:
#include
<
stdlib.h
>
#include < stdio.h >
#include < windows.h >
typedef long NTSTATUS;
#define ULONG_PTR ULONG
#define STATUS_INFO_LENGTH_MISMATCH ((NTSTATUS)0xC0000004L)
#define NT_SUCCESS(Status) ((NTSTATUS)(Status)>=0)
//
// Unicode strings are counted 16-bit character strings. If they are
// NULL terminated, Length does not include trailing NULL.
//
typedef struct _UNICODE_STRING
{
USHORT Length;
USHORT MaximumLength;
PWSTR Buffer;
} UNICODE_STRING, * PUNICODE_STRING;
//
// Thread priority
//
typedef LONG KPRIORITY;
// -----------------------------------------------------------------------------
// Query system information
typedef enum _SYSTEM_INFORMATION_CLASS
{
SystemBasicInformation, // 0x00 SYSTEM_BASIC_INFORMATION
SystemProcessorInformation, // 0x01 SYSTEM_PROCESSOR_INFORMATION
SystemPerformanceInformation, // 0x02
SystemTimeOfDayInformation, // 0x03
SystemPathInformation, // 0x04
SystemProcessInformation, // 0x05
SystemCallCountInformation, // 0x06
SystemDeviceInformation, // 0x07
SystemProcessorPerformanceInformation, // 0x08
SystemFlagsInformation, // 0x09
SystemCallTimeInformation, // 0x0A
SystemModuleInformation, // 0x0B SYSTEM_MODULE_INFORMATION
SystemLocksInformation, // 0x0C
SystemStackTraceInformation, // 0x0D
SystemPagedPoolInformation, // 0x0E
SystemNonPagedPoolInformation, // 0x0F
SystemHandleInformation, // 0x10
SystemObjectInformation, // 0x11
SystemPageFileInformation, // 0x12
SystemVdmInstemulInformation, // 0x13
SystemVdmBopInformation, // 0x14
SystemFileCacheInformation, // 0x15
SystemPoolTagInformation, // 0x16
SystemInterruptInformation, // 0x17
SystemDpcBehaviorInformation, // 0x18
SystemFullMemoryInformation, // 0x19
SystemLoadGdiDriverInformation, // 0x1A
SystemUnloadGdiDriverInformation, // 0x1B
SystemTimeAdjustmentInformation, // 0x1C
SystemSummaryMemoryInformation, // 0x1D
SystemNextEventIdInformation, // 0x1E
SystemEventIdsInformation, // 0x1F
SystemCrashDumpInformation, // 0x20
SystemExceptionInformation, // 0x21
SystemCrashDumpStateInformation, // 0x22
SystemKernelDebuggerInformation, // 0x23
SystemContextSwitchInformation, // 0x24
SystemRegistryQuotaInformation, // 0x25
SystemExtendServiceTableInformation, // 0x26
SystemPrioritySeperation, // 0x27
SystemPlugPlayBusInformation, // 0x28
SystemDockInformation, // 0x29
// SystemPowerInformation, // 0x2A
// SystemProcessorSpeedInformation, // 0x2B
// SystemCurrentTimeZoneInformation, // 0x2C
// SystemLookasideInformation // 0x2D
} SYSTEM_INFORMATION_CLASS, * PSYSTEM_INFORMATION_CLASS;
//
// Process information
// NtQuerySystemInformation with SystemProcessInformation
//
typedef struct _SYSTEM_PROCESS_INFORMATION {
ULONG NextEntryOffset;
ULONG NumberOfThreads;
LARGE_INTEGER SpareLi1;
LARGE_INTEGER SpareLi2;
LARGE_INTEGER SpareLi3;
LARGE_INTEGER CreateTime;
LARGE_INTEGER UserTime;
LARGE_INTEGER KernelTime;
UNICODE_STRING ImageName;
KPRIORITY BasePriority;
ULONG_PTR UniqueProcessId;
ULONG_PTR InheritedFromUniqueProcessId;
ULONG HandleCount;
// Next part is platform dependent
} SYSTEM_PROCESS_INFORMATION, * PSYSTEM_PROCESS_INFORMATION;
typedef NTSTATUS
(NTAPI * PNFNtQuerySystemInformation)(
IN SYSTEM_INFORMATION_CLASS SystemInformationClass,
OUT PVOID SystemInformation,
IN ULONG SystemInformationLength,
OUT PULONG ReturnLength
);
PNFNtQuerySystemInformation pNtQuerySystemInformation;
//
// GetProcessUsername()
//
/*
While I have not yet had time to thoroughly test this solution,
it's working well for me so far (I just finished this initial version in the last couple of hours). Posting here because I searched all over before deciding to try a different approach, and could not find one. It seems that the DEBUG privilege will allow you to open a process handle, but not necessairly the process tokens. No back door for that!
I have been able to use GetUserObjectSecurity() from an Admin account to get the Owner SID for the process, and that generally turns out to be the user who started the process. Several system processes show "Builtin\Administrators" for their owner for my purposes I return NULL for those (other code then defaults the user to "SYSTEM" to match TaskMgr). You will still need the DEBUG privilege for this to work (else OpenProcess could fail).
I adapted this code from another post I found that used the well-known OpenProcessToken pathway. It isn't very pretty, but as I said I just got it working. Note the need for STANDARD_RIGHTS_READ on the hProcess. I also have PROCESS_QUERY_INFORMATION and PROCESS_VM_READ included in my calling code (for access to other process information) and have not tried calling GetProcessUsername() on a handle without these set to see if that works or not.
NOTE THAT THE RESULT IS RETURNED AS A STATIC!! It would be cleaner to let the caller pass in a buffer (in fact there are lots of things that should be cleaned up in this sample). It nonetheless demonstrates the concept.
Since I just came up with this and have had limited time to test it, if you use it please let me know if it works (or doesn't) for your application:
*/
// Get username and domain from a supplied process handle.
//
// hProcess : is the process handle of which
// to get the username from.
//
// bIncDomain : if true will prepend the DOMAIN and to
// the returned string.
//
// Returns a reference to a static string containing the
// username or NULL on error.
//
//
char * GetProcessUsername(HANDLE hProcess, BOOL bIncDomain)
{
static char sname[ 300 ];
char name[ 300 ], dom[ 300 ], * pret = 0 ;
SECURITY_DESCRIPTOR * psd = NULL;
BOOL b;
int iUse, rc;
DWORD d;
SECURITY_INFORMATION SecInfo = OWNER_SECURITY_INFORMATION;
// This Is a round-about method I discovered. Instead of OpenProcessToken and GetTokenInformation use GetUserObjectSecurity and pull
// the OWNER information. Ignore BUILTIN Administrators group as an owner (we want that to show up as SYSTEM). Using the tokens is
// subject to ACCESS DENIED errors on OpenProcessToken, even for administrators. This work around seems to work regardless. Unclear
// what the diff between GetUserObjectSecurity and GetKernelObjectSecurity is. So stick with GetUserObjectSecurity for now.
// Requires STANDARD_RIGHTS_READ on hProcess (in OpenProcess call).
// b = GetKernelObjectSecurity(hProcess, SecInfo, psd, 0, &d);
b = GetUserObjectSecurity(hProcess, & SecInfo, psd, 0 , & d);
rc = GetLastError();
psd = (SECURITY_DESCRIPTOR * )malloc(d);
if (psd != NULL)
{
memset (psd, 0 , d);
// b = GetKernelObjectSecurity(hProcess, SecInfo, psd, d, &d);
b = GetUserObjectSecurity(hProcess, & SecInfo, psd, d, & d);
if (b)
{
PSID psidOwner;
BOOL bDefaulted;
b = GetSecurityDescriptorOwner(psd, & psidOwner, & bDefaulted);
if (IsValidSid(psidOwner) )
{
// We have a valid Owner SID. Decode it
DWORD dlen = sizeof (dom);
DWORD nlen = sizeof (name);
b = LookupAccountSid( 0 , psidOwner, name, & nlen, dom, & dlen, (PSID_NAME_USE) & iUse);
if (b && lstrcmpi(dom, " Builtin " ) != 0 && lstrcmpi(dom, " Administrators " ) != 0 )
{
// copy info to our static buffer
if (dlen && bIncDomain)
{
lstrcpy(sname,dom);
lstrcat(sname, " \\ " );
lstrcat(sname,name);
}
else
lstrcpy(sname,name);
// set our return variable
pret = sname;
}
else
rc = GetLastError();
}
}
else
rc = GetLastError();
}
if (psd != NULL)
free (psd);
return pret;
}
BOOL QueryThreadInfo()
{
HMODULE hMod = GetModuleHandle( " ntdll.dll " );
if (hMod == NULL)
{
hMod = LoadLibrary( " ntdll.dll " );
if (hMod == NULL)
{
printf( " LoadLibrary Error: %d\n " , GetLastError());
return FALSE;
}
}
pNtQuerySystemInformation = (PNFNtQuerySystemInformation)GetProcAddress(hMod, " NtQuerySystemInformation " );
if ( pNtQuerySystemInformation == NULL )
{
printf( " GetProcAddress for NtQuerySystemInformation Error: %d\n " , GetLastError());
return FALSE;
}
// ULONG dwNumberBytes = 0x8000;
// char* pBuf = (char*)malloc(dwNumberBytes);
// PSYSTEM_PROCESS_INFORMATION pProcessInfo = (PSYSTEM_PROCESS_INFORMATION)pBuf;
ULONG nNeedSize = 0 ;
NTSTATUS nStatus = pNtQuerySystemInformation(SystemProcessInformation, NULL, NULL, & nNeedSize);
if (STATUS_INFO_LENGTH_MISMATCH != nStatus)
{
return FALSE;
}
PVOID lpBuffer = LocalAlloc(LPTR, nNeedSize);
if (NULL == lpBuffer)
{
return FALSE;
}
nStatus = pNtQuerySystemInformation(SystemProcessInformation, lpBuffer, nNeedSize, 0 );
if (NT_SUCCESS(nStatus))
{
PSYSTEM_PROCESS_INFORMATION ProcessInfo = (PSYSTEM_PROCESS_INFORMATION)lpBuffer;
while ( NULL != ProcessInfo )
{
char szANSIString[MAX_PATH];
memset(szANSIString, 0 , MAX_PATH);
WideCharToMultiByte(CP_ACP,
WC_COMPOSITECHECK,
ProcessInfo -> ImageName.Buffer,
- 1 ,
szANSIString,
sizeof (szANSIString),
NULL,
NULL);
printf( " %d " , ProcessInfo -> UniqueProcessId);
printf( " %s " , szANSIString);
HANDLE hProcess = ::OpenProcess(PROCESS_ALL_ACCESS, FALSE, ProcessInfo -> UniqueProcessId);
printf( " %s " , GetProcessUsername(hProcess, FALSE));
CloseHandle(hProcess);
printf( " \n " );
if ( ProcessInfo -> NextEntryOffset )
{
ProcessInfo = (PSYSTEM_PROCESS_INFORMATION)
((DWORD)ProcessInfo + (DWORD)(ProcessInfo -> NextEntryOffset));
}
else
{
ProcessInfo = NULL;
}
}
return TRUE;
}
else
{
LocalFree(lpBuffer);
return FALSE;
}
return FALSE;
}
int main()
{
if ( ! QueryThreadInfo() )
{
printf( " QueryThreadInfo Error!\n " );
return 0 ;
}
return 0 ;
}
#include < stdio.h >
#include < windows.h >
typedef long NTSTATUS;
#define ULONG_PTR ULONG
#define STATUS_INFO_LENGTH_MISMATCH ((NTSTATUS)0xC0000004L)
#define NT_SUCCESS(Status) ((NTSTATUS)(Status)>=0)
//
// Unicode strings are counted 16-bit character strings. If they are
// NULL terminated, Length does not include trailing NULL.
//
typedef struct _UNICODE_STRING
{
USHORT Length;
USHORT MaximumLength;
PWSTR Buffer;
} UNICODE_STRING, * PUNICODE_STRING;
//
// Thread priority
//
typedef LONG KPRIORITY;
// -----------------------------------------------------------------------------
// Query system information
typedef enum _SYSTEM_INFORMATION_CLASS
{
SystemBasicInformation, // 0x00 SYSTEM_BASIC_INFORMATION
SystemProcessorInformation, // 0x01 SYSTEM_PROCESSOR_INFORMATION
SystemPerformanceInformation, // 0x02
SystemTimeOfDayInformation, // 0x03
SystemPathInformation, // 0x04
SystemProcessInformation, // 0x05
SystemCallCountInformation, // 0x06
SystemDeviceInformation, // 0x07
SystemProcessorPerformanceInformation, // 0x08
SystemFlagsInformation, // 0x09
SystemCallTimeInformation, // 0x0A
SystemModuleInformation, // 0x0B SYSTEM_MODULE_INFORMATION
SystemLocksInformation, // 0x0C
SystemStackTraceInformation, // 0x0D
SystemPagedPoolInformation, // 0x0E
SystemNonPagedPoolInformation, // 0x0F
SystemHandleInformation, // 0x10
SystemObjectInformation, // 0x11
SystemPageFileInformation, // 0x12
SystemVdmInstemulInformation, // 0x13
SystemVdmBopInformation, // 0x14
SystemFileCacheInformation, // 0x15
SystemPoolTagInformation, // 0x16
SystemInterruptInformation, // 0x17
SystemDpcBehaviorInformation, // 0x18
SystemFullMemoryInformation, // 0x19
SystemLoadGdiDriverInformation, // 0x1A
SystemUnloadGdiDriverInformation, // 0x1B
SystemTimeAdjustmentInformation, // 0x1C
SystemSummaryMemoryInformation, // 0x1D
SystemNextEventIdInformation, // 0x1E
SystemEventIdsInformation, // 0x1F
SystemCrashDumpInformation, // 0x20
SystemExceptionInformation, // 0x21
SystemCrashDumpStateInformation, // 0x22
SystemKernelDebuggerInformation, // 0x23
SystemContextSwitchInformation, // 0x24
SystemRegistryQuotaInformation, // 0x25
SystemExtendServiceTableInformation, // 0x26
SystemPrioritySeperation, // 0x27
SystemPlugPlayBusInformation, // 0x28
SystemDockInformation, // 0x29
// SystemPowerInformation, // 0x2A
// SystemProcessorSpeedInformation, // 0x2B
// SystemCurrentTimeZoneInformation, // 0x2C
// SystemLookasideInformation // 0x2D
} SYSTEM_INFORMATION_CLASS, * PSYSTEM_INFORMATION_CLASS;
//
// Process information
// NtQuerySystemInformation with SystemProcessInformation
//
typedef struct _SYSTEM_PROCESS_INFORMATION {
ULONG NextEntryOffset;
ULONG NumberOfThreads;
LARGE_INTEGER SpareLi1;
LARGE_INTEGER SpareLi2;
LARGE_INTEGER SpareLi3;
LARGE_INTEGER CreateTime;
LARGE_INTEGER UserTime;
LARGE_INTEGER KernelTime;
UNICODE_STRING ImageName;
KPRIORITY BasePriority;
ULONG_PTR UniqueProcessId;
ULONG_PTR InheritedFromUniqueProcessId;
ULONG HandleCount;
// Next part is platform dependent
} SYSTEM_PROCESS_INFORMATION, * PSYSTEM_PROCESS_INFORMATION;
typedef NTSTATUS
(NTAPI * PNFNtQuerySystemInformation)(
IN SYSTEM_INFORMATION_CLASS SystemInformationClass,
OUT PVOID SystemInformation,
IN ULONG SystemInformationLength,
OUT PULONG ReturnLength
);
PNFNtQuerySystemInformation pNtQuerySystemInformation;
//
// GetProcessUsername()
//
/*
While I have not yet had time to thoroughly test this solution,
it's working well for me so far (I just finished this initial version in the last couple of hours). Posting here because I searched all over before deciding to try a different approach, and could not find one. It seems that the DEBUG privilege will allow you to open a process handle, but not necessairly the process tokens. No back door for that!
I have been able to use GetUserObjectSecurity() from an Admin account to get the Owner SID for the process, and that generally turns out to be the user who started the process. Several system processes show "Builtin\Administrators" for their owner for my purposes I return NULL for those (other code then defaults the user to "SYSTEM" to match TaskMgr). You will still need the DEBUG privilege for this to work (else OpenProcess could fail).
I adapted this code from another post I found that used the well-known OpenProcessToken pathway. It isn't very pretty, but as I said I just got it working. Note the need for STANDARD_RIGHTS_READ on the hProcess. I also have PROCESS_QUERY_INFORMATION and PROCESS_VM_READ included in my calling code (for access to other process information) and have not tried calling GetProcessUsername() on a handle without these set to see if that works or not.
NOTE THAT THE RESULT IS RETURNED AS A STATIC!! It would be cleaner to let the caller pass in a buffer (in fact there are lots of things that should be cleaned up in this sample). It nonetheless demonstrates the concept.
Since I just came up with this and have had limited time to test it, if you use it please let me know if it works (or doesn't) for your application:
*/
// Get username and domain from a supplied process handle.
//
// hProcess : is the process handle of which
// to get the username from.
//
// bIncDomain : if true will prepend the DOMAIN and to
// the returned string.
//
// Returns a reference to a static string containing the
// username or NULL on error.
//
//
char * GetProcessUsername(HANDLE hProcess, BOOL bIncDomain)
{
static char sname[ 300 ];
char name[ 300 ], dom[ 300 ], * pret = 0 ;
SECURITY_DESCRIPTOR * psd = NULL;
BOOL b;
int iUse, rc;
DWORD d;
SECURITY_INFORMATION SecInfo = OWNER_SECURITY_INFORMATION;
// This Is a round-about method I discovered. Instead of OpenProcessToken and GetTokenInformation use GetUserObjectSecurity and pull
// the OWNER information. Ignore BUILTIN Administrators group as an owner (we want that to show up as SYSTEM). Using the tokens is
// subject to ACCESS DENIED errors on OpenProcessToken, even for administrators. This work around seems to work regardless. Unclear
// what the diff between GetUserObjectSecurity and GetKernelObjectSecurity is. So stick with GetUserObjectSecurity for now.
// Requires STANDARD_RIGHTS_READ on hProcess (in OpenProcess call).
// b = GetKernelObjectSecurity(hProcess, SecInfo, psd, 0, &d);
b = GetUserObjectSecurity(hProcess, & SecInfo, psd, 0 , & d);
rc = GetLastError();
psd = (SECURITY_DESCRIPTOR * )malloc(d);
if (psd != NULL)
{
memset (psd, 0 , d);
// b = GetKernelObjectSecurity(hProcess, SecInfo, psd, d, &d);
b = GetUserObjectSecurity(hProcess, & SecInfo, psd, d, & d);
if (b)
{
PSID psidOwner;
BOOL bDefaulted;
b = GetSecurityDescriptorOwner(psd, & psidOwner, & bDefaulted);
if (IsValidSid(psidOwner) )
{
// We have a valid Owner SID. Decode it
DWORD dlen = sizeof (dom);
DWORD nlen = sizeof (name);
b = LookupAccountSid( 0 , psidOwner, name, & nlen, dom, & dlen, (PSID_NAME_USE) & iUse);
if (b && lstrcmpi(dom, " Builtin " ) != 0 && lstrcmpi(dom, " Administrators " ) != 0 )
{
// copy info to our static buffer
if (dlen && bIncDomain)
{
lstrcpy(sname,dom);
lstrcat(sname, " \\ " );
lstrcat(sname,name);
}
else
lstrcpy(sname,name);
// set our return variable
pret = sname;
}
else
rc = GetLastError();
}
}
else
rc = GetLastError();
}
if (psd != NULL)
free (psd);
return pret;
}
BOOL QueryThreadInfo()
{
HMODULE hMod = GetModuleHandle( " ntdll.dll " );
if (hMod == NULL)
{
hMod = LoadLibrary( " ntdll.dll " );
if (hMod == NULL)
{
printf( " LoadLibrary Error: %d\n " , GetLastError());
return FALSE;
}
}
pNtQuerySystemInformation = (PNFNtQuerySystemInformation)GetProcAddress(hMod, " NtQuerySystemInformation " );
if ( pNtQuerySystemInformation == NULL )
{
printf( " GetProcAddress for NtQuerySystemInformation Error: %d\n " , GetLastError());
return FALSE;
}
// ULONG dwNumberBytes = 0x8000;
// char* pBuf = (char*)malloc(dwNumberBytes);
// PSYSTEM_PROCESS_INFORMATION pProcessInfo = (PSYSTEM_PROCESS_INFORMATION)pBuf;
ULONG nNeedSize = 0 ;
NTSTATUS nStatus = pNtQuerySystemInformation(SystemProcessInformation, NULL, NULL, & nNeedSize);
if (STATUS_INFO_LENGTH_MISMATCH != nStatus)
{
return FALSE;
}
PVOID lpBuffer = LocalAlloc(LPTR, nNeedSize);
if (NULL == lpBuffer)
{
return FALSE;
}
nStatus = pNtQuerySystemInformation(SystemProcessInformation, lpBuffer, nNeedSize, 0 );
if (NT_SUCCESS(nStatus))
{
PSYSTEM_PROCESS_INFORMATION ProcessInfo = (PSYSTEM_PROCESS_INFORMATION)lpBuffer;
while ( NULL != ProcessInfo )
{
char szANSIString[MAX_PATH];
memset(szANSIString, 0 , MAX_PATH);
WideCharToMultiByte(CP_ACP,
WC_COMPOSITECHECK,
ProcessInfo -> ImageName.Buffer,
- 1 ,
szANSIString,
sizeof (szANSIString),
NULL,
NULL);
printf( " %d " , ProcessInfo -> UniqueProcessId);
printf( " %s " , szANSIString);
HANDLE hProcess = ::OpenProcess(PROCESS_ALL_ACCESS, FALSE, ProcessInfo -> UniqueProcessId);
printf( " %s " , GetProcessUsername(hProcess, FALSE));
CloseHandle(hProcess);
printf( " \n " );
if ( ProcessInfo -> NextEntryOffset )
{
ProcessInfo = (PSYSTEM_PROCESS_INFORMATION)
((DWORD)ProcessInfo + (DWORD)(ProcessInfo -> NextEntryOffset));
}
else
{
ProcessInfo = NULL;
}
}
return TRUE;
}
else
{
LocalFree(lpBuffer);
return FALSE;
}
return FALSE;
}
int main()
{
if ( ! QueryThreadInfo() )
{
printf( " QueryThreadInfo Error!\n " );
return 0 ;
}
return 0 ;
}