diff -Nru doona-0.7+git20131211/bedmod/dict.pm doona-1.0+git20160212/bedmod/dict.pm --- doona-0.7+git20131211/bedmod/dict.pm 1970-01-01 00:00:00.000000000 +0000 +++ doona-1.0+git20160212/bedmod/dict.pm 2016-09-22 14:15:20.000000000 +0000 @@ -0,0 +1,140 @@ +package bedmod::dict; +use Socket; + +# This package is an extension to BED, to check +# for DICT server vulnerabilities. + +# Authentication is not implemented for this module. +# There's a bunch of placeholders which will help +# should you wish to implement authentication. +# For more information, review: +# - RFC 2229 (DICT) - section 3.11 - The AUTH Command +# - RFC 1939 (POP) - section 4 - The AUTHORIZATION State + +sub new { + my $this = {}; + # Authentication is not implemented for this module. + # These default values are used to fuzz auth verbs: + $this->{username} = 'anonymous'; + $this->{password} = 'password'; + bless $this; + return $this; +} + +sub init { + my $this = shift; + %special_cfg=@_; + + $this->{proto}="tcp"; + + if ($special_cfg{'p'} eq "") { $this->{port}='2628'; } + else { $this->{port} = $special_cfg{'p'}; } + $this->{vrfy} = "HELP\r\n"; + + # Authentication is not implemented for this module. + # This is a placeholder + $this->{username} = $special_cfg{'u'} if $special_cfg{'u'}; + $this->{password} = $special_cfg{'v'} if $special_cfg{'v'}; + + # Test connection to target (skip if dump mode is set) + if ($special_cfg{'d'}) { return; } + $iaddr = inet_aton($this->{target}) || die "Unknown host: $this->{target}\n"; + $paddr = sockaddr_in($this->{port}, $iaddr) || die "getprotobyname: $!\n"; + $proto = getprotobyname('tcp') || die "getprotobyname: $!\n"; + socket(SOCKET, PF_INET, SOCK_STREAM, $proto) || die "socket: $!\n"; + connect(SOCKET, $paddr) || die "connection attempt failed: $!\n"; + # Authentication is not implemented for this module. + # so we grab the banner instead + send(SOCKET, "\r\n", 0); + $recvbuf = ; + print ($recvbuf); + + # The psuedo-code below checks if the server requires authentication. + #send(SOCKET, "AUTH $this->{username} md5($this->{password})\r\n", 0) || die "Authentication failed: $!\n"; + #do { + # $recvbuf = ; + # print ($recvbuf); + # if ( $recvbuf =~ "530" ) { + # print ("Access is denied, can't login\n"); + # exit(1); + # } + # if ( $recvbuf =~ "531" ) { + # print ("Username or password incorrect, can't login\n"); + # exit(1); + # } + # sleep(0.2); + ## 230 Authentication successful + #} until ( $recvbuf =~ "230" ); + #send(SOCKET, "QUIT\r\n", 0); + close(SOCKET); +} + +sub getQuit { + return("QUIT\r\n"); +} + +sub getLoginarray { + my $this = shift; + # Authentication is not implemented for this module. + # so we return an empty string + return (""); + # This is a placeholder + @Loginarray = ( + "XAXAX\r\n", + "AUTH XAXAX\r\n", + "AUTH XAXAX XAXAX\r\n", + "AUTH $this->{username} XAXAX\r\n", + "SASLAUTH XAXAX\r\nSASLRESP XAXAX\r\n", + "SASLAUTH XAXAX XAXAX\r\nSASLRESP XAXAX\r\n" + ); + return (@Loginarray); +} + +sub getCommandarray { + my $this = shift; + + # the XAXAX will be replaced with the buffer overflow / format string + # just comment them out if you don't like them. + @cmdArray = ( + "XAXAX\r\n", + "AUTH XAXAX\r\n", + "AUTH XAXAX XAXAX\r\n", + "AUTH $this->{username} XAXAX\r\n", + "SASLAUTH XAXAX\r\nSASLRESP XAXAX\r\n", + "SASLAUTH XAXAX XAXAX\r\nSASLRESP XAXAX\r\n", + "DEFINE ! XAXAX\r\n", + "DEFINE XAXAX XAXAX\r\n", + "MATCH ! XAXAX XAXAX\r\n", + "MATCH XAXAX XAXAX XAXAX\r\n", + "SHOW XAXAX\r\n", + "SHOW INFO XAXAX\r\n", + "CLIENT XAXAX\r\n", + "OPTION XAXAX\r\n" + ); + return(@cmdArray); +} + +sub getLogin { + my $this = shift; + # Authentication is not implemented for this module. + # so we return an empty string + @login = ""; + return(@login); + # This is a placeholder + @login = ("AUTH $this->{username} $this->{password}\r\n"); + return(@login); +} + +sub testMisc { + return(); +} + +sub usage { + print qq~ DICT module specific options: + -u = Username to use for authentication (default: anonymous) + -v = Password to use for authentication (default: password) + +~; +} + +1; diff -Nru doona-0.7+git20131211/bedmod/ftp.pm doona-1.0+git20160212/bedmod/ftp.pm --- doona-0.7+git20131211/bedmod/ftp.pm 2013-12-11 17:47:43.000000000 +0000 +++ doona-1.0+git20160212/bedmod/ftp.pm 2016-09-22 14:15:20.000000000 +0000 @@ -6,6 +6,7 @@ sub new { my $this = {}; + $this->{'healthy'} = undef; $this->{username} = 'anonymous'; # specific for just this $this->{password} = 'user@this.bed'; # module bless $this; @@ -29,7 +30,8 @@ # let's see if we got a correct login (skip if dump mode is set) if ($special_cfg{'d'}) { return; } - $iaddr = inet_aton($this->{target}) || die "Unknown host: $host\n"; + die "FTP server failed health check!\n" unless($this->health_check()); + $iaddr = inet_aton($this->{target}) || die "Unknown host: $this->{target}\n"; $paddr = sockaddr_in($this->{port}, $iaddr) || die "getprotobyname: $!\n"; $proto = getprotobyname('tcp') || die "getprotobyname: $!\n"; socket(SOCKET, PF_INET, SOCK_STREAM, $proto) || die "socket: $!\n"; @@ -51,6 +53,25 @@ close(SOCKET); } +sub health_check { + my $this = shift; + $iaddr = inet_aton($this->{target}) || die "Unknown host: $this->{target}\n"; + $paddr = sockaddr_in($this->{port}, $iaddr) || die "getprotobyname: $!\n"; + $proto = getprotobyname('tcp') || die "getprotobyname: $!\n"; + socket(SOCKET, PF_INET, SOCK_STREAM, $proto) || die "socket: $!\n"; + connect(SOCKET, $paddr) || die "connection attempt failed: $!\n"; + do { + $recv=; + sleep(0.2); + } until $recv =~ /^220/; + send(SOCKET, "PASS\r\n", 0); + $recv=; + if (!$this->{'healthy'}) { + $this->{'healthy'} = $recv if ($recv =~ /^\d\d\d/); + } + return $recv =~ /^$this->{'healthy'}$/; +} + sub getQuit { return("QUIT\r\n"); } @@ -80,13 +101,17 @@ "ABOR XAXAX\r\n", "ACCL XAXAX\r\n", "ACCT XAXAX\r\n", + "ADAT XAXAX\r\n", "ALLO XAXAX\r\n", "APPE XAXAX\r\n", "APPE /XAXAX\r\n", + "CCC XAXAX\r\n", "CDUP XAXAX\r\n", + "CONF XAXAX\r\n", "CWD XAXAX\r\n", "CEL XAXAX\r\n", "DELE XAXAX\r\n", + "ENC XAXA\r\n", "EPRT XAXAX\r\n", "EPRT |XAXAX|127.0.0.1|6275|\r\n", "EPRT |1|XAXAX|6275|\r\n", @@ -94,15 +119,19 @@ "EPSV XAXAX\r\n", "FEAT XAXAX\r\n", "HELP XAXAX\r\n", + "LANG XAXAX\r\n", "LIST XAXAX\r\n", "LIST -XAXAX\r\n", "LIST *XAXAX\r\n", "LOCK XAXAX\r\n", "LOCK / XAXAX\r\n", + "LPRT XAXAX\r\n", + "LPSV XAXAX\r\n", "MDTM XAXAX\r\n", "MDTM XAXAX file.txt\r\n", "MDTM 19990929043300 XAXAX\r\n", "MDTM 20031111111111+ XAXAX\r\n", + "MIC XAXAX\r\n", "MLST XAXAX\r\n", "MODE XAXAX\r\n", "MKD XAXAX\r\n", @@ -116,8 +145,10 @@ "OPTS XAXAX\r\n", "PASS XAXAX\r\n", "PASV XAXAX\r\n", + "PBSZ XAXAX\r\n", "PORT XAXAX\r\n", "PWD XAXAX\r\n", + "QUOTE XAXAX\r\n", "REIN XAXAX\r\n", "REST XAXAX\r\n", "RETR XAXAX\r\n", @@ -157,7 +188,11 @@ "XMD5 XAXAX\r\n", "XMKD XAXAX\r\n", "XPWD XAXAX\r\n", + "XRCP XAXAX\r\n", "XRMD XAXAX\r\n", + "XRSQ XAXAX\r\n", + "XSEM XAXAX\r\n", + "XSEN XAXAX\r\n", ); return(@cmdArray); } @@ -179,7 +214,7 @@ @traversal = ("...", "%5c..%5c", ,"%5c%2e%2e%5c", "/././..", "/...", "/......", "\\...", "...\\", "....", "*", "\\*", "\\....", "*\\\\.....", "/..../", "/../../../", "\\..\\..\\..\\", "\@/..\@/.."); foreach $Directory (@traversal){ - $iaddr = inet_aton($this->{target}) || die "Unknown host: $host\n"; + $iaddr = inet_aton($this->{target}) || die "Unknown host: $this->{target}\n"; $paddr = sockaddr_in($this->{port}, $iaddr) || die "getprotobyname: $!\n"; $proto = getprotobyname('tcp') || die "getprotobyname: $!\n"; socket(SOCKET, PF_INET, SOCK_STREAM, $proto) || die "socket: $!\n"; diff -Nru doona-0.7+git20131211/bedmod/http.pm doona-1.0+git20160212/bedmod/http.pm --- doona-0.7+git20131211/bedmod/http.pm 2013-12-11 17:47:43.000000000 +0000 +++ doona-1.0+git20160212/bedmod/http.pm 2016-09-22 14:15:20.000000000 +0000 @@ -15,6 +15,7 @@ %special_cfg=@_; $this->{proto}="tcp"; + $this->{healthy}=undef; if ($special_cfg{'p'} eq "") { $this->{port}='80'; @@ -23,14 +24,28 @@ } if ($special_cfg{'d'}) { return; } - $iaddr = inet_aton($this->{target}) || die "Unknown host: $host\n"; + die "HTTP server failed health check!\n" unless($this->health_check()); +} + +sub health_check { + my $this = shift; + $iaddr = inet_aton($this->{target}) || die "Unknown host: $this->{target}\n"; $paddr = sockaddr_in($this->{port}, $iaddr) || die "getprotobyname: $!\n"; $proto = getprotobyname('tcp') || die "getprotobyname: $!\n"; socket(SOCKET, PF_INET, SOCK_STREAM, $proto) || die "socket: $!\n"; connect(SOCKET, $paddr) || die "connection attempt failed: $!\n"; send(SOCKET, "HEAD / HTTP/1.0\r\n\r\n", 0) || die "HTTP request failed: $!\n"; + my $resp = ; + if (!$this->{healthy}) { + if ($resp =~ /HTTP/) { + $this->{healthy}=$resp; + } + # print "Set healthy: $resp"; + } + return $resp =~ m/^$this->{healthy}$/; } + sub getQuit { return("\r\n\r\n"); } @@ -101,6 +116,7 @@ "From: XAXAX\r\n\r\n", "Charge-To: XAXAX\r\n\r\n", "Authorization: XAXAX", + "Authorization XAXAX: Basic AAAAAA\r\n\r\n", "Authorization: XAXAX : foo\r\n\r\n", "Authorization: foo : XAXAX\r\n\r\n", "If-Modified-Since: XAXAX\r\n\r\n", @@ -118,6 +134,7 @@ "Range: bytes=0-1,XAXAX\r\n", "Content-Length: XAXAX\r\n\r\n", "Cookie: XAXAX\r\n\r\n", + "X-Headr: XAXAX\r\n XAXAX\r\n\r\n", "TE: XAXAX\r\n\r\n", "Upgrade: XAXAX\r\nConnection: upgrade\r\n\r\n", ); diff -Nru doona-0.7+git20131211/bedmod/nntp.pm doona-1.0+git20160212/bedmod/nntp.pm --- doona-0.7+git20131211/bedmod/nntp.pm 1970-01-01 00:00:00.000000000 +0000 +++ doona-1.0+git20160212/bedmod/nntp.pm 2016-09-22 14:15:20.000000000 +0000 @@ -0,0 +1,146 @@ +package bedmod::nntp; +use Socket; + +# This package is an extension to bed, to check +# for NNTP server vulnerabilities. + +sub new { + my $this = {}; + $this->{username} = 'anonymous'; # specific for just this + $this->{password} = 'password'; # module + bless $this; + return $this; +} + +sub init { + my $this = shift; + %special_cfg=@_; + + $this->{proto}="tcp"; + + if ($special_cfg{'p'} eq "") { $this->{port}='119'; } + else { $this->{port} = $special_cfg{'p'}; } + $this->{vrfy} = "HELP\r\n"; + + $this->{username} = $special_cfg{'u'} if $special_cfg{'u'}; + $this->{password} = $special_cfg{'v'} if $special_cfg{'v'}; + + # let's see if we got a correct login (skip if dump mode is set) + if ($special_cfg{'d'}) { return; } + $iaddr = inet_aton($this->{target}) || die "Unknown host: $this->{target}\n"; + $paddr = sockaddr_in($this->{port}, $iaddr) || die "getprotobyname: $!\n"; + $proto = getprotobyname('tcp') || die "getprotobyname: $!\n"; + socket(SOCKET, PF_INET, SOCK_STREAM, $proto) || die "socket: $!\n"; + connect(SOCKET, $paddr) || die "connection attempt failed: $!\n"; + send(SOCKET, "authinfo user $this->{username}\r\n", 0) || die "Username failed: $!\n"; + $recvbuf = ; + sleep(1); + send(SOCKET, "authinfo pass $this->{password}\r\n", 0) || die "Password failed: $!\n"; + do { + $recvbuf = ; + print ($recvbuf); + if ( $recvbuf =~ "452" ) { + print ("Username or password incorrect, can't login\n"); + exit(1); + } + sleep(0.2); + # 281 Authorization accepted + } until ( $recvbuf =~ "281" ); + send(SOCKET, "QUIT\r\n", 0); + close(SOCKET); +} + +sub getQuit { + return("QUIT\r\n"); +} + +sub getLoginarray { + my $this = shift; + @Loginarray = ( + "XAXAX\r\n", + "authinfo XAXAX\r\n", + "authinfo XAXAX XAXAX\r\n", + "authinfo user XAXAX\r\nXAXAX\r\n", + "authinfo user XAXAX\r\nauthinfo pass XAXAX\r\n", + "authinfo user $this->{username}\r\nauthinfo pass XAXAX\r\n", + "authinfo pass XAXAX\r\n", + "authinfo simple XAXAX\r\n", + "authinfo simple\r\nXAXAX XAXAX\r\n", + "authinfo simple\r\n$this->{username} XAXAX\r\n", + "authinfo generic XAXAX\r\n", + "authinfo generic XAXAX XAXAX\r\n" + ); + return (@Loginarray); +} + +sub getCommandarray { + my $this = shift; + + # the XAXAX will be replaced with the buffer overflow / format string + # just comment them out if you don't like them.. + @cmdArray = ( + "XAXAX\r\n", + "authinfo XAXAX\r\n", + "authinfo XAXAX XAXAX\r\n", + "authinfo user XAXAX\r\nXAXAX\r\n", + "authinfo user XAXAX\r\nauthinfo pass XAXAX\r\n", + "authinfo user $this->{username}\r\nauthinfo pass XAXAX\r\n", + "authinfo pass XAXAX\r\n", + "authinfo simple XAXAX\r\n", + "authinfo simple\r\nXAXAX XAXAX\r\n", + "authinfo simple\r\n$this->{username} XAXAX\r\n", + "authinfo generic XAXAX\r\n", + "authinfo generic XAXAX XAXAX\r\n", + "article XAXAX\r\n", + "body XAXAX\r\n", + "charset XAXAX\r\n", + "check XAXAX\r\n", + "group XAXAX\r\n", + "head XAXAX\r\n", + "help XAXAX\r\n", + "ihave XAXAX\r\n", + "list XAXAX\r\n", + "list active XAXAX\r\n", + "list newsgroups XAXAX\r\n", + "listgroup XAXAX\r\n", + "mode XAXAX\r\n", + "mode stream XAXAX\r\n", + "mode reader XAXAX\r\n", + "newgroups XAXAX XAXAX XAXAX XAXAX\r\n", + "newnews XAXAX XAXAX XAXAX XAXAX XAXAX\r\n", + "stat XAXAX\r\n", + "takethis XAXAX\r\n", + "xgtitle XAXAX\r\n", + "xhdr XAXAX\r\n", + "xhdr header XAXAX\r\n", + "xindex XAXAX\r\n", + "xover XAXAX\r\n", + "xover XAXAX\r\n", + "xpat XAXAX XAXAX XAXAX XAXAX\r\n", + "xpath XAXAX\r\n", + "xreplic XAXAX\r\n", + "xthread XAXAX\r\n", + "xgtitle\r\n" + ); + return(@cmdArray); +} + +sub getLogin { # login procedure + my $this = shift; + @login = ("authinfo user $this->{username}\r\nauthinfo pass $this->{password}\r\n"); + return(@login); +} + +sub testMisc { + return(); +} + +sub usage { + print qq~ NNTP module specific options: + -u = Username to use for authentication (default: anonymous) + -v = Password to use for authentication (default: password) + +~; +} + +1; diff -Nru doona-0.7+git20131211/bedmod/pop.pm doona-1.0+git20160212/bedmod/pop.pm --- doona-0.7+git20131211/bedmod/pop.pm 2013-12-11 17:47:43.000000000 +0000 +++ doona-1.0+git20160212/bedmod/pop.pm 2016-09-22 14:15:20.000000000 +0000 @@ -29,7 +29,7 @@ $this->{username} = $special_cfg{'u'}; $this->{password} = $special_cfg{'v'}; $this->{vrfy} = "NOOP\r\n"; - $iaddr = inet_aton( $this->{target} ) || die "Unknown host: $host\n"; + $iaddr = inet_aton( $this->{target} ) || die "Unknown host: $this->{target}\n"; $paddr = sockaddr_in( $this->{port}, $iaddr ) || die "getprotobyname: $!\n"; $proto = getprotobyname('tcp') || die "getprotobyname: $!\n"; socket( SOCKET, PF_INET, SOCK_STREAM, $proto ) || die "socket: $!\n"; diff -Nru doona-0.7+git20131211/bedmod/proxy.pm doona-1.0+git20160212/bedmod/proxy.pm --- doona-0.7+git20131211/bedmod/proxy.pm 2013-12-11 17:47:43.000000000 +0000 +++ doona-1.0+git20160212/bedmod/proxy.pm 2016-09-22 14:15:20.000000000 +0000 @@ -15,6 +15,7 @@ %special_cfg=@_; $this->{proto}="tcp"; + $this->{healthy}=undef; if ($special_cfg{'p'} eq "") { $this->{port}='8080'; @@ -23,12 +24,31 @@ } if ($special_cfg{'d'}) { return; } - $iaddr = inet_aton($this->{target}) || die "Unknown host: $host\n"; + die "Proxy server failed health check!\n" unless($this->health_check()); +# $iaddr = inet_aton($this->{target}) || die "Unknown host: $this->{target}\n"; +# $paddr = sockaddr_in($this->{port}, $iaddr) || die "getprotobyname: $!\n"; +# $proto = getprotobyname('tcp') || die "getprotobyname: $!\n"; +# socket(SOCKET, PF_INET, SOCK_STREAM, $proto) || die "socket: $!\n"; +# connect(SOCKET, $paddr) || die "connection attempt failed: $!\n"; +# send(SOCKET, "HEAD / HTTP/1.0\r\n\r\n", 0) || die "HTTP request failed: $!\n"; +} + +sub health_check { + my $this = shift; + $iaddr = inet_aton($this->{target}) || die "Unknown host: $this->{target}\n"; $paddr = sockaddr_in($this->{port}, $iaddr) || die "getprotobyname: $!\n"; $proto = getprotobyname('tcp') || die "getprotobyname: $!\n"; socket(SOCKET, PF_INET, SOCK_STREAM, $proto) || die "socket: $!\n"; connect(SOCKET, $paddr) || die "connection attempt failed: $!\n"; send(SOCKET, "HEAD / HTTP/1.0\r\n\r\n", 0) || die "HTTP request failed: $!\n"; + my $resp = ; + if (!$this->{healthy}) { + if ($resp =~ /HTTP/) { + $this->{healthy}=$resp; + } + # print "Set healthy: $resp"; + } + return $resp =~ m/$this->{healthy}/; } sub getQuit { @@ -89,6 +109,7 @@ "Proxy-Authorization: XAXAX\r\n\r\n", "ChargeTo: XAXAX\r\n\r\n", "Pragma: XAXAX\r\n\r\n", + "Proxy-Connection: XAXAX\r\n\r\n", "Expect: XAXAX\r\n\r\n", "Range: XAXAX\r\n\r\n", "Range: bytes=1-XAXAX\r\n\r\n", @@ -106,6 +127,10 @@ @login = ( "GET http://127.0.0.2/ HTTP/1.0\r\n", "POST http://127.0.0.2/ HTTP/1.0\r\n", + "CONNECT 127.0.0.1:80 HTTP/1.1\r\n", + "GET http://127.0.0.2/ HTTP/1.1\r\n", + "POST http://127.0.0.2/ HTTP/1.1\r\n", + "CONNECT 127.0.0.2:80 HTTP/1.0\r\n", ); return(@login); } diff -Nru doona-0.7+git20131211/bedmod/rtsp.pm doona-1.0+git20160212/bedmod/rtsp.pm --- doona-0.7+git20131211/bedmod/rtsp.pm 2013-12-11 17:47:43.000000000 +0000 +++ doona-1.0+git20160212/bedmod/rtsp.pm 2016-09-22 14:15:20.000000000 +0000 @@ -6,6 +6,7 @@ sub new{ my $this = {}; + $this->{healthy}=undef; bless $this; return $this; } @@ -17,17 +18,31 @@ $this->{proto}="tcp"; if ($special_cfg{'p'} eq "") { - $this->{port}='80'; + $this->{port}='554'; } else { $this->{port} = $special_cfg{'p'}; } + if ($special_cfg{'d'}) { return; } + die "RTSP server failed health check!\n" unless($this->health_check()); +} - $iaddr = inet_aton($this->{target}) || die "Unknown host: $host\n"; +sub health_check { + my $this = shift; + $iaddr = inet_aton($this->{target}) || die "Unknown host: $this->{target}\n"; $paddr = sockaddr_in($this->{port}, $iaddr) || die "getprotobyname: $!\n"; $proto = getprotobyname('tcp') || die "getprotobyname: $!\n"; socket(SOCKET, PF_INET, SOCK_STREAM, $proto) || die "socket: $!\n"; connect(SOCKET, $paddr) || die "connection attempt failed: $!\n"; - send(SOCKET, "HEAD / HTTP/1.0\r\n\r\n", 0) || die "HTTP request failed: $!\n"; + send(SOCKET, "DESCRIBE / RTSP/1.0\r\n\r\n", 0) || die "HTTP request failed: $!\n"; + my $resp = ; + if (!$this->{healthy}) { + if ($resp =~ /RTSP/) { + $this->{healthy}=$resp; + } + # print "Set healthy: $resp"; + } + #print "DBG: Health resp: $resp\n"; + return $resp =~ m/^$this->{healthy}$/; } sub getQuit{ @@ -38,8 +53,10 @@ my $this = shift; @Loginarray = ( "XAXAX\r\n\r\n", + " XAXAX RTSP/1.0\r\nCSeq: 1\r\n\r\n", "XAXAX / RTSP/1.0\r\nCSeq: 1\r\n\r\n", "XAXAX rtsp://localhost/file.mpg\r\nCSeq: 1\r\n\r\n", + "XAXAX rtsp://localhost/file.mpg RTSP/1.0\r\nCSeq: 1\r\n\r\n", "OPTIONS XAXAX RTSP/1.0\r\nCSeq: 1\r\n\r\n", "OPTIONS /XAXAX RTSP/1.0\r\nCSeq: 1\r\n\r\n", "OPTIONS * XAXAX\r\nCSeq: 1\r\n\r\n", @@ -49,14 +66,32 @@ "DESCRIBE XAXAX://localhost/file.mpg RTSP/1.0\r\nCSeq: 1\r\n\r\n", "DESCRIBE rtsp://XAXAX/file.mpg RTSP/1.0\r\nCSeq: 1\r\n\r\n", "DESCRIBE rtsp://localhost/XAXAX RTSP/1.0\r\nCSeq: 1\r\n\r\n", + "DESCRIBE rtsp://localhost/XAXAX=0 RTSP/1.0\r\nCSeq: 1\r\n\r\n", + "DESCRIBE rtsp://localhost/trackID=XAXAX RTSP/1.0\r\nCSeq: 1\r\n\r\n", + "DESCRIBE rtsp://XAXAX\@localhost/file.mpg RTSP/1.0\r\nCSeq: 1\r\n\r\n", + "DESCRIBE rtsp://XAXAX:pass\@localhost/file.mpg RTSP/1.0\r\nCSeq: 1\r\n\r\n", + "DESCRIBE rtsp://user:XAXAX\@localhost/file.mpg RTSP/1.0\r\nCSeq: 1\r\n\r\n", + "DESCRIBE rtsp://XAXAX:XAXAX\@localhost/file.mpg RTSP/1.0\r\nCSeq: 1\r\n\r\n", + "DESCRIBE rtsp://localhost/file.mpg XAXAX\r\nCSeq: 1\r\n\r\n", + "DESCRIBE rtsp://localhost/file.mpg RTSP/XAXAX\r\nCSeq: 1\r\n\r\n", "SETUP XAXAX RTSP/1.0\r\nCSeq: 1\r\n\r\n", "SETUP XAXAX://localhost/file.mpg RTSP/1.0\r\nCSeq: 1\r\n\r\n", "SETUP rtsp://XAXAX/file.mpg RTSP/1.0\r\nCSeq: 1\r\n\r\n", "SETUP rtsp://localhost/XAXAX RTSP/1.0\r\nCSeq: 1\r\n\r\n", + "SETUP rtsp://localhost/file.mpg RTSP/1.0\r\nCSeq: 7\r\nContent-length: 3200\r\n\r\nXAXAX\r\n\r\n", "PLAY XAXAX RTSP/1.0\r\nCSeq: 1\r\n\r\n", "PLAY XAXAX://localhost/file.mpg RTSP/1.0\r\nCSeq: 1\r\n\r\n", "PLAY rtsp://XAXAX/file.mpg RTSP/1.0\r\nCSeq: 1\r\n\r\n", "PLAY rtsp://localhost/XAXAX RTSP/1.0\r\nCSeq: 1\r\n\r\n", + "PLAY rtsp://localhost/XAXAX=0 RTSP/1.0\r\nCSeq: 1\r\n\r\n", + "PLAY rtsp://localhost/trackID=XAXAX RTSP/1.0\r\nCSeq: 1\r\n\r\n", + "PLAY rtsp://XAXAX\@localhost/file.mpg RTSP/1.0\r\nCSeq: 1\r\n\r\n", + "PLAY rtsp://XAXAX:pass\@localhost/file.mpg RTSP/1.0\r\nCSeq: 1\r\n\r\n", + "PLAY rtsp://user:XAXAX\@localhost/file.mpg RTSP/1.0\r\nCSeq: 1\r\n\r\n", + "PLAY rtsp://XAXAX:XAXAX\@localhost/file.mpg RTSP/1.0\r\nCSeq: 1\r\n\r\n", + "PLAY rtsp://localhost/file.mpg XAXAX\r\nCSeq: 1\r\n\r\n", + "PLAY rtsp://localhost/file.mpg RTSP/XAXAX\r\nCSeq: 1\r\n\r\n", + "PLAY rtsp://localhost/file.mpg RTSP/1.0\r\nCSeq: 7\r\nContent-length: 3200\r\n\r\nXAXAX\r\n\r\n", "PAUSE XAXAX RTSP/1.0\r\nCSeq: 1\r\n\r\n", "PAUSE XAXAX://localhost/file.mpg RTSP/1.0\r\nCSeq: 1\r\n\r\n", "PAUSE rtsp://XAXAX/file.mpg RTSP/1.0\r\nCSeq: 1\r\n\r\n", @@ -97,9 +132,11 @@ "Accept-Charset: XAXAX\r\n\r\n", "Authorization: XAXAX\r\n\r\n", "Authorization: XAXAX", + "Authorization XAXAX: Basic AAAAAA\r\n\r\n", "Authorization: XAXAX:foo\r\n\r\n", "Authorization: foo:XAXAX\r\n\r\n", "Content-length: XAXAX\r\n", + "Content-type: XAXAX\r\n", "Content-Type: text/parameters\r\n\r\nXAXAX: XAXAX\r\n\r\n", "CSeq: XAXAX\r\n\r\n", "From: XAXAX\r\n\r\n", @@ -118,7 +155,14 @@ sub getLogin{ my $this = shift; - @login = ("DESCRIBE rtsp://localhost/media.mp4 RTSP/1.0\r\nCSeq: 1\r\n"); + @login = ( + "ANNOUNCE rtsp://localhost/file.mpg RTSP/1.0\r\nCSeq: 1\r\n", + "DESCRIBE rtsp://localhost/file.mpg RTSP/1.0\r\nCSeq: 1\r\n", + "DESCRIBE rtsp://localhost/file.mpg RTSP/1.0\r\n", + "PLAY rtsp://localhost/file.mpg RTSP/1.0\r\nCSeq: 1\r\n", + "PAUSE rtsp://localhost/file.mpg RTSP/1.0\r\nCSeq: 1\r\n", + "SETUP rtsp://localhost/file.mpg RTSP/1.0\r\nCSeq: 1\r\n", + ); return(@login); } diff -Nru doona-0.7+git20131211/bedmod/smtp.pm doona-1.0+git20160212/bedmod/smtp.pm --- doona-0.7+git20131211/bedmod/smtp.pm 2013-12-11 17:47:43.000000000 +0000 +++ doona-1.0+git20160212/bedmod/smtp.pm 2016-09-22 14:15:20.000000000 +0000 @@ -58,16 +58,16 @@ "ETRN XAXAX\r\n", "ETRN \@XAXAX\r\n", "MAIL FROM: <$this->{mail}>\r\nRCPT TO: \r\n", - "MAIL FROM: <$this->{mail}>\r\nRCPT TO: <$mailaccount> XAXAX\r\n", - "MAIL FROM: <$this->{mail}>\r\nRCPT TO: <$mailaccount> NOTIFY=XAXAX\r\n", - "MAIL FROM: <$this->{mail}>\r\nRCPT TO: <$mailaccount> ORCPT=XAXAX\r\n", + "MAIL FROM: <$this->{mail}>\r\nRCPT TO: <$this->{mail}> XAXAX\r\n", + "MAIL FROM: <$this->{mail}>\r\nRCPT TO: <$this->{mail}> NOTIFY=XAXAX\r\n", + "MAIL FROM: <$this->{mail}>\r\nRCPT TO: <$this->{mail}> ORCPT=XAXAX\r\n", "HELP XAXAX\r\n", "VRFY XAXAX\r\n", "RCTP TO: XAXAX\r\n", "RCTP TO: \r\n", - "RCPT TO: <$mailaccount> XAXAX\r\n", - "RCPT TO: <$mailaccount> NOTIFY=XAXAX\r\n", - "RCPT TO: <$mailaccount> ORCPT=XAXAX\r\n", + "RCPT TO: <$this->{mail}> XAXAX\r\n", + "RCPT TO: <$this->{mail}> NOTIFY=XAXAX\r\n", + "RCPT TO: <$this->{mail}> ORCPT=XAXAX\r\n", "RSET XAXAX\r\n", "AUTH mechanism XAXAX\r\n", "DATA XAXAX\r\n", diff -Nru doona-0.7+git20131211/bedmod/tftp.pm doona-1.0+git20160212/bedmod/tftp.pm --- doona-0.7+git20131211/bedmod/tftp.pm 2013-12-11 17:47:43.000000000 +0000 +++ doona-1.0+git20160212/bedmod/tftp.pm 2016-09-22 14:15:20.000000000 +0000 @@ -47,9 +47,10 @@ "\x00\x01XAXAX\x00netascii\x00", #RRQ "\x00\x01XAXAX\x00octet\x000", #RRQ "\x00\x01XAXAX\x00mail\x00", #RRQ - "\x00\x01fuzz\x00XAXAX\x00", #RRQ + "\x00\x01"."fuzz\x00XAXAX\x00", #RRQ "\x00\x02\x41\x00XAXAX\x00", #WRQ "\x00\x03\x41\x00XAXAX\x00", #DATA? + "\x0c\x0dXAXAX\x00", ); return(@cmdArray); } diff -Nru doona-0.7+git20131211/debian/changelog doona-1.0+git20160212/debian/changelog --- doona-0.7+git20131211/debian/changelog 2016-07-29 12:35:29.000000000 +0000 +++ doona-1.0+git20160212/debian/changelog 2016-09-27 12:47:35.000000000 +0000 @@ -1,3 +1,13 @@ +doona (1.0+git20160212-1) unstable; urgency=medium + + * Team upload. + + [ Sophie Brun ] + * Import new upstream release + * Add a patch to work with Perl 5.22.2-5 (closes #838630) + + -- Gianfranco Costamagna Tue, 27 Sep 2016 14:46:04 +0200 + doona (0.7+git20131211-1) unstable; urgency=low * Initial release (Closes: #832910) diff -Nru doona-0.7+git20131211/debian/doona.1 doona-1.0+git20160212/debian/doona.1 --- doona-0.7+git20131211/debian/doona.1 2016-07-29 12:35:29.000000000 +0000 +++ doona-1.0+git20160212/debian/doona.1 2016-09-27 12:45:33.000000000 +0000 @@ -22,6 +22,9 @@ \fB\-r\fR Resumes fuzzing at test case index .TP +\fB\-k\fR +Keep trying until server passes a health check +.TP \fB\-d\fR Dump test case to stdout (use in combination with \fB\-r\fR) .TP diff -Nru doona-0.7+git20131211/debian/patches/fix-for-perl-5-22.patch doona-1.0+git20160212/debian/patches/fix-for-perl-5-22.patch --- doona-0.7+git20131211/debian/patches/fix-for-perl-5-22.patch 1970-01-01 00:00:00.000000000 +0000 +++ doona-1.0+git20160212/debian/patches/fix-for-perl-5-22.patch 2016-09-27 12:47:17.000000000 +0000 @@ -0,0 +1,20 @@ +Description: Fix to work with Perl 5.22.2-5 + '.' has been removed from @INC by default in Perl 5.22.2-5 in debian + (fixes 588017) +Origin: upstream, https://github.com/wireghoul/doona/issues/9 +Bug: https://github.com/wireghoul/doona/issues/9 +Bug-Kali: https://bugs.kali.org/view.php?id=3608 +Last-Update: 2016-09-22 +--- +This patch header follows DEP-3: http://dep.debian.net/deps/dep3/ +--- a/doona.pl ++++ b/doona.pl +@@ -6,6 +6,8 @@ + # + # Doona is a BED fork maintained by wireghoul ( www.justanotherhacker.com ) + # BED was written by mjm ( www.codito.de ) and snakebyte ( www.snake-basket.de ) ++use FindBin; ++use lib $FindBin::Bin; + use Getopt::Std; + use Socket; + use Config; diff -Nru doona-0.7+git20131211/debian/patches/series doona-1.0+git20160212/debian/patches/series --- doona-0.7+git20131211/debian/patches/series 1970-01-01 00:00:00.000000000 +0000 +++ doona-1.0+git20160212/debian/patches/series 2016-09-27 12:47:17.000000000 +0000 @@ -0,0 +1 @@ +fix-for-perl-5-22.patch diff -Nru doona-0.7+git20131211/Docs/CHANGES doona-1.0+git20160212/Docs/CHANGES --- doona-0.7+git20131211/Docs/CHANGES 2013-12-11 17:47:43.000000000 +0000 +++ doona-1.0+git20160212/Docs/CHANGES 2016-09-22 14:15:20.000000000 +0000 @@ -1,3 +1,20 @@ +[ Coming in 1.0 ] +- Added health check support (-c flag) +- Added keep trying support (-k flag) +- Added more fuzz cases (http, rtsp, tftp, proxy) +- Added more fuzz data + +[ 0.9 ] +- Added NNTP module (from @bcoles) +- Added DICT module (from @bcoles) +- More http fuzz cases +- Fixed bug in test case dump + +[ 0.8 ] +- Fixed some bugs in the smtp module +- Fixed faulty error messages in pop, http, ftp, rtsp and proxy modules +- Added more ftp test cases + [ 0.7 ] - resolved the need for a hardcoded plugin list - added max requests option to allow parallel execution (easier than hacking in thread support) diff -Nru doona-0.7+git20131211/Docs/dummy.pm doona-1.0+git20160212/Docs/dummy.pm --- doona-0.7+git20131211/Docs/dummy.pm 2013-12-11 17:47:43.000000000 +0000 +++ doona-1.0+git20160212/Docs/dummy.pm 2016-09-22 14:15:20.000000000 +0000 @@ -1,120 +1,113 @@ package bedmod::dummy; use Socket; -# Example plugin for bed2 -# -# Feel free to fill in the gaps ... :) -# -# search bed.pl for "dummy" to see what you need to -# change to include your module -# (just one entry ... no need to be scared *g* ) +# Example plugin for a doona module +# Replace the use of "dummy" with your module name +# Copy the file to bedmod as # -# \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ # create a new instance of this object sub new{ - my $this = {}; + my $this = {}; - # define everything you might need - $this->{dummy} = undef; - bless $this; - return $this; + # define everything you might need + $this->{something} = undef; + bless $this; + return $this; } -# \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ # initialise some parameters sub init{ - my $this = shift; - %special_cfg=@_; + my $this = shift; + %special_cfg=@_; # Set protocol tcp/udp - $this->{proto} = "tcp"; + $this->{proto} = "tcp"; # insert your default port here... if ($special_cfg{'p'} eq "") { $this->{port}='110'; } else { $this->{port} = $special_cfg{'p'}; } - # verify you got everything you need, - # $special_cfg will provide you the commandline - # switches from u, v, w and x - if ( $special_cfg{'u'} eq "") { - print qq~ - Parameters for the dummy plugin: - - -u - -~; - exit(1); - } - - # set info nessecairy for for your module.. - $this->{dummy} = $special_cfg{'u'}; - - # how can bed check that the server is still alive - # This string will simply be send to the server - # ( server should reply something to this ) - $this->{vrfy} = "HELP\r\n"; + # verify you got everything you need, + # $special_cfg will provide you the commandline + # switches from u, v, w and x + if ( $special_cfg{'u'} eq "") { + &usage; + } + + # set info necessary for for your module.. + $this->{u} = $special_cfg{'u'}; + + # check that the server is still alive + die "Server failed health check!\n" unless($this->health_check()); +} + +# Perform a common action such as authenticating here +# if it this check assume it has crashed +sub health_check { + # Should send/receive packet and match expected behaviour to be considered healthy + # return true to continue fuzzing + return 1; } -# \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ # how to quit ? sub getQuit{ - # what to send to close the connection the right way - return("QUIT\r\n"); + # what to send to close the connection the right way + return("QUIT\r\n"); } -# \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ -# what to test without doing a login before -# ..mainly the login stuff *g* +# what to test without authenticating +# Typically the login stuff sub getLoginarray { - my $this = shift; - @Loginarray = ( - "USER XAXAX\r\n", - "USER $this->{username}\r\nPASS XAXAX\r\n" - ) - return (@Loginarray); + my $this = shift; + @Loginarray = ( + "USER XAXAX\r\n", + "USER $this->{username}\r\nPASS XAXAX\r\n" + ); + return (@Loginarray); } -# \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ # which commands does this protocol know ? sub getCommandarray { - my $this = shift; - # the XAXAX will be replaced with the buffer overflow / format string data - # place every command in this array you want to test - @cmdArray = ( - "foo XAXAX\r\n", - "bar XAXAX\r\n", - "XAXAX\r\n" - ); - return(@cmdArray); + my $this = shift; + # the XAXAX will be replaced with the buffer overflow / format string data + # place every command in this array you want to test + @cmdArray = ( + "foo XAXAX\r\n", + "bar XAXAX\r\n", + "XAXAX\r\n" + ); + return(@cmdArray); } -# \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ # what to send to login ? -sub getLogin{ # login procedure - my $this = shift; - @login = ( - "Hi, I am a dummy\r\n", - "This is my pass: foobar\r\n" - ); - return(@login); +sub getLogin{ # login procedure + my $this = shift; + @login = ( + "Hi, I am a dummy\r\n", + "This is my pass: foobar\r\n" + ); + return(@login); } -# \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ # here we can test everything besides buffer overflows and format strings sub testMisc{ - # Insert your favourite directory traversal bug here :) - my $this = shift; - return(); + # Insert your favourite directory traversal bug here :) + my $this = shift; + return(); } # Module specific help goes here # Leave an empty sub if there is no module specific help sub usage { - print qq~ Module spacific help: + print qq~ + Parameters for the dummy plugin: + + -u ~; +exit(1); } 1; diff -Nru doona-0.7+git20131211/doona.pl doona-1.0+git20160212/doona.pl --- doona-0.7+git20131211/doona.pl 2013-12-11 17:47:43.000000000 +0000 +++ doona-1.0+git20160212/doona.pl 2016-09-22 14:15:20.000000000 +0000 @@ -13,7 +13,7 @@ #use strict; #use warnings; my $SOCKET; -my $VERSION = '0.7'; +my $VERSION = '1.0'; $SIG{'INT'} = \&sigHandler; $SIG{'TERM'} = \&sigHandler; @@ -23,8 +23,18 @@ # the hope is to overwrite a return pointer on the stack, # making the server execute invalid code and crash -my @overflowstrings = ("A" x 33, "A" x 254, "A" x 255, "A" x 1023, "A" x 1024, "A" x 2047, "A" x 2048, "A" x 5000, "A" x 10000, "\\" x 200, "/" x 200, " " x 9000, "AA " x 200); -my @formatstrings = ("%s" x 4, "%s%p%x%d", "%s" x 8, "%s" x 15, "%s" x 30, "%.1024d", "%.2048d", "%.4096d", '%@' x 53, "%.16i705u%2\$hn", "%#123456x"); +my @overflowstrings = ( + "A" x 33, "A" x 254, "A" x 255, "A" x 256, "A" x 257, "A" x 1023, "A" x 1024, "A" x 1025, "A" x 1026, + "A" x 1044, "A" x 2047, "A" x 2048, "A" x 2049, "A" x 2068, "A" x 3092, "A" x 4116, "A" x 5140, + "A" x 6164, "A" x 7188, "A" x 8212, "A" x 9236, "A" x 10260, "A" x 11284, "A" x 12308, "A" x 13332, + "A" x 14356, "A" x 15380, + "\\" x 200, "\\" x 255, "\\" x 9000, "/" x 200, "/" x 256, "/" x 9000, + "A/" x 256, "AA/" x 256, "AAA/" x 256, "AAAA/" x 256, + "." x 200, "." x 255, "." x 9000, " " x 9000, "AA " x 200, +); +my @formatstrings = ( + "%s" x 4, "%s%p%x%d", "%s" x 8, "%s" x 15, "%s" x 30, "%.1024d", "%.2048d", "%.4096d", '%@' x 53, "%.16i705u%2\$hn", "%#123456x" +); # three ansi overflows, two ansi format strings, two OEM Format Strings my @unicodestrings = ("\x99" x 4, "\x99" x 512, "\x99" x 1024, "\xCD" x 10, "\xCD" x 40, "\xCB" x 10, "\xCB"x40); @@ -41,10 +51,10 @@ my @miscstrings = ("/", "\\", "%0xa", " ", "+", "<", ">", "<>", "%", "-", "+", "*", ".", ":", "&", "%u000", "\t", "\r", "\r\n", "\n"); my $idx = 0; my $prevfuzz = ''; -print "\n Doona $VERSION by Wireghoul (www.justanotherhacker.com) based on BED by mjm and snakebyte\n\n"; +print "\n Doona $VERSION by Wireghoul (www.justanotherhacker.com)\n\n"; # get the parameters we need for every test -getopts('m:s:t:o:p:r:u:v:w:x:M:dh'); +getopts('m:s:t:o:p:r:u:v:w:x:M:c:dhk'); $opt_s = $opt_m if ($opt_m); &usage unless($opt_s); $opt_s = lc($opt_s); # convert it to lowercase @@ -66,6 +76,8 @@ "p" => "$opt_p", # port "r" => "$opt_r", # resume test case number 'M' => "$opt_M", # Max requests to perform + 'c' => "$opt_c", # How often do we call health_check + 'k' => "$opt_k", # Keep trying until a healt check passes 'd' => "$opt_d", # Print fuzz case to screen and quit "u" => "$opt_u", # special parameters for the module... "v" => "$opt_v", @@ -135,7 +147,7 @@ my @testArray = @_; my $command; my $socktype; - if ( $module->{proto} eq "udp" ) {i + if ( $module->{proto} eq "udp" ) { $socktype = SOCK_DGRAM; } else { $socktype = SOCK_STREAM; @@ -166,7 +178,7 @@ $command = $cmd; $command =~ s/XAXAX/$LS/ig; # prepare the string if ($special_cfg{'d'}) { - print "\nFuzz case: --copy--\n"; + print "\nFuzz case ($idx)\n--copy--\n"; } else { my $iaddr = inet_aton($module->{target}) || die "Unknown host: $module->{target}\n"; my $paddr = sockaddr_in($module->{port}, $iaddr) || die "getprotobyname: $!\n"; @@ -188,7 +200,7 @@ } #} - if ($special_cfg{'d'}) { print "$command\\r\\n\n--cut--\n"; exit; } + if ($special_cfg{'d'}) { $command =~ s/\n/\\n/g;$command =~ s/\r/\\r/g; print "$command\n--cut--\n"; exit; } send(SOCKET, $command, 0); # send the attack and verify that the server is still alive # Is there a possibility to check within connection? if ($module->{vrfy} ne "") { @@ -207,6 +219,18 @@ } sleep($module->{timeout}); # some servers would kick us for too fast rogins + if ($special_cfg{'c'} && $idx % $special_cfg{'c'} == 0) { + # Health check + if ($special_cfg{'k'}) { + do { + print "\r---Waiting for server to pass health check ($idx)---"; + sleep 1; + } until $module->health_check() + } else { + die "Health check failed! ($idx)\n" unless($module->health_check()); + } + print ':' + } } print " ($idx)\n"; } @@ -220,10 +244,12 @@ $0 -m [module] -m = ~ . join('/', map(uc, @modules)). qq~ + -c = Execute a health check after every fuzz cases -t = Host to check (default: localhost) -p = Port to connect to (default: module specific standard port) -o = seconds to wait after each test (default: 2 seconds) -r = Resumes fuzzing at test case index + -k = Keep trying until server passes a health check -d = Dump test case to stdout (use in combination with -r) -M = Exit after executing number of fuzz cases -h = Help (this text) diff -Nru doona-0.7+git20131211/README doona-1.0+git20160212/README --- doona-0.7+git20131211/README 2013-12-11 17:47:43.000000000 +0000 +++ doona-1.0+git20160212/README 2016-09-22 14:15:20.000000000 +0000 @@ -15,7 +15,9 @@ @Wireghoul .:: Version ::. - + 1.0 - New command line switches, more fuzz data and fuzz cases + 0.9 - Bugfixes, more fuzz cases and new modules + 0.8 - Bugfixes and more fuzz cases 0.7 - Multi verb support, more fuzz cases and bug fixes 0.6 - First official doona release 0.5 - Fork from BED @@ -40,10 +42,5 @@ BED was written by: Eric Sesterhenn aka. 'Snakebyte' - -Mail: snakebyte@gmx.de - -Web: www.snake-basket.de - Martin J. Muench aka. 'mjm' - -Mail: mjm@codito.de - -Web: www.codito.de