https://www.youtube.com/watch?v=ytDamqTjPwg
hice este script para hacer grĂ¡ficas como la que se ve en el minuto 17. En esta charla explican cĂ³mo de forma manual categorizaron miles de correos para hacer esas grĂ¡ficas, ya que el contenido era visual y no era fĂ¡cil buscar texto en ellos de forma automĂ¡tica (aunque... ¿no podrĂan haber cogido la direcciĂ³n de quien lo enviaba, y la fecha?)
Eso es lo que hace el siguiente programa precisamente, busca en la carpeta de spam de un correo usando SMTP y saca todos los correos existentes y hace grĂ¡ficas de nĂºmero de correos acumulados por fecha para cada uno de los distintos spammers. Es de destacar que a veces entran en la carpeta de spam correos legĂtimos, y estos tambiĂ©n aparecerĂ¡n en la grĂ¡fica.
Lo interesante de la charla de Defcon es que a partir de las pendientes de estas grĂ¡ficas eran capaces de caracterizar la frecuencia con la que los bots de cada spammer enviaban correo basura.
Llevo probĂ¡ndolo poco tiempo, un mes, como para tener grĂ¡ficas muy significativas, pero se ve una pendiente clara, por ejemplo en los correos enviados por facebook, lo que indica que tienen un bot que envĂa cada dĂa correos con aproximadamente la misma frecuencia. Por eso llegan tantos correos de facebook sobre cosas que no tienen nada que ver con mi actividad.
El script en python cuenta con varias funciones que hacen tareas especĂficas, llamadas por una funciĂ³n principal. Por lo que se ve, sacar informaciĂ³n de los correos en el servidor es lento y no hay forma de sacar Ăºnicamente la cabecera, hay que extraerla del mensaje completo. Por esto, el script crea un archivo donde guarda los remitentes y fechas.Hay dos funciones para extraer correo del servidor: la primera, read_server_fast() cuenta cuĂ¡ntos spams hay leĂdos previamente, y almacenados en el archivo de texto (cuyo nombre es el nombre de usuario de la cuenta de email en cuestiĂ³n). Entonces empieza a recoger correos del servidor tomando como correo inicial aquĂ©l cuya id coincida con el nĂºmero de correos en el archivo de texto +1.
La funciĂ³n read_server_slow() no hace falta a menos que se haya borrado manualmente algo del servidor. Lo que hace es comparar uno a uno los correos del archivo con cada uno del servidor, para decidir si lo añade o no a la lista. Pero esta funciĂ³n es mucho mĂ¡s lenta y en principio no hay que usarla.
Antes de usar el script hay que activar IMAP en nuestro servidor. En este ejemplo, se muestra cĂ³mo hacerlo en Gmail:
1- Primero se activa IMAP en la configuraciĂ³n de la cuenta:
2- Después hay que habilitar el acceso a la cuenta desde aplicaciones que no sean la web de Gmail. Esto se encuentra en https://www.google.com/settings/security/lesssecureapps
Una vez hecho esto, el script funciona. Hace falta instalar matplotlib para las grĂ¡ficas. La variable show por defecto tiene valor False, y si se pone a True hace ademĂ¡s un grĂ¡fico tipo "tarta" para ver quiĂ©n ha enviado cuĂ¡ntos spams.
La variable crit fija un criterio para decidir si se representa o no un spammer en la grĂ¡fica en funciĂ³n del tiempo. Como se puede ver, muchos spammers solo envĂan un correo, asĂ que tendremos muchos puntos individuales que liaran mucho todo, y la leyenda quedarĂ¡ enorme. Subiendo crit a 3, por ejemplo, se deja de ver a todos estos spammers ocasionales:
![]() |
| criterio crit=0. Se muestran todos los spammers |
![]() |
| Criterio crit=3. Se filtran todos los que han enviado menos de 3 correos |
![]() |
| GrĂ¡fico "tarta" de todos los spammers, cada uno con su contribuciĂ³n. |
A continuaciĂ³n el script, pensado para extraer spam de Gmail. Para otras cuentas, habrĂ¡ que modificar los nombres de las carpetas del servidor.
IMPORTANTE: hay que añadir en las variables user y pwd, en la funciĂ³n principal, nuestras credenciales (entre comillas):
###########################################
import email, imaplib
import matplotlib.pyplot as plt
import matplotlib.dates as mdates
import datetime as dt
import numpy as np
import math
folder = "Todos"
days = {'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'}
def readfile():
list_senders = []
list_dates = []
list_lines = []
g = open('{}-{}.txt'.format(user,folder),'r')
for i, line in enumerate(g.readlines()):
list_lines.append(line)
g.close()
return list_lines
def read_server_fast():
m = imaplib.IMAP4_SSL("imap.gmail.com")
m.login(user,pwd)
print(m.list())
a = m.select("[Gmail]/"+folder)
lis = m.list()
lis1 = a
existing_lines = readfile()
resp, items = m.search(None, "ALL")
items = items[0].split()
already_there = False
print(items)
g = open('{}-{}.txt'.format(user,folder),'a')
for emailid in range(len(existing_lines)+1,len(items)):
resp, data = m.fetch(emailid, "(RFC822)")
email_body = data[0][1]
mail = email.message_from_string(email_body)
print emailid
try:
sender = mail["From"].split('<')[1].split('>')[0]
date = mail["Date"]
print(sender, date)
g.write(sender + ';' + date + '\n')
except:
g.write('error;error\n')
g.close()
def read_server_slow():
m = imaplib.IMAP4_SSL("imap.gmail.com")
m.login(user,pwd)
a = m.select("[Gmail]/"+folder)
lis = m.list()
lis1 = a
existing_lines = readfile()
resp, items = m.search(None, "ALL")
items = items[0].split()
print(items)
already_there = False
g = open('{}.txt'.format(user),'a')
for emailid in items:
resp, data = m.fetch(emailid, "(RFC822)")
email_body = data[0][1]
mail = email.message_from_string(email_body)
print emailid
sender = mail["From"].split('<')[1].split('>')[0]
date = mail["Date"]
print(sender, date)
for i in range(len(existing_lines)):
check = existing_lines[i].split(';')
if (sender == check[0] and date == check[1].split('\n')[0]):
already_there = True
print "Already in file!"
break
else:
already_there = False
if already_there == False:
g.write(sender + ';' + date + '\n')
g.close()
def get_sen_dat():
"""Get senders and dates from lines in file and put them in arrays senders and dates
The senders arrays contains the number of messages per sender.
The dates dic contains the dates when a message from a certain sender (dates.keys are the senders
), with all the dates in a list for each sender"""
senders = {}
dates = {}
f = open('{}-{}.txt'.format(user,folder),'r')
for i, line in enumerate(f.readlines()):
sender, date = line.split(';')
if sender in senders.keys():
senders[sender] += 1
else:
senders[sender] = 1
if sender != "error":
if sender in dates.keys():
dates[sender].append(date)
else:
dates[sender] = [date]
if i == 0: #for calculating the day span and adjust the ticks in graph
first_date = date
last_date = date
f.close()
first = first_date.split(',')[1].split(' ')
last = last_date.split(',')[1].split(' ')
f = first[1] + ' ' + months_dic[first[2]] + ' ' + first[3]
l = last[1] + ' ' + months_dic[last[2]] + ' ' + last[3]
a = dt.datetime.strptime(f, '%d %m %Y')
b = dt.datetime.strptime(l, '%d %m %Y')
day_interval = (b - a).days
print(day_interval)
return (senders, dates, day_interval)
def pie_chart(senders, show = False):
l_labels = []
l_values = []
for sender in senders.keys():
#print (sender, senders[sender])
l_labels.append(sender)
l_values.append(senders[sender])
if show == True:
plt.pie(l_values, labels=l_labels)
plt.show()
return(l_values, l_labels)
def time_graph(dates, l_values, crit, day_interval):
k=0
for value in l_values:
if value > crit:
k += 1
num_plots = len(dates.keys())
colormap = plt.cm.gist_ncar
plt.gca().set_color_cycle([colormap(i) for i in np.linspace(0, 0.9, k)])
i = 0
sender_address = []
ax = plt.subplot(111)
for sender in dates.keys():
dates1 = []
vals1 = []
val = 0
for date_list in dates[sender]:
week_day = date_list.split()[0].strip(',')
if week_day in days:
day = date_list.split()[1]
month = months_dic[date_list.split()[2]]
year = date_list.split()[3]
hours = date_list.split()[4]
else:
day = date_list.split()[0]
month = months_dic[date_list.split()[1]]
year = date_list.split()[2]
hours = date_list.split()[3]
date = month + ' ' + day + ' ' + year + ' ' + hours
date_fmt = dt.datetime.strptime(date,'%m %d %Y %H:%M:%S')
val += 1
dates1.append(date_fmt)
vals1.append(val)
sender_address.append(sender)
if(len(vals1) > crit):
plt.gca().xaxis.set_major_formatter(mdates.DateFormatter('%m/%d/%Y'))
plt.gca().xaxis.set_major_locator(mdates.DayLocator(interval = int(math.floor(day_interval * 0.2))))
plt.plot(dates1,vals1,'-o',label=sender)
plt.gcf().autofmt_xdate()
box = ax.get_position()
ax.set_position([box.x0, box.y0, box.width * 0.6, box.height])
#plt.legend(loc='center left',bbox_to_anchor=(1, 0.5))
plt.show()
if __name__ == '__main__':
user = "user"
pwd = "pass"
f = open('{}-{}.txt'.format(user,folder),'a')
f.close()
months_dic = {
'Jan':'1','Feb':'2', 'Mar':'3','Apr':'4',
'May':'5','Jun':'6', 'Jul':'7','Aug':'8',
'Sep':'9','Oct':'10', 'Nov':'11','Dec':'12'}
read_server_fast()
#read_server_slow() #use after deleting spam to start all over
senders, dates, day_interval = get_sen_dat()
show = False
l_values, l_labels = pie_chart(senders, show)
crit = 3
time_graph(dates, l_values, crit, day_interval)




No hay comentarios:
Publicar un comentario