如何解釋審計日誌的“saddr”欄位?
我正在嘗試記錄 的參數
connect
,所以我添加了一條規則auditctl
。現在在 audit.log 我得到這樣的行:
類型=SOCKADDR 消息=審計(1385638181.866:89758729):saddr=十六進製字元串
那麼我應該如何從十六進製字元串中解釋目標地址(我不確定該十六進製字元串中儲存了什麼)?
我找到了這個 Perl 腳本parse-audit-log.pl,它顯示了一個可以解析該字元串的函式,如下所示:
sub parse_saddr { my $sockfd = $_[0]; my $saddr = $_[1]; # 0 - sys_bind(), 1 - sys_connect(), 2 - sys_accept() my $action = $_[2]; ($f1, $f2, $p1, $p2, @addr) = unpack("A2A2A2A2A2A2A2A2", $saddr); $family = hex2dec($f1) + 256 * hex2dec($f2); $port = 256 * hex2dec($p1) + hex2dec($p2); $ip1 = hex2dec($addr[0]); $ip2 = hex2dec($addr[1]); $ip3 = hex2dec($addr[2]); $ip4 = hex2dec($addr[3]); #print "$saddr\n"; if ($family eq 2) { #&& $ip1 ne 0) { my $dst_addr = "$ip1.$ip2.$ip3.$ip4:$port"; # print "family=$family $dst_addr\n\n"; # todo: avoid code duplication if ($action eq 0) { $sockfd_hash{ $sockfd } = $dst_addr; } elsif ($action eq 1) { my $src_addr; if (exists $sockfd_hash{ $sockfd }) { $src_addr = $sockfd_hash{ $sockfd }; } else { $src_addr = "x.x.x.x:x"; } print "$src_addr -> $dst_addr\n"; } elsif ($action eq 2) { my $src_addr; if (exists $sockfd_hash{ $sockfd }) { $src_addr = $sockfd_hash{ $sockfd }; } else { $src_addr = "x.x.x.x:x"; } print "$dst_addr <- $src_addr\n"; } else { print "unknown action\n"; } } elsif ($family eq 1) { $tmp1 = 0; ($tmp1, $tmp2) = unpack("A4A*", $saddr); my $file = pack("H*", $tmp2); # print "family=$family file=$file\n"; } else { # print "$saddr\n"; } }
該腳本是CERN 網站上 TWiki 頁面的一部分,位於LinuxSupport下。標題為:IDSNetConnectionLogger的頁麵包含 2 個感興趣的文件。一個是我上面提到的腳本parse-audit-log.pl,另一個是範例audit.log文件。
執行腳本
如果您下載這 2 個文件,您會注意到這就是您要詢問的內容。
例子
$ ./parse-audit-log.pl -l audit.log x.x.x.x:x -> 0.0.0.0:22 x.x.x.x:x -> 137.138.32.52:22 137.138.32.52:22 <- x.x.x.x:x x.x.x.x:x -> 0.0.0.0:22 x.x.x.x:x -> 137.138.32.52:0 x.x.x.x:x -> 137.138.16.5:53 x.x.x.x:x -> 137.138.16.5:53 x.x.x.x:x -> 137.138.16.5:53 x.x.x.x:x -> 137.138.128.158:88 x.x.x.x:x -> 137.138.16.5:53 x.x.x.x:x -> 137.138.16.5:53 x.x.x.x:x -> 137.138.16.5:53 x.x.x.x:x -> 137.138.128.148:750 x.x.x.x:x -> 137.138.16.5:53 x.x.x.x:x -> 137.138.16.5:53 x.x.x.x:x -> 137.138.16.5:53 x.x.x.x:x -> 137.138.128.158:88 x.x.x.x:x -> 137.138.32.52:0 x.x.x.x:x -> 137.138.16.5:53 x.x.x.x:x -> 137.138.16.5:53 x.x.x.x:x -> 137.138.16.5:53 x.x.x.x:x -> 137.138.128.158:88 x.x.x.x:x -> 127.0.0.1:6010
拉出解析器邏輯
我們可以將上面的內容壓縮成一個
saddr
解析器。這是我的精簡版。$ cat parse_saddr.pl #!/usr/bin/perl -w # Getopt::Std module from the perl package use Getopt::Std; my %Options; getopt('s', \%Options); if (defined($Options{'s'})) { $saddr = $Options{'s'}; } else { print "saddr not given\n"; exit(-1); } sub hex2dec($) { return hex $_[0] } sub parse_saddr { my $saddr = $_[0]; ($f1, $f2, $p1, $p2, @addr) = unpack("A2A2A2A2A2A2A2A2", $saddr); $family = hex2dec($f1) + 256 * hex2dec($f2); $port = 256 * hex2dec($p1) + hex2dec($p2); $ip1 = hex2dec($addr[0]); $ip2 = hex2dec($addr[1]); $ip3 = hex2dec($addr[2]); $ip4 = hex2dec($addr[3]); #print "$saddr\n"; if ($family eq 2) { #&& $ip1 ne 0) { my $dst_addr = "$ip1.$ip2.$ip3.$ip4:$port"; print "family=$family $dst_addr\n\n"; } elsif ($family eq 1) { $tmp1 = 0; ($tmp1, $tmp2) = unpack("A4A*", $saddr); my $file = pack("H*", $tmp2); print "family=$family file=$file\n"; } else { print "$saddr\n"; } } &parse_saddr($saddr);
saddr 解析器腳本的範例執行
我們可以這樣執行它:
$ ./parse_saddr.pl -s 02000035898A1005000000000000000030BED20858D83A0010000000 family=2 137.138.16.5:53
然後,您可以使用這樣的命令來解析上述文件中的所有
saddr=..
行:audit.log
$ for i in $(grep saddr audit.log | cut -d"=" -f4);do echo $i; \ ./parse_saddr.pl -s $i;done | less
以上是一起破解的,因此它不處理 family=1 類型的
saddr
. 您必須深入探勘,但這為您提供瞭如何處理所有這些問題的粗略開始。範例輸出
$ for i in $(grep saddr audit.log | cut -d"=" -f4);do echo $i; \ ./parse_saddr.pl -s $i;done | less ... 01002F6465762F6C6F67000000000000 family=1 file=/dev/log^@^@^@^@^@^@ ... 02000035898A10050000000000000000726E2E6368009A0900000000 family=2 137.138.16.5:53 ... 02000058898A809E0000000000000000 family=2 137.138.128.158:88 ... 020002EE898A80940000000000000000 family=2 137.138.128.148:750 ... 0200177A7F0000010000000000000000 family=2 127.0.0.1:6010 ...
Perl 的打包/解包函式
一旦您了解了它們的工作原理,這些都是非常強大的功能。如果您以前從未使用過它們,那麼我會看一下教程perlpacktut。
這些函式背後的想法是,它們接收數據並使用模板返回數據,使用模板作為數據應該如何組織的結構。
同樣,這裡有一個簡單的 Perl 腳本,它顯示了
saddr
.$ cat unpack.pl #!/usr/bin/perl $saddr = "02000035898A1005000000000000000030BED20858D83A0010000000"; ($f1, $f2, $p1, $p2, @addr) = unpack("A2A2A2A2A2A2A2A2", $saddr); printf "org string: $saddr\n"; printf "org values==> f1: %s f2: %s p1: %s p2: %s addr: %s\n", $f1,$f2,$p1,$p2,join("",@addr); printf "new values==> f1: %2s f2: %2s p1: %2s p2: %2s addr: %s.%s.%s.%s\n\n", hex($f1),hex($f2),hex($p1),hex($p2),hex($addr[0]),hex($addr[1]),hex($addr[2]),hex($addr[3]);
產生這個:
$ ./unpack.pl org string: 02000035898A1005000000000000000030BED20858D83A0010000000 org values==> f1: 02 f2: 00 p1: 00 p2: 35 addr: 898A1005 new values==> f1: 2 f2: 0 p1: 0 p2: 53 addr: 137.138.16.5
在這裡,我們獲取其中包含的數據
$saddr
並呼叫unpack()
告訴函式一次獲取 2 個字節的數據 (A2)。這樣做 10 次。前 4A2
個塊,實際上每個塊只有 2 個字元,儲存在變數中:$f1
,$f2
,$p1
,$p2
。剩餘的字元儲存在數組中@addr
。