¡Acceso ilimitado 24/7 a todos nuestros libros y vídeos! Descubra la Biblioteca Online ENI. Pulse aquí
¡Acceso ilimitado 24/7 a todos nuestros libros y vídeos! Descubra la Biblioteca Online ENI. Pulse aquí
  1. Libros
  2. Hacking y Forensic
  3. Python: Los fundamentos
Extrait - Hacking y Forensic Desarrolle sus propias herramientas en Python
Extractos del libro
Hacking y Forensic Desarrolle sus propias herramientas en Python Volver a la página de compra del libro

Python: Los fundamentos

Introducción

La elección de un lenguaje es a veces un recorrido tortuoso y difícil. Existe una multitud de lenguajes, desde el nivel más bajo al más alto, cada uno con sus características. Para no citar más que unos pocos, encontramos el ensamblador (diferentes mnemónicos según las arquitecturas: x86, arm, 68000), C, C++, C#, Java, Perl, Ruby, Python...

Cuando nuestro negocio es la seguridad informática debemos tener una buena visión de conjunto de los diferentes lenguajes o, al menos, saber encontrar la información cuando es necesario. Pero por experiencia, hay que conocer al menos el ensamblador x86 (y x64), el lenguaje C y un lenguaje de los llamados de alto nivel.

¿Por qué elegir Python?

