Se me cayo un exploit

SEGURIDAD INFORMÁTICA

HACKING . PROGRAMACIÓN . ELECTRÓNICA . GNU/LINUX

Se me cayó un exploit en tu server.... por @UnaPibaGeek

[email protected]:~$ ./ASM

¡El lenguaje más interesante! Por lo menos para mí :p

El camino de aprender ASM

asm.png

Sin dudas hay mil caminos para aprender algo, cada uno toma el que mejor se adapte a sus preferencias de aprendizaje. En esta nota contaré el camino que he tomado yo -en aquel entonces, hace algunos años- para aprender ASM (Assembly), aunque no significa que sea el camino ideal para quien esté leyendo estas líneas. Sin embargo, considero que, si no te sirve mi metodología... al menos seguro te servirán los recursos que citaré. Porque hasta donde sé no hay cursos para aprender Assembly, y si los hay estoy segura de que serán bastante superficiales y orientados a una sola arquitectura o procesador en particular. Por lo tanto, si tienes gran ambición por el conocimiento como yo, aquello no te conformará.

Actualmente manejo este lenguaje para microcontroladores Microchip y procesadores Intel/AMD x86 y x64. Si bien aprender ASM lleva tiempo (sobre todo si lo aprendes para diferentes arquitecturas como yo) no considero que sea difícil ni destinado únicamente a ser comprendido por mentes "brillantes" como muchos piensan. Permíteme aconsejarte eliminar previamente el prejuicio. Cuando a los programadores les hablan del bajo nivel a menudo se asustan, por lo diferente que se ve un código en ASM de uno desarrollado en alto nivel, consideran imposible aprenderlo y se dan por vencidos antes de empezar. Mi pensamiento es que, no tiene sentido comparar al bajo nivel con el alto nivel... aprender a programar en alto nivel no es más difícil que aprender ASM, ni aprender ASM es más difícil que aprender un lenguaje de alto nivel, porque simplemente no son cosas comparables, son muy diferentes. Si programas en alto nivel y te resultó difícil lograrlo, no significa que aprender Assembly te vaya a costar más. Conozco gente que es excelente programadora en ASM sin embargo no logra dominar el alto nivel y viceversa. Son cosas diferentes, así que antes de comenzar, recomiendo eliminar cualquier prejuicio que tengas sobre el bajo nivel.

Como seguramente estarás deduciendo de mis párrafos anteriores: no hay un solo ASM, por eso mencionaba que lleva tiempo aprenderlo para diferentes procesadores y arquitecturas. Si bien hay un común denominador, que es el gran parecido -ya que en definitiva sigue siendo Assembly- notarás que entre diferentes plataformas hay cosas que cambian. Por ejemplo: el set de instrucciones (podrían existir más, menos o ser diferentes), el orden en el que se le pasan los operadores a una instrucción, la longitud de los datos con los que se opera (8 bits, 16bits, 32bits, 64bits), etc.

Si nunca has tenido contacto con el bajo nivel, es probable que varias cosas que mencione a lo largo de esta nota te suenen a chino. Pero no te preocupes, entenderás perfectamente a qué me refería a medida que vayas estudiando y avanzando en el camino que te contaré a continuación, si decides seguirme los pasos...

Pero antes de continuar, quiero aclarar algo súper importante: a excepción del caso de los microcontroladores, actualmente no tiene sentido aprender a PROGRAMAR en Assembly. Hoy en día para cualquier aplicación que deseemos desarrollar utilizaremos un lenguaje de alto nivel. ¿Entonces? Lo que haremos para el caso de los microprocesadores es ENTENDER el Assembly. Esto es lo que necesitamos para poder hacer reversing y será suficiente para armar nuestras shellcodes también.


Parte I: Aprender ASM para programar microcontroladores (8bits)
Como dije, los microcontroladores son la excepción. Aquí si tiene sentido aprender a programarlos en Assembly, pero a su vez admito que es una cuestión de gustos. Desde hace algunos años los microcontroladores pueden ser programados en C también, pero en mi caso me encanta programarlos directamente en ASM porque siento que tengo un control más directo sobre los periféricos del hardware que utilizo. De todos modos, si eliges hacerlo en C, te deseo mucha suerte con el optimizador :)

A mi en lo personal, programar los microcontroladores en ASM me sirvió muchísimo para entender la lógica del bajo nivel. Es más difícil programar que leer y entender el código, cuando vas escribiendo las instrucciones línea por línea te ves en la obligación de pensar muy bien de manera lógica lo que estás haciendo, trabajando literalmente bit a bit, armando delays utilizando loops con operaciones matemáticas, entre muchas otras cosas que jamás tendrás que hacer "a mano" en el alto nivel. En los microcontroladores el set de instrucciones es más reducido y mayormente su arquitectura es de 8bits, lo que hace que sea todo más simple e ideal para adentrarse en el mundo del Assembly.

