Bruteforce

Tema labai mėgstama "jaunųjų hackerių", nes kažkada buvo galima, ir teoriškai dabar įmanoma, nulaužinėti slaptažodžius šiuo būdu. Gal naudos ne tiek ir daug, bet technika vertinga išmokti, nes tą galima pritaikyti ir kitose užduotyse :)

Pirmas žingsnis - susigeneruoti simbolių seką

symbols = list(map(chr, range(32, 127)))

Turbūt suprasti šioje eilutėje kažką yra gan sudėtinga, bet iš tiesų čia atliekama labai paprasta operacija

  • Pasižiūrime į simbolių lentelę čia.

  • Pasakome, kad norime simbolių tarp 32 ir 126 (Paskutinio range komanda nebeima t.y. x >= 32 ir x < 127)

Galima imti ir kur kas mažiau simbolių, tačiau šitaip padengiame daugumą galimų variantų.

Sukuriame nuosavą generatorių

class Brute(object):
    symbols = list(map(chr, range(32, 126)))

    def __init__(self):
        self.cnt = len(self.symbols)
        self.current = 0

    def __iter__(self):
        return self

    def __next__(self):
        if self.current < self.cnt:
            self.current += 1
        else:
            self.current = 1

        return self.symbols[self.current - 1]

__iter__ ir __next__ (Python 3.4, 2.7 versijoje naudojamas tiesiog next) metodais mes pasakome, jog šita klasė yra iteratorius. Kadangi ji yra iteratorius, galima elgtis su juo kaip su tokiu:

    force = Brute()
    for brute in force:
        print(brute)

Rezultatas maždaug toks:

<...>
*
+
,
-
.
/
0
1
2
3
4
5
6
<...>

Tik pagrindinė įdomybė yra ta, jog jis yra amžinas kadangi neiškvietėme raise StopIteration . Tai yra dalis idėjos.

Kita idėjos dalis - sukurti amžiną tokių iteratorių grandinę. Kodas kiek bjaurokas, atsiprašau už tai, bet idėją turėtų būti lengva perprasti

class Brute(object):
    symbols = list(map(chr, range(32, 126)))

    def __init__(self):
        self.cnt = len(self.symbols)
        self.current = 0
        self.child = None
        self.extra = ""

    def __iter__(self):
        return self

    def __next__(self):
        if self.current < self.cnt:
            self.current += 1
        else:
            if not self.child:
                self.child = Brute()
            self.extra = self.child.__next__()
            self.current = 1

        return self.symbols[self.current - 1] + self.extra

Taigi trumpai tariant - kiekvienas generatorius gali turėti vieną vaiką. Jį 'pasigimdo' tada, kai vieną kartą praeina visus simbolius ir visados perduoda vaiko sugeneruotą simbolį. Kol vaiko nėra - tai tėra tuščias tarpas, kai jis atsiranda - po mažu generuoja.

Taigi paleidus seką gauname:

<...>
InR
JnR
KnR
LnR
MnR
NnR
OnR
PnR
QnR
RnR
<...>

Kaip matote, čia yra jau 3 simboliai. Palaukus ilgiau galima pasiekti didesnį skaičių.

O dabar patestuokime:

import unittest


class BruteCase(unittest.TestCase):
    def test_guess_simple_password(self):
        pwd = "test"
        force = Brute()
        for brute in force:
            if brute == pwd:
                self.assertTrue(True, "Atspėjo!")
                break

Kiek laiko užtrunka atspėti slaptažodį "test"? Maniškiui kompiuteriui - 49 sekundės :)

python apsauga generavimas bruteforce

Šarūnas Navickas

http://griaustinis.lt

Ilgalaikis programavimo entuziastas. Šiuo metu Python/Scala developeris Adform Kaunas. Domiuosi įvairiais apsimokančiais, metaeuristiniais algoritmais, bei apskritai viskuo, kas leidžia kompiuterį paversti bent šiek tiek protingu

blog comments powered by Disqus