Python与Hack之Zip文件口令破解
1.需要的库:
**import zipfile
**import optparse
**from threading import Thread
(1)zipfile:
1.1 zipfile.ZipFile(fileName[, mode[, compression[, allowZip64]]])
fileName是没有什么疑问的了。
mode和一般的文件操作一样,'r'表示打开一个存在的只读ZIP文件;'w'表示清空并打开一个只写的ZIP文件,或创建一个只写的ZIP文件;'a'表示打开一个ZIP文件,并添加内容。
compression表示压缩格式,可选的压缩格式只有2个:ZIP_STORE;ZIP_DEFLATED。ZIP_STORE是默认的,表示不压缩;ZIP_DEFLATED表示压缩,如果你不知道什么是Deflated,那么建议你去补补课。
allowZip64为True时,表示支持64位的压缩,一般而言,在所压缩的文件大于2G时,会用到这个选项;默认情况下,该值为False,因为Unix系统不支持。
1.2 zipfile.close()
说真的,这个没什么可说的,如果有的话,那就是你写入的任何文件在关闭之前不会真正写入磁盘。
1.3 zipfile.write(filename[, arcname[, compress_type]])
acrname是压缩文件中该文件的名字,默认情况下和filename一样
compress_type的存在是因为zip文件允许被压缩的文件可以有不同的压缩类型。
1.4 zipfile.extractall([path[, member[, password]]])
path解压缩目录,没什么可说的
member需要解压缩的文件名儿列表
password当zip文件有密码时需要该选项
对于简单的应用,这么多就够了。
(2)optparse:
Python 有两个内建的模块用于处理命令行参数:
一个是 getopt,《Deep in python》一书中也有提到,只能简单处理 命令行参数;
另一个是 optparse,它功能强大,而且易于使用,可以方便地生成标准的、符合Unix/Posix 规范的命令行说明。
简单流程
**首先,必须 import OptionParser 类,创建一个 OptionParser 对象:
- from optparse import OptionParser
- [...]
- parser = OptionParser()
**然后,使用 add_option 来定义命令行参数:
- parser.add_option(opt_str, ...,
- attr=value, ...)
**每个命令行参数就是由参数名字符串和参数属性组成的。如 -f 或者 –file 分别是长短参数名:
- parser.add_option("-f", "--file", ...)
**最后,一旦你已经定义好了所有的命令行参数,调用 parse_args() 来解析程序的命令行:
- (options, args) = parser.parse_args()
**注: 你也可以传递一个命令行参数列表到 parse_args();否则,默认使用 sys.argv[:1]。
parse_args() 返回的两个值:
- options,它是一个对象(optpars.Values),保存有命令行参数值。只要知道命令行参数名,如 file,就可以访问其对应的值: options.file 。
- args,它是一个由 positional arguments 组成的列表。
Actions
action 是 parse_args() 方法的参数之一,它指示 optparse 当解析到一个命令行参数时该如何处理。actions 有一组固定的值可供选择,默认是’store ‘,表示将命令行参数值保存在 options 对象里。
示例
- parser.add_option("-f", "--file",
- action="store", type="string", dest="filename")
- args = ["-f", "foo.txt"]
- (options, args) = parser.parse_args(args)
- print options.filename
最后将会打印出 “foo.txt”。
当 optparse 解析到’-f’,会继续解析后面的’foo.txt’,然后将’foo.txt’保存到 options.filename 里。当调用 parser.args() 后,options.filename 的值就为’foo.txt’。
你也可以指定 add_option() 方法中 type 参数为其它值,如 int 或者 float 等等:
- parser.add_option("-n", type="int", dest="num")
默认地,type 为’string’。也正如上面所示,长参数名也是可选的。其实,dest 参数也是可选的。如果没有指定 dest 参数,将用命令行的参数名来对 options 对象的值进行存取。
store 也有其它的两种形式: store_true 和 store_false ,用于处理带命令行参数后面不 带值的情况。如 -v,-q 等命令行参数:
- parser.add_option("-v", action="store_true", dest="verbose")
- parser.add_option("-q", action="store_false", dest="verbose")
这样的话,当解析到 ‘-v’,options.verbose 将被赋予 True 值,反之,解析到 ‘-q’,会被赋予 False 值。
其它的 actions 值还有:store_const 、append 、count 、callback 。
(3)Thread:多线程处理
Thread 类描绘了一个单独运行的控制线程活动,我们有两种方式指定这种活动,通过一个可调用对象的构造函数,或者通过覆盖子类run()方法。没有其他的方法应在子类中重写。换句话说,只有推翻这个类的__init__()和run()方法。
一旦Thread这个对象被创建,这个对象的活动必须通过 thread 的start()方法启动。这将唤起run()方法在单独的线程控制。
一旦线程的活动开始,这个线程的状态就是“alive”。当run()方法结束时才会结束“alive“状态。我们也可以直接运行 is_alive()方法判断这个进程的状态时"alive"
一个线程可以调用另一个线程的join()方法。这种叫做阻塞调用线程,直到其join()方法叫做线程终止。
一个线程的名字是通过构造器传递的,也可以通过name属性修改或者读取。
一个线程可以标记为守护线程(daemon thread),这种被标记的线程时当python程序退出时它才退出。它的最初的值时当线程被创建时继承下来的。 这个标志可以通过daemon 或者daemone constructor变量设定。
提示:daemon thread 是当程序关闭的时候立即被中断的。它时不会被适宜的释放。 如果你想让你的线程适宜的停止。可以让它non-daemonic 或者用一些适当的信号机制。
Thread 中常用的方法和变量:
1.start()
启动线程活动。
2.run()
这个方法描述线程的活动,我们可以在子类中覆盖这个方法。
3.join()
python的Thread类中还提供了join()方法,使得一个线程可以等待另一个线程执行结束后再继续运行。这个方法还可以设定一个timeout参数,避免无休止的等待。因为两个线程顺序完成,看起来象一个线程,所以称为线程的合并.
通过传给join一个参数来设置超时,也就是超过指定时间join就不在阻塞进程。而在实际应用测试的时候发现并不是所有的线程在超时时间内都结束的,而是顺序执行检验是否在time_out时间内超时,例如,超时时间设置成2s,前面一个线程在没有完成的情况下,后面线程执行join会从上一个线程结束时间起再设置2s的超时。
4.name()
5.getname(0
6.setname()
7.ident()
8.is_alive()
9.daemon
一个布尔值,指示是否该线程是damemon thread(TRUE)或不(假)。这之前必须设置start()叫,否则运行时出错了。它的初始值是从创建线程继承;主线程不是一个守护线程,因此在守护=假主线程默认创建的所有线程。
整个Python程序退出时没有活着的非守护线程离开。
10.isDaemon()
11. setDaemon()
Zip文件口令破解机的源代码:
import zipfile
import optparse
from threading import Thread
def extractFile(zFile,password):
try:
zFile.extractall(pwd=password)
print('[+] Found password'+password+'\n')
except:
pass
def main():
parser=optparse.OptionParser("usage%prog"+\
"-f <zipfile> -d <dictionary>")
parser.add_option('-f',dest='zname',type='string',\
help='specify dictionary file')
parser.add_option('-d',dest='dname',type='string',\
help='specify diction file')
(options,args)=parser.parse_args()
if(options.zname==None) | (options.dname==None):
print(parser.usage)
exit(0)
else:
zname=options.zname
dname=options.dname
zFile=zipfile.ZipFile(zname)
passFile=open(dname)
for line in passFile.readline():
password=line.strip('\n')
t=Thread(target=extractFile,args=(zFile,password))
t.start()
if __name__=='__main__':
main()
**一直没有运行出来,今天下午终于运行出来:主要采用逐行print()的方法,发现:
1.主函数没大问题,就是在for循环的时候:
for line in passFile.readline():这就错了
readline()函数是只读取一个字母的,要读取完整的字母需要readlines()函数,只差了一个“s”而已!!!!!
2.文件对象提供了三个“读”方法: .read()、.readline() 和 .readlines()。每种方法可以接受一个变量以限制每次读取的数据量,但它们通常不使用变量。 .read() 每次读取整个文件,它通常用于将文件内容放到一个字符串变量中。然而 .read() 生成文件内容最直接的字符串表示,但对于连续的面向行的处理,它却是不必要的,并且如果文件大于可用内存,则不可能实现这种处理。
3.readlines() 示例
fh = open( 'c:\\autoexec.bat') for line in fh.readlines(): print line.readline() 和 .readlines()之间的差异是后者一次读取整个文件,象 .read()一样。.readlines()自动将文件内容分析成一个行的列表,该列表可以由 Python 的 for... in ... 结构进行处理。另一方面,.readline()每次只读取一行,通常比 .readlines()慢得多。仅当没有足够内存可以一次读取整个文件时,才应该使用.readline()。
写:
writeline()是输出后换行,下次写会在下一行写。write()是输出后光标在行末不会换行,下次写会接着这行写
这次实验重点掌握的函数:
1.ZipFile.extract(member[, path[, pwd]])
将zip文档内的指定文件解压到当前目录。参数member指定要解压的文件名称或对应的ZipInfo对象;参数path指定了解析文件保存的文件夹;参数pwd为解压密码。下面一个例子将保存在程序根目录下的txt.zip内的所有文件解压到D:/Work目录:
压zip文档中的所有文件到当前目录。参数members的默认值为zip文档内的所有文件名称列表,也可以自己设置,选择要解压的文件名称。
2.strip()函数: