def recv(self): self.response_data = self._transport.recv() self.response_header = MSRPCRespHeader(self.response_data) off = self.response_header.get_header_size() if self.response_header.get_type() == MSRPC_FAULT and self.response_header.get_frag_len() >= off+4: status_code = unpack("<L",self.response_data[off:off+4])[0] if rpc_status_codes.has_key(status_code): raise Exception(rpc_status_codes[status_code]) else: raise Exception('Unknown DCE RPC fault status code: %.8x' % status_code) answer = self.response_data[off:] auth_len = self.response_header.get_auth_len() if auth_len: auth_len += 8 auth_data = answer[-auth_len:] ntlmssp = ntlm.NTLMAuthHeader(data = auth_data) answer = answer[:-auth_len] if ntlmssp['auth_level'] == ntlm.NTLM_AUTH_PKT_PRIVACY: answer = self.cipher_encrypt(answer) if ntlmssp['auth_pad_len']: answer = answer[:-ntlmssp['auth_pad_len']] if ntlmssp['auth_level'] in [ntlm.NTLM_AUTH_PKT_INTEGRITY, ntlm.NTLM_AUTH_PKT_PRIVACY]: ntlmssp = ntlm.NTLMAuthVerifier(data = auth_data) data = self.cipher_encrypt(ntlmssp['data']) zero, crc, sequence = unpack('<LLL', data) self.sequence = sequence + 1 return answer
def load(self, data): ptr = unpack('<L', data[:4])[0] index = 4 if 0 == ptr: # No data. May be a bug in certain versions of Samba. return self._count, _, self._max_count = unpack('<LLL', data[index:index + 12]) index += 12 # Read each object's header. for i in range(0, self._count): aindex, length, size, _ = unpack('<LHHL', data[index:index + 12]) self._elements.append(MSRPCArray(aindex, length, size)) index += 12 # Read the objects themselves. for element in self._elements: max_len, offset, curlen = unpack('<LLL', data[index:index + 12]) index += 12 element.set_name( unicode(data[index:index + 2 * curlen], 'utf-16le')) element.set_max_len(max_len) element.set_offset(offset) element.set_length2(curlen) index += 2 * curlen if curlen & 0x1: index += 2 # Skip padding.
def load(self, data): ptr = unpack('<L', data[:4])[0] index = 4 if 0 == ptr: # No data. May be a bug in certain versions of Samba. return self._count, _, self._max_count = unpack('<LLL', data[index:index+12]) index += 12 # Read each object's header. for i in range(0, self._count): aindex, length, size, _ = unpack('<LHHL', data[index:index+12]) self._elements.append(MSRPCArray(aindex, length, size)) index += 12 # Read the objects themselves. for element in self._elements: max_len, offset, curlen = unpack('<LLL', data[index:index+12]) index += 12 element.set_name(unicode(data[index:index+2*curlen], 'utf-16le')) element.set_max_len(max_len) element.set_offset(offset) element.set_length2(curlen) index += 2*curlen if curlen & 0x1: index += 2 # Skip padding.
def recv(self): self.response_data = self._transport.recv() self.response_header = MSRPCRespHeader(self.response_data) off = self.response_header.get_header_size() if self.response_header.get_type( ) == MSRPC_FAULT and self.response_header.get_frag_len() >= off + 4: status_code = unpack("<L", self.response_data[off:off + 4])[0] if rpc_status_codes.has_key(status_code): raise Exception(rpc_status_codes[status_code]) else: raise Exception('Unknown DCE RPC fault status code: %.8x' % status_code) answer = self.response_data[off:] auth_len = self.response_header.get_auth_len() if auth_len: auth_len += 8 auth_data = answer[-auth_len:] ntlmssp = ntlm.NTLMAuthHeader(data=auth_data) answer = answer[:-auth_len] if ntlmssp['auth_level'] == ntlm.NTLM_AUTH_PKT_PRIVACY: answer = self.cipher_encrypt(answer) if ntlmssp['auth_pad_len']: answer = answer[:-ntlmssp['auth_pad_len']] if ntlmssp['auth_level'] in [ ntlm.NTLM_AUTH_PKT_INTEGRITY, ntlm.NTLM_AUTH_PKT_PRIVACY ]: ntlmssp = ntlm.NTLMAuthVerifier(data=auth_data) data = self.cipher_encrypt(ntlmssp['data']) zero, crc, sequence = unpack('<LLL', data) self.sequence = sequence + 1 return answer
def sendDHCP(self, type, chaddr, hostname=None, ip=None, xid=None, opts=[]): p = DhcpPacket() opt = [('message-type', type)] + list(opts) if xid is None: xid = randint(0, 0xffffffff) if ip: ip = structure.unpack('!L', socket.inet_aton(ip))[0] p['ciaddr'] = ip opt.append(('requested-ip', ip)) if hostname is not None: for i in range(0, len(hostname), 255): opt.append(('host-name', hostname[i:i + 255])) p['op'] = p.BOOTREQUEST p['xid'] = xid p['chaddr'] = chaddr p['cookie'] = 0x63825363 p['options'] = opt self.sock.send(str(p))
def portmap_dump(self, rpc_handle='\x00' * 20): if self.endianness == '>': from impacket.structure import unpack, pack try: rpc_handle = ''.join(map(chr, rpc_handle)) except: pass uuid = list(unpack('<LLHHBB6s', rpc_handle)) rpc_handle = pack('>LLHHBB6s', *uuid) lookup = EPMLookupRequestHeader(endianness=self.endianness) lookup.set_handle(rpc_handle) self._dcerpc.send(lookup) data = self._dcerpc.recv() resp = EPMRespLookupRequestHeader(data) return resp
def portmap_dump(self, rpc_handle = '\x00'*20): if self.endianness == '>': from impacket.structure import unpack,pack try: rpc_handle = ''.join(map(chr, rpc_handle)) except: pass uuid = list(unpack('<LLHHBB6s', rpc_handle)) rpc_handle = pack('>LLHHBB6s', *uuid) lookup = EPMLookupRequestHeader(endianness = self.endianness) lookup.set_handle(rpc_handle); self._dcerpc.send(lookup) data = self._dcerpc.recv() resp = EPMRespLookupRequestHeader(data) return resp
def sendDHCP(self, type, chaddr, hostname = None, ip = None, xid = None,opts = []): p = DhcpPacket() opt = [('message-type',type)] + list(opts) if xid is None: xid = randint(0,0xffffffff) if ip: ip = structure.unpack('!L',socket.inet_aton(ip))[0] p['ciaddr'] = ip opt.append(('requested-ip',ip)) if hostname is not None: for i in range(0,len(hostname),255): opt.append(('host-name',hostname[i:i+255])) p['op'] = p.BOOTREQUEST p['xid'] = xid p['chaddr'] = chaddr p['cookie'] = 0x63825363 p['options'] = opt self.sock.send(str(p))
def sendDHCP(self, type, chaddr, hostname=None, ip=None, xid=None, opts=[]): p = DhcpPacket() opt = [("message-type", type)] + list(opts) if xid is None: xid = randint(0, 0xFFFFFFFF) if ip: ip = structure.unpack("!L", socket.inet_aton(ip))[0] p["ciaddr"] = ip opt.append(("requested-ip", ip)) if hostname is not None: for i in range(0, len(hostname), 255): opt.append(("host-name", hostname[i : i + 255])) p["op"] = p.BOOTREQUEST p["xid"] = xid p["chaddr"] = chaddr p["cookie"] = 0x63825363 p["options"] = opt self.sock.send(str(p))
def recv(self): finished = False forceRecv = 0 retAnswer = '' while not finished: # At least give me the MSRPCRespHeader, especially important for TCP/UDP Transports self.response_data = self._transport.recv( forceRecv, count=MSRPCRespHeader._SIZE) self.response_header = MSRPCRespHeader(self.response_data) # Ok, there might be situation, especially with large packets, that the transport layer didn't send us the full packet's contents # So we gotta check we received it all while (len(self.response_data) < self.response_header['frag_len']): self.response_data += self._transport.recv( forceRecv, count=(self.response_header['frag_len'] - len(self.response_data))) off = self.response_header.get_header_size() if self.response_header[ 'type'] == MSRPC_FAULT and self.response_header[ 'frag_len'] >= off + 4: status_code = unpack("<L", self.response_data[off:off + 4])[0] if rpc_status_codes.has_key(status_code): raise Exception(rpc_status_codes[status_code]) else: raise Exception('Unknown DCE RPC fault status code: %.8x' % status_code) if self.response_header['flags'] & MSRPC_LASTFRAG: # No need to reassembly DCERPC finished = True else: # Forcing Read Recv, we need more packets! forceRecv = 1 answer = self.response_data[off:] auth_len = self.response_header['auth_len'] if auth_len: auth_len += 8 auth_data = answer[-auth_len:] ntlmssp = ntlm.DCERPC_NTLMAuthHeader(data=auth_data) answer = answer[:-auth_len] if ntlmssp['auth_level'] == ntlm.NTLM_AUTH_PKT_PRIVACY: if self.__flags & ntlm.NTLMSSP_NTLM2_KEY: # TODO: FIX THIS, it's not calculating the signature well # Since I'm not testing it we don't care... yet answer, signature = ntlm.SEAL( self.__flags, self.__serverSigningKey, self.__serverSealingKey, answer, answer, self.__sequence, self.__serverSealingHandle, isDCE=True) else: answer, signature = ntlm.SEAL( self.__flags, self.__serverSigningKey, self.__serverSealingKey, answer, answer, self.__sequence, self.__serverSealingHandle, isDCE=True) self.__sequence += 1 else: ntlmssp = ntlm.DCERPC_NTLMAuthVerifier(data=auth_data) if self.__flags & ntlm.NTLMSSP_NTLM2_KEY: signature = ntlm.SIGN(self.__flags, self.__serverSigningKey, answer, self.__sequence, self.__serverSealingHandle, isDCE=True) else: signature = ntlm.SIGN(self.__flags, self.__serverSigningKey, ntlmssp['data'], self.__sequence, self.__serverSealingHandle, isDCE=True) # Yes.. NTLM2 doesn't increment sequence when receiving # the packet :P self.__sequence += 1 if ntlmssp['auth_pad_len']: answer = answer[:-ntlmssp['auth_pad_len']] retAnswer += answer return retAnswer
def bind(self, uuid, alter = 0, bogus_binds = 0): bind = MSRPCBind(endianness = self.endianness) syntax = '\x04\x5d\x88\x8a\xeb\x1c\xc9\x11\x9f\xe8\x08\x00\x2b\x10\x48\x60' if self.endianness == '>': syntax = unpack('<LHHBB6s', syntax) syntax = pack('>LHHBB6s', *syntax) uuid = list(unpack('<LHHBB6sHH', uuid)) uuid[-1] ^= uuid[-2] uuid[-2] ^= uuid[-1] uuid[-1] ^= uuid[-2] uuid = pack('>LHHBB6sHH', *uuid) ctx = 0 for i in range(bogus_binds): bind.set_ctx_id(self._ctx, index = ctx) bind.set_trans_num(1, index = ctx) bind.set_if_binuuid('A'*20, index = ctx) bind.set_xfer_syntax_binuuid(syntax, index = ctx) bind.set_xfer_syntax_ver(2, index = ctx) self._ctx += 1 ctx += 1 bind.set_ctx_id(self._ctx, index = ctx) bind.set_trans_num(1, index = ctx) bind.set_if_binuuid(uuid,index = ctx) bind.set_xfer_syntax_binuuid(syntax, index = ctx) bind.set_xfer_syntax_ver(2, index = ctx) bind.set_ctx_num(ctx+1) if alter: bind.set_type(MSRPC_ALTERCTX) if (self.__auth_level != ntlm.NTLM_AUTH_NONE): if (self.__username is None) or (self.__password is None): self.__username, self.__password, nth, lmh = self._transport.get_credentials() auth = ntlm.NTLMAuthNegotiate() auth['auth_level'] = self.__auth_level auth['auth_ctx_id'] = self._ctx + 79231 bind.set_auth_data(str(auth)) self._transport.send(bind.get_packet()) s = self._transport.recv() if s != 0: resp = MSRPCBindAck(s) else: return 0 #mmm why not None? if resp.get_type() == MSRPC_BINDNAK: resp = MSRPCBindNak(s) status_code = resp.get_reason() if rpc_status_codes.has_key(status_code): raise Exception(rpc_status_codes[status_code], resp) else: raise Exception('Unknown DCE RPC fault status code: %.8x' % status_code, resp) self.__max_xmit_size = resp.get_max_tfrag() if self.__auth_level != ntlm.NTLM_AUTH_NONE: authResp = ntlm.NTLMAuthChallenge(data = resp.get_auth_data().tostring()) self._ntlm_challenge = authResp['challenge'] response = ntlm.NTLMAuthChallengeResponse(self.__username,self.__password, self._ntlm_challenge) response['auth_ctx_id'] = self._ctx + 79231 response['auth_level'] = self.__auth_level if self.__auth_level in (ntlm.NTLM_AUTH_CONNECT, ntlm.NTLM_AUTH_PKT_INTEGRITY, ntlm.NTLM_AUTH_PKT_PRIVACY): if self.__password: key = ntlm.compute_nthash(self.__password) if POW: hash = POW.Digest(POW.MD4_DIGEST) else: hash = MD4.new() hash.update(key) key = hash.digest() else: key = '\x00'*16 if POW: cipher = POW.Symmetric(POW.RC4) cipher.encryptInit(key) self.cipher_encrypt = cipher.update else: cipher = ARC4.new(key) self.cipher_encrypt = cipher.encrypt if response['flags'] & ntlm.NTLMSSP_KEY_EXCHANGE: session_key = 'A'*16 # XXX Generate random session key response['session_key'] = self.cipher_encrypt(session_key) if POW: cipher = POW.Symmetric(POW.RC4) cipher.encryptInit(session_key) self.cipher_encrypt = cipher.update else: cipher = ARC4.new(session_key) self.cipher_encrypt = cipher.encrypt self.sequence = 0 auth3 = MSRPCHeader() auth3.set_type(MSRPC_AUTH3) auth3.set_auth_data(str(response)) self._transport.send(auth3.get_packet(), forceWriteAndx = 1) return resp # means packet is signed, if verifier is wrong it fails
def recv(self): finished = False forceRecv = 0 retAnswer = '' while not finished: # At least give me the MSRPCRespHeader, especially important for # TCP/UDP Transports self.response_data = self._transport.recv(forceRecv, count=MSRPCRespHeader._SIZE) self.response_header = MSRPCRespHeader(self.response_data) # Ok, there might be situation, especially with large packets, that # the transport layer didn't send us the full packet's contents # So we gotta check we received it all while ( len(self.response_data) < self.response_header['frag_len'] ): self.response_data += self._transport.recv(forceRecv, count=(self.response_header['frag_len']-len(self.response_data))) off = self.response_header.get_header_size() if self.response_header['type'] == MSRPC_FAULT and self.response_header['frag_len'] >= off+4: status_code = unpack("<L",self.response_data[off:off+4])[0] if rpc_status_codes.has_key(status_code): raise Exception(rpc_status_codes[status_code]) else: raise Exception('Unknown DCE RPC fault status code: %.8x' % status_code) if self.response_header['flags'] & MSRPC_LASTFRAG: # No need to reassembly DCERPC finished = True else: # Forcing Read Recv, we need more packets! forceRecv = 1 answer = self.response_data[off:] auth_len = self.response_header['auth_len'] if auth_len: auth_len += 8 auth_data = answer[-auth_len:] sec_trailer = SEC_TRAILER(data = auth_data) answer = answer[:-auth_len] if sec_trailer['auth_level'] == RPC_C_AUTHN_LEVEL_PKT_PRIVACY: if self.__auth_type == RPC_C_AUTHN_WINNT: if self.__flags & ntlm.NTLMSSP_NTLM2_KEY: # TODO: FIX THIS, it's not calculating the signature well # Since I'm not testing it we don't care... yet answer, signature = ntlm.SEAL(self.__flags, self.__serverSigningKey, self.__serverSealingKey, answer, answer, self.__sequence, self.__serverSealingHandle) else: answer, signature = ntlm.SEAL(self.__flags, self.__serverSigningKey, self.__serverSealingKey, answer, answer, self.__sequence, self.__serverSealingHandle) self.__sequence += 1 else: if self.__auth_type == RPC_C_AUTHN_WINNT: ntlmssp = auth_data[12:] if self.__flags & ntlm.NTLMSSP_NTLM2_KEY: signature = ntlm.SIGN(self.__flags, self.__serverSigningKey, answer, self.__sequence, self.__serverSealingHandle) else: signature = ntlm.SIGN(self.__flags, self.__serverSigningKey, ntlmssp, self.__sequence, self.__serverSealingHandle) # Yes.. NTLM2 doesn't increment sequence when receiving # the packet :P self.__sequence += 1 if sec_trailer['auth_pad_len']: answer = answer[:-sec_trailer['auth_pad_len']] retAnswer += answer return retAnswer
def bind(self, uuid, alter=0, bogus_binds=0): bind = MSRPCBind(endianness=self.endianness) syntax = '\x04\x5d\x88\x8a\xeb\x1c\xc9\x11\x9f\xe8\x08\x00\x2b\x10\x48\x60' if self.endianness == '>': syntax = unpack('<LHHBB6s', syntax) syntax = pack('>LHHBB6s', *syntax) uuid = list(unpack('<LHHBB6sHH', uuid)) uuid[-1] ^= uuid[-2] uuid[-2] ^= uuid[-1] uuid[-1] ^= uuid[-2] uuid = pack('>LHHBB6sHH', *uuid) ctx = 0 for i in range(bogus_binds): bind.set_ctx_id(self._ctx, index=ctx) bind.set_trans_num(1, index=ctx) bind.set_if_binuuid('A' * 20, index=ctx) bind.set_xfer_syntax_binuuid(syntax, index=ctx) bind.set_xfer_syntax_ver(2, index=ctx) self._ctx += 1 ctx += 1 bind.set_ctx_id(self._ctx, index=ctx) bind.set_trans_num(1, index=ctx) bind.set_if_binuuid(uuid, index=ctx) bind.set_xfer_syntax_binuuid(syntax, index=ctx) bind.set_xfer_syntax_ver(2, index=ctx) bind.set_ctx_num(ctx + 1) if alter: bind.set_type(MSRPC_ALTERCTX) if (self.__auth_level != ntlm.NTLM_AUTH_NONE): if (self.__username is None) or (self.__password is None): self.__username, self.__password, nth, lmh = self._transport.get_credentials( ) auth = ntlm.NTLMAuthNegotiate() auth['auth_level'] = self.__auth_level auth['auth_ctx_id'] = self._ctx + 79231 bind.set_auth_data(str(auth)) self._transport.send(bind.get_packet()) s = self._transport.recv() if s != 0: resp = MSRPCBindAck(s) else: return 0 #mmm why not None? if resp.get_type() == MSRPC_BINDNAK: resp = MSRPCBindNak(s) status_code = resp.get_reason() if rpc_status_codes.has_key(status_code): raise Exception(rpc_status_codes[status_code], resp) else: raise Exception( 'Unknown DCE RPC fault status code: %.8x' % status_code, resp) self.__max_xmit_size = resp.get_max_tfrag() if self.__auth_level != ntlm.NTLM_AUTH_NONE: authResp = ntlm.NTLMAuthChallenge( data=resp.get_auth_data().tostring()) self._ntlm_challenge = authResp['challenge'] response = ntlm.NTLMAuthChallengeResponse(self.__username, self.__password, self._ntlm_challenge) response['auth_ctx_id'] = self._ctx + 79231 response['auth_level'] = self.__auth_level if self.__auth_level in (ntlm.NTLM_AUTH_CONNECT, ntlm.NTLM_AUTH_PKT_INTEGRITY, ntlm.NTLM_AUTH_PKT_PRIVACY): if self.__password: key = ntlm.compute_nthash(self.__password) if POW: hash = POW.Digest(POW.MD4_DIGEST) else: hash = MD4.new() hash.update(key) key = hash.digest() else: key = '\x00' * 16 if POW: cipher = POW.Symmetric(POW.RC4) cipher.encryptInit(key) self.cipher_encrypt = cipher.update else: cipher = ARC4.new(key) self.cipher_encrypt = cipher.encrypt if response['flags'] & ntlm.NTLMSSP_KEY_EXCHANGE: session_key = 'A' * 16 # XXX Generate random session key response['session_key'] = self.cipher_encrypt(session_key) if POW: cipher = POW.Symmetric(POW.RC4) cipher.encryptInit(session_key) self.cipher_encrypt = cipher.update else: cipher = ARC4.new(session_key) self.cipher_encrypt = cipher.encrypt self.sequence = 0 auth3 = MSRPCHeader() auth3.set_type(MSRPC_AUTH3) auth3.set_auth_data(str(response)) self._transport.send(auth3.get_packet(), forceWriteAndx=1) return resp # means packet is signed, if verifier is wrong it fails
def packetHandler(self, hdr, data): eth = self.decoder.decode(data) eth_type = eth.get_ether_type() src_mac = ImpactPacket.Ethernet.as_eth_addr(eth.get_ether_shost()) if src_mac == self.local_mac_str: # 忽略所有从本地网卡发出的数据包 return if eth_type == ImpactPacket.ARP.ethertype: # 收到 ARP 包 arp = eth.child() op_name = arp.get_op_name(arp.get_ar_op()) saddr = arp.as_pro(arp.get_ar_spa()) taddr = arp.as_pro(arp.get_ar_tpa()) if op_name == 'REQUEST' and saddr != '0.0.0.0' and saddr == taddr: # 对端已经有 IP,将本地 IP 设为与其同一子网 print 'Got gratuitous ARP packet' local_addr = arp.get_ar_spa() if local_addr[-1] + 1 > 254: local_addr[-1] -= 1 else: local_addr[-1] += 1 # 设置本地 IP 并结束抓包 self.laddr = arp.as_pro(local_addr) self.lmask = '255.255.255.0' self.done = True elif eth_type == ImpactPacket.IP.ethertype: # 收到 IP 包 ip = eth.child() src_addr = ip.get_ip_src() dst_addr = ip.get_ip_dst() if ip.get_ip_p() == ImpactPacket.UDP.protocol: udp = ip.child() src_port = udp.get_uh_sport() dst_port = udp.get_uh_dport() if src_addr == '0.0.0.0' \ and dst_addr == '255.255.255.255' \ and src_port == 68 \ and dst_port == 67: # 收到非本网卡发送的 DHCP 请求广播包,解析数据包 dhcp = DhcpPacket(udp.get_data_as_string()) msg_type = dhcp.getOptionValue('message-type') # 构造 DHCP 响应包公用字段 dhcp_r = DhcpPacket() dhcp_r['op'] = DhcpPacket.BOOTREPLY dhcp_r['xid'] = dhcp['xid'] dhcp_r['secs'] = dhcp['secs'] dhcp_r['yiaddr'] = structure.unpack('!L', socket.inet_aton(self.predef_cip))[0] dhcp_r['siaddr'] = structure.unpack('!L', socket.inet_aton(self.predef_sip))[0] dhcp_r['chaddr'] = dhcp['chaddr'] dhcp_r['cookie'] = dhcp['cookie'] opts = [ ('subnet-mask', structure.unpack('!L', socket.inet_aton(self.predef_mask))[0]), ('lease-time', self.predef_lease), ('server-id', structure.unpack('!L', socket.inet_aton(self.predef_sip))[0]), ('router', (structure.unpack('!L', socket.inet_aton(self.predef_router))[0],)), ('domain-name-server', (structure.unpack('!L', socket.inet_aton(self.predef_dns))[0],)), ] if msg_type == DhcpPacket.DHCPDISCOVER: print 'Got DHCP discover packet, responds with DHCP offer packet' opts.append(('message-type', DhcpPacket.DHCPOFFER)) elif msg_type == DhcpPacket.DHCPREQUEST: print 'Got DHCP request packet, responds with DHCP ack packet' dhcp_r['ciaddr'] = structure.unpack('!L', socket.inet_aton(self.predef_cip))[0] opts.append(('message-type', DhcpPacket.DHCPACK)) # DHCP ACK 响应发送后即完成 IP 配置过程 # 设置本地 IP 并结束抓包 self.laddr = self.predef_sip self.lmask = self.predef_mask self.done = True # 依次构造 Ethernet/IP/UDP/DHCP 包结构 dhcp_r['_options'] = dhcp_r.packOptions(opts) data = ImpactPacket.Data(str(dhcp_r)) udp_r = ImpactPacket.UDP() udp_r.set_uh_sport(67) udp_r.set_uh_dport(68) udp_r.contains(data) ip_r = ImpactPacket.IP() ip_r.set_ip_src(self.predef_sip) ip_r.set_ip_dst(self.predef_cip) ip_r.contains(udp_r) eth_r = ImpactPacket.Ethernet() eth_r.set_ether_shost(self.local_mac) eth_r.set_ether_dhost(eth.get_ether_shost()) eth_r.contains(ip_r) # 通过 PCAP 发送响应包 self.pcap.sendpacket(eth_r.get_packet())