【发布时间】:2023-03-03 19:38:01
【问题描述】:
我正在尝试提取一个受密码保护的 .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)
但是,如果我使用与 zipv1.zip 相同的方法进行另一个压缩 (zipv2.zip),唯一的区别是 Congrats.txt 位于一个文件夹中,该文件夹与 Congrats.txt 一起压缩,我确实得到与 @987654352 相同的结果@ 但这次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:;该程序可以读取/处理一个小的单词列表/密码列表/字典,但如果它很大(?)则不能。
我的意思是说zipv1.zip中存在一个.txt文档;命名为Congrats.txt,文本为You have cracked the .zip!。 zipv2.zip 中也存在相同的 .txt,但这次放在名为 ZIP Contents 的文件夹中,然后进行压缩/密码保护。两个拉链的密码都是dominique。
请注意,每个 .zip 都是使用 Deflate 压缩方法和 ZipCrypto 加密在 7zip 中生成的。
现在密码在Line 35(35/52 行)John The Ripper Jr.txt 和Line 1968 中用于John The Ripper.txt(1968/3106 行)。
现在,如果您在 CMD(或您选择的 IDE)中执行 python Program.py -z zipv1 -f "John The Ripper Jr.txt";它将创建一个名为Extracted 的文件夹并将Congrats.txt 与我们之前设置的句子放在一起。 zipv2 也是如此,但 Congrats.txt 将位于 ZIP Contents 文件夹中,该文件夹位于 Extracted 文件夹内。在这种情况下,提取 .zip 没有问题。
但是,如果您在 CMD(或您选择的 IDE)中使用 John The Ripper.txt 即 python Program.py -z zipv1 -f "John The Ripper.txt" 尝试相同的操作,它将在两个 zip 中创建 Extracted 文件夹;就像John The Ripper Jr.txt 一样,但这次Congrats.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)
我不确定为什么会发生这种情况,也无法在任何地方找到此问题的答案。据我所知,它完全未知,我找不到调试或解决此问题的方法。
无论单词/密码列表如何,这种情况都会继续发生。尝试使用相同的Congrats.txt 生成更多.zip,但使用来自不同单词列表/密码列表/字典的不同密码。同样的方法;使用了较大和较小版本的 .txt,并获得了与上述相同的结果。
但是我确实发现如果我删掉John The Ripper.txt 中的前2k 个单词并制作一个新的.txt;说John The Ripper v2.txt; .zip 解压成功,Extracted 文件夹出现,Congrats.txt 出现,其中包含文本。所以我相信它与密码后的行有关。所以在这种情况下Line 1968; Line 1968 之后脚本在哪里没有停止?我不确定为什么这会起作用。我猜这不是解决方案,而是迈向解决方案的一步......
编辑 2
所以我尝试使用“池终止”代码:
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.
现在,如果我使用它,两个 zip 都将成功提取,就像之前的实例一样。 但是这次zipv1.zip的Congrats.txt完好无损;里面有消息。但不能说zipv2.zip 仍然是空的。
【问题讨论】:
-
你能分享你的 ZIP 文件吗?
-
我能够在两个 .zip 文件上成功运行代码,无一例外,文件被提取,使用一个虚拟 file.txt 组成12 行(其中一行显然是 dominique)。
-
我也倾向于 subprocess 假设。但是我能够使用新的 .txt 文件运行程序,我什至用 将它加倍(也尝试了 0、1、2 次出现 dominique) Python 3.6 和 3.7 32/64,(支持 f 字符串),但它仍然作品。 :(