Outbreak Labs

I can do anything I want to. And so can you.

Debugging Scala code inside SBT inside Vagrant, using IntelliJ

For Scala, a common development environment is the combination of IntelliJ, Vagrant, and SBT. IntelliJ to edit Scala code, Vagrant to keep a consistent, reproducible, VM-based work area, and SBT to build and run Scala code. It isn't obvious how to use the debugger in IntelliJ against the code executing under SBT within the VM. Here's how you do it.

1. In your project's SBT build settings, locate the area in which options are passed to the JVM. This likely includes such options as "-Djava.library.path=lib".
2. To this section, add the following options:
"-Xdebug",
"-Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=5005"
3. Rebuild and run your SBT project.
4. Open your project in IntelliJ, and go to Run> Edit Configurations


5. Click the plus icon in the upper left to add a new configuration, and select Remote

6. Name this configuration whatever you'd like (I called mine Vagrant), but enter your vagrant box's hostname or IP address where indicated

7. Press "OK". You should now see this new configuration selectable and debuggable in the upper right corner of the IDE.



If you've done everything correctly, IntelliJ should attach to your running Scala program.

Things that could've gone wrong:
  • If the Java options were not correctly applied, the JVM won't listen on port 5005 for the remote debugger connection. You should see a message in your console indicating that it's listening on that socket.
  • Your Vagrant instance might not be set up for networking, or to forward ports.
  • Your guest or host OS might have a firewall preventing the connection from going through

Good luck!

Calculating the WPA2 PTK using C#

Continuing with the quest to decrypt wifi traffic, I needed to be able to calculate the PTK (Pairwise Transient Key). As before, I studied the airdecap-ng source code as well as various online resources, to come up with the following code:

public static byte[] CalculatePTK(byte[] pmk, byte[] stmac, byte[] bssid, byte[] snonce, byte[] anonce)
        {           
            var pke = new byte[100];
            var ptk = new byte[80];

            using (var ms = new System.IO.MemoryStream(pke))
            {
                using (var bw = new System.IO.BinaryWriter(ms))
                {
                    bw.Write(new byte[] { 0x50, 0x61, 0x69, 0x72, 0x77, 0x69, 0x73, 0x65, 0x20, 0x6b, 0x65, 0x79, 0x20, 0x65, 0x78, 0x70, 0x61, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0 });/* Literally the string Pairwise key expansion, with a trailing 0*/

                    if (memcmp(stmac, bssid) < 0)
                    {
                        bw.Write(stmac);
                        bw.Write(bssid);
                    }
                    else
                    {
                        bw.Write(bssid);
                        bw.Write(stmac);
                    }

                    if (memcmp(snonce, anonce) < 0)
                    {
                        bw.Write(snonce);
                        bw.Write(anonce);
                    }
                    else
                    {
                        bw.Write(anonce);
                        bw.Write(snonce);
                    }

                    bw.Write((byte)0); // Will be swapped out on each round in the loop below
                }
            }
                        
            for (byte i = 0; i < 4; i++ )
            {
                pke[99] = i;
                var hmacsha1 = new HMACSHA1(pmk);                
                hmacsha1.ComputeHash(pke);
                hmacsha1.Hash.CopyTo(ptk, i * 20);                
            }
            return ptk;
        }
Perhaps the most unexpected part of this algorithm was that the string "Pairwise key expansion" is actually part of it. The airdecap-ng implementation is more efficient in a number of ways, but performance was not my goal here. It takes advantage of the fast memcmp c function in order to compare some of the variables not just for equality, but also "order". This behavior of memcmp is often overlooked; most "ports" of the function to other languages only determine equality. Here is the implementation I used, I'm afraid I've lost the original source:

 for (int i = 0; i < b1.Length; i++)
            {
                if (b1[i] != b2[i])
                {
                    if ((b1[i] >= 0 && b2[i] >= 0) || (b1[i] < 0 && b2[i] < 0))
                        return b1[i] - b2[i];
                    if (b1[i] < 0 && b2[i] >= 0)
                        return 1;
                    if (b2[i] < 0 && b1[i] >= 0)
                        return -1;
                }
            }
            return 0;
          }
The algorithm for calculating the PTK is roughly as follows...

Part 1:
1. Construct a 100 element array beginning with the null terminated ascii string "Pairwise key expansion".
2. Next, write the following pairs, with the smaller of each element first:
(stmac, bssid)
(snonce, anonce)
3. Finally, write an additional 0 byte, which will be swapped out in the next part of the algorithm.

