#!/usr/bin/perl -w # # Copyright (c) 2006-2007, Gregory Fleischer (gfleischer@gmail.com) # # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # 1. Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # 2. Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # 3. The names of the authors may not be used to endorse or promote # products derived from this software without specific prior # written permission. # # THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR # IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. # use Crypt::DES; use strict; # read passwords and generate LM hash while (<>) { chomp; next if /^\s*$/; my $hash = &make_lm_hash($_); # convert to upper case hex values print uc(unpack("H*", $hash)), "\n"; } exit 0; sub make_lm_hash { # see http://en.wikipedia.org/wiki/LM_hash # password is converted to upper case my $password = $_[0]; $password = uc($password); # passwords longer than 14 characters are truncated # passwords shorter than 14 characters are null padded my $len = length($password); if ($len > 14) { $password = substr($password, 0, 14); } elsif ($len < 14) { $password .= chr(0) x (14 - $len); } # password is then split into 2 seven byte halves # the halves are used to create keys for the DES encryption # then constant string "KGS!@#$%" is encrypted my $k1 = &create_key(substr($password, 0, 7)); my $k2 = &create_key(substr($password, 7, 7)); my $c1 = Crypt::DES->new($k1); my $c2 = Crypt::DES->new($k2); my $h1 = $c1->encrypt('KGS!@#$%'); my $h2 = $c2->encrypt('KGS!@#$%'); # the result hash are the two hex values concatenated return $h1 . $h2; } sub create_key { # create the key splitting it into eight 7-bit pieces # then add a bit of odd parity # result is eight bytes my $piece = shift; my $result = ""; my $bits = unpack("B56", $piece); for(my $i = 0; $i < 8; ++$i) { my $tmp = substr($bits, $i*7, 7); my $c = 0; for (my $j = 0; $j < 7; ++$j) { $c += substr($tmp, $j, 1); } if ($c % 2 == 0) { $tmp .= "1"; } else { $tmp .= "0"; } $result .= $tmp; } return pack("B64", $result); } # eof