//------------------------------------------------------------
//
// Netstatp
//
// Copyright (C) 1998 Mark Russinovich
// Systems Internals
// http://www.sysinternals.com
//
// This program implements a subset of the Netstat program's
// functionality. Specifically, it enumerates and displays
// information about all UDP and TCP endpoints.
//
//------------------------------------------------------------
#include "windows.h"
#include "stdio.h"
#include "snmp.h"
#include "winsock.h"
#define HOSTNAMELEN 256
#define PORTNAMELEN 256
#define ADDRESSLEN HOSTNAMELEN+PORTNAMELEN
typedef struct _tcpinfo {
struct _tcpinfo *prev;
struct _tcpinfo *next;
UINT state;
UINT localip;
UINT localport;
UINT remoteip;
UINT remoteport;
} TCPINFO, *PTCPINFO;
BOOL (__stdcall *SnmpExtensionInit)(
IN DWORD dwTimeZeroReference,
OUT HANDLE *hPollForTrapEvent,
OUT AsnObjectIdentifier *supportedView);
BOOL (__stdcall *SnmpExtensionQuery)(
IN BYTE requestType,
IN OUT RFC1157VarBindList *variableBindings,
OUT AsnInteger *errorStatus,
OUT AsnInteger *errorIndex);
//
// Possible TCP endpoint states
//
static char TcpState[][32] = {
"???",
"CLOSED",
"LISTENING",
"SYN_SENT",
"SEN_RECEIVED",
"ESTABLISHED",
"FIN_WAIT",
"FIN_WAIT2",
"CLOSE_WAIT",
"CLOSING",
"LAST_ACK",
"TIME_WAIT"
};
//
// Lists of endpoints
//
TCPINFO TcpInfoTable;
TCPINFO UdpInfoTable;
//------------------------------------------------------------
//
// GetPortName
//
// Translate port numbers into their text equivalent if
// there is one
//
//------------------------------------------------------------
char *GetPortName( UINT port, char *proto, char *name, int namelen )
{
struct servent *psrvent;
if( psrvent = getservbyport( htons( (USHORT) port ), proto )) {
strcpy( name, psrvent->s_name );
} else {
sprintf(name, "%d", port);
}
return name;
}
//------------------------------------------------------------
//
// GetIpHostName
//
// Translate IP addresses into their name-resolved form
// if possible.
//
//------------------------------------------------------------
char *GetIpHostName( BOOL local, UINT ipaddr, char *name, int namelen )
{
struct hostent *phostent;
UINT nipaddr;
nipaddr = htonl( ipaddr );
if( !ipaddr ) {
if( !local ) {
sprintf( name, "%d.%d.%d.%d",
(nipaddr >> 24) & 0xFF,
(nipaddr >> 16) & 0xFF,
(nipaddr >> 8) & 0xFF,
(nipaddr) & 0xFF);
} else {
gethostname(name, namelen);
}
} else if( ipaddr == 0x0100007f ) {
if( local ) {
gethostname(name, namelen);
} else {
strcpy( name, "localhost" );
}
} else if( phostent = gethostbyaddr( (char *) &ipaddr,
sizeof( nipaddr ), PF_INET )) {
strcpy( name, phostent->h_name );
} else {
sprintf( name, "%d.%d.%d.%d",
(nipaddr >> 24) & 0xFF,
(nipaddr >> 16) & 0xFF,
(nipaddr >> 8) & 0xFF,
(nipaddr) & 0xFF);
}
return name;
}
//------------------------------------------------------------
//
// LoadInetMibEntryPoints
//
// Load the TCP/IP SNMP extension DLL and locate the entry
// points we will use.
//
//------------------------------------------------------------
BOOLEAN LoadInetMibEntryPoints()
{
HINSTANCE hInetLib;
if( !(hInetLib = LoadLibrary( "inetmib1.dll" ))) {
return FALSE;
}
if( !(SnmpExtensionInit = (void *) GetProcAddress( hInetLib,
"SnmpExtensionInit" )) ) {
return FALSE;
}
if( !(SnmpExtensionQuery = (void *) GetProcAddress( hInetLib,
"SnmpExtensionQuery" )) ) {
return FALSE;
}
return TRUE;
}
//------------------------------------------------------------
//
// Main
//
// Do it all. Load and initialize the SNMP extension DLL and
// then build a table of TCP endpoints and UDP endpoints. After
// each table is built resolve addresses to names and print
// out the information
//
//------------------------------------------------------------
int main( int argc, char *argv[] )
{
HANDLE hTrapEvent;
AsnObjectIdentifier hIdentifier;
RFC1157VarBindList bindList;
RFC1157VarBind bindEntry;
UINT tcpidentifiers[] = { 1,3,6,1,2,1,6,13,1,1};
UINT udpidentifiers[] = { 1,3,6,1,2,1,7,5,1,1};
AsnInteger errorStatus, errorIndex;
TCPINFO *currentEntry, *newEntry;
UINT currentIndex;
WORD wVersionRequested;
WSADATA wsaData;
char localname[HOSTNAMELEN], remotename[HOSTNAMELEN];
char remoteport[PORTNAMELEN], localport[PORTNAMELEN];
char localaddr[ADDRESSLEN], remoteaddr[ADDRESSLEN];
//
// Initialize winsock
//
wVersionRequested = MAKEWORD( 1, 1 );
if( WSAStartup( wVersionRequested, &wsaData ) ) {
printf("Could not initialize Winsock.\n");
return 1;
}
//
// Locate and initialize INETMIB1
//
if( !LoadInetMibEntryPoints()) {
printf("Could not load extension DLL.\n");
return 1;
}
if( !SnmpExtensionInit( GetCurrentTime(), &hTrapEvent, &hIdentifier )) {
printf("Could not initialize extension DLL.\n");
return 1;
}
//
// Initialize the query structure once
//
bindEntry.name.idLength = 0xA;
bindEntry.name.ids = tcpidentifiers;
bindList.list = &bindEntry;
bindList.len = 1;
TcpInfoTable.prev = &TcpInfoTable;
TcpInfoTable.next = &TcpInfoTable;
//
// Roll through TCP connections
//
currentIndex = 1;
currentEntry = &TcpInfoTable;
while(1) {
if( !SnmpExtensionQuery( ASN_RFC1157_GETNEXTREQUEST,
&bindList, &errorStatus, &errorIndex )) {
return 1;
}
//
// Terminate when we're no longer seeing TCP information
//
if( bindEntry.name.idLength < 0xA ) break;
//
// Go back to start of table if we're reading info
// about the next byte
//
if( currentIndex != bindEntry.name.ids[9] ) {
currentEntry = TcpInfoTable.next;
currentIndex = bindEntry.name.ids[9];
}
//
// Build our TCP information table
//
switch( bindEntry.name.ids[9] ) {
case 1:
//
// Always allocate a new structure
//
newEntry = (TCPINFO *) malloc( sizeof(TCPINFO ));
newEntry->prev = currentEntry;
newEntry->next = &TcpInfoTable;
currentEntry->next = newEntry;
currentEntry = newEntry;
currentEntry->state = bindEntry.value.asnValue.number;
break;
case 2:
currentEntry->localip =
*(UINT *) bindEntry.value.asnValue.address.stream;
currentEntry = currentEntry->next;
break;
case 3:
currentEntry->localport =
bindEntry.value.asnValue.number;
currentEntry = currentEntry->next;
break;
case 4:
currentEntry->remoteip =
*(UINT *) bindEntry.value.asnValue.address.stream;
currentEntry = currentEntry->next;
break;
case 5:
currentEntry->remoteport =
bindEntry.value.asnValue.number;
currentEntry = currentEntry->next;
break;
}
}
//
// Now print the connection information
//
printf("%7s %-30s %-30s %s\n", "Proto", "Local", "Remote", "State" );
currentEntry = TcpInfoTable.next;
while( currentEntry != &TcpInfoTable ) {
sprintf( localaddr, "%s:%s",
GetIpHostName( TRUE, currentEntry->localip, localname, HOSTNAMELEN),
GetPortName( currentEntry->localport, "tcp", localport, PORTNAMELEN ));
sprintf( remoteaddr, "%s:%s",
GetIpHostName( FALSE, currentEntry->remoteip, remotename, HOSTNAMELEN),
currentEntry->remoteip ?
GetPortName( currentEntry->remoteport, "tcp", remoteport, PORTNAMELEN ):
"0" );
printf("%7s %-30s %-30s %s\n", "TCP",
localaddr, remoteaddr,
TcpState[currentEntry->state]);
currentEntry = currentEntry->next;
}
printf("\n");
//
// Initialize the query structure once
//
bindEntry.name.idLength = 0xA;
bindEntry.name.ids = udpidentifiers;
bindList.list = &bindEntry;
bindList.len = 1;
UdpInfoTable.prev = &UdpInfoTable;
UdpInfoTable.next = &UdpInfoTable;
//
// Roll through UDP endpoints
//
currentIndex = 1;
currentEntry = &UdpInfoTable;
while(1) {
if( !SnmpExtensionQuery( ASN_RFC1157_GETNEXTREQUEST,
&bindList, &errorStatus, &errorIndex )) {
return 1;
}
//
// Terminate when we're no longer seeing TCP information
//
if( bindEntry.name.idLength < 0xA ) break;
//
// Go back to start of table if we're reading info
// about the next byte
//
if( currentIndex != bindEntry.name.ids[9] ) {
currentEntry = UdpInfoTable.next;
currentIndex = bindEntry.name.ids[9];
}
//
// Build our TCP information table
//
switch( bindEntry.name.ids[9] ) {
case 1:
//
// Always allocate a new structure
//
newEntry = (TCPINFO *) malloc( sizeof(TCPINFO ));
newEntry->prev = currentEntry;
newEntry->next = &UdpInfoTable;
currentEntry->next = newEntry;
currentEntry = newEntry;
currentEntry->localip =
*(UINT *) bindEntry.value.asnValue.address.stream;
break;
case 2:
currentEntry->localport =
bindEntry.value.asnValue.number;
currentEntry = currentEntry->next;
break;
}
}
//
// Now print the connection information
//
currentEntry = UdpInfoTable.next;
while( currentEntry != &UdpInfoTable ) {
printf("%7s %s:%s\n", "UDP",
GetIpHostName( TRUE, currentEntry->localip, localname, HOSTNAMELEN),
GetPortName( currentEntry->localport, "udp", localport, PORTNAMELEN ) );
currentEntry = currentEntry->next;
}
printf("\n");
}
#define UNICODE
#define _UNICODE
#include <tchar.h>
#include <stdio.h>
#pragma warning ( disable: 4768)
#include <map>
typedef enum _SYSTEM_INFORMATION_CLASS
{
SystemHandleInformation = 16,
} SYSTEM_INFORMATION_CLASS;
typedef struct _SYSTEM_HANDLE_INFORMATION
{
ULONG ProcessId;
UCHAR ObjectTypeNumber;
UCHAR Flags;
USHORT Handle;
PVOID Object;
ACCESS_MASK GrantedAccess;
} SYSTEM_HANDLE_INFORMATION, *PSYSTEM_HANDLE_INFORMATION;
typedef enum _OBJECT_INFORMATION_CLASS
{
ObjectBasicInformation,
ObjectNameInformation,
ObjectTypeInformation,
ObjectAllTypesInformation,
ObjectHandleInformation
} OBJECT_INFORMATION_CLASS;
typedef struct _OBJECT_BASIC_INFORMATION
{
ULONG Attributes;
ACCESS_MASK GrantedAccess;
ULONG HandleCount;
ULONG PointerCount;
ULONG PagedPoolUsage;
ULONG NonPagedPoolUsage;
ULONG Reserved [ 3];
ULONG NameInformationLength;
ULONG TypeInformationLength;
ULONG SecurityDescriptorLength;
LARGE_INTEGER CreateTime;
} OBJECT_BASIC_INFORMATION, *POBJECT_BASIC_INFORMATION;
typedef struct _OBJECT_TYPE_INFORMATION
{
UNICODE_STRING Name;
ULONG ObjectCount;
ULONG HandleCount;
ULONG Reserved1 [ 4];
ULONG PeakObjectCount;
ULONG PeakHandleCount;
ULONG Reserved2 [ 4];
ULONG InvalidAttributes;
GENERIC_MAPPING GenericMapping;
ULONG ValidAccess;
UCHAR Unknown;
BOOLEAN MaintainHandleDatabase;
NT::POOL_TYPE PoolType;
ULONG PagedPoolUsage;
ULONG NonPagedPoolUsage;
} OBJECT_TYPE_INFORMATION, *POBJECT_TYPE_INFORMATION;
typedef struct _OBJECT_NAME_INFORMATION
{
UNICODE_STRING Name;
} OBJECT_NAME_INFORMATION, *POBJECT_NAME_INFORMATION;
typedef std::map<ULONG, ULONG> pid_map;
extern "C"
NTSTATUS
__stdcall
ZwQuerySystemInformation ( SYSTEM_INFORMATION_CLASS,
PVOID,
ULONG,
PULONG
);
extern "C"
NTSTATUS
__stdcall
ZwQueryObject ( HANDLE,
OBJECT_INFORMATION_CLASS,
PVOID,
ULONG,
PULONG
);
extern "C"
NTSTATUS
__stdcall
ZwDuplicateObject ( HANDLE,
HANDLE,
HANDLE,
PHANDLE,
ACCESS_MASK,
ULONG,
ULONG
);
POBJECT_NAME_INFORMATION
GetObjectNameInformation ( HANDLE __hObject, wchar_t* __pwszTypeFilter)
{
NTSTATUS _ntStatus;
OBJECT_BASIC_INFORMATION _obi;
POBJECT_TYPE_INFORMATION _poti;
POBJECT_NAME_INFORMATION _poni;
ULONG _ul;
ZwQueryObject ( __hObject,
ObjectBasicInformation,
&_obi,
sizeof ( _obi),
&_ul
);
_ul = _obi.TypeInformationLength + 2;
_poti = ( POBJECT_TYPE_INFORMATION) new char [ _ul];
_ntStatus = ZwQueryObject ( __hObject,
ObjectTypeInformation,
_poti,
_ul,
&_ul
);
if ( __pwszTypeFilter && !wcscmp ( _poti->Name.Buffer, __pwszTypeFilter))
{
delete [] _poti;
return NULL;
}
_ul = !_obi.NameInformationLength
? MAX_PATH * sizeof ( WCHAR)
: _obi.NameInformationLength;
_poni = ( POBJECT_NAME_INFORMATION) new char [ _ul];
_ntStatus = ZwQueryObject ( __hObject,
ObjectNameInformation,
_poni,
_ul,
&_ul
);
/*
wprintf ( L"Obj 0x%8.8x %.*s %.*s\n",
__hObject,
_poni->Name.Length / 2,
_poni->Name.Buffer,
_poti->Name.Length / 2,
_poti->Name.Buffer
);
*/
delete [] _poti;
return ( _poni);
}
void PrintObjectUsers ( wchar_t* __pwszObj, wchar_t* __pwszTypeFilter)
{
pid_map _pid_map;
ULONG _ulPID;
NTSTATUS _ntStatus;
HANDLE _hObject;
HANDLE _hProcess;
PSYSTEM_HANDLE_INFORMATION _pshi;
POBJECT_NAME_INFORMATION _poni;
ULONG _ul = 0x1000;
PULONG _pul = new ULONG [ _ul];
// hProcess = OpenProcess ( PROCESS_DUP_HANDLE, FALSE, dwPID);
while ( STATUS_INFO_LENGTH_MISMATCH == ZwQuerySystemInformation ( SystemHandleInformation,
_pul,
_ul * sizeof ( ULONG),
0
)
) delete [] _pul, _pul = new ULONG [ _ul *= 2];
_pshi = ( PSYSTEM_HANDLE_INFORMATION) ( _pul + 1);
for ( ULONG _i = 0; _i < *_pul; _i++)
{
_ulPID = _pshi [ _i].ProcessId;
_hObject = NULL;
_hProcess = OpenProcess ( PROCESS_DUP_HANDLE,
FALSE,
_ulPID
);
if ( !_hProcess)
{
//wprintf ( L"FAILED to 'OpenProcess()' for PID %d\n", _ulPID);
continue;
}
ZwDuplicateObject ( _hProcess,
( HANDLE) _pshi [ _i].Handle,
NtCurrentProcess (),
&_hObject,
0,
0,
DUPLICATE_SAME_ATTRIBUTES
);
if ( !_hObject)
{
wprintf ( L"FAILED to 'ZwDuplicateObject()' for PID %d\n", _ulPID);
continue;
}
if ( _hObject)
{
_poni = GetObjectNameInformation ( _hObject, __pwszTypeFilter);
if ( !_poni) continue;
if ( !_poni->Name.Length) continue;
if ( wcsstr ( _poni->Name.Buffer, __pwszObj))
{
pid_map::iterator _i_map = _pid_map.find ( _ulPID);
// if ( _i_map == _pid_map.end ())
{
wprintf ( L"PID: %d\tNAME: %s\n",
_ulPID,
_poni->Name.Buffer
);
// _pid_map.insert ( pid_map::value_type ( _ulPID, _ulPID));
}
}
delete [] _poni;
}
CloseHandle ( _hObject);
CloseHandle ( _hProcess);
}
delete [] _pul;
}
int wmain ( int __wargc,
wchar_t** __wargv
)
{
wchar_t* __pwc;
if ( 2 != __wargc)
return ( -1);
PrintObjectUsers ( *( __wargv + 1), NULL);
return ( 0);
}
#include <windows.h>
#include <lmcons.h>
#include <stdio.h>
#pragma comment ( lib, "advapi32.lib")
#pragma comment ( lib, "user32.lib")
int GetProcessOwner ( HANDLE hProcess, char* acBuffer, ULONG ulSize)
{
PSECURITY_DESCRIPTOR psd;
PSID psid;
DWORD dwSDLength;
DWORD dwNeeded;
DWORD dwErr;
DWORD dwNameSize;
char acReferencedDomain [ LM20_DNLEN + 1];
DWORD dwDomainBufSize = sizeof ( acReferencedDomain);
SID_NAME_USE eUse;
BOOL bDefaulted;
SECURITY_INFORMATION si = OWNER_SECURITY_INFORMATION;
dwNameSize = ulSize;
if ( !GetKernelObjectSecurity ( hProcess,
si,
NULL,
0,
&dwNeeded
)
)
{
dwErr = GetLastError ();
if ( ERROR_INSUFFICIENT_BUFFER != dwErr)
{
return ( dwErr);
}
dwSDLength = dwNeeded;
psd = ( PSECURITY_DESCRIPTOR) LocalAlloc ( LPTR,
dwSDLength
);
__try
{
if ( !GetKernelObjectSecurity ( hProcess,
si,
psd,
dwSDLength,
&dwNeeded
)
)
{
dwErr = GetLastError ();
__leave;
}
if ( !GetSecurityDescriptorOwner ( psd,
&psid,
&bDefaulted
)
)
{
dwErr = GetLastError ();
__leave;
}
// lookup clear text name of the owner
if ( !LookupAccountSid ( NULL,
psid,
acBuffer,
&dwNameSize,
acReferencedDomain,
&dwDomainBufSize,
&eUse
)
)
{
dwErr = GetLastError ();
__leave;
}
dwErr = 0;
}
__finally
{
LocalFree ( psd);
}
}
return ( dwErr);
}
BOOL EnableDebugPriv ( BOOL bEnable)
{
HANDLE hToken;
TOKEN_PRIVILEGES tp;
if ( !OpenProcessToken ( GetCurrentProcess (),
TOKEN_ADJUST_PRIVILEGES,
&hToken
)
) return ( FALSE);
tp.PrivilegeCount = 1;
LookupPrivilegeValue ( NULL,
SE_DEBUG_NAME,
&tp.Privileges [ 0].Luid
);
tp.Privileges [ 0].Attributes = bEnable
? SE_PRIVILEGE_ENABLED
: 0;
AdjustTokenPrivileges ( hToken,
FALSE,
&tp,
sizeof ( tp),
NULL,
NULL
);
return ( GetLastError() == ERROR_SUCCESS);
}
void main ( int argc, char** argv)
{
HANDLE hProcess;
char acBuf [ 256];
DWORD dwErr;
if ( 2 != argc)
return;
DWORD dwPID = atoi(*( argv + 1));
printf ( "\nPID:\t%d\n", dwPID);
EnableDebugPriv ( TRUE);
hProcess = OpenProcess ( PROCESS_ALL_ACCESS, FALSE, dwPID);
dwErr = GetProcessOwner ( hProcess, acBuf, 256);
if ( !dwErr)
printf ( "\nowner:\t%s\n", acBuf);
else
printf ( "\nerror:\t%d\n", dwErr);
CloseHandle ( hProcess);
}