Saturday, October 4, 2008

More cmd.exe vs Powershell

This ditz below gets me a columnar listing of IP Address, DNS Name from cmd.exe . In the next post, we will whip that up in Powershell.

:: Produces columnar listing of IP and DNS name for range of IPs
:: Takes one argument with the first three octets of an IP  
:: 'CheckNames 209.85.171 | findstr IP_Name' or
:: 'CheckNames 209.85.171 | findstr IP_Name >> Out.txt'
:: requires Cygwin in path or GNU grep, gawk, tr for Win32

@echo off
 set args=%1
 (for /l %%i in (1,1,255) do ( set OCT=%%i  && set args && call :loop ))
goto end

:loop
set OCT
for /f %%i in ('ping -n 1 -l 1 -w 750 %args%.%OCT% ^| grep Reply ^| gawk '{ print $3 }' ^| tr -d : '  ) do set IP=%%i
for /f %%i in ('nslookup %args%.%OCT% ^| grep Name: ^| gawk '{ print $2 }' ') do set Name=%%i
echo IP_Name %IP% %Name%
 set IP=
 set Name=
:end

Some sample output shows some of the problems in constructing complicated cmd.exe logic:

IP_Name  cg-in-f107.google.com
IP_Name 209.85.171.108 cg-in-f108.google.com
IP_Name
IP_Name
IP_Name
IP_Name 209.85.171.112 cg-in-f112.google.com
IP_Name 209.85.171.113 cg-in-f113.google.com
IP_Name
IP_Name 209.85.171.115 cg-in-f115.google.com
IP_Name 209.85.171.116

We know some ICMP fails, we know some name resolution fails, but we can't easily uncover the reasons for the failures or run additional code to check on the status of the failed ICMP and DNS requests.

Sunday, September 14, 2008

More Parsing Event Logs. Another way to do this , referencing part  of Brandon Shell and  Shay Levi's discussion. This doesn't parse the unformatted message text into object as I did in the post before.  In any event, it would be useful to get away from using findstr.exe.

$now = [System.DateTime]::get_now()
$now.ToShortDateString()
$Now_ToString = $now.ToShortDateString()
get-eventlog -logname Security | where-object {($_.timegenerated -match "$Now_ToString") -and ($_.message -match "Windows Firewall")}  | fl * |  findstr "Port number"
# or
get-eventlog -logname Security | where-object {($_.timegenerated -match "$Now_ToString") -and ($_.message -match "Port number")}  | fl * | findstr "Port number"

Wednesday, September 10, 2008

Creates a columnar listing of Ports to which the Windows Firewall has denied access. No doubt there is a simpler way....This uses Lee Holmes 'Convert-TextObject.ps1' from the "The Windows Powershell Cookbook". To get around parsing the message fields in the Event Log which aren't objects, I used findstr.exe with "MessageFilters.txt" as far below.

$now = [System.DateTime]::get_now()
$nowshort = ($now.ToShortDateString()).ToString()
$TodaysFA = ( ( get-eventlog -logname security | where {$_.EntryType -eq "FailureAudit" -and $_.TimeGenerated -match "$nowshort" } )| Select TimeGenerated,Message )
$TodaysFA_Delimited = ($TodaysFA | fl * | findstr /g:MessageFilters.txt) | .\Convert-TextObject.ps1 -Delimiter ":"
$TodaysFA_Ports = $TodaysFA_Delimited | where-object {$_.Property1 -match "Port"} | sort-object {$_.Property2}
$TodaysFA_PortNumber =  $TodaysFA_Ports | Select {$_.Property2} 

MessageFilters.txt

TimeGenerated :
Message:
Process identifier:
User account:
User domain:
Service:
RPC server:
IP version:
IP protocol:
Port number:
Allowed:
User notified:


Tuesday, September 2, 2008

Parsing Event Logs for Windows Firewall Entries

