Asamblea de aprendizaje [cerrado]


102

Decidí aprender el lenguaje ensamblador. La razón principal para hacerlo es poder entender el código desensamblado y tal vez poder escribir partes de código más eficientes (por ejemplo, a través de c ++), hacer cosas como cuevas de código, etc. Vi que hay un trillón de sabores diferentes de ensamblaje , entonces, para los propósitos que menciono, ¿cómo debo comenzar? ¿Qué tipo de montaje debo aprender? Quiero aprender primero haciendo algunos programas fáciles (es decir, una calculadora), pero el objetivo en sí será acostumbrarme a él para poder entender el código que muestra, por ejemplo, IDA Pro.

Estoy usando Windows (si eso hace alguna diferencia).

editar: Entonces, parece que todos apuntan hacia MASM. Aunque entiendo que tiene capacidades de alto nivel, todo bueno para el programador de código ensamblador, eso no es lo que estoy buscando. Parece tener instrucciones if, invoke, etc. que no se muestran en los desensambladores populares (como IDA). Entonces, lo que me gustaría escuchar, si es posible, es la opinión de cualquiera que use ASM para los propósitos que estoy preguntando (leer el código exe sin ensamblar en IDA), no solo los programadores de ensamblaje "generales".

editar: OK. Ya estoy aprendiendo a montar. Estoy aprendiendo MASM, no usando cosas de alto nivel que no me importan. Lo que estoy haciendo ahora es probar mi código en las directivas __asm ​​en c ++, para poder probar las cosas mucho más rápido que si tuviera que hacerlo todo desde cero con MASM.



Sí, yo también estaba leyendo ese. Pero mi pregunta está un poco más "enfocada", diría yo.
Devoró elisio

Si está en Windows, el destino (que es el procesador y, por lo tanto, el conjunto de instrucciones) es x86 o x86-64. A menos que obtenga otra máquina o una placa MCU o use un emulador. Entonces, ¿la pregunta es qué ensamblador debo usar? ¿O realmente estás preguntando a qué arquitectura apuntar? Personalmente, me encantan las buenas instrucciones ortogonales establecidas en los chips de la serie m68k, ay, ay.
dmckee --- ex-moderador gatito

2
"Parece tener instrucciones if, invoke, etc." - Esas son macros (la 'M' en "MASM") y no tienes que usarlas incluso si el ensamblador las admite.
ChrisW

3
Fue una decisión difícil dar a la pregunta su 65 ° voto a favor, 64 es un número tan hermoso. . .
735Tesla

Respuestas:


40

Comience con MASM32 y desde allí observe FASM . Pero te divertirás con MASM.


Escuché de MASM. Si no me equivoco, tiene muchas características de "alto nivel", que no veo cuando miro el código desarmado. Me gustaría tener que programar en algo que sea exactamente como el código de salida de la mayoría de los desensambladores, si esto tiene sentido.
Devoró elisio

1
Básicamente, eso sería como escribir códigos de operación, lo que realmente no tiene sentido. Aprender MASM32 lo ayudará a comprender cómo se ve el código en un depurador. También te puede interesar
Noon Silk

7
No entiendes el montaje. Necesitas entenderlo. Un código de operación es un número. Los depuradores intentarán resolver los códigos de operación según sus instrucciones (a veces es difícil). Necesita comprender las instrucciones básicas. Aprender MASM te ayudará a lograrlo. No es necesario decir nada más.
Mediodía Silk

5
No tiene que usar todas las funciones de MASM solo porque están ahí; puede hacer que las cosas sean tan difíciles de leer como desee, si cree que aprenderá más de esa manera.
JasonTrue

3
MASM, con sus peculiaridades, errores y las llamadas características de alto nivel, ha hecho más para confundir a los programadores de ensambladores, tanto a principiantes como a expertos, más que cualquier cosa que se me ocurra.
IJ Kennedy

44

He hecho esto muchas veces y sigo haciéndolo. En este caso, donde su objetivo principal es leer y no escribir ensamblador, creo que esto se aplica.

Escriba su propio desensamblador. No con el propósito de hacer el próximo mejor desensamblador, este es estrictamente para usted. El objetivo es aprender el conjunto de instrucciones. Ya sea que esté aprendiendo ensamblador en una nueva plataforma, recordando ensamblador para una plataforma que una vez conocí. Comience con solo unas pocas líneas de código, agregando registros, por ejemplo, y haciendo ping pong entre el desmontaje de la salida binaria y la adición de instrucciones cada vez más complicadas en el lado de entrada:

1) aprender el conjunto de instrucciones para el procesador específico

