2016-05-01 4 views
-1

У меня есть этот логфайлПодсчитайте количество переменных комбинаций в лог-файл с помощью Perl

New connection: 141.8.83.213:64400 (172.17.0.6:2222) [session: e696835c] 
    2016-04-29 21:13:59+0000 [SSHService ssh-userauth on HoneyPotTransport,3,141.8.83.213] login attempt [user1/test123] failed 
    2016-04-29 21:14:10+0000 [SSHService ssh-userauth on HoneyPotTransport,3,141.8.83.213] login attempt [user1/test1234] failed 
    2016-04-29 21:14:13+0000 [SSHService ssh-userauth on HoneyPotTransport,3,141.8.83.213] login attempt [user1/test123] failed 

Я хочу вывести в файл результат, как этот:

Port,Status,Occurrences 
64400,failed,2 
64400,failed,1 

«Появления» переменная будет представлять количество комбинаций регистрационных данных [имя пользователя и пароль], которые были записаны в файл. User1 test123 видно два раза с одного и того же IP-адреса. Как я могу это сделать? Я два, пока петли на данный момент и подпрограммой вызывается внутри первого в то время как петли так:

Subroutine

sub counter(){ 

     $result = 0; 
     #open(FILE2, $cowrie) or die "Can't open '$cowrie': $!"; 
     while(my $otherlines = <LOG2>){ 

       if($otherlines =~ /login attempt/){ 
         ($user, $password) = (split /[\s:\[\]\/]+/, $otherlines)[-3,-2]; 
         if($_[1] =~ /$user/ && $_[2] =~ /$password/){ 
           $result++; 
         }#if ip matches i think i have to do this with split 

         #print "TEST\n"; 
       } 
     #print "Combo $_[0] and $_[1]\n"; 

     } 
     #print "$result"; 
     return $result; 
} 

Основной метод

sub cowrieExtractor(){ 

     open(FILE2, $cowrie) or die "Can't open '$cowrie': $!"; 

     open(LOG2, $path2) or die "Can't open '$path2': $!"; 

     $seperator = chr(42); 
     #To output user and password of login attempt, set $ip variable to the contents of array at that x position of new 
     #connection to match the ip of the login attempt 
     print FILE2 "SourcePort"."$seperator". 
     "Status"."$seperator"."Occurences"."$seperator"."Malicious"."\n"; 

     $ip = ""; 
     $port = ""; 
     $usr = ""; 
     $pass = ""; 
     $status = ""; 
     $frequency = 0; 

     #Given this is a user/pass attempt honeypot logger, I will use a wide character to reduce the possibility of stopping 
     #the WEKA CSV loader from functioning by using smileyface as seperators. 


     while(my $lines = <LOG2>){ 

       if($lines =~ /New connection/){ 

       ($ip, $port) = (split /[\[\]\s:()]+/, $lines)[7,8]; 

       } 
       if($lines =~ /login attempt/){#and the ip of the new connection 
if($lines =~ /$ip/){ 
       ($usr, $pass, $status) = (split /[\s:\[\]\/]+/, $lines)[-3,-2,-1]; 

         $frequency = counter($ip, $usr, $pass); 

         #print $frequency; 
         if($ip && $port && $usr && $pass && $status ne ""){ 
           print FILE2 join "$seperator",($port, $status, $frequency, $end); 
           print FILE2 "\n"; 
         } 
       } 


       } 
     } 


} 

прямо сейчас в выходе под Occurrences на выходе я получаю 0, и когда я тестировал, похоже, что он исходит из того, что я инициализирую переменную $result в подпрограмме. т.е. 0; что утверждение if внутри подпрограммы не работает должным образом. Любая помощь?

+1

Вы не должны использовать прототипы для подпрограмм Perl. Они не делают того, что, по вашему мнению, делают. Просто 'sub counter {...}' и 'sub cowrieExtractor {...}' правильный – Borodin

+2

* "без привлечения хэшей, если это возможно" * хэши - это именно то, что нужно для этого. Почему вы хотите их избежать? – Borodin

+1

Я не могу не спросить: почему «без участия хешей»? И что это значит - решение, которое вообще не будет использовать хэш-тип данных? (Каковы ваши требования?) – zdim

ответ

1

Вот базовый способ получения ожидаемого результата. Вопросы о контексте (цели) остаются.

use warnings; 
use strict; 

my $file = 'logfile.txt'; 
open my $fh_in, '<', $file; 

# Assemble results for required output in data structure: 
# %rept = { $port => { $usr => { $status => $freq } }; 

my %rept; 
my ($ip, $port); 

while (my $line = <$fh_in>) 
{ 
    if ($line =~ /New connection/) { 
     ($ip, $port) = $line =~ /New connection:\s+([^:]+):(\d+)/; 
     next; 
    } 

    my ($usr, $status) = $line =~ m/login\ attempt \s+ \[ ([^\]]+) \] \s+ (\w+)/x; 
    if ($usr and $status) { 
     $rept{$port}{$usr}{$status}++; 
    } 
    else { warn "Line with an unexpected format:\n$line" } 
} 