Note:Sat Jun  9 11:39:23 Pacific Daylight Time 2012
A number of posts  on my Network Security blog update this post some -THX RMF

Parsing Event Logs. So what I am trying to do is fish out all the Windows Firewall Entries that tell me what internal ports communicate with the outside world. This is a useful way to use pfirewall.log (Windows Firewall to check for Trojans). I have eventviewer entries like below that give me more information than the pfirewall.log

Event Type: Failure Audit
Event Source: Security
Event Category: Detailed Tracking
Event ID: 861
Date: 9/3/2008
Time: 6:58:53 AM
User: NT AUTHORITY\NETWORK SERVICE
Computer: RMFMEDIA
Description:
The Windows Firewall has detected an application listening for incoming traffic.

Name: -
Path: C:\WINDOWS\system32\svchost.exe
Process identifier: 1432
User account: NETWORK SERVICE
User domain: NT AUTHORITY
Service: Yes
RPC server: No
IP version: IPv4
IP protocol: UDP
Port number: 61248
Allowed: No
User notified: No

D:\>tail pfirewall.log
2008-09-03 07:27:37 OPEN UDP 192.168.1.114 69.7.46.8 56319 53 - - - - - - - - -
2008-09-03 07:27:37 OPEN TCP 192.168.1.114 72.14.207.191 1551 80 - - - - - - - - -
2008-09-03 07:27:38 OPEN UDP 192.168.1.114 192.168.0.2 1025 514 - - - - - - - - -
2008-09-03 07:27:44 CLOSE TCP 192.168.1.114 72.14.223.191 1550 80 - - - - - - - - -
2008-09-03 07:27:44 DROP TCP 72.14.223.191 192.168.1.114 80 1550 288 AP 2880782099

This is the basic idea:

( ( get-eventlog -logname security | where {$_.EntryType -eq "FailureAudit"} )| Select ReplacementStrings,TimeGenerated,Message )

The spew below also works now. What I wanted to do is limit the event log entries to today's date, but I couldn't find any easy way to embed a 'get-date' command without parsing it.

$date = (get-date -format g).Split(" ")
$now = $date[0].ToString()
$TodaysFA = ( ( get-eventlog -logname security | where {$_.EntryType -eq "FailureAudit" -and $_.TimeGenerated -match "$now" } )| Select ReplacementStrings,TimeGenerated,Message )

$date = (get-date -format g).Split(" ")
$now = $date[0].ToString()
$Todays_861 = ( ( get-eventlog -logname security | where {$_.EventID -eq "861" -and $_.TimeGenerated -match "$now" } )| Select ReplacementStrings,TimeGenerated,Message )

Next up: to dump just the Message field and extract out the port number and other various info into a csv. What I really want is just this information in a csv:

Process identifier: 1432
User account: NETWORK SERVICE
User domain: NT AUTHORITY
Service: Yes
RPC server: No
IP version: IPv4
IP protocol: UDP
Port number: 61248
Allowed: No

Tuesday, July 15, 2008

With the help of Kuma:

http://groups.google.com/group/microsoft.public.windows.powershell
/browse_thread/thread/9b10ea1270dfd0ad/eb78a0bc226837d6#eb78a0bc226837d6

I have picked up this gem, which gives all the physical IPs on a system:

0..1 | %{([System.Net.DNS]::GetHostEntry(""))
.AddressList[$_].IPAddressToString}

Monday, July 7, 2008

/\/\o\/\/ came up with the following brilliance:
http://thepowershellguy.com/blogs/posh/archive/2008/06/30/powershell-get-ipconfig-function.aspx?
CommentPosted=true#commentmessage

[System.Net.NetworkInformation.NetworkInterface]::GetAllNetworkInterfaces()
|% {$_.getIPProperties().UnicastAddresses[0]}


Address : 192.168.0.5
IPv4Mask : 255.255.255.0
IsTransient : False
IsDnsEligible : True
PrefixOrigin : Dhcp
SuffixOrigin : OriginDhcp
DuplicateAddressDetectionState : Preferred
AddressValidLifetime : 349435
AddressPreferredLifetime : 349435
DhcpLeaseLifetime : 349435

