zipfile.BadZipFile:提取受密码保护的.zip和.zip时,提取时损坏了错误的CRC-32

时间:2019-02-05 10:12:50

标签: python zip extract zipfile crc32

我正在尝试提取一个受密码保护的.zip文件,其中包含一个.txt文件(对于这种情况,请说Congrats.txt)。现在Congrats.txt中包含文本,因此其大小不为0kb。将其放置在.zip中(出于线程的考虑,让其命名为.zip zipv1.zip),并为此密码设置dominique。该密码将存储在另一个.txt中的其他单词和名称中(出于这个问题,我们将其命名为file.txt)。现在,如果我通过执行python Program.py -z zipv1.zip -f file.txt(假设所有这些文件都与Program.py在同一文件夹中)运行下面的代码,我的程序将显示dominique作为zipv1.zip的正确密码file.txt中的其他单词/密码,并提取zipv1.zip,但Congrats.txt为空,大小为0kb。

现在我的代码如下:

import argparse
import multiprocessing
import zipfile

parser = argparse.ArgumentParser(description="Unzips a password protected .zip", usage="Program.py -z zip.zip -f file.txt")
# Creates -z arg
parser.add_argument("-z", "--zip", metavar="", required=True, help="Location and the name of the .zip file.")
# Creates -f arg
parser.add_argument("-f", "--file", metavar="", required=True, help="Location and the name of file.txt.")
args = parser.parse_args()


def extract_zip(zip_filename, password):
    try:
        zip_file = zipfile.ZipFile(zip_filename)
        zip_file.extractall(pwd=password)
        print(f"[+] Password for the .zip: {password.decode('utf-8')} \n")
    except:
        # If a password fails, it moves to the next password without notifying the user. If all passwords fail, it will print nothing in the command prompt.
        pass


def main(zip, file):
    if (zip == None) | (file == None):
        # If the args are not used, it displays how to use them to the user.
        print(parser.usage)
        exit(0)
    # Opens the word list/password list/dictionary in "read binary" mode.
    txt_file = open(file, "rb")
    # Allows 8 instances of Python to be ran simultaneously.
    with multiprocessing.Pool(8) as pool:
        # "starmap" expands the tuples as 2 separate arguments to fit "extract_zip"
        pool.starmap(extract_zip, [(zip, line.strip()) for line in txt_file])


if __name__ == '__main__':
    main(args.zip, args.file)

