Monday, March 8, 2010

Which services are communicating on Vista?

What I want to know is which services are engaging in network communication. How they are changing over time. Network Monitor 3.3 tracks data packets back to executables but has an "unknown" category that carries a lot of data.  TCPView gives a dynamic list of Process, Protocol, Address  and Port in real-time. In the batch files below I pipe uniq tcpvcon output of process IDs  to tasklist /SVC and have FC detect what has changes.  Tasklist /SVC is slow however.

@echo off
@for /f %%i in ('tcpvcon -a -c ^| gawk -F"," '{print $3}' ^| sort ^| uniq') do @(tasklist /NH /FO CSV /SVC /FI "PID eq %%i") >&1>> temp1
@for /f %%i in ('tcpvcon -a -c ^| gawk -F"," '{print $3}' ^| sort ^| uniq') do @(tasklist /NH /FO CSV /SVC /FI "PID eq %%i") >&1>> temp2
fc temp1 temp2 > &1>> diff


@echo off
:top
del temp1
del temp2
@for /f %%i in ('tcpvcon -a -c ^| gawk -F"," '{print $3}' ^| sort ^| uniq') do @(tasklist /NH /FO CSV /SVC /FI "PID eq %%i") >&1>> temp1
@for /f %%i in ('tcpvcon -a -c ^| gawk -F"," '{print $3}' ^| sort ^| uniq') do @(tasklist /NH /FO CSV /SVC /FI "PID eq %%i") >&1>> temp2
fc temp1 temp2
goto top

Some relatively simple Powershell also helps detect which services are communicating:


$global:svchost = get-wmiObject win32_process -filter "name='svchost.exe'"
$global:win32_handle = $svchost | foreach { gwmi -query "Select * from win32_service where processID = $($_.handle)" }
$global:Sort_handle = $win32_handle | sort processID, Name
$global:Sort_svchost = $svchost | sort processID
$Sort_handle | format-table processID,name,state, startmode,Started,AcceptStop,Description -AutoSize
$Sort_svchost | format-table ProcessID,ThreadCount,HandleCount,WS,VM,KernelModeTime,ReadOperationCount,ReadTransferCount,OtherTransferCount -Autosize

Sunday, June 14, 2009

Enumerating running modules

Some code worth publishing (from some work I am doing over at RMF Network Security on Conficker, worm detection, etc: ):

$Global:ps = ps
$ps_count = $ps.count
write "Process Count = $ps_count"
$Global:all_modules = 0..$ps_count |%{$ps[$_].Modules} | Select Size,ModuleName,FileName,FileVersion
$allmod_count = $all_modules.count
write "All instances of loaded modules = $allmod_count"
$Global:unique_all_modules = $all_modules | Select -property ModuleName | Sort -Unique -property ModuleName
$uniqmod_count = $unique_all_modules.count
write "All uniq module names = $uniqmod_count"
$Global:all_modules_memory = $all_modules | Select -property ModuleName,Size | Sort -property Size
$Global:MO_all_mod_mem = $all_modules_memory | measure-object -property Size -sum
$Global:CountModMem = $MO_all_mod_mem.count
$Global:SumModMem = $MO_all_mod_mem.sum
$SumModMemMB = ( ( $SumModMem * 1000)/ 1GB)
write "Sum of $CountModMem modules memory size = $SumModMemMB GB"

Tuesday, April 14, 2009


Well, I thought this was pretty cool.  Blackberry Storm, Cygwin, Powershell v2CTP3,MidpSSH 1.7:






Wednesday, April 8, 2009

Gathering Network Statistics

# In PS CTP2v3, .NET access to IP statistics is non-existent. There are no static members 
# for the interface statistics yet, although there are non static members:

[System.Net.NetworkInformation.IcmpV4Statistics].getmembers() | %{$_.name}
[System.Net.NetworkInformation.IPGlobalStatistics].getmembers() | %{$_.name}

Wednesday, April 1, 2009

Working with netmon caps in Powershell

An update to this post 8:32 PM 8/7/2009:

I have no path to loading nmcap files into powershell now that logparser does not work with Netmon 3.3 file format. I added my comment to this feature request:

https://connect.microsoft.com/feedback/ViewFeedback.aspx?FeedbackID=265564&SiteID=216

