I have very strange behavior with zipfile class and I hope that someone can help me solve the problem that bothers me.
I wrote a short script which tries to open zip file encrypted by password (it was ziped by WinRar), but turned out that zipfile class does not rise an exception for several other passwords which are incorrect.
So my password for the zip file was 'evil' but zFile.extractall did not rise execpction when password was one of
'checkouts',
'disannuller',
'euornithes' or
'yamaltu'.
Additional content after extracting with zipfile class using any listed passwords were incorrect. Even WinRar does not allow unziping using those passwords.
My Python code is as follows:
import zipfile
diffrentPass = [
'wrongpass1',
'wrongpass2',
'checkouts',
'disannuller',
'euornithes',
'evil',
'yamaltu']
def extractFile(zFile, password):
try:
answer= zFile.extractall(pwd=password)
print 'Fount password : ', password
except:
pass
def main():
zFile = zipfile.ZipFile("evil.zip")
for password in diffrentPass:
extractFile(zFile, password)
if __name__ == '__main__':
main()
UPDATE :
I know that i skipped exception, but please look on out from program :
wrongpass1 was incorrect
wrongpass2 was incorrect
Fount password : checkouts
Fount password : disannuller
Fount password : euornithes
Fount password : evil
Fount password : yamaltu
Process finished with exit code 0
lines :
Fount password : checkouts
Fount password : disannuller
Fount password : euornithes
Fount password : yamaltu
should not appear at all
Adding for example :
def extractFile(zFile, password):
try:
answer= zFile.extractall(pwd=password)
print 'Fount password : ', password
except Exception, e:
print password + " was incorrect"
nothing changes in output
UPDATE + what happened
#Phil Frost Explain what happened
to be sure that it is actually the point of the my problem i add to scripts some debug prints to compare check_byte in password and file.
Example output :
#!! Wrong pass, check_byte are diffrent
# raised RuntimeError("Bad password for file", name)
Checking bytes for : wrongpass1
pass check_byte : 47
file check_byte 112
Pass is correct for zipfile class : False
#!! wrong password but for zipFile is ok , check_byte are the same
# but file will be the unpacked incorrectly
# RuntimeError("Bad password for file", name) will be not rise
Checking bytes for : checkouts
pass check_byte : 112
file check_byte 112
Pass is correct for zipfile class : True
Fount password : checkouts
#!! password ok
Checking bytes for : evil
pass check_byte : 112
file check_byte 112
Pass is correct for zipfile class : True
Fount password : evil
Code :
import zipfile, zlib, binascii, struct
from zipfile import _ZipDecrypter
diffrentPass = [
'wrongpass1',
'wrongpass2',
'checkouts',
'disannuller',
'euornithes',
'evil',
'yamaltu',
'wrongpass1',]
def extractFile(zFile, password, bytes):
print '\nChecking bytes for : ', password
zd = _ZipDecrypter(password)
h = map(zd, bytes[0:12])
print 'pass check_byte :', ord(h[11])
for item in zFile.infolist():
if item.flag_bits & 0x8:
check_byte = (item._raw_time >> 8) & 0xff
else:
check_byte = (item.CRC >> 24) & 0xff
print 'file check_byte ',check_byte
print "Pass is correct for zipfile class : " , ord(h[11]) == check_byte
try:
answer= zFile.extractall(pwd=password)
print 'Fount password : ', password
except Exception, e:
pass
def main():
# begining of ziped file must be cut off dummy method works ony on this specific zip file
# ....20111126036.jpg
bytes = open('evil.zip', 'rb').read(45+12)[-12:]
zFile = zipfile.ZipFile("evil.zip")
for password in diffrentPass:
extractFile(zFile, password,bytes)
if __name__ == '__main__':
main()
The exception is raised, but you are "swallowing it", because you do not show any error on it and just ignore it by calling "pass".
Also, there's another problem with your code, main module part is indented incorrectly.
In your current code the main() is never called because the call to the main module is part of the definition of main()
import zipfile
diffrentPass = [
'wrongpass1',
'wrongpass2',
'checkouts',
'disannuller',
'euornithes',
'evil',
'yamaltu']
def extractFile(zFile, password):
try:
answer= zFile.extractall(pwd=password)
print 'Fount password : ', password
except:
print password + " was incorrect"
def main():
zFile = zipfile.ZipFile("evil.zip")
for password in diffrentPass:
extractFile(zFile, password)
if __name__ == '__main__':
main()
I'm guessing the goal of this program is to brute-force the password out of a zip file. I'm guessing that you have a longer list of passwords that you have tried, and just the few listed in the question are not raising exceptions, while you have many more that behaved as expected.
It seems to me that as zipfile is implemented, you have a 1 in 255 chance of a password being accepted, and thus not raising an exception. This is because the password is validated by checking a 1-byte checksum:
if ord(h[11]) != check_byte:
raise RuntimeError("Bad password for file", name)
(full source)
Edit: after further research, this could be a duplicate question.
As far as I'm aware, zip encryption is weak and easily broken through means other than brute-force. However, I've never had a reason to do it myself and I don't know the particulars of what you are trying to accomplish, so I can't suggest a more specific solution.
It looks like you are explicitly discarding any exception that might be raised, here:
try:
answer= zFile.extractall(pwd=password)
print 'Fount password : ', password
except:
pass
if zFile.extractall() raises an exception, then the except: block is executed. Your except block contains pass, which in python means "do nothing" or "no-op".
You have ignored the exception in your code. If you want it to raise exception, then:
def extractFile(zFile, password):
try:
answer= zFile.extractall(pwd=password)
print 'Fount password : ', password
except Exception, e:
# do something here before raising exception
raise e
Or do not use try except block at all.
Edit after comment
If you want to report that password is wrong then you have to do that in except block, because when zFile.extractall(pwd=password) is executed exception is already thrown for the bad password, so the print will never executed.
def extractFile(zFile, password):
try:
answer= zFile.extractall(pwd=password)
print 'Password "%s" is correct' % password
except Exception, e:
print 'Password "%s" is incorrect' % password
pass
try:
zFile.extractall(pwd=password)
print 'Fount password : ', password
except:
pass
I removed the "answer =", it didn't make any sense.
Also if you want a way out of the exception handler loop you could do this:
def zipExit(password):
print 'Password found: '+password
exit(0)
def extractFile(zFile, password)
try:
zFile.extractall(pwd=password)
zipExit(password)
except:
pass
def main():
....the rest of your code here.
And for a password cracker (if you're using linux, but I'm asuming not since you use winRar) you don't want to print failed attempts to the screen, that is why the exception handler passes instead of printing something.
Because you could point the program to output into a file.
~/python zipcrack.py > cracked.password
something like this.
Related
there's a function which called getpass which asks you to provide a password inside a input() and then it returns the password.
I'm trying to cast a string as a getpass object. without using an input.
I'm communicating with telethon api
Whenever I try to use anormal string as my password I endup with the message "Couldn't login"
you can view the code here:
try:
obj.client.sign_in(obj.user.phone, code = code)
except SessionPasswordNeededError:
try:
obj.client.sign_in(password=obj.client.cloud)
except:
print("Couldn't log")
But when I use
try:
obj.client.sign_in(obj.user.phone, code = code)
except SessionPasswordNeededError:
try:
passw = getpass.getpass()
obj.client.sign_in(password=passw)
except:
print("Couldn't log")
I get no exception and all is working good.
therefore I know getpass is not returning a normal string and I need to cast my string to a getpass object
Is there any option to do that?
Thanks in advance!
------Edit------
as #Chris mentioned in the comments, getpass returns a normal string. The problem was with the "obj.client.cloud" it had a line break inside of it that's why when I've printed both strings I thought they were the same.
You can check the object type using type(obj) as #Chris pointed.
and you can check if both are the same using ("string" == getpass.getpass()) and it will return if true.
I need help with this code as I don't know where I've gone wrong with this as I want the if statement to read abc first then def after so then it can say access granted. Here is the code below:
file=open("test.txt","r")
username = input("enter username")
if file.read() == username:
print("Enter password")
else:
print("enter password")
password = input()
if file.read() == password:
print ("acsess granted")
else:
print ("access denied")
Here is the text file contents:
abc
def
The problem that I'm getting with this is that it will always output access denied where as both abc and def have been in both separate lines. I have used f.readlines() however this also outputs the same message. Putting a \n in the code will result in this error message:
Traceback (most recent call last):
File "/Users/boys/Documents/test.py", line 8, in <module>
if file.read('\n') == password:
TypeError: integer argument expected, got 'str'
Note: I will have to have more than one username and password for this, and a admin username and admin password.
The problem is that readline() includes the newline (\n) at the end. The splitlines() function is one way to work around this:
file=open("test.txt","r")
text = file.read().splitlines()
username = input("enter username")
if text[0] == username:
print("Enter password")
password = input()
if text[1] == password:
print ("acsess granted")
else:
print ("access denied")
else:
print("Wrong username!")
EDIT: I also fixed the logic so that an incorrect password but correct username no longer prints "access granted" (which I assume was not the OP's intended beahvior).
First, your code has a security issue - your user is able to recognize correct username without yet entering a password.
Second, it is a little complicated, so I give you another one
with open("test.txt") as inp:
u_name = inp.readline()
p_word = inp.readline()
username = input("Enter username: ")
password = input("Enter password: ")
if username == u_name.strip() and password == p_word.strip():
print("Access granted")
else:
print("Access denied")
Some explanation:
Use a context manager (with) instead of direct open() - it safely closes your file in all situations and gives you other advantages.
"r" is the default, so you may omit it in open() function.
strip() function strips out whitespace symbols (spaces, tabs, newlines, ...) from both ends of a string.
I would comment on Brendan's post, but I still don't have enough rep to add comments, so I'm throwing this into an answer.
A couple other corrections I would suggest is to use RAW_INPUT() over INPUT(), so that you don't need to include quotes when entering in your information. RAW_INPUT assumes a string, while input assumes a number or variable if the quotes are not included.
Also, your first else statement is misleading you (from a validation standpoint). While testing your code, you should have them saying something a little different, maybe adding a number indicator to see which part of the statement the logic hit.
Hello I am trying to make 'try' only work under one condition:
try:
print "Downloading URL: ", url
contents = urllib2.urlopen(url).read()
except:
message = "No record retrieved."
print message
return None
I do not want the above code to work if the kwarg nodownload is True.
So I have tried the following:
try:
if nodownload:
print "Not downloading file!"
time.sleep(6)
raise
print "Downloading URL: ", url
contents = urllib2.urlopen(url).read()
except:
message = "No record retrieved."
print message
return None
The above always downloads no matter if the --nd argument is passed in the command line. The below always skips the file rather the argument is passed or not.
if not nodownload:
print "Not downloading file!"
time.sleep(6)
raise
print "Downloading URL: ", url
contents = urllib2.urlopen(url).read()
except:
message = "No record retrieved."
print message
return None
No download is input at the command line:
parser.add_argument('--nodownload', dest='nodownload', action='store_true',
help='This doesn't work for some reason')
You can use raise to cause an exception when you need to, thus making the try fail.
As others have mentioned, one can raise an exception.
Apart from using predefined exceptions, you may also use your own:
class BadFriend(Exception):
pass
class VirtualFriend(Exception):
pass
class DeadFriend(Exception):
pass
try:
name = raw_input("Tell me name of your friend: ")
if name in ["Elvis"]:
raise DeadFriend()
if name in ["Drunkie", "Monkey"]:
raise BadFriend()
if name in ["ET"]:
raise VirtualFriend()
print("It is nice, you have such a good friend.")
except BadFriend:
print("Better avoid bad friends.")
except VirtualFriend:
print("Whend did you shake hands with him last time?")
except DeadFriend:
print("I am very sorry to tell you, that...")
You can even pass some data via raised exception, but be careful not to abuse it too far (if
standard structures are working, use simpler ones).
I have attempted to get this code working in Python 3.5.1 but I am having problems with it not writing the hashed password and username to the file specified. Is there something I'm doing wrong?
import sys
import hashlib
import getpass
def main():
print ('\nUser & Password Storage Program v.01\n')
if input('The file will be modieifed if it exists.\nDo you wish to continue (Y/N): ') not in ('Y','y'):
sys.exit('\nChanges were not recorded\n')
user_name = input(str('Please Enter a User Name: '))
pwdinput = input("Now enter a password:").encode('utf-8')
password = hashlib.sha224(pwdinput).hexdigest()
try:
f = open(passfile.txt,'a+')
f.write(user_name + '\n')
f.write(password + '\n')
f.close()
except:
sys.exit('There was a problem writing to the file!')
print ('\nPassword safely stored in passfile.txt.\n')
main()
You don't have a variable called passfile.txt, and that is making the open call fail. It would be correctly opening the file if you surrounded it in quotes, like 'passfile.txt'
The reason this syntax error isn't obvious is because you have a catch all, and your program will just print 'There was a problem writing to the file!' instead.
Rather than catch all exceptions using except:, use the syntax except IOError:, as that will be thrown whenever there is an actual error in writing to the file.
The error is that your open() function is taking an object as a parameter, but you probably meant to use it as a string.
Also, you generally should use a with block when opening files.
try:
with open("passfile.txt",'a+') as f:
f.write("{}\n{}\n".format(user_name, password))
except Exception as e: # Use other exceptions for more accurate results
sys.exit('There was a problem writing to the file!\nError: {}'.format(str(e)))
So i'm making a little app here, and I have try blocks (because I need to see if a file already exists or should be created). Although... my try block is repeating for some reason! I have ABSOLUTELY no idea why this is happening. Please help?
Also, the file is created fine :)
Code:
import sys
import time
Version = "V0.1"
def user():
PISBNdat = open("PISBN.dat", "w")
PISBNdat.write(Version)
cuser = raw_input("Please enter account username!")
for line in PISBNdat:
print "Test"
if cuser in line:
print("User already exists! Try again!")
user()
def start():
print "Hello and welcome to Plaz's PISBN!"
print "Opening file..."
time.sleep(0.8)
try:
fin = open("PISBN.dat", "r")
print "Success!"
fin.close()
user()
except:
time.sleep(0.5)
print "Did not recognize/find file!"
time.sleep(0.1)
print "Creating file!"
time.sleep(0.5)
try:
fout = open("PISBN.dat", "w")
print "Success!"
fout.close()
user()
except:
print "Failed!"
exit()
start()
And here's the output...:
Hello and welcome to Plaz's PISBN!
Opening file...
Did not recognize/find file!
Creating file!
Success!
Please enter account username! [This is what I entered: Plazmotech]
Failed!
Now obviously, since it said 'Failed!', it means its running my try block... because thats the only place it could output 'Failed!' So please help here!
Catch only the exceptions you want to handle. Note that printing "Failed!" and exiting is not handling an exception. Python's going to do that anyway, plus it's going to give you a buttload of information as to what happened, so why write extra code that does less and hides the cause of the problem?
As somebody (who just deleted his post) pointed out before, you call user() again in your user function, which is likely by mistake here.
I however believe your problems lie somewhere else. I assume you want "PISBN.dat" to contain a database where you look up for accounts. However, opening the file with only write permission will not help there. This causes your loop "for line in PISBNdat:" not working at all, so that the message "Test" did not appear.
It makes me think that "raw_input" failed and exception is caught. But as kindall pointed out, your code has some design flaws.
Here's an example of start() with correct try...except usage:
def start():
print "Hello and welcome to Plaz's PISBN!"
print "Opening file..."
time.sleep(0.8)
try: #try bloc contains minimum amount of code to catch the pertinent error.
f = open("PISBN.dat", "r")
print "Success!"
except IOError: #Only catch the exceptions you want to handle. IOError, in this case
f = None
if not f:
print "Did not recognize/find file!"
print "Creating file!"
try:
f = open("PISBN.dat", "w")
print "Success!"
except IOError:
print "Failed!"
exit()
f.close()
user() #Call user() after the file has been tested and/or created.