python - 使用 pyinstaller 制作的 exe 文件被 Windows Defender 报告为病毒威胁
问题描述
我正在尝试使用 pyinstaller 为学校项目创建一个 exe,但是 Windows Defender 似乎报告了病毒威胁并阻止了该文件。我想将此 exe 发送给其他人,但除非我解决此问题,否则我将无法做到这一点。所以这些是我的疑问 -为什么 exe 文件被报告为病毒?对病毒总数的快速扫描表明,有16 个引擎将此文件检测为特洛伊木马。另外,有什么方法可以防止 Windows Defender 或任何其他防病毒软件向用户发出病毒威胁警报,我的意思是,有没有什么方法可以让我的文件看起来对防病毒软件来说是安全的,以防它只是一个虚假的威胁?如果这是不可能的,pyinstaller 的其他安全替代方案是什么?我只是一个初学者,所以任何提示都会非常感激。谢谢。
编辑:应@Pro Chess 的要求,我包含了我的脚本。
import socket
import threading
import pickle
class Server :
def __init__(self) :
self.HEADER = 64
self.PORT = 5050
self.SERVER = socket.gethostbyname(socket.gethostname())
self.ADDR = (self.SERVER, self.PORT)
self.FORMAT = 'utf-8'
self.DISCONNECT_MESSAGE = "!DISCONNECT"
self.server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.server.bind(self.ADDR)
self.save_dict = {}
def file_access(self) :
with open("project_data\\savedata.dat","rb") as save_file :
save_dict = pickle.load(save_file)
return save_dict
def file_dump(self) :
with open("project_data\\savedata.dat","wb") as save_file :
pickle.dump(self.save_dict,save_file)
def recieve(self,conn) :
msg_length = conn.recv(self.HEADER).decode(self.FORMAT)
if msg_length:
msg_length = int(msg_length)
msg = conn.recv(msg_length).decode(self.FORMAT)
return msg
def handle_client(self,conn, addr):
print(f"[NEW CONNECTION] {addr} connected.")
connected = True
while connected:
try :
self.save_dict = self.file_access()
msg = self.recieve(conn)
if msg == self.DISCONNECT_MESSAGE:
connected = False
elif msg == "Save Data" :
player_id = conn.recv(5000)
try :
name,code = pickle.loads(player_id)
except EOFError :
pass
if (name,code) not in self.save_dict :
conn.send("Available".encode(self.FORMAT))
msg1 = self.recieve(conn)
if msg1 == "Game Data" :
game_data = conn.recv(5000)
#msg = pickle.loads(msg_data)
self.save_dict[(name,code)] = game_data
print(self.save_dict)
conn.send("Success".encode(self.FORMAT))
else :
conn.send("Exists".encode(self.FORMAT))
msg1 = self.recieve(conn)
if msg1 == "Game Data" :
game_data = conn.recv(5000)
self.save_dict[(name,code)] = game_data
conn.send("Success".encode(self.FORMAT))
elif msg == "Wipe" :
self.save_dict.pop((name,code))
print(f"new dict is ",self.save_dict)
elif msg == "Load" :
player_id = conn.recv(5000)
try :
name,code = pickle.loads(player_id)
except EOFError :
pass
if (name,code) in self.save_dict :
conn.send("Present".encode(self.FORMAT))
conn.send(self.save_dict[(name,code)])
else :
conn.send("Absent".encode(self.FORMAT))
elif msg == "Check Data" :
player_id = conn.recv(5000)
try :
name,code = pickle.loads(player_id)
except EOFError :
pass
if (name,code) in self.save_dict :
conn.send("Exists".encode(self.FORMAT))
else :
conn.send("New".encode(self.FORMAT))
self.file_dump()
except ConnectionResetError :
connected = False
conn.close()
print(f"[Terminated] connection terminated for {addr}")
def start(self):
self.server.listen()
print(f"[LISTENING] Server is listening on {self.SERVER}")
while True:
conn, addr = self.server.accept()
thread = threading.Thread(target=self.handle_client, args=(conn, addr))
thread.start()
print(f"[ACTIVE CONNECTIONS] {threading.activeCount() - 1}")
print("[STARTING] server is starting...")
server = Server()
server.start()
我已经使用 socket 包在我的本地网络上运行服务器。
解决方案
方法一
一个可能的解决方案是加密您的代码。有几种加密代码的方法。但最简单的一种是使用base64
或基本上转换text-to-binary
编码。并且您需要确保没有特殊字符,因为 base64 只有这个字符集。您可以在此处查看 base64 表https://en.wikipedia.org/wiki/Base64
import base64
your_code = base64.b64encode(b"""
# All your code goes in here.
import socket
import threading
import pickle
class Server :
def __init__(self) :
self.HEADER = 64
self.PORT = 5050
self.SERVER = socket.gethostbyname(socket.gethostname())
self.ADDR = (self.SERVER, self.PORT)
self.FORMAT = 'utf-8'
self.DISCONNECT_MESSAGE = "!DISCONNECT"
# Continue your code...
""")
exec(base64.b64decode(your_code))
此技术用于黑客攻击和其他恶意目的,以避免防病毒软件将其检测为恶意软件。这可能对你有用。尝试重新编译它。让我们知道它是否有效。
方法二
如果上述方法不起作用,请尝试此方法。此方法使用fernet cryptography
. 这意味着代码被更紧密地加密,anti-virus software
比第一种方法更难将其识别为恶意软件。为此,您需要一个名为cryptography
https://pypi.org/project/cryptography/的 python 模块
from cryptography.fernet import Fernet
import base64
code = b"""
import socket
import threading
import pickle
class Server :
def __init__(self) :
self.HEADER = 64
self.PORT = 5050
self.SERVER = socket.gethostbyname(socket.gethostname())
self.ADDR = (self.SERVER, self.PORT)
self.FORMAT = 'utf-8'
self.DISCONNECT_MESSAGE = "!DISCONNECT"
self.server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.server.bind(self.ADDR)
self.save_dict = {}
def file_access(self) :
with open("project_data\\savedata.dat","rb") as save_file :
save_dict = pickle.load(save_file)
return save_dict
def file_dump(self) :
with open("project_data\\savedata.dat","wb") as save_file :
pickle.dump(self.save_dict,save_file)
def recieve(self,conn) :
msg_length = conn.recv(self.HEADER).decode(self.FORMAT)
if msg_length:
msg_length = int(msg_length)
msg = conn.recv(msg_length).decode(self.FORMAT)
return msg
def handle_client(self,conn, addr):
print(f"[NEW CONNECTION] {addr} connected.")
connected = True
while connected:
try :
self.save_dict = self.file_access()
msg = self.recieve(conn)
if msg == self.DISCONNECT_MESSAGE:
connected = False
elif msg == "Save Data" :
player_id = conn.recv(5000)
try :
name,code = pickle.loads(player_id)
except EOFError :
pass
if (name,code) not in self.save_dict :
conn.send("Available".encode(self.FORMAT))
msg1 = self.recieve(conn)
if msg1 == "Game Data" :
game_data = conn.recv(5000)
#msg = pickle.loads(msg_data)
self.save_dict[(name,code)] = game_data
print(self.save_dict)
conn.send("Success".encode(self.FORMAT))
else :
conn.send("Exists".encode(self.FORMAT))
msg1 = self.recieve(conn)
if msg1 == "Game Data" :
game_data = conn.recv(5000)
self.save_dict[(name,code)] = game_data
conn.send("Success".encode(self.FORMAT))
elif msg == "Wipe" :
self.save_dict.pop((name,code))
print(f"new dict is ",self.save_dict)
elif msg == "Load" :
player_id = conn.recv(5000)
try :
name,code = pickle.loads(player_id)
except EOFError :
pass
if (name,code) in self.save_dict :
conn.send("Present".encode(self.FORMAT))
conn.send(self.save_dict[(name,code)])
else :
conn.send("Absent".encode(self.FORMAT))
elif msg == "Check Data" :
player_id = conn.recv(5000)
try :
name,code = pickle.loads(player_id)
except EOFError :
pass
if (name,code) in self.save_dict :
conn.send("Exists".encode(self.FORMAT))
else :
conn.send("New".encode(self.FORMAT))
self.file_dump()
except ConnectionResetError :
connected = False
conn.close()
print(f"[Terminated] connection terminated for {addr}")
def start(self):
self.server.listen()
print(f"[LISTENING] Server is listening on {self.SERVER}")
while True:
conn, addr = self.server.accept()
thread = threading.Thread(target=self.handle_client, args=(conn, addr))
thread.start()
print(f"[ACTIVE CONNECTIONS] {threading.activeCount() - 1}")
print("[STARTING] server is starting...")
server = Server()
server.start()
"""
key = Fernet.generate_key()
encryption_type = Fernet(key)
encrypted_message = encryption_type.encrypt(code)
decrypted_message = encryption_type.decrypt(encrypted_message)
exec(decrypted_message)
这次编译exe
后上传到https://www.virustotal.com/gui/效果更好
方法 3 - 使用另一种方法来冻结您的代码
有很多方法可以将您的代码转换为exe
. 另一种最流行的冻结代码的方法是使用py2exe
. 从 pypi 网站安装模块。
setup.py
在与主代码文件相同的目录中创建一个新的 python文件。然后将以下内容粘贴到您的setup.py
文件中。
from distutils.core import setup
import py2exe
setup(console=['main.py'])
打开cmd并输入
python setup.py py2exe
一段时间后,
dist
将创建一个名为的文件夹。它将包含您的所有依赖项exe
。现在您可以通过压缩来压缩此文件并将其发送给其他人。另一种可能的解决方案是使用像InnoSetup这样的编译器将您
exe
的所有依赖项和依赖项编译到一个msi
文件中。
推荐阅读
- javascript - 当用户在 KendoNumericTextbox 中输入十进制字符时显示错误
- javascript - 如何在 ASP.NET MVC 上使用 Razor 将字符串列表传递给 javascript?
- c++ - 从 'SymbolInfo*' 转换为 'YYSTYPE {aka int}' 失去精度
- c# - 在没有 ASP.NET 核心的情况下使用 Kestrel
- php - 在 GAE 上托管一个包含一些 php 文件的大部分静态网站
- angular - 找不到与 angular-meteor 配合得很好的日期选择器
- delphi - TListView OnCustomDrawItem 行为在 10.2 更新 3 中更改
- reactjs - 如何在 React-Native 中将元素与 Flatlist 对齐
- bootstrap-4 - 订购 div 断点移动 Bootstrap 4
- android - 根据先前的提交推送更改?