"The jump between 3.2 and 3.3 file formats/APIs broke logparser2.2 interface to netmon files which was extraordinarily useful since logparser would convert file formats, sql-lize queries, create charts and datagrids, etc. Examples are below. Granted this is probably a logparser (e.g. unsupported ware) defect, however...The real defect is here is that there is no path to convert Netmon 3.3 captures files to CSV.C:\Program Files (x86)\Log Parser 2.2>logparser -headers OFF -stats NO -i:NETMON -o:CSV "SELECT DateTime,SrcMAC,SrcPort,DstMAC,DstPort,WindowSize FROM32.cap"2009-01-13 11:37:53,00095B00F3DA,80,0013021A607B,2004,328902009-01-13 11:37:53,0013021A607B,2006,00095B00F3DA,80,163842009-01-13 11:37:54,00095B00F3DA,80,0013021A607B,2006,58402009-01-13 11:37:54,0013021A607B,2006,00095B00F3DA,80,175202009-01-13 11:37:54,0013021A607B,2006,00095B00F3DA,80,17520.....C:\Program Files (x86)\Log Parser 2.2>logparser -headers OFF -i:NETMON -o:CSV "SELECT DateTime,SrcMAC,SrcPort,DstMAC,DstPort,WindowSize FROM 33.cap"Statistics:-----------Elements processed: 0Elements output: 0Execution time: 0.01 seconds"

7:10 AM 4/2/2009: An update to this post


Once you have a capture in the form of an object, you can do interesting work with it in powershell:


$DstSrcPort_8NET = $capture where-object {($_.SrcIP -match "^8\." ) -or ($_.DstIP -match "^8\.")}
$DstSrcPort_8NET Sort DateTime -unique ft more
$DstSrcPort_8NET group-object DstPort Sort -descending Count
$DstSrcPort_8NET measure-object -average -minimum -maximum -property WindowSize
$a = $DstSrcPort_8NET Sort SrcIP -unique
$a %{[System.Net.DNS]::Resolve($_.SrcIP)}



In progress...concating collections of nmcap files and searching them for specific SrcIP and DstIp with Powershell and LogParser. This code is working now, but still "to be continued"...

function Search-IP($IP_String)
{ #start function
(ls -name *.cap)
foreach-object -begin {$file =[DateTime]::now.ToFileTime().ToString()} `
-process {
$filename = $_ ;
$temp = logparser -headers OFF -stats NO -i:NETMON -o:CSV "SELECT DateTime,SrcIP,SrcPort,DstIP,DstPort,WindowSize FROM $filename" ;
out-file -inputobject $temp -append -noclobber -filepath $file} `
-end {
$header = "DateTime","SrcIP","SrcPort","DstIP","DstPort","WindowSize" ;
$Global:capture = Import-csv $file -header $header ;
$Global:MatchIPObject = $capture where-object {$_ -match $IP_String} ;
$Global:MatchIPString = Select-String $IP_String $file -AllMatches}
} #end function

:$MatchIPObject[0..10] ft

DateTime SrcIP SrcPort DstIP DstPort WindowSize
-------- ----- ------- ----- ------- ----------
2007-07-16 13:59:52 68.26.116.175 1169 66.133.124.56 443 16384
2007-07-16 13:59:52 66.133.124.56 443 68.26.116.175 1169 4140
2007-07-16 13:59:52 68.26.116.175 1169 66.133.124.56 443 16560
2007-07-16 13:59:52 68.26.116.175 1169 66.133.124.56 443 16560
2007-07-16 13:59:52 66.133.124.56 443 68.26.116.175 1169 4140
2007-07-16 13:59:52 68.26.116.175 1169 66.133.124.56 443 15753
2007-07-16 13:59:52 68.26.116.175 1169 66.133.124.56 443 15753
2007-07-16 13:59:52 68.26.116.175 1170 66.133.124.56 443 16384
2007-07-16 13:59:52 66.133.124.56 443 68.26.116.175 1169 4229
2007-07-16 13:59:52 66.133.124.56 443 68.26.116.175 1169 4229
2007-07-16 13:59:52 68.26.116.175 1169 66.133.124.56 443 15753


:$MatchIPString[0..10]

