Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Capture Packets By Process Id #147

Open
hammad2224 opened this issue Jul 17, 2020 · 20 comments
Open

Capture Packets By Process Id #147

hammad2224 opened this issue Jul 17, 2020 · 20 comments

Comments

@hammad2224
Copy link

As this is the feature lack by most network monitoring tools.
is it possible to add a feature where we capture the traffic by process id.
and then create a wincap file to perform the analysis in wireshark?

If that can be done then it would be great

Thanks for this excellent work.

Regards,
Hammad

@chmorgan
Copy link
Collaborator

@hammad2224 it may be possible to see what process is on a given port if you run as a privileged process, then you could map back using that info and the port a given packet was transferring on. I'm not sure how it goes back into the capture file though. You might want to check to see if the npcap sdk provides any of that process info.

@hammad2224
Copy link
Author

yahhh i was thinking that if we netstat and get the opened ports by process id and when capturring the packets set the processId property in the packet at the time of capture. and que the captures we need to analyze.

or at the time of capturing we could do netstat and include any of the data received by setting the process id.

i will write down the function and show you may be you can include that in the source.

@kayoub5
Copy link
Collaborator

kayoub5 commented Sep 27, 2020

@hammad2224 In addition to @chmorgan solution, you could also use the WinDivertDevice, since the WinDivert driver offer filtering by process id.

@globalpolicy
Copy link

@kayoub5 The filter token 'processId' as listed https://reqrypt.org/windivert-doc.html is only supported in WinDivert version 2.2. But even when this exact version of the WinDivert dll and driver is used, SharpPCap gives a PCapException Filter string is invalid at position .... Filter expression contains a bad token for layer

@kayoub5
Copy link
Collaborator

kayoub5 commented Apr 3, 2021

@globalpolicy sample code?

@globalpolicy
Copy link

@kayoub5 https://pastebin.com/BXR0jeTx
The exception occurs at line 13.
Also, the event OnPacketArrival doesn't trigger.

@kayoub5
Copy link
Collaborator

kayoub5 commented Apr 3, 2021

You need to change device.Layer, processId requires layer FLOW, SOCKET or REFLECT (default value Network). See https://reqrypt.org/windivert-doc.html#filter_language and WinDivertLayer enum.

@globalpolicy
Copy link

I tried doing that but it still gives me the same exception.

@AlmightyLks
Copy link

Would you guys be interested if I looked into implementing this? 🤔
I feel like I am onto something, but I wouldn't waste efforts on something that won't be accepted in the first place. 😄

@kayoub5
Copy link
Collaborator

kayoub5 commented Dec 5, 2021

After some digging I found that WinDivert can either:

  • Listen for Socket Events (bind/connect/disconnect), where you can filter on process id
  • Read packets, but it does not have process id for each packet

Having a lookup table that record socket events, and cache a mapping table between endpoint and process id has to be done in an extra class.

The initial values for the table could be filled using AllocateAndGetTcpExTableFromStack, see https://www.codeproject.com/Articles/4298/Getting-active-TCP-UDP-connections-on-a-box and https://docs.microsoft.com/en-us/windows/win32/api/iphlpapi/nf-iphlpapi-allocateandgettcpextablefromstack.

All this is nice and possible, but those are Windows only drivers/APIs.
I assume similar functions exist for Linux/Mac.

@AlmightyLks I can't say for sure if your solution will be accepted or not without even seeing it.
But if it's implemented as an extra helper class that returns process id from given IP endpoint (like the ARP class), so that it does not affect performance of existing code, and the PR includes enough coverage, then I don't see a reason why not.

@AlmightyLks
Copy link

@kayoub5
For all I know, TCP packets can be associated back to the process via a simple API class from .NET. i am not sure whether it's windows-only, from the top of my head, I only remember that it has UnsupportedPlatforms("android").

I looked more into this last night and I'd say that this would suit more into PacketNet, as it requires getting the port which needs to be parsed from the byte data. I guess this would belong into the TcpPacket class then 😄

