我试图使用我用于测试的脚本中的pyinstaller创建简单的可执行文件,所以我不必在服务器上安装所有内容,而不是测试。
#! /usr/bin/env python
from scapy.all import *
sourceport=int(raw_input('Soruce port:'))
destinationport=int(raw_input('Destination port:'))
destinationip=raw_input('Destination IP:')
maxttl=int(raw_input('MAX TTL:'))
for i in range(1,maxttl):
udptrace = IP(dst=destinationip,ttl=i)/UDP(dport=destinationport,sport=sourceport,len=500)
received=sr1(udptrace,verbose=0,timeout=2)
try:
print received.summary()
except AttributeError:
print "** TIMEOUT **"
然后我制作可执行文件:
pyinstaller -F udp.py
然而,当我运行它时,我有以下错误:
Soruce port:500
Destination port:500
Destination IP:4.4.4.4
MAX TTL:3
Traceback (most recent call last):
File "<string>", line 16, in <module>
NameError: name 'IP' is not defined
user@:~/2/dist$
我花了一些时间研究,但没有找到任何答案。
答案 0 :(得分:1)
首先,我们需要找出确切的问题。
PyInstaller 手册specifies:
某些Python脚本以 PyInstaller 无法检测的方式导入模块:例如,使用带有可变数据的
__import__()
函数。
检查Scapy's source code表明这正是导入各种网络层的方式:
scapy/layers/all.py
:
def _import_star(m):
mod = __import__(m, globals(), locals())
for k,v in mod.__dict__.iteritems():
globals()[k] = v
for _l in conf.load_layers:
log_loading.debug("Loading layer %s" % _l)
try:
_import_star(_l)
except Exception,e:
log.warning("can't import layer %s: %s" % (_l,e))
请注意,__import__
中的每个模块都会调用conf.load_layers
。
scapy/config.py
:
class Conf(ConfClass):
"""This object contains the configuration of scapy."""
load_layers = ["l2", "inet", "dhcp", "dns", "dot11", "gprs", "hsrp", "inet6", "ir", "isakmp", "l2tp",
"mgcp", "mobileip", "netbios", "netflow", "ntp", "ppp", "radius", "rip", "rtp",
"sebek", "skinny", "smb", "snmp", "tftp", "x509", "bluetooth", "dhcp6", "llmnr", "sctp", "vrrp",
"ipsec" ]
请注意,Conf.load_layers
包含"inet"
。
文件scapy/layers/inet.py
定义IP
类,但未在附带的示例中成功导入。
现在,我们找到了根本原因,让我们看看可以做些什么。
PyInstaller 手册suggests针对此类导入问题的一些解决方法:
- 您可以在 PyInstaller 命令行上提供其他文件。
- 您可以在命令行上提供其他导入路径。
- 您可以编辑第一次为脚本运行 PyInstaller 时写入的
myscript.spec
文件。在spec文件中,您可以告诉 PyInstaller 有关脚本特有的代码和数据文件。- 你可以写&#34; hook&#34;通知 PyInstaller 隐藏导入的文件。如果你&#34;挂钩&#34;对于其他用户也可能使用的包的导入,您可以将您的挂钩文件提供给 PyInstaller 。
一些谷歌搜索显示一个合适的&#34;钩子&#34;已添加到此commit的默认 PyInstaller 分发中,该分发引入了文件PyInstaller/hooks/hook-scapy.layers.all.py
。
PyInstaller 手册indicates,这些内置的钩子应该自动运行:
总之,&#34; hook&#34; file告诉 PyInstaller 关于特定模块调用的隐藏导入。钩子文件的名称是
hook-<module>.py
,其中&#34;<module>
&#34;是Analysis将找到的脚本或导入模块的名称。您应该浏览 PyInstaller 分发文件夹的hooks文件夹中的现有挂钩,只是为了查看许多支持的导入的名称。例如
hook-cPickle.py
是一个钩子文件,告诉模块cPickle
使用的隐藏导入。当您的脚本有import cPickle
时,Analysis会记录它并检查挂钩文件hook-cPickle.py
。
因此,请确认您正在运行最新版本的 PyInstaller 。如果您无法升级到最新版本,或者它没有包含文件PyInstaller/hooks/hook-scapy.layers.all.py
,请使用following content创建它:
#-----------------------------------------------------------------------------
# Copyright (c) 2013, PyInstaller Development Team.
#
# Distributed under the terms of the GNU General Public License with exception
# for distributing bootloader.
#
# The full license is in the file COPYING.txt, distributed with this software.
#-----------------------------------------------------------------------------
from PyInstaller.hooks.hookutils import collect_submodules
# The layers to load can be configured using scapy's conf.load_layers.
# from scapy.config import conf; print(conf.load_layers)
# I decided not to use this, but to include all layer modules. The
# reason is: When building the package, load_layers may not include
# all the layer modules the program will use later.
hiddenimports = collect_submodules('scapy.layers')