128830930248593750:7:2007-07-16 13:59:52,68.26.116.175,1169,66.133.124.56,443,16384
128830930248593750:9:2007-07-16 13:59:52,66.133.124.56,443,68.26.116.175,1169,4140
128830930248593750:10:2007-07-16 13:59:52,68.26.116.175,1169,66.133.124.56,443,16560
128830930248593750:11:2007-07-16 13:59:52,68.26.116.175,1169,66.133.124.56,443,16560
128830930248593750:12:2007-07-16 13:59:52,66.133.124.56,443,68.26.116.175,1169,4140
128830930248593750:13:2007-07-16 13:59:52,68.26.116.175,1169,66.133.124.56,443,15753
128830930248593750:14:2007-07-16 13:59:52,68.26.116.175,1169,66.133.124.56,443,15753
128830930248593750:15:2007-07-16 13:59:52,68.26.116.175,1170,66.133.124.56,443,16384
128830930248593750:16:2007-07-16 13:59:52,66.133.124.56,443,68.26.116.175,1169,4229
128830930248593750:17:2007-07-16 13:59:52,66.133.124.56,443,68.26.116.175,1169,4229
128830930248593750:18:2007-07-16 13:59:52,68.26.116.175,1169,66.133.124.56,443,15753


:$MatchIPObject[0..10] gm


TypeName: System.Management.Automation.PSCustomObject

Name MemberType Definition
---- ---------- ----------
Equals Method System.Boolean Equals(Object obj)
GetHashCode Method System.Int32 GetHashCode()
GetType Method System.Type GetType()
ToString Method System.String ToString()
DateTime NoteProperty System.String DateTime=2007-07-16 13:59:52
DstIP NoteProperty System.String DstIP=66.133.124.56
DstPort NoteProperty System.String DstPort=443
SrcIP NoteProperty System.String SrcIP=68.26.116.175
SrcPort NoteProperty System.String SrcPort=1169
WindowSize NoteProperty System.String WindowSize=16384


:$MatchIPString[0..10] gm


TypeName: Microsoft.PowerShell.Commands.MatchInfo

Name MemberType Definition
---- ---------- ----------
Equals Method System.Boolean Equals(Object obj)
GetHashCode Method System.Int32 GetHashCode()
GetType Method System.Type GetType()
ToString Method System.String ToString(), System.String ToString(String directory)
Context Property Microsoft.PowerShell.Commands.MatchInfoContext Context {get;set;}
Filename Property System.String Filename {get;}
IgnoreCase Property System.Boolean IgnoreCase {get;set;}
Line Property System.String Line {get;set;}
LineNumber Property System.Int32 LineNumber {get;set;}
Matches Property System.Text.RegularExpressions.Match[] Matches {get;set;}
Path Property System.String Path {get;set;}
Pattern Property System.String Pattern {get;set;}

Monday, March 30, 2009

I experimented with a powershell script  in the start folder. I had some issues. I am still not sure how to get consecuitive commands that share the same environment running.  So I simply appended my function name after defining it in my script.  I did not use the "-file" option but invoked the script like a command from a cmd.exe file.  This cmd.exe file still requires me to type an Administrative password after startup. Not quite sure how to get around that... 

:: Powershell startup to pump established connections to the Event Log 
echo Powershell -windowStyle hidden -noexit -noprofile "& D:\PS1\netstat_Established_log_startup.ps1" >TCPListen.cmd
runas /profile /env /user:Administrator TCPListen.cmd

Tuesday, March 24, 2009

Metadata

Jason Shirk's excellent post on meta-programming inspired this function and alias I have added to my profile to help me get a handle on the use and format of paramaters in CTP2 v3 scripts. 

function Create-Metadata($args0) {
$args0 = new-object System.Management.Automation.CommandMetadata (get-command $args0)
[System.Management.Automation.ProxyCommand]::Create($args0) | out-file ProxyCommand.txt
more ProxyCommand.txt
}
Set-Alias cm Create-Metadata

Run as below:
CM("trace-command")


