Hello monks! :) I am currently working on a WPA implementation in Perl, - just as a way for me to learn about not only the protocol, but Perl too, because that's what life's all about!
Anyways, I have read loads of documentation and source code, including that from Aircrack-NG. Across the board, the docs don't really match up really and are very vague, at best. So this is what I came up with. I used Net::Pcap with WiFi to capture a perfect EAPOL and beacon with which I passed to Aircrack-NG with a word list and my password inside that list. For those unfamiliar with aircrack-ng, it produces the PTK transient Key, EAPOL, and PMK. I can do the PMK, that's incredibly easy, and you will see from my simple code below. The PTK part is where I am having trouble it seems. I have hard-coded the Anonce, Snonce, AP-MAC (BSSID), and Station MAC into the code as well.
The way it seems to work in practice is that the PMK is used to create the PTK, using a function like so (taken directly from Aircrack-NG):
/* pre-compute the key expansion buffer */
memcpy( pke, "Pairwise key expansion", 23 );
if( memcmp( ap->wpa.stmac, ap->bssid, 6 ) < 0 ) {
memcpy( pke + 23, ap->wpa.stmac, 6 );
memcpy( pke + 29, ap->bssid, 6 );
} else {
memcpy( pke + 23, ap->bssid, 6 );
memcpy( pke + 29, ap->wpa.stmac, 6 );
}
if( memcmp( ap->wpa.snonce, ap->wpa.anonce, 32 ) < 0 ) {
memcpy( pke + 35, ap->wpa.snonce, 32 );
memcpy( pke + 67, ap->wpa.anonce, 32 );
} else {
memcpy( pke + 35, ap->wpa.anonce, 32 );
memcpy( pke + 67, ap->wpa.snonce, 32 );
}
// then to get the PTK, they used the string above, like so:
/* compute the pairwise transient key and the frame MIC */
for (i = 0; i < 4; i++)
{
pke[99] = i;
HMAC(EVP_sha1(), pmk[j], 32, pke, 100, ptk[j] + i * 20
+, NULL);
/*
unsigned char *HMAC(const EVP_MD *evp_md, const vo
+id *key,
int key_len, const unsigned char *d, int n,
unsigned char *md, unsigned int *md_len);
*/
}
I have placed in comments a definition of that simple HMAC() function. I tried to make my code mimic, as closely as I could, this function (and as I said, I have hard coded my PMK (which I know is correct)) but simply fall short and cannot replicate the correct PTK given to me from Aircrack-NG or CowPatty :( Below is my code:
#!/usr/bin/perl -w
use strict;
use Crypt::PBKDF2;
use Digest::HMAC_SHA1 qw(hmac_sha1 hmac_sha1_hex);
use List::Util qw( min max );
my $usage = "Usage: perl wpa2hex <ESSID> <PASSPHRASE>\n";
my $essid = shift || die $usage;
my $passwd = shift || die $usage; # pack the next few registers up
my $smac = pack("H*","489d2477179a"); # station MAC (RIM)
my $amac = pack("H*","001dd0f694b0"); # AP MAC (Arris)
my $snonce = pack("H*","143fbb4333341f36e17667f88aa02c5230ab82c508cc4b
+d5947dd7e50475ad36");
my $anonce = pack("H*","87f2718bad169e4987c94255395e054bcaf77c8d791698
+bf03dc85ed3c90832a");
my $pbkdf2 = Crypt::PBKDF2->new(
hash_class => 'HMACSHA1', # HMAC-SHA1
hash_args => {
sha_size => 512,
},iterations => 4096,
salt_len => length($essid),
output_len => 32
);
my $pmk = uc($pbkdf2->PBKDF2($essid, $passwd));
my $pbkdf2b = Crypt::PBKDF2->new(
hash_class => 'HMACSHA1', # HMAC-SHA1
hash_args => {
sha_size => 512,
},iterations => 4096,
salt_len => length($pmk),
output_len => 20
);
print "Master Key: ",uc(unpack("H*",$pmk)),"\n";
prf512();
sub prf512{
my $a = "Pairwise key expansion"; # application-specific data
my $b = $amac.$smac.$snonce.$anonce;
my $r = "";
for(my $i=0;$i<4;$i++){
my $data = $a."\x00".$b.$i;
$r .= $pbkdf2b->PBKDF2($pmk,$data);
}
print "Transient Key: ",uc(unpack("H*",$r)),"\n";
return;
}
I simply used Wikipedia and this site: http goo.gl UVXhGi as a reference. That site, however states that you need to use a "0 byte" between the "Pairwise key expansion" string and the first MAC address in the data passed to the function. Aircrack-NG's source code, as you see above, does not! Anyways, I am not trying to re-invent the wheel here, I am just a student of 802.11, Perl, C and life.
If anyone has any idea as to where I am wrong, please, the help would be greatly appreciated. Thank you in advance, and peace be with you monks <3
Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
Read Where should I post X? if you're not absolutely sure you're posting in the right place.
Please read these before you post! —
Posts may use any of the Perl Monks Approved HTML tags:
- a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
| |
For: |
|
Use: |
| & | | & |
| < | | < |
| > | | > |
| [ | | [ |
| ] | | ] |
Link using PerlMonks shortcuts! What shortcuts can I use for linking?
See Writeup Formatting Tips and other pages linked from there for more info.