piątek, 2 listopada 2012

Windows TCP source port + PID , DLL

Link1
SRC_PORT + PID

------
;~  _GetTCPtable( [optional handle to "ws2_32.dll" [, optional handle to "iphlpapi.dll" ] ] ) ;~ ;~  Return Value ;~  Success:    TCPtable[][] = 2-D array ;~               [0][0] = number of connections ;~           for connection n: ;~               [n][0] = connection state (integer) ;~               [n][1] = local IP ;~               [n][2] = local port ;~               [n][3] = remote IP ;~               [n][4] = remote port ;~               [n][5] = connection state (informative text) ;~  Failure:    TCPtable[0][0] = -1 Func _GetTCPtable($WSdll = "ws2_32.dll", $IHdll = "iphlpapi.dll")     Local Const $connState[12] = ["CLOSED", "LISTENING", "SYN_SENT", "SYN_RCVD", "ESTABLISHED", "FIN_WAIT1", _             "FIN_WAIT2", "CLOSE_WAIT", "CLOSING", "LAST_ACK", "TIME_WAIT", "DELETE_TCB"]         Local $TCPtable[1][1] = [[ -1]] ; preset to "failed"     $dwSize = DllStructCreate("dword") ; for MIB_TCPTABLE buffer size     $MIB_TCPTABLE = DllStructCreate("dword") ; nominal struct initially     DllStructSetData($dwSize, 1, 0) ; force zero size     $ret = DllCall($IHdll, "int", "GetTcpTable", "ptr", DllStructGetPtr($MIB_TCPTABLE), "ptr", DllStructGetPtr($dwSize), "int", 1) ; get size     If @error Or $ret[0] <> 122 Then Return $TCPtable ; dllCall error or RC is *not* ERROR_INSUFFICIENT_BUFFER = 122     $MIB_TCPTABLE = ""     For $i = 1 To DllStructGetData($dwSize, 1) / 4 ; make to requested size of buffer         $MIB_TCPTABLE &= "dword;"     Next     $MIB_TCPTABLE = DllStructCreate(StringTrimRight($MIB_TCPTABLE, 1)) ; requested struct     DllStructSetData($dwSize, 1, DllStructGetSize($MIB_TCPTABLE)) ; recheck its size     $ret = DllCall($IHdll, "int", "GetTcpTable", "ptr", DllStructGetPtr($MIB_TCPTABLE), "ptr", DllStructGetPtr($dwSize), "int", 1) ; get data     If @error Or $ret[0] Then Return $TCPtable ; dllCall error or RC is Error     $numTCPentries = DllStructGetData($MIB_TCPTABLE, 1) ; number of entries     ReDim $TCPtable[$numTCPentries + 1][6]         For $i = 1 To $numTCPentries         $offset = ($i - 1) * 5 + 1 ; dword offset into struct         $TCPtable[$i][0] = DllStructGetData($MIB_TCPTABLE, $offset + 1) ; integer connection state         $TCPtable[$i][5] = $connState[$TCPtable[$i][0] - 1] ; connection state text                 $ret = DllCall($WSdll, "str", "inet_ntoa", "uint", DllStructGetData($MIB_TCPTABLE, $offset + 2)) ; local IP / translate         If @error Then Return $TCPtable ; dllCall error         $TCPtable[$i][1] = $ret[0]         $ret = DllCall($WSdll, "ushort", "ntohs", "uint", DllStructGetData($MIB_TCPTABLE, $offset + 3)) ; local port / translate         If @error Then Return $TCPtable ; dllCall error         $TCPtable[$i][2] = $ret[0]                 If $TCPtable[$i][0] <= 2 Then ; CLOSED or LISTENING state             $TCPtable[$i][3] = "0.0.0.0"             $TCPtable[$i][4] = 0         Else             $ret = DllCall($WSdll, "str", "inet_ntoa", "uint", DllStructGetData($MIB_TCPTABLE, $offset + 4)) ; remote IP / translate             If @error Then Return $TCPtable ; dllCall error             $TCPtable[$i][3] = $ret[0]             $ret = DllCall($WSdll, "ushort", "ntohs", "uint", DllStructGetData($MIB_TCPTABLE, $offset + 5)) ; remote port / translate             If @error Then Return $TCPtable ; dllCall error             $TCPtable[$i][4] = $ret[0]         EndIf     Next     $dwSize = 0     $MIB_TCPTABLE = 0     $TCPtable[0][0] = $numTCPentries ; success     Return $TCPtable     EndFunc   ;==>_GetTCPtable ;~  _CloseTCPconnection( LocalIP, LocalPort, RemoteIP, RemotePort, [optional handle to "ws2_32.dll" [, optional handle to "iphlpapi.dll"]] ) ;~ ;~  Return Value ;~  Success:    1 ;~  Failure:    0 Func _CloseTCPconnection($localIP, $localPort, $remoteIP, $remotePort, $WSdll = "ws2_32.dll", $IHdll = "iphlpapi.dll")     $MIB_TCPROW = DllStructCreate("dword;dword;dword;dword;dword") ; connection struct     DllStructSetData($MIB_TCPROW, 1, 12) ; set to DELETE_TCB state = 12         $ret = DllCall($WSdll, "uint", "inet_addr", "str", $localIP) ; local IP / translate     If Not @error Then DllStructSetData($MIB_TCPROW, 2, $ret[0])     $ret = DllCall($WSdll, "uint", "htons", "ushort", $localPort) ; local port / translate     If Not @error Then DllStructSetData($MIB_TCPROW, 3, $ret[0])     $ret = DllCall($WSdll, "uint", "inet_addr", "str", $remoteIP) ; remote IP / translate     If Not @error Then DllStructSetData($MIB_TCPROW, 4, $ret[0])     $ret = DllCall($WSdll, "uint", "htons", "ushort", $remotePort) ; remote port / translate     If Not @error Then DllStructSetData($MIB_TCPROW, 5, $ret[0])     $ret = DllCall($IHdll, "int", "SetTcpEntry", "ptr", DllStructGetPtr($MIB_TCPROW)) ; close connection     If @error Or $ret[0] Then Return 0 ; dllCall error or RC is Error         $MIB_TCPROW = 0     Return 1 ; success     EndFunc   ;==>_CloseTCPconnection
-----------------


---------------------


Alright, so I'm extending my company's flexlm vendor daemon to be a little bit more revealing to client applications.
I need to be able to find out what port lmgrd is listening on before clients connect. The API documentation seems to be rather barren, and I believe they keep most of their code in a compiled form so I can't just look at their source.
Is it possible to call upon the awesome power of the Windows API to find out what ports a particular process is using? If Process Explorer from sysinternals can do it, I should be able to right? Does anyone have sample code for this?
It needs to support Windows XP and higher since many of our clients have yet to upgrade.
Edit: I should note that it turns out FLEX has support for pulling the port from the license file. I don't have the code in front of me, but know that this isn't the best way to find out what ports your vendor daemon/lmgrd is running.
share|improve this question

64% accept rate
feedback

3 Answers

GetTcpTable2 -- see EDIT
The GetTcpTable function retrieves the IPv4 TCP connection table.
This will fill in a MIB_TCPTABLE structure.
typedef struct _MIB_TCPTABLE {
  DWORD      dwNumEntries;
  MIB_TCPROW table[ANY_SIZE];
} MIB_TCPTABLE, *PMIB_TCPTABLE;
And now the MIB_TCPROW
typedef struct _MIB_TCPROW {
  DWORD dwState;
  DWORD dwLocalAddr;
  DWORD dwLocalPort;
  DWORD dwRemoteAddr;
  DWORD dwRemotePort;
} MIB_TCPROW, *PMIB_TCPROW;
EDIT IMPORTANT:
You need to use GetTcpTable2 in order to get the corresponding PID associated as well.
typedef struct _MIB_TCPROW2 {
  DWORD                        dwState;
  DWORD                        dwLocalAddr;
  DWORD                        dwLocalPort;
  DWORD                        dwRemoteAddr;
  DWORD                        dwRemotePort;
  DWORD                        dwOwningPid;
  TCP_CONNECTION_OFFLOAD_STATE dwOffloadState;
} MIB_TCPROW2, *PMIB_TCPROW2;
dwOwningPid
share|improve this answer
Crap. No can do. Seems the GetTcpTable2 function is a Vista and higher function. I should have specified it should work with Windows XP as a minimum since many of our clients haven't upgraded yet. I'll update my original post. Excellent find though, I must say. – RandomInsano Jun 28 '11 at 20:14
So... it seems the closest Windows XP version of this is AllocateAndGetTcpExTableFromStackmsdn.microsoft.com/en-us/library/aa365804(v=vs.85).aspx – RandomInsano Jun 28 '11 at 20:57
1 
The GetTcpTable or GetExtendedTcpTable functions should be used to retrieve the TCP connection table instead of using the AllocateAndGetTcpExTableFromStack function. Note The AllocateAndGetTcpExTableFromStack function is deprecated and not supported on Windows Vista and later. On the Microsoft Windows Software Development Kit (SDK) released for Windows Vista and later, the function prototype for AllocateAndGetTcpExTableFromStack is still defined in the Iphlpapi.h header file for continued support on Windows Server 2003 and Windows XP. – kisplit Jun 28 '11 at 21:02
1 
Use: GetExtendedTcpTable and GetOwnerModuleFromTcpEntry – kisplit Jun 28 '11 at 21:02
Just found the GetExtendedTcpTable. Awesome! – RandomInsano Jun 28 '11 at 21:16
feedback
In the worst case, you could always parse the output of:
netstat -bna
share|improve this answer
Interesting idea. More to find a reverse engineered version of that app. I've fallen upon the old winternals source code and will see how that fellow implemented his TCPView application. – RandomInsano Jun 28 '11 at 20:30
feedback
Here's the code I ended up with, for anyone who hits this problem after me
#include "stdafx.h"
#include 
#include 

// These are just for the ntohl function in the printf below
#include 
#pragma comment(lib, "Ws2_32.lib")

DWORD (WINAPI *pGetExtendedTcpTable)(
  PVOID pTcpTable,
  PDWORD pdwSize,
  BOOL bOrder,
  ULONG ulAf,
  TCP_TABLE_CLASS TableClass,
  ULONG Reserved
);

int _tmain(int argc, _TCHAR* argv[])
{
    MIB_TCPTABLE_OWNER_PID *pTCPInfo;
    MIB_TCPROW_OWNER_PID *owner;
    DWORD size;
    DWORD dwResult;

    HMODULE hLib = LoadLibrary( "iphlpapi.dll" );

    pGetExtendedTcpTable = (DWORD (WINAPI *)(PVOID,PDWORD,BOOL,ULONG,TCP_TABLE_CLASS,ULONG))
        GetProcAddress(hLib, "GetExtendedTcpTable");

    if ( !pGetExtendedTcpTable )
    {
        printf("Could not load iphlpapi.dll. This application is for Windows XP SP2 and up.\n");
        return 1;
    }

    dwResult = pGetExtendedTcpTable(NULL,       &size, false, AF_INET, TCP_TABLE_OWNER_PID_LISTENER, 0);
    pTCPInfo = (MIB_TCPTABLE_OWNER_PID*)malloc(size);
    dwResult = pGetExtendedTcpTable(pTCPInfo,   &size, false, AF_INET, TCP_TABLE_OWNER_PID_LISTENER, 0);

    if (dwResult != NO_ERROR)
    {
        printf("Couldn't get our IP table");
        return 2;
    }

    printf("Iterating though table:\n");
    for (DWORD dwLoop = 0; dwLoop < pTCPInfo->dwNumEntries; dwLoop++)
    {
        owner = &pTCPInfo->table[dwLoop];

        printf("  PID: %5u - Port: %5u\n", owner->dwOwningPid, ntohs(owner->dwLocalPort));
    }

    // Pause a moment
    printf("Done Processing\n");

    return 0;
}
share|improve this answer

Brak komentarzy:

Prześlij komentarz

Ginekolog dr n. med. Piotr Siwek

Gabinet ginekologiczny specjalista ginekolog - położnik dr n. med. Piotr Siwek