[CmdletBinding(DefaultParameterSetName='expressionSet')]
param(
    [Parameter(ValueFromPipeline=$true)]
    [System.Management.Automation.PSObject]
    ${InputObject},

    [Parameter(Mandatory=$true, Position=0)]
    [System.String[]]
    ${Name},

    [Parameter(Position=2)]
    [System.Management.Automation.PSTraceSourceOptions]
    ${Option},

    [Parameter(ParameterSetName='expressionSet', Mandatory=$true, Position=1)]
    [System.Management.Automation.ScriptBlock]
    ${Expression},

    [Parameter(ParameterSetName='commandSet', Mandatory=$true, Position=1)]
    [System.String]
    ${Command},

    [Parameter(ParameterSetName='commandSet', ValueFromRemainingArguments=$true)]
    [Alias('Args')]
    [System.Object[]]
    ${ArgumentList},

    [System.Diagnostics.TraceOptions]
    ${ListenerOption},

    [Alias('PSPath')]
    [System.String]
    ${FilePath},

  .....
Some notes on FileVersionInfo, finding Modules, loaded dlls:

(get-process -id $pid).modules | %{$_} | fl * | more

Size              : 152
Company           : Microsoft Corporation
FileVersion       : 6.1.6949.0 (fbl_srv_powershell_ctp(srvbld).081105-1651)
ProductVersion    : 6.1.6949.0
Description       : Windows PowerShell
Product           : Microsoft? Windows? Operating System
ModuleName        : PowerShell.exe
FileName          : C:\WINDOWS\system32\WindowsPowerShell\v1.0\PowerShell.exe
BaseAddress       : 579928064
ModuleMemorySize  : 155648
EntryPointAddress : 579954429
FileVersionInfo   : File:             C:\WINDOWS\system32\WindowsPowerShell\v1.0\PowerShell.exe
                    InternalName:     POWERSHELL
                    OriginalFilename: PowerShell.EXE
                    FileVersion:      6.1.6949.0 (fbl_srv_powershell_ctp(srvbld).081105-1651)
                    FileDescription:  Windows PowerShell
                    Product:          Microsoft? Windows? Operating System
                    ProductVersion:   6.1.6949.0
                    Debug:            False
                    Patched:          False
                    PreRelease:       False
                    PrivateBuild:     True
                    SpecialBuild:     False
                    Language:         English (United States)
....


A workable tlist substitute:
$a =foreach ($id in (get-process)) {write $id.Name,$id.Size,$id.modules}
$a | more

alg

   Size(K) ModuleName                                         FileName
   ------- ----------                                         --------
        52 alg.exe                                            C:\WINDOWS\System32\alg.exe
       700 ntdll.dll                                          C:\WINDOWS\system32\ntdll.dll
       984 kernel32.dll                                       C:\WINDOWS\system32\kernel32.dll
       352 msvcrt.dll                                         C:\WINDOWS\system32\msvcrt.dll
        68 ATL.DLL                                            C:\WINDOWS\System32\ATL.DLL
       580 USER32.dll                                         C:\WINDOWS\system32\USER32.dll
       292 GDI32.dll                                          C:\WINDOWS\system32\GDI32.dll
       620 ADVAPI32.dll                                       C:\WINDOWS\system32\ADVAPI32.dll
       584 RPCRT4.dll                                         C:\WINDOWS\system32\RPCRT4.dll
        68 Secur32.dll                                        C:\WINDOWS\system32\Secur32.dll
      1268 ole32.dll                                          C:\WINDOWS\system32\ole32.dll
       556 OLEAUT32.dll                                       C:\WINDOWS\system32\OLEAUT32.dll
        36 WSOCK32.dll                                        C:\WINDOWS\System32\WSOCK32.dll

.....



Monday, March 16, 2009

This will be worth some more investigation.  I can send a Powershell array of cmd.exe strings to the cmd.exe interpreter and pass cmd.exe a Powershell "here string" that will passthru a Powershell variable to the cmd.exe interpreter. Be interesting to next see if I can reverse the process.


# writes out time and date from cmd.exe
write "Time and Date from CMD.EXE:" 
$Global:command = 
"time /t",
"date /t"
out-file -inputobject $command -encoding ASCII -filepath $pwd\cmd.txt
Start-Process cmd.exe -argument /Q -nonewwindow -wait -redirectstandardinput $pwd\cmd.txt

Friday, March 13, 2009

Finding Time

FindingTimes in Powershell (and cmd.exe).  I have put the script FindingTimes.ps1 in my repository.  I am returning various results.  This script demonstrates different methods of finding System Time and Uptime on Windows with cmd.exe or Powershell.  There is a discrepancy in the method results between .NET and GWMI. I do not know what is causing this, I suspect the hibernate process or uptime.exe heartbeat function (from MS Reskit) is causing the descrepancy.


PS D:\PS1> .\FindingTime_001.ps1
Finding Current and Boot Times from Powershell: A Medley of Methods
System Times:
Time now using Get-Date:
03/16/2009 19:41:35


DisplayHint : DateTime
DateTime    : Monday, March 16, 2009 7:41:35 PM
Date        : 3/16/2009 12:00:00 AM
Day         : 16
DayOfWeek   : Monday
DayOfYear   : 75
Hour        : 19
Kind        : Local
Millisecond : 343
Minute      : 41
Month       : 3
Second      : 35
Ticks       : 633728292953437500
TimeOfDay   : 19:41:35.3437500
Year        : 2009



Time From .NET:
.NET Date Time Now is 03/16/2009 19:41:35
.NET UTC Date Time Now is 03/17/2009 02:41:35
.NET Time is Date Hours Minutes Seconds MS : 16 19 41 35 359
.NET UTC Time is Date Hours Minutes Seconds MS : 17 2 41 35 359
.
Time from WMI Win32_OperatingSystem LocalDateTime:
03/16/2009 19:41:35
.
Time and Date from CMD.EXE:
Microsoft Windows XP [Version 5.1.2600]
(C) Copyright 1985-2001 Microsoft Corp.

D:\PS1>07:41 PM

D:\PS1>Mon 03/16/2009

D:\PS1>.
System UpTimes:
Uptime for cmd.exe
Microsoft Windows XP [Version 5.1.2600]
(C) Copyright 1985-2001 Microsoft Corp.

D:\PS1>Running cmd.exe

D:\PS1>Current TimeStamp is 03.16.2009_19.41.35.59
Statistics since 3/14/2009 9:45 AM
.
Uptime From Microsoft Resource Kit: 'D:\uptime.exe:'
\\RMFMEDIA has been up for: 2 day(s), 9 hour(s), 57 minute(s), 26 second(s)
.
Uptimes from the System Event 6009 Log Query and (get-date): Elapsed from Last Boot Times
Last boot Date/Time -- LBTs from Current Time in Days.Hours.Minutes.Seconds
03/14/2009 09:44:52 -- 2.9.56.44
03/04/2009 14:25:00 -- 12.5.16.36
02/20/2009 01:24:35 -- 24.18.17.1
02/19/2009 20:47:39 -- 24.22.53.57
02/18/2009 11:10:45 -- 26.8.30.51
02/16/2009 10:24:21 -- 28.9.17.15
02/16/2009 10:10:47 -- 28.9.30.49
02/03/2009 11:33:24 -- 41.8.8.12
01/15/2009 22:40:17 -- 59.21.1.19
01/09/2009 09:52:51 -- 66.9.48.45
01/07/2009 17:39:39 -- 68.2.1.57
01/05/2009 18:30:06 -- 70.1.11.30
01/05/2009 11:01:59 -- 70.8.39.37
12/24/2008 11:20:21 -- 82.8.21.15
.
Uptime from Get-WmiObject -class Win32_PerfFormattedData_PerfOS_System
Number of Days = 2.41489583333333
Number of Hours = 57.9575
Number of Minutes = 3477.45
Number of Seconds 208647
.
Uptme from GWMI Win32_OperatingSystem -Namespace root\CIMV2 LastBootUpTime and (get-date)
Last Boot Time: 03/16/2009 03:33:43 Current Time: 03/16/2009 19:41:36
Uptimes from Last Boot in Days.Hours.Minutes.Seconds = 0.16.7.52
.
Uptime from Get-WmiObject -class Win32_OperatingSystem LastBootUpTime and LocalDateTime
Uptime is 0.16.7.52
.
Uptime from D:\cygwin\bin\uptime.exe (procps version 3.2.6)
 19:41:36 up 16:07,  1 user,  load average: 0.00, 0.00, 0.00
.

Friday, March 6, 2009

The last few days have been horrible for me.  There is a level of knowledge I am missing about .NET and Powershell that is preventing me from doing great new creative things. Fortunately, there are brilliant coders like Josh Einstein and others stumbling across similar issues. For example:http://groups.google.com/group/microsoft.public.windows.powershell/browse_thread/thread/40356985a4e3e015/9112f551260968f0?hl=en#9112f551260968f0

It's amazing how useful ad-hoc discussions about new features in CTPv3 are to many us. "Jaykul"Bennett posted one I am sure is being mined from all over the world:


Oh well, back to Holmes, Payette, Deshev, and others and see if I can figure out what I am doing. Perhaps some time spent just reading .NET  and C# books would be useful....hmmmm...

I've posted this:
"In learning Powershell, once you are over the humps of the pipeline, 
automatic variables, conditional loops, .NET, network admin tricks 
etc. (e.g. a "better cmd line"),  you are faced with absorbing the 
intent of the architects in creating and using functionality like: 

params for Functions 
scriptlets 
[cmdletbinding] 
Cmdlet architecture 

etc. and a subset of other dev skillsets like error handling, 
debugging that would make the difference for between someone who is 
rewriting his 10 line cmd scripts or someone who is creating 
significant functionality in Powershell scripts.  I think what I would 
like is book with a title like "Design Patterns for Powershell" that 
provides examples and discussion on how to best implement Powershell 
for performance, for re-usable design, when something more "lambda" 
than "imperative" makes sense and the converse.  Currently, there is a 
lot of research leg work to go through to come up with this "all by 
your lonesome".  Other pieces of this might be a Visio or VisStudio 
design template(s), advice on writing testable and easily debugged 
functions, PSIE extensions that provide for intellisense or design 
templates. It's true folks like Bennet, Lee, Snover, Payette, Holmes, 
and the Powershell team have some discussion and some examples  about 
this...but I find myself with many questions...and feeling a little 
confused.  Do I need to master "Design Patterns for C#" or understand 
Functional Language style vs. Imperative Language issues before I 
write elegant, correct, re-usable functions, and scriplets for 
Powershell?"



Monday, February 23, 2009

Teaching myself debugging...some random notes:

There are no locals or watch windows in the CTP2  v3 ISE. They are sorely needed.  However, there is a plethora of debugging facilities in Powershell. Today's post is about my morning exploration  of such facilities. I have a function List-TCPConnections that works fine with one argument but doesn't work with multiple pipeline values.  This param: [ValueFromPipeline] gives me a "load assembly" error message and I am not ready to debug that right now ;-) .  I have a cmd.exe test script to give myself connection states: for /l %i in (1000,100,10000) do wget %i.com.  I run through TCP Connection States like this: '0..11 | %{List-TCPConnections $_}'

