Sample scripts

Here are a few interesting (and useful) hacking related scripts.

Timer

#!/usr/bin/env bash

if [ "$1" == "" ]; then
        echo "Please enter starting secconds for countdown timer."
        exit 0
fi

wait_time=$1 # seconds


echo ""
temp_cnt=${wait_time}
while [[ ${temp_cnt} -gt 0 ]];
do
        printf "\r%2d second(s)" ${temp_cnt}
            sleep 1
            ((temp_cnt--))
        done
        echo ""

Perl ioT Scanner

use AnyEvent::HTTP;
use Data::Dumper;
use MIME::Base64;
use Digest::SHA;
use JSON;

my $devs = {};
my $body;
my $headers = {};
my $devType = "";
my @ipList = ();
my $ptr = -1;
my $httpPort = 80;
my $debug = 0;
my $ip = $ARGV[0];
if ($ARGV[0] =~ /^\-?h/) {
    print "perl iotScanner.pl <ipRanges> [devCfgUrl=<devCfgUrl>]\n";
    exit;
}
my $devCfgUrl = "";
for ($i=1; $i<=$#ARGV; $i++) {
    if ($ARGV[$i] =~ /devCfgUrl=/) {
        $devCfgUrl = $';
    } elsif ($ARGV[$i] =~ /^debug/) {
        if ($' =~ /^\=/) {
            $debug = $';
        } else {
            $debug = 1;
        }
        print "debug=$debug\n";
    }
}
readDevices();

foreach $e (split(/\,/, $ARGV[0])) {
    if ($e =~ /\-/) {
        $start = $`;
        $end   = $';
        print "$start|$end|\n";
        for ($i = ip2num($start); $i<=ip2num($end); $i++) {
            push @ipList, num2ip($i);
        }
    } else {
        push @ipList, $e;
    }
}
my $numOfIps = scalar @ipList;
my $numOfResults = 0;
my $i;
my $w = AnyEvent->condvar; #

for ($i=0; $i<10; $i++) {
kickoff();
}

$w->recv;

sub kickoff {
    $ptr ++;
    if (! defined $ipList[$ptr]) { return; }
    check({ip => $ipList[$ptr], stage => ""});
}

sub check_login {
    my $ctx = shift;
    my $url = composeURL($ctx);
    $headers = {};
    my $dev = $ctx->{dev};
    if ($dev->{auth}->[0] eq "basic") {
        if ($dev->{auth}->[1] eq "") {
            http_get $url, sub {
                my $status = $_[1]->{Status};
                if ($status == 200) {
                    print "device $ctx->{ip} is of type $ctx->{devType} still has default password\n";
                } else {
                    print "device $ctx->{ip} of type $ctx->{devType} has changed password\n";
                }
                $numOfResults ++; if ($numOfResults == $numOfIps) { exit;} else {kickoff();}
            };
            return;
        }
        $tmp = "Basic " . encode_base64($dev->{auth}->[1]); # am9objpyYXBpZDc=\r\n
        chomp($tmp);
        $headers->{Authorization} = $tmp;
    } elsif ($dev->{auth}->[0] eq "form") {
        my $subtype = $dev->{auth}->[1];
        my $postdata = $dev->{auth}->[2];
        if (defined $dev->{extractFormData}) {
            foreach $e (@{$dev->{extractFormData}}) {
                if ($body =~ /$e/) {
                    if (! defined $ctx->{extractedData}) { $ctx->{extractedData} = [];}
                    push @{$ctx->{extractedData}}, $1;
                }
            }
        }
        if ($subtype =~ /^sub/) {
            $subtype = "";
            $postdata = substitute($postdata, $ctx->{extractedData});
        }
        if ($subtype eq "") {
            http_post $url, $postdata, sub {
                #print "body=$_[0]\n";
                my $status = $_[1]->{Status};
                my $body = $_[0];
                if ($dev->{auth}->[3] eq "body") {
                    if ($dev->{auth}->[4] eq "regex") {
                        $pattern = $dev->{auth}->[5];
                        if ($body =~ /$pattern/) {
                            print "device $ctx->{ip} is of type $ctx->{devType} still has default password\n";
                        } else {
                            print "device $ctx->{ip} of type $ctx->{devType} has changed password\n";
                        }
                        $numOfResults ++; if ($numOfResults == $numOfIps) { exit;} else {kickoff();}
                    } elsif ($dev->{auth}->[4] eq "!substr") {
                        if (index($body, $dev->{auth}->[5]) < 0) {
                            print "device $ctx->{ip} is of type $ctx->{devType} still has default password\n";
                        } else {
                            print "device $ctx->{ip} of type $ctx->{devType} has changed password\n";
                        }
                        $numOfResults ++; if ($numOfResults == $numOfIps) { exit;} else {kickoff();}
                    }
                } 
            };
        } 
        
        return;
    }
    
    if ($debug) {print "checking login on $url\n";}
    http_get $url, headers=> $headers, sub {
        my $status = $_[1]->{Status};
        if ($debug) {print "check_login status=$status\n";}
        if ($status == 200) {
            if ($ctx->{dev}->{auth}->[0] eq "basic") {
                print "device $ctx->{ip} is of type $ctx->{devType} still has default password\n";
            } elsif ($ctx->{dev}->{auth}->[0] eq "expect200") {
                print "device $ctx->{ip} is of type $ctx->{devType}  doesnot have any password\n";
            }
        } elsif ($status == 301 || $status == 302) {
            print "device $ctx->{ip} is of type $ctx->{devType} still has default password\n";
        } elsif ($status == 401 && $ctx->{dev}->{auth}->[0] eq "basic") {
            print "device $ctx->{ip} is of type $ctx->{devType} has changed password\n";
        } else {
            print "device $ctx->{ip}: unexpected resp code $status\n";
        }
        $numOfResults ++; if ($numOfResults == $numOfIps) { exit;} else {kickoff();}
    };
}

sub composeURL {
    my $ctx = shift;
    my $portStr = ($httpPort != 80)? ":$httpPort" : "";
    if (! defined $ctx->{url}) {
        return "http://$ctx->{ip}$portStr/";
    } elsif ($ctx->{url} =~ /^https?:/) {
        return $ctx->{url};
    } elsif ($ctx->{url} =~ /^\//) {
        return "http://$ctx->{ip}$portStr$ctx->{url}";
    } elsif ($ctx->{url} =~ /^\//) {
        print "unexpected partial url $ctx->{url}\n";
        return;
    }
}

sub search4devType { #with $body and $header
    my $e;
    my $i;
    my $j;
    my $len;
    my $len2;
    my $p;
    my $q;
    foreach $e (keys %{$devs}) {
        $p = $devs->{$e}->{devTypePattern};
        #$len = scalar @{$devs->{$e}->{devTypePattern}};
        if ($p->[0]->[0] eq "header") {
            $tmp = $headers->{$p->[0]->[1]};
        } elsif ($p->[0]->[0] eq "body") {
            if ($p->[0]->[1] eq "") {
                $tmp = $body;
            } else {
                $pattern = "<$p->[0]->[1]>(.*?)</$p->[0]->[1]>";
                if ($body =~ /$pattern/) {
                    $tmp = $1;
                } else {
                    #print "didnot find pattern $pattern\n";
                    next;
                }
            }
        }
        $p = $devs->{$e}->{devTypePattern}->[1];
        $len = scalar @{$p};
        if ($p->[0] eq "==") {
            if ($tmp eq $p->[1]) {
                return $e;
            }
        } elsif ($p->[0] =~ /^regex/) {
            for ($i=1; $i < $len; $i++) {
                $pattern = $p->[$i];
                if ($tmp !~ /$pattern/) { last; }
            }
            if ($i == $len) { return $e;}
        } elsif ($p->[0] eq "substr") {
            if (index($tmp,$p->[1]) >= 0) {
                return $e;
            }
        }
    }
    return "";
}

sub check {
    my $ctx = shift;
    my $url = composeURL($ctx);
    if ($ctx->{stage} eq "initialClickLoginPage") {
        return check_init_login($ctx);
    }
    http_get $url,  sub {
        ($body, $headers) = @_;
        my $status = $headers->{Status};
        if ($debug) {print "got status=$status for $url\n";}
        if ($status == 301 || $status == 302) {
            if ($debug) {print "http redirect to $headers->{location}\n";}
            $ctx->{url} = $headers->{location};
            return check($ctx);
        } elsif ($status == 401) {
            $devType = search4devType();
            if ($devType eq "") {
                print "$ctx->{ip}: didnot find dev type after trying all devices\n";
                $numOfResults ++; if ($numOfResults == $numOfIps) { exit;} else {kickoff();}
                kickoff();
                return;
            }
            if ($debug) {print "devType=$devType\n";}
            $ctx->{devType} = $devType;
            $ctx->{url} = $url;
            $ctx->{dev} = $devs->{$devType};
            return check_login($ctx);
        } elsif ($status == 200) {
            $devType = search4devType();
            if ($devType ne "") {
                if ($debug) {print "devType=$devType\n";}
                $ctx->{dev} = $devs->{$devType};
                $ctx->{devType} = $devType;
                goto gotoCheckLogin;
            } elsif ($ctx->{stage} eq "look4LoginPage") { #come from refreshUrl
                #pass through
            } elsif ($ctx->{stage} eq "") {
                $url = getRefreshUrl($ctx->{url});
                #print "url=$url\n";
                if ($url ne "") {
                    $ctx->{url} = $url;
                    $ctx->{stage} = "look4LoginPage";
                    return check($ctx);
                }
            }
        } elsif ($status == 404) {
            print "canot find dev type for $ctx->{ip} due to 404 response\n";
            $numOfResults ++; if ($numOfResults == $numOfIps) { exit;} else {kickoff();}
            return;
        } else {
            if ($status == 595) {
                print "device $ctx->{ip}: failed to establish TCP connection\n";
            } else {
                print "unexpected status code $status for ip $ctx->{ip}\n";
            }
            $numOfResults ++; if ($numOfResults == $numOfIps) { exit;} else {kickoff();}
            return;
        }
        $devType = search4devType();
        if ($devType eq "") {
            print "$ctx->{ip}: didnot find dev type after trying all devices\n";
            $numOfResults ++; if ($numOfResults == $numOfIps) { exit;} else {kickoff();}
            kickoff();
            return;
        }
        #print "devType=$devType\n";
        $ctx->{dev} = $devs->{$devType};
        $ctx->{devType} = $devType;
        if ($status == 401) {
            $ctx->{url}   = $url;
            return check_login($ctx);
        }
gotoCheckLogin:
        if (defined $ctx->{dev}->{loginUrlPattern}) {
            $pattern = $ctx->{dev}->{loginUrlPattern};
            if ($body =~ /$pattern/) {
                $ctx->{url}   = $1;
                #print "url=$1\n";
                return check_login($ctx);
            }
        } else {#nextUrl
            $tmp = $ctx->{dev}->{nextUrl};
            if ($tmp->[0] eq "string") {
                if ($tmp->[1] ne "") {
                    $ctx->{url}   = $tmp->[1];
                } else {
                    $ctx->{url} = $url;
                }
            }
        }
        #$ctx->{url} = $ctx->{dev}->{nextUrl};
        check_login($ctx);
    };
}

sub getRefreshUrl {
    my $prevUrl = shift;
    my $newUrl;
    my $tmpBody = $body;
    while($tmpBody =~ /\<META\s+[^\>]*url=(.*?)>/i) {
        $tmpBody = $';
        $tmp = $1;
        if ($tmp =~ /^[\"\'](.*?)[\"\']/) {
            $newUrl = $1; last;
        } elsif ($tmp =~ /^(.*?)[\>\"\s]/) {
            $newUrl = $1; last;
        }
    }
    #print "newUrl=$newUrl\n";
    if ($newUrl ne "" && $newUrl ne $prevUrl) {
        return $newUrl;
    } else {
        return "";
    }
}

sub match {
    my $title;
    if ($body !~ /<title>(.*?)<\/title>/) {
        return "";
    }
    $title = $1;
    my $e;
    my $f;
    foreach $e (keys %{$devs}) {
        my $patterns = $devs->{$e}->{devTypePattern};
        my $isMatch = 1;
        #print "e=$e\n";
        foreach $f (@{$patterns}) {
            #print "f=$f\n";
            if ($title !~ /$f/) {
                $isMatch = 0; last;
            }
        }
        if ($isMatch) { return $e; }
    }
    return "";
}

sub search4login {
    my $ctx = shift;
    $devType = match();
    #print "devType=$devType|\n";
    if ($devType eq "") { 
        print "didnot find devType for $ctx->{ip}\n";
        $numOfResults ++; if ($numOfResults == $numOfIps) { exit;} else {kickoff();}
        return; }
    my $pattern = $devs->{$devType}->{loginUrlPattern};
    #printf "%d pattern=$pattern\n", length($body);
    if ($body =~ /$pattern/) {
        #print "found url\n";
        return $1;
    }
    return "";
}

sub readDevices {
    #open FD, "devices.cfg" || die "Failed to open devices.cfg $!\n";
    if ($devCfgUrl ne "") {
        #partially from http://www.perlmonks.org/?node_id=1078704
        my $ua = new LWP::UserAgent;
        $ua->agent('Mozilla/5.0');
        $ua->ssl_opts( verify_hostname => 0 ,SSL_verify_mode => 0x00);
        my $req = new HTTP::Request('GET',$devCfgUrl);
        my $res = $ua->request($req);
        $buff = $res->{_content};
    } else {
        open FD, "devices.cfg" || die "Failed to open devices.cfg $!\n";
        read FD, $buff, 0x100000;
        close FD;
    }
    $devs = decode_json($buff);
}
sub substitute {
    my ($str, $p) = @_;
    my $ret;
    while ($str =~ /\$(\d+)/) {
        $ret .= $` . $p->[$1 - 1];
        $str = $';
    }
    $ret .= $str;
    return $ret;
}

sub ip2num {
    my @a = split(/\./, $_[0]);
    return ($a[0]<<24) + ($a[1] << 16) + ($a[2] << 8) + $a[3];
}

sub num2ip {
    my $n = shift;
    return sprintf("%d.%d.%d.%d", ($n >> 24), ($n >> 16) & 0xff, ($n >> 8) & 0xff, $n & 0xff);
}

__END__
--- to handle page 404