Package rekall :: Package plugins :: Package linux :: Module netstat
[frames] | no frames]

Source Code for Module rekall.plugins.linux.netstat

  1  # Rekall Memory Forensics 
  2  # 
  3  # Copyright 2013 Google Inc. All Rights Reserved. 
  4  # 
  5  # This program is free software; you can redistribute it and/or modify 
  6  # it under the terms of the GNU General Public License as published by 
  7  # the Free Software Foundation; either version 2 of the License, or (at 
  8  # your option) any later version. 
  9  # 
 10  # This program is distributed in the hope that it will be useful, but 
 11  # WITHOUT ANY WARRANTY; without even the implied warranty of 
 12  # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 
 13  # General Public License for more details. 
 14  # 
 15  # You should have received a copy of the GNU General Public License 
 16  # along with this program; if not, write to the Free Software 
 17  # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 
 18   
 19  __author__ = "Michael Cohen <scudette@google.com>" 
 20   
 21   
 22  from rekall import testlib 
 23  from rekall.plugins.linux import common 
 24  from rekall.plugins.overlays import basic 
25 26 27 -class Netstat(common.LinuxPlugin):
28 """Print the active network connections.""" 29 30 __name = "netstat" 31
32 - def sockets(self):
33 """Enumerate all socket objects.""" 34 35 lsof = self.session.plugins.lsof(session=self.session) 36 for task, file_struct, fd in lsof.lsof(): 37 if (file_struct.f_op == self.profile.get_constant( 38 "socket_file_ops") or 39 file_struct.m("d_entry").d_op == self.profile.get_constant( 40 "sockfs_dentry_operations")): 41 42 iaddr = file_struct.dentry.d_inode 43 44 # See http://lxr.free-electrons.com/source/include/net/sock.h?v=3.8#L1319 45 skt = basic.container_of(iaddr, "socket_alloc", 46 "vfs_inode").socket 47 48 yield task, fd, skt.sk, iaddr
49
50 - def render(self, renderer):
51 unix_sockets = [] 52 inet_sockets = [] 53 54 for task, fd, sock, iaddr in self.sockets(): 55 inet_sock = sock.dereference_as("inet_sock") 56 57 if sock.sk_protocol not in ("IPPROTO_TCP", "IPPROTO_UDP", 58 "IPPROTO_IPV4", "IPPROTO_IPV6", 59 "IPPROTO_HOPOPT"): 60 continue 61 62 sk_common = sock.m("__sk_common") 63 64 if sk_common.skc_family in ("AF_UNIX", "AF_LOCAL"): 65 unix_sock = sock.dereference_as("unix_sock") 66 name = unix_sock.addr.name[0].sun_path 67 unix_sockets.append((task, fd, sock, iaddr, sk_common)) 68 69 elif sk_common.skc_family in ("AF_INET", "AF_INET6"): 70 inet_sockets.append((task, fd, sock, iaddr, sk_common)) 71 72 # First do the AF_INET and AF_INET6 sockets. 73 renderer.table_header([("Proto", "proto", "12"), 74 ("SAddr", "saddr", "15"), 75 ("SPort", "sport", "8"), 76 ("DAddr", "daddr", "15"), 77 ("DPort", "dport", "5"), 78 ("State", "state", "15"), 79 ("Pid", "pid", "8"), 80 ("Comm", "comm", "20")]) 81 82 for task, fd, sock, iaddr, sk_common in inet_sockets: 83 inet_sock = sock.dereference_as("inet_sock") 84 85 renderer.table_row( 86 inet_sock.sk.sk_protocol, 87 inet_sock.src_addr, 88 inet_sock.src_port, 89 inet_sock.dst_addr, 90 inet_sock.dst_port, 91 sk_common.skc_state, 92 task.pid, 93 task.comm, 94 ) 95 96 renderer.section() 97 98 # Now do the UNIX sockets. 99 renderer.table_header([("Proto", "proto", "12"), 100 ("RefCount", "ref", "^8"), 101 ("Type", "type", "15"), 102 ("State", "state", "18"), 103 ("Inode", "inode", "8"), 104 ("Path", "path", "20")]) 105 106 for task, fd, sock, iaddr, sk_common in unix_sockets: 107 unix_sock = sock.dereference_as("unix_sock") 108 name = unix_sock.addr.name[0].sun_path 109 110 renderer.table_row( 111 "UNIX", 112 unix_sock.addr.refcnt.counter, 113 sock.sk_type, 114 sk_common.skc_state, 115 iaddr.i_ino, 116 name 117 )
118
119 120 -class PacketQueues(common.LinuxPlugin):
121 """Dumps the current packet queues for all known open sockets.""" 122 123 __name = "pkt_queues" 124 125 @classmethod
126 - def args(cls, parser):
127 super(PacketQueues, cls).args(parser) 128 parser.add_argument( 129 "--dump_dir", default=None, help="Output directory", 130 required=True)
131
132 - def __init__(self, dump_dir=None, **kwargs):
133 super(PacketQueues, self).__init__(**kwargs) 134 self.output_dir = dump_dir
135
136 - def process_socket(self, renderer, task, fd_num, socket):
137 queues = ["receive", "write"] 138 for queue_name in queues: 139 sk_buff_head_name = "sk_{0:s}_queue".format(queue_name) 140 queue = getattr(socket, sk_buff_head_name) 141 filename = "{0:d}.{1:s}.{2:s}.{3:d}".format( 142 task.pid, task.name, queue_name, fd_num) 143 data = [] 144 for sk_buff in queue.walk_list("next", False): 145 pkt_len = sk_buff.len 146 if pkt_len > 0: 147 if not sk_buff.data: 148 continue 149 data.append(self.kernel_address_space.read( 150 sk_buff.data.obj_offset, pkt_len)) 151 if data: 152 with renderer.open(directory=self.output_dir, 153 filename=filename, 154 mode="wb") as fd: 155 fd.write(''.join(data)) 156 self.session.logging.debug("Wrote %d bytes to %s", 157 fd.tell(), filename) 158 return True 159 160 else: 161 self.session.logging.debug("Skipped empty queue %s", filename) 162 return False
163
164 - def render(self, renderer):
165 netstat_plugin = self.session.plugins.netstat(session=self.session) 166 sockets = netstat_plugin.sockets() 167 168 all_sockets = list(sockets) 169 skipped_sockets_count = 0 170 for task, fd, socket, _ in all_sockets: 171 if not self.process_socket(renderer, task, fd, socket): 172 skipped_sockets_count += 1 173 174 renderer.format("Skipped {0:d}/{1:d} sockets.", skipped_sockets_count, 175 len(all_sockets))
176
177 178 -class TestPacketQueues(testlib.HashChecker):
179 PARAMETERS = dict( 180 commandline="pkt_queues --dump_dir %(tempdir)s" 181 )
182