Package rekall :: Package plugins :: Package windows :: Module netscan
[frames] | no frames]

Source Code for Module rekall.plugins.windows.netscan

  1  # Rekall Memory Forensics 
  2  # 
  3  # Copyright 2013 Google Inc. All Rights Reserved. 
  4  # 
  5  # Authors: 
  6  # Michael Hale Ligh <michael.hale@gmail.com> 
  7  # 
  8  # This program is free software; you can redistribute it and/or modify 
  9  # it under the terms of the GNU General Public License as published by 
 10  # the Free Software Foundation; either version 2 of the License, or (at 
 11  # your option) any later version. 
 12  # 
 13  # This program is distributed in the hope that it will be useful, but 
 14  # WITHOUT ANY WARRANTY; without even the implied warranty of 
 15  # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 
 16  # General Public License for more details. 
 17  # 
 18  # You should have received a copy of the GNU General Public License 
 19  # along with this program; if not, write to the Free Software 
 20  # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 
 21  # 
 22   
 23  # pylint: disable=protected-access 
 24   
 25  from rekall.plugins.windows import common 
 26  from rekall.plugins.overlays.windows import tcpip_vtypes 
 27   
 28  # Python's socket.AF_INET6 is 0x1e but Microsoft defines it 
 29  # as a constant value of 0x17 in their source code. Thus we 
 30  # need Microsoft's since that's what is found in memory. 
 31  AF_INET = 2 
 32  AF_INET6 = 0x17 
