使用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包在本地网络上运行了一台服务器。

方法1

一个可能的解决方案是加密您的代码。有几种加密代码的方法。但最简单的是使用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))

该技术用于黑客攻击和其他恶意目的,以避免反病毒软件将其检测为恶意软件。这可能对你有用。试着重新编译它。让我们知道它是否有效。

方法2

如果上面的方法不起作用,试试这个方法。此方法使用fernet cryptography。这意味着代码被更严格地加密,这使得anti-virus software甚至比第一种方法更难将其识别为恶意软件。为此,您需要一个名为cryptography的python模块https://pypi.org/project/cryptography/

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网站安装模块。

  1. 在与主代码文件相同的目录中创建一个名为setup.py的新python文件。然后将以下内容粘贴到您的setup.py文件中
from distutils.core import setup
import py2exe
setup(console=['main.py'])
  1. 打开cmd并键入python setup.py py2exe

  2. 过一段时间,将创建一个名为dist的文件夹。它将包含exe的所有依赖项。

  3. 现在,您可以通过压缩该文件并将其发送给其他人来压缩该文件。另一种可能的解决方案是使用像InnoSetup这样的编译器将所有exe和依赖项编译到一个msi文件中。

检查temp文件夹中是否有创建的.exe文件。如果是,那么这将是你的反病毒检测恶意软件的原因之一
通常,如果程序访问临时文件夹,它将被视为潜在的有害应用程序并被标记。这是恶意软件的行为,它可以访问temp,并开始从temp控制电脑。
这就是为什么如果你已经观察到,如果你运行它,防病毒会清除temp文件夹,因为temp文件夹是其中包含大部分大块的文件夹。
确保你在temp文件夹中放置了no可执行文件。

UTF-8问题已解决

如果代码中有UTF-8字符,则无法转换为字节。

SyntaxError: bytes can only contain ASCII literal characters.

解决

import base64
def encode(data):
try:
# Standard Base64 Encoding
encodedBytes = base64.b64encode(data.encode("utf-8"))
return str(encodedBytes, "utf-8")
except:
return ""

def decode(data):
try:
message_bytes = base64.b64decode(data)
return message_bytes.decode('utf-8')
except:
return ""
your_code = encode("""
# coding: utf-8
# In[2]:

import os
import requests
import time
import pickle

Your code here.........
""")
exec(decode(your_code))

之所以出现此问题,是因为pyinstaller编译类似于特洛伊木马,并且windows防御程序知道exe文件是恶意文件。如果您使用nuitka编译代码,那么这个问题就解决了。我建议你读这篇文章。https://github.com/Nuitka/Nuitka祝你今天愉快。

我也遇到了同样的问题,然后我发现,这只是因为我使用了多行注释的docstring,
如果你有它,你会很好的

"quot"此处的代码。。。。。。。。。"quot">

我在使用pyinstaller -F选项进行编译时遇到了同样的问题(将所有内容都放在一个exe文件中,而不是放在有很多文件的文件夹中(。

使用此选项,病毒评分为12/70。

我在没有-F选项的情况下又做了一次:结果更大(从9MB到20MB(,但病毒总得分现在是2/70。

最新更新