Address : 127.0.0.1
IPv4Mask :
IsTransient : False
IsDnsEligible : True
PrefixOrigin : Manual
SuffixOrigin : Manual
DuplicateAddressDetectionState : Preferred
AddressValidLifetime : 3079514780
AddressPreferredLifetime : 3079514780
DhcpLeaseLifetime : 3079514780




[System.Net.NetworkInformation.NetworkInterface]::GetAllNetworkInterfaces()
|% {$_.getIPProperties}


MemberType : Method
OverloadDefinitions : {System.Net.NetworkInformation.IPInterfaceProperties GetIPProperties()}
TypeNameOfValue : System.Management.Automation.PSMethod
Value : System.Net.NetworkInformation.IPInterfaceProperties GetIPProperties()
Name : GetIPProperties
IsInstance : True

MemberType : Method
OverloadDefinitions : {System.Net.NetworkInformation.IPInterfaceProperties GetIPProperties()}
TypeNameOfValue : System.Management.Automation.PSMethod
Value : System.Net.NetworkInformation.IPInterfaceProperties GetIPProperties()
Name : GetIPProperties
IsInstance : True

MemberType : Method
OverloadDefinitions : {System.Net.NetworkInformation.IPInterfaceProperties GetIPProperties()}
TypeNameOfValue : System.Management.Automation.PSMethod
Value : System.Net.NetworkInformation.IPInterfaceProperties GetIPProperties()
Name : GetIPProperties
IsInstance : True

Sunday, July 6, 2008

I find it simply amazing that Powershell can use the .NET to find the Broadcast and Loopback with little complication, but not the host IP Address:
[System.Net.IPAddress]::Broadcast.IPAddressToString
or
[System.Net.IPAddress]::Loopback.IPAddressToString

I can find all NetworkInterface information BUT the IP easily enough:
[System.Net.NetworkInformation.NetworkInterface]::
GetAllNetworkInterfaces()

But if I want my local host IP address through .NET I need some kludge like:
$host_name = [System.Net.Dns]::GetHostName() ; [System.Net.Dns]::Resolve("$host_name")

Or I can dredge up some other not quite satisfactory kludge from gwmi:

$NetworkInfo =gwmi -query "SELECT * FROM Win32_NetworkAdapterConfiguration"
function NetworkInfoSort {$NetworkInfo | Select-Object IPAddress,Description,Index,DefaultIPGateway | sort-object Index}
NetworkInfoSort

gwmi -class win32_NetworkAdapterConfiguration | %{ $_.IPAddress }

gwmi -query "SELECT IPAddress FROM Win32_NetworkAdapterConfiguration" | Select IPAddress

I wish I could just do something like:

[System.Net.IPAddress]::LocalHost.IPAddressToString
or
[System.Net.NetworkInformation.NetworkInterface]::
GetAllNetworkInterfaces.IPAddress
or
Get-ipconfig

Wednesday, July 2, 2008

Still relatively confused on how to use the .NET through Powershell. Here are some simple examples that were easy to find because they have accessible overloaded interfaces (??):

$Ping = new-object System.Net.NetworkInformation.ping
$Ping.Send("192.168.0.1")
Status : Success
Address : 192.168.0.1
RoundtripTime : 1 ms
BufferSize : 32
Options : TTL=127, DontFragment=False


[System.Net.Dns]::Resolve("google.com") | fl *
HostName : google.com
Aliases : {}
AddressList : {64.233.167.99, 72.14.207.99, 64.233.187.99}


[System.Net.Dns]::GetHostName()
rmfmedia

[System.Net.NetworkInformation.NetworkInterface]::GetAllNetworkInterfaces()