但是,如果我使用与zipv2.zip相同的方法(只是区别为zipv1.zip的另一个zip(Congrats.txt)位于文件夹中,并且该文件夹与Congrats.txt一起压缩,确实获得了与zipv1.zip相同的结果,但是这次Congrats.txt沿其所在的文件夹提取,并且Congrats.txt是完整的;其中的文字及其大小保持不变。

因此,为解决此问题,我尝试阅读zipfile's documentation,结果发现如果密码与.zip不匹配,则会抛出RuntimeError。因此,我确实将代码中的except:更改为except RuntimeError:,并在尝试解压缩zipv1.zip时遇到此错误:

(venv) C:\Users\USER\Documents\Jetbrains\PyCharm\Program>Program.py -z zipv1.zip -f file.txt
[+] Password for the .zip: dominique

multiprocessing.pool.RemoteTraceback:
"""
Traceback (most recent call last):
  File "C:\Users\USER\AppData\Local\Programs\Python\Python37\lib\multiprocessing\pool.py", line 121, in worker
result = (True, func(*args, **kwds))
  File "C:\Users\USER\AppData\Local\Programs\Python\Python37\lib\multiprocessing\pool.py", line 47, in starmapstar
return list(itertools.starmap(args[0], args[1]))
  File "C:\Users\USER\Documents\Jetbrains\PyCharm\Program\Program.py", line 16, in extract_zip
zip_file.extractall(pwd=password)
  File "C:\Users\USER\AppData\Local\Programs\Python\Python37\lib\zipfile.py", line 1594, in extractall
self._extract_member(zipinfo, path, pwd)
  File "C:\Users\USER\AppData\Local\Programs\Python\Python37\lib\zipfile.py", line 1649, in _extract_member
shutil.copyfileobj(source, target)
  File "C:\Users\USER\AppData\Local\Programs\Python\Python37\lib\shutil.py", line 79, in copyfileobj
buf = fsrc.read(length)
  File "C:\Users\USER\AppData\Local\Programs\Python\Python37\lib\zipfile.py", line 876, in read
data = self._read1(n)
  File "C:\Users\USER\AppData\Local\Programs\Python\Python37\lib\zipfile.py", line 966, in _read1
self._update_crc(data)
  File "C:\Users\USER\AppData\Local\Programs\Python\Python37\lib\zipfile.py", line 894, in _update_crc
raise BadZipFile("Bad CRC-32 for file %r" % self.name)
zipfile.BadZipFile: Bad CRC-32 for file 'Congrats.txt'
"""

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "C:\Users\USER\Documents\Jetbrains\PyCharm\Program\Program.py", line 38, in <module>
main(args.zip, args.file)
  File "C:\Users\USER\Documents\Jetbrains\PyCharm\Program\Program.py", line 33, in main
pool.starmap(extract_zip, [(zip, line.strip()) for line in txt_file])
  File "C:\Users\USER\AppData\Local\Programs\Python\Python37\lib\multiprocessing\pool.py", line 276, in starmap
return self._map_async(func, iterable, starmapstar, chunksize).get()
  File "C:\Users\USER\AppData\Local\Programs\Python\Python37\lib\multiprocessing\pool.py", line 657, in get
raise self._value
zipfile.BadZipFile: Bad CRC-32 for file 'Congrats.txt'

虽然发生了相同的结果;在file.txt中找到了密码,提取了zipv1.zip,但是Congrats.txt为空,大小为0kb。因此,我再次运行了程序,但是这次是zipv2.zip,结果是这样的:

(venv) C:\Users\USER\Documents\Jetbrains\PyCharm\Program>Program.py -z zipv2.zip -f file.txt
[+] Password for the .zip: dominique

multiprocessing.pool.RemoteTraceback:
"""
Traceback (most recent call last):
  File "C:\Users\USER\AppData\Local\Programs\Python\Python37\lib\multiprocessing\pool.py", line 121, in worker
result = (True, func(*args, **kwds))
  File "C:\Users\USER\AppData\Local\Programs\Python\Python37\lib\multiprocessing\pool.py", line 47, in starmapstar
return list(itertools.starmap(args[0], args[1]))
  File "C:\Users\USER\Documents\Jetbrains\PyCharm\Program\Program.py", line 16, in extract_zip
zip_file.extractall(pwd=password)
  File "C:\Users\USER\AppData\Local\Programs\Python\Python37\lib\zipfile.py", line 1594, in extractall
self._extract_member(zipinfo, path, pwd)
  File "C:\Users\USER\AppData\Local\Programs\Python\Python37\lib\zipfile.py", line 1649, in _extract_member
shutil.copyfileobj(source, target)
  File "C:\Users\USER\AppData\Local\Programs\Python\Python37\lib\shutil.py", line 79, in copyfileobj
buf = fsrc.read(length)
  File "C:\Users\USER\AppData\Local\Programs\Python\Python37\lib\zipfile.py", line 876, in read
data = self._read1(n)
  File "C:\Users\USER\AppData\Local\Programs\Python\Python37\lib\zipfile.py", line 966, in _read1
self._update_crc(data)
  File "C:\Users\USER\AppData\Local\Programs\Python\Python37\lib\zipfile.py", line 894, in _update_crc
raise BadZipFile("Bad CRC-32 for file %r" % self.name)
zipfile.BadZipFile: Bad CRC-32 for file 'Congrats.txt'
"""

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "C:\Users\USER\Documents\Jetbrains\PyCharm\Program\Program.py", line 38, in <module>
main(args.zip, args.file)
  File "C:\Users\USER\Documents\Jetbrains\PyCharm\Program\Program.py", line 33, in main
pool.starmap(extract_zip, [(zip, line.strip()) for line in txt_file])
  File "C:\Users\USER\AppData\Local\Programs\Python\Python37\lib\multiprocessing\pool.py", line 276, in starmap
return self._map_async(func, iterable, starmapstar, chunksize).get()
  File "C:\Users\USER\AppData\Local\Programs\Python\Python37\lib\multiprocessing\pool.py", line 657, in get
raise self._value
zipfile.BadZipFile: Bad CRC-32 for file 'Congrats.txt'

同样,结果相同;成功提取文件夹的位置,同时还提取了Congrats.txt以及其中包含文本且大小不变的文件。

我确实查看了this个相似的线程以及this个线程,但是它们没有帮助。我还检查了zipfile's documentation,但对于该问题没有帮助。

我不确定是什么原因导致了我的问题或如何解决该问题,并希望对此寻求帮助。

编辑

现在由于某种未知和奇怪的原因而实施了with zipfile.ZipFile(zip_filename, 'r') as zip_file:之后;该程序可以读取/处理一个小的单词列表/密码列表/字典,但是如果它的大(?)则不能。

我的意思是说{。{1}}中存在一个.txt文档;名为zipv1.zip的文本Congrats.txtYou have cracked the .zip!中也存在相同的.txt,但是这次将其放置在名为zipv2.zip的文件夹中,然后进行了压缩/密码保护。两个邮编的密码均为ZIP Contents

请注意,每个.zip都是使用dominique压缩方法和7 {zip中的Deflate加密生成的。

现在该密码在ZipCrypto(35/52行)Line 35中,在John The Ripper Jr.txt中则是Line 1968(1968/3106行)。

现在,如果您在CMD(或您选择的IDE)中执行John The Ripper.txt;它将创建一个名为python Program.py -z zipv1 -f "John The Ripper Jr.txt"的文件夹,并将Extracted放入我们先前设置的句子中。 Congrats.txt也是如此,但是zipv2将位于Congrats.txt文件夹内的ZIP Contents文件夹中。在这种情况下解压缩.zip文件没有问题。

但是,如果您在CMD(或您选择的IDE)中使用ExtractedJohn The Ripper.txt尝试相同的操作,则会创建两个压缩文件的python Program.py -z zipv1 -f "John The Ripper.txt"文件夹;就像Extracted一样,但是这次John The Ripper Jr.txt对于这两个原因都将为空,原因不明。

我的代码和所有必要的文件如下:

Congrats.txt

Program.py

zipv1.zip

zipv2.zip

John The Ripper Jr.txt

John The Ripper.txt

John The Ripper v2.txt

我不确定为什么会这样,并且在任何地方都找不到解决此问题的答案。据我所知,它是完全未知的,我找不到调试或解决此问题的方法。

无论单词/密码列表不同,这种情况都会继续发生。尝试使用相同的import argparse import multiprocessing import zipfile parser = argparse.ArgumentParser(description="Unzips a password protected .zip by performing a brute-force attack.", usage="Program.py -z zip.zip -f file.txt") # Creates -z arg parser.add_argument("-z", "--zip", metavar="", required=True, help="Location and the name of the .zip file.") # Creates -f arg parser.add_argument("-f", "--file", metavar="", required=True, help="Location and the name of the word list/password list/dictionary.") args = parser.parse_args() def extract_zip(zip_filename, password): try: with zipfile.ZipFile(zip_filename, 'r') as zip_file: zip_file.extractall('Extracted', pwd=password) print(f"[+] Password for the .zip: {password.decode('utf-8')} \n") except: # If a password fails, it moves to the next password without notifying the user. If all passwords fail, it will print nothing in the command prompt. pass def main(zip, file): if (zip == None) | (file == None): # If the args are not used, it displays how to use them to the user. print(parser.usage) exit(0) # Opens the word list/password list/dictionary in "read binary" mode. txt_file = open(file, "rb") # Allows 8 instances of Python to be ran simultaneously. with multiprocessing.Pool(8) as pool: # "starmap" expands the tuples as 2 separate arguments to fit "extract_zip" pool.starmap(extract_zip, [(zip, line.strip()) for line in txt_file]) if __name__ == '__main__': # Program.py - z zipname.zip -f filename.txt main(args.zip, args.file) 生成更多.zip,但使用来自不同单词列表/密码列表/词典的不同密码的.zip。相同的方法; .txt使用了较大和较小的版本,并且获得了与上述相同的结果。

我确实发现,如果我剪掉Congrats.txt中的前2k个单词并创建一个新的.txt,说John The Ripper.txt; .zip文件成功解压缩,出现John The Ripper v2.txt文件夹,其中出现Extracted并带有文本。因此,我认为它与密码输入后的行有关。因此,在这种情况下,Congrats.txt;在Line 1968之后脚本不会停止的地方?我不知道为什么会这样。我想这不是解决方案,而是迈向解决方案的一步...

任何帮助将不胜感激。

编辑2

所以我尝试使用“池终止”代码:

Line 1968

现在,如果我使用此两个zip,则它们都将像先前的实例一样成功提取。 这次import argparse import multiprocessing import zipfile parser = argparse.ArgumentParser(description="Unzips a password protected .zip by performing a brute-force attack using", usage="Program.py -z zip.zip -f file.txt") # Creates -z arg parser.add_argument("-z", "--zip", metavar="", required=True, help="Location and the name of the .zip file.") # Creates -f arg parser.add_argument("-f", "--file", metavar="", required=True, help="Location and the name of the word list/password list/dictionary.") args = parser.parse_args() def extract_zip(zip_filename, password, queue): try: with zipfile.ZipFile(zip_filename, "r") as zip_file: zip_file.extractall('Extracted', pwd=password) print(f"[+] Password for the .zip: {password.decode('utf-8')} \n") queue.put("Done") # Signal success except: # If a password fails, it moves to the next password without notifying the user. If all passwords fail, it will print nothing in the command prompt. pass def main(zip, file): if (zip == None) | (file == None): print(parser.usage) # If the args are not used, it displays how to use them to the user. exit(0) # Opens the word list/password list/dictionary in "read binary" mode. txt_file = open(file, "rb") # Create a Queue manager = multiprocessing.Manager() queue = manager.Queue() with multiprocessing.Pool(8) as pool: # Allows 8 instances of Python to be ran simultaneously. pool.starmap_async(extract_zip, [(zip, line.strip(), queue) for line in txt_file]) # "starmap" expands the tuples as 2 separate arguments to fit "extract_zip" pool.close() queue.get(True) # Wait for a process to signal success pool.terminate() # Terminate the pool pool.join() if __name__ == '__main__': main(args.zip, args.file) # Program.py -z zip.zip -f file.txt. 的{​​{1}}是完整的;里面有消息。但是关于zipv1.zip仍然是空的,不能说相同的话。

2 个答案:

答案 0 :(得分:1)

很抱歉长时间停顿了。看来您已经有点咸了。

1。调查

场景很复杂(我想说,与 M CVE 距离很远),可以做很多事情对此行为负责。

zipv1.zip / zipv2.zip 不匹配开始。仔细观察,看来 zipv2 也很混乱。如果对于 zipv1 Congrats.txt 是唯一的文件)来说很容易发现,对于 zipv2 “ ZIP目录/黑色-Large.png“ 的大小为 0
它可以复制任何文件,甚至更多:它适用于zf.namelist 返回的1 st 条目(不是目录)。< / p>

因此,事情开始变得更加清晰:

  • 由于 dominique 存在于密码文件中,因此文件内容正在解压缩(不知道到那时会发生什么情况)
  • 稍后, .zip 的1 st 条目被截断为 0 个字节

查看尝试使用错误密码提取文件时引发的异常,共有3种类型(其中最后2种可以组合在一起):

  1. RuntimeError:文件密码错误...
  2. 其他:
    • zlib.error:解压缩数据时出现错误-3 ...
    • zipfile.BadZipFile:文件CRC-32错误...

我创建了自己的存档文件。为了保持一致性,从现在开始我将使用它,但是所有内容也将适用于任何其他文件。

  • 内容:
    • DummyFile0.zip 10 个字节)-包含: 0123456789
    • DummyFile1.zip 10 个字节)-包含: 0000000000
    • DummyFile2.zip 10 个字节)-包含: AAAAAAAAAA
  • 使用 Total Commander 9.21a )内部 zip 打包程序存档3个文件,并使用 dominique 对其进行密码保护>( zip2.0 加密)。生成的存档(命名为 arc0.zip (但名称不相关))长 392 个字节