¿Cómo se puede aprender a programar microcontroladores en ASM? Lo mejor es dirigirse al datasheet o "el manual" de los microcontroladores ya que están perfectamente documentados e incluso contienen ejemplos de código en ASM para utilizar sus diferentes periféricos de hardware. Microchip tiene documentación de sobra online y de acceso gratuito que detalla cada uno de sus microcontroladores y también hay muchos ejemplos en los diferentes foros relacionados al tema.

Desconozco si hay algún curso o libro actual de programación de microcontroladores en ASM, estimo que no. En casa tengo dos libros pero son bastantes viejos aunque pueden servir bastante como base. Uno es "Electrónica y Microcontroladores PIC" y el otro "Microcontroladores" ambos de la editorial RedUSERS. No sé si aún estarán a la venta en las librerías pero sino, alguien lo habrá subido en pdf por ahí... :P



Pero más allá de los libros y los trozos de códigos sueltos que encuentres en los foros -que quizás en algún momento brinden alguna ayuda- mi consejo es utilizar siempre el manual (datasheet) del modelo de microcontrolador que has elegido. Consulta allí sobre el periférico que deseas utilizar, siempre se detalla cómo funciona, qué registros del procesador utiliza y algún ejemplo simple de su implementación en Assembly.

Si no te gusta la electrónica ni tienes interés en aprenderla, tendrás que saltarte esta fase. Afortunadamente para ti, no es indispensable, se puede comenzar aprendiendo sobre Assembly para microprocesadores, como detallaré a continuación.


Parte II: Incrementando de a poco la dificultad... ASM Intel/AMD (16bits)

Se podría decir que la dificultad del Assembly es directamente proporcional al poder del microprocesador... y el poder de estos aumenta en gran medida acorde a la cantidad de datos en simultaneo con los que son capaces de operar, lo cual se representa en su arquitectura: 8bits, 16bits, 32bits y 64bits.

Por lo tanto, cuando se trata de microprocesadores, es una buena idea comenzar a entender el ASM de 16bits y luego ir escalando. En esta etapa para mí hubo un libro que fue fundamental: "Assembler desde cero + Interrupciones" de Mario Ginzburg. No sé si aún seguirá a la venta en las librerías, pero no dudo que debe circular el pdf por algún lado...



Este libro comienza explicando los registros del microprocesador (hasta 16bits) y cómo utilizarlos. Luego continúa iniciando con una larga serie de ejercicios... ¡Tiene 52 ejercicios en total! Como buena estudiante los hice todos O:) Igualmente no es necesario que los hagas paso a paso en el debugger, pero sí es importante que te sientes a leer cada ejercicio y entiendas el porqué de cada una de las instrucciones que lo componen. El objetivo es ampliar la mente en cuanto a la lógica del bajo nivel, ahora trabajando con 16bits.

En varios de los ejercicios se opera también con 8bits utilizando la parte baja y alta de los registros de 16bits. Esto también se utiliza en arquitecturas 32 y 64, por lo que es útil que te acostumbres y comprendas las operaciones que utilizan una parte del contenido del registro en lugar de la totalidad de sus bytes.

Una vez que logres leer los ejercicios y entender lo que ocurre casi al mismo tiempo que vas leyendo las instrucciones, entonces podemos avanzar. En el libro que mencioné hay la suficiente cantidad de ejercicios para practicar comprensión de código ASM y llegar a ese nivel.


Parte III: Comenzando con una arquitectura más común... ASM Intel/AMD (32bits)

Si bien los procesadores 64bits han arrasado desde ya hace varios años, muchas aplicaciones mantienen hasta hoy retrocompatibilidad con procesadores de 32. Es por eso que, muy probablemente, puedas reversear su correspondiente binario en dicha arquitectura. Lo cual es recomendable si te encuentras en esta fase y aun no has tenido contacto con aplicaciones compiladas para 64bits.

La arquitectura de 32bits (también conocida como x86) es la más ampliamente documentada, podemos encontrar innumerables recursos tanto en español como en inglés. Además, es una buena idea programar algunos trozos de código sencillos en C y compilarlos en dicha arquitectura, con el fin de analizar su código en ASM.

Recuerda que nuestro objetivo es poder comprender el Assembly, es decir, abrir un binario en un desensamblador o debugger, leer sus instrucciones y entender qué es lo que está haciendo la función o trozo de código que estemos analizando.

Siendo sincera, hace tantos años que empecé a leer sobre Assembly x86 que no recuerdo bien cuales fueron los primeros materiales que estudié. Ehm si, les mentí un poquito, porque mis primeros contactos con ASM x86 fueron antes de aprender a programar microcontroladores pero... todo empezó a entenderse mejor cuando comencé de nuevo desde más abajo ;). Muy probablemente mis primeras lecturas hayan sido un conjunto de muchos artículos sueltos colgados por internet.

Más allá de eso, voy a citar los recursos más actuales que he leído, y que me han parecido muy interesantes e útiles.

El primero, en español, será el curso de IDA PRO del maestro @ricnar que puedes descargar gratuitamente desde aquí. En los capítulos del 1 al 7 Ricnar hace una introducción breve pero práctica al ASM x86. Recomiendo continuar leyendo todos los capítulos del curso, los ejercicios propuestos están orientados a aprender reversing y cada uno de ellos ayuda a seguir mejorando la capacidad de comprensión del bajo nivel.

Por otro lado, el libro "Practical Reverse Engineering" (en inglés) de la editorial Wiley, dedica su primer capítulo a ASM x86 y x64, aunque lo cierto es que casi todo el capítulo es sobre x86, luego en la última página se mencionan las principales diferencias respecto a 64bits.

Sin lugar a dudas, mi recurso favorito ha sido el libro "Secrets of Reverse Engineering" (en inglés) también de la editorial Wiley. Si bien el capítulo 2 tiene una sección de "ASM 101" lo mejor se encuentra en los apéndices del libro, que ocupan casi 100 páginas del mismo. Estos apéndices me han parecido realmente fabulosos, están dedicados a ayudar al lector a comprender la lógica del ASM, que es nuestro objetivo.

El apéndice A, llamado "Deciphering Code Structures" explica cómo se ven en el bajo nivel todas aquellas estructuras que utilizamos continuamente en el alto nivel, tal como condiciones if, elseif, switch, for, while, etc. En la parte final se dedica una sección al "Branchless logic" que es fantástica, ya que explica como muchas de estas estructuras son optimizadas por el compilador y el resultado de esto en el bajo nivel puede parecerse muy poco a algo familiar. Sin dudas es de gran ayuda.

El apéndice B trata exclusivamente las operaciones aritméticas tanto en 32 como 64bits. Por último, el apéndice C explica como son manejadas en el bajo nivel todas las estructuras de datos (variables, constantes, arrays, parámetros a funciones, etc). También hay un apartado que trata las "Calling Conventions" implementadas por diferentes compiladores para 32bits.



Aprender ASM x86 en un buen nivel lleva tiempo, probablemente esta fase del aprendizaje se lleve la mayor parte y está bien que así sea. Debemos dedicarle todo el tiempo que sea necesario hasta sentirnos con comodidad a la hora de hacer reversing sobre aplicaciones en 32bits.


Parte IV: Cerebro a pruebas de balas... ASM Intel/AMD (64bits)

Si tenemos la suficiente práctica con ASM x86, hacer el "upgrade" a 64bits será relativamente sencillo, hay diferencias puntuales a las que debemos prestarle atención. Por ejemplo, los procesadores x64 poseen más registros, y los que ya conocíamos desde los 32bits poseen una extensión a 64bits que se denomina de diferente manera. Las "Calling Conventions" también son diferentes, existe otra manera de pasarle los parámetros a las funciones.

Como ya se ha mencionado, los libros "Practical Reverse Engineering" y "Secrets of Reverse Engineering" hacen mención de las principales diferencias entre 32 y 64bits.

Un articulo que me resultó útil para tomar idea de estas diferencias fue el siguiente: https://software.intel.com/en-us/articles/introduction-to-x64-assembly.

Otro que también me ha gustado mucho, el cual habla sobre el manejo del stack, las calling conventions, el prólogo y epílogo de las funciones, etc, en 64bits, es uno de Microsoft que se encuentra publicado aquí: https://docs.microsoft.com/en-us/cpp/build/x64-software-conventions?view=vs-2017.

A pesar de los años que llevan los procesadores x64 en el mercado, no hay la misma cantidad de documentación sobre ellos como si la hay sobre sus pares de 32bits. Sin embargo, como ya he mencionado, si tenemos la suficiente práctica en x86 bastará con conocer las principales diferencias y empezar a practicar reverseando aplicaciones en x64. Al menos eso fue lo que hice yo y no me llevó tanto tiempo acostumbrarme.


Parte V: Otros procesadores y arquitecturas
El mundo no se acaba aquí, existen otros procesadores con sus respectivas arquitecturas que también se implementan en diversos dispositivos actualmente. Por ejemplo, los procesadores ARM. Tengo pendiente aprender el Assembly para ARM, es mi próximo paso en este camino que te he contado. No es difícil aprender el ASM de un nuevo procesador cuando ya conoces otros, lo que sí ocurre -y me ha pasado- es confundirse algunas instrucciones, a mi se me suelen mezclar el orden de los operadores de las instrucciones del ASM de microcontroladores PIC, con el de procesadores Intel/AMD. Eso también ocurre cuando se aprende a leer las diferentes notaciones del ASM en binarios compilados sobre x86 o x64 pero en plataformas diferentes.


Conclusión

Espero que te sea útil mi método y los recursos que he citado si te encuentras a punto de comenzar el camino para entrar al fascinante mundo del bajo nivel ;)
¡Gracias por leer!

¿Te cansaste de leer? Tomate un café (share):

Fecha: 14/02/2019

¡Suscribite!

Aprendé más en...