33 34 -class PoolScanUdpEndpoint(common.PoolScanner):
35 """PoolScanner for Udp Endpoints""" 36
37 - def __init__(self, **kwargs):
38 super(PoolScanUdpEndpoint, self).__init__(**kwargs) 39 min_size = self.profile.get_obj_size("_UDP_ENDPOINT") 40 if not min_size: 41 raise RuntimeError(repr(min_size)) 42 43 self.checks = [ 44 ('PoolTagCheck', dict( 45 tag=self.profile.get_constant("UDP_END_POINT_POOLTAG"))), 46 47 ('CheckPoolSize', dict(min_size=min_size)), 48 49 ('CheckPoolType', dict(non_paged=True, free=True, paged=True)), 50 51 ('CheckPoolIndex', dict(value=0)), 52 ]
53
54 55 -class PoolScanTcpListener(common.PoolScanner):
56 """PoolScanner for Tcp Listeners""" 57
58 - def __init__(self, **kwargs):
59 super(PoolScanTcpListener, self).__init__(**kwargs) 60 min_size = self.profile.get_obj_size("_TCP_LISTENER") 61 if not min_size: 62 raise RuntimeError(repr(min_size)) 63 64 self.checks = [ 65 ('PoolTagCheck', dict( 66 tag=self.profile.get_constant("TCP_LISTENER_POOLTAG"))), 67 68 ('CheckPoolSize', dict(min_size=min_size)), 69 70 ('CheckPoolType', dict(non_paged=True, free=True, paged=True)), 71 72 ('CheckPoolIndex', dict(value=0)), 73 ]
74
75 76 -class PoolScanTcpEndpoint(common.PoolScanner):
77 """PoolScanner for TCP Endpoints""" 78
79 - def __init__(self, **kwargs):
80 super(PoolScanTcpEndpoint, self).__init__(**kwargs) 81 min_size = self.profile.get_obj_size("_TCP_ENDPOINT") 82 if not min_size: 83 raise RuntimeError(repr(min_size)) 84 85 self.checks = [ 86 ('PoolTagCheck', dict( 87 tag=self.profile.get_constant("TCP_END_POINT_POOLTAG"))), 88 89 ('CheckPoolSize', dict(min_size=min_size)), 90 91 ('CheckPoolType', dict(non_paged=True, free=True, paged=True)), 92 93 ('CheckPoolIndex', dict(value=0)), 94 ]
95
96 97 -class WinNetscan(tcpip_vtypes.TcpipPluginMixin, 98 common.PoolScannerPlugin):
99 """Scan a Vista, 2008 or Windows 7 image for connections and sockets""" 100 101 __name = "netscan" 102 103 table_header = [ 104 dict(name="offset", style="address"), 105 dict(name="protocol", width=8), 106 dict(name="local_addr", width=20), 107 dict(name="remote_addr", width=30), 108 dict(name="state", width=16), 109 dict(name="pid", width=5, align="r"), 110 dict(name="owner", width=14), 111 dict(name="created") 112 ] 113 114 scanner_defaults = dict( 115 scan_kernel_nonpaged_pool=True 116 ) 117 118 @classmethod
119 - def is_active(cls, session):
120 # This plugin works with the _TCP_ENDPOINT interfaces. This interface 121 # uses the new HashTable entry in ntoskernl.exe. 122 return (super(WinNetscan, cls).is_active(session) and 123 session.profile.get_constant('RtlEnumerateEntryHashTable'))
124
125 - def generate_hits(self, run):
126 scanner = PoolScanTcpListener( 127 profile=self.tcpip_profile, session=self.session, 128 address_space=run.address_space) 129 130 for pool_obj in scanner.scan(run.start, run.length): 131 pool_header_end = pool_obj.obj_offset + pool_obj.obj_size 132 tcpentry = self.tcpip_profile._TCP_LISTENER( 133 vm=run.address_space, offset=pool_header_end) 134 135 # Only accept IPv4 or IPv6 136 af_inet = tcpentry.InetAF.dereference(vm=self.kernel_address_space) 137 if af_inet.AddressFamily not in (AF_INET, AF_INET6): 138 continue 139 140 # For TcpL, the state is always listening and the remote port is 141 # zero 142 for ver, laddr, raddr in tcpentry.dual_stack_sockets( 143 vm=self.kernel_address_space): 144 yield (tcpentry, "TCP" + ver, laddr, 145 tcpentry.Port, raddr, 0, "LISTENING") 146 147 # Scan for TCP endpoints also known as connections 148 scanner = PoolScanTcpEndpoint( 149 profile=self.tcpip_profile, session=self.session, 150 address_space=run.address_space) 151 152 for pool_obj in scanner.scan(run.start, run.length): 153 pool_header_end = pool_obj.obj_offset + pool_obj.obj_size 154 tcpentry = self.tcpip_profile._TCP_ENDPOINT( 155 vm=run.address_space, offset=pool_header_end) 156 157 af_inet = tcpentry.InetAF.dereference(vm=self.kernel_address_space) 158 if af_inet.AddressFamily == AF_INET: 159 proto = "TCPv4" 160 elif af_inet.AddressFamily == AF_INET6: 161 proto = "TCPv6" 162 else: 163 continue 164 165 # Switch profiles to the kernel profile. 166 owner = tcpentry.Owner.dereference_as( 167 vm=self.kernel_address_space, profile=self.session.profile) 168 169 # Switch to the kernel's address space. 170 local_addr = tcpentry.LocalAddress(vm=self.kernel_address_space) 171 remote_addr = tcpentry.RemoteAddress(vm=self.kernel_address_space) 172 173 # These are our sanity checks 174 if tcpentry.State.v() not in tcpip_vtypes.TCP_STATE_ENUM: 175 continue 176 177 if not owner and not local_addr: 178 continue 179 180 yield (tcpentry, proto, local_addr, tcpentry.LocalPort, 181 remote_addr, tcpentry.RemotePort, tcpentry.State) 182 183 # Scan for UDP endpoints 184 scanner = PoolScanUdpEndpoint( 185 profile=self.tcpip_profile, session=self.session, 186 address_space=run.address_space) 187 188 for pool_obj in scanner.scan(run.start, run.length): 189 pool_header_end = pool_obj.obj_offset + pool_obj.obj_size 190 udpentry = self.tcpip_profile._UDP_ENDPOINT( 191 vm=run.address_space, offset=pool_header_end) 192 193 af_inet = udpentry.InetAF.dereference(vm=self.kernel_address_space) 194 195 # Only accept IPv4 or IPv6 196 if af_inet.AddressFamily not in (AF_INET, AF_INET6): 197 continue 198 199 # For UdpA, the state is always blank and the remote end is 200 # asterisks 201 for ver, laddr, _ in udpentry.dual_stack_sockets( 202 vm=self.kernel_address_space): 203 yield (udpentry, "UDP" + ver, laddr, udpentry.Port, 204 "*", "*", "")
205
206 - def collect(self):
207 for run in self.generate_memory_ranges(): 208 for (net_object, proto, laddr, lport, raddr, rport, 209 state) in self.generate_hits(run): 210 lendpoint = "{0}:{1}".format(laddr, lport) 211 rendpoint = "{0}:{1}".format(raddr, rport) 212 213 owner = net_object.Owner.dereference_as( 214 vm=self.kernel_address_space, profile=self.session.profile) 215 216 yield (net_object.obj_offset, proto, lendpoint, 217 rendpoint, state, 218 owner.UniqueProcessId, 219 owner.ImageFileName, 220 net_object.CreateTime)
221