Monday, April 23, 2012

On using BinarySearch and IComparer in Powershell:Part I

The Binary Search algorithm is exposed in Powershell v3.0 . It is not clear to me how to implement System.Collections.IComparer  as of yet. However, even without IComparer, Powershell's BinarySearch  has some usefulness.  Here are the overloads: 

 [Array]::BinarySearch.OverloadDefinitions
static int BinarySearch(array array, System.Object value)
static int BinarySearch(array array, int index, int length, System.Object value)
static int BinarySearch(array array, System.Object value, System.Collections.IComparer comparer)
static int BinarySearch(array array, int index, int length, System.Object value, System.Collections.IComparer comparer)
static int BinarySearch[T](T[] array, T value)
static int BinarySearch[T](T[] array, T value, System.Collections.Generic.IComparer[T] comparer)
static int BinarySearch[T](T[] array, int index, int length, T value)
static int BinarySearch[T](T[] array, int index, int length, T value, System.Collections.Generic.IComparer[T] comparer)

Friday, March 30, 2012

Code Scratch: Querying the Registry with Powershell (Part I of many to come)

Below, some nearly incomprehensible code scratch on querying registry values and subkeys with  gci and gp. Querying the registry with Powershell will deserve more narrative than this in the future:

HKLM:\system\CurrentControlSet\Services

$a=Get-ChildItem hklm:\system\CurrentControlSet\Services
$b=Get-ChildItem hklm:\system\CurrentControlSet\Services | ForEach-Object {Get-ItemProperty $_.pspath}
$b| export-csv C:\ps1\CCS_gp.csv
$a.count
$b.count

Friday, February 24, 2012

opens all profile locations


$a=(($profile | get-member -type noteproperty | % {$_.Definition}) -split("="))[1,3,5,7]
foreach ($i in $a) {notepad $i}

Thursday, January 5, 2012

Two methods to query psdrives

Both the methods below will query remote and local drives of all types:



Wednesday, January 4, 2012

Parse TCP and UDP ports from services file



# Parses TCP and UDP ports from services file on Windows 7

$a=gc C:\Windows\System32\drivers\etc\services
$tcp=$a | sls tcp
$udp=$a | sls udp

[array[]]$tcp=0..(($tcp.count) -1) | % { (($tcp.GetValue($_) -split("/"))[0])}
[array[]]$udp=0..(($udp.count) -1) | % { (($udp.GetValue($_) -split("/"))[0])}

[array[]]$tcp_service_ports=0..(($tcp.count) -1) | % { (($tcp.GetValue($_) -split(" "))[-1])}
[array[]]$udp_service_ports=0..(($udp.count) -1) | % { (($udp.GetValue($_) -split(" "))[-1])}

Count the number of binaries in your path

Powershell 3.0 CTP2

Count the number of binaries in your path:

([System.Environment]::GetEnvironmentVariables().Path -split(";") |% { ls $_ *.exe}).count

Saturday, September 3, 2011

Compound variable assignment as [array[]] based storage

Below is a function I have written to demonstrate a function which recursively checks ownership and access for files modified within a given time span. What I call to your attention is the ability to use the assignment operator ('+=') to store data recursively as highlighted in salmon.  This is mentioned in 'about_assignment_operators' in the help for Powershell V2:

When the value of the variable is an array, the += operator appends the
 values on the right side of the operator to the array. Unless the array is
 explicitly typed by casting, you can append any type of value to the array..."
In the second part of the script below, I pump the results of a foreach loop into an explicitly typed compound assignment variable ("$RecurseList"):

Wednesday, August 24, 2011

Storing 'Get-counter' data

You can do this:

((get-counter -counter '\\rmfvpc\TCPv4\Connections Established').countersamples) | % {$_.CookedValue}


and this:

(get-counter -counter '\\rmfvpc\TCPv4\Connections Established').Readings | findstr ^[0-9]

and this:

(get-counter -counter '\\rmfvpc\TCPv4\Connections Established' -continuous -sampleinterval 2)