2) aprenda los matices de cómo escribir código en ensamblado para dicho procesador de modo que pueda mover cada bit de código de operación en cada instrucción

3) aprende el conjunto de instrucciones mejor que la mayoría de los ingenieros que utilizan ese conjunto de instrucciones para ganarse la vida

En su caso, hay un par de problemas, normalmente recomiendo el conjunto de instrucciones ARM para empezar, hay más productos basados ​​en ARM enviados hoy que cualquier otro (computadoras x86 incluidas). Pero la probabilidad de que esté usando ARM ahora y no conozca el ensamblador suficiente para que escriba el código de inicio u otras rutinas sabiendo que ARM puede ayudar o no a lo que está tratando de hacer. La segunda y más importante razón para ARM primero es porque las longitudes de las instrucciones son de tamaño fijo y están alineadas. Desmontar instrucciones de longitud variable como x86 puede ser una pesadilla como primer proyecto, y el objetivo aquí es aprender el conjunto de instrucciones, no para crear un proyecto de investigación. Third ARM es un conjunto de instrucciones bien hecho, los registros se crean de la misma manera y no tienen matices especiales individuales.

Por lo tanto, tendrá que averiguar con qué procesador desea comenzar. Sugiero el msp430 o ARM primero, luego ARM primero o segundo y luego el caos de x86. Independientemente de la plataforma, cualquier plataforma que valga la pena usar tiene hojas de datos o manuales de referencia de programadores gratuitos del proveedor que incluyen el conjunto de instrucciones y la codificación de los códigos de operación (los bits y bytes del lenguaje de máquina). Con el fin de aprender lo que hace el compilador y cómo escribir código con el que el compilador no tiene que luchar, es bueno conocer algunos conjuntos de instrucciones y ver cómo se implementa el mismo código de alto nivel en cada conjunto de instrucciones con cada compilador con cada optimización. ajuste. No desea optimizar su código solo para descubrir que lo ha mejorado para un compilador / plataforma, pero mucho peor para todos los demás.

Ah, para desensamblar conjuntos de instrucciones de longitud variable, en lugar de simplemente comenzar desde el principio y desensamblar cada palabra de cuatro bytes linealmente a través de la memoria como lo haría con el ARM o cada dos bytes como el msp430 (el msp430 tiene instrucciones de longitud variable pero aún puede pasar pasando linealmente a través de la memoria si comienza en los puntos de entrada de la tabla de vectores de interrupción). Para la longitud variable, desea encontrar un punto de entrada basado en una tabla de vectores o conocimiento sobre cómo arranca el procesador y sigue el código en el orden de ejecución. Debe decodificar cada instrucción por completo para saber cuántos bytes se utilizan, luego, si la instrucción no es una rama incondicional, asuma que el siguiente byte después de esa instrucción es otra instrucción. También debe almacenar todas las direcciones de sucursales posibles y asumir que esas son las direcciones de byte de inicio para obtener más instrucciones. La única vez que tuve éxito hice varias pasadas a través del binario. Comenzando en el punto de entrada, marqué ese byte como el comienzo de una instrucción y luego decodifiqué linealmente a través de la memoria hasta llegar a una rama incondicional. Todos los destinos de rama se etiquetaron como direcciones de inicio de una instrucción. Hice varias pasadas a través del binario hasta que no encontré nuevos objetivos de rama. Si en algún momento encuentra una instrucción de 3 bytes, pero por alguna razón ha etiquetado el segundo byte como el comienzo de una instrucción, tiene un problema. Si el código fue generado por un compilador de alto nivel, esto no debería suceder a menos que el compilador esté haciendo algo malo, si el código tiene un ensamblador escrito a mano (como por ejemplo un viejo juego de arcade) es muy posible que haya ramas condicionales que nunca pueden suceder como r0 = 0 seguido de un salto si no es cero. Puede que tenga que editar manualmente los que están fuera del binario para continuar. Para sus objetivos inmediatos, que supongo que estarán en x86, no creo que tenga un problema.

Recomiendo las herramientas gcc, mingw32 es una forma fácil de usar las herramientas gcc en Windows si x86 es su objetivo. Si no, mingw32 plus msys es una excelente plataforma para generar un compilador cruzado a partir de fuentes binutils y gcc (generalmente bastante fácil). mingw32 tiene algunas ventajas sobre cygwin, como programas significativamente más rápidos y evita el infierno de cygwin dll. gcc y binutils te permitirán escribir en C o ensamblador y desensamblar tu código y hay más páginas web de las que puedes leer que te muestran cómo hacer una o todas las tres. Si va a hacer esto con un conjunto de instrucciones de longitud variable, le recomiendo que utilice un conjunto de herramientas que incluya un desensamblador. Un desensamblador de terceros para x86, por ejemplo, será un desafío de usar, ya que nunca se sabe realmente si se ha desmontado correctamente. Algo de esto también depende del sistema operativo, el objetivo es compilar los módulos en un formato binario que contenga instrucciones de marcado de información a partir de datos para que el desensamblador pueda hacer un trabajo más preciso. Su otra opción para este objetivo principal es tener una herramienta que pueda compilar directamente en ensamblador para su inspección y luego esperar que cuando compile en un formato binario cree las mismas instrucciones.