code.py

#!/usr/bin/env python3

import sys
import os
import zipfile


def main():
    arc_name = sys.argv[1] if len(sys.argv) > 1 else "./arc0.zip"
    pwds = [
        #b"dominique",
        #b"dickhead",
        b"coco",
    ]
    pwds = [item.strip() for item in open("orig/John The Ripper.txt.orig", "rb").readlines()]
    print("Unpacking (password protected: dominique) {:s},"
          " using a list of predefined passwords ...".format(arc_name))
    if not os.path.isfile(arc_name):
        raise SystemExit("Archive file must exist!\nExiting.")
    faulty_pwds = list()
    good_pwds = list()
    with zipfile.ZipFile(arc_name, "r") as zip_file:
        print("Zip names: {:}\n".format(zip_file.namelist()))
        for idx, pwd in enumerate(pwds):
            try:
                zip_file.extractall("Extracted", pwd=pwd)
            except:
                exc_cls, exc_inst, exc_tb = sys.exc_info()
                if exc_cls != RuntimeError:
                    print("Exception caught when using password ({:d}): [{:}] ".format(idx, pwd))
                    print("    {:}: {:}".format(exc_cls, exc_inst))
                    faulty_pwds.append(pwd)
            else:
                print("Success using password ({:d}): [{:}] ".format(idx, pwd))
                good_pwds.append(pwd)
    print("\nFaulty passwords: {:}\nGood passwords: {:}".format(faulty_pwds, good_pwds))