Id : {0348D5D7-6D83-44C8-B556-B29466698340}
Name : Wireless Network Connection
Description : Intel(R) PRO/Wireless 3945ABG Network Connection - Packet Scheduler Miniport
NetworkInterfaceType : Ethernet
OperationalStatus : Up
Speed : 54000000
IsReceiveOnly : False
SupportsMulticast : True
....

[System.Net.NetworkInformation.NetworkInterface]::GetIsNetworkAvailable()
True

Tuesday, June 17, 2008

Exploration of .NET through 'Powertab' interrogation continues. I still don't know how to benefit from 'Powertab' just yet...I would like to know is Powershell can call these Properties below.

[System.Net.NetworkInformation.TcpState]
.GetMembers() | %{$_.Name}


...
Unknown
Closed
Listen
SynSent
SynReceived
Established
FinWait1
FinWait2
CloseWait
Closing
LastAck
TimeWait
Querying .NET in Powershell. The ability to use the vast repertoire of .NET in Powershell is impressive. More difficult of late has been how to find .NET functions and call arguments. I was stuck reading the 3.5 Framework docs doing clunky stuff like this:

$webclient = New-Object System.Net.WebClient
$a = ($webclient | gm) | % {$_.Name}
$b = ( $a | % {$WebClient.$_} )
$c = ( $b | Select Name , OverloadDefinitions )
write $c

But then I installed 'PowerTab' and can tab my way to knowledge with the '.findmember' property. (This works without 'PowerTab' but is nowhere near as easy and complete.)