En esta época me faltaba, conociendo ensamblador y C, un lenguaje fácil de aprender que proporcionara un resultado rápido. Tras varios intentos con Java y C++, el lenguaje Python me abrió las puertas del desarrollo y me dio la herramienta ideal para mis clases de licencia CDAISI (Ciberdefensa y anti-intrusión de los sistemas de información de la UVHC http://www.univ-valenciennes.fr) y mis auditorías técnicas (pentest) dentro de la empresa Serval-concept (http://www.serval-concept.com).

La programación Python ha conformado su pedigrí y Python se ha convertido en un lenguaje popular y utilizado en todos los ámbitos...

Historia

El lenguaje Python fue inventado por Guido van Rossum, desarrollador de los Países Bajos. Se considera en la Comunidad Python como el "dictador benevolente de por vida".

images/HF02EP01.png

La primera versión publicada data de 1991. Una versión 1.5 se publicó en abril de 1999 y luego una versión 2.0 en octubre de 2000.

La última versión de Python de la rama 2, la 2.7, salió en julio de 2000.

La rama 3.x llega en 2009 con la 3.0.1 y su objetivo es eliminar las deficiencias del lenguaje garantizando una compatibilidad hacia atrás con 2.x.

La versión 3.5.0 salió el 13 de septiembre de 2015.

Puedes descargar las últimas versiones de Python en el sitio oficial: https://www.python.org/downloads/

Características del lenguaje

Python es:

  • Un software libre: su uso, estudio, modificación y copia para su difusión están permitidos, técnica y legalmente.

  • Portable: se desarrolló en ANSI C portable.

  • Interoperable con otros lenguajes.

  • Orientado a objetos con soporte para funcionalidades avanzadas.

  • Fácil de usar y perfecto para el desarrollo ágil.

  • Fácil de aprender: la sintaxis es simple y natural.

images/01-01.png

La librería estándar proporciona módulos escritos totalmente en Python. Estos módulos son robustos y de fácil uso, permiten la interacción con el sistema operativo y el sistema de archivos. Funcionan sobre todas las plataformas reconocidas por Python.

Los módulos de extensión, por su parte, permiten a las aplicaciones tener acceso a componentes de software adicionales (redes, cálculo numérico, tratamiento de datos, procesamiento de imágenes…). Estos módulos, que pueden no estar escritos en Python, pueden servir de enlace con otros lenguajes. Cpython (implementación nativa), Jython (implementación de Python en Java), IronPython (Implementación en C# para .NET y Mono)...

Se incluye una documentación directamente accesible desde el intérprete Python. El comando help() permite acceder a la ayuda en línea integrada.

La búsqueda en la documentación se puede...

Tipos de datos

Los tipos de datos son mutables (modificables) o immutables (no modificables).

Los tipos inmutables se manipulan copiando valores (números, cadenas de caracteres y tuplas), los tipos mutables se manipulan por punteros (listas, diccionarios).

Los tipos de datos Python son secuencias (cadenas de caracteres, tuplas y listas) o colecciones (diccionarios).

Una secuencia es una lista ordenada de elementos; una secuencia puede recorrerse de forma iterativa.

1. Los números

Los números son de tipos clásicos para aquellos acostumbrados a los lenguajes de programación. Encontramos enteros, longs, reales, complejos.

El tipado en Python es dinámico, no se requiere definir el tipo de variable, se asigna solo.

Podemos comprobar esto mediante la función type().

Para probar esto podemos entrar en el intérprete interactivo:

images/01-05.png

Python también nos brinda diferentes notaciones como la notación exponencial, octal, binaria, hexadecimal.

images/01-06.png

El tipado es dinámico, es decir, que puede cambiar a lo largo de la ejecución del programa (que puede llamarse script).

En el ejemplo a continuación, empleamos un bucle for. El objetivo aquí por el momento no es comprender el bucle, sino constatar el cambio de tipo de forma dinámica.

images/01-07.png

También podemos utilizar los operadores convencionales tales como el desplazamiento a la derecha (>>) o a la izquierda (<<) y los operadores booleanos (O, Y y O exclusivo). Los operadores matemáticos convencionales también forman parte (adición +, sustracción -, división entera //, multiplicación *, modulo % y potencia **).

images/01-08.png

Podemos convertir de un tipo a otro cuando sea posible, mediante los constructores int(), float(), complex(), bin(), hex(), OSD()...

images/01-09.png

Existen algunas trampas que debemos evitar con los números. Hay que ser prudentes con la división de enteros y la definición de números complejos.

images/01-10.png

2. Las operaciones aritméticas

Ya hemos visto antes las operaciones aritméticas básicas.

Encontramos por supuesto, las operaciones +, -, /, * (suma, resta, división y multiplicación).

También hemos visto el exponencial representado en Python con **.

También tenemos otros operadores y funciones que pueden ayudarnos en nuestros proyectos.

  • round(x) redondea un "real" (al entero superior a partir...

Estructuras condicionales y repetitivas

1. Test if ... elif ... else

La instrucción if ... elif ... else nos permitirá verificar condiciones y, en función del resultado, efectuar las acciones asociadas a este.


if <condición>:  
    #ejecución si la condición es verdadera  
elif <otra condición>:  
    #ejecución si otra condición es verdadera  
else:  
    #ejecución si las condiciones son falsas.
 

if puede utilizarse solo, con else o con elif y else.

Podemos tener tantos elif como deseemos siguiendo a las condiciones a verificar. 

En Python, no existe la instrucción switch ... case como podemos encontrar en otros lenguajes. La estructura elif permite reproducirla con facilidad.

Las condiciones serán comprobaciones como == (igual), != (diferente), < (menor que), > (mayor que), <= (menor o igual) y >= (mayor o igual).


__author__ = 'franckebel'  
#--*--coding:utf-8--*--  
nbr=raw_input("introduzca un número")  
while not nbr.isdigit():  
    print "Por favor, introduzca un número"  
    nbr=raw_input("introduzca un número")  
nbr=int(nbr)  
if nbr<10:  
    print "ha introducido un número inferior a 10"  ...

Funciones, módulos y paquetes

1. Definición y llamadas de función

Para definir una función, utilizaremos la instrucción def. Al igual que todo en Python, la sangría es importante para especificar qué pertenece a la función definida.


def mi_función:  
       print "Estoy en mi función"
 

El nombre de la función puede ser cualquier cosa exceptuando las palabras reservadas por el lenguaje. No existen normas propiamente dichas, pero se aconseja utilizar minúsculas, sobre todo al principio del nombre.

images/01-22.png

Declaramos la función hola5() sin parámetros. Esta función contiene un bucle while que muestra Hola. El bucle se ejecutará 5 veces. No olvidemos utilizar una variable para verificar el número de bucles que debemos incrementar en 1 en cada ciclo.

La función se invoca escribiendo su nombre.

Si llamamos a un nombre de función que no existe, como en el ejemplo, se muestra un mensaje de error. Veremos más tarde cómo gestionar estos errores.

Podemos llamar a esta función tantas veces como queramos, y también llamarla desde otra función.

images/01-23.png

Podemos por supuesto pasar parámetros a una función, parámetros que se situarán en los paréntesis.

Imaginemos que deseamos elegir el número de veces que queremos escribir Hola. Tendremos que indicar este número a la función.

images/01-24.png

Pedimos primero al usuario el número de veces que desea mostrar Hola.

Luego llamaremos a la función transmitiendo la variable que contiene el número.

En la función, el único cambio es que hacemos la comprobación del while con este número.

La instrucción return permite devolver un valor.


def cuadrado(x) :  
    return x**2
 

Si deseamos devolver una lista por ejemplo (deberemos adaptarlo para una tupla o un diccionario):


def cuadrado(x) :  
    return [x**2,x**3]
 

En la definición de la función, podemos proporcionar a los parámetros valores por defecto. Si en la llamada se encuentra el valor, este se utiliza, en caso contrario se utilizará el valor por defecto.


def  Hola( nb= "Hola "...

Las clases

En Python, como hemos visto, todo son objetos: cadenas, enteros, listas, funciones, clases, módulos, etc.

Todo objeto es manipulado por referencia: una variable contiene una referencia a un objeto y un objeto puede ser referenciado por varias variables.

Una función, una clase, un módulo son espacios de nombres organizados de modo jerárquico: un módulo contiene las clases que contienen las funciones (los métodos).

Una clase funcionará de la misma forma que una función, es decir, terminará con : y el bloque al que pertenece se indicará mediante la sangría.

Por convención, el nombre de una clase comienza con una letra mayúscula.

Se utiliza la palabra clave class.

Cualquier método se define como una función con un primer argumento (self) que constituye el objeto sobre el cual será aplicada durante su ejecución. El nombre es libre, pero se utiliza en general self. Un método que no utiliza parámetros tendrá por lo tanto, a pesar de todo, un argumento.

La instanciación se realiza sin una palabra clave en particular. Basta con escribir unos paréntesis a continuación del nombre de una clase (con o sin parámetros) para desencadenar una instanciación. La invocación se efectúa utilizando la notación de punto, una llamada a una variable que referencia a un objeto.

Los atributos se definen en la primera asignación. Una variable se considera como un atributo si es "dependiente" del objeto: se accede a ella mediante self. Cualquier acceso a un atributo o un método del objeto a partir de su implementación se realiza obligatoriamente mediante la variable self. El constructor es un «método» llamado __init__. Al igual que todo método, algunos de sus parámetros pueden tener valores por defecto. Esta posibilidad es importante porque una clase tiene un único constructor en Python.

1. Declaración de una clase

En este ejemplo, declaramos una clase Informatica:


class Informatica(object):  
    def __init__(self, lenguaje):  
        self.lenguaje = lenguaje  
    def los_lenguajes(self):  
        for line in self.lenguaje:  
            print(line)  
  ...

Manipulación de archivos

Nos será muy útil poder leer el contenido de un archivo o escribir en un archivo. Por ejemplo, cuando queremos guardar información, si esta no es demasiado extensa, utilizaremos un archivo de texto.

La instrucción open() permite abrir un archivo, devolviendo un objeto de tipo File.

Los modos de apertura del archivo pueden ser r (read), w (write) y a (append). Podemos añadir a estos modos b (modo binario), t (modo texto), + (apertura de lectura y escritura).


mi_archivo=open("archivo.txt",'a+')
 

El método close() permite cerrar un archivo.

Los archivos de texto son legibles directamente por el usuario, contienen texto (letras, puntuación, números...). Su contenido suele estar dividido en líneas. En entorno Unix, los archivos de configuración en /etc son ejemplos de archivos de texto. Es el mismo caso con el código fuente de un programa Python.

Los binarios no contienen (exclusivamente) texto, solo pueden ser tratados de forma adecuada empleando programas especializados. Un archivo PDF, una imagen TIFF o un MP3 son algunos ejemplos de archivos binarios.


# apertura en modo lectura del archivo archivo1.txt    
archivo=open('archivo1.txt','r')
# lectura del archivo texto=archivo.read() 
# cierre del archivo texto1.txt    
archivo.close()
# apertura en modo escritura de un archivo texto2.txt    ...

Las excepciones

Hemos visto a lo largo de este libro que, algunas veces, nos encontramos con un error al ejecutar un programa.


>>> nbr = raw_input('Por favor, introduzca un número\n')  
Por favor, introduzca un número  
AZ  
>>> int(nbr)  
Traceback (most recent call last):  
  File "<stdin>", line 1, in <module>  
ValueError: invalid literal for int() with base 10: 'AZ'  
>>>
 

Desearíamos poder gestionar estos errores. Esto se hace utilizando las excepciones. 

Una excepción permite reponerse de una anomalía en la llamada a un programa. Esta anomalía puede ser un error o un caso particular.

Una excepción se caracteriza por un nombre y un mensaje de error que permite identificar el origen del error.

Python está provisto de clases muy completas de excepciones estándar y podemos también crear nuestras propias excepciones mediante el simple mecanismo de la herencia de objeto.

El inconveniente con los errores no gestionados en los programas es que nuestro script se detendrá. Por esto, debemos encontrar la manera de gestionar estas excepciones para poder paliar el error y continuar con nuestro programa.

try nos permitirá intentar ejecutar un segmento de código. Si el segmento de código funciona, no hay problema y seguimos con nuestro script....

Módulos útiles para la continuación del libro

1. Módulo sys

El módulo sys nos permitirá una interacción con el intérprete.

El módulo sys contiene la mayoría de la información relativa a la ejecución en curso, actualizada por el intérprete, así como una serie de funciones y objetos de bajo nivel.

argv contiene la lista de parámetros de ejecución de un script. El primer elemento de la lista es el nombre del script seguido de la lista de parámetros.


import sys  
print "Este es el nombre del script: ", sys.argv[0]  
print "Aquí el número de argumentos: ", len(sys.argv)  
print "Los argumentos son: " , str(sys.argv)  
print "El primer argumento es: " , sys.argv[1]
 

Sys.exit(<código de retorno>) sale del intérprete generando una excepción SystemError. Recibe como parámetro un entero que se utilizará como código de retorno proporcionado al sistema siguiendo la norma:

  • 0 si el programa ha funcionado correctamente.

  • > 0 en caso de error.

sys.getfilesystemencoding() devuelve la codificación empleada por el sistema de archivos.

sys.getdefaultencoding() devuelve la codificación por defecto.

sys.path devuelve una lista con todos los directorios en los cuales el intérprete busca los módulos cuando la directiva import se emplea, o cuando los nombres de los archivos se utilizan sin su ruta completa. path puede ser modificado sobre la marcha en un programa.

Sys.platform informará sobre el sistema operativo actual (linux2, freebsd, Win32...).

Sys.stdin, sys.stdout y sys.stderr son objetos de archivo que apuntan respectivamente a la entrada estándar, la salida estándar y la salida estándar para los errores.

La función exec_info() devuelve una tupla de tres valores que nos proporciona información sobre la excepción que está en curso.

sys.versión (cadena) y sys.versión_info (tupla) indican el número de versión del intérprete.

Existen muchas otras funciones y métodos que podemos encontrar en la documentación. 


>>> import sys  
>>> sys.platform  
'linux'  
>>> sys.stdout.write("escritura con stdout por ENI")  
escritura...

Conclusión

Acabamos de recorrer la parte esencial del Lenguaje Python. Existen otros libros mucho más detallados para el aprendizaje del lenguaje.

Veremos, siguiendo las necesidades de los demás capítulos, otros módulos que presentaremos previamente.

El libro se concentrará en las aplicaciones de hacking y forensic, los conceptos vistos en este capítulo se consideran adquiridos. Le deseamos un feliz comienzo en el misterioso mundo del hacking y forensic...