x86 Arkitektur
Malware udnytter ofte systemers designprincipper. For at forstå hvordan malware fungerer, er det essentielt at kende arkitekturen i de systemer, de kører på.
CPU-Arkitektur
Von Neumann Arkitekturen
Den mest anvendte CPU-arkitektur er afledt af Von Neumann-arkitekturen.
CPU-komponenter
Control Unit (Kontrolenhed) - Henter instruktioner fra hovedhukommelsen
-
Adressen til næste instruktion gemmes i et register kaldet Instruction Pointer (IP)
-
I 32-bit systemer: EIP (Extended Instruction Pointer)
-
I 64-bit systemer: RIP (Register Instruction Pointer)
Arithmetic Logic Unit (ALU) - Udfører de instruktioner, der hentes fra hukommelsen - Resultaterne gemmes i enten registre eller hukommelsen
Registre - CPU'ens lager
-
Meget mindre end hovedhukommelsen
-
Hjælper med at spare tid ved at CPU'en har direkte adgang til data'en
Hukommelse (Memory) - Også kaldet Main Memory eller RAM
-
Indeholder al kode og data for et program
-
Når et program udføres, indlæses dets kode og data i hukommelsen
CPU-Registre
Instruction Pointer
-
Indeholder adressen til næste instruktion, der skal udføres
-
Også kaldet Program Counter
-
16-bit (IP) → 32-bit (EIP) → 64-bit (RIP)
General Purpose Registers (Generelle Registre)
EAX/RAX (Accumulator Register) - Resultater af aritmetiske operationer gemmes ofte her
-
32-bit: EAX
-
64-bit: RAX
-
Kan også adresseres som: AX (16-bit)
EBX/RBX (Base Register) - Bruges ofte til at gemme base adressen for referencering af offset
- Samme adresseringsmuligheder: RBX, EBX, BX, BH, BL
ECX/RCX (Counter Register) - Bruges ofte i tælleoperationer som loops
- Samme adresseringsmuligheder: RCX, ECX, CX, CH, CL
EDX/RDX (Data Register) - Bruges ofte i multiplikation/divisions-operationer
- Samme adresseringsmuligheder: RDX, EDX, DX, DH, DL
ESP/RSP (Stack Pointer) - Peger på toppen af stacken
-
Bruges sammen med Stack Segment registeret
-
32-bit: ESP | 64-bit: RSP
EBP/RBP (Base Pointer) - Bruges til at tilgå parametre passed via stacken
-
Bruges sammen med Stack Segment registeret
-
32-bit: EBP | 64-bit: RBP
ESI/RSI (Source Index Register) - Bruges til string-operationer
-
Bruges med Data Segment (DS) registeret som offset
-
32-bit: ESI | 64-bit: RSI
EDI/RDI (Destination Index Register) - Bruges også til string-operationer
- 32-bit: EDI | 64-bit: RDI
Status Flag Registers
EFLAGS/RFLAGS
-
32-bit register (EFLAGS) i 32-bit systemer
-
64-bit register (RFLAGS) i 64-bit systemer
-
Består af individuelle single-bit flags (1 eller 0)
Zero Flag (ZF) - Indikerer når resultatet af sidste instruktion var nul
- Eksempel: RAX - RAX = 0, så ZF = 1
Carry Flag (CF) - Indikerer når resultatet er for stort eller for lille til destinationen
- Eksempel: 0xFFFFFFFF + 0x00000001 i et 32-bit register → CF = 1
Sign Flag (SF) - Indikerer om resultatet er negativt eller MSB (mest signifikante bit) er sat til 1
- Hvis betingelser opfyldt: SF = 1, ellers SF = 0
Trap Flag (TF) - Indikerer om processoren er i debugging-mode
-
Når TF er sat, udfører CPU'en én instruktion ad gangen
-
Kan bruges af malware til at identificere om de kører i en debugger
Segment Registers
16-bit registre der konverterer flad hukommelse til forskellige segmenter for lettere adressering.
CS (Code Segment) - Peger på kodesektionen i hukommelsen
DS (Data Segment) - Peger på programmets datasektion i hukommelsen
SS (Stack Segment) - Peger på programmets stack i hukommelsen
ES, FS, GS (Extra Segments) - Peger på forskellige datasektioner - Sammen med DS opdeles programmets hukommelse i fire distinkte datasektioner
Hukommelseslayout
Når et program indlæses i hukommelsen i Windows, ser det et abstraheret view af hukommelsen. Programmet har kun adgang til sin egen hukommelse.
Hukommelsessektioner
Code-sektion - Indeholder programmets kode
-
Refererer til text-sektionen i en Portable Executable-fil
-
Indeholder instruktioner udført af CPU'en
-
Har execute-rettigheder
Data-sektion - Indeholder initialiserede data, der ikke er variable
- Ofte globale variabler og data, der ikke skal ændres under programudførelse
Heap - Også kendt som dynamisk hukommelse
-
Indeholder variabler og data oprettet og destrueret under programudførelse
-
Hukommelse allokeres ved runtime og frigives når variablen slettes
Stack - Meget vigtig fra et malwareanalyse-perspektiv
-
Indeholder lokale variabler, argumenter passed til programmet, og returadresse
-
Ofte målrettet af malware for at kapre kontrolflowet
Stack-layout
Stack Karakteristika
-
Last In First Out (LIFO) hukommelse
-
Sidste element pushed på stacken er første til at blive popped ud
Stack-registre
Stack Pointer (ESP/RSP) - Peger på toppen af stacken
- Ændrer position når elementer pushes eller poppes
Base Pointer (EBP/RBP) - Forbliver konstant for et program
- Referenceadresse hvor stacken tracker sine lokale variabler og argumenter
Stack-elementer (fra bund til top)
-
Argumenter (laveste adresse, pushes først)
-
Return Address
-
Old Base Pointer ← Base Pointer (EBP/RBP) peger her
-
Lokale variabler ← Stack Pointer (ESP/RSP) peger her (højeste adresse)
Stack Buffer Overflow
En almindelig teknik til at kapre kontrolflow:
-
Overflow en lokal variabel på stacken
-
Overskriv Return Address med en adresse efter malware-forfatterens valg
Function Prologue
Kode der forbereder stacken når en funktion kaldes:
-
Argumenter pushes på stacken
-
Return Address pushes på stacken
-
Old Base Pointer pushes på stacken
-
Base Pointer ændres til toppen af stacken
Function Epilogue
Kode der rydder op når funktionen afsluttes:
-
Old Base Pointer poppes tilbage til Base Pointer
-
Return Address poppes til Instruction Pointer
-
Stack Pointer omarrangeres til at pege på toppen
Sources
https://tryhackme.com/room/x8664arch
Bemærkning
Noterne er struktureret og rettet med hjælp af LLM'en Claude.