La respuesta corta (está bien, un poco más corta) a su pregunta. Escriba un desensamblador para aprender un conjunto de instrucciones. Comenzaría con algo RISCY y fácil de aprender como ARM. Una vez que conoce un conjunto de instrucciones, los demás se vuelven mucho más fáciles de aprender, a menudo en unas pocas horas, con el tercer conjunto de instrucciones puede comenzar a escribir código casi de inmediato utilizando la hoja de datos / manual de referencia para la sintaxis. Todos los procesadores que vale la pena usar tienen una hoja de datos o un manual de referencia que describe las instrucciones hasta los bits y bytes de los códigos de operación. Aprenda un procesador RISC como ARM y un CISC como x86 lo suficiente como para tener una idea de las diferencias, cosas como tener que pasar por registros para todo o poder realizar operaciones directamente en la memoria con menos o ningún registro. Tres instrucciones de operando versus dos, etc. A medida que ajusta su código de alto nivel, compile para más de un procesador y compare la salida. Lo más importante que aprenderá es que no importa lo bien que esté escrito el código de alto nivel, la calidad del compilador y las opciones de optimización que se hagan marcan una gran diferencia en las instrucciones reales. Recomiendo llvm y gcc (con binutils), ni producirgran código, pero son multiplataforma y multiplataforma y ambos tienen optimizadores. Y ambos son gratuitos y puede crear fácilmente compiladores cruzados a partir de fuentes para varios procesadores de destino.


Gracias por la respuesta. Pero ni siquiera sé cómo escribir un desensamblador.
Devoró elisio

8
"Escriba su propio desensamblador" - estoy de acuerdo, así es como lo aprendí mejor. (¿Qué pasa con "Pero ni siquiera sé cómo escribir un desmontador"?) LOL.
slashmais

¡Voy contigo! Acabo de comprar un MSP430 y un libro sobre él ... :)
Pepe

1
Tengo algunos ejemplos de msp430 github.com/dwelch67 más algunos simuladores de conjuntos de instrucciones para experimentar con la inclusión de aprendizaje asm, etc.
old_timer

Me gusta mucho esta idea.
Millie Smith

33

El ensamblado que escribiría a mano y el ensamblado generado por un compilador suelen ser muy diferentes cuando se ven desde un nivel alto. Por supuesto, las entrañas del programa serán muy similares ( a = b + cdespués de todo, solo hay tantas formas diferentes de codificar ), pero no son el problema cuando intentas realizar ingeniería inversa en algo. El compilador agregará una tonelada de código repetitivo incluso a ejecutables simples: la última vez que comparé, "Hello World" compilado por GCC fue de aproximadamente 4kB, mientras que si se escribe a mano en ensamblador es alrededor de 100 bytes. Es peor en Windows: la última vez que comparé (es cierto, esto fue el siglo pasado) ¡el "Hola mundo" más pequeño que pude obtener para generar mi compilador de Windows de elección era 52kB! Por lo general, este texto estándar solo se ejecuta una vez, si es que se ejecuta, por lo que no afecta mucho la velocidad del programa; como dije anteriormente, el núcleo del programa, la parte donde se gasta la mayor parte del tiempo de ejecución, suele ser bastante similar, ya sea compilado o escrito a mano.

Al final del día, esto significa que un programador de ensamblaje experto y un desensamblador experto son dos especialidades diferentes. Por lo general, se encuentran en la misma persona, pero en realidad están separados, y aprender a ser un excelente codificador de ensamblajes no te ayudará mucho a aprender ingeniería inversa.

Lo que quiere hacer es tomar los manuales de arquitectura IA-32 y AMD64 (ambos están cubiertos juntos) de Intel y AMD , y revisar las primeras secciones sobre instrucciones y códigos de operación. Tal vez lea uno o dos tutoriales sobre lenguaje ensamblador, solo para aprender los conceptos básicos del lenguaje ensamblador. Entonces toma un pequeñomuestra el programa que le interesa y desmóntelo: recorra su flujo de control e intente comprender lo que está haciendo. Vea si puede parchearlo para hacer otra cosa. Luego, vuelva a intentarlo con otro programa y repita hasta que se sienta lo suficientemente cómodo como para intentar lograr un objetivo más útil. Es posible que le interesen cosas como "crackmes", producidos por la comunidad de ingeniería inversa, que son desafíos para que las personas interesadas en la ingeniería inversa prueben y, con suerte, aprendan algo en el camino. Varían en dificultad desde lo básico (¡comienza aquí!) Hasta lo imposible.

Sobre todo, solo necesitas practicar . Como en muchas otras disciplinas, con la ingeniería inversa, la práctica hace al maestro ... o al menos mejor .


Sé que cuando compila algo con un lenguaje de alto nivel, obtendrá una gran cantidad de código "basura" que no sería necesario si estuviera codificado directamente en ensamblador. También entiendo que hay una diferencia entre un programador de ensamblaje experto y un desensamblador experto. Pero lo mismo podría decirse de casi todo lo demás.
Devoró elisio

3
Mi preocupación es que, si bien en teoría podría leer los artículos y comprender lo que significan, hasta que no empiece a escribir cosas por mí mismo, no creo que lo entienda realmente. Usted dice que puedo comenzar cambiando pequeñas partes del código, pero para hacerlo primero debo saber qué tipo de ensamblado "sabor" IDA pro, por ejemplo, usa.
Devoró elisio

Además, ¿qué usa MSVC ++ para el código ensamblador en línea? MASM?
Devoró elisio

15

Iré en contra de la mayoría de las respuestas y recomendaré la variante MMIX de Knuth de la arquitectura MIPS RISC. No será tan útil en la práctica como los lenguajes ensambladores x86 o ARM (no es que sean tan cruciales en sí mismos en la mayoría de los trabajos de la vida real en estos días ... ;-), pero te desbloqueará la magia de la última versión de Knuth versión de la obra maestra más grande de la historia sobre la comprensión profunda de algoritmos y estructuras de datos de bajo nivel: TAOCP , "El arte de la programación informática". ¡Los enlaces de las dos URL que he citado son una excelente manera de comenzar a explorar esta posibilidad!


12

(No sé ustedes pero estaba emocionado con el montaje)

Una sencilla herramienta para experimentar con el montaje ya está instalada en su PC.

Vaya al menú Inicio-> Ejecutar y escribadebug

debug (comando)

debug es un comando en DOS, MS-DOS, OS / 2 y Microsoft Windows (solo versiones x86, no x64) que ejecuta el programa debug.exe (o DEBUG.COM en versiones anteriores de DOS). Debug puede actuar como un programa ensamblador, desensamblador o volcado hexadecimal que permite a los usuarios examinar de forma interactiva el contenido de la memoria (en lenguaje ensamblador, hexadecimal o ASCII), realizar cambios y ejecutar selectivamente COM, EXE y otros tipos de archivos. También tiene varios subcomandos que se utilizan para acceder a sectores de disco específicos, puertos de E / S y direcciones de memoria. La depuración de MS-DOS se ejecuta en un nivel de proceso de 16 bits y, por lo tanto, está limitada a programas de computadora de 16 bits . FreeDOS Debug tiene una versión "DEBUGX" que también admite programas DPMI de 32 bits.

Tutoriales:


Si desea comprender el código que ve en IDA Pro (u OllyDbg ), deberá aprender cómo está estructurado el código compilado. Recomiendo el libro Reversing: Secrets of Reverse Engineering

Experimenté un par de semanas debugcuando comencé a aprender a ensamblar (hace 15 años).
Tenga en cuenta que debugfunciona a nivel de máquina base, no hay comandos de ensamblaje de alto nivel.

Y ahora un ejemplo simple:

Dar apara comenzar a escribir código ensamblador - escriba el programa de abajo - y finalmente dar gpara ejecutarlo.

texto alternativo


( INT 21muestra en pantalla el carácter ASCII almacenado en el DLregistro si el AHregistro está configurado en 2- INT 20termina el programa)


Tuve que presionar ctrl-c, antes de poder ingresar "g".
ericp

2
@ericp, no tienes que presionar ctrl-c. Por ejemplo, escribe a& [enter] para comenzar a escribir el código ensamblador. Si presiona [enter] dos veces, sale del modo de ensamblaje. g& [enter] para ejecutarlo (compensación 100 por defecto).
Nick Dandoulakis

¿Realmente causa un desbordamiento de pila o simplemente lo escribe en la pantalla?
Janus Troelsen

1
@usuario, solo escribe el nombre de este sitio :-)
Nick Dandoulakis

