整理资料时发现几个 zip 文件的密码忘记了,于是尝试用python暴力破解

首先是读取和解压zip文件,使用 zipfile 库

import zipfile
z = zipfile.ZipFile(r'./file.zip')
z.extractall(pwd=password.encode('utf-8'))

定义一个密码元字符串,每次从里面取出一些字符,比如:

meta_str = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'

随机密码

使用 random.sample 生成指定长度的密码,然后出现过的密码放入一个 set

choiced_set = set()
rand_str = ''.join(random.sample(meta_str, 4))
if rand_str not in choiced_set:
choiced_set.add(rand_str)

为了不断的产生密码并尝试解压,此处应该有循环,那么将尝试解压和生成密码封闭为函数:

import zipfile
import random meta_str = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'
choiced_set = set() def guess(z, password):
try:
z.extractall(pwd=password.encode('utf-8'))
print('guessed pwd: {}'.format(password))
return True
except Exception:
print('invalid password [{}]'.format(password))
return False def main():
z = zipfile.ZipFile(r'./file.zip')
while True:
rand_str = ''.join(random.sample(meta_str, 4))
if rand_str not in choiced_set:
choiced_set.add(rand_str)
if guess(z, rand_str):
raise Exception('found')

此方法代码里固定写了只支持4个字符长度,若密码不是4个字符,则会无止境的循环下去,显然不科学。

为了支持n位密码字符,需对代码稍加修改:

  1. 增加n位字符, for x in range(n) 可以解决
  2. n位密码长度的中止条件

密码个数

由于将生成的密码全部放入set,所以只需要判断set的长度,就知道当前生成了多少密码。

而密码字符可以重复,所以'abcd' 可生成的2位密码有:

'aa', 'ab', 'ac', 'ad',
'ba', 'bb', 'bc', 'bd',
'ca', 'cb', 'cc', 'cd',
'da', 'db', 'dc', 'dd,

相当于对字符串'abcd' 和 'abcd' 作笛卡尔积,那么一共是 len('abcd') * len('abcd') = 16 个密码,

所以n位密码的个数就是 len(meta_str) ** n

random.sample 不支持重复字符,替换为 numpy.random.choice(sq, n, replace=True)

引入 numpy 并修改 main 函数:

def main():
z = zipfile.ZipFile(r'./file.zip')
meta_str_len = len(meta_str)
meta_str_list = list(meta_str)
while True:
for n in range(1, 5):
while len(choiced_set) != meta_str_len ** n:
rand_str = ''.join(np.random.choice(meta_str_list, n, replace=True))
if rand_str not in choiced_set:
choiced_set.add(rand_str)
if guess(z, rand_str):
raise Exception('found')
choiced_set.clear()

耗时

以上代码虽然可以正常运行,但是解一个4位长度的密码需要计算 62 * 62 * 62 * 62 = 14776336 次,而且随着 choiced_set 的增长,生成非重复密码的概率越来越低,几乎是一个不可能完成的任务。

字母顺序密码

如果按顺序生成密码,总有一个密码能满足条件,比如: 元字符'abcd'生成2位密码,是一个笛卡尔积,其实就是一个字符全排列的过程,所以这里可以使用深度优先算法生成字符

调用 dfs_str(0) 即可不断生成 4 位长度的密码

一个简单的栗子:

def guess(v):
if v == 'abcd':
print('guessed pwd: {}'.format(v))
return True
else:
print('invalid pwd: {}'.format(v))
return False meta_str = 'abcd1234'
chars = []
def dfs_str(step):
if step >= 4:
if guess(''.join(chars)):
raise Exception('found')
return
for ch in meta_str:
chars.append(ch)
dfs_str(step + 1)
chars.pop()

密码生成器

使用这种方式 guess 函数处于深度优先搜索算法中,耦合紧密,那么有没有办法一次生成一个密码,然后传给 guess 呢?当然是有的,这时候轮到生成器出场了

实现一个密码生成器,只需要一些小的改动,在函数里增加 yield 关键字

def dfs_str_gen(step):
if step >= 4:
yield ''.join(chars)
return
for ch in meta_str:
chars.append(ch)
yield from dfs_str_gen(step + 1)
chars.pop()

密码生成器类

上面的代码已经限定了只能生成 4 位长度的密码,然而我们的密码可能是 1 2 3 4 5 甚至8位以上,难道每次都要手动修改吗?或者是在 dfs_str_gen 里传入参数?

当然传参可以,离我的目标很近了,然而更好的办法是包装成一个 class, 初始化时传入想要生成密码的长度:

class PasswordGenerator:
meta_str = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'
def __init__(self, n=4):
self.maxlen = n
self.endstr = self.meta_str[-1] * self.maxlen # 标记循环结束字符串
self.chars = []
self.g = self._proxy_gen() def _dfs_str(self, step):
if step >= self.maxlen:
yield ''.join(self.chars)
return
for ch in self.meta_str:
self.chars.append(ch)
yield from self._dfs_str(step + 1)
self.chars.pop() def _proxy_gen(self):
while True:
yield from self._dfs_str(0) def __iter__(self):
return self def __next__(self):
s = self.g.send(None)
if s == self.endstr:
self.g.close()
return s

调用 PasswordGenerator(n) 即可生成 n 位长度的密码

itertools 生成器

写了这么多,其实标准库 itertools 已经有了解决方案

import itertools
meta_str = 'abcdefg'
itertools.product(meta_str, repeat=4)

