# .py 확장자를 가진 파일 실행 모드 # >는 리다이렉션 기호: 파일 저장하는 것 !echo print \"Hello World\" > ch01/hello.py !python ch01/hello.py !cat ch01/hello.py # Interactive 모드. # ipython notebook이 좋은 예 print 'Hello World1111' port = 21 port banner = 'FreeFloat FTP Server' print '\'' print '[+] Checking for ' + banner + ' on port ' + port print '[+] Checking for ' + banner + ' on port ' + str(port) type(banner) type(port) type(str(port)) portList = [21, 22, 80, 110] # A list type(portList) portList2 = [21, 22, 80, 110, 'string'] # A list portList2 portOpen = True # A boolean type(portOpen) banner # string에서 어떤 메소드들을 사용할 수 있는지 알려줌 dir(banner) banner # 대문자로 변경 print banner.upper() # 소문자로 변경 print banner.lower() # 문자열 변경 print banner.replace('FreeFloat', 'Ability') # 문자열 찾기 print banner.find('FTP') # 문자열을 찾지 못했을 때 print banner.find('FTP2') print banner.index('FTP') print banner.index('FTP2') portList = [] portList portList.append(21) portList portList.append(80) portList.append(443) portList.append(25) portList # 이 list 자체가 정렬이 되버려서 내가 원하는 작업을 할지 못할 때가 있다. # 이 때는 slice를 이용해서 복사해야 한다. portList.sort() portList portList10 = [21, 80, 443, 25] portList10 portList11 = portList10 portList11 # 객체의 참조가 복사되어서 모두 동시에 바뀌는 것을 알 수 있다. # 쉽게 이야기하면 객체의 주소가 전달되어 portList11과 portList10이 동일한 객체를 가르키게 되는것 portList11.sort() print 'portList11 ', portList11 print 'portList10 ', portList10 portList2 = [21, 80, 443, 25] portList2 # slice 연산자인 :를 사용하면 복사가 이루어진다. portList3 = portList2[:] portList3.sort() print 'portList3 ', portList3 print 'portList2 ', portList2 portList2[:] # slice # 시작 index(포함): 끝 index(미포함) portList2[0:2] portList2 portList2[1:3] # sorting 되어진 상태 portList pos = portList.index(80) pos type(pos) print '[+] There are ' + str(pos) + ' ports to scan before 80.' print '[+] There are ' + pos + ' ports to scan before 80.' portList portList.remove(443) print portList cnt = len(portList) help(len) len? print '[+] Scanning ' + str(cnt) + ' Total Ports.' # key: value # 콤마를 기준으로 나뉜다. services = {'ftp': 21, 'ssh': 22, 'smtp': 25, 'http': 80} # 정렬이 뒤죽박죽이 되어 있습니다. # 내부적으로 해쉬값으로 저장이 되기 때문에 사용자들이 어떻게 할 수 없습니다. services type(services) services.keys() services.values() # items를 사용하면 key, value를 튜플 형태로 돌려준다. services.items() l = [1,2] l l[0] = 5 l t = (1, 3) t t[0] = 5 # 전체는 list type(services.items()) # 그 안에 요소들은 tuple type(services.items()[0]) services.items()[0] # key값으로 접근 가능 services['ftp'] # 아까와 똑같지만 services 라는 dictionary를 활용하니 # ftp라는 name만 알면 port를 자동으로 넣을 수가 있다. print '[+] Found vuln with FTP on port ' + str(services['ftp']) import socket socket.setdefaulttimeout(5) socket.setdefaulttimeout? # socket 클래스로부터 새로운 변수 s 생성 s = socket.socket() my_local_ftp = '172.16.190.128' my_local_ftp = '192.168.32.159' # ftp 서버로 접속 # 책에는 s.connect(('172.16.190.128', 21))로 써져 있는데 항상 변수를 쓰는 습관을 갖자. s.connect((my_local_ftp, 21)) !telnet 192.168.32.159 21 ans = s.recv(1024) print ans ans 'FreeFloat Ftp Server (Version 1.00)' in ans 'FreeFloat Ftp Server (Version 1.00)2' in ans # 자.. if, elif, else문이다. # 뭔가 똑같은게 반복이 되는게 느껴진다.. if ('FreeFloat Ftp Server (Version 1.00)' in ans): print '[+] FreeFloat FTP Server is vulnerable.' elif ('3Com 3CDaemon FTP Server Version 2.0' in ans): print '[+] 3CDaemon FTP Server is vulnerable.' elif ('Ability Server 2.34' in ans): print '[+] Ability FTP Server is vulnerable.' elif ('Sami FTP Server 2.0.2' in ans): print '+] Sami FTP Server is vulnerable.' else: print '[-] FTP Server is not vulnerable.' print 1337/0 # ZeroDivisionError가 안 뜨고 except 처리되어 에러 메시지가 출력된걸 확인할 수 있다. try: print '[+] 1337 / 0 = ' + str(1337 / 0) except: print '[-] Error.' # Exception, e를 추가함으로써 어떤 오류 메시지가 발생했는지 알려줌 try: print '[+] 1337/0 = ' + str(1337/0) except Exception, e: print '[-] Error = ' + str(e) import socket socket.setdefaulttimeout(2) s = socket.socket() try: s.connect(('1.1.1.1', 21)) except Exception, e: print '[-] Error = ' + str(e) # FTP 서버에 연결하여 배너를 반환하는 함수 import socket def retBanner(ip, port): try: socket.setdefaulttimeout(2) s = socket.socket() s.connect((ip, port)) banner = s.recv(1024) return banner except: return def main(): ip1 = '192.168.32.159' ip2 = '172.16.190.129' port = 21 banner1 = retBanner(ip1, port) if banner1: print '[+] ' + ip1 + ': ' + banner1 banner2 = retBanner(ip2, port) if banner2: print '[+] ' + ip2 + ': ' + banner2 if __name__ == '__main__': main() banner2 = None print banner2 if banner2: print 'I have a True' else: print 'I have a False' %%writefile main_test.py def main(): print 'echo: __name__ is', __name__ main() %%writefile main_test2.py def main(): print 'echo: __name__ is', __name__ if __name__ == '__main__': main() import main_test reload(main_test) reload(main_test2) !python ch01/main_test.py !python ch01/main_test2.py # !ls # !ls ch01 # FTP 서버에 연결하여 배너를 반환하는 함수 # 여기에서도 뭔가 반복되는게 feel 이 와야된다.. import socket def retBanner(ip, port): try: socket.setdefaulttimeout(2) s = socket.socket() s.connect((ip, port)) banner = s.recv(1024) return banner except: return def checkVulns(banner): if ('FreeFloat Ftp Server (Version 1.00)' in banner): print '[+] FreeFloat FTP Server is vulnerable.' elif ('3Com 3CDaemon FTP Server Version 2.0' in banner): print '[+] 3CDaemon FTP Server is vulnerable.' elif ('Ability Server 2.34' in banner): print '[+] Ability FTP Server is vulnerable.' elif ('Sami FTP Server 2.0.2' in banner): print '+] Sami FTP Server is vulnerable.' else: print '[-] FTP Server is not vulnerable.' return def main(): ip1 = '192.168.32.159' ip2 = '172.16.190.129' ip3 = '172.16.190.130' port = 21 banner1 = retBanner(ip1, port) if banner1: print '[+] ' + ip1 + ': ' + banner1 checkVulns(banner1) banner2 = retBanner(ip2, port) if banner2: print '[+] ' + ip2 + ': ' + banner2 checkVulns(banner2) banner3 = retBanner(ip3, port) if banner3: print '[+] ' + ip3 + ': ' + banner3 checkVulns(banner3) if __name__ == '__main__': main() # range 함수는 처음 값인 1은 포함하지만 마지막 값인 255는 포함하지 않는다. # 1 <= x < 255 라고 볼 수 있다. # 1 <= x <= 254 for x in range(1, 255): print '192.168.32.' + str(x) 2**8 portList = [21, 22, 25, 80, 110] for port in portList: print port for x in range(1, 255): for port in portList: print '[+] Checking 192.168.32.' + str(x) + ': ' + str(port) # 254 * 5 len( range(1, 255) ) * len( portList ) cnt = 0 for x in range(1, 255): for port in portList: if not x in [1]: #print '[+] Checking 172.16.190.' + str(x) + ': ' + str(port) cnt += 1 print cnt # 172.16.190.0/24 서브넷에 있는 모든 255 주소를 점검 # 서비스는 telnet, SSH, smtp, http, imap, https 점검 import socket def retBanner(ip, port): '''서버에 연결해 배너값을 돌려 받는다.''' try: socket.setdefaulttimeout(2) s = socket.socket() s.connect((ip, port)) banner = s.recv(1024) return banner except: return def checkVulns(banner): '''받은 배너값으로 취약한 버전인지 확인한다.''' if ('FreeFloat Ftp Server (Version 1.00)' in banner): print '[+] FreeFloat FTP Server is vulnerable.' elif ('3Com 3CDaemon FTP Server Version 2.0' in banner): print '[+] 3CDaemon FTP Server is vulnerable.' elif ('Ability Server 2.34' in banner): print '[+] Ability FTP Server is vulnerable.' elif ('Sami FTP Server 2.0.2' in banner): print '+] Sami FTP Server is vulnerable.' else: print '[-] FTP Server is not vulnerable.' return # main에서 ip, port 지정하여 def main(): '''이중 for문으로 ip와 port를 지정하여 retBanner 실행하고 retBanner 있으면 checkVulns 실행''' portList = [21, 22, 25, 80, 110, 443] # for x in range(1, 255): for x in range(159, 160): ip = '192.168.32.' + str(x) for port in portList: banner = retBanner(ip, port) if banner: print '[+] ' + ip + ': ' + banner checkVulns(banner) if __name__ == '__main__': main() %%writefile ch01/vuln_banners.txt 3Com 3CDaemon FTP Server Version 2.0 Ability Server 2.34 CCProxy Telnet Service Ready ESMTP TABS Mail Server for Windows NT FreeFloat Ftp Server (Version 1.00) IMAP4rev1 MDaemon 9.6.4 ready MailEnable Service, Version: 0-1.54 NetDecision-HTTP-Server 1.0 PSO Proxy 0.9 SAMBAR Sami FTP Server 2.0.2 Spipe 1.0 TelSrv 1.5 WDaemon 6.8.5 WinGate 6.1.1 Xitami YahooPOPs! Simple Mail Transfer Service Ready %%writefile ch01/vuln_banners.txt 3Com 3CDaemon FTP Server Version 2.0 Ability Server 2.34 CCProxy Telnet Service Ready ESMTP TABS Mail Server for Windows NT FreeFloat Ftp Server (Version 1.00) IMAP4rev1 MDaemon 9.6.4 ready MailEnable Service, Version: 0-1.54 NetDecision-HTTP-Server 1.0 PSO Proxy 0.9 SAMBAR Sami FTP Server 2.0.2 Spipe 1.0 TelSrv 1.5 WDaemon 6.8.5 WinGate 6.1.1 Xitami YahooPOPs! Simple Mail Transfer Service Ready Add FTP to check vulnerable version 0.1 by geun young !cat ch01/vuln_banners.txt try: f = open('ch01/vuln_banners.txt') except: print 'err' s = ' aaa ccc \t ddd \t ' print s print s.strip() # 글자수 확인하면 다른 것을 알 수 있다. print len(s), len(s.strip()) # finally로 file을 닫을 필요가 없어요. def checkVulns(banner): with open('ch01/vuln_banners.txt') as f: # for line in f.readlines(): for line in f: if line.strip('\n') in banner: print '[+] Server is vulnerable: ' + banner.strip('\n') # Error 발생 # def test_with(): # with open('ch01/vuln_banners.txt') as f: # for line in f: # print line.strip() # except Exception, e: # print e # test_with() # with open as f 테스트 해봄 try: with open('ch01/vuln_banners2.txt') as f: for line in f: print line.strip() except Exception, e: print e from contextlib import contextmanager @contextmanager def opened_w_error(filename, mode="r"): try: f = open(filename, mode) except IOError, err: yield None, err else: try: yield f, None finally: f.close() with opened_w_error("ch01/vuln_banners.txt", "r") as (f, err): if err: print "IOError:", err else: for line in f: print line.strip() with opened_w_error("/etc/passwd", "a") as (f, err): if err: print "IOError:", err else: f.write("guido::0:0::/:/bin/sh\n") %%writefile ch01/vuln-scanner.py import sys if len(sys.argv) == 2: filename = sys.argv[1] print '[+] Reading Vulnerabilities From: ' + filename # sys.argv[0] sys.argv[1] !python ch01/vuln-scanner.py vuln-banners.txt %%writefile ch01/test_confirm.py import sys import os if len(sys.argv) == 2: filename = sys.argv[1] if not os.path.isfile(filename): print '[-] ' + filename + ' does not exist.' exit(0) if not os.access(filename, os.R_OK): print '[-] ' + filename + ' access denied.' exit(0) print '[+] Reading Vulnerabilities From: ' + filename import os help(os.access) os.R_OK # 파일이 없을때 !python ch01/test_confirm.py ch01/vuln_banners_not_exist.txt # 정상적으로 파일을 읽었을떄 !python ch01/test_confirm.py ch01/vuln_banners.txt !cp ch01/vuln_banners.txt ch01/vuln_banners2.txt !chmod 000 ch01/vuln_banners2.txt # access denied 됐을때 !python ch01/test_confirm.py ch01/vuln_banners2.txt !ls -l ch01/ %%writefile ch01/vuln_scanner.py import socket import os import sys def retBanner(ip, port): try: socket.setdefaulttimeout(2) s = socket.socket() s.connect((ip, port)) banner = s.recv(1024) return banner except: return def checkVulns(banner, filename): with open(filename, 'r') as f: for line in f: if line.strip('\n') in banner: print '[+] Server is vulnerable: ' + \ banner.strip('\n') def main(): if len(sys.argv) == 2: filename = sys.argv[1] if not os.path.isfile(filename): print '[-] ' + filename + \ ' does not exist.' exit(0) if not os.access(filename, os.R_OK): print '[-] ' + filename + \ ' access denied.' exit(0) else: print '[-] Usage: ' + str(sys.argv[0]) + \ ' ' exit(0) portList = [21, 22, 25, 80, 110, 443] for x in range(159, 160): ip = '192.168.32.' + str(x) for port in portList: banner = retBanner(ip, port) if banner: print '[+] ' + ip + ': ' + banner checkVulns(banner, filename) if __name__ == '__main__': main() !python ch01/vuln_scanner.py ch01/vuln_banners.txt !python ch01/vuln_scanner.py ch01/vuln_banners2.txt !python ch01/vuln_scanner.py ch01/vuln_banners_not_exist.txt help('crypt') import crypt # victim 계정의 패스워드와 일치하는 것 확인 crypt.crypt('egg', 'HX') !cat ch01/passwords.txt !cat ch01/dictionary.txt # %%writefile ch01/test_pass.py import crypt def testPass(cryptPass): '''dictionary 파일을 읽어서 대입 word와 salt를 묶어서 암호문을 만든다. 새로 만들어진 암호문과 우리가 탈취한 암호문과 비교해서 같다면 대입 word가 원래 사용자의 암호다.''' # 제일 앞에 2개는 salt salt = cryptPass[0:2] dictionary = 'ch01/dictionary.txt' dictFile = open(dictionary, 'r') for word in dictFile: word = word.strip('\n') # crypt 메소드에 dictionary에서 읽은 라인별 word와 # salt(이건 위에서 1번만 읽으면 됨)를 넣음 cryptWord = crypt.crypt(word, salt) # 새로 만든 암호문과 우리가 얻어 온 암호문과 똑같은지 비교 if(cryptWord == cryptPass): print '[+] Found Password: ' + word + '\n' return print '[-] Password Not Found. \n' return def main(): '''암호화된 passwords 파일을 열어서 testPass를 호출하여 dictionary 방식으로 암호를 Brute Forcing 한다.''' passwords = 'ch01/passwords.txt' passFile = open(passwords) for line in passFile: # ':' 이 있을 때만 if ':' in line: # :의 앞부분은 user: victim, root user = line.split(':')[0] # : 뒤의 부분이 HX~ cryptPass = line.split(':')[1].strip(' ') print '[*] Cracking Password For: ' + user # : 뒤의 부분을 testPass에 넘겨줌. 우리가 풀어야 할 암호문 testPass(cryptPass) if __name__ == '__main__': main() s = '''victim: HX9LLTdc/jiDE: 503:100:Iama Victim:/home/victim:/bin/sh''' print s s.split(':') s.split(':')[1].strip()[0:2] # cat /etc/shadow | grep root # root:$6$ms32yIGN$NyXj0Yofkk14MpRwFHvXQW0yvUid.slJtgxHE2EuQqgD74S/GaGGs5VCnqeC.bS0MzTf/EFS3uspQMNeepIAc.:15503:0:99999:7::: !cat ch01/dictionary.txt %%writefile ch01/shadow.txt root:$6$ms32yIGN$NyXj0Yofkk14MpRwFHvXQW0yvUid.slJtgxHE2EuQqgD74S/GaGGs5VCnqeC.bS0MzTf/EFS3uspQMNeepIAc.:15503:0:99999:7::: %%writefile ch01/test_sha512.py # This source is not exactly. import os,sys import crypt import codecs from datetime import datetime,timedelta import argparse def testPass(cryptPass,user): dicFile = open ('ch01/dictionary.txt','r') ctype = cryptPass.split("$")[1] if ctype == '6': print "[+] Hash type SHA-512 detected ..." print "[+] Be patien ..." salt = cryptPass.split("$")[2] insalt = "$" + ctype + "$" + salt + "$" for word in dicFile.readlines(): word=word.strip('\n') cryptWord = crypt.crypt(word,insalt) if (cryptWord == cryptPass): time = time = str(datetime.today() - today) print "[+] Found password for the user: " + user + " ====> " + word + " Time: "+time+"\n" return else: print "Nothing found, bye!!" break def main(): parse = argparse.ArgumentParser(description=\ 'A simple brute force /etc/shadow .') parse.add_argument('-f', action='store', dest='path', \ help='Path to shadow file, example: \'/etc/shadow\'') argus=parse.parse_args() if argus.path == None: parse.print_help() else: passFile = open (argus.path,'r') for line in passFile.readlines(): line = line.replace("\n","").split(":") if not line[1] in [ 'x', '*','!' ]: user = line[0] cryptPass = line[1] testPass(cryptPass,user) if __name__=="__main__": main() !python ch01/test_sha512.py -f ch01/shadow.txt %%writefile ch01/test_512_2.py import crypt import hashlib def testPass(cryptPass): salt=cryptPass.split('$')[2] print '[i] salt = ' + salt myPass=cryptPass.split('$')[3] print 'myPass ', myPass dictFile = open('ch01/dictionary.txt', 'r') for word in dictFile.readlines(): word = word.strip('\n') cryptWord = crypt.crypt(word, '$6$' + salt + '$') print cryptWord cryptWord = cryptWord.split('$')[3] if cryptWord==myPass: print '[+] Found password: ' + word + '\n' return print '[-] Password not found.\n' return def main(): passwords = 'ch01/shadow.txt' passFile = open(passwords) for line in passFile: # ':' 이 있을 때만 if ':' in line: # :의 앞부분은 user: victim, root user = line.split(':')[0] # : 뒤의 부분이 HX~ cryptPass = line.split(':')[1].strip(' ') print '[*] Cracking Password For: ' + user # : 뒤의 부분을 testPass에 넘겨줌. 우리가 풀어야 할 암호문 testPass(cryptPass) if __name__ == '__main__': main() help('zipfile') %%writefile ch01/unzip.py import zipfile zFile = zipfile.ZipFile('ch01/evil.zip', 'r') zFile.extractall(path='tmp', pwd='secret') !rm -rf ch01/evil !ls -l ch01/ import zipfile zFile = zipfile.ZipFile('ch01/evil.zip', 'r') zFile.extract? !python ch01/unzip.py # extractall에서 path를 지정해주지 않으니 notebook이 실행된 root에 생성이 됐네. # 괜히 폴더 찾아보면서 삽질했다. # 항상 실행된 주체가 어디인지 확인할 것. 이걸로 인해 많은 삽질 발생 !ls -l tmp !ls -l evil/ !open evil/evil.jpg !cat evil/note_to_adam.txt %%writefile ch01/unzip_except.py import zipfile zFile = zipfile.ZipFile('ch01/evil.zip', 'r') try: zFile.extractall(path='tmp', pwd='orange') except Exception, e: print e !python ch01/unzip_except.py %%writefile ch01/unzip3.py import zipfile zFile = zipfile.ZipFile('ch01/evil.zip') dictionary = 'ch01/dictionary.txt' passFile = open(dictionary) for line in passFile: password = line.strip('\n') try: zFile.extractall(pwd=password) print '[+] Password = ' + password + '\n' exit(0) except Exception, e: # no operation pass !python ch01/unzip3.py %%writefile ch01/unzip_module.py import zipfile def extractFile(zFile, password): try: zFile.extractall(pwd=password) return password except: return def main(): zFile = zipfile.ZipFile('ch01/evil.zip') passFile = open('ch01/dictionary.txt') for line in passFile: password = line.strip('\n') guess = extractFile(zFile, password) if guess: print '[+] Password = ' + password + '\n' exit(0) if __name__ == '__main__': main() !python ch01/unzip_module.py %%writefile ch01/unzip_thread.py import zipfile from threading import Thread def extractFile(zFile, password): try: zFile.extractall(pwd=password) print '[+] Password = ' + password + '\n' except: pass def main(): zFile = zipfile.ZipFile('ch01/evil.zip') passFile = open('ch01/dictionary.txt') for line in passFile: password = line.strip('\n') t = Thread(target=extractFile, args=(zFile, password)) t.start() if __name__ == '__main__': main() !python ch01/unzip_thread.py import zipfile from threading import Thread from multiprocessing import Process, Queue def extractFile(zFile, password): try: zFile.extractall(pwd=password) print '[+] Password = ' + password + '\n' except: pass def main_original(): zFile = zipfile.ZipFile('ch01/evil.zip') passFile = open('ch01/dictionary.txt') for line in passFile: password = line.strip('\n') extractFile(zFile, password) def main_thread(): zFile = zipfile.ZipFile('ch01/evil.zip') passFile = open('ch01/dictionary.txt') for line in passFile: password = line.strip('\n') t = Thread(target=extractFile, args=(zFile, password)) t.start() # Queue를 사용하지 않아 똑같은 변수를 받아가서 실행하는 멍청한 multiprocess def main_multi(): zFile = zipfile.ZipFile('ch01/evil.zip') passFile = open('ch01/dictionary.txt') for line in passFile: password = line.strip('\n') result = Queue() pr1 = Process(target=extractFile, args=(zFile, password)) pr2 = Process(target=extractFile, args=(zFile, password)) pr1.start() pr2.start() pr1.join() pr2.join() def main_multi2(): zFile = zipfile.ZipFile('ch01/evil.zip') passFile = open('ch01/dictionary.txt') result = Queue() for line in passFile: result.put(line.strip('\n')) pr1 = Process(target=extractFile, args=(zFile, result.get())) pr2 = Process(target=extractFile, args=(zFile, result.get())) pr1.start() pr2.start() pr1.join() pr2.join() main_multi() main_thread() # %timeit main_multi() %timeit main_multi2() %%writefile ch01/1thread.py from threading import Thread def do_work(start, end, result): sum = 0 for i in range(start, end): sum += i result.append(sum) return if __name__ == '__main__': START, END = 0, 20000000 result = list() th1 = Thread(target=do_work, args=(START, END, result)) th1.start() th1.join() print 'Result : ', sum(result) !time python ch01/1thread.py %%writefile ch01/2thread.py from threading import Thread def do_work(start, end, result): sum = 0 for i in range(start, end): sum += i result.append(sum) return if __name__ == '__main__': START, END = 0, 20000000 result = list() th1 = Thread(target=do_work, args=(START, END, result)) th2 = Thread(target=do_work, args=(START, END, result)) th1.start() th2.start() th1.join() th2.join() print 'Result : ', sum(result) !time python ch01/2thread.py %%writefile ch01/2process.py from multiprocessing import Process, Queue def do_work(start, end, result): sum = 0 for i in range(start, end): sum += i result.put(sum) return if __name__ == '__main__': START, END = 0, 20000000 result = Queue() pr1 = Process(target=do_work, args=(START, END/2, result)) pr2 = Process(target=do_work, args=(END/2, END, result)) pr1.start() pr2.start() pr1.join() pr2.join() result.put('STOP') sum = 0 while True: tmp = result.get() if tmp == 'STOP': break else: sum += tmp print 'Result : ', sum !time python 2process.py %%writefile ch01/zipcrack.py import zipfile import optparse from threading import Thread from multiprocessing import Process, Queue def extractFile(zFile, password): try: zFile.extractall(pwd=password) print '[+] Found password ' + password + '\n' except: pass def main(): parser = optparse.OptionParser('usage%prog ' + \ '-f \ -d ') parser.add_option('-f', dest='zname', type='string', \ help='specify zip file') parser.add_option('-d', dest='dname', type='string', \ help='specify dictionary 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) passQueue = Queue() for line in passFile: passQueue.put(line.strip('\n')) pr1 = Process(target=extractFile, args=(zFile, passQueue.get())) pr2 = Process(target=extractFile, args=(zFile, passQueue.get())) pr1.start() pr2.start() pr1.join() pr2.join() if __name__ == '__main__': main() !python ch01/zipcrack.py -f ch01/evil.zip -d ch01/dictionary.txt def extractFile(zFile, password): try: zFile.extractall(pwd=password) print '[+] Password = ' + password + '\n' except: pass def main_original(): import zipfile zFile = zipfile.ZipFile('ch01/evil.zip') passFile = open('ch01/dictionary.txt') for line in passFile: password = line.strip('\n') extractFile(zFile, password) main_original()