but you can't do this:

Monday, August 22, 2011

Some addendum on modules

If you add modules like  PSUserTools from Microsoft you receive some enhanced functionality. You also receive some well conceived script.  After you have imported your modules ('import-module'), you can use a function like that below to list all the exported commands:


function Global:get-module_exports {

[CmdletBinding()]
Param(
[Parameter(Mandatory=$true)]
$ModName
          )
$commands=(get-module $ModName).ExportedCommands
[Array[]]$list=(($commands).Values) | %{$_.Name} | Sort
$list
}

Friday, May 6, 2011

$$ Recursion?

After reading Lee Holmes $$ blog post, I realized the $$ command has some recursive properties.
You can assign a function to the $$ variable and then init that function as follows:



Function Repeat-History
{
$$='function gh {get-history}'
Invoke-History $$
gh
}

Wednesday, February 9, 2011

Displaying IP addresses with Windows Powershell

How many IP Addresses on a Windows 7 system?

Here are two different Powershell commands that produce a list of IPv4 and IPv6 addresses on the same Windows 7 workstation. One parses 'ipconfig' and validates five addresses through  '[System.Net.IPaddress]'. The other uses 'gwmi' and the format of the addresses it produces will not similarly validate. Aside from the formatting of the object produced, I cannot understand why they will not validate.  It appears here I am extracting IPv6 anycast and broadcast addresses with 'ipconfig' that 'gwmi' is not giving me.

$IPAddress_ipconfig=(ipconfig | Select-string Address) -split ": " | Select-string -notmatch ". ."
foreach ($IP in $IPAddress_ipconfig) {([System.Net.IPaddress]::Parse("$IP")).IPAddressToString}

fe80::6172:6ecf:2d05:b0ae%12
192.168.0.11
fe80::cddc:ceef:b717:a5ac%11
2001:0:4137:9e76:30c3:129:3f57:fff4
fe80::30c3:129:3f57:fff4%17

(Get-WmiObject Win32_NetworkAdapterConfiguration | ? {$_.IPAddress} | Select IPaddress | fc -expand CoreOnly | findstr [0-9])

fe80::cddc:ceef:b717:a5ac
192.168.0.11
fe80::6172:6ecf:2d05:b0ae

Saturday, January 8, 2011

ping multiple subnets

# 'ping-multiple_subnets.ps1
# All Rights Reserved Ryan M. Ferris r.10:34 PM 1/7/2011
# Powershell V2 functions to ping multiple-subnets
# Consists of three functions: (ping-subnet, ping-ip , ping-multi)
# ping-subnet : .NET $ping.send - a single (simple) eight byte ICMP packet
# ping-ip : WMI 'test-connection' - a single (wmi info) eight byte ICMP packet
# ping-multi : wrapper function 
    # first create multiple Class C ranges: e.g.: 
    # $IPRange = 0..5 | %{"192.168.$_"}
    # use 'ping-multi' to discover them: e.g.:
    # $IPRange | % {ping-multi $_}
# The .NET $ping.send is much faster than WMI although 'test-connection' returns more
# information and can be configured to do authentication and impersonation
# Essentially, 'ping-subnet' does discovery that it pumps to 'ping-ip' which 
# creates csv files named per subnet per pass.

function global:Ping-Subnet
{
   [CmdletBinding()]
   Param(
       [Parameter(Mandatory=$true,ValueFromPipeline=$true)]
       [string]$Network,
       [array] $subnet=@(0..254),
       [int32] $buffersize=8,
       [Int32] $timeout=10,
       [Int32] $TTL=128,
       [bool]  $fragment=$false,
       [string]$ErrorActionPreference="silentlycontinue"
          )
$ping = new-object System.Net.NetworkInformation.Ping
$pingoptions = new-object System.Net.NetworkInformation.PingOptions
$pingoptions.ttl=$TTL
$pingoptions.dontfragment=$fragment
$Global:SNIPs=( $subnet | % -process  {$Ping.Send("$Network.$_", $timeout, $buffersize, $PingOptions)} | 
                where {$_.Status -eq "Success"})
$Global:IPs= $SNIPs | % {$_.Address.IPAddressToString}
}

function global:Ping-ip 
{
   [CmdletBinding()]
   Param(
       [Parameter(Mandatory=$true,ValueFromPipeline=$true)]
       [string]$computername,
       [int32] $buffersize=8,
       [int32] $count=1,
       [Int32] $TimeToLive=128,
       [Int32] $Delay=1,
       [string] $ErrorActionPreference="silentlycontinue"
          )

        $global:result= Test-connection    -computername $computername `
                        -buffersize $buffersize `
                        -count $count `
                        -TimeToLive $TimeToLive `
                        -Delay $Delay
        $global:icmp_out  = New-Object PSObject -Property @{
            IPv4          = $result.IPv4Address.IPAddressToString
            IPv6          = $result.IPv6Address.IPAddressToString
            BytesSent     = $result.BufferSize
            BytesReturned = $result.ReplySize
            ResponseTime  = $result.ResponseTime
            ReplyInc      = $result.ReplyInconsistency
      } | Select-Object IPv4,IPv6,BytesSent,BytesReturned,Responsetime,ReplyInc
    
if ($icmp_out -ne $null)
    {$ICMP_out | ConvertTo-Csv -NoTypeInformation | out-file -width 120 -append -NoClobber (write "$3OCT.csv")}
}
function ping-multi
{
Param(
       [Parameter(Mandatory=$true,ValueFromPipeline=$true)]
       [string] $Global:3OCT
       )
$3OCT | % {ping-subnet $_}
$IPs  | % {ping-ip $_}
}

Tuesday, January 4, 2011

Using Test-Connection

'Test-Connection' is Powershell V2's GWMI-based icmp test cmdlet that returns considerable amounts of information in object format.  'Test-Connection' also has the ability to authenticate (at various levels) to the computer whose ICMP responses it is testing, but I do not discuss that in this post. 'Test-Connection' can return a number of errors, which I found difficult to trap, throw, or try-catch-finally.  So, like some others (1,2), I punted on error-trapping with:
 [string] $ErrorActionPreference="silentlycontinue"  (Yea, I know...what a wimp...) 
Although, 'Test-Connection' is slower than System.Net.NetworkInformation.Ping will probably ever be, it does return considerable amounts of useful information. Below is the function 'Ping-IP' with the returned object and some statistical results from 'measure-object'. I've created a hash table and renamed six of the properties.  Notice how I can use 'Test-Connection' to check for IPv4 and IPv6 connections simultaneously (if you have an existing IPv6 interface).

Tuesday, December 21, 2010

Powershell log time-stamping

The function 'logtime'  below will work as a logging function in scripts


$FileTime=[DateTime]::Now.ToFileTime()

function logtime{
$date = [DateTime]::Now.Day
$hour = [DateTime]::Now.TimeOfDay.Hours
$minutes = [DateTime]::Now.TimeOfDay.Minutes
$seconds = [DateTime]::Now.TimeOfDay.Seconds
$ms = [DateTime]::Now.TimeOfDay.Milliseconds

[object]$logtime = New-Object PSObject -Property @{
date=$date
hour=$hour
minutes=$minutes
seconds=$seconds
ms=$ms
}
write $logtime | ft -HideTableHeaders -AutoSize -Property date,hour,minutes,seconds,ms | out-file -append -noclobber $PWD\$FileTime

}


[output]
PS C:\Users\rferrisx\Documents> gc 129374235* | more

  21    8      45      43 821
  21    8      51      12 604
  21    8      51      12 616
  21    8      51      12 656
  21    8      51      12 662




Wednesday, December 8, 2010

System.Net.NetworkInformation.Ping

Here are some Powershell ping notes from System.Net.NetworkInformation.Ping.  Powershell v 2.0 provides for the  gwmi  based Win32_PingStatus  in the 'Test-Connection' cmdlet . 'Test-connection'  provides a wealth of information.  However this post simply examines how to use:
  • System.Net.NetworkInformation.Ping
  • System.Net.NetworkInformation.PingOptions