if __name__ == "__main__":
    print("Python {:s} on {:s}\n".format(sys.version, sys.platform))
    main()

输出

[cfati@CFATI-5510-0:e:\Work\Dev\StackOverflow\q054532010]> "e:\Work\Dev\VEnvs\py_064_03.06.08_test0\Scripts\python.exe" code.py arc0.zip
Python 3.6.8 (tags/v3.6.8:3c6b436a57, Dec 24 2018, 00:16:47) [MSC v.1916 64 bit (AMD64)] on win32

Unpacking (password protected: dominique) arc0.zip, using a list of predefined passwords ...
Zip names: ['DummyFile0.txt', 'DummyFile1.txt', 'DummyFile2.txt']

Exception caught when using password (1189): [b'mariah']
    <class 'zlib.error'>: Error -3 while decompressing data: invalid code lengths set
Exception caught when using password (1446): [b'zebra']
    <class 'zlib.error'>: Error -3 while decompressing data: invalid block type
Exception caught when using password (1477): [b'1977']
    <class 'zlib.error'>: Error -3 while decompressing data: invalid block type
Success using password (1967): [b'dominique']
Exception caught when using password (2122): [b'hank']
    <class 'zlib.error'>: Error -3 while decompressing data: invalid code lengths set
Exception caught when using password (2694): [b'solomon']
    <class 'zlib.error'>: Error -3 while decompressing data: invalid distance code
