【问题标题】:How to take an element after a re.compile?重新编译后如何获取元素?
【发布时间】:2015-05-19 11:34:13
【问题描述】:

我使用“re”编译握手的数据,如下所示:

 piece_request_handshake = re.compile('13426974546f7272656e742070726f746f636f6c(?P<reserved>\w{16})(?P<info_hash>\w{40})(?P<peer_id>\w{40})')

 handshake = piece_request_handshake.findall(hex_data)

然后我打印出来

我无法添加图片,因为我是新手,所以这是输出:

root@debian:/home/florian/Téléchargements# python script.py 
[('0000000000100005', '606d4759c464c8fd0d4a5d8fc7a223ed70d31d7b', '2d5452323532302d746d6e6a657a307a6d687932')]

我的问题是,我怎样才能只获取该数据的第二部分,即“hash_info”(“606d47...”)?

我已经尝试过使用以下行的 re 组:

   print handshake.group('info_hash')

但结果是错误(再次抱歉我无法显示屏幕...):

*root@debian:/home/florian/Téléchargements# python script.py 
Exception in thread Thread-1:
Traceback (most recent call last):
  File "/usr/lib/python2.7/threading.py", line 552, in __bootstrap_inner
    self.run()
  File "script.py", line 122, in run
    self.p.dispatch(0, PieceRequestSniffer.cb)
  File "script.py", line 82, in cb
    print handshake.group('info_hash')
AttributeError: 'list' object has no attribute 'group'*

这是我为好奇者准备的完整代码的开始:

import pcapy
import dpkt
from threading import Thread
import re
import binascii
import socket
import time

liste=[]
prefix = '13426974546f7272656e742070726f746f636f6c'
hash_code = re.compile('%s(?P<reserved>\w{16})(?P<info_hash>\w{40})(?P<peer_id>\w{40})' % prefix)
match = hash_code.match()
piece_request_handshake = re.compile('13426974546f7272656e742070726f746f636f6c(?P<aaa>\w{16})(?P<bbb>\w{40})(?P<ccc>\w{40})')
piece_request_tcpclose = re.compile('(?P<start>\w{12})5011')


#-----------------------------------------------------------------INIT------------------------------------------------------------

class PieceRequestSniffer(Thread):
    def __init__(self, dev='eth0'):
        Thread.__init__(self)

        self.expr = 'udp or tcp'

        self.maxlen = 65535  # max size of packet to capture
        self.promiscuous = 1  # promiscuous mode?
        self.read_timeout = 100  # in milliseconds
        self.max_pkts = -1  # number of packets to capture; -1 => no limit

        self.active = True
        self.p = pcapy.open_live(dev, self.maxlen, self.promiscuous, self.read_timeout)
        self.p.setfilter(self.expr)

    @staticmethod
    def cb(hdr, data):

        eth = dpkt.ethernet.Ethernet(str(data))
        ip = eth.data



#------------------------------------------------------IPV4 AND TCP PACKETS ONLY---------------------------------------------------           



            #Select Ipv4 packets because of problem with the .p in Ipv6
        if eth.type == dpkt.ethernet.ETH_TYPE_IP6:
            return
        else:

            #Select only TCP protocols
            if ip.p == dpkt.ip.IP_PROTO_TCP:
                tcp = ip.data

                src_ip = socket.inet_ntoa(ip.src)
                dst_ip = socket.inet_ntoa(ip.dst)

                fin_flag = ( tcp.flags & dpkt.tcp.TH_FIN ) != 0
                #if fin_flag:
                    #print "TH_FIN src:%s dst:%s" % (src_ip,dst_ip)




                try:
                    #Return hexadecimal representation
                    hex_data = binascii.hexlify(tcp.data)
                except:
                    return



#-----------------------------------------------------------HANDSHAKE-------------------------------------------------------------




                handshake = piece_request_handshake.findall(hex_data)
                if handshake and (src_ip+" "+dst_ip) not in liste and (dst_ip+" "+src_ip) not in liste and handshake != '':
                    liste.append(src_ip+" "+dst_ip)
                    print match.group('info_hash')

【问题讨论】:

  • 欢迎来到 Stack Overflow(以及 Stack Exchange 网络的其余部分)!你的问题实际上没有屏幕截图会更好,因为命令行程序的输出是纯文本。不幸的是,我不知道答案,但我认为这是来自第一次使用的用户的very good question,值得一票。

