Buffer overflows en shellcode
Verken de werking van kwetsbaarheden door buffer overflows en hoe deze kunnen worden misbruikt om kwaadaardige shellcode te injecteren en uit te voeren.
Buffer overflows en shellcode is een gratis Assemblytaal en x86-programmeren voor systemen op laag niveau-les op CoddyKit. Dit is les 3 van 4. Je kunt de volledige les hieronder gratis lezen en daarna in de browser praktisch oefenen met een ingebouwde code-editor en een AI-begeleider die 24/7 beschikbaar is. Deze les maakt deel uit van het leertraject Assemblytaal en x86-programmeren voor systemen op laag niveau. Je voortgang wordt gesynchroniseerd op het web en in de CoddyKit-app. De cursus Assemblytaal en x86-programmeren voor systemen op laag niveau bevat in totaal 4 lessen.
Introductie: bufferoverflows
Welkom bij een belangrijk onderwerp in low-levelbeveiliging: bufferoverflows. Dit is een type kwetsbaarheid in software waarmee aanvallers controle over een programma kunnen krijgen.
Een bufferoverflow ontstaat wanneer een programma meer gegevens naar een buffer met een vaste grootte probeert te schrijven dan waarvoor die buffer is ontworpen. Deze overtollige gegevens lopen over naar aangrenzende geheugengebieden.
Wat is een buffer?
Bij het programmeren, vooral in talen zoals C of assembly, is een buffer eenvoudigweg een geheugenblok dat is gereserveerd om gegevens op te slaan. Je kunt het zien als een container met een bepaalde capaciteit.
- Buffers worden vaak gebruikt voor tijdelijke opslag, bijvoorbeeld voor gebruikersinvoer of netwerkgegevens.
- Je kunt ze declareren als arrays van tekens (tekenreeksen) of van andere gegevenstypen.
- Met
char username[32];declareer je bijvoorbeeld een buffer die maximaal 31 tekens plus een null-terminator kan bevatten.
Code: een kwetsbare buffer
Bekijk een eenvoudig C-programma met opzettelijk een kwetsbaarheid voor bufferoverflows. Let goed op de functie strcpy.
strcpy kopieert een tekenreeks van de bron naar de bestemming, maar controleert niet de grootte van de bestemmingsbuffer. Dit is een veelvoorkomende oorzaak van overflows.
/* buffer_example.c */
#include <stdio.h>
#include <string.h>
// This function is intentionally vulnerable
void vulnerable_greet(char *name_input) {
char buffer[16]; // A small buffer, 16 bytes
// This is the vulnerability! strcpy doesn't check size.
// If name_input is longer than 15 chars (+ null terminator),
// it will overflow 'buffer'.
strcpy(buffer, name_input);
printf("Hello, %s!\n", buffer);
}
int main() {
// Let's call the vulnerable function with a safe input
vulnerable_greet("CoddyKit User");
printf("Program finished normally.\n");
return 0;
}Het stackframe
Om te begrijpen hoe overflows kunnen worden misbruikt, moeten we de callstack opnieuw bekijken. Wanneer een functie wordt aangeroepen, wordt er een nieuw stackframe gemaakt.
Dit stackframe bevat doorgaans:
- Lokale variabelen voor de functie.
- De opgeslagen basepointer (EBP/RBP).
- Het belangrijkste: het retouradres, dat de CPU vertelt waar de uitvoering moet worden hervat nadat de functie is voltooid.
Het retouradres overschrijven
Wanneer er op de stack een bufferoverflow optreedt, worden door de overtollige gegevens niet alleen aangrenzende lokale variabelen beschadigd. Als er genoeg gegevens worden aangeleverd, kunnen ze de opgeslagen EBP en vervolgens het retouradres zelf overschrijven.
Door het retouradres te wijzigen, kan een aanvaller het programma laten springen naar een willekeurige geheugenlocatie in plaats van terug te keren naar de legitieme aanroeper. Dit is het belangrijkste mechanisme achter veel exploits voor bufferoverflows.
Kennismaken met shellcode
Waar wil de aanvaller het programma naartoe laten springen? Meestal naar een stukje code waarover diegene controle heeft, genaamd shellcode.
- Shellcode is een klein, zelfstandig stuk machinecode.
- Het belangrijkste doel is vaak het uitvoeren van een 'shell' (een opdrachtprompt) op het doelsysteem.
- Shellcode kan ook andere schadelijke acties uitvoeren, zoals nieuwe gebruikers aanmaken, bestanden downloaden of verbinding maken met een externe server.
Anatomie van eenvoudige shellcode
Shellcode wordt doorgaans geschreven in assembly om deze zo compact en efficiënt mogelijk te maken. Null-bytes (\x00) worden vermeden, omdat veel tekenreeksfuncties stoppen met kopiëren bij de eerste null-byte.
Een veelvoorkomend doel is het aanroepen van de systeemaanroep execve (op Linux) om /bin/sh te starten.
; Example (conceptual) Linux x86 shellcode snippet:
; mov eax, 0x0b ; Syscall number for execve
; mov ebx, addr_of_sh ; Pointer to '/bin/sh' string
; mov ecx, 0 ; Arg 2 (argv) = NULL
; mov edx, 0 ; Arg 3 (envp) = NULL
; int 0x80 ; Invoke kernel (syscall)Shellcode injecteren
Hoe komt de shellcode in het programma terecht? De aanvaller voegt deze toe aan de schadelijke invoer die de bufferoverflow veroorzaakt.
Wanneer de buffer overloopt, wordt de shellcode naar het geheugen van het programma geschreven, meestal naar de stack, naast het overschreven retouradres.
Exploitstructuur: NOP-slede
Aanvallers gebruiken vaak een NOP-slede (No Operation-slede) om hun exploit betrouwbaarder te maken.
- Een NOP-slede is een reeks instructies voor 'No Operation' (NOP), zoals
\x90op x86. - Als de aanvaller het retouradres overschrijft met een adres dat ergens binnen de NOP-slede ligt, voert de CPU eenvoudig NOP's uit totdat deze naar de eigenlijke shellcode 'glijdt'.
- Hierdoor wordt gecompenseerd voor kleine onnauwkeurigheden bij het raden van het exacte geheugenadres van de shellcode.
Beveiligingen en maatregelen
Besturingssystemen en compilers hebben verschillende beveiligingen tegen bufferoverflows ontwikkeld:
- ASLR (Address Space Layout Randomization): maakt geheugenadressen willekeurig, zodat het moeilijker wordt om het retouradres of de locatie van de shellcode te raden.
- DEP/NX-bit (Data Execution Prevention/No-Execute): markeert geheugengebieden, zoals de stack, als niet-uitvoerbaar, zodat shellcode daar niet kan worden uitgevoerd.
- Stackcanaries: door de compiler gegenereerde willekeurige waarden die op de stack worden geplaatst; als ze worden overschreven, detecteert het programma de manipulatie en wordt het afgebroken.
- Veilige functies: functies gebruiken zoals
strncpy,snprintf,fgetsof C++-tekenreeksen die de grenzen controleren.
Controleer je begrip
Met een stackbufferoverflow kan een aanvaller voorbij het einde van een buffer schrijven. Wat is het belangrijkste doel dat een aanvaller probeert te bereiken door invoer zorgvuldig samen te stellen en daarmee het retouradres te overschrijven?
Herhaling: overflows en shellcode
In deze les hebben we de gevaarlijke wereld van bufferoverflows verkend. We hebben geleerd dat deze ontstaan wanneer er te veel gegevens naar een buffer met een vaste grootte worden geschreven, waardoor aangrenzend geheugen wordt beschadigd.
Cruciaal is dat een aanvaller de besturing over het programma kan overnemen als deze overflow het retouradres op de stack bereikt. Dit gebeurt door shellcode—kleine, schadelijke machinecode—te injecteren en de uitvoering ernaartoe om te leiden, vaak met behulp van een NOP-slede. Ook hebben we belangrijke maatregelen tegengegaan, zoals ASLR, DEP en stack-canaries.
Leer Assembly met een AI-tutor — gratis
Schrijf echte code en voer die uit in je browser, krijg direct hulp van een AI-tutor die 24/7 beschikbaar is en ga verder waar je gebleven bent op het web of in de app.
- Cursussen
- 12
- Lessen
- 48
Veelgestelde vragen
Is de les “Buffer overflows en shellcode” gratis?
Ja — de volledige tekst van “Buffer overflows en shellcode” kun je hier gratis op het web lezen. Als je interactief wilt oefenen met een ingebouwde code-editor en een AI-begeleider die 24/7 beschikbaar is, en de rest van de cursus Assemblytaal en x86-programmeren voor systemen op laag niveau wilt ontgrendelen, kun je upgraden naar CoddyKit PRO. De cursus Assemblytaal en x86-programmeren voor systemen op laag niveau bevat in totaal 4 lessen.
Wat leer ik in “Buffer overflows en shellcode”?
Verken de werking van kwetsbaarheden door buffer overflows en hoe deze kunnen worden misbruikt om kwaadaardige shellcode te injecteren en uit te voeren. Je oefent met Assemblytaal en x86-programmeren voor systemen op laag niveau door code rechtstreeks in de browser uit te voeren. Een AI-begeleider die 24/7 beschikbaar is beantwoordt je vragen terwijl je de les doorwerkt.
Heb ik ervaring nodig om met Assemblytaal en x86-programmeren voor systemen op laag niveau te beginnen?
Ervaring vooraf is niet nodig. Assemblytaal en x86-programmeren voor systemen op laag niveau op CoddyKit is opgebouwd voor beginners tot gevorderden, zodat je hier of bij het begin kunt starten en in je eigen tempo kunt leren. Dit is les 3 van 4.
Hoe lang duurt de les “Buffer overflows en shellcode”?
De meeste lessen van CoddyKit duren ongeveer 5–10 minuten. Elke les is kort en interactief, zodat je gestaag vooruitgaat en op het web en in de app precies verdergaat waar je was gebleven.
Kan ik code schrijven en uitvoeren in deze les over Assemblytaal en x86-programmeren voor systemen op laag niveau?
Ja. Elke les over Assemblytaal en x86-programmeren voor systemen op laag niveau bevat een ingebouwde code-editor, zodat je rechtstreeks in je browser echte code kunt schrijven en uitvoeren en direct feedback van AI krijgt — lokale installatie is niet nodig.
Alle lessen in deze cursus
- Cachecoherentie en prestaties
- Kritieke secties handmatig optimaliseren
- Buffer overflows en shellcode
- Branch prediction en speculatieve uitvoering