Assembler och lågnivåprogrammering för x86-system · Lektion

Buffertspill och shellcode

Utforska hur sårbarheter med buffertspill fungerar och hur de kan utnyttjas för att injicera och köra skadlig shellcode.

Lektion 3 av 412 steg

Buffertspill och shellcode är en gratis lektion i Assembler och lågnivåprogrammering för x86-system på CoddyKit. Detta är lektion 3 av 4. Ni kan läsa hela lektionen gratis nedan och sedan öva praktiskt i webbläsaren med en inbyggd kodredigerare och en AI-handledare som är tillgänglig dygnet runt. Den ingår i lärvägen för Assembler och lågnivåprogrammering för x86-system, och Era framsteg synkroniseras mellan webben och CoddyKit-appen. Kursen i Assembler och lågnivåprogrammering för x86-system innehåller totalt 4 lektioner.

Introduktion: buffertspill

Välkommen till ett viktigt ämne inom säkerhet på låg nivå: buffertspill. Detta är en typ av sårbarhet i programvara som kan göra det möjligt för angripare att ta kontroll över ett program.

Ett buffertspill uppstår när ett program försöker skriva mer data i en minnesbuffert med fast storlek än den är avsedd att rymma. Överskottet 'spiller över' till angränsande minnesområden.

Vad är en buffert?

Inom programmering, särskilt i språk som C eller assembler, är en buffert helt enkelt ett minnesblock som reserverats för lagring av data. Tänk på den som en behållare med en bestämd kapacitet.

  • Buffertar används ofta för tillfällig lagring, till exempel för att lagra användarinmatning eller nätverksdata.
  • De kan deklareras som arrayer av tecken (strängar) eller andra datatyper.
  • Exempelvis deklarerar char username[32]; en buffert som kan innehålla upp till 31 tecken plus en nullterminator.

Kod: en sårbar buffert

Vi ska titta på ett enkelt C-program med en avsiktlig sårbarhet för buffertspill. Var särskilt uppmärksam på funktionen strcpy.

strcpy kopierar en sträng från källan till målet, men kontrollerar inte storleken på målbuffer­ten. Detta är en vanlig orsak till buffertspill.