Exception caught when using password (2768): [b'target']
    <class 'zlib.error'>: Error -3 while decompressing data: invalid block type
Exception caught when using password (2816): [b'trish']
    <class 'zlib.error'>: Error -3 while decompressing data: invalid code lengths set
Exception caught when using password (2989): [b'coco']
    <class 'zlib.error'>: Error -3 while decompressing data: invalid stored block lengths

Faulty passwords: [b'mariah', b'zebra', b'1977', b'hank', b'solomon', b'target', b'trish', b'coco']
Good passwords: [b'dominique']

ZipFile.extractall代码,它尝试提取所有成员。 1 st 引发了一个异常,因此它变得更清楚为什么会如此行事。但是,当尝试使用2个错误的密码提取项目时,为什么会有行为上的差异?
从对2种引发的异常类型的追溯中可以看出,答案位于ZipFile.open的末尾。

经过更多调查,结果是由于

2。由 zip 加密弱点

确定的冲突

根据[UT.CS]: dmitri-report-f15-16.pdf - Password-based encryption in ZIP files((最后)强调是我的):

  

3.1传统的PKWARE加密

     

原始加密方案(通常称为PKZIP密码)是由   罗杰·谢菲(Roger Schaffely)[1]。在[5]中,Biham和Kocher证明密码很弱并且证明   攻击需要13个字节的纯文本。已经开发了进一步的攻击,其中一些攻击   完全不需要用户提供纯文本[6]。   PKZIP密码本质上是流密码,即通过生成伪密码对输入进行加密   随机密钥流,并将其与明文进行XOR运算。密码的内部状态包括   三个32位字中的一个: key0 key1 key2 。它们被初始化为 0x12345678 0x23456789 和   分别 0x34567890 。该算法的核心步骤涉及使用   输入单字节...

     

...

     

在加密档案中的文件之前,首先将12个随机字节添加到压缩后的文件中   内容,然后加密结果字节流。解密后,前12个字节   需要丢弃。根据规范,这样做是为了呈现纯文本   攻击对数据无效。   规范还指出,在12个前置字节中,实际上只有前11个字节   随机,最后一个字节等于未压缩的CRC-32的高位字节   文件内容。这样可以快速验证给定的密码是否正确   通过比较解密的12字节标头的最后一个字节与实际的高字节   本地文件标题中包含的CRC-32值。这可以在解密   文件的其余部分。

其他参考文献:

算法弱点:由于仅对一个字节进行了区分,对于 256 不同(并经过精心选择),错误的事实密码,将至少产生一个与正确密码相同的数字

