#!/usr/bin/perl # Attempt to figure out when a domain was registered. # Copyright 2006, Kees Cook , http://outflux.net/ # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 # of the License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software Foundation, # Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA # http://www.gnu.org/copyleft/gpl.html use strict; use warnings; use Net::Whois::Raw; # qw( $TIMEOUT ); use Date::Manip; use Data::Dumper; sub date_extract($) { my ($str) = @_; # Look for common DD-Mmm-YY(YY) first if ($str=~/(\d\d-\D{3}-\d{2,4})/) { my $date = ParseDate($1); return $date if ($date); } # Look for common YYYY-MM-DD next if ($str=~/(\d{4}-\d\d-\d\d)/) { my $date = ParseDate($1); return $date if ($date); } # Fallback to aggressive word-splitting my @forward = split(/\b/,$str); while (@forward) { my @backward=@forward; while (@backward) { my $str=join("",@backward); # skip garbage that may be parsed as "empty" if ($str=~/[a-z0-9]/i) { warn "\t\tParsing: '$str'\n"; my $date = ParseDate($str); return $date if ($date); } pop(@backward); } shift(@forward); } return 0; } sub date_from_servers($) { my ($servers)=@_; my $date=0; foreach my $response (@{ $servers }) { # in the hash: level, text, srv print STDERR Dumper($response); # All the prefixes I've found (including some JP UTF8 sequences) while ($response->{'text'} =~ /^\s*(?:\[\$BEPO?G\/7nF|\(B\]|(?:(?:domain|record)\s*){0,2}(?:(?:activat|creat|register)ed|(?:activa|crea|registra)tion)(?:\s+(?:on|date))?)[:\.\s]*(?!.*registrar)(.*)/img) { my $str=$1; warn "\tMatched: '$str'\n"; $date = date_extract($str); return $date if ($date); } } return $date; } while (defined($ARGV[0])) { my $domain=shift @ARGV; my $date=0; eval { # Try first level only, then go deeper my ($text,$srv) = get_whois($domain, undef, "QRY_FIRST"); $date = date_from_servers([{ level => '0', 'text' => $text, 'srv' => $srv }]); if (!$date) { my $servers = get_whois($domain, undef, "QRY_ALL"); # Drop the first level, since we already failed to scan it shift(@{ $servers }) if (scalar(@{ $servers })>0); $date = date_from_servers($servers); } }; if ($@) { $date=0; warn "Lookup exploded: $@\n"; } if ($date) { print "'$domain' created on: ".UnixDate($date,"%Y-%m-%d")."\n"; } else { print "Nothing known about '$domain'\n"; } }