| Malware documentation | Contained in the Malware distribution. |
Malware - Perl extension for storing and manipulation malware and it's attributes
See Constructor new()
The idea of this module is to allow authors to parse different inputs that perform malware analysis and build objects that describe a piece of malware's behaviour. From here we can write detection or blocking rules based on that behavior.
For now, the parsers will live within this class as they are directly connected to the API, this may change in the future.
Object Constructor
my $m = Malware->new( -platform => 'win32', -filesize => $size, -filesizeUnits => $units, -filename => $name, -classification => $class, -md5sum => $md5, -source => $src, -sourceLoc => $srcLoc, -rawReport => $rawTextReport, -dt_found => $dt, # [see Time::Timestamp] -connections => $cons, # [see Net::Connection::Simple] -securityIssues => $si, -antiEmulation => $ae, -backdoors => $bd, # [see Net::Protocol::Simple] -malwareFiles => $mw # [hashref], );
By setting the -platform, the module will try to re-bless itself as that module (ie: Malware::Win32 for -platform => win32). This allows you to scale into specific OS's and their properties (registry for win32).
See OBJECT ACCESSORS for the i/o of these properties
Returns a blurb of the raw report in a nicer Text::Table'ish form. If you subclass (Malware::$platform) this module, you can tag into this method by creating a 'sub _blurb' function that returns a HASHREF in the form:
sub _blurb {
my $self = shift;
my $hr = {};
$hr->{Registry} = $self->registry();
return $hr;
}
Diggs into the connections property and returns the type of connection you are looking for.
Example: We want all the url connections the malware made
my @http = $m->returnConnectionsByLayer( -type => 'url', -layer => 7, -protocol => 'http') );
Example: We want all the irc connections the malware made via dns
my @irc_dns = $m->returnConnectionsByLayer( -type => 'dns', -layer => 7, -protocol => 'IRC') );
Example: We want all the irc connections the malware made via direct IP
my @irc_dip = $m->returnConnectionsByLayer( -type => 'dip', -layer => 7, -protocol => 'IRC') );
All three params are required or it will return:
("Invalid parameters...",undef)
On success it returns an @rray of strings
Sets and returns the filesize
Sets and returns the filesizeUnits
Sets and returns the filename()
Sets and returns the malware classification
Sets and returns the md5sum
Sets and returns the date found, return is a Time::Timestamp object
$m->dt_found($timestamp,$timezone);
Timezone is optional, but the timing could get screwed up if you don't set it
Sets and returns the malware report source (where did you get it?)
Sets and returns the source location (what medium did you get it from (email, website, etc...)
Sets and returns the connection behaviour of the malware.
my $c = Net::Connection::Simple->new(...);
$m->connections($c);
my @cons = @{$m->connections()};
Accepts: Net::Connection::Simple or returns ($errstr,undef)
Returns: a ref to an array of Net::Connection::Simple objects
Sets and returns the malwares backdoor behavior.
my $p = Net::Protocol::Simple->new(...);
$m->backdoors($p);
my @bds = @{$m->backdoors};
Accepts: Net::Protocol::Simple or returns ($errstr,undef)
Returns: a ref to an array of Net::Protocol::Simple objects
Sets and returns the processInfo behavior.
Accepts: string
Returns: a ref to an array of strings
Sets and returns the filesystem behavior.
Accepts: string
Returns: a ref to an array of strings
Sets and returns the raw report string
Accepts: string
Returns: string
Sets and returns a list of other files that are found to be created or associated with this malware
Accepts: HASHREF or returns ($errstr,undef)
$m->malwareFiles({
$f1 => $md5,
$f2 => $virus_sig,
});
OR
$m->malwareFiles({
$f1->{md5} = $md5,
$f1->{vsig} = $virus_sig,
$f1->{snortSig} = $snort_sig,
});
Returns: HASHREF
Sets and returns the antiEmulation behavior.
Accepts: int [undef|1|0]
Returns: whatever you put in
**Note: the blurb will translate [undef] as unknown
Sets and returns other security issues that are caused.
Accepts: string
Returns: a ref to an array of strings
Time::Timestamp,Net::Connection::Simple,Net::Protocol::Simple
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;
use 5.008007; use strict; use warnings; use Time::Timestamp; use Text::Table; use Class::ParmList qw(parse_parms); our $VERSION = '1.02';
sub new { my ($class,%parms) = @_; my $self = {}; bless($self,$class); $self->init(%parms); if(defined($parms{-platform})){ $class .= '::'.ucfirst($parms{-platform}); eval 'use '.$class; if(!$@){ bless($self,$class); eval { $self->init(%parms) }; } else { return ('Error loading: '.$parms{-platform}."\n".$@,undef); } } return $self; } sub init { my ($self,%parms) = @_; $self->filesize( $parms{-filesize}); $self->filesizeUnits( $parms{-filesizeUnits}); $self->filename( $parms{-filename}); $self->classification( $parms{-classification}); $self->md5sum( $parms{-md5sum}); $self->source( $parms{-source}); $self->sourceLoc( $parms{-sourceLoc}); $self->rawReport( $parms{-rawReport}); $self->dt_found( $parms{-dt_found}); $self->connections( $parms{-connections}); $self->securityIssues( $parms{-securityIssues}); $self->antiEmulation( $parms{-antiEmulation}); $self->backdoors( $parms{-backdoors}); $self->malwareFiles( $parms{-malewareFiles}); } # METHODS
sub blurb { my $self = shift; my $txtFilename = $self->filename(); $txtFilename = 'unknown' if(!$txtFilename); my $txtClassification = $self->classification(); $txtClassification = 'unknown' if(!$txtClassification); my $txtMd5sum = $self->md5sum(); $txtMd5sum = 'unknown' if(!$txtMd5sum); my $txtAntiEmulation = 'unknown'; if(defined($self->antiEmulation())){ $txtAntiEmulation = 'yes'; $txtAntiEmulation = 'no' if($self->antiEmulation() == 0); } my $txtConnections = 'unknown'; if(my @a = @{$self->connections()}){ $txtConnections = ''; $txtConnections = Text::Table->new(); my @txt; foreach my $c (@a){ next unless(ref($c) eq 'Net::Connection::Simple'); my $p = $c->protocols(); $p->{3}->{_dip} = 'unknown' if(!$p->{3}->{_dip}); $p->{4}->{_dport} = 'unknown' if(!$p->{4}->{_dport}); $p->{7}->{_dns} = 'unknown' if(!$p->{7}->{_dns}); my $tz = Text::Table->new('Layer','Protocol',''); $tz->load( [3,$p->{3}->protocol(),"DIP:\t".$p->{3}->{_dip}], [4,$p->{4}->protocol(),"DPORT:\t".$p->{4}->{_dport}], [7,$p->{7}->protocol(),"DNS:\t".$p->{7}->{_dns}], ["\n",undef], ); push(@txt,$tz); } $txtConnections->load(\@txt); } my $txtMalwareFiles = 'unkown'; if(my @a = @{$self->malwareFiles()}){ $txtMalwareFiles = Text::Table->new('Filename',"\t".'Signature'); foreach my $hr (@a){ next unless(ref($hr) eq 'HASH'); foreach my $f (keys %$hr){ $txtMalwareFiles->load([$f,"\t".$hr->{$f}]); } } } my $txtProcessInfo = 'unknown'; if(my @a = @{$self->processInfo()}){ $txtProcessInfo = Text::Table->new(); foreach my $x (@a){ $txtProcessInfo->load([$x]); } } my $txtFilesystem = 'unknown'; if(my @a = @{$self->filesystem()}){ $txtFilesystem = Text::Table->new(); foreach my $x (@a){ $txtFilesystem->load([$x]); } } my $txtDtFound = 'unknown'; $txtDtFound = $self->dt_found->tsIso() if($self->dt_found()); my $txtSource = $self->source(); $txtSource = 'unknown' if(!$txtSource); my $txtFilesize = $self->filesize(); $txtFilesize = 'unknown' if(!$txtFilesize); my $txtFilesizeUnits = $self->filesizeUnits(); $txtFilesizeUnits = '' if(!$txtFilesizeUnits); my $t = Text::Table->new(); $t->load( ['Filename:',$txtFilename], ['Filesize:',$txtFilesize.' '.$txtFilesizeUnits], ['MD5:',$txtMd5sum], ['Classification:',$txtClassification], ['source:',$txtSource], ['Date Found:',$txtDtFound], ['Anti-Emulation:',$txtAntiEmulation], ["\n",undef], ['Malware Files:',$txtMalwareFiles], ["\n",undef], ['Process Information:',$txtProcessInfo], ["\n",undef], ['Filesystem Changes:',$txtFilesystem], ["\n",undef], ['Connections:',$txtConnections], ); my $hr; eval { $hr = $self->_blurb() }; return $t unless($hr); foreach my $key (keys %$hr){ my $txt = Text::Table->new(); foreach my $x (@{$hr->{$key}}){ $txt->load([$x]); } $t->load([$key.':',$txt]); $t->load(["\n",undef]); } return $t; }
sub returnConnectionsByLayer_array { my $self = shift; return unless($self->connections()); my $parms = parse_parms({ -parms => \@_, -required => [qw(-layer -protocol -type)], }); return ("invalid parameters\n".Carp::longmess (Class::ParmList->error()),undef) unless(defined($parms)); my ($l,$p,$t) = $parms->get('-layer','-protocol','-type'); my @a = @{$self->connections()}; my @return; foreach my $c (@a){ my $proto = $c->protocols(); next unless(defined($proto->{$l}->{"_$t"}) && (($proto->{$l}->protocol() eq uc($p)))); push(@return,$proto->{$l}->{"_$t"}); } return @return; } # ACCESSORS/MODIFIERS
sub filesize { my ($self,$v) = @_; $self->{_filesize} = $v if(defined($v)); return $self->{_filesize}; }
sub filesizeUnits { my ($self,$v) = @_; $self->{_filesizeUnits} = $v if(defined($v)); return $self->{_filesizeUnits}; }
sub filename { my ($self,$v) = @_; $self->{_filename} = $v if(defined($v)); return $self->{_filename}; }
sub classification { my ($self,$v) = @_; $self->{_classification} = $v if(defined($v)); return $self->{_classification}; }
sub md5sum { my ($self,$v) = @_; $self->{_md5sum} = $v if(defined($v)); return $self->{_md5sum}; }
sub dt_found { my ($self,$v,$tz) = @_; $self->{_dt_found} = Time::Timestamp->new(ts => $v, tz => $tz) if(defined($v)); return $self->{_dt_found}; }
sub source { my ($self,$v) = @_; $self->{_source} = $v if(defined($v)); return $self->{_source}; }
sub sourceLoc { my ($self,$v) = @_; $self->{_sourceLoc} = $v if(defined($v)); return $self->{_sourceLoc}; }
sub connections { my ($self,$v) = @_; if(defined($v)){ return ('Net::Connection::Simple required',undef) unless(ref($v) eq 'Net::Connection::Simple'); push(@{$self->{_connections}},$v); } return $self->{_connections}; }
sub backdoors { my ($self,$v) = @_; if(defined($v)){ return ('expecting a Net::Protocol::Simple',undef) unless(ref($v) eq 'Net::Protocol::Simple'); push(@{$self->{_backdoors}},$v); } return $self->{_backdoors}; }
sub processInfo { my ($self,$v) = @_; push(@{$self->{_processInfo}},$v) if(defined($v)); return $self->{_processInfo}; }
sub filesystem { my ($self,$v) = @_; push(@{$self->{_filesystem}},$v) if(defined($v)); return $self->{_filesystem}; }
sub rawReport { my ($self,$v) = @_; $self->{_rawReport} = $v if(defined($v)); return $self->{_rawReport}; }
sub malwareFiles { my ($self,$v) = @_; if(defined($v)){ return ('expecting a HASH',undef) unless(ref($v) eq 'HASH'); push(@{$self->{_malwareFiles}},$v); } return $self->{_malwareFiles}; }
sub antiEmulation { my ($self,$v) = @_; $self->{_antiEmulation} = $v if(defined($v)); return $self->{_antiEmulation}; }
sub securityIssues { my ($self,$v) = @_; push(@{$self->{_securityIssues}},$v) if(defined($v)); return $self->{_securityIssues}; } 1; __END__