~ruther/NosSmooth

ref: b91870a525340f7604b92910f2d3dd2559930b53 NosSmooth/Pcap/NosSmooth.Pcap/TcpConnectionHelper.cs -rw-r--r-- 6.7 KiB
b91870a5 — Rutherther feat(pcap): try to guess packet is world packet if no encryption key is detected 2 years ago
                                                                                
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
//
//  TcpConnectionHelper.cs
//
//  Copyright (c) František Boháček. All rights reserved.
//  Licensed under the MIT license. See LICENSE file in the project root for full license information.

using System.Diagnostics;
using System.Net.NetworkInformation;
using System.Runtime.InteropServices;

namespace NosSmooth.Pcap;

/// <summary>
/// A class for obtaining process tcp connections.
/// </summary>
/// <remarks>
/// Works on Windows only so far.
/// </remarks>
public static class TcpConnectionHelper
{
    private const int AF_INET = 2; // IP_v4 = System.Net.Sockets.AddressFamily.InterNetwork
    private const int AF_INET6 = 23; // IP_v6 = System.Net.Sockets.AddressFamily.InterNetworkV6

    /// <summary>
    /// Get TCP IPv4 connections of the specified processes.
    /// </summary>
    /// <param name="processIds">The process ids to look for.</param>
    /// <returns>Map from process ids to connecitons.</returns>
    /// <exception cref="NotImplementedException">Thrown if not windows.</exception>
    public static IReadOnlyDictionary<int, List<TcpConnection>> GetConnections(IReadOnlyList<int> processIds)
    {
        if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
        {
            throw new NotImplementedException();
        }

        var result = new Dictionary<int, List<TcpConnection>>();
        var tcpv4Connections = GetAllTCPv4Connections();

        foreach (var connection in tcpv4Connections)
        {
            var process = processIds.FirstOrDefault(x => x == connection.OwningPid, -1);
            if (process != -1)
            {
                if (!result.ContainsKey(process))
                {
                    result.Add(process, new List<TcpConnection>());
                }

                result[process].Add
                (
                    new TcpConnection
                    (
                        connection.LocalAddr,
                        (ushort)(connection.LocalPort[1] | (connection.LocalPort[0] << 8)),
                        connection.RemoteAddr,
                        (ushort)(connection.RemotePort[1] | (connection.RemotePort[0] << 8))
                    )
                );
            }
        }

        return result;
    }

    private static List<MIB_TCPROW_OWNER_PID> GetAllTCPv4Connections()
    {
        return GetTCPConnections<MIB_TCPROW_OWNER_PID, MIB_TCPTABLE_OWNER_PID>(AF_INET);
    }

    private static List<MIB_TCP6ROW_OWNER_PID> GetAllTCPv6Connections()
    {
        return GetTCPConnections<MIB_TCP6ROW_OWNER_PID, MIB_TCP6TABLE_OWNER_PID>(AF_INET6);
    }

    private static List<TIPR> GetTCPConnections<TIPR, TIPT>(int ipVersion)
    {
        // IPR = Row Type, IPT = Table Type

        TIPR[] tableRows;
        int buffSize = 0;
        var dwNumEntriesField = typeof(TIPT).GetField("DwNumEntries");

        // how much memory do we need?
        uint ret = GetExtendedTcpTable
        (
            IntPtr.Zero,
            ref buffSize,
            true,
            ipVersion,
            TCP_TABLE_CLASS.TCP_TABLE_OWNER_PID_ALL
        );
        IntPtr tcpTablePtr = Marshal.AllocHGlobal(buffSize);

        try
        {
            ret = GetExtendedTcpTable
            (
                tcpTablePtr,
                ref buffSize,
                true,
                ipVersion,
                TCP_TABLE_CLASS.TCP_TABLE_OWNER_PID_ALL
            );
            if (ret != 0)
            {
                return new List<TIPR>();
            }

            // get the number of entries in the table
            TIPT table = (TIPT)Marshal.PtrToStructure(tcpTablePtr, typeof(TIPT))!;
            int rowStructSize = Marshal.SizeOf(typeof(TIPR));
            uint numEntries = (uint)dwNumEntriesField!.GetValue(table)!;

            // buffer we will be returning
            tableRows = new TIPR[numEntries];

            IntPtr rowPtr = (IntPtr)((long)tcpTablePtr + 4);
            for (int i = 0; i < numEntries; i++)
            {
                TIPR tcpRow = (TIPR)Marshal.PtrToStructure(rowPtr, typeof(TIPR))!;
                tableRows[i] = tcpRow;
                rowPtr = (IntPtr)((long)rowPtr + rowStructSize); // next entry
            }
        }
        finally
        {
            // Free the Memory
            Marshal.FreeHGlobal(tcpTablePtr);
        }
        return tableRows != null ? tableRows.ToList() : new List<TIPR>();
    }

    // https://msdn2.microsoft.com/en-us/library/aa366913.aspx
    [StructLayout(LayoutKind.Sequential)]
    private struct MIB_TCPROW_OWNER_PID
    {
        public uint State;
        public uint LocalAddr;
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
        public byte[] LocalPort;
        public uint RemoteAddr;
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
        public byte[] RemotePort;
        public uint OwningPid;
    }

    // https://msdn2.microsoft.com/en-us/library/aa366921.aspx
    [StructLayout(LayoutKind.Sequential)]
    private struct MIB_TCPTABLE_OWNER_PID
    {
        public uint DwNumEntries;
        [MarshalAs(UnmanagedType.ByValArray, ArraySubType = UnmanagedType.Struct, SizeConst = 1)]
        public MIB_TCPROW_OWNER_PID[] Table;
    }

    // https://msdn.microsoft.com/en-us/library/aa366896
    [StructLayout(LayoutKind.Sequential)]
    private struct MIB_TCP6ROW_OWNER_PID
    {
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)]
        public byte[] LocalAddr;
        public uint LocalScopeId;
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
        public byte[] LocalPort;
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)]
        public byte[] RemoteAddr;
        public uint RemoteScopeId;
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
        public byte[] RemotePort;
        public uint State;
        public uint OwningPid;
    }

    // https://msdn.microsoft.com/en-us/library/windows/desktop/aa366905
    [StructLayout(LayoutKind.Sequential)]
    private struct MIB_TCP6TABLE_OWNER_PID
    {
        public uint DwNumEntries;
        [MarshalAs(UnmanagedType.ByValArray, ArraySubType = UnmanagedType.Struct, SizeConst = 1)]
        public MIB_TCP6ROW_OWNER_PID[] Table;
    }

    [DllImport("iphlpapi.dll", SetLastError = true)]
    private static extern uint GetExtendedTcpTable
    (
        IntPtr pTcpTable,
        ref int dwOutBufLen,
        bool sort,
        int ipVersion,
        TCP_TABLE_CLASS tblClass,
        uint reserved = 0
    );

    private enum TCP_TABLE_CLASS
    {
        TCP_TABLE_BASIC_LISTENER,
        TCP_TABLE_BASIC_CONNECTIONS,
        TCP_TABLE_BASIC_ALL,
        TCP_TABLE_OWNER_PID_LISTENER,
        TCP_TABLE_OWNER_PID_CONNECTIONS,
        TCP_TABLE_OWNER_PID_ALL,
        TCP_TABLE_OWNER_MODULE_LISTENER,
        TCP_TABLE_OWNER_MODULE_CONNECTIONS,
        TCP_TABLE_OWNER_MODULE_ALL
    }
}
Do not follow this link