Under such test, the function below works as expected, pumping out connection states, IP addresses to console and (classic) EventLog:
function global:List-TCPEstablished {do {List-TCPConnections 5} while (1)}

This  (pipeline function) does not work :
function global:List-TCPAllStates {do {0..11 | %{List-TCPConnections $_}} while (1)}  

Originally, I tried some simple 'print debug' type strategies with "get-variable" (gv) and  "out-gridview". But the compound variables do not Invoke() (for me)  in "out-gridview" so these strategies weren't helping. 

   (gv -s 0)| out-gridview ## scope for everything
   (gv -s 1)| out-gridview ## one scope up

   ## Just what the script gives subtracted from everything
    compare-object (gv -s script) (gv -s 0) | out-gridview

Along the same lines, I thought I would be more tricky and pump out  variable arrays I wanted to watch  as needed: 

    $local_out=
    "last_netblock",
    "netblock",
    "State" 

    $dbg = $local_out | %{gv ($_)}; $dbg | out-gridview

That still wasn't helpful for the above reasons. Below, the trace command dumps lots of information, but still doesn't help me with logic errors:

trace-command -name metadata,parameterbinding,cmdlet -option ExecutionFlow,data,errors {do {0..11 | %{List-TCPConnections $_};sleep -s 5} while (1)}-pshost

Using a script block at the start of my Begin{} function and calling it as needed  was most useful at this point.

## Debug Print Script Block
    $Global:locals_out=
    {
    $State
    $last_netblock
    write .
    $netblock
    }

 ## Debug
    write $Locals_out.Invoke()

to be continued...

Wednesday, February 18, 2009

Three of the four last posts have resulted in a considerable speed up of my Powershell learning curve. In my February 6th post , I created a (not so) simple script to log all new Established TCP Connections.  'Compare-Object' was very useful in finding the diff between one netblock and the last. In my February 12th post, I worked through how to send those Established TCP Connections to the (classic) Event Viewer.  I then spent quite a bit of time trying to build a script that iterated all TCPStates past the current TCP Connection diff in an attempt to send all TCP State Connections to the Event Log.  I spent a lot of time failing to create such an iteration. (Update February 25): Eventually, I did create a function(s) which will log select TCP Connection States. It is posted here: http://www.rmfdevelopment.com/PowerShell_Scripts/List-TCPConnections_Advanced.ps1
 There are a ton of issues for me to work out with Powershell involving .NET overloads, Functions Types, Iteration, Parameters....But the foreach-object can be used in a block to process an  array line by line. Very simple and straightforward:
       $global:c = compare-object -referenceobject $State_netblock -differenceobject $State_last_netblock
                    
       if ($c -eq $null){}
       elseif($c.SideIndicator -eq "<=" )
          {$C |
                foreach-object -process{                                    
                $LocalAddress = $_.InputObject.LocalEndPoint.Address
                $RemoteAddress = $_.InputObject.RemoteEndPoint.Address           
                $LocalPort = $_.InputObject.LocalEndPoint.Port
                $RemotePort = $_.InputObject.RemoteEndPoint.Port
                $TCP_State = $TCPState[$State]
                $name = [System.Net.DNS]::Resolve("$RemoteAddress")
                $name_canon = $name.hostname
                write "$TimeNow $RemoteAddress $name_canon : $RemotePort $TCP_State"
                $EventLog.Source = "$name_canon" 
                $EventLog.WriteEntry("$LocalAddress $TCP_State connection to $RemoteAddress($name_canon) from Local Port: $LocalPort to Remote Port: $RemotePort",$infoevent,$RemotePort,$State) 

                } 
           }


Update on event log queries for the event log generated by the above script:

Source
$Source_8NetUnique = get-eventlog -log EstablishedTCPConnections  | ?{$_.Source -match "^8\."} | sort-object -property Source -unique
$SourceNetUnique = get-eventlog -log EstablishedTCPConnections  | ?{$_.Source -match "^*"} | sort-object -property Source -unique
$SourceNetUniqueGroupBy = get-eventlog -log EstablishedTCPConnections  | ?{$_.Source -match "^*"} | group-object -property Source | Sort-object -property count -descending
Function Get-NetName ($CountNetName) { get-eventlog -log EstablishedTCPConnections  | ?{$_.Source -match "^$CountNetName"} |  group-object -property Source | Sort-object -property count -descending}
foreach($i in (gc alpha.txt)){get-netname $i}
Port
$Port80 = get-eventlog -log EstablishedTCPConnections  | ?{$_.EventID -match "^80"}|  sort-object -property TimeGenerated -descending
$EventIDNetUnique = get-eventlog -log EstablishedTCPConnections  | ?{$_.EventID -match "^*"} | sort-object -property EventID -unique
$EventIDNetUniqueGroupBy = get-eventlog -log EstablishedTCPConnections  | ?{$_.EventID -match "^*"} | group-object -property EventID | Sort-object -property count -descending
Function Get-PortType ($CountPortType) { get-eventlog -log EstablishedTCPConnections  | ?{$_.EventID -match "^$CountPortType"} |  group-object -property EventID | Sort-object -property count -descending}

$Source = get-eventlog -log EstablishedTCPConnections | group-object -property Source | sort-object -property Count -descending
$Port = get-eventlog -log EstablishedTCPConnections | group-object -property EventID  | sort-object -property Count -descending

$UniqSource = get-eventlog -log EstablishedTCPConnections |  sort-object -property Source -descending -unique 
$UniqPort = get-eventlog -log EstablishedTCPConnections |  sort-object -property EventID -descending -unique 

$UniqSource = get-eventlog -log EstablishedTCPConnections | group-object -property Source | sort-object -property Count -descending
$UniqSource | Select Count,Name | cvhtml > UniqSource.html

$a | %{[System.Net.DNS]::Resolve($_.Source)}
$a | %{whois ($_.Source)}           

Thursday, February 12, 2009

This function pushes off the stack every new Established TCP connection as so:

PS >List-EstablishedTCP
209.62.20.43 ev1s-209-62-20-43.theplanet.com : 80
72.30.190.105 rc10.ysm.vip.ac2.yahoo.com : 80
165.160.9.37 165.160.9.37 : 80
66.235.133.3 dc2-3.112.2o7.net : 80
75.101.151.37 ec2-75-101-151-37.compute-1.amazonaws.com : 80
8.12.226.77 8.12.226.77 : 80
96.17.232.242 a96-17-232-242.deploy.akamaitechnologies.com : 80

