for循环卡在列表中的第一项-python

for循环卡在列表中的第一项-python,python,loops,scapy,sniffer,Python,Loops,Scapy,Sniffer,我想创建脚本从ARP协议中提取IP和MAC地址(被动扫描) 我在debian上使用了python3.8和scapy2.4.4。 我使用的代码返回所有地址,但我希望它打印出IP/MAC而不重复,因此我创建了一个列表,以检查MAC之前是否已注册,如果未注册,它将添加到列表中并显示在输出中。 但是for循环卡在列表的第一项,然后所有的mac都被打印出来了 守则: from scapy.all import * print("-"*33,"\nIP\t\tMac Addre

我想创建脚本从ARP协议中提取IP和MAC地址(被动扫描) 我在debian上使用了python3.8和scapy2.4.4。 我使用的代码返回所有地址,但我希望它打印出IP/MAC而不重复,因此我创建了一个列表,以检查MAC之前是否已注册,如果未注册,它将添加到列表中并显示在输出中。 但是for循环卡在列表的第一项,然后所有的mac都被打印出来了

守则:

from scapy.all import *
print("-"*33,"\nIP\t\tMac Address\n","-"*33)
mac_list = [1]
def arp_display(pkt):
    if ((pkt[ARP].op == 2 ) or (pkt[ARP].op == 1 )):
        new_mac = pkt[ARP].hwsrc
        for i in mac_list :
            if ( i != new_mac):
            mac_list.append(new_mac)
            return f"{pkt[ARP].psrc}    {pkt[ARP].hwsrc} "
sniff(prn=arp_display, filter="arp", store=0, iface='eth0')
我尝试使用以下代码打印(I)值、新MAC值和列表值:

from scapy.all import *
print("-"*33,"\nIP\t\tMac Address\n","-"*33)
mac_list = [1]
def arp_display(pkt):
    if ((pkt[ARP].op == 2 ) or (pkt[ARP].op == 1 )): #is-at (response)
        new_mac = pkt[ARP].hwsrc
        for i in mac_list :
            print("i=",i)
            print("New MAC", new_mac)
            print("List=", mac_list)
            if ( i != new_mac):
                mac_list.append(new_mac)
                return f"{pkt[ARP].psrc}    {pkt[ARP].hwsrc} "
sniff(prn=arp_display, filter="arp", store=0, iface='eth0')
结果是:

---------------------------------
IP              Mac Address
 ---------------------------------
i= 1
New MAC 3c:95:09:77:86:01
List= [1]
192.168.60.2    3c:95:09:77:86:01
i= 1
New MAC 00:0c:29:de:7b:39
List= [1, '3c:95:09:77:86:01']
192.168.60.3    00:0c:29:de:7b:39
i= 1
New MAC 3c:47:11:bf:84:f2
List= [1, '3c:95:09:77:86:01', '00:0c:29:de:7b:39']
192.168.60.1    3c:47:11:bf:84:f2
i= 1
New MAC 00:0c:29:de:7b:39
List= [1, '3c:95:09:77:86:01', '00:0c:29:de:7b:39', '3c:47:11:bf:84:f2']
192.168.60.3    00:0c:29:de:7b:39

正如您所看到的,列表中有项目,但for循环在第一个循环中卡住了。

您没有发布
sniff
的功能,因此很难说您是如何获得输出的。但是,我猜,
sniff
运行了几次
arp\u display
,每次for循环只执行一次迭代
I=1
,其中1是
mac\u列表的第一个元素

每次运行时,
mac\u list
都会变长。请参见
arp\u display
部分,其中您将
附加到
mac\u列表中
?您还可以返回
,它退出for循环和函数。就像每次跑步一样,
i!=新的_mac
在第一次迭代时为true,其中
i=1
,因此您可以在
i=1
处继续退出for循环


我不确定您希望如何修复它,但通常我会避免在for循环中迭代将
追加到列表(或任何其他iterable)中。列表可能会越来越长,因此在程序内存耗尽之前for循环永远不会结束。

1
永远不会等于MAC地址,因此每次迭代,
如果(i!=new\u MAC):
将为真,然后从该正文返回
,这将阻止进一步的迭代

只需使用
集合
。集合不能包含重复项,因此您无需担心重复项:

mac_set = set()  # A set instead of a list
def arp_display(pkt):
    if ((pkt[ARP].op == 2) or (pkt[ARP].op == 1)): #is-at (response)
        new_mac = pkt[ARP].hwsrc
        mac_set.add(new_mac)  # add instead of append
        return f"{pkt[ARP].psrc}    {pkt[ARP].hwsrc} "

但这并不能维持秩序,因为集合是无序的。

@batwannab如果你是对的,
返回值在错误的位置,我试图将其从for循环中写入,然后我得到了正确的结果

第二个错误是循环函数分别传递所有元素,如果新项(
new\u mac
)与循环函数传递到的元素(
mac\u list
)不匹配,则添加新项(
new\u mac
)的值,为了避免此问题,我添加了
Double
变量,因此,当循环函数通过列表项(
mac_list
)时,如果不匹配,它将添加值
0
,否则将添加值
1
,然后中断循环函数

因此,我们已经确定新的MAC地址是否在列表中

最终代码如下:

from scapy.all import *
print("-"*33,"\nIP\t\tMac Address\n","-"*33)
mac_list = ['1']
output = ""
def arp_display(pkt):
    if ((pkt[ARP].op == 2 ) or (pkt[ARP].op == 1 )): #is-at (response)
        new_mac = str(pkt[ARP].hwsrc)
        double = 0
        for i in mac_list :
            if ( i != new_mac ):
                double = 0
            else:
                double = 1
                break
        if(double == 0):
            mac_list.append(new_mac)
            output = f"{pkt[ARP].psrc}    {pkt[ARP].hwsrc} "
        else:
            output = None
    return output
sniff(prn=arp_display, filter="arp", store=0, iface='eth0')

是的,
arp\u display
函数在服务器上运行一段时间,因此我将
mac\u列表
置于功能之外,以避免丢失旧项目。我需要
arp\u display
功能添加新项目并显示它们。如果您正在查找
mac_列表
,您将看到它不是空的,并且包含其他项,我不会在for循环中使用这些项,以避免在输出上重复使用mac