整理资料时发现几个 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. Flask框架 请求与响应 & 模板语法

    目录 Flask框架 请求与响应 & 模板语法 简单了解Flask框架 Flask 框架 与 Django 框架对比 简单使用Flask提供服务 Flask 中的 Response(响应) F ...

  2. ORACLE表、索引和分区详解

    ORACLE表.索引和分区 一.数据库表 每种类型的表都有不同的特性,分别应用与不同的领域 堆组织表 聚簇表(共三种) 索引组织表 嵌套表 临时表 外部表和对象表 1.行迁移 建表过程中可以指定以下两 ...

  3. 【Jmeter】他人总结篇链接(共八篇相关文章)

    [Jmeter]他人总结篇链接(共八篇相关文章) https://blog.csdn.net/mu_wind/article/category/9029006

  4. Mac版StarUML破解方法

    StarUML是用nodejs写的.确切的说是用Electron前端框架写的.新版本中所有的starUML源代码是通过asar工具打包而成.确切的代码位置在“%LOCALAPPDATA%\Progra ...

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

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

  6. Typora 基础的使用方法

    大标题:通过ctrl + 数字 1 2 3 ....方式,还可以通过加# 的方式 一级标题 二级标题 三级标题 最多可以有6个#号 序号标题: 有序缩进是1. + tab 回车之后自动生成下一个序号 ...

  7. http,socket,进程通信,网络通信(1)

    众所周知,网络通信本质上就是进程间通信,进程间通信有以下常见的通信方式: 1,管道pipe:管道是一种半双工的通信方式,数据只能单向流动,而且只能在具有亲缘关系的进程间使用,进程的亲缘关系通常指父子进 ...

  8. HTML&CSS基础-内联框架

    HTML&CSS基础-内联框架 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.如下图所示,在同一个路径中有两个网页 <!DOCTYPE html> < ...

  9. poj1734 Sightseeing trip(Floyd求无向图最小环)

    #include <iostream> #include <cstring> #include <cstdio> #include <algorithm> ...

  10. Linux查看文件指定行数内容

    1.tail date.log               输出文件末尾的内容,默认10行 tail -20  date.log        输出最后20行的内容 tail -n -20  date ...