Self modifying code
 
5. Mogelijkheden in de toekomst

In dit hoofdstuk zal worden ingegaan op de mogelijkheden van self modifying code die nog niet bekeken zijn en in de toekomst misschien een toepassing hebben. Ook zal worden gekeken naar de toepasbaarheid van de techniek in de nabije toekomst.

Één van de plaatsten waar self modifying code gebruikt zou kunnen worden is fout-detectie en fout-correctie in het eigen programma. Bij sommige toepassingen is het van groot belang dat de programmatuur blijft werken, omdat het de besturing van kritieke apparaten of installaties bevat. Hierbij kan bijvoorbeeld gedacht worden aan code in satellieten of andere apparatuur die worden blootgesteld aan extreme omstandigheden. Er zou dan door het programma zelf gecontroleerd kunnen worden of zijn code nog wel voldoet aan één of andere checksum. Als dit niet het geval is zouden maatregelen genomen kunnen worden. De originele instructies zouden teruggezet kunnen worden of de code zou in het geheugen verplaatst kunnen worden. Een dergelijke methode zou ook gebruikt kunnen worden om infecties door virussen te detecteren.

Zolang besturingssystemen self modifying code toelaten en er virussen bestaan, zullen deze self modifying code gebruiken om hun activiteiten te verbergen. Er zullen slimmere virussen komen die steeds moeilijker te ontdekken zijn. Gedacht zou kunnen worden aan virussen die logica bevatten om hun eigen instructies te herschrijven met behoud van functionaliteit. De instructies uit figuur 5.1 hebben bijvoorbeeld allemaal het resultaat dat register r1 de waarde 0 krijgt. Ook is de volgorde van instructies lang niet altijd van belang en zijn hierin ook verschillende combinaties mogelijk.

move #0,r1
xor r1,r1
sub r1,r1
and #0,r1
figuur 5.1

Bij elke nieuwe generatie kan het virus zichzelf compleet herschrijven met andere instructies. Voeg hierbij een nieuwe coderingsmethode of andere stealth vormen en je hebt een enorme hoeveelheid vormen van het hetzelfde virus. Twee opvolgende generaties van deze virussen zullen weinig tot geen woorden meer het zelfde hebben. Dit alles maakt het vinden van deze virussen een stuk moeilijker. Deze virussen zullen zeer zeker veel groter zijn dan hun huidige soortgenoten, maar met de toenemende grote van normale programmatuur zal dat niet of nauwelijks opvallen.

Er zijn systemen waarbij voor het executeren van code gecontroleerd wordt of deze code geen schadelijke dingen kan uitvoeren. De java class loader kan bijvoorbeeld tijdens het laden van de code een check doen om te zien of de structuur geldig is. Er wordt onder andere gekeken of er het programma geen ongeldige instructies bevat, of er geen ongeldige pointerbewerkingen plaatsvinden, of de stack geldig blijft en of toegangsrechten op objecten nageleefd worden (private members zijn niet toegankelijk vanuit andere objecten). Als dit soort systemen self modifying code toelaten (wat java, voor zover wij kunnen nagaan niet doet) is dit een methode om tijdens runtime 'schadelijke' code te genereren. Dit kan gebruikt worden de checks die bij het laden gedaan worden te omzeilen.

Omdat het gedrag van self modifying code erg moeilijk te voorspellen is, is het bij het controleren van de code niet eenvoudig om de werking ervan af te leiden. Om veiligheid te garanderen is het dus nodig dat ook tijdens runtime de nodige controles uitgevoerd worden.

Een toepassing van het aanpassen van code die nog wel onderzocht wordt is het gebruik van genetische algoritmes. Genetische algoritmes zijn zoek algoritmes die het systeem van natuurlijk selectie bij levende wezens nabootsen. Delen van code binnen deze algoritmes worden gezien als chromosomen of genen. Genetische algoritmes werken door tussen twee fasen heen en weer te bewegen, namelijk de "fit testing" en "vermenigvuldigen". In de eerste fase worden een grote populatie van programma's uitgevoerd. Deze krijgen een score hoe goed ze presteren tijdens het uitvoeren van een taak. De programma's die het hoogst scoren mogen zich "voortplanten".

Voortplanting wordt gerealiseerd door delen van elkaars code om te wisselen. Dus algoritme A ruilt een stuk code met dat van algoritme B. Een andere vorm van voortplanten is mutatie. Bij mutatie wordt een deel van een van de kinderen een klein beetje aangepast.

(1)
(2)
(3)
  A-G-E-Y-S-V-P-T-S
  A-G-E-j-w-a-h-r-x
  A-G-F-j-w-a-h-r-x
algoritme 1
  n-e-g-j-w-a-h-r-x
  n-e-g-Y-S-V-P-T-S
  n-e-g-Y-S-V-P-T-S
algoritme 2
figuur 5.2

In figuur 5.2 zijn voorbeelden van mutaties van code gegeven. De letters stellen verschillende codedelen (genen) voor. In stap 1 zijn twee kandidaat algoritmen gegeven die klaar zijn om voortgeplant te worden. In stap 2 hebben de twee algoritmen code uitgewisseld en in stap 3 heeft algoritme 1 een kleine mutatie ondergaan. Het is mogelijk om zo van een klein aantal algoritmen een groot aantal nieuwe algoritmen te genereren.

Het doel van genetische algoritme is te beginnen met "willekeurige" code en het algoritme te laten evolueren om een bepaalde taak uit te voeren. Omdat programma's beloont afhankelijk van hoe ze presteren tijdens het uitvoeren van deze taak, voert elke nieuwe generatie van het algoritme de taak beter uit.

Door neurale netwerken te maken met behulp van genetische algoritmen, eventueel met self modifying code, zouden wellicht systemen gemaakt kunnen worden die dynamischer zijn dan de huidige systemen. Het dynamisch op problemen inspelen zou wel eens belangrijk kunnen worden in de toekomst, vooral bij grotere beslissingssystemen.

Gezien de huidige ontwikkelingen in de hardware en besturingssystemen is het niet waarschijnlijk dat self modifying code, voor general purpose systemen, een 'gezonde' toekomst tegemoet gaat. Steeds meer processoren en besturingssystemen gebruiken technieken waarin code als statisch wordt beschouwd en verandering van code grote kosten met zich meebrengt. Door de toename in snelheid van computers en ook het heel goedkoop zijn van geheugen is het gebruik van self modifying code voor tijd en ruimte optimalisatie bij 'gewone' systemen niet meer nodig. Hierdoor zal self modifying code steeds minder gebruikt gaan worden op systemen voor algemene toepassingen.