Bluetooth Flooder per Symbian – 24/08/2009
Questa applicazione è stata creata da me per puro scopo didattico. Dovevo imparare ad utilizzare il bluetooth in Python e ho finito per creare questa simpatica applicazione.
Descrizione:
Una volta selezionato un file presente sul vostro cellulare, BT Flooder tenterà di inviarlo a tutte le periferiche bluetooth che sono nei paragi, tenendo una conta delle vittime che accettano il vostro file.
L’applicazione può essere utile per inviare un’immagine, magari un vostro sticker o una foto che volete condividere con tutti, oppure una semplice nota testo contenente un messaggio, un indirizzo di un sito internet, o qualsiasi cosa vi venga in mente.
L’applicazione supporta inoltre un filtro che permette di esonerare determinate periferiche dall’assillante invito a ricevere un file, e una funzione di logging, tramite la quale potrete conoscere, al termine dell’esecuzione, tutte le periferiche che hanno accettato il vostro file.
BT Flooder è stato scritto in Python, quindi necessita (ovviamente) che l’interprete sia installato sul vostro cellulare. Oltre a questo l’applicazione fa uso del modulo esterno LightBlue, necessario per cercare periferiche bluetooth silenziosamente. Il file di installazione è scaricabile a questo indirizzo, e va installato nella memoria interna, non sulla memory card.
– Download BT Flooder (versione .sis) –
– Download BT Flooder (versione .py) –
– Download modulo LightBlue –
Aggiornamento – 24/08/2009
Ho aggiornato l’applicazione perché presentava un bug nella codifica UTF-8. Non era infatti possibile selezionare periferiche e file con caratteri non-ASCII.
Segue il codice sorgente dell’applicazione.
import os
import e32
import sys
import socket
import appuifw
import globalui
import graphics
try:
import lightblue
except:
appuifw.note(u'Modulo lightblue non trovato.', 'error')
if appuifw.query(u'Scaricare il modulo richiesto?', 'query'):
url = 'http://lightblue.sourceforge.net/#downloads'
browser = 'BrowserNG.exe'
e32.start_exe(browser, ' "4 %s"' % url, 1)
sys.exit()
#Variabili
log_file = u'C:\\bt_flooder_log.txt'
log_ok = False
accept = 0 #Persone che accettano
attemp = 0 #Tentativi di invio
filtro = [] #Filtro di MAC
devices = () #Periferiche
obj = u'Nessuno' #File selezionato
file_ok = False
status = u'Flooder in pausa.' #Stato flooder
#Draw
PAD = 5 #Padding
TXT = (0, 0, 0) #Colore testo
VAL = (255, 0, 0) #Colore valore
STATUS = (0, 200, 0) #Colore stato applicazione
ABOUT = (180, 180, 180) #Colore about
BACKGROUND = (240, 255, 255)
MRG = 25 #Margin
FONT_T = (None, 20)
FONT_V = (None, 20, 1)
def draw(r=None):
"""Disegna la schermata di stato"""
global devices, status, attemp
img.clear(BACKGROUND)
#File oggetto
img.text((PAD, MRG), u'File:', fill = TXT, font = FONT_T)
X = img.measure_text(u'File: ', font = FONT_T)[1]
img.text((PAD + X, MRG), u'%s' % obj[obj.rfind('\\')+1:], fill = VAL, font = FONT_V)
#Log attivo/disattivo
img.text((PAD, MRG * 2), u'Log:', fill = TXT, font = FONT_T)
X = img.measure_text(u'Log: ', font = FONT_T)[1]
img.text((PAD + X, MRG * 2), (log_ok and u'Attivato' or u'Disattivato'), fill = VAL, font = FONT_V)
#Vittime che accettano
img.text((PAD, MRG * 3), u'Vittime:', fill = TXT, font = FONT_T)
X = img.measure_text(u'Vittime: ', font = FONT_T)[1]
img.text((PAD + X, MRG * 3), u'%d' % accept, fill = VAL, font = FONT_V)
#Tentativi di invio file
img.text((PAD, MRG * 4), u'Tentativi invio:', fill = TXT, font = FONT_T)
X = img.measure_text(u'Tentativi invio: ', font = FONT_T)[1]
img.text((PAD + X, MRG * 4), u'%d' % attemp, fill = VAL, font = FONT_V)
#Periferiche bluetooth nei paragi
img.text((PAD, MRG * 5), u'Periferiche BT:', fill = TXT, font = FONT_T)
X = img.measure_text(u'Periferiche BT: ', font = FONT_T)[1]
img.text((PAD + X, MRG * 5), u'%d' % len(devices), fill = VAL, font = FONT_V)
#Stato applicazione
img.text((PAD, MRG * 6), status, fill = STATUS, font = FONT_V)
#About
img.text((PAD, MRG * 7 + 20), u'Created by Ale152', fill = ABOUT, font = FONT_T)
img.text((PAD, MRG * 8 + 20), u'www.Wirgilio.it', fill = ABOUT, font = FONT_T)
c.blit(img)
#Canvas
c = appuifw.Canvas(redraw_callback = draw)
img = graphics.Image.new(c.size)
appuifw.app.body = c
def list(path):
"""Lista una directory e restituisce un file selezionato"""
#Torna indietro
if path.endswith('\\..'):
#Mostra dischi
if path in ['C:\\\\..', 'E:\\\\..']:
files = ['C:', 'E:']
path = ''
#Mostra directory precedente
else:
path = path[:path.rfind('\\\\..')] #Elimino il \\.. dal path
path = path[:path.rfind('\\')] #Elimino l'ultima dir dal path
#Listo la dir
files = os.listdir(path)
files.sort()
files[0:0] = ['\\..']
#Lista directory
elif path:
files = os.listdir(path)
files.sort()
files[0:0] = ['\\..']
ufiles = [i.decode('utf-8') for i in files] #appuifw richiede unicode
try:
selected = files[appuifw.selection_list(ufiles, 1)] #1 abilita ricerca
except:
#Nessun file selezionato
pass
#Se hai selezionato E: non deve restituire \E: !
return path and path+'\\'+selected or selected
def select_file():
"""Seleziona un file da inviare alle vittime"""
global log_ok, file_ok, obj
appuifw.note(u'Selezionare un file da inviare alle vittime.')
file_ok = False #File non selezionato
path = 'C:\\\\..' #Torna indietro ai dischi
temp = list(path)
while not file_ok:
temp = list(temp)
#Se è un file, restituisce l'indirizzo
#Se è una cartella, la lista
if os.path.isfile(temp):
file_ok = True
obj = temp.decode('utf-8')
appuifw.note(u'File selezionato.', 'conf')
draw()
if log_ok:
log.write('%s> file = %s\n' % (strftime('%H:%M:%S'), obj))
def logging():
"""Attiva o disattiva il file di log"""
global log_ok, log, strftime
log_ok = globalui.global_query(u'Salvare un file di log?')
if log_ok:
log = file(log_file, 'a')
from time import strftime
log.write('\n\nSession starts on %s\n' % strftime('%H:%M:%S'))
appuifw.note(log_file+' creato.', 'conf')
#Chiede di attivare il logging all'avvio dell'applicazione
logging()
#*****************
# Filtro #
#*****************
def filter(action):
"""Gestisce il filtro periferiche. Le periferiche nel filtro non verranno
infastidite dal flooder"""
global filtro
#Aggiungi periferica
if action == 'add':
try:
mac = socket.bt_obex_discover()[0]
if mac:
filtro.append(mac)
appuifw.note(u'Periferica aggiunta.', 'conf')
else:
appuifw.note(u'Periferica non raggiungibile!', 'error')
except:
appuifw.note(u'Periferica non raggiungibile!', 'error')
#Mostra periferiche
elif action == 'show':
if filtro:
ufiltro = [i.decode('utf-8') for i in filtro]
appuifw.selection_list(ufiltro)
else:
appuifw.note(u'Nessuna periferica nel filtro!', 'error')
#Elimina periferiche
elif action == 'del':
if filtro:
ufiltro = [i.decode('utf-8') for i in filtro]
delete = appuifw.selection_list(ufiltro)
filtro.remove(filtro[delete])
appuifw.note(u'Periferica rimossa.', 'conf')
else:
appuifw.note(u'Nessuna periferica nel filtro!', 'error')
#About
def about():
appuifw.query(u'BT Flooder created by Ale152.', 'query')
appuifw.query(u'www.wirgilio.it', 'query')
#*****************
# Applicazione #
#*****************
def app(oper):
global log_ok, file_ok, run, accept, obj, devices, status, attemp
##
## Run
##
if oper == 'run':
run = True
#Seleziona un file come oggetto
if not file_ok:
select_file()
while run:
#Cerco periferiche nei paragi
status = u'Cerco periferiche...'
draw()
try:
devices = lightblue.finddevices()
if log_ok:
log.write('%s> %d devices found!\n' %
(strftime('%H:%M:%S'), len(devices)))
except SymbianError:
appuifw.note(u'Bluetooth disattivato!', 'error')
app('stop')
break
#Cerco i servizi offerti
for device in devices:
try: #Supporta obex?
status = 'Verifico '+device[1]+'...'
draw()
#obex = (mac, {'srv':chan})
obex = socket.bt_obex_discover(device[0])
if obex and obex[0] not in filtro:
status = device[1]+' supporta OBEX!'
draw()
canale = obex[1].items()[0][1]
indirizzo = obex[0]
if log_ok:
log.write('%s> trying to send "%s" to %s (%s)...' %
(strftime('%H:%M:%S'), obj, indirizzo, str(device[1])))
status = u'Provo ad inviare il file...'
attemp += 1
draw()
try: #Provo ad inviare il file
socket.bt_obex_send_file(indirizzo, canale, obj)
accept += 1
status = u'File inviato!'
draw()
e32.ao_sleep(1)
if log_ok:
log.write(' file sent! (%d)\n' % accept)
except:
if log_ok:
log.write(' file refused!\n')
status = u'File rifiutato :('
draw()
except: #Non supporta obex.
status = device[1]+' non supportato.'
draw()
e32.ao_sleep(0.01)
##
## Stop
##
elif oper == 'stop':
run = False
status = u'Flooder in pausa.'
draw()
##
## Quit
##
elif oper == 'quit':
run = False
#Chiude il log se aperto
if log_ok:
log.write('%s> victims = %d' % (strftime('%H:%M:%S'), accept))
log.write('\nSession ends on %s\n\n' % strftime('%H:%M:%S'))
log.close()
lock.signal()
appuifw.app.set_exit()
#Appuifw
appuifw.app.title = u'BT Flooder'
appuifw.app.exit_key_handler = lambda: app('quit')
appuifw.app.menu = [(u'Flooder', ((u'Avvia', lambda: app('run')),
(u'Arresta', lambda: app('stop')),
(u'Seleziona file', select_file))
),
(u'Filtro periferiche', ((u'Mostra', lambda: filter('show')),
(u'Aggiungi', lambda: filter('add')),
(u'Elimina', lambda: filter('del'))
)),
(u'File log', logging),
(u'About', about),
(u'Esci', lambda: app('quit'))]
lock = e32.Ao_lock()
lock.wait()