Help little sister crack the encrypted compressed package -- brute force cracking dictionary generation

Posted by visualed on Tue, 08 Mar 2022 13:58:15 +0100

 

introduction

Some time ago, a young lady downloaded an encrypted compressed package resource, which is the latest movie in release, so she found me and asked me to help her crack it.

The blogger thought it was not easy, so he went to the Internet to find a compressed package password cracking software, but when using it, he found that he cracked it with a violent cracking dictionary. As a result, the software download package didn't come with it.

It's not easy to generate a cracking dictionary and let the program do it~~~

Sad journey I -- pure digital dictionary

According to "data analysis" (i.e. unreliable data inference), the length of encrypted password generally does not exceed 6 bits, which is generally in digital form. Then you can directly use range to generate from 0 to 999999, and then make a format, as shown in the following code.

with open('violence_breaks_dictionary.txt','w') as f:
    for i in range(0,1e6):
        f.write('{}\n'.format(i))

Easily handle the pure digital dictionary, put it into the cracking software and crack it. After the program runs, it is found that no password is correct. Then we experimented with 7-bit pure numbers and 8-bit pure numbers...... Even 11 digit pure numbers (generally 11 digits for mobile phone numbers) are wrong.

It can be seen that the password may not be in the form of pure numbers, but may be a combination of uppercase letters, lowercase letters and numbers.

Sad Journey II - letter + number dictionary

The form of letters + numbers is really a little brain consuming, because it is necessary to generate all combinations of 1-6 bits at one time. It is obviously impossible to do it directly by using for or while loops. (ps: actually, it's OK, but that method is a little inconsistent with the basic quality of a program APE)

number=[str(i) for i in range(10)] # number
ALPHABET=[chr(i) for i in range(65,26+65)] # capital
alphabet=[chr(i) for i in range(97,97+26)] # Lowercase letters
char_set=('',)+tuple(number+ALPHABET+alphabet)
with open('violence_breaks_dictionary.txt','w') as f:
    for i1 in char_set:
        for i2 in char_set:
            for i3 in char_set:
                for i4 in char_set:
                    for i5 in char_set:
                        for i6 in char_set:
                            f.write(f'{i1}{i2}{i3}{i4}{i5}{i6}\n')

So, the question is, how to use limited code to generate a brute force dictionary with all possible combinations of 1 to 6 bits in the form of letters and numbers?

Lying in bed, someone thought of a great magic, that is recursion.

So there is a version of the code, as shown below.

number=[str(i) for i in range(10)] # number
ALPHABET=[chr(i) for i in range(65,26+65)] #capital
alphabet=[chr(i) for i in range(97,97+26)] #Lowercase letters
char_set=tuple(number+ALPHABET+alphabet)

nl = []

def gan_number(n):
    if n==1:
        nl.extend(char_set)
        yield char_set
    else:
        for i in char_set:
            char_item=[i+item_ for item in gan_number(n - 1) for item_ in item]
            nl.extend(char_item)
            yield char_item

print(list(gan_number(6)))
print(nl)

Ran for a long time... It seems that there is no problem when looking at the final nl output, but there are too many data, so test gan_number(2).

The result is obviously not good, because the data of n=1 is repeated many times, so what to do is very simple, Gan_ The call of number (n - 1) might as well go into the loop and let him call it only once ~ ~ ~ r

number=[str(i) for i in range(10)] # number
ALPHABET=[chr(i) for i in range(65,26+65)] #capital
alphabet=[chr(i) for i in range(97,97+26)] #Lowercase letters
char_set=tuple(number+ALPHABET+alphabet)

nl = []

def gan_number(n):
    if n==1:
        nl.extend(char_set)
        yield char_set
    else:
        gan_=gan_number(n - 1)
        for i in char_set:
            char_item=[i+item_ for item in gan_ for item_ in item]
            nl.extend(char_item)
            yield char_item

print(list(gan_number(6)))
print(nl)

Then, how can things be so simple? Too young,too simple

What's the matter? Why doesn't the code play cards according to the routine ~ young man, don't talk about martial ethics. (just kidding ~)

What's going on, so I have to talk about python iterators (please refer to this article) Yes, I have said it in detail here. I won't repeat it here.

So the key problem here is that the iterator is a "burn after reading" thing. To put it bluntly, the data can only be extracted once.

So what to do? It can only cancel the iterator feature. In short, it is to take out all the data, and then let him execute the following for loop.

number=[str(i) for i in range(10)] # number
ALPHABET=[chr(i) for i in range(65,26+65)] #capital
alphabet=[chr(i) for i in range(97,97+26)] #Lowercase letters
char_set=tuple(number+ALPHABET+alphabet)

nl = []

def gan_number(n):
    if n==1:
        nl.extend(char_set)
        yield char_set
    else:
        gan_=tuple(gan_number(n - 1))
        for i in char_set:
            char_item=[i+item_ for item in gan_ for item_ in item]
            nl.extend(char_item)
            yield char_item

print(list(gan_number(6)))
print(nl)

In this way, we get the results we need. Finally, we only need to save the nl data as a file.

number=[str(i) for i in range(10)] # number
ALPHABET=[chr(i) for i in range(65,26+65)] #capital
alphabet=[chr(i) for i in range(97,97+26)] #Lowercase letters
char_set=tuple(number+ALPHABET+alphabet)

nl = []

def gan_number(n):
    if n==1:
        nl.extend(char_set)
        yield char_set
    else:
        gan_=tuple(gan_number(n - 1))
        for i in char_set:
            char_item=[i+item_ for item in gan_ for item_ in item]
            nl.extend(char_item)
            yield char_item

print(list(gan_number(6)))
with open('violence_breaks_dictionary.txt','w') as f:
    for item in nl:
        f.write(item+'\n')

Topics: Python