[System.Net.*
[System.Net.WebClient].
[System.Net.WebClient].FindMembers

PS [RMFMEDIA] >[System.Net.WebClient].FindMembers | ft -auto -wrap

WARNING: 4 columns do not fit into the display and were removed.

MemberType OverloadDefinitions
---------- -------------------
Method {System.Reflection.MemberInfo[] FindMembers(MemberTypes memberType, BindingFlags bindingAttr, MemberFilter filter, Object filterCriteria)}

Wednesday, June 11, 2008

Selected 'Exif' statistics script is below. There are a number of ways I can improve it: Stream output, skip csv file creation (as an interim step) read list with arrays and parameters, using regex expressions to best effect. Still, quite a few lessons learned with this and the output can help check for errors. The issue is that 'exif' (Cygwin, GNU output) will sometimes skip fields. I am not checking for that or other error conditions in general but the 'Counts' need to sync up at least. That being said, 'measure-object' cmdlet gives me some easy 'meta-file' (exif) stats about my JPGs. Output looks as below. I am still not solving the problem that I do not know how to obtain select "meta-file" information from Powershell.

Count : 214
Average :
Sum :
Maximum :
Minimum :
Property : Exif_Tag

Count : 214
Average : 7.07102803738318
Sum :
Maximum : 13
Minimum : 3.5
Property : FNumber

Count : 214
Average : 58.0140186915888
Sum :
Maximum : 82
Minimum : 27
Property : Focal_Length

## Get-exif-stats.ps1
$exif_index = gci *.jpg | %{exif ($_.Name)}
$c = $exif_index | Select-String -pattern "EXIF tag" , FNumber , "Focal Length In 35mm"
$c1 = ("$c").Split( ) | Select-String -pattern JPG , f/ , mm
$c2 = (("$c1").Replace( "'" , "")).Split()
$c3 = (("$c2").Replace( " |f/" , ",")).Split()
$c4 = (("$c3").Replace( " 35mm|" , ",")).Split()

if ((gci PhotoData.csv).Exists -eq "True") {mv PhotoData.csv PhotoData.csv.old -force}

"Exif_Tag,FNumber,Focal_Length" | out-file PhotoData.csv
$c4 | out-file -append PhotoData.csv
$PhotoData = import-csv -path PhotoData.csv

$FileName = ( $PhotoData | Measure-Object -Property Exif_Tag )
$FNumber = ( $PhotoData | Measure-Object -Property FNumber -average -maximum -minimum )
$Focal_Length = ( $PhotoData | Measure-Object -Property Focal_Length -average -maximum -minimum )

echo $FileName
echo $FNumber
echo $Focal_Length

Monday, June 9, 2008

Some progress tonight parsing 'exif' output with .Split and .Replace operators. Lee Holmes book is excellent on the use of comparison operators and text parsing. The script below takes text like this:

EXIF tags in 'P1050027.JPG' ('Intel' byte order):
FNumber |f/3.7
Focal Length In 35mm|71

and turns it into CSV delimited fields like this:

P1050027.JPG,f/3.7,71

## ParseExif.ps1
$exif_index = gci *.jpg | %{exif ($_.Name)}

$c = $exif_index | Select-String -pattern "EXIF tag" , FNumber , "Focal Length In 35mm"
$c1 = ("$c").Split( ) | Select-String -pattern JPG , f/ , mm
$c2 = (("$c1").Replace( "'" , "")).Split()

$c3 = (("$c2").Replace( " |" , ",")).Split()

$c4 = (("$c3").Replace( " 35mm|" , ",")).Split()

Sunday, June 8, 2008

The 'exif' program spits out an array of tags which I thought were consistently 56 lines (see below). (They are not of course.) So I attempted to query the 0 (filename) and the 20 (FNumber) per every group of 56 as if the output was an artificial array always 56 lines in length.

e.g. I am attempting to index an array of data by line number. This wasn't useful, but as an exercise in use of PS range operators and while construct. I am looking for some method to use PS to create objects from foreign data constructs. I think this may be approached more effectively else wise.


$exif_index = gci *.jpg | %{exif ($_.Name)}
$eil = $exif_index.length
$i = $eil

while ($i -gt 56)
{

$file_name = ($eil - ($i - 0))
$FNumber = ($eil - ($i - 20))
$exif_index[$file_name]
$exif_index[$FNumber]
## 56 is size of array
$i = ($i - 56)
}


Something like this results:
D:\images\06.04.08a
EXIF tags in 'P1050027.JPG' ('Intel' byte order):
FNumber |f/3.7
EXIF tags in 'P1050028.JPG' ('Intel' byte order):
FNumber |f/3.7
EXIF tags in 'P1050029.JPG' ('Intel' byte order):
FNumber |f/4.1
EXIF tags in 'P1050030.JPG' ('Intel' byte order):
FNumber |f/4.1

[full exif dump]

26# $exif_index | more
EXIF tags in 'P1050027.JPG' ('Intel' byte order):
--------------------+----------------------------------------------------------
Tag |Value
--------------------+----------------------------------------------------------
Manufacturer |Panasonic
Model |DMC-TZ1
Orientation |top - left
x-Resolution |72.00
y-Resolution |72.00
Resolution Unit |Inch
Software |Ver.1.0
Date and Time |2008:06:04 09:54:14
YCbCr Positioning |co-sited
Compression |JPEG compression
Orientation |top - left
x-Resolution |72.00
y-Resolution |72.00
Resolution Unit |Inch
YCbCr Positioning |co-sited
Exposure Time |1/800 sec.
FNumber |f/3.7

Saturday, June 7, 2008

All I really want is a 'Get-exif' cmdlet in Powershell so I can compare specs in 'list' below for photos I have taken. I don't want to query .NET or load an assembly or set up an array. !!! Read four or five blogs on the matter. Read Lee Holmes Cookbook. Cygwin's exif with CMD.exe trumps anything Powershell I could come up with. A stupid wasted afternoon and morning.

more list
Exposure Time
FNumber
ISO

Focal Length

Exposure Mode


(one line in cmd.exe)
for /f %i in ('dir /b *.jpg') do exif %i | Findstr -g:list && pause


(I need PS to do more than this..)

$exif_index = gci *.jpg | %{exif ($_.Name)}


Sunday, June 1, 2008

Okay...This uses 'Ping-Host' from PSCX PSSnapin. My function still doesn't do what I want it to do but..more promising. Give function first three octets (and hard code range - 1..254) , Bytes, Wait, Count (which only works as below with count of one right now...) Then Prints (only) Hosts UP, IP Address, AverageTime, MinimumTime, MaximumTime, Loss as so....Stats are misleading since I think (?) it is the ave, min, max for each separate run? )....Will fix this...and TTL...Man, Powergui is helpful. So are the NetCmdlets. Anyway, 'ping-host' is faster..than accessing the .NET ping(send) functionality from the post before this. My programming logic is still not standard. I should be using params and arrays as Holmes and Payette specify

.\CheckClassC_NC_function.ps1 209.85.173. 8000 1 20

Host UP,209.85.173.4,228,228,228,0
Host UP,209.85.173.5,42,42,42,0
Host UP,mh-in-f17.google.com,38,38,38,0
Host UP,mh-in-f18.google.com,41,41,41,0
Host UP,mh-in-f19.google.com,37,37,37,0
Host UP,mh-in-f32.google.com,42,42,42,0
...

function CheckHostClassC_function
## ($Subnet,$BufferSize,$Count,$Timeout,$TTL)
{
begin {$ping =(Ping-Host -Quiet -HostName $Subnet$_
-BufferSize $BufferSize -Count $Count -Timeout $Timeout );
$pingtrue =($ping.Received)
$host_ = ($ping.Host) ;
$AverageTime_ = ($ping.AverageTime) ;
$MinimumTime_ = ($ping.MinimumTime) ;
$MaximumTime_ = ($ping.MaximumTime) ;
$Loss_ = ($ping.Loss) ;
}

process {if ($pingtrue -eq "1")
{"Host UP"+","+"$host_"+","+"$AverageTime_"+","+
"$MinimumTime_"+","+"$MaximumTime_"+","+"$Loss_"}
}
}

sv Subnet $Args[0]
sv BufferSize $Args[1]
sv Count $Args[2]
sv Timeout $Args[3]
## sv TTL $Args[4]

1..254 | %{CheckHostClassC_function}

Sunday, May 25, 2008

So in thinking about what I have learned doing the work below...Please see my next post...To make matters worse, the pipe command does not appear in this blog.

Pinging IP subnet ranges in Powershell. This will be more difficult than...(you know the rest)..I am attempting to duplicate the functionality of my previous post.

PS D:\> $var = '192.168.0.1','192.168.0.2'

PS D:\> $var

192.168.0.1
192.168.0.2

PS D:\> $ping = new-object System.Net.NetworkInformation.Ping

PS D:\> $var foreach-object -process {$ping.Send($_)} ft -auto


Status Address RoundtripTime Options Buffer
------ ------- ------------- ------- ------
Success 192.168.0.1 1 System.Net.NetworkInformation.PingOptions {97, 98, 99, 100...}

TimedOut 0 {}

Closer yet...

PS D:\> $ping = new-object System.Net.NetworkInformation.Ping
PS D:\> $3OCT='71.0.0.'
PS D:\> 1..254 [pipe command here] foreach-object -process { if($ping.Send("$3OCT$_").status -eq "Success") {"$3OCT$_"} }


71.0.0.1
71.0.0.3
71.0.0.7
71.0.0.8
71.0.0.9
71.0.0.11


Putting this together a little bit more...

PS D:\> $3OCT = '190.10.10.'
PS D:\> function Ping-Host { begin{ $ping = new-object System.Net.NetworkInformation.Ping; } process{ if($ping.Send("$3OCT$_").status -eq "Success") {"$3OCT$_";} } }

PS D:\> 1..254 [pipe command here] Ping-Host
190.10.10.1
190.10.10.10
190.10.10.17

Looking Much Better this morning:

PS D:\> function Ping-Host { begin{ $ping = new-object System.Net.NetworkInformation.Ping; } process{ if($ping.Send("$3OCT$_","8").status -eq "Success") {"$3OCT$_"+","+($ping.Send("$3OCT$_","8").roundtriptime)+","+(date-time);} } }
PS D:\> 1..20 Ping-Host


71.0.0.1,80,05/26/2008 07:09:31
71.0.0.3,107,05/26/2008 07:09:32
71.0.0.7,97,05/26/2008 07:09:33
71.0.0.8,118,05/26/2008 07:09:33
71.0.0.11,104,05/26/2008 07:09:34

Below this 'works', but I had all kinds of issues with it and suspect that
(a) I don't understand argument and text passing in Powershell very well
(b) such skill are more idiosyncratic than they appear.

There were all kinds of issues here....lots of idiosyncratic behaviour to think about in Powershell. Actually, a whole host of Powershell topological and semantic rules exist that are not well described anywhere....


# CheckHostClassC.ps1 5:55 PM 5/26/2008 Down, dirty attempt to ping subnet. Takes two args: first three octets and wait time. Prints out IP address date, roundtriptime. No error checking.

function date-time {get-date -displayhint datetime}

function CheckHostClassC {begin {$ping = new-object System.Net.NetworkInformation.Ping; } process { if($ping.Send("$3OCT$_","$WaitTime").status -eq "Success") {"$3OCT$_"+","+($ping.Send("$3OCT$_","$WaitTime").roundtriptime)+","+(date-time);} }}

sv 3OCT $Args[0]
sv WaitTime $Args[1]

1..254 [pipe command here] CheckHostClassC

PS D:\> .\CheckHostClassC.ps1 193.172.1. 100

193.172.1.1,211,05/26/2008 18:24:37

193.172.1.3,212,05/26/2008 18:24:38

193.172.1.5,215,05/26/2008 18:24:39


Saturday, May 24, 2008

Okay, so let's try to start rewriting some CMD.EXE skillsets in Powershell. Here's something common: ping a range of subnets to see if the hosts are up and what their latency is. In CMD exe we first need some to code to produce an accurate timestamp because there is no native way to do this. Thus this complicated and idiosyncratic use of the set command to parse out time/date stamps:

:: realtd.cmd
@echo off

set realdate=%date:/=.%
set realdate=%realdate:* =%
set realtime=%time::=.%
set timestamp=%realdate%_%realtime%

Now we need some nearly unreadable spew, some help fron gawk, some hard coded ping options, a hard coded subnet range...:

:: TestSubnet.cmd
@echo off
set ThreeOctets=%1
for /l %%i in (1,1,255) do set #=%%i && call :label
goto EOF
:label @(call realtd)
@(ping -l 1 -n 1 -w 2 %ThreeOctets%.%#% | findstr Reply | gawk '{print "%timestamp%" ":" $1 ":" $3$5}' )

:EOF


and last we can put a collection of the first three octects into text file and call them like this:

for /f %i in (subnets) do call Testsubnet %i

This gives us some reasonably parseable output:

D:\>call Testsubnet 193.0.0
....
05.24.2008_19.43.04.01:Reply:193.0.0.232:time=173ms 05.24.2008_19.43.05.51:Reply:193.0.0.236:time=169ms 05.24.2008_19.43.06.01:Reply:193.0.0.238:time=171ms 05.24.2008_19.43.07.01:Reply:193.0.0.241:time=171ms

D:\>call Testsubnet 194.0.0 05.24.2008_19.43.40.01:Reply:194.0.0.53:time=100ms

Okay, so you can see quite a bit of inelegance here to start with. Let's list some issues:

(1) a separate cmd file needs to run each time to log the timestamp
(2) the ping options are hardcoded...that probably could be fixed...but more inelegance
(3) we don't really need the field 'Reply' or 'time='. but they are hard to parse out. Once again more awk or perl code would probably do this but at what cost of complexity
(4) I don't really want to have to call the file that calls THE file...I just want to point to an XML file with all the correct options....
(5) requires Cygwin or GNU-Win32 gawk in your path....

I could go on, but you get the picture. Let's assemble this tool with less complexity, more readability and more functionality in Powershell in the next post...

Sunday, May 18, 2008

The world of Windows traditional cmd line is full of cumbersome crap. Just extracting the (NBT bound) IP Address takes two lines of idiosyncratic backquotes, escaped pipes, two temp files, Finally a call to snort with BPF options:

@echo off

:: find the NBT tied IP Address
for /f "usebackq delims=:" %%i in (`ping -n 1 -l 8 %computername% ^| findstr Reply`) do @echo %%i > IPReplyString.txt

for /f "tokens=1-3" %%i in (IPReplyString.txt) do echo %%k > IP.txt

:: set the IP address to %localIP%
for /f %%i in (IP.txt) do set localIP=%%i

:: start Snort with BPF filters...
snort -l D:\SnortLogs -vdeX dst host %localIP% and !(port 53 or 80 or 110)

....

Wednesday, May 14, 2008

I will confess to being nearly a complete loser when it comes to successfully implementing sed, awk and regex. to search logs. I usually end up parsing my Authlogs with something really clueless like:

(IP Address and Port of invalid users with failed passwords)

$ grep "Failed password for invalid user" Sampleauthlog.txt | cut -b 75-110| uniq
from 202.163.221.227 port 43985 ssh
from 202.163.221.227 port 44553 ssh2
...

or (the IP Address of valid users with failed passwords )

$ grep Failed Sampleauthlog | grep -v invalid | awk '{print $11}'| uniq -c
5 202.163.221.227

I have some idea that I can break down each time, user, IP address, port, ssh type into a typical Powershell objects and do more informative and complex queries, but this needed some work:

$var=Select-string Failed SampleAuthlog.txt | Where-object {$_ -match "\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}"}

PS D:\Microsoft\Powershell> $var
SampleAuthlog.txt:3:Apr 26 01:20:29 rmfbsd sshd[30534]: Failed password for invalid user test5 from 202.163.221.227 port 43985 ssh2
SampleAuthlog.txt:5:Apr 26 01:20:32 rmfbsd sshd[11478]: Failed password for root from 202.163.221.227 port 44267 ssh2
....

Select-object $var
Select-Object : Cannot convert System.Management.Automation.PSObject to one of the following types {System.String, System.Management.Automation.ScriptBlock}.
At line:1 char:14.

One way around this is to massage a log file into a CSV format which AWK does easily, then use Powershell import-csv routine and manually add headers to the first line:


$ grep Failed authlog | grep -v invalid | awk '{print $1","$2","$3","$9","$11","$13,$15}'
Apr,26,01:20:32,root,202.163.221.227,44267
Apr,26,01:20:36,root,202.163.221.227,44411
...

$ grep Failed authlog | grep -v invalid | awk '{print $1","$2","$3","$9","$11","$13,$15}' >> /cygdrive/D/Microsoft/Powershell/Powershell.out


$PWSH = import-csv Powershell.csv
$PWSH | ft -auto
PS D:\Microsoft\Powershell> $PWSH | ft -auto

Month Day Time User IP Port
----- --- ---- ---- -- ----
Apr 26 01:20:32 root 202.163.221.227 44267
Apr 26 01:20:36 root 202.163.221.227 44411
Apr 26 01:20:47 root 202.163.221.227 44725
Apr 26 01:21:02 root 202.163.221.227 45354
...

Now we have part of an OPENBSD Authlog stored as a Powershell object. Thanks AWK!

Friday, May 9, 2008

Sequential file and Directory Creation

Sequential file and Directory Creation. Useful for Test Engineers.

creates directories

1..100 | %{ni ( "NewDirectory-{0:0}" -f $_ ) -type directory }

creates files with sequential content

1..100 | %{ni ( "NewFile-{0:0}" -f $_ ) -type "file" -value "Number $_ of 100 files."}