| Malware documentation | Contained in the Malware distribution. |
Malware::Parser::NormanSandBoxLive - Perl extension for parsing norman sandbox email digests
my $n = Malware::Parser::NormanSandBoxLive->new( -zip => $f, -cleanup => 1);
my (@http,@bn);
foreach my $m (@{$n->malware()}){
if(my @a = $m->returnConnectionsByLayer_array(-type => 'url', -layer => 7, -protocol => 'http')){
push(@http,@a) if(@a);
}
if(my @a = $m->returnConnectionsByLayer_array(-type => 'dns', -layer => 7, -protocol => 'irc')){
push(@bn,@a) if(@a);
}
}
warn Dumper(@http);
warn Dumper(@bn);
This module is a parser for NormanSandBoxLive email digests (does the web too...but email is better if you can get it). From here you can take the malware behavior and use it to create detection rules etc...
my $n = Malware::Parser::NormanSandBoxLive->new( -auto => 1, # default, do we want to auto extract the zip and parse? (yes, rgc, i am that lazy ;-) -zip => $PATH_TO_ZIPFILE, -path => $PATH_TO_SANDBOX_FILE # use this if you dont have the zip, filename must start with 'sandbox_' -cleanup => 1, # clean up the zip file and its extractions after? }
Uses Archive::Extract to open up the zip file (used internally if you -auto on new()) and sets the path of the sandbox file.
$n->zip($zipFilePath); $n->extractFromZip();
Returns 1 on sucess, dies() on error
Parses the main text file and pushes each malware object it creates into $self->malware()
Returns 1 on success, dies() if the file can't be opened
Sets and Returns the zipFile path
Sets and Returns the sandbox_ file path
Sets and Returns auto property (auto parse)
Sets and Returns the cleanup property (do we unlink() files on parse?)
Stores an arrayref of malware objects.
Accepts Malware Objects or return ($errstr,undef)
Returns arrayref of malware objects
Stores an array of strings that hold unknown classifications
Accepts strings
Returns arrayref of strings
Malware,Net::Connection::Simple,Net::Connection::Simple,Time::Timestamp
Wes Young, <saxguard9-cpan@yahoo.com>
Copyright (C) 2006 by Wes Young
This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself, either Perl version 5.8.7 or, at your option, any later version of Perl 5 you may have available.
| Malware documentation | Contained in the Malware distribution. |
package Malware::Parser::NormanSandBoxLive;
use 5.008007; use strict; use warnings; use Malware; use Archive::Extract; use Net::Protocol::Simple; use Net::Connection::Simple; use Class::ParmList qw(parse_parms); use constant AUTO => 1; # auto extract and parse? use constant CLEAN => 1; # auto unlink() files? our $VERSION = '1.02';
sub new { my ($class,%parms) = @_; my $self = {}; bless($self,$class); $self->init(%parms); return $self; } sub init { my ($self,%parms) = @_; $parms{-auto} = AUTO() if(!$parms{-auto}); $self->zip( $parms{-zip}); $self->path( $parms{-path}); $self->cleanup( $parms{-cleanup}); $self->auto( $parms{-auto}); if($self->auto()){ $self->extractFromZip() if($self->zip()); if($self->path()){ return $self->parse_txtFile(); } else { die 'No Text file found...'."\n";} } }
sub extractFromZip { my $self = shift; my $fz = Archive::Extract->new( archive => $self->zip() ); my $ok = $fz->extract() || die $fz->error(); foreach my $x (@{$fz->files()}){ if((uc($x)) =~ /SANDBOX_/){ $self->path($x); next; } unlink($x) if(!defined($self->cleanup()) || $self->cleanup() == 1); } unlink($self->zip()) if(!defined($self->cleanup()) || $self->cleanup() == 1); return 1; }
sub parse_txtFile { my $self = shift; my ($ct,$s) = (0,0); # count,start my $hr = {}; my (@a,$m,$tmpSec); # return array, tmp_maleware_placeholder, tmp_section open(F, $self->path()) || die 'can not open file: '.$self->path(); while(<F>){ chomp(); next unless length(); next if(/ \* \*\*IMPORTANT: PLEASE SEND THE SCANNED FILE TO/); if($s == 0){ if(/^Detection:\s.*$/){ $s=1; } else { next; } } if(/^Detection:\s(.*)$/){ if($ct > 0){ $m->rawReport($hr->{$ct}); $self->parser($m); $self->malware($m); } $ct++; my $platform = undef; for(uc($1)){ if(/^W32/){ $platform = 'Win32'; last; } $self->unknown($1); } $m = Malware->new( -source => 'NormanSandBox', -sourceLoc => 'NormanEmailDigest', -classification => $platform, -platform => $platform, ); next; } if(/\[\s(.*)\s\]/){ $tmpSec = $1; next; } if(/\*\s(.*)\./){ push(@{$hr->{$ct}->{$tmpSec}},$1); next; } } close(F); unlink($self->path()) if(!defined($self->cleanup()) || $self->cleanup() == 1); return 1; } # ACCESSORS / MODIFIERS
sub zip { my ($self,$v) = @_; $self->{_zip} = $v if(defined($v)); return $self->{_zip}; }
sub path { my ($self,$v) = @_; $self->{_path} = $v if(defined($v)); return $self->{_path}; }
sub auto { my ($self,$v) = @_; $self->{_auto} = $v if(defined($v)); return $self->{_auto}; }
sub cleanup { my ($self,$v) = @_; $self->{_cleanup} = $v if(defined($v)); return $self->{_cleanup}; }
sub malware { my ($self,$v) = @_; if(defined($v)){ return ('expecting malware object', undef) if(!(ref($v) =~ /^Malware/)); push(@{$self->{_malware}},$v); } return $self->{_malware}; }
sub unknown { my ($self,$v) = @_; push(@{$self->{_unknown}},$v) if(defined($v)); return $self->{_unknown}; } # Internal functions sub parser { my ($self,$m) = @_; my $hr = $m->rawReport(); foreach my $x (keys %$hr) { for($x){ if(/^classification$/){ $m->classification($hr->{$x}); next; } if(/^Network services$/){ foreach my $y (@{$hr->{$x}}) { for($y){ if(/^Connects to "(\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b)" on port (\d+) \((\S+)\)/){ my $c = Net::Connection::Simple->new(); my $p = Net::Protocol::Simple->new(protocol => 'ip', layer => 3); $p->{dip} = $1; $c->protocols($p); $p = Net::Protocol::Simple->new(protocol => $3, layer => 4); $p->{dport} = $2; $c->protocols($p); $p = Net::Protocol::Simple->new(protocol => 'irc', layer => 7); $c->protocols($p); $m->connections($c); last; } if(/^Connects to "(\S+\.\S+\.\S+)" on port (\d+) \((\S+)\)/){ my $c = Net::Connection::Simple->new(); my $p; $p = Net::Protocol::Simple->new(protocol => 'ip', layer => 3); $c->protocols($p); $p = Net::Protocol::Simple->new(protocol => $3, layer => 4); $p->{_dport} = $2; $c->protocols($p); $p = Net::Protocol::Simple->new(protocol => 'irc', layer => 7); $p->{_dns} = $1; $c->protocols($p); $m->connections($c); last; } if(/^IRC: Joins channel (\S+) with password (\S+)/){ last; } if(/^Downloads file from (.*) as.*$/){ my $c = Net::Connection::Simple->new(); my $p; $p = Net::Protocol::Simple->new(protocol => 'ip', layer => 3); $c->protocols($p); $p = Net::Protocol::Simple->new(protocol => 'tcp', layer => 4); $p->{_dport} = 80; $c->protocols($p); $p = Net::Protocol::Simple->new(protocol => 'HTTP', layer => 7); $p->{_url} = $1; $c->protocols($p); $m->connections($c); last; } } } last; } if(/^General information$/){ foreach my $y (@{$hr->{$x}}) { if($y =~ /^MD5 hash:\s(.*)$/){ $m->md5sum($1); next; } if($y =~ /^Anti debug\/emulation code present$/){ $m->antiEmulation(1); next; } if($y =~ /^File length:\s+(\d+)\s(\S+)$/){ $m->filesize($1); $m->filesizeUnits($2); } } last; } if(/^Changes to registry$/){ foreach my $y (@{$hr->{$x}}) { $m->registry($y); } last; } if(/^Changes to filesystem$/){ foreach my $y (@{$hr->{$x}}) { $m->filesystem($y); } last; } if(/^Security issues$/){ foreach my $y (@{$hr->{$x}}) { if($y =~ /^Possible backdoor functionality \S+ port (\d+)$/){ my $p = Net::Protocol::Simple->new(protocol => 'tcp', layer => 4); $p->{_sport} = $1; $m->backdoors($p); next; } $m->securityIssues($y); } last; } if(/^Process\/window information$/){ foreach my $y (@{$hr->{$x}}) { $m->processInfo($y); } last; } if(/^Signature Scanning$/){ my $hr2; foreach my $y (@{$hr->{$x}}) { if($y =~ /^(.*)\s\(.*\)\s:\s(.*)$/){ $hr2->{$1} = $2; } } $m->malwareFiles($hr2); last; } } } } 1; __END__