/* 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;
}

Stackramen

För att förstå hur buffertspill kan utnyttjas behöver vi gå tillbaka till anropsstacken. När en funktion anropas skapas en ny stackram.

Denna stackram innehåller vanligtvis:

  • Lokala variabler för funktionen.
  • Den sparade baspekaren (EBP/RBP).
  • Framför allt: returadressen, som talar om för CPU:n var exekveringen ska återupptas när funktionen är klar.

Skriva över returadressen

När ett buffertspill inträffar på stacken skadas inte bara angränsande lokala variabler av överskottsdatan. Om tillräckligt mycket data skickas kan den skriva över det sparade EBP och därefter själva returadressen.

Genom att ändra returadressen kan en angripare lura programmet att hoppa till en godtycklig minnesadress i stället för att återvända till den legitima anroparen. Detta är den centrala mekanismen bakom många buffertspillsexploater.

Introduktion till shellcode

Vart vill angriparen att programmet ska hoppa? Vanligtvis till en koddel som angriparen kontrollerar och som kallas shellcode.

  • Shellcode är en liten, självständig del maskinkod.
  • Det främsta syftet är ofta att starta ett 'skal' (en kommandotolk) på målsystemet.
  • Den kan även utföra andra skadliga åtgärder, till exempel skapa nya användare, hämta filer eller ansluta till en fjärrserver.

Enkel shellcodes uppbyggnad

Shellcode skrivs vanligtvis i assembler för att bli så kompakt och effektiv som möjligt. Den undviker nullbyte (\x00) eftersom många strängfunktioner slutar kopiera vid det första nullbytet.

Ett vanligt mål är att anropa systemanropet execve (i Linux) för att starta /bin/sh.

; 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)

Injicera shellcode

Hur kommer shellcode in i programmet? Angriparen inkluderar den som en del av den skadliga indata som orsakar buffertspill.

När bufferten svämmar över skrivs shellcode in i programmets minne, vanligtvis på stacken tillsammans med den överskrivna returadressen.

Exploitens uppbyggnad: NOP-släde

Angripare använder ofta en NOP-släde (No Operation-släde) för att öka tillförlitligheten hos sin exploit.

  • En NOP-släde är en sekvens av instruktioner av typen 'No Operation' (NOP), till exempel \x90 i x86.
  • Om angriparen skriver över returadressen så att den pekar någonstans i NOP-släden kör CPU:n helt enkelt NOP-instruktionerna tills den 'glider' in i den faktiska shellcoden.
  • Detta kompenserar för mindre felaktigheter i uppskattningen av shellcodens exakta minnesadress.

Skydd och motåtgärder

Operativsystem och kompilatorer har utvecklat flera skydd mot buffertspill:

  • ASLR (Address Space Layout Randomization): Slumpar minnesadresser för att göra det svårare att gissa returadressen eller shellcodens plats.
  • DEP/NX-bit (Data Execution Prevention/No-Execute): Märker minnesområden (som stacken) som icke-exekverbara och hindrar shellcode från att köras där.
  • Stack canaries: Slumpvärden som genereras av kompilatorn och placeras på stacken; om de skrivs över upptäcker programmet manipuleringen och avbryts.
  • Säkra funktioner: Använd funktioner som strncpy, snprintf, fgets eller C++-strängar som kontrollerar gränser.

Kontrollera Era kunskaper

Ett buffertspill på stacken gör det möjligt för en angripare att skriva förbi slutet av en buffert. Vad är det primära målet som en angripare försöker uppnå genom att noggrant utforma indata så att returadressen skrivs över?

Repetition: buffertspill och shellcode

I den här lektionen utforskade vi den farliga världen med buffertspill. Vi lärde oss att de uppstår när för mycket data skrivs till en buffert med fast storlek och skadar närliggande minne.

Om spillningen når returadressen på stacken kan en angripare ta över programmets kontrollflöde. Det gör angriparen genom att injicera shellcode – liten, skadlig maskinkod – och omdirigera exekveringen till den, ofta med hjälp av en NOP-släde. Vi berörde också viktiga skyddstekniker som ASLR, DEP och stackkanariefåglar.

Gratis att börja

Lär dig Assembly med en AI-lärare – gratis

Skriv och kör riktig kod i webbläsaren, få omedelbar hjälp av en AI-lärare dygnet runt och fortsätt där du slutade – på webben eller i appen.

Kurser
12
Lektioner
48

Vanliga frågor

Är lektionen ”Buffertspill och shellcode” gratis?

Ja – hela texten till ”Buffertspill och shellcode” kan läsas gratis här på webben. Om Ni vill öva interaktivt med en inbyggd kodredigerare och en AI-handledare som är tillgänglig dygnet runt och låsa upp resten av kursen i Assembler och lågnivåprogrammering för x86-system, kan Ni uppgradera till CoddyKit PRO. Kursen i Assembler och lågnivåprogrammering för x86-system innehåller totalt 4 lektioner.

Vad lär jag mig i ”Buffertspill och shellcode”?

Utforska hur sårbarheter med buffertspill fungerar och hur de kan utnyttjas för att injicera och köra skadlig shellcode. Ni övar på Assembler och lågnivåprogrammering för x86-system med praktisk kod som körs direkt i webbläsaren, medan en AI-handledare som är tillgänglig dygnet runt svarar på Era frågor under lektionen.

Behöver jag någon erfarenhet för att börja lära mig Assembler och lågnivåprogrammering för x86-system?

Du behöver inga förkunskaper. Utbildningen i Assembler och lågnivåprogrammering för x86-system på CoddyKit är upplagd för allt från nybörjare till avancerade elever, så att du kan börja här eller från början och gå fram i din egen takt. Detta är lektion 3 av 4.

Hur lång tid tar lektionen ”Buffertspill och shellcode”?

De flesta CoddyKit-lektioner tar cirka 5–10 minuter. Varje lektion är kort och interaktiv, så att du gör stadiga framsteg och kan fortsätta precis där du slutade – på webben eller i appen.

Kan jag skriva och köra kod i den här Assembler och lågnivåprogrammering för x86-system-lektionen?

Ja. Varje Assembler och lågnivåprogrammering för x86-system-lektion innehåller en inbyggd kodredigerare, så att du kan skriva och köra riktig kod direkt i webbläsaren och få omedelbar AI-feedback – utan lokal installation.

Alla lektioner i den här kursen

  1. Cachekoherens och prestanda
  2. Handoptimera kritiska kodavsnitt
  3. Buffertspill och shellcode
  4. Grenförutsägelse och spekulativ exekvering
← Tillbaka till Assembler och lågnivåprogrammering för x86-system