该算法会丢弃大多数错误的密码,但有一些密码不是。

回溯:尝试使用密码提取文件时:

  • 如果在文件密码的最后一个字节上计算出的“哈希”与文件 CRC 的高位字节不同,则会引发异常
  • 但是,如果它们相等:
    • 打开了一个新的文件流以进行写入(如果已经存在,则清空文件)
    • 尝试减压:
      • 对于错误的密码(已通过上述检查),解压缩将失败(但文件已被清空)

从上面的输出中可以看到,对于我的( .zip )文件,有 8 个密码将其弄乱了。请注意:

  • 对于每个存档文件,结果都不同
  • 成员的文件名和内容是相关的(至少对于第一个 st )。更改其中任何一个都会产生不同的结果(对于“相同”存档文件)

这是基于我的 .zip 文件中的数据的测试:

>>> import zipfile
>>>
>>> zd_coco = zipfile._ZipDecrypter(b"coco")
>>> zd_dominique = zipfile._ZipDecrypter(b"dominique")
>>> zd_other = zipfile._ZipDecrypter(b"other")
>>> cipher = b'\xd1\x86y ^\xd77gRzZ\xee'  # Member (1st) file cipher: 12 bytes starting from archive offset 44
>>>
>>> crc = 2793719750  # Member (1st) file CRC - archive bytes: 14 - 17
>>> hex(crc)
'0xa684c7c6'
>>> for zd in (zd_coco, zd_dominique, zd_other):
...     print(zd, [hex(zd(c)) for c in cipher])
...
<zipfile._ZipDecrypter object at 0x0000021E8DA2E0F0> ['0x1f', '0x58', '0x89', '0x29', '0x89', '0xe', '0x32', '0xe7', '0x2', '0x31', '0x70', '0xa6']
<zipfile._ZipDecrypter object at 0x0000021E8DA2E160> ['0xa8', '0x3f', '0xa2', '0x56', '0x4c', '0x37', '0xbb', '0x60', '0xd3', '0x5e', '0x84', '0xa6']
<zipfile._ZipDecrypter object at 0x0000021E8DA2E128> ['0xeb', '0x64', '0x36', '0xa3', '0xca', '0x46', '0x17', '0x1a', '0xfb', '0x6d', '0x6c', '0x4e']
>>>  # As seen, the last element of the first 2 arrays (coco and dominique) is 0xA6 (166), which is the same as the first byte of the CRC

我使用其他拆包引擎(使用默认参数)进行了一些测试:

  1. WinRar :对于错误的密码,文件不会被修改,但是对于错误的密码,文件将被截断(与此处相同)
  2. 7-Zip :询问用户是否覆盖文件,并且不管压缩结果如何都将其覆盖
  3. 总指挥官的内部( zip )解包器:与 #2。

3。结论

  • 我将其视为 zipfile 错误。指定这样一个错误(错误)的密码不应覆盖现有文件(如果有)。或者至少,行为应该是一致的(对于所有错误的密码)
  • 快速浏览没有发现 Python
  • 上的任何错误
  • 我看不到简单的解决方法,例如:
    • zip 算法无法改进(以更好地检查密码是否正确)
    • 我想到了几个解决方法,但是它们可能会对性能产生负面影响,或者在某些(角落)情况下可能会导致性能下降

@ EDIT0

我已经提交了 [GitHub]: python/cpython - [3.6] bpo-36247: zipfile - extract truncates (existing) file when bad password provided (zip encryption weakness) ,该已关闭分支 3.6 的分支(仅在安全修补程序中< / em>模式)。不知道它的结果是什么(在其他分支机构),但是无论如何,它很快就不会可用(在接下来的几个月里)。

作为替代,您可以下载补丁,然后在本地应用更改。检查[SO]: Run/Debug a Django application's UnitTests from the mouse right click context menu in PyCharm Community Edition? (@CristiFati's answer)修补 utrunner 部分),了解如何在 Win 上应用补丁(基本上,每行以开头)一个“ +” 符号进入,以一个“-” 符号开头的每一行都熄灭)。我正在使用 Cygwin btw
如果要保留,则可以将 zipfile.py Python 的目录复制到项目(或某些“个人”)目录并修补该文件。 Python 安装原始版本。

答案 1 :(得分:0)

我遇到了这个问题,经过一番挖掘后发现,问题出在我对zip文件加密的选择。我从7-Zip,ZipCrypto提供的默认值更改为AES-256,一切都很好。