标签: python hash filter


【解决方案1】:

re.findall() 返回一个元组列表,每个元组都包含与 re 模式中的命名组相对应的匹配字符串。此示例(使用简化模式)演示了您可以通过索引访问所需的项目:

import re

prefix = 'prefix'
pattern = re.compile('%s(?P<reserved>\w{4})(?P<info_hash>\w{10})(?P<peer_id>\w{10})' % prefix)
handshake = 'prefix12341234567890ABCDEF1234'    # sniffed data
match = pattern.findall(handshake)

>>> print match
[('1234', '1234567890', 'ABCDEF1234')]
>>> info_hash = match[0][1]
>>> print info_hash
1234567890

但命名组的意义在于提供一种按名称访问命名组的匹配值的方法。您可以改用re.match()

import re

prefix = 'prefix'
pattern = re.compile('%s(?P<reserved>\w{4})(?P<info_hash>\w{10})(?P<peer_id>\w{10})' % prefix)
handshake = 'prefix12341234567890ABCDEF1234'    # sniffed data
match = pattern.match(handshake)

>>> print match
<_sre.SRE_Match object at 0x7fc201efe918>
>>> print match.group('reserved')
1234
>>> print match.group('info_hash')
1234567890
>>> print match.group('peer_id')
ABCDEF1234

这些值也可以通过字典访问获得:

>>> d = match.groupdict()
>>> d
{'peer_id': 'ABCDEF1234', 'reserved': '1234', 'info_hash': '1234567890'}
>>> d['info_hash']
'1234567890'

最后,如果输入数据中有多个握手序列,可以使用re.finditer()

import re

prefix = 'prefix'
pattern = re.compile('%s(?P<reserved>\w{4})(?P<info_hash>\w{10})(?P<peer_id>\w{10})' % prefix)
handshake = 'blahprefix12341234567890ABCDEF1234|randomjunkprefix12349876543210ABCDEF1234,more random junkprefix1234hellothereABCDEF1234...'    # sniffed data

for match in pattern.finditer(handshake):
    print match.group('info_hash')

输出:

1234567890 9876543210 你好

【讨论】:

  • 感谢您的宝贵时间和很好的回答@mhawke,实际上 pattern.match 似乎放置了已知信息,问题是我不知道握手中的数据,我尝试了 pattern.match (handshake) with handshake 作为我所有数据的变量,但它输出错误,因为 match 需要一个字符串:/
  • handshake 是一个列表,因此您不能将其传递给 re.match()。关于“已知数据”,您的意思是您不知道您的示例中的前缀13426974546f7272656e742070726f746f636f6c
  • re.match() 从字符串的开头匹配,因此如果您的握手数据包含已知前缀之前的任何内容,则匹配将失败。如果前缀之前有数据,并且嗅探到的数据中只有一个握手序列,你可以尝试使用pattern.search(handshake)。但是,如果嗅探数据中有多次握手,请尝试改用pattern.finditer()。我已经更新了答案以显示 finditer() 的使用。
  • 如果您在同一数据字符串中有多个握手序列,findall() 也应该可以工作。您可以在元组中使用 for 循环和索引来获取匹配的组(如第一个示例所示)。
  • 问题已解决,非常感谢您抽出宝贵时间@mhawke,在我的代码中,handshake 实际上是hex_data,我使用了您的matchgroup 建议,它确实有效。
【解决方案2】:

re.findall 将返回一个元组列表。 group() 调用适用于 Match 对象,由 re 中的一些其他函数返回:

for match in re.finditer(needle, haystack):
    print match.group('info_hash')

此外,如果您只是匹配一次握手,则可能不需要 findall

【讨论】:

  • 实际上,re.findall() 返回一个包含匹配命名组的元组列表。
  • 啊,我的错,看来你是对的。恐怕我太快假设re 中的所有内容都提供Match 对象...
猜你喜欢
  • 1970-01-01
  • 2013-06-01
  • 2012-01-31
  • 1970-01-01
  • 2015-08-08
  • 1970-01-01
  • 2015-03-30
  • 1970-01-01
  • 2018-07-25
相关资源
最近更新 更多