Discussion:
Packet Sniffer script
(too old to reply)
Robbie Foust
2007-11-19 02:16:54 UTC
Permalink
Hi,

I meant to post this a while back but never got around to it. I wrote
a IP packet sniffer script for powershell and figure that others might
find it useful. The script is on my blog:

http://blog.robbiefoust.com

Let me know if anyone has questions. :-)

- Robbie

--
Robbie Foust
Windows Tech Lead
OIT/CSI - Duke University
Jon
2007-11-19 12:19:32 UTC
Permalink
Post by Robbie Foust
Hi,
a IP packet sniffer script for powershell and figure that others might
http://blog.robbiefoust.com
Let me know if anyone has questions. :-)
- Robbie
--
Robbie Foust
Windows Tech Lead
OIT/CSI - Duke University
Looks useful. Thanks Robbie.


I've been looking for a decent packet sniffer for Vista, so something like
this that's entirely customizable, may be just the thing. I hadn't
considered PowerShell for it previously, but in retrospect it seems ideally
suited.


A couple of observations here ...



(1) I get this error message on first run of the script (but works fine on
subsequent runs) with this line ....


[void]$socket.iocontrol([net.sockets.iocontrolcode]::ReceiveAll,$byteIn,$byteOut)



#---------------------------
Exception calling "IOControl" with "3" argument(s): "The attempted operation
is not supported for the type of object referenced"
At C:\PS-ScriptsLibrary\get-packet.ps1:91 char:24
+ [void]$socket.iocontrol( <<<<
[net.sockets.iocontrolcode]::ReceiveAll,$byteIn,$byteOut)
#---------------------------



Oddly, if I rerun the same command, then it works fine.



So I replaced that line with these, and it then works. You will probably be
able to think of a better solution to that issue....

#-----------------------------
$ErrorActionPreference = "SilentlyContinue"
[void]$socket.iocontrol([net.sockets.iocontrolcode]::ReceiveAll,$byteIn,$byteOut)
If ($? -ne $true) {
[void]$socket.iocontrol([net.sockets.iocontrolcode]::ReceiveAll,$byteIn,$byteOut) If ($? -ne $true) {exit}}$ErrorActionPreference = "stop"#-----------------------------(2) Secondly, the script doesn't pick up the local ip address for my USBInternet connection, if it's not specified (perhaps understandably sinceit's a USB connection rather than via a network card). Anyhow something likethis works fine ....$Winsock = New-Object -ComObject "MSWinsock.Winsock"$localIP = $Winsock.LocalIPOtherwise it works great, and I'm sure it will prove useful. Thanks forsharing.--Jon
Jon
2007-11-19 12:24:53 UTC
Permalink
The second portion of that seems to have gotten hashed up .. so here's how
it SHOULD have read ....


2) Secondly, the script doesn't pick up the local ip address for my USB
Internet connection, if it's not specified (perhaps understandably sinceit's
a USB connection rather than via a network card). Anyhow something likethis
works fine ....


$Winsock = New-Object -ComObject "MSWinsock.Winsock"
$localIP = $Winsock.LocalIP



Otherwise it works great, and I'm sure it will prove useful. Thanks for
sharing.
--
Jon
Robbie Foust
2007-11-19 14:37:53 UTC
Permalink
Hi Jon,

Thanks for the feedback. That iocontrol error is odd...I haven't run
into that problem. I'll investigate and see if I can figure out what
may be causing it. Otherwise, I'll just modify the code with your
changes. I also like your suggestion for obtaining the local IP.

One thing I didn't mention was that I know the script doesn't work on
w2k8 as is because w2k8 has ipv6 installed by default, and the way I'm
determining the local ip wasn't quite working the way I wanted.
Hopefully your suggestion will fix that, but if not, I'll find a
workaround and post it when I have a solution.

- Robbie
Jon
2007-11-19 22:30:45 UTC
Permalink
Post by Robbie Foust
Hi Jon,
Thanks for the feedback. That iocontrol error is odd...I haven't run
into that problem. I'll investigate and see if I can figure out what
may be causing it. Otherwise, I'll just modify the code with your
changes. I also like your suggestion for obtaining the local IP.
One thing I didn't mention was that I know the script doesn't work on
w2k8 as is because w2k8 has ipv6 installed by default, and the way I'm
determining the local ip wasn't quite working the way I wanted.
Hopefully your suggestion will fix that, but if not, I'll find a
workaround and post it when I have a solution.
- Robbie
Hi Robbie


Just been playing a bit more with this, and I've noticed that if I set


$byteIn[0] = 3 (corresponding to RCVALL_IPLEVEL - ie capture at the IP
level in non-promiscuous mode ???)

in the original script as opposed to

$byteIn[0] = 1 ( corresponding to promiscuous mode RCVALL_ON ??? )


then I don't get any errors with the script concerning my Internet
connection via modem, but still seem to get the packets captured to the
level I was looking for.

So it's perhaps the 'promiscuous mode' aspect to it that's causing the error
in my case, whereas capture at the ip level is ok.

I basically based the value of 3 from a guessed value for the
RCVALL_IPLEVEL option in the RCVALL_VALUE enumeration on this page

Winsock IOCTLs
http://msdn2.microsoft.com/en-us/library/bb736550.aspx