Below is the common code needed for all three examples. This code sets up $ping and $pingoptions:

#Set up the ping options
$ping = new-object System.Net.NetworkInformation.Ping
$pingoptions = new-object System.Net.NetworkInformation.PingOptions
$pingoptions.ttl=255
$pingoptions.dontfragment=$false
# Here is the overload
#  From $ping.send.overloaddefinitions  use: System.Net.NetworkInformation.PingReply Send(string hostNameOrAddress, int timeout, byte[] buffer, System.Net.NetworkInformation.PingOptions options)

#now ping a subnet with one line of code
(1..254 | % -process  {$Ping.Send("192.168.0.$_", 10, 64, $PingOptions)})
# or (stop output) or redirect to a variable:
$a=(1..254 | % -process  {$Ping.Send("192.168.0.$_", 10, 64, $PingOptions)})

This gives us something interesting like this:


PS C:\ps1> $a | where {$_.Status -eq "Success"} | ft * -auto


 Status Address       RoundtripTime Options                                   Buffer
 ------ -------       ------------- -------                                   ------
Success 192.168.0.1               2 System.Net.NetworkInformation.PingOptions {64}
Success 192.168.0.6               1 System.Net.NetworkInformation.PingOptions {64}
Success 192.168.0.11              0 System.Net.NetworkInformation.PingOptions {64}
Success 192.168.0.13              0 System.Net.NetworkInformation.PingOptions {64}


If you functionalize/filterize the output :
function pingsn {1..254 | % -process  {$Ping.Send("192.168.0.$_", 10, 64, $PingOptions)}}
filter success {if ($_.status -eq "Success") {($_.Address.IPAddressToString)+" "+($_.roundtriptime)}}
you get a similar output:
pingsn | success

192.168.0.1 1
192.168.0.6 1
192.168.0.9 0
192.168.0.11 1

We can also ping and array of names (as below) and retrieve similar information if we pipe the output to a variable. Or we can do something more CSV like:

#ping a multiple names
$DNS_array="google.com", "googel.com", "googley.com"
($DNS_array | % -process  {$Ping.Send("$_", 10, 64, $PingOptions)})

Status        : Success
Address       : 72.14.213.99
RoundtripTime : 29
Options       : System.Net.NetworkInformation.PingOptions
Buffer        : {64, 0, 0, 0...}


Status        : Success
Address       : 74.125.224.17
RoundtripTime : 38
Options       : System.Net.NetworkInformation.PingOptions
Buffer        : {64}


Status        : Success
Address       : 74.117.221.11
RoundtripTime : 96
Options       : System.Net.NetworkInformation.PingOptions
Buffer        : {64}


($DNS_array | % -process  {$Ping.Send("$_", 10, 64, $PingOptions)}) | 
% {$_.Address.IPAddressToString +","+  $_.Status +","+ $_.RoundTripTime}


72.14.213.99,Success,25
74.125.224.17,Success,38
74.117.221.11,Success,98

Something more clever to ping multiple subnets is needed. The code below isn't very fast. The use of a filter might speed it up. However, you can make it faster by specifying exactly the hosts you want in $Host_array.

#ping multiple subnets
[array]$Host_array=1..20
$Subnet_array="192.168.0","192.168.1","192.168.2"
$count=$Subnet_array.count
$i=0
do
{
$global:out = $host_array | % -process {$Ping.Send($Subnet_array[$i]+"."+$_ , 1, 64, $PingOptions)}
$out | % {if ($_.Address) {$_.Address.IPAddressToString +","+  $_.Status +","+ $_.RoundTripTime}}
$i=$i+1
}
while ($i -lt $count)

Saturday, July 31, 2010

Looking at Process, Threads, Modules with Powershell 2.0

I have published "Looking at Processes, Modules, and Threads with Powershell 2.0 Part I".  The paper concerns itself with comparing Processes, Modules, and Threads and offers some discussion for comparing their changes over time. See also:
http://www.rmfdevelopment.com/PowerShell_Scripts/diff_PMT.ps1 