It also send a message to the (classic) Event Log named "EstablishedTCPConnections" as shown here.  One PoSh blog was very helpful with this: http://winpowershell.blogspot.com/2006/07/writing-windows-events-using.html

function Global:EstablishedTCP 
{ ## start function

    $a = [System.Net.NetworkInformation.IPGlobalProperties]::GetIPGlobalProperties()
    $b = $a.GetActiveTcpConnections() | where{$_.State -eq "Established" }
        
    if ($b -ne $null -and $last_b -ne $null) 
    {
    $c = compare-object $b $last_b;
    }
    
    if ($c.SideIndicator -eq "<=" )
        {        
        $LocalAddress = $c.InputObject.LocalEndPoint.Address
        $RemoteAddress = $c.InputObject.RemoteEndPoint.Address           
        $LocalPort = $c.InputObject.LocalEndPoint.Port
        $RemotePort = $c.InputObject.RemoteEndPoint.Port
        
        $name = [System.Net.DNS]::Resolve("$RemoteAddress")
        $name_canon = $name.hostname
        
        write "$RemoteAddress $name_canon : $RemotePort"
        
        $EventLog = new-object System.Diagnostics.EventLog("EstablishedTCPConnections") 
        $EventLog.Source = "$name_canon" 
        $infoevent = [System.Diagnostics.EventLogEntryType]::Information 
        $EventLog.WriteEntry("$LocalAddress established connection to $RemoteAddress ($name_canon) from Local Port: $LocalPort to Remote Port: $RemotePort",$infoevent,$RemotePort,01) 
        }

start-sleep -m 100
$global:last_b = $b
  
} ## end function Established

function global:List-EstablishedTCP {do {EstablishedTCP} while (1)}

Sunday, February 8, 2009

This is a weird peice of code inspired by some syntax I found in Hristo Deshev's interesting book: "Pro Windows Powershell". Hristo talks about converting IDictionary objects to Hash Tables.  'PS' or 'get-process' uses the PID as the hash code for the process object. This allows a construct that produces a hash table with explict PIDs as hash keys. It is too late to figure out if this side-effect would have any value to anyone.

$script_block_ID = {ps | %{$_.ID} | Sort-object }
$dict = new-object Collections.Specialized.OrderedDictionary
$script_block_ID.Invoke() | %{$dict[(ps -id $_ | Select Name)] = $_.GetHashCode()}
write `r`n `$dict:
$dict 
$hash = [hashtable]$dict
write `r`n `$hash:
$hash 

[$hash:]
@{Name=cmd}                    1364                                            
@{Name=alg}                    864                                             
@{Name=explorer}               3212                                            
@{Name=gvim}                   1852                                            
@{Name=wmiprvse}               1332                                            
@{Name=VCSExpress}             3980                                            
@{Name=wscntfy}                352                                             
@{Name=chrome}                 2724                                            
@{Name=svchost}                1536 
....      

Friday, February 6, 2009

Enumerating TCP Connections

What I was looking for is a simple script to capture all new ("Established") connections.  This could use some improve since my code has some side-effects.  'Compare-object' subtracts the diff between two arrays: the reference set and the difference set. To run this I type this at a PS prompt:
  • function Est_do {do {Established} while (1)}
  • Est_do | out-file $pwd\Established.txt

function global:Established 
{
    Begin
    {
    $a = [System.Net.NetworkInformation.IPGlobalProperties]::GetIPGlobalProperties()
    }
    Process
    {
    if ($b -ne $null) {$last_b = $b}
    $b = $a.GetActiveTcpConnections()   | where{$_.State -eq "Established" }  
    if ($last_b -ne $null) 
        {$c = compare-object $last_b $b;
            if ($c.SideIndicator -eq "=>" ) {write $c.InputObject | ft -HideTableHeaders}       
        }
   $global:last_b = $b
      }
    End 
    {
    start-sleep -m 250
    }  
}


[Established.txt] :

Established 192.168.0.8:3419 209.85.147.83:80
Established 192.168.0.8:3420 74.125.19.191:80
Established 192.168.0.8:3422 74.125.19.191:80
...