so I may well be off on completely the wrong track with that (in which case
please feel free to correct me), but hey it seems to work ;-)


So thanks again.


[ NB I've only tested it on Vista too, which I probably should also have
mentioned. ]
--
Jon
Kuma
2007-11-19 23:50:56 UTC
Permalink
Post by Jon
Post by Robbie Foust
Hi Jon,
Thanks for the feedback. That iocontrol error is odd...I haven't run
into that problem. I'll investigate and see if I can figure out what
may be causing it. Otherwise, I'll just modify the code with your
changes. I also like your suggestion for obtaining the local IP.
One thing I didn't mention was that I know the script doesn't work on
w2k8 as is because w2k8 has ipv6 installed by default, and the way I'm
determining the local ip wasn't quite working the way I wanted.
Hopefully your suggestion will fix that, but if not, I'll find a
workaround and post it when I have a solution.
- Robbie
Hi Robbie
Just been playing a bit more with this, and I've noticed that if I set
$byteIn[0] = 3 (corresponding to RCVALL_IPLEVEL - ie capture at the IP
level in non-promiscuous mode ???)
in the original script as opposed to
$byteIn[0] = 1 ( corresponding to promiscuous mode RCVALL_ON ??? )
then I don't get any errors with the script concerning my Internet
connection via modem, but still seem to get the packets captured to the
level I was looking for.
So it's perhaps the 'promiscuous mode' aspect to it that's causing the error
in my case, whereas capture at the ip level is ok.
I basically based the value of 3 from a guessed value for the
RCVALL_IPLEVEL option in the RCVALL_VALUE enumeration on this page
Winsock IOCTLshttp://msdn2.microsoft.com/en-us/library/bb736550.aspx
so I may well be off on completely the wrong track with that (in which case
please feel free to correct me), but hey it seems to work ;-)
So thanks again.
[ NB I've only tested it on Vista too, which I probably should also have
mentioned. ]
--
Jon- Hide quoted text -
- Show quoted text -
Tried this on XP SP2 but it seems that the first 2 characters of the
Data are chopped off for some reason.
Jon
2007-11-20 00:46:39 UTC
Permalink
Post by Kuma
Tried this on XP SP2 but it seems that the first 2 characters of the
Data are chopped off for some reason.
True, there does seem to be the odd byte missing.

Possibly some of the formulae in the ReadBytes(...) portions of the lines
with

$Data = .....

need to be reviewed (??).
--
Jon
Robbie Foust
2007-11-20 16:42:29 UTC
Permalink
Ok, I fixed a few bugs and changed some things. (download the script
again at the same link). I found the off-by-2-bytes bug (I was
comparing words, not bytes. oops). Also I'm now scraping the output
of "route print 0*" to get the local IP address associated with the
default route. The problem with using "mswinsock.winsock" is that it
isn't installed by default, otherwise I'd use it. :-)

Jon, I think the problem you're seeing with promiscuous mode is that
your driver probably doesn't support it, so when you use
RCVALL_IPLEVEL, you're only receiving traffic that is destined for
your machine. Promiscuous mode receives all traffic, even if it isn't
destined for your system. The only way around that is to use a
driver shim, so for that you might as well download winpcap. ;-) Or
just settle for receiving only traffic destined for your system (which
is probably fine for what most of us use a packet capture program for
anyway).

I'll see if I can come up with a way to determine if a driver supports
that mode or not, and maybe fall back to the "iplevel" option.

Hope this helps,

- Robbie
Jon
2007-11-20 18:20:02 UTC
Permalink
New script is working well.

Noticed that you've modified the IP Header and TCP Header sections, and in
the process resolved the 'missing data' issue that Kuma referred to. Also a
clever way of getting the local ip address.

Yes, I'm not overly bothered (if at all) about the promiscuous mode aspect
for my Internet connection. As you say, I pretty much exclusively use a
packet sniffer to keep tabs on what traffic is flowing to / from my machine
(for which ip level capture seems perfectly adequate), and for peeking
inside TCP packets to see what they contain. This script is now working well
with respect to both uses.

You've also taught me a lot about how all this works via your well-commented
script and this thread, and some of the articles which all this has
encouraged me to read - which I suspect we all appreciate far more than just
downloading some 'closed source' tool and learning nothing from it.

So keep up the good work!
--
Jon
Post by Robbie Foust
Ok, I fixed a few bugs and changed some things. (download the script
again at the same link). I found the off-by-2-bytes bug (I was
comparing words, not bytes. oops). Also I'm now scraping the output
of "route print 0*" to get the local IP address associated with the
default route. The problem with using "mswinsock.winsock" is that it
isn't installed by default, otherwise I'd use it. :-)
Jon, I think the problem you're seeing with promiscuous mode is that
your driver probably doesn't support it, so when you use
RCVALL_IPLEVEL, you're only receiving traffic that is destined for
your machine. Promiscuous mode receives all traffic, even if it isn't
destined for your system. The only way around that is to use a
driver shim, so for that you might as well download winpcap. ;-) Or
just settle for receiving only traffic destined for your system (which
is probably fine for what most of us use a packet capture program for
anyway).
I'll see if I can come up with a way to determine if a driver supports
that mode or not, and maybe fall back to the "iplevel" option.
Hope this helps,
- Robbie
Loading...