Självmodifierande kod

Den aktuella versionen av sidan har ännu inte granskats av erfarna bidragsgivare och kan skilja sig väsentligt från versionen som granskades den 6 juli 2019; kontroller kräver 3 redigeringar .

Självmodifierande kod (SMC) är en programmeringsteknik där en applikation skapar eller ändrar en del av sin programkod vid körning. Sådan kod används vanligtvis i program skrivna för en processor med en von Neumann- minnesorganisation.

Vid tidpunkten för ändringen är metoden uppdelad i:

I båda fallen sker ändringen direkt i maskinkoden när nya instruktioner skriver över gamla (t.ex. en villkorlig gren JZ , JNZ , JE , JNE , etc. ersätts av en ovillkorlig gren JMP eller NOP ). IBM /360 och Z/Architecture - instruktionsuppsättningarna har en EXECUTE (EX) -instruktion som skriver över målinstruktionen (inspelad i den andra byten av EX-instruktionen) med de minst signifikanta 8 bitarna av register 1. På dessa arkitekturer implementerar den en standard, legitim metod för att tillfälligt ändra instruktioner .

Utnämning

Huvudapplikationer för självmodifierande kod:

Tillämpbarhet på processorer med Harvard-arkitektur

I Harvard-arkitekturen är minne för kod och minne för data separerade. Följaktligen blir arbetet med självmodifierande kod mycket mer komplicerat i dem. Även om x86- arkitekturen definieras som von Neumann (enkelkod och dataminne) har de flesta moderna processorer separata cacheområden för kod och data. Samtidigt stöder kodcachen inte skrivning, och när man ändrar det cachade minnesområdet, antingen en partiell eller fullständig återställning av kodcachen (x86) eller en explicit instruktion till processorn att återställa kodcachen ( SPARC ) kan krävas. På grund av detta kan nymodifierad kod köras långsammare eller kräva ytterligare kommandon för att fungera korrekt. Genom att ändra koden återställs även processorpipelinen . [2]

Vissa idéer om Harvard-arkitekturen är också implementerade i operativsystemet (till exempel Data Execution Prevention i Windows, W^X i OpenBSD ) och i processorer (för x86 - NX-bitar och liknande). I dessa implementeringar kan enskilda minnesbitar markeras som icke-körbara (dvs data) eller som körbara men inte modifierbara (dvs kod utan rätt att ändra). Användningen av självmodifierande kod i sådana programmeringsmiljöer är komplicerad, eftersom den antingen måste placeras i ett oskyddat minnesområde (ibland är det här området stacken ), eller uttryckligen inaktivera skyddet för att koden ska ändras .

Användning

Tolkade språk

Perl , PHP och Python tillåter ett program att skapa ny kod vid körning och köra den med hjälp av eval-funktionen, men tillåter inte att befintlig kod modifieras själv (interaktivt python-skal) :

>>> x = 1 >>> eval ( 'x + 1' ) 2 >>> eval ( 'x' ) 1

Illusionen av modifiering (förutsatt att ingen inbyggd kod faktiskt ändras) uppnås genom att ändra funktionspekaren, som i detta JavaScript- exempel:

var f = funktion ( x ) { return x + 1 }; alert ( f ( 0 )); //ett f = ny funktion ( 'x' , 'retur x + 2' ); // tilldela en ny definition till f alert ( f ( 0 )); //2

Se även

Anteckningar

  1. Se till exempel Doom Legacy källkod , funktion ASM_PatchRowBytes.
  2. Kaspersky, stycke med "Processors of the Pentium family .."

Länkar