http://rmfdevelopment.com/PowerShell_Scripts/diff_PMT_adv.ps1

Wednesday, May 5, 2010

Which processes are communicating on Vista? Part II

This is a faster method of telling which processes are communicating. It feeds netstat output to tasklist:

@for /f "tokens=1-5" %a in ('@netstat -nto ^| findstr /V Active ^| findstr /V Proto') do @tasklist /FO CSV /V /FI "PID eq %e" /NH

If put in a batch file that is properly escaped:

@for /f "tokens=1-5" %%a in ('@netstat -nto ^| findstr /V Active ^| findstr /V Proto') do @tasklist /FO CSV /V /FI "PID eq %%e" /NH

and then run as below, it gives you process information on Established TCP connections. Tested on Vista. :

@ntob_ts.cmd | sort /+2
"chrome.exe","3192","Console","1","77,012 K","Running","RMFVista\Admin","0:02:54","Daily Alerts - Google Analytics - Google Chrome"
"chrome.exe","3192","Console","1","77,012 K","Running","RMFVista\Admin","0:02:54","Daily Alerts - Google Analytics - Google Chrome"
"opera.exe","4092","Console","1","346,284 K","Running","RMFVista\Admin","0:09:03","http://sn114w.snt114.mail.live.com/default.aspx?wa=wsignin1.0 - Opera"
"opera.exe","4092","Console","1","346,328 K","Running","RMFVista\Admin","0:09:03","http://sn114w.snt114.mail.live.com/default.aspx?wa=wsignin1.0 - Opera"



This  batch file below includes netstat endpoints but seems to randomly attach an IP address to the System Idle process ("0"):

@echo off
for /f "tokens=1-5" %%a in ('@netstat -nto ^| findstr /V Active ^| findstr /V Proto') do set EP=%%c& set PID=%%e& call :loop
goto EOF
:loop

@echo "%EP%", | findstr /V "ECHO" 
@tasklist /FO CSV /V /FI "PID eq %PID%" /NH
@echo " " >NUL

:EOF


[output]
"74.125.19.17:443",
"chrome.exe","3192","Console","1","89,400 K","Running","RMFVista\Admin","0:03:34","Blogger: Horizontal Logic - Edit Post "Which Processes are communicating on Vista? Part I...
" - Google Chrome"
"74.125.19.19:443",
"chrome.exe","3192","Console","1","89,400 K","Running","RMFVista\Admin","0:03:34","Blogger: Horizontal Logic - Edit Post "Which Processes are communicating on Vista? Part I...
" - Google Chrome"
"74.125.19.19:443",
"opera.exe","4092","Console","1","346,312 K","Running","RMFVista\Admin","0:09:40","http://sn114w.snt114.mail.live.com/default.aspx?wa=wsignin1.0 - Opera"
"74.125.19.19:443",
"opera.exe","4092","Console","1","346,324 K","Running","RMFVista\Admin","0:09:40","http://sn114w.snt114.mail.live.com/default.aspx?wa=wsignin1.0 - Opera"
"74.125.19.101:80",
"chrome.exe","3192","Console","1","89,400 K","Running","RMFVista\Admin","0:03:34","Blogger: Horizontal Logic - Edit Post "Which Processes are communicating on Vista? Part I...
" - Google Chrome"
"74.125.10.23:80",
"chrome.exe","3192","Console","1","89,400 K","Running","RMFVista\Admin","0:03:34","Blogger: Horizontal Logic - Edit Post "Which Processes are communicating on Vista? Part I...
" - Google Chrome"
"76.96.30.119:110",
"System Idle Process","0","Services","0","24 K","Unknown","NT AUTHORITY\SYSTEM","24:51:17","N/A"
"85.13.200.108:110",
"WinMail.exe","4456","Console","1","179,712 K","Running","RMFVista\Admin","0:34:00","Google Alert - TCP/IP"

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: