Skip to content

Instantly share code, notes, and snippets.

@m0rb
Last active February 24, 2024 17:21
Show Gist options
  • Save m0rb/96a6dda65ddaae3dc30228dd8c9199e5 to your computer and use it in GitHub Desktop.
Save m0rb/96a6dda65ddaae3dc30228dd8c9199e5 to your computer and use it in GitHub Desktop.
virustotal auto-uploader for stupid botnet droppers
#!/usr/bin/perl -w
use strict;
use warnings;
use utf8;
use DateTime;
use JSON;
use File::Tail;
use File::Basename;
use LWP::UserAgent;
use URL::Encode qw(encode_entities);
use HTML::Entities;
use Sys::Syslog;
use Data::Dumper;
use Digest::SHA;
use Parallel::ForkManager;
binmode(STDOUT,":utf8");
my $forky = Parallel::ForkManager->new(4);
my $pid = $$;
my ($next,$debug,$timeout,@files,@i,%h);
my $apikey = "";
my $vtbase = "https://www.virustotal.com/api/v3/files";
my $basedir = "malware/";
my $mal = LWP::UserAgent->new(agent=> "Mozilla/5.0",show_progress=>1);
$mal->proxy([qw(http https)] => 'socks://127.0.0.1:9050');
my $vt = LWP::UserAgent->new(show_progress=>1);
$vt->default_header('x-apikey'=>$apikey);
push(@files,File::Tail->new(name=>"/var/log/nginx/access.log",debug=>$debug,reset_tail=>0));
while (1) {
my ($nfound,$timeleft,@pending) = File::Tail::select(undef,undef,undef,$timeout,@files);
unless ($nfound) {} else {
foreach (@pending) {
my $line = $_->read;
unless ( $line =~ /192\.168\./ ) {
if ( $line =~ /((wget|curl).*?(?=\;))/ ) {
my $out = url_decode_utf8($1); $out =~ s/(wget|curl -O )//; $out =~ s/\$\{IFS\}//;
$out =~ s/-O.*//; $out =~ s/(\ |\;.*)//g;
push @i,$out;
}
FORKY:
foreach ( my @u = grep { ! $h{ $_ }++ } @i) {
my $fn = basename($_); $fn =~ s/\ //g;
my $time = DateTime->now->epoch;
my $dir = $basedir.$time;
mkdir $dir;
my $file = "$dir/$fn";
$forky->start and next FORKY;
my $resp = $mal->get($_, ":content_file" => "$dir/$fn" );
if ( $resp->is_success ) {
my $sha256 = Digest::SHA->new(256)->addfile("$dir/$fn")->hexdigest;
openlog($pid.'[BOT]','nowait','LOG_LOCAL0');
syslog("NOTICE","Alert! Grabbed $_ ($time/$fn : $sha256)");
print "$_ : $sha256\n";
my $vtquery = $vt->get($vtbase."/".$sha256);
unless ($vtquery->is_success) {
if ($vtquery->content =~ /NotFoundError/i) {
my $idiot = $vt->post($vtbase, Content_Type =>
"form-data", Content => [ file => [ "$dir/$fn" ] ] );
$line =~ s/\"(\d.*)\"$//g;
my %compost = (data=>{type=>"comment",attributes=>{text=>encode_entities($line)}});
select(undef,undef,undef,15);
my $comment = $vt->post($vtbase."/".$sha256."/comments", Content => encode_json(\%compost)
);
syslog("NOTICE","Uploaded $sha256 to VirusTotal");
}
} else {
print "$sha256 is already on VT.\n";
}
closelog;
}
}
$forky->finish;
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment