1## This file is part of Scapy
2## See http://www.secdev.org/projects/scapy for more informations
3## Copyright (C) Philippe Biondi <phil@secdev.org>
4## This program is published under a GPLv2 license
5
6"""
7Sebek: kernel module for data collection on honeypots.
8"""
9
10# scapy.contrib.description = Sebek
11# scapy.contrib.status = loads
12
13from scapy.fields import *
14from scapy.packet import *
15from scapy.layers.inet import UDP
16
17
18### SEBEK
19
20
21class SebekHead(Packet):
22    name = "Sebek header"
23    fields_desc = [ XIntField("magic", 0xd0d0d0),
24                    ShortField("version", 1),
25                    ShortEnumField("type", 0, {"read":0, "write":1,
26                                             "socket":2, "open":3}),
27                    IntField("counter", 0),
28                    IntField("time_sec", 0),
29                    IntField("time_usec", 0) ]
30    def mysummary(self):
31        return self.sprintf("Sebek Header v%SebekHead.version% %SebekHead.type%")
32
33# we need this because Sebek headers differ between v1 and v3, and
34# between v3 type socket and v3 others
35
36class SebekV1(Packet):
37    name = "Sebek v1"
38    fields_desc = [ IntField("pid", 0),
39                    IntField("uid", 0),
40                    IntField("fd", 0),
41                    StrFixedLenField("cmd", "", 12),
42                    FieldLenField("data_length", None, "data",fmt="I"),
43                    StrLenField("data", "", length_from=lambda x:x.data_length) ]
44    def mysummary(self):
45        if isinstance(self.underlayer, SebekHead):
46            return self.underlayer.sprintf("Sebek v1 %SebekHead.type% (%SebekV1.cmd%)")
47        else:
48            return self.sprintf("Sebek v1 (%SebekV1.cmd%)")
49
50class SebekV3(Packet):
51    name = "Sebek v3"
52    fields_desc = [ IntField("parent_pid", 0),
53                    IntField("pid", 0),
54                    IntField("uid", 0),
55                    IntField("fd", 0),
56                    IntField("inode", 0),
57                    StrFixedLenField("cmd", "", 12),
58                    FieldLenField("data_length", None, "data",fmt="I"),
59                    StrLenField("data", "", length_from=lambda x:x.data_length) ]
60    def mysummary(self):
61        if isinstance(self.underlayer, SebekHead):
62            return self.underlayer.sprintf("Sebek v%SebekHead.version% %SebekHead.type% (%SebekV3.cmd%)")
63        else:
64            return self.sprintf("Sebek v3 (%SebekV3.cmd%)")
65
66class SebekV2(SebekV3):
67    def mysummary(self):
68        if isinstance(self.underlayer, SebekHead):
69            return self.underlayer.sprintf("Sebek v%SebekHead.version% %SebekHead.type% (%SebekV2.cmd%)")
70        else:
71            return self.sprintf("Sebek v2 (%SebekV2.cmd%)")
72
73class SebekV3Sock(Packet):
74    name = "Sebek v2 socket"
75    fields_desc = [ IntField("parent_pid", 0),
76                    IntField("pid", 0),
77                    IntField("uid", 0),
78                    IntField("fd", 0),
79                    IntField("inode", 0),
80                    StrFixedLenField("cmd", "", 12),
81                    IntField("data_length", 15),
82                    IPField("dip", "127.0.0.1"),
83                    ShortField("dport", 0),
84                    IPField("sip", "127.0.0.1"),
85                    ShortField("sport", 0),
86                    ShortEnumField("call", 0, { "bind":2,
87                                                "connect":3, "listen":4,
88                                               "accept":5, "sendmsg":16,
89                                               "recvmsg":17, "sendto":11,
90                                               "recvfrom":12}),
91                    ByteEnumField("proto", 0, IP_PROTOS) ]
92    def mysummary(self):
93        if isinstance(self.underlayer, SebekHead):
94            return self.underlayer.sprintf("Sebek v%SebekHead.version% %SebekHead.type% (%SebekV3Sock.cmd%)")
95        else:
96            return self.sprintf("Sebek v3 socket (%SebekV3Sock.cmd%)")
97
98class SebekV2Sock(SebekV3Sock):
99    def mysummary(self):
100        if isinstance(self.underlayer, SebekHead):
101            return self.underlayer.sprintf("Sebek v%SebekHead.version% %SebekHead.type% (%SebekV2Sock.cmd%)")
102        else:
103            return self.sprintf("Sebek v2 socket (%SebekV2Sock.cmd%)")
104
105bind_layers( UDP,           SebekHead,     sport=1101)
106bind_layers( UDP,           SebekHead,     dport=1101)
107bind_layers( UDP,           SebekHead,     dport=1101, sport=1101)
108bind_layers( SebekHead,     SebekV1,       version=1)
109bind_layers( SebekHead,     SebekV2Sock,   version=2, type=2)
110bind_layers( SebekHead,     SebekV2,       version=2)
111bind_layers( SebekHead,     SebekV3Sock,   version=3, type=2)
112bind_layers( SebekHead,     SebekV3,       version=3)
113