Отправка поддельных сообщений системного журнала в Perl - PullRequest
0 голосов
/ 27 июня 2018

TL; DR Я пытаюсь отправить сообщения системного журнала, которые я уже создал, на сервер системного журнала, используя поддельные IP-адреса источника, но я делаю это очень трудно для себя и могу сделать с кратким подходом

Большинство вопросов о системном журнале не включают проблему подделки IP, поэтому я спрашиваю заново.

Я пишу (хорошо обновляю) скрипт, который я написал давным-давно, который генерирует поддельные сообщения системного журнала (используя UDP). В настоящее время он использует Net :: RawIP, который ужасен для переносимости, а также код для передачи, которую я написал много лет назад, решил прекратить работу в Perl 5 (я не использовал это целую вечность, и я обновляю его). Я давно хотел избавиться от Net :: RawIP, но это единственный, который я знаю, как использовать!

Учитывая, что мне нужно это исправить, и у меня сейчас немного времени, я, вероятно, хочу перейти на использование возможности Socket, с чем я и играл - используя код из SO или gists или других мест, которые я могу найти - а не что-то вроде IO :: Socket, так как мне нужно разрешение на поддельные IP-адреса, учитывая низкую возможность записи в сокеты.

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

По сути, я могу продолжать играть с чрезмерно сложным кодом, который у меня есть, или попросить помощи, чтобы упростить его, так как я не знаю, как работают сокеты, и многие часы поиска в Google не сильно помогли. Я продолжаю находить код, который будет работать, но в некотором роде он не совместим - вероятно, это не проблема для того, для чего они обычно предназначены: для DDOS или для Syn-атак или для чего-либо другого.

Ключевыми требованиями для этого являются (которые каждая попытка, которую я предпринял, потерпела неудачу в той или иной форме!):

  • должен исходить от поддельного IP-адреса источника и переходить к известному IP-адресу назначения (следовательно, я использую UDP) (оба из которых у меня есть в переменных конфигурации), так что сервер системного журнала обрабатывает множество различных устройств, генерирующих журналы
  • должен прийти с установленного порта и перейти на заданный порт (оба из которых у меня в существующие переменные конфигурации)
  • должен содержать сообщение, которое я уже сформировал, которое включает все содержимое системного журнала (PRI и содержимое сообщения системного журнала)
  • должно быть полностью подано с контрольными суммами, длиной пакета и т. Д. При получении
  • быть настолько переносимым, насколько это возможно (я, вероятно, включу его в свой основной скрипт, чтобы хранить все это в одном файле, которым я могу поделиться с другими). ​​

Я просто чувствую, что должен быть простой и легкий способ сделать это, потому что все, что у меня есть, слишком гибкое и сложное и кошмар, чтобы расслабиться.

NB. В Sourceforge он используется как «must syslog», поэтому вы можете видеть, что я делал, но знать, что он перестал работать, поэтому он не будет работать, если вы запустите его сейчас! Как только я исправлю это, я загрузлю новую версию.

Приветствия, --Chris

1 Ответ

0 голосов
/ 27 июня 2018

На самом деле, у меня только что был прорыв, я связал исходники в коде, но я нашел довольно простую тестовую систему и некоторый код контрольной суммы UDP, который с небольшой долей игры работал вместе, и wireshark подтверждает, что все правильно

Написано на случай, если кому-то еще это понадобится, так как мне понадобилось пару дней, чтобы добраться до этого

#!/usr/bin/perl
use Socket;
use List::Util qw(sum);


sub udp_checksum {
    # thanks to ikegami in post https://stackoverflow.com/questions/46181281/udp-checksum-function-in-perl
    my $packed_src_addr = shift;  # As 4-char string, e.g. as returned by inet_aton.
     my $packed_dst_addr = shift;  # As 4-char string, e.g. as returned by inet_aton.
    my $udp_packet      = shift;  # UDP header and data as a string.

    my $sum = sum(
    IPPROTO_UDP,
    length($udp_packet),
    map({ unpack('n*', $_) }
        $packed_src_addr,
        $packed_dst_addr,
        $udp_packet."\0",  # Extra byte ignored if length($udp_packet) is even.
        ),
    );

    while (my $hi = $sum >> 16) {
        $sum = ($sum & 0xFFFF) + $hi;
    }

    return ~$sum & 0xFFFF;
}

#this was found and adapted from http://rhosted.blogspot.com/2009/08/creating-udp-packetip-spoofing-through.html

$src_host = $ARGV[0];
$dst_host = $ARGV[1];
$src_port = 33333;
$dest_port = 514;
$cksum = 0; #initialise, we will sort this later

#$udp_len is the udp packet length in the udp header. Its just 8 plus the length of the data
#for this test harness we will set the data here too
$data = "<132> %FWSM-3-106010: Deny inbound tcp src outside:215.251.218.222/11839 dst inside:192.168.1.1/369";
$udp_len = 8+length($data);

$udp_proto = 17; #17 is the code for udp


#Prepare the udp packet, needed for the checksum to happen, then get the checksum (horrifically complicated, just google it)
$udp_packet = pack("nnnna*", $src_port,$dest_port,$udp_len, $cksum, $data);
$cksum = udp_checksum(inet_aton($src_host),inet_aton($dst_host),$udp_packet);

$zero_cksum = 0; 

#test harness checks about host IPs
my $dst_host = (gethostbyname($dst_host))[4]; my $src_host = (gethostbyname($src_host))[4];

# Now lets construct the IP packet
my $ip_ver = 4;
my $ip_len = 5;
my $ip_ver_len = $ip_ver . $ip_len;
my $ip_tos = 00;
my ($ip_tot_len) = $udp_len + 20;
my $ip_frag_id = 19245;
my $ip_frag_flag = "010";
my $ip_frag_oset = "0000000000000";
my $ip_fl_fr = $ip_frag_flag . $ip_frag_oset;
my $ip_ttl = 30;

#H2H2nnB16C2na4a4 for the IP Header part#nnnna* for the UDP Header part.
#To understand these, see the manual of pack function and IP and UDP Header formats
#IP checksum ($zero_cksum is calculated by the kernel. Dont worry about it.)

my ($pkt) = pack('H2H2nnB16C2na4a4nnnna*',
$ip_ver_len,$ip_tos,$ip_tot_len,$ip_frag_id,
$ip_fl_fr,$ip_ttl,$udp_proto,$zero_cksum,$src_host,
$dst_host,$src_port,$dest_port,$udp_len, $cksum, $data);

#bit that makes the socket and sends the packet
socket(RAW, AF_INET, SOCK_RAW, 255) || die $!; setsockopt(RAW, 0, 1, 1);
my ($destination) = pack('Sna4x8', AF_INET, $dest_port, $dst_host);
send(RAW,$pkt,0,$destination);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...