# use Data::Dumper; 
# print Dumper \%rept; 

print "Port,Status,Occurences\n"; 
foreach my $port (sort keys %rept) { 
    foreach my $usr (sort keys %{$rept{$port}}) { 
     foreach my $stat (sort keys %{$rept{$port}{$usr}}) { 
      print "$port,$stat,$rept{$port}{$usr}{$stat}\n"; 
     } 
    } 

} 

С вашего входа копируется в файл logfile.txt печатается

 
Port,Status,Occurences 
64400,failed,2 
64400,failed,1 

Я беру всю user1/test123 (и т.д.) для идентификации пользователя. Это может быть изменено в регулярном выражении по мере необходимости. Обратите внимание, что это не позволит вам запрашивать или упорядочивать данные по-разному, в основном вытягивает то, что необходимо для требуемого вывода. Пожалуйста, дайте мне знать, если нужны объяснения.


Вводный объяснение вложенной хэш используется выше

Во-первых, я настоятельно рекомендую хорошее чтение некоторых из многих доступных материалов. Хорошим стартом, безусловно, является стандартный учебник по Perl references, а также кулинарная книга сортов на Perl data structures.

Хэш используется для сбора данных имеют ключи, которые являются номерами портов, и каждый из них имеет за ее значение а хэша-справочник (или, скорее, анонимного хэш). Каждый из этих хешей имеет ключи, которые являются пользователями, которые по своим значениям имеют снова хеш-ссылки. Ключами для них являются возможные значения состояния, поэтому есть две клавиши (неудачно и успешно). Их значения - это частоты. Этот вид «гнездования» представляет собой комплекс структура данных. Есть еще одна важная вещь. В первый раз, когда отображается заявка $rept{$port}{$usr}{$status}++, создается вся иерархия. Таким образом, ключ $port не должен был существовать заранее.Важно отметить, что это auto vivification происходит, даже если структура запрашивается только для значений (если она фактически не существует ).

После первой итерации хэш

%rept = { '64400' => { 'user1/test123' => { 'failed' => 1 } } } 

Во второй итерации тот же самый порт видно, но новый пользователь, так что новые данные добавляются к анонимному хэшу второго уровня. Создается ключ с новым пользователем, его значение является (новым) анонимным хешем, с status => count. Весь Хеш:

%rept = { 
    '64400' => { 
     'user1/test123' => { 'failed' => 1 }, 
     'user1/test1234' => { 'failed' => 1 }, 
    } 
} 

В следующей итерации тот же порт рассматривается и один из уже существующих пользователей, и , как это происходит со статусом (не удалось), который также существует. Таким образом, счетчик для этого статуса увеличивается.

Вся конструкция может быть удобно видна, например, с помощью Data::Dumper. комментируемые из строки в коде выше будет производить

 
$VAR1 = { 
    '64400' => { 
     'user1/test123' => { 
           'failed' => 2 
          }, 
     'user1/test1234' => { 
           'failed' => 1 
          } 
       } 
     }; 

Как сохранить технологические линии новых ключи добавляются по мере необходимости (портов, пользователей, статус) с полной иерархией вплоть до подсчета (1 в первый раз), или, если существующее встречается, его счет увеличивается. Сгенерированную структуру данных можно перемещать и использовать, например, в коде. Дополнительную информацию см. Также в обширной документации.

+0

это работало очень хорошо, спасибо. Что делать, если я хочу увеличивать число вхождений также в зависимости от того, сколько раз IP X.X.X.X использовал ту же комбинацию попыток pass/usr? Таким образом, это будет как оператор '||' каким-либо образом либо увеличивать, если несколько портов используют один и тот же комбо или IP, используя тот же комбо? – firepro20

+0

Также как работает 'my ($ usr, $ status) = $ line = ~ m/login \ попытка \ s + \ [([^ \]] +) \] \ s + (\ w +)/x;' работать так, чтобы Я также могу извлечь IP-адрес и сделать условие 'or' до приращения? – firepro20

+0

@ firepro20 Я буду иметь дело с этим, как только смогу, и добавить объяснение. Однако, учитывая ваш следующий пост, это может помочь немедленно. '$ Rept {$ port} {$ usr} {$ stat}' (из последней строки печати) означает следующее: в hash '% rept', для номера порта' $ port' и для пользователя '$ usr' и для статуса '$ stat' (не удалось или успешно) частота равна именно: $ rept {$ port} {$ usr} {$ stat}'. Таким образом, это частота «неудачных» или «сукцидированных» для пользователя '$ usr' в порту' $ port'. Затем печать проходит через все возможности, предоставляя частоты в каждом порту для каждого пользователя для каждого состояния. Помогает ли это? – zdim