Tags: python zip 

Rating:

After downloading the zipfiles, extracting it give us 100 encrypted zip files.

Extracting `begin.zip` with the given password `coolkarni` give us 3 files.
```bash
$ unzip zip_files/begin.zip
Archive: zip_files/begin.zip
[zip_files/begin.zip] filename.txt password:
extracting: filename.txt
extracting: hash.txt
extracting: pattern.txt
```

We may guess that the `filename.txt` will contains the following file to crack password, the `hash.txt` is the sha1 hash in hex string of the password and the `pattern.txt` contains the pattern of the password.

Note that the hint give us:
> *Hint*: You need to guess the password of the next zip file. However, the underscores in the pattern appear in the same positions as they do in the actual password, so you don't need to guess them. For example, the first pattern is `__0_0_`, which means that you need to guess the 3rd and 5th characters.

I have to say this is the first password cracking on the zip file in my life. At first, I have thought that from the pattern, all we need is a charset and loop on it to crack the password. But LOL. It is a huge pain! It is TOO slow. And I try to use combinations but it is the wrong way to do.

Luckily, after reading docs page about `itertools`, I choose `product` for generating pattern. Honestly, thanks for that I also knew how to expand a list into arguments by `*list` syntax.

Finally, we have this python code. This code will run about 25 seconds with Core i7 - 4xxx on my computer, but on EasyCTF server it took about 8 min ? That's weird! :-P
```python
#!/usr/bin/env python2
import zipfile
from hashlib import sha1
from itertools import product
import sys
import string

def sha1sum(m):
obj = sha1(m)
return obj.hexdigest()

def crack_pwd(pattern, hashstring):
pwd = ''
charset = []
for c in pattern:
if c == '_':
pwd += c
else:
pwd += r'%c'
if c == 'A':
charset.append(string.ascii_uppercase)
elif c == 'a':
charset.append(string.ascii_lowercase)
elif c == '0':
charset.append(string.digits)
else:
raise Exception("What is this char %r"%c)

parsed = product(*charset)
for p in parsed:
guess = pwd%p
sys.stdout.write("\r[*] Trying %r"%guess)
if sha1sum(guess) == hashstring:
return guess

raise ValueError("none")

def unzip(path, pwd):
with zipfile.ZipFile(path, 'r') as zip_ref:
ziplist = zip_ref.namelist()
zip_ref.extractall("extracted/", pwd=pwd)
for l in ziplist:
if 'flag' in l:
with open('extracted/' + l, 'r') as flag:
print("FLAG: %r"%flag.read())
sys.exit(0)

unzip('zip_files/begin.zip', 'coolkarni')

while True:
with open('extracted/filename.txt', 'r') as fntxt:
path = fntxt.read().strip()
with open('extracted/hash.txt', 'r') as hshtxt:
hashstr = hshtxt.read().strip()
with open('extracted/pattern.txt', 'r') as pttxt:
pattern = pttxt.read().strip()

print("[+] Cracking file %r with hash %r and pattern %r"%(path, hashstr, pattern))
pwd = crack_pwd(pattern, hashstr)
print("\n\tCracked with pass: %r"%pwd)
print("\tUnziping: %r"%path)
unzip(path, pwd)

# easyctf{you_must_REALLY_luv_zip_files_by_now!}
```