忘记zip密码咋办?python在手密码我有的更多相关文章

  1. Python用户名密码登录系统(MD5加密并存入文件,三次输入错误将被锁定)及对字符串进行凯撒密码加解密操作

    # -*- coding: gb2312 -*- #用户名密码登录系统(MD5加密并存入文件)及对字符串进行凯撒密码加解密操作 #作者:凯鲁嘎吉 - 博客园 http://www.cnblogs.co ...

  2. 忘记原来的myql的root的密码;

    修改的用户都以root为列.一.拥有原来的myql的root的密码: 方法一:在mysql系统外,使用mysqladmin# mysqladmin -u root -p password " ...

  3. centOS7忘记密码,修改root账号密码

    centOS7忘记密码,修改root账号密码 RHEL7 的世界发生了变化,重置 root 密码的方式也一样.虽然中断引导过程的旧方法(init=/bin/bash)仍然有效,但它不再是推荐的.“Sy ...

  4. 经典问题(c++/python)素数、杨辉三角(金字塔型)、统计单词数、简单计算器、密码安全程度、凯撒密码加密、汉诺塔 (python课设实验实例)-- biaobiao88

    [编写程序,输人一个大于2的自然数,然后输出小于该数字的所有素数组成的列表.]所谓素数,是指除了1和自身之外没有其他因数的自然数,最小的素数是2,后面依次是3.5.7.11.13... c++代码: ...

  5. 忘记VMware vcenter的Administrator@vsphere.local密码

    忘记VMware vcenter的Administrator@vsphere.local密码的解决办法一. 重置密码:ssh root@192.168.230.100Connecting to 192 ...

  6. 使用Mysql修改密码命令更改root的密码

    使用Mysql修改密码命令更改root的密码. 进入Mysql数据库命令行方式有两种方式: 方式一:在Mysql开始菜单里包含Mysql命令行客户端,只要点击输入root的密码即可进入. 方式二:在D ...

  7. 搭建web之 服务器鉴权失败,请确认服务器已启用密码鉴权并且账号密码正确?

    实例化时,登录过程中出现 服务器鉴权失败! 这是由于密码错误所致! 第一种情况:原始随机密码 第一种情况,你没有修改密码,则可以直接查找原始密码: 过程详见官网 使用密码登录的前提条件 密码: 若用户 ...

  8. ecshop2.73修改密码方法|ecshop2.73修改密码方法

    ecshop2.73修改密码方法|ecshop2.73修改密码方法 ECSHOP教程/ ecshop教程网(www.ecshop119.com) 2012-09-09   ecshop2.73正式版后 ...

  9. 利用phpmyadmin修改mysql的root密码及如何进入修改密码后的phpmyadmin

    1.利用phpmyadmin修改mysql的root密码 很多人利用phpmyadmin或者命令行来修改了mysql的root密码,重启后发现mysql登录错误,这是为什么呢?修改mysql的root ...

随机推荐

  1. 英语DYAMAUND钻石DYAMAUND单词

    dyamaund and the English words dyamaund The Vertu of the Dyamaund": Gemstones, Knowledge and Va ...

  2. Java 初始化块

    初始化块是和成员变量.成员函数一个级别的.一般用于类的初始化,也可执行其他java代码,作用和构造函数相同. 创建对象时,初始化块在构造函数之前执行. 初始化块分为普通初始化块.静态初始化块. 普通初 ...

  3. [JavaScript] js中全局标识正则表达式的lastIndex属性

    在JavaScript中使用正则表达式时,遇到一个坑:第一次匹配是true,第二次匹配是false. 因为在带全局标识"g"的正则表达式对象中,才有“lastIndex” 属性,该 ...

  4. 爬虫入门urlib,urlib2的基本使用和进阶

    python2中的urlib和urlib2 1.分分钟扒一个网页下来 怎样扒网页呢?其实就是根据URL来获取它的网页信息,虽然我们在浏览器中看到的是一幅幅优美的画面,但是其实是由浏览器解释才呈现出来的 ...

  5. 无法将“ng”项识别为 cmdlet、函数、脚本文件或可运行程序的名称。 通用解决方案

    1.找到你安装的路径 以@angular/cli 为例 (找到 ng.cmd 这个指令的具体位置) 2. 右键 这台电脑 添加路径到 系统变量的 Path中, 如下图 3.关闭所有的 cmd,并重新打 ...

  6. ondblclick和dblclick区别

    1.ondblclick是一个HTML DOM Event 对象,没有jquery也可以触发这个事件的,使用方法例如 1 <button ondblclick="xxx"&g ...

  7. Vue命名规范

    views 命名 views 文件夹下面是由 以页面为单位的vue文件 或者 模块文件夹 组成的,放在 src 目录之下,与 components.assets 同级. views 下的文件夹命名 v ...

  8. 用java刷剑指offer(数组中只出现一次的数字)

    题目描述 一个整型数组里除了两个数字之外,其他的数字都出现了两次.请写程序找出这两个只出现一次的数字. 牛客网链接 思路 链接:https://www.nowcoder.com/questionTer ...

  9. xpath+多进程爬取八零电子书百合之恋分类下所有小说。

    代码 # 需要的库 import requests from lxml import etree from multiprocessing import Pool import os # 请求头 he ...

  10. Improving Sequential Recommendation with Knowledge-Enhanced Memory Networks(知识图谱)

    本文作者:杨昆霖,2015级本科生,目前研究方向为知识图谱,推荐系统,来自中国人民大学大数据管理与分析方法研究北京市重点实验室. 引言 经常上购物网站时,注意力会被首页上的推荐吸引过去,往往本来只想买 ...