Part 2:
1. Using the HMACSHA1 algorithm initialized with the PMK as data (see the previous post for calculating the PMK), compute the hash of the array. This hash is this first 20 bytes of the PTK.
2. Swap out the last byte of the array you constructed (the 0 byte) for a 1.
3. Repeat the hash in step 1. This is the second 20 bytes of the PTK.
4. Swap out the last byte of the array you constructed (now a 1) for a 2.
5. Repeat the hash in step 1. This is the third 20 bytes of the PTK.
6. Swap out the last byte of the array you constructed (now a 2) for a 3.
7. Repeat the hash in step 1. This is the final 20 bytes of the PTK.

The parameters for the PTK calculation consist of the the PMK, which we already know how to calculate, the station MAC and bssid, which are obtained easily enough, and the snonce and the anonce. How do we get those nonces? From the EAPOL four-way handshake. This is one of the aspects of WPA2 that is more secure than WEP: Traffic cannot be decrypted, even if you know the PSK, without also capturing the authentication handshake to obtain the nonces.

As part of this adventure, I've had to add support for Radiotap, 802.1X, and EAPOL to PacketGremlin. I don't think any of that is deserving of a post, but I just wanted to mention it. I've got nearly all the pieces required for decryption in place!

Calculating the WPA2 PMK using C#

One of the features I've wanted to implement for Packet Gremlin is the ability to decrypt encrypted WiFi traffic. I only know of two tools capable of this: Airdecap-ng, which can't do it on a live capture, and Wireshark, which can't capture wireless traffic on Windows due to a limitation of WinPCap. One of the things needed for implementing this feature is to calculate the PMK (Pairwise Master Key). By studying the source code of airdecap-ng and various online resources, I found that this is actually trivial:

Update 6/1/14: The code as originally posted was technically correct, and did pass the AirCrack unit tests and validate with other tools, however I found that the result was causing me to generate invalid PTKs. It turns out that while the PMK can be generated to an arbitrary length, and the Aircrack unit test used 40 bytes, the length expected for use in PTK calculation is actually 32 bytes. I have updated the code with this option and default accordingly.
       
public static byte[] CalculatePMK(byte[] psk, byte[] ssid, int pmkLength = 32)
        {
            Rfc2898DeriveBytes pbkdf2 = new Rfc2898DeriveBytes(psk, ssid, 4096);
            return pbkdf2.GetBytes(pmkLength);
        }


I was pleased to find a small set of unit tests accompany the aircrack suite, including one for PMK calculation. I ported it to C# and... it crashed. It turns out that, for reasons unknown to me, the Rfc2898DeriveBytes class requires that the salt (in this case, the ssid) be at least 8 bytes in length. Since ssids (including the one in this unit test) can be fewer than 8 bytes in length, I needed to work around this artificial limitation. I used Reflector to examine the source of this class, and found that the exception is thrown in the setter for the Salt property, which is invoked in the constructor. The setter does three things:

1. Validates the length of the salt
2. Copies the salt to the private byte[] m_salt
3. Calls the private method Initialize()

I found that the public method Reset calls the private method Initialize, but upon further inspection of the Initialize method itself, I realized that in this particular case, I don't need to do it since this is a fresh instance of the class. All I really needed to do was fill in m_salt.

I used an empty byte[8] as a placeholder for the salt in the constructor, then used reflection to get a reference to the private m_salt field, and set it with the ssid:

       
public static byte[] CalculatePMK(byte[] psk, byte[] ssid, int pmkLength = 32)
        {
            Rfc2898DeriveBytes pbkdf2 = new Rfc2898DeriveBytes(psk, /*ssid*/ new byte[8], 4096);
            //This reflection is required because there's an arbitrary restriction that the salt must be at least 8 bytes
            var saltProp = pbkdf2.GetType().GetField("m_salt", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
            saltProp.SetValue(pbkdf2, ssid);

            //pbkdf2.Reset(); 
            //To officially complete the reflection trick, the private method Initialize() should be called. That's all Reset() does. 
            //But I don't think it's needed because we haven't hashed anything yet.

            return pbkdf2.GetBytes(pmkLength);
        }


With that change, the unit test passed, and the PMK calculation was complete. In a subsequent post I will discuss the less trivial implementation of the PTK calculation.