Главная > Программирование > Python: генератор списка паролей для перебора (brute-force).

Python: генератор списка паролей для перебора (brute-force).

При написании в очередной раз программы для подбора паролей к чему-либо (исключительно в образовательных целях и для учёбы) опять возникла необходимость в итераторе по заданному алфавиту. Т.е. необходимо написать класс, который мог бы генерировать пароли для последующей передачи их в программу, которая «примеряла» их к чему-надо. К чему – дело третье и сейчас нас (вернее вас) не волнует. В результате получился скромный класс, который приведён ниже со столь же скромными моими комментариями к нему.

Сам класс для перебора паролей ко всему и вся таков:

# -*- coding: utf-8 -*-

EN = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
en = "abcdefghijklmnopqrstuvwxyz"
RU = "АБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯ"
ru = "абвгдеёжзийклмнопрстуфхцчшщъыьэюя"
digits = "1234567890"
space = " "
p = ",.-!?;:'\"/()"
op = "+-*/:^()<>="
all_spec = "`~!@#$%^&*-_=+\\|/?.>,< '\";:[]{}" class ABCIterator: firstuse_flag = True stop = None def __init__(self, start="", stop=None, start_len=None, stop_len=None, abc=en+EN+digits+all_spec): assert len(abc) > 0
if start_len is not None:
assert start_len > 0
#assert start == ""
self.current_str = list(abc[0]*start_len)
else:
self.current_str = list(filter(lambda x: x in abc, start))
if stop_len is not None:
assert (start_len is None) or (start_len <= stop_len) assert stop_len > 0
self.stop = list(abc[0]*(stop_len+1)) # т.к. итератор работает с полуотрезками
else:
if stop is not None: self.stop = list(filter(lambda x: x in abc, stop))
self.abc = list(abc)

def __iter__(self):
return self

def next(self):
if (self.stop is not None) and (self.stop == self.current_str):
raise StopIteration
if self.current_str == []:
self.current_str.append(self.abc[0])
self.firstuse_flag = False
return self.abc[0]
elif self.firstuse_flag:
self.firstuse_flag = False
return "".join(self.current_str)
offset = 0
while offset < len(self.current_str): if self.current_str[offset] != self.abc[-1]: self.current_str[offset] = self.abc[self.abc.index(self.current_str[offset])+1] # выпендрёшь для полуотрезка if (self.stop is not None) and (self.current_str == self.stop): raise StopIteration return "".join(self.current_str) self.current_str[offset] = self.abc[0] offset += 1 self.current_str = [self.abc[0]] + self.current_str # опять же оно же if (self.stop is not None) and (self.current_str == self.stop): raise StopIteration return "".join(self.current_str)[/code] А таковы мои пояснения к нему:

  • firstuse_flag – свойство, которое указывает на то, что итератор используется впервые и не стоит производить итерацию, надо лишь вернуть текущее значени строки. Это нужно для того, чтобы в цикле не «съедалось» первое значение (напр., инициализировали итератор с начальной строкой «aaa», а при 1й же итерации он вернул бы, без этого чудесного свойства, «baa»)
  • stop – указывает на значение, на котором пора бы уже остановиться и вызвать исключение StopIteration. Если не задано (имеет значение None), то не пора, итератор будет бесконечным
  • __init__(start='', stop=None, start_len=None, stop_len=None, abc=en+EN+digits+all_spec, **kwargs) – в общем то сам конструктор. start – начальное значение, stop – конечное, если не задано или идёт до начального, то итерации происходят бесконечно. Можно так же задать начальную и конечную длину, место конкретных значений с помощью start_len и stop_len. Если задана длина и начальные значения, то приоритет будет иметь длина, что можно легко исправить, если для кого-то это критично. abc – алфавит, над которым будут производиться итерации.
  • __iter__() – необходимо для того чтобы класс был полноценным итератором.
  • next() – возвращает следующую строку, в общем-то этот метод так же необходим для того чтобы класс был итератором.

Пример использования:
[code lang="python"]>>> for i in ABCIterator(start_len=1, stop_len=3, abc="abc"):
... i
...
'a'
'b'
[...]
'bcc'
'ccc'
>>>

Ну, как-то так оно и работает. Если кому-то что-то непонятно, то могу объяснить подробнее. В общем как обычно, всё в комменты. Неплохо было бы ещё реализовать преобразование чисел в строки и наоборот, но это позже... может быть.

Update:
Python: генератор списка паролей для перебора (brute-force). Code Review.

Пожалуйста, оцените полезность и качество данной статьи. Одна звезда - плохо, 5 - хорошо.
1/5. Мы будем признательны, если вы напишете комментарий с причиной низкой оценки.2/5. Мы будем признательны, если вы напишете комментарий с причиной низкой оценки.3/5. Мы будем признательны, если вы напишете комментарий с причиной низкой оценки.4/5.5/5. (8 голосов, средний: 5,00 из 5)
Загрузка...
  1. lizz
    12 февраля 2013 в 15:14 | #1

    Полезная ссылка из старых комментариев: http://docs.python.org/library/itertools.html#itertools.product

  2. Вилен
    14 июня 2014 в 19:52 | #2

    Здравствуйте, нужно сгенерить список комбинаций длиной в 16 знаков из таких символов:

    0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ

    Общее количество комбинаций получилось

    47672401706823532720689250304

    И ни одна прога на просторах инета не способна на это(по крайней мере за 3 дня усердных поисков я такую не нашел )!!! сможете чем то помочь????????

  3. lizz
    25 июня 2014 в 11:56 | #3

    @Вилен
    3 дня - слишком маленький срок. ;) Вы посчитайте сколько это займёт места на диске. Если допустить что вам нужно 16 байт на хранение каждой комбинации, выходит что потрубется записать 630 938 йоттабайт (или 693 724 748 370 347 264 терабайт). Да, можно хранить данные в двоичном виде и уменьшить требуемый объём, но при таких цифрах - не значительно.

    Вы всё ещё уверены что вам это действительно надо?

    Если теоретизировать, то с помощью итератов в python и последовательной записи в файл эта задача решаема. Вопрос только в ограничении места на диске и времени работы программы.

  4. Corvus_Alba
    25 июля 2014 в 15:05 | #4

    @ Вилен
    http://rusfolder.com/41294784
    Сам искал подобную программу, не нашел, написал сам. Программа держит в памяти лишь 1 пароль, который постоянно изменяется, поэтому требует мало оперативной памяти для осуществления своей работы.
    Проблему с памятью, необходимой на хранение паролей частично решил: можно указать сколько паролей хранить в одном файле, а потом, когда память будет забиваться потихоньку вручную переносить уже готовые файлы на внешний носитель.
    Проблема со скоростью зависит от мощности Вашего компьютера, тут я помочь не в силах.

    P.S. - Это мой первый модуль на Python, прошу не судить строго. Программу, как и исходный код можете свободно распространять.

  5. anton
    5 сентября 2014 в 00:02 | #5

    можно с тобой пообщаться отдельно?
    @ lizz

  6. lizz
    7 сентября 2014 в 23:55 | #6

    @anton

    Можно. :)

  7. lizz
    8 сентября 2014 в 00:00 | #7

    @lizz
    Пардон, email я удалил из коммента т.к. он был похож (или такой же?) на тот, что указан в поле email, а вот на тот письма не ходят. В общем мои контакты в разделе "о блоге".

    P.S. Вообще странно указывать левый ящик в поле email и оставлять нормальный в публичном сообщении. :)

  8. Валерий
    15 мая 2015 в 17:53 | #8

    Недавно начал заниматься питоном и накидал аналогичный скрипт, но получился гораздо компактнее...
    Оцени пожалуйста на свой взгляд

    # -*- coding: utf-8 -*-

    class gen_pas( object ):
    alph = ''
    pos = 0
    s_pass = ''
    len_alph = 0
    len_min = 1
    len_max = 1
    len_now = 1

    def __init__(self, alph, len_min, len_max, pass_now):
    self.alph = alph
    self.len_alph = len(alph) - 1
    if ( len(pass_now) > len_min ):
    self.len_min = self.len_now = len(pass_now)
    else:
    self.len_min = self.len_now = len_min
    self.len_max = len_max
    self.s_pass = pass_now
    self.pos = self.len_min - 1

    def generate(self):
    if (self.s_pass == ''):
    self.s_pass = self.alph[0] * self.len_min
    elif ( self.s_pass[self.pos] == self.alph[self.len_alph] ):
    if ( self.pos == 0 ):
    if ( self.len_now == self.len_max ):
    self.s_pass = None
    else:
    self.pos = self.len_now
    self.len_now += 1
    self.s_pass = self.s_pass[0:self.pos] + self.alph[0] + self.s_pass[self.pos:]
    self.s_pass = self.alph[0] + self.s_pass[1:]
    else:
    self.s_pass = self.s_pass[0:self.pos] + self.alph[0]
    self.pos -= 1
    self.s_pass = self.generate()
    self.pos = self.len_now - 1
    else:
    self.s_pass = self.s_pass[0:self.pos] + self.alph[ self.alph.find( self.s_pass[self.pos] ) + 1 ]
    self.pos = self.len_now - 1

    if ( self.s_pass == None ):
    return self.s_pass
    else:
    return self.s_pass + ' '

    # Запускаем...
    min = 1
    max = 4
    start = '--k'
    alphabet = '0123456789abcdefghijklmnopqrstuvwxyz_-'

    print ('Начальная длина пароля - ', min )
    print ('Конечная длина пароля - ', max )
    print ('Начинаем генерировать с ', start )
    print ('Диапазон символов - ', alphabet )

    psswrds = gen_pas(alphabet, min, max, start)
    password = psswrds.generate()

    print('***************************************')
    while password != None:
    print (password)
    password = psswrds.generate()
    print('***************************************')

  9. Валерий
    15 мая 2015 в 17:54 | #9

    мляяяя все отступы просрались((((

  10. lizz
    11 июня 2015 в 20:17 | #10

    @Валерий

    Постараюсь не забыть посмотреть в ближайшее время (не смотря на то, что коммент твой был в мае :)) ). Отступы восстановлю, но вообще лучше какой-нибудь paste.bin юзать для этого.

  11. Кирилл
    27 августа 2015 в 23:32 | #11

    Я вот тоже на днях написал кое что на эту тему, получилось весьма оригинально и просто, если кое что добавить то эта прога создаст словарь и сохранит его в фаил, ну или можно вставить в готовый брути тогда она будет загружать комп раза в два меньше...
    Вот это будет работать весьма долго...
    #_*_coding: utf-8 _*_
    c=""
    sostav{1:"йцукенгшщзхэждлорпавыфячсмитьюб1234567890",2:"qwertyuioplkjhgfdsazxcvbnm1234567890",3:"йцукенгшщзхэждлорпавыфячсмитьбюЙФЫЦУКЕНГШЗЩХВАЯЧСМПРИЬТОЛБЮДЖЭ1234567890",4:"qwertyuioplkjhgfdsazxcvbnmQWERTYUOIPLKJHGFDSAMNBVCXZ",5:"1234567890",}
    sostav1=input("русские-1, английские-2, Русские-3, английские-4, числа-5:\n…")
    asdf=sostav[int(sostav1)]
    vcod="c+="
    ch="for a1 in a:\n print ('::;:::')"
    v=""
    b="\n"
    kol=["q","w","e","r","t","y","u","i","o","p"]
    inp=input('Сколько знаков?\n…')
    pr=" "
    cod="c=''\nv="+str(inp)+"\nino=v\na='"+asdf+"'\n"
    bloc="for "
    bloc2="c+="
    bloc3=" in a:\n"
    op=""
    slovar={2:[1,2],3:[1,2,3],4:[1,2,3,4],6:[1,2,3,4,5,6],5:[1,2,3,4,5],7:[1,2,3,4,5,6,7],8:[1,2,3,4,5,6,7,8],9:[1,2,3,4,5,6,7,7,9]}
    for kir in slovar[int(inp)]:
    cod+=str(bloc)+"a"+str(kir)+str(bloc3)
    cod+=kir*pr
    cod+="f=a"+str(kir)+"\n"
    cod+=kir*pr
    op+="1"
    if op=="1":
    vcod+="str(a"+str(kir)+")"
    else:
    vcod+="+"+"str(a"+str(kir)+")"
    bloc2+="+str(a"+str(kir)+")"
    cod+="if len(c)== v:\n"+str(str(pr)*int(1+int(inp)))+"v+=int(ino)+1\n"+str(str(pr)*int(1+int(inp)))+"c+='%'\n"+str(str(pr)*int(int(inp)))+str(vcod)+"\n"+"print(c)"
    print (cod)
    exec(cod)
    v=int(inp)
    c12=""
    for ty in c:
    if ty=="%":
    f=0
    else:
    if len(c12)==v:
    v+=int(inp)+1
    c12+="\n"
    c12+=ty
    print(c12) #э

    Вот это для вложение непосредственно в брут( уже быстрее)
    #_*_coding: utf-8 _*_
    c=""
    sostav{1:"йцукенгшщзхэждлорпавыфячсмитьюб1234567890",2:"qwertyuioplkjhgfdsazxcvbnm1234567890",3:"йцукенгшщзхэждлорпавыфячсмитьбюЙФЫЦУКЕНГШЗЩХВАЯЧСМПРИЬТОЛБЮДЖЭ1234567890",4:"qwertyuioplkjhgfdsazxcvbnmQWERTYUOIPLKJHGFDSAMNBVCXZ",5:"1234567890",}
    sostav1=input("русские-1, английские-2, Русские-3, английские-4, числа-5:\n…")
    asdf=sostav[int(sostav1)]
    vcod="c+="
    ch="for a1 in a:\n print ('::;:::')"
    v=""
    b="\n"
    kol=["q","w","e","r","t","y","u","i","o","p"]
    inp=input('Сколько знаков?\n…')
    pr=" "
    cod="c=''\nv="+str(inp)+"\nino=v\na='"+asdf+"'\n"
    bloc="for "
    bloc2="c+="
    bloc3=" in a:\n"
    op=""
    slovar={2:[1,2],3:[1,2,3],4:[1,2,3,4],6:[1,2,3,4,5,6],5:[1,2,3,4,5],7:[1,2,3,4,5,6,7],8:[1,2,3,4,5,6,7,8],9:[1,2,3,4,5,6,7,7,9]}
    for kir in slovar[int(inp)]:
    cod+=str(bloc)+"a"+str(kir)+str(bloc3)
    cod+=kir*pr
    cod+="f=a"+str(kir)+"\n"
    cod+=kir*pr
    op+="1"
    if op=="1":
    vcod+="str(a"+str(kir)+")"
    else:
    vcod+="+"+"str(a"+str(kir)+")"
    bloc2+="+str(a"+str(kir)+")"
    cod+="if len(c)== v:\n"+str(str(pr)*int(1+int(inp)))+"v+=int(ino)+1\n"+str(str(pr)*int(1+int(inp)))+"c+='%'\n"+str(str(pr)*int(int(inp)))+str(vcod)+"\n"+"print(c)"
    print (cod)
    exec(cod)

  1. Пока что нет уведомлений.