@AlmightyLks
Copy link

As you are thinking about manually mapping the tcp connection tables from the winapi, .NET actually already has a class and an appropriate method for it.

https://docs.microsoft.com/en-us/dotnet/api/system.net.networkinformation.ipglobalproperties.getactivetcpconnections

That the System.Net,* devs did mark this to be unsupported for android, but didn't mark it for linux/unix and continue to keep it fully available up to .NET 6 should mean that it is cross-platform. I'll do some more digging via source.dot.net later

@kayoub5
Copy link
Collaborator

kayoub5 commented Dec 5, 2021

I am aware of that API, unfortunately it does not provide process id.

@AlmightyLks
Copy link

I just noticed! 😄
As I was looking into iphlpapi.dll's GetExtendedTcpTable function, a friend told me that there already exited a wrapped API for this.
That was my last track that I was looking into that night
Alright, back to the winapi then

@AlmightyLks
Copy link

AlmightyLks commented Dec 24, 2021

TLDR;
Seemingly next to impossible, unless lots of efforts and knowledgeable people are involved


Alright. After days of research and prototyping, I've looked into it in depth.
I have got a prototype of Windows to work, and I've got a prototype of Linux to work.
However, unlike Windows' implementation of a simple Win32 API P/Invoke to get all information at once, the effort to get it to work on Linux is a mess.

For Linux I have to open and read the /proc/net/tcp file and then iterate through and fetch all sub directories of /proc/N/fd where N is practically sequential and can possibly range from 1 to 2147483647, if not even 4294967295, to find a file named socket[Y] where Y is the socket INode gathered from the info fetched from /proc/net/tcp, meaning I need to fetch all file names, parse the file name to get the INode from socket[Y] and match the port from /proc/net/tcp and the process id by parsing the directory name /proc/N/fd, so I can combine the two via the inode id.

image


Top right

An example program which continuously sends data through a tcp connection, taking up port 8000 (An example target what I am looking for)

Bottom right

Getting my example program's process id (3793) to simulate and skip the process of scanning through all /proc/ directories and directly navigate to the right folder to see result

Top left

cat /proc/net/tcp to view all open tcp connections including the socket's inode from our target port

Bottom left

ls /proc/3793/fd -l containing the process id (which we know) from a "simulated" iteration through all folders, now at the point of finding the folder of which contains the socket with the target inode (socket[52096])


This is very very inefficient from Linux's side and can't be tolerated, as it is pure bruteforcing and trial & error'ing access violations, as well as a horrible iterative approach.
Unfortuanetly, seemingly there is no native function to call, for this information on Linux, and built-in tools such as netstat and ss do it that way as well..
For that matter I have shared and proposed the idea in a dotnet/runtime issue and furthermore I have, just a few hours ago, found a discussion about this in a WireShark issue where specifically this is of interest, talking about how associating ports and process id's is a mess for cross-platform compatibility

@kayoub5
Copy link
Collaborator

kayoub5 commented Dec 24, 2021

@AlmightyLks I know this may seem inefficient, but why not just use lsof in Linux once you get the inode?

@AlmightyLks
Copy link

AlmightyLks commented Dec 24, 2021

@kayoub5 Interesting point. Could you provide a CLI-example to fetch the info filtered by a given inode, so I could mess with it?

@kayoub5
Copy link
Collaborator

kayoub5 commented Dec 24, 2021

Syntax: ls -i[46][protocol][@hostname|hostaddr][:service|port]
Example:

lsof -i4TCP@172.29.45.73:59686 -Fp

It could be slow (due to creating a new child process), but it is accurate and simple.

@kayoub5
Copy link
Collaborator

kayoub5 commented Jan 15, 2022

@AlmightyLks did you get any luck?

@AlmightyLks
Copy link

AlmightyLks commented Jan 15, 2022

Didn't have the time to look into it yet, but this is also unsuiting imo, especially as this - again - is going to be very unperformant

I also will be away for a while due to personal reasons, so no time to check up on it now

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants