executable self-modifying

executable - ¿Cuáles son los usos del código de auto modificación?



self-modifying (14)

¿Inteligencia artificial?

¿Hay algún uso real para el código de auto modificación ?

Sé que se pueden usar para construir gusanos / virus, pero me preguntaba si hay alguna buena razón para que un programador tenga que usar el código de auto modificación.

¿Algunas ideas? Las situaciones hipotéticas también son bienvenidas.


En el pasado, donde la RAM era limitada, se usaba código de auto modificación para ahorrar memoria. Hoy en día, por ejemplo, las utilidades de compresión de aplicaciones como UPX se usan para descomprimir / modificar el propio código después de cargar una imagen comprimida de la aplicación.


He visto código de auto modificación usado para:

  1. optimización de velocidad, haciendo que el programa escriba más código sobre la marcha

  2. obstrucción, para hacer la ingeniería inversa mucho más difícil


LOL - He escrito código de auto modificación en dos ocasiones:

  1. cuando aprendí por primera vez el lenguaje ensamblador, antes entendía el acceso indizado indirecto
  2. accidentalmente, como errores de puntero en lenguaje ensamblador y C

Puedo imaginar que puede haber escenarios en los que el código de auto modificación sería más eficiente que las alternativas, pero nada obvio salta a la mente. En general, esto es algo que hay que evitar: depurar pesadillas, etc., a menos que intentes ofuscar deliberadamente como se mencionó anteriormente.


La vinculación dinámica es una especie de auto-modificación (parcheo de ubicaciones de salto absolutas y / o relativas) ... eso normalmente lo hace el cargador de programas de O / S.


Mike Abrash describió el generador de códigos Pixomatic para el Dr. Dobb''s Journal hace un tiempo: http://www.ddj.com/architect/184405807 . Es un rasterizador compatible con el software 3d dx7 (?).


Muchas razones La parte superior de mi cabeza:

  • Construcción de clases en tiempo de ejecución y meta programación. Por ejemplo, tener una fábrica de clases que toma una conexión con una tabla SQL y genera una clase de cliente especializada para esa tabla (con accesodores para las columnas, métodos de búsqueda, etc.).

  • Luego, por supuesto, está el famoso ejemplo de bitblt y los análogos de regexp.

  • Optimización dinámica basada en información de RT a la tracing JIT

  • Subtipo de especialización de las funciones genéricas del estilo ada en un entorno de crecimiento.

- MarkusQ


Porque el Commodore 64 no tiene muchos registros y tiene un procesador de 1Mhz. Cuando necesite leer una dirección de memoria compensada por un valor, es más fácil modificar la fuente.

@Reader: LDA $C000 STA $D020 INC Reader+1 JMP Reader

Esa es la última vez que escribí el código de auto modificación de todos modos :-)


Resulta que la entrada de Wikipedia en " código de auto modificación " tiene una gran lista:

  1. Optimización semiautomática de un ciclo dependiente del estado.
  2. Generación de código en tiempo de ejecución , o especialización de un algoritmo en tiempo de ejecución o tiempo de carga (que es popular, por ejemplo, en el dominio de gráficos en tiempo real) como una utilidad de ordenamiento general que prepara código para realizar la comparación de claves descrita en una invocación específica.
  3. Alteración del estado de un objeto en línea, o simulación de la construcción de cierres de alto nivel.
  4. Aplicación de parches a las llamadas a direcciones de subrutinas , como suele hacerse en el momento de la carga de las bibliotecas dinámicas, o en cada invocación parcheando las referencias internas de la subrutina a sus parámetros para utilizar sus direcciones reales. Si esto se considera como ''código de auto modificación'' o no es un caso de terminología.
  5. Sistemas de computación evolutivos como la programación genética.
  6. Ocultación de código para evitar la ingeniería inversa , como a través del uso de un desensamblador o depurador.
  7. Ocultación de código para evadir la detección por software de escaneo de virus / spyware y similares.
  8. Llenando el 100% de la memoria (en algunas arquitecturas) con un patrón continuo de códigos de operación repetitivos, para borrar todos los programas y datos , o para grabar hardware .
  9. Compresión del código que se descomprimirá y ejecutará en el tiempo de ejecución, por ejemplo, cuando la memoria o el espacio en el disco sea limitado.
  10. Algunos conjuntos de instrucciones muy limitados no dejan otra opción más que usar código de auto modificación para lograr cierta funcionalidad . Por ejemplo, una máquina "Una computadora con conjunto de instrucciones" que utiliza solo la "instrucción" restar y ramificar si es negativa no puede hacer una copia indirecta (algo así como el equivalente de "* a = ** b" en la programación C idioma) sin usar código de auto modificación.
  11. Alterando las instrucciones para la tolerancia a fallas

Sobre el punto de frustrar a los piratas informáticos usando código de auto modificación:

En el transcurso de varias actualizaciones de firmware, DirectTV montó lentamente un programa en su tarjeta inteligente para destruir tarjetas que han sido pirateadas para recibir ilegalmente canales no pagados. Vea el artículo de Jeff''s Coding Horror en el Black Sunday Hack para más información.



La generación dinámica de código en SwiftShader es una forma de código de auto modificación que le permite implementar Direct3D 9 de manera eficiente en la CPU.


Porque es realmente genial, y a veces eso es motivo suficiente.


Las aplicaciones que implementan sus propios lenguajes de scripting a menudo hacen esto. Por ejemplo, los servidores de bases de datos a menudo compilan procedimientos almacenados (o consultas) de esta manera.


Los lenguajes ensambladores de la era de los años 60 usaban código de auto modificación para implementar llamadas a funciones sin una pila.

Knuth, v1, 1ed p.182:

MAX100 STJ EXIT ;Subroutine linkage ENT3 100 ;M1. Initialize JMP 2F 1H CMPA X,3 ;M3. Compare JGE *+3 2H ENT2 0,3 ;M4. Change m LDA X,3 ;(New maximum found) DEC3 1 ;M5. Decrease k J3P 1B ;M2. All tested? EXIT JMP * ;Return to main program

En un programa más grande que contiene esta codificación como subrutina, la instrucción única "JMP MAX100" haría que el registro A se establezca en el valor máximo actual de las ubicaciones X + 1 a X + 100, y la posición del máximo aparecería en rI2 . El enlace de subrutina en este caso se logra mediante las instrucciones "MAX100 STJ EXIT" y, más tarde, "EXIT JMP *". Debido a la forma en que funciona el registro J, la instrucción de salida saltará a la ubicación siguiente al lugar donde se hizo la referencia original a MAX100.

Editar: Puede ser difícil ver lo que está pasando, incluso con la breve explicación aquí. En la línea MAX100 STJ EXIT , MAX100 es una etiqueta para la instrucción (y por lo tanto para el procedimiento en conjunto), STJ significa ALMACENAR el registro de salto (de donde venimos), EXIT significa que la ubicación de la memoria etiquetada ''EXIT'' es la objetivo de la TIENDA. EXIT , vemos más adelante es la etiqueta de la última instrucción. ¡Así que está sobrescribiendo el código! Pero, muchas instrucciones (incluido STJ aquí) sobrescriben implícitamente solo la parte de operando de la palabra de instrucción. Por lo tanto, el JMP permanece intacto y el * es un token falso, ya que no tiene nada significativo colocar, solo se sobrescribe.

El código de auto-modificación también se usa cuando el direccionamiento indirecto no está disponible, y sin embargo, la dirección que necesita se encuentra justo ahí en el registro. PDP-1 LISP:

dap .+1 ;deposit address part of accumulator in (IP+1) lac xy ;load accumulator with (ADDRESS) [xy is a dummy symbol, just like * above]

Estas dos instrucciones realizan ACC := (ACC) modificando el operando de la instrucción de carga.

Las modificaciones como estas son relativamente seguras, y en arquitecturas antiguas, son necesarias.