整理资料时发现几个 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. Mac音频播放

    Mac音频播放 audioqueue播放pcm数据 http://msching.github.io/blog/2014/08/02/audio-in-ios-5/ audiounit播放pcm数据  ...

  2. zookeeper 事务日志查看

    在version下的日志是二进制文件,查看需要转换 创建/data/middleware/zookeeper-3.4.14/translog.sh 脚本 格式化命令: java -classpath ...

  3. day 08 预科

    目录 可变和不可变 不可变类型 可变类型 可变: 列表/字典 ---->值变id不变 不可变: 数字/字符串 ---->值变id也变 列表的内置方法 字典的内置方法 可变和不可变 可变和不 ...

  4. 搭建docker本地仓库

    如果没有创建docker环境的话,需要先安装docker环境. 1. 使用命令创建容器 docker run -d -p 8081:8080 atcol/docker-registry-ui 8081 ...

  5. ng add ng-zorro-antd 安装时报错 已经是管理员还需要权限Error: EPERM: operation not permitted, lstat 'C:\ngWorkspace\qd\node_modules\fsevents\node_modules'

    Error: EPERM: operation not permitted, lstat 'C:\ngWorkspace\qd\node_modules\fsevents\node_modules' ...

  6. MyBatis日记(四):MyBatis——insert、update、delete、select

    MyBatis简单增删改查操作,此处所做操作,皆是在之前创建的MyBatis的Hello world的工程基础上所做操作. 首先在接口文件(personMapper.java)中,添加操作方法: pa ...

  7. 网页代码编辑器Blocs for mac如何进行行的控制?

    行是Blocs应用程序中的关键结构元素之一,它们是列和Bloc容器,它们构成了构建站点布局的基础.在本篇文章中,我们介绍的是网页代码编辑器Blocs for mac如何进行行的控制? ] 网页代码编辑 ...

  8. ThinkPHP支持的4种路由模式

    下面这个说法和示例,比较具有总结性.

  9. 微服务:springboot与swagger2的集成

    现在测试都提倡自动化测试,那我们作为后台的开发人员,也得进步下啊,以前用postman来测试后台接口,那个麻烦啊,一个字母输错就导致测试失败,现在swagger的出现可谓是拯救了这些开发人员,便捷之处 ...

  10. Django REST framework —— 权限组件源码分析

    在上一篇文章中我们已经分析了认证组件源码,我们再来看看权限组件的源码,权限组件相对容易,因为只需要返回True 和False即可 代码 class ShoppingCarView(ViewSetMix ...