1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111
| # 自动读取爆破加密zip所有1-4字节文件CRC,输出文件名(密码段顺序)和结果 # 如果个别文件爆破失败,修改multiCrack中dic字典变量即可 from zipfile import ZipFile import itertools, binascii, re
def permutations_with_replacement(szDic, k): # 注意:此函数会产生非常大的列表(内存占用高),如果数据量大建议改成生成器版本 result = [] for i in itertools.product(szDic, repeat = k): result.append(''.join(i)) return result
def multiCrack(iSize, lCrcs): # 根据需要修改 dic 字符集 dic = '''abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ!-@_{}''' # 更宽泛字符集(若需要): # dic = '''abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ!"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~ ''' dResult = {} mydic = permutations_with_replacement(dic, iSize) mask = 0xFFFFFFFF for txt in mydic: crc = str(binascii.crc32(txt.encode()) & mask) if crc in lCrcs: print(f"FOUND CRC {hex(int(crc))} -> {txt}") dResult[crc] = txt # 如果对同一 crc 只需要第一个匹配,这里可以选择继续或 break return dResult
def crack(lFilesCRC): """ lFilesCRC: 列表,每项格式 'filename|size|CRC' 返回:列表形式的匹配结果和一个 filename->plaintext 的字典 """ matches_list = [] found_map = {} # filename -> plaintext
# 收集所有待爆破长度 iSizes = set([int(i.split('|')[1]) for i in lFilesCRC]) for iSize in iSizes: # 当前长度对应的所有 crc 字符串 lCrcs = [i.split('|')[2] for i in lFilesCRC if i.split('|')[1] == str(iSize)] dTMP = multiCrack(iSize, lCrcs) # 把找到的 crc 结果分配回对应文件名 for entry in lFilesCRC: fname, fsize, fcrc = entry.split('|') if fcrc in dTMP: found_map[fname] = dTMP[fcrc] matches_list.append(f"{entry} {dTMP[fcrc]}")
return matches_list, found_map
def make_concatenation(filelist, found_map): """ 按数字顺序(如果文件名是数字开头,例如 1.txt)拼接明文段。 未找到的文件会以 <MISSING:filename> 占位。 返回 (concatenated_string, missing_files_list) """ # 试着提取文件名前面的数字,作为排序键;否则按字典序 def keyfn(fname): m = re.match(r'(\d+)', fname) return (0, int(m.group(1))) if m else (1, fname)
sorted_files = sorted(filelist, key=keyfn) parts = [] missing = [] for fname in sorted_files: if fname in found_map: parts.append(found_map[fname]) else: parts.append(f"<MISSING:{fname}>") missing.append(fname) concat = ''.join(parts) return concat, missing
if __name__ == "__main__": zip_path = r"attachment.zip" myzip = ZipFile(zip_path) fInfos = myzip.filelist lFilesCRC = []
# 仅处理 file_size < 5 的短文件(1-4 字节) for fInfo in fInfos: if fInfo.file_size < 5: # 格式“文件名|原始大小|CRC”——如“1.txt|4|3463500836” lFilesCRC.append(fInfo.filename + '|' + str(fInfo.file_size) + '|' + str(fInfo.CRC))
# 执行爆破 matches_list, found_map = crack(lFilesCRC)
# 输出逐文件的匹配结果 print("==== 单段匹配结果 ====") for m in sorted(matches_list): print(m)
# 输出拼接明文(按文件名顺序) filelist = [i.split('|')[0] for i in lFilesCRC] concat, missing = make_concatenation(filelist, found_map) print("\n==== 拼接结果 ====") print(concat)
if missing: print("\n以下文件未找到对应明文:") for m in missing: print(" -", m) else: print("\n所有段已找到。")
# 如果你想把拼接结果保存为文件,取消下面注释: # with open("concatenated_plain.txt", "w", encoding="utf-8") as fw: # fw.write(concat)
|