@JanusTroelsen esos números (53, 74, 61, etc.) son los códigos ASCII para 'S' 't' 'a' ... ¡Cada llamada Int21 imprime un carácter a la vez! Esta es la razón por la que el montaje NO es más rápido :)
doug65536

8

Me pareció que Hacking: The Art of Exploitation es una forma interesante y útil de abordar este tema ... no puedo decir que alguna vez haya usado el conocimiento directamente, pero en realidad no es por eso que lo leí. Le brinda una apreciación mucho más rica de las instrucciones en las que se compila su código, lo que ocasionalmente ha sido útil para comprender errores más sutiles.

No se deje intimidar por el título. La mayor parte de la primera parte del libro es "Hacking" en el sentido de la palabra Eric Raymond: formas creativas, sorprendentes y casi furtivas de resolver problemas difíciles. Yo (y tal vez usted) estaba mucho menos interesado en los aspectos de seguridad.


7

No me concentraría en intentar escribir programas en ensamblador, al menos no al principio. Si está en x86 (que supongo que lo está, ya que está usando Windows), hay toneladas de casos especiales extraños que es inútil aprender. Por ejemplo, muchas instrucciones asumen que está operando en un registro que no nombra explícitamente, y otras instrucciones funcionan en algunos registros pero no en otros.

Aprendería lo suficiente sobre su arquitectura prevista para que comprenda los conceptos básicos, luego simplemente salte e intente comprender la salida de su compilador. Ármate con los manuales de Intel y sumérgete directamente en la salida de tu compilador. Aísle el código de interés en una función pequeña, de modo que pueda estar seguro de comprender todo.

Consideraría que lo básico es:

  • registros: ¿cuántos hay, cómo se llaman y cuáles son sus tamaños?
  • orden de operando: add eax, ebxsignifica "Agregar ebx a eax y almacenar el resultado en eax".
  • FPU: aprenda los conceptos básicos de la pila de punto flotante y cómo se convierte a / desde fp.
  • modos de direccionamiento: [base + desplazamiento * multiplicador], pero el multiplicador solo puede ser 1, 2 o 4 (¿o quizás 8?)
  • convenciones de llamada: ¿cómo se pasan los parámetros a una función?

Muchas veces será sorprendente lo que emite el compilador. Conviértalo en un rompecabezas de averiguar por qué diablos el compilador pensó que esto sería una buena idea. Te enseñará mucho.

Probablemente también le ayude armarse con los manuales de Agner Fog , especialmente con el listado de instrucciones. Le dirá aproximadamente el costo de cada instrucción, aunque esto es más difícil de cuantificar directamente en los procesadores modernos. Pero ayudará a explicar por qué, por ejemplo, el compilador se desvía tanto para evitar emitir una idivinstrucción.

Mi único otro consejo es que siempre uses la sintaxis Intel en lugar de AT&T cuando tengas la opción. Solía ​​ser bastante neutral en este punto, hasta el día en que me di cuenta de que algunas instrucciones son totalmente diferentes entre los dos (por ejemplo, movslqen la sintaxis de AT&T está movsxden la sintaxis de Intel). Dado que todos los manuales están escritos con la sintaxis Intel, quédese con eso.

¡Buena suerte!


3

Comencé a aprender MIPS, que es una arquitectura muy compacta de 32 bits. Es un conjunto de instrucciones reducido, pero eso es lo que lo hace fácil de entender para los principiantes. Aún podrá comprender cómo funciona el ensamblaje sin sentirse abrumado por la complejidad. Incluso puedes descargar un pequeño y agradable IDE, que te permitirá compilar tu código MIPS: clicky Una vez que lo domines, creo que sería mucho más fácil pasar a arquitecturas más complejas. Al menos eso es lo que pensé :) En este punto, tendrá los conocimientos esenciales de asignación y administración de memoria, flujo lógico, depuración, pruebas, etc.


3

La sugerencia de usar depuración es divertida, se pueden hacer muchos trucos ingeniosos con eso. Sin embargo, para un sistema operativo moderno, aprender el ensamblaje de 16 bits puede ser un poco menos útil. Considere, en cambio, usar ntsd.exe. Está integrado en Windows XP (desafortunadamente se eliminó en Server 2003 y versiones posteriores), lo que lo convierte en una herramienta conveniente para aprender ya que está ampliamente disponible.

Dicho esto, la versión original en XP adolece de varios errores. Si realmente desea usarlo (o cdb, o windbg, que son esencialmente interfaces diferentes con la misma sintaxis de comandos y el back-end de depuración), debe instalar el paquete de herramientas de depuración de Windows gratuitas .

El archivo debugger.chm incluido en ese paquete es especialmente útil cuando se trata de descubrir la sintaxis inusual.

Lo mejor de ntsd es que puede abrirlo en cualquier máquina XP que esté cerca y usarlo para ensamblar o desmontar. Hace una herramienta de aprendizaje de ensamblaje / great / X86. Por ejemplo (usando cdb, ya que está en línea en el indicador de dos, es idéntico)

(los errores de símbolo se omitieron porque son irrelevantes; también, espero que este formato funcione, esta es mi primera publicación)

C:\Documents and Settings\User>cdb calc

Microsoft (R) Windows Debugger Version 6.10.0003.233 X86
Copyright (c) Microsoft Corporation. All rights reserved.

CommandLine: calc
Symbol search path is: *** Invalid ***
Executable search path is:
ModLoad: 01000000 0101f000   calc.exe
ModLoad: 7c900000 7c9b2000   ntdll.dll
ModLoad: 7c800000 7c8f6000   C:\WINDOWS\system32\kernel32.dll
ModLoad: 7c9c0000 7d1d7000   C:\WINDOWS\system32\SHELL32.dll
ModLoad: 77dd0000 77e6b000   C:\WINDOWS\system32\ADVAPI32.dll
ModLoad: 77e70000 77f02000   C:\WINDOWS\system32\RPCRT4.dll
ModLoad: 77fe0000 77ff1000   C:\WINDOWS\system32\Secur32.dll
ModLoad: 77f10000 77f59000   C:\WINDOWS\system32\GDI32.dll
ModLoad: 7e410000 7e4a1000   C:\WINDOWS\system32\USER32.dll
ModLoad: 77c10000 77c68000   C:\WINDOWS\system32\msvcrt.dll
ModLoad: 77f60000 77fd6000   C:\WINDOWS\system32\SHLWAPI.dll
(f2c.208): Break instruction exception - code 80000003 (first chance)
eax=001a1eb4 ebx=7ffd6000 ecx=00000007 edx=00000080 esi=001a1f48 edi=001a1eb4
eip=7c90120e esp=0007fb20 ebp=0007fc94 iopl=0         nv up ei pl nz na po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000202
ntdll!DbgBreakPoint:
7c90120e cc              int     3
0:000> r eax
eax=001a1eb4
0:000> r eax=0
0:000> a eip
7c90120e add eax,0x100
7c901213
0:000> u eip
ntdll!DbgBreakPoint:
7c90120e 0500010000      add     eax,100h
7c901213 c3              ret
7c901214 8bff            mov     edi,edi
7c901216 8b442404        mov     eax,dword ptr [esp+4]
7c90121a cc              int     3
7c90121b c20400          ret     4
ntdll!NtCurrentTeb:
7c90121e 64a118000000    mov     eax,dword ptr fs:[00000018h]
7c901224 c3              ret
0:000> t
eax=00000100 ebx=7ffd6000 ecx=00000007 edx=00000080 esi=001a1f48 edi=001a1eb4
eip=7c901213 esp=0007fb20 ebp=0007fc94 iopl=0         nv up ei pl nz na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000206
ntdll!DbgUserBreakPoint+0x1:
7c901213 c3              ret
0:000>`

Además, mientras juegas con IDA, asegúrate de consultar el IDA Pro Book de Chris Eagle (desvinculado ya que StackOverflow no quiere permitirme publicar más de dos enlaces para mi primera publicación). Es sin duda la mejor referencia que existe.


1
+1 para el libro de Chris Eagle. Tengo que poner un poco de amor allí para el Sk3wl de r00t;)
mrduclaw

3

Recientemente tomé una clase de sistemas informáticos. Uno de los temas fue el ensamblaje como herramienta para comunicarse con el hardware.

Para mí, el conocimiento del ensamblaje no habría sido completo sin comprender los detalles de cómo funcionan los sistemas informáticos. Comprender eso trae una nueva comprensión de por qué las instrucciones de ensamblaje en una arquitectura de procesador son excelentes, pero son terribles en otra arquitectura.

Dado esto, me inclino a recomendar el libro de texto de mi clase:

Sistemas informáticos: la perspectiva de un programador .

Sistemas informáticos: la perspectiva de un programador
(fuente: cmu.edu )

Cubre el ensamblaje x86, pero el libro es mucho más amplio que eso. Cubre el revestimiento de la tubería del procesador y la memoria como caché, el sistema de memoria virtual y mucho más. Todo esto puede afectar cómo se podría optimizar el ensamblaje para las características dadas.


2

Creo que desea aprender los mnemónicos del código de operación en ASCII (y sus parámetros), que son generados por un desensamblador y que son entendidos por (se pueden usar como entrada para) un ensamblador.

Cualquier ensamblador (por ejemplo, MASM) serviría.

Y / o quizás sea mejor que leas un libro al respecto (se han recomendado libros sobre SO, no recuerdo cuál).


2

¿Estás haciendo otro trabajo de desarrollo en Windows? ¿En qué IDE? Si es VS, entonces no hay necesidad de un IDE adicional solo para leer el código desensamblado: depure su aplicación (o adjúntela a una aplicación externa), luego abra la ventana de desensamblaje (en la configuración predeterminada, eso es Alt + 8). Pase y observe la memoria / registros como lo haría con el código normal. También es posible que desee mantener abierta una ventana de registros (Alt + 5 de forma predeterminada).

Intel ofrece manuales gratuitos , que brindan tanto un resumen de la arquitectura básica (registros, unidades de procesador, etc.) como una referencia de instrucciones completa. A medida que la arquitectura madura y se vuelve más compleja, los manuales de 'arquitectura básica' se vuelven cada vez menos legibles. Si puede conseguir una versión anterior, probablemente tenga un mejor lugar para comenzar (incluso los manuales P3, que explican mejor el mismo entorno de ejecución básico).

Si desea invertir en un libro, aquí tiene un buen texto introductorio. Busque en Amazon para 'x86' y obtendrá muchos otros. Puede obtener varias otras instrucciones de otra pregunta aquí .

Por último, puede beneficiarse bastante de la lectura de algunos de bajo - nivel blogs. Estos bits de información de tamaño de byte funcionan mejor para mí, personalmente.


2

¡Esto no necesariamente le ayudará a escribir código eficiente!

Los códigos de operación i86 son más o menos un formato "heredado" que persiste debido al gran volumen de código y binarios ejecutables para Windows y Linux que existen.

Es un poco como los antiguos eruditos que escriben en latín, un hablante de italiano como Galileo escribiría en latín y su artículo podría ser entendido por un hablante de polaco como Copérnico. Ésta seguía siendo la forma más eficaz de comunicarse, a pesar de que ninguno era particularmente bueno en latín, y el latín es un idioma basura para expresar ideas matemáticas.

Por lo tanto, los compiladores generan código x86 de forma predeterminada, y los chips modernos leen los códigos de operaciones anceint y transfieren lo que ven en instrucciones de riesgo en paralelo, con ejecución reordenada, ejecución especulativa, canalización, etc., además de que hacen uso completo de los 32 o 64 registros del procesador. en realidad tiene (a diferencia del patético 8 que ves en las instrucciones x86).

Ahora, todos los compiladores de optimización saben que esto es lo que realmente sucede, por lo que codifican secuencias de códigos OP que saben que el chip puede optimizar de manera eficiente, aunque algunas de estas secuencias parecerían insuficientes para un programador .asm de alrededor de 1990.

En algún momento, debe aceptar que las decenas de miles de años de esfuerzo que los escritores de compiladores han realizado han dado sus frutos y, confíe en ellos.

La forma más sencilla y fácil de obtener un tiempo de ejecución más eficiente es comprar el compilador Intel C / C ++. Tienen un nicho de mercado para compiladores eficientes y tienen la ventaja de poder preguntar a los diseñadores de chips sobre lo que sucede dentro.


Su historia sugiere un poco que los procesadores CISC se han convertido internamente en procesadores RISC. Puede que lo haya entendido mal, pero esto simplemente no es cierto. ¿Y el patético 8? Los procesadores modernos (digamos, desde 1999) incluyen muchos más: 10 gpr: EAX-EFLAGS, FP0-FP7 de 80 bits, MMX0-MMX7 de 64 bits, XMM0-XMM7 de 128 bits, segmento: CS-GS, especiales: CR0-CR4 , DR0-DR7, TR3-TR7, GDTR, IDTR, LDTR, MSR y en x86-64 también R8-R15. No todos son accesibles desde ring-3, pero la mayoría son y la mayoría son utilizados por compiladores recientes (posteriores a 2006) de GCC / VC ++. En total un poco más que el "patético 8";).
Abel

2

Para hacer lo que quiere hacer, simplemente tomé la referencia del conjunto de instrucciones de Intel (puede que no sea exactamente la que usé, pero parece suficiente) y algunos programas simples que escribí en Visual Studio y comencé a lanzarlos en IDAPro / Windbg . Cuando crecí más que mis propios programas, el software de crackmes fue útil.

Supongo que tiene un conocimiento básico de cómo se ejecutan los programas en Windows. Pero realmente, para leer el ensamblaje, solo hay unas pocas instrucciones para aprender y algunos sabores de esas instrucciones (por ejemplo, hay una instrucción de salto, el salto tiene algunos sabores como jump-if-equal, jump-if-ecx-is-zero , etc.). Una vez que aprenda las instrucciones básicas, es bastante sencillo obtener la esencia de la ejecución del programa. La vista gráfica de IDA ayuda, y si está rastreando el programa con Windbg, es bastante simple averiguar qué hacen las instrucciones si no está seguro.

Después de jugar un poco así, compré Hacker Disassembly Uncovered . En general, me mantengo alejado de los libros con la palabra "Hacker" en el título, pero me gustó mucho la forma en que este fue tan profundo acerca de cómo se veía desmontado el código compilado. También entra en las optimizaciones del compilador y algunas cosas de eficiencia que fueron interesantes.

En realidad, todo depende de cuán profundamente desee comprender el programa también. Si está aplicando ingeniería inversa a un objetivo en busca de vulnerabilidades, si está escribiendo código de explotación o analizando malware empaquetado en busca de capacidades, necesitará más tiempo de preparación para que las cosas realmente funcionen (especialmente para el malware más avanzado ). Por otro lado, si solo quieres poder cambiar el nivel de tu personaje en tu videojuego favorito, deberías estar bien en un período de tiempo relativamente corto.


1

Uno de los lenguajes ensambladores pedagógicos estándar que existen es MIPS. Puede obtener simuladores MIPS (spim) y varios materiales didácticos para ello.

Personalmente, no soy fan. Me gusta mucho IA32.


MIPS es bueno. 68000 también lo es, y si aprende 68000, puede escribir binarios que se ejecuten en MAME. :-)
Nosredna

1

Mi favorito personal es NASM, sobre todo porque es multiplataforma y compila MMX, SSE, 64 bits ...

Comencé a compilar un archivo fuente simple en C con gcc, y "transcodificando" la instrucción del ensamblador del formato gcc al formato NASM. Luego, puede cambiar pequeñas porciones de código y verificar la mejora de rendimiento que aporta.

La documentación de NASM es realmente completa, nunca necesité buscar información en libros u otras fuentes.



0

Muchas buenas respuestas aquí. La programación de bajo nivel, el ensamblaje, etc. son populares en la comunidad de seguridad, por lo que vale la pena buscar sugerencias y sugerencias allí una vez que comience. Incluso tienen algunos buenos tutoriales como este sobre ensamblaje x86 .


0

Para alcanzar realmente su objetivo, puede considerar comenzar con el IDE en el que se encuentra. Por lo general, es una ventana de desensamblador, por lo que puede hacer un solo paso a través del código. Por lo general, hay una vista de algún tipo que le permite ver los registros y buscar áreas de memoria.

El examen de código c / c ++ no optimizado ayudará a crear un vínculo en el tipo de código que genera el compilador para sus fuentes. Algunos compiladores tienen algún tipo de palabra reservada ASM que le permite insertar instrucciones de máquina en su código.

Mi consejo sería jugar con ese tipo de herramientas por un tiempo y mojarse los pies, ¿luego dar un paso adelante? ¿abajo? al código ensamblador directo en cualquier plataforma en la que esté ejecutando.

Hay muchas herramientas excelentes, pero es posible que le resulte más divertido evitar la empinada curva de aprendizaje al principio.


0

Aprendimos a ensamblar con un kit de desarrollo de microcontroladores (Motorola HC12) y una hoja de datos gruesa.


0

Fuera del tema, lo sé, pero como usted es un programador de Windows, no puedo evitar pensar que puede ser un uso más apropiado y / o mejor de su tiempo para aprender MSIL. No, no es ensamblaje, pero probablemente sea más relevante en esta era .NET.


0

Conocer el ensamblaje puede ser útil para la depuración, pero no me entusiasmaría demasiado usarlo para optimizar su código. Los compiladores modernos suelen ser mucho mejores optimizando que un humano en estos días.


Hmm. Todavía puede exprimir un poco más de ensamblaje de codificación usted mismo, pero se necesita más trabajo para vencer al compilador que antes.
Nosredna

0

Puede ver el curso de video de ensamblaje xorpd x86 . (Yo lo escribi). El curso en sí es de pago, pero los ejercicios son de código abierto, en github. Si tienes algo de experiencia en programación, creo que deberías poder trabajar solo con los ejercicios y entender todo.

Tenga en cuenta que el código es para la plataforma Windows y está escrito con el ensamblador Fasm . El curso y los ejercicios no contienen construcciones de alto nivel, sin embargo, puede usar Fasm para crear macros muy complicadas, si alguna vez desea hacerlo.

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.