Cover
Jetzt kostenlos starten 7_AssemblyContinued.pdf
Summary
# Introductie tot de PREMA-cursus en les 7
Dit document introduceert de Practical Reverse Engineering and Malware Analysis (PREMA) cursus en specificeert dat les 7 zich richt op assembly en geavanceerde statische analyse, met een focus op het bestand `Code42.exe`.
### 1.1 Overzicht van de PREMA-cursus en les 7
De Practical Reverse Engineering and Malware Analysis (PREMA) cursus behandelt reverse engineering en malware analyse. Les 7 van deze cursus richt zich specifiek op assembly-taal en geavanceerde technieken voor statische analyse. Een essentieel onderdeel van deze les is de analyse van het bestand `Code42.exe` [1](#page=1) [2](#page=2).
### 1.2 De focus op `Code42.exe` in les 7
Les 7 van de PREMA-cursus maakt gebruik van het bestand `Code42.exe` om de behandelde concepten te illustreren. Dit bestand wordt gepresenteerd als een voorbeeld van "essentiële delen van de broncode" wat impliceert dat studenten zullen worden aangemoedigd om de structuur en functionaliteit ervan te onderzoeken via statische analyse en assembly-interpretatie [1](#page=1) [2](#page=2) [5](#page=5).
> **Tip:** Begrijpen hoe specifieke bestanden zoals `Code42.exe` worden gebruikt in de lesstof, helpt bij het toepassen van de theoretische concepten van statische analyse en assembly-taal in een praktische context [2](#page=2) [5](#page=5).
---
# Praktische voorbeelden: Code42.exe
Dit gedeelte behandelt het analyseren van het programma Code42.exe, met de focus op het ontgrendelen van de code door middel van statische analyse van assemblyinstructies of door de code te patchen [2](#page=2).
### 2.1 Achtergrond en doel
Het programma Code42.exe lijkt een wachtwoord als argument te accepteren. Het doel is om de code te ontgrendelen door het juiste vergelijkings- en sprongcommando (zoals `cmp` en `je`/`jz`) te identificeren. Dit kan worden bereikt door de assemblyinstructies te lezen en het programma te begrijpen, of door de code te patchen om het gedrag van het programma te veranderen [3](#page=3) [4](#page=4).
### 2.2 Methoden om de code te ontgrendelen
Er worden twee hoofmethoden voorgesteld om de code te ontgrendelen:
#### 2.2.1 Statische analyse van assemblyinstructies
Deze methode omvat het lezen en begrijpen van de assemblyinstructies van het programma. Het is de meest interessante methode omdat hiermee de correcte "code" ontdekt kan worden. Essentiële onderdelen van de broncode worden gepresenteerd om te helpen bij deze analyse [4](#page=4) [5](#page=5).
#### 2.2.2 Patchen van de code
Bij deze methode wordt de code van het programma aangepast om het gedrag ervan te veranderen. Hoewel dit kan leiden tot het zien van het ontgrendelde printstatement, zal de correcte code hierbij niet bekend worden [4](#page=4).
### 2.3 Verwijzingen en instructies
Voor een dieper begrip van de assemblyinstructies, specifiek mnemomics en opcodes, wordt verwezen naar de Intel 64 en IA-32 Architectures Software Developer's Manual. Specifieke voorbeelden van instructies en hun opcodes zijn [6](#page=6):
* `JZ rel8` – `74 cb` [6](#page=6).
* `JNZ rel8` – `75 cb` [6](#page=6).
> **Tip:** Het is essentieel om de documentatie van de processorarchitectuur te raadplegen voor een gedetailleerde uitleg van assembly-instructies en hun bijbehorende opcodes.
> **Voorbeeld:** Wanneer we de `JZ` (Jump if Zero) instructie tegenkomen, weten we dat deze wordt uitgevoerd met de opcode `74 cb` en dat deze een relatieve sprong (rel8) van 8 bits gebruikt. Dit betekent dat de sprongafstand beperkt is [6](#page=6).
---
# Praktische voorbeelden: Bomb.exe
Deze sectie behandelt de statische analyse van het programma `Bomb.exe` met behulp van IDA, met een focus op het identificeren van strings, PE-headers, en het ontleden van codestromen aan de hand van vergelijkingen en sprongen [7](#page=7).
### 3.1 Statische analyse met IDA
De analyse begint met het verkennen van de basisstatische elementen van `Bomb.exe` [8](#page=8).
#### 3.1.1 Identificatie van strings en PE-headers
Belangrijke strings die in het programma worden gevonden, zijn onder andere "BOOM! BOOM! You failed!:(" en "You saved the day! Great Job!!!". Deze kunnen indicaties geven van de functionaliteit van het programma, zoals faal- of succesberichten [8](#page=8).
De PE-headers bevatten cruciale informatie zoals de "Image Base" en het "Address of Entry Point" (0000117D). Deze gegevens zijn essentieel voor het begrijpen van de geheugenlay-out en het startpunt van de executie van het programma [8](#page=8).
#### 3.1.2 Analyseren van codestromen met IDA
Bij het selecteren van aanroepen (calls) in IDA kan men een patroon herkennen waarbij `sub_4010C1` direct na een `push` op een offset van een string wordt aangeroepen. Dit suggereert sterk dat `sub_4010C1` een functie is zoals `Printf` [9](#page=9).
Een belangrijke vergelijking die wordt aangetroffen, is `cmp [ebp+argc, 3`. Deze vergelijking splitst de codestroom [9](#page=9):
* Eén pijl (groen) leidt naar de code die wordt uitgevoerd als er twee getallen worden ingevoerd en het programma vervolgens afsluit [9](#page=9).
* De andere pijl (rood) leidt naar verdere functionaliteit [9](#page=9).
Het is niet direct noodzakelijk om je zorgen te maken over de vlaggen (ZF en CF) op dit punt van de analyse [9](#page=9).
##### 3.1.2.1 De rol van _atol
Recht boven de "correcte" `cmp` instructie, gebaseerd op de strings, bevinden zich twee aanroepen naar `_atol`. De functie `_atol` converteert een string naar een lange integer (ASCII to long). Het is dus een "string naar getal" conversiefunctie [10](#page=10).
Door de eerste aanroep naar `_atol` te inspecteren, zien we `push ecx`. Om te begrijpen wat `ecx` bevat, analyseren we `mov [ecx, eax+8]`. Verderop vinden we `mov eax, [ebp+argv]`. Dit betekent dat `eax` de command-line argumenten bevat. Het is hierbij belangrijk op te merken dat `argv ` de programmanaam is, `argv ` zich op `[eax+4]` bevindt, en `argv ` op `[eax+8]`. Dit impliceert dat het tweede argument eerst wordt verwerkt [10](#page=10) [1](#page=1) [2](#page=2).
##### 3.1.2.2 Analyse van sub_401000
Een andere significante aanroep is `call sub_401000`. Het resultaat van deze sub-routine wordt opgeslagen in `eax`. Direct daarna volgt een vergelijking (`cmp`) met 0, gevolgd door een voorwaardelijke sprong `jge` (jump greater or equal) [11](#page=11).
* Een sprong hiernaartoe leidt tot de "BOOM!" (falen) [11](#page=11).
* Om dit te vermijden, willen we dat de sprong *niet* wordt genomen, wat betekent dat de voorwaarde "less" (kleiner dan) moet zijn [11](#page=11).
Deze sub-routine is waarschijnlijk de functie die de getallen vergelijkt. Het is raadzaam om deze subroutine te hernoemen voor betere leesbaarheid [11](#page=11).
#### 3.1.3 Het ontleden van sub_401000
Wanneer we `sub_401000` verder analyseren, zien we dat deze twee argumenten accepteert: `arg_0` en `arg_4`. Variabelen `var_8` en `var_4` worden gedeclareerd. `var_4` lijkt de retourwaarde te zijn [12](#page=12).
* Aan het begin wordt `var_4` op 0 gezet, en dit is de retourwaarde [12](#page=12).
* IDA kan `var_4` als een unsigned integer weergeven, maar het is feitelijk -1 [12](#page=12).
* Om het gewenste pad te bewandelen, willen we een retourwaarde van -1, en *niet* 0 [12](#page=12).
Er zijn dus twee mogelijke paden [12](#page=12).
##### 3.1.3.1 Pad 1: Correcte invoer
In `sub_401000` wordt `var_4` (de retourwaarde) op 0 gezet en niet veel gebruikt. `var_8` heeft de waarde 8 [13](#page=13).
Het eerste argument (`Argument1`) wordt in `eax` geplaatst en vergeleken met een globaal gedefinieerd dword van waarde 12 (hexadecimaal `0Ch`). Dit dword kan hernoemd worden naar "number12" [13](#page=13).
* Als `Argument1` gelijk is aan 12, wordt het tweede argument vergeleken met 11 (hexadecimaal `0Bh`) [13](#page=13).
* Als deze vergelijking correct is, wordt er direct gesprongen naar een retourwaarde van -1, wat aangeeft dat een pad is gevonden. Dit pad vereist dus de invoer van de argumenten 12 en 11 [13](#page=13).
##### 3.1.3.2 Pad 2: Alternatieve correcte invoer
Er bestaat ook een ander pad binnen `sub_401000`. Als `Argument1` niet 12 is, of `Argument2` niet 11, dan wordt er gesprongen naar een ander blok dat `Argument1` vergelijkt met 13 (hexadecimaal `0Dh`) [14](#page=14).
* Vervolgens wordt `jle` gebruikt om naar de exit met retourwaarde 0 te gaan. Dit is het "niet goede" pad, wat betekent dat we een sprong moeten vermijden die groter is dan [14](#page=14).
* Hierna wordt het tweede argument (`Argument2`) vergeleken met `var_8` (met de waarde 8) [14](#page=14).
* De sprong `jge` (jump greater or equal) leidt wederom naar het "niet goede" pad. Dit impliceert dat het tweede argument *minder* moet zijn dan 8 om het juiste pad te volgen [14](#page=14).
Samenvattend vereist dit tweede pad dat het eerste argument groter is dan 13 en het tweede argument kleiner is dan 8 [14](#page=14).
---
# Oefeningen en extra samples
Dit gedeelte bevat een overzicht van oefeningen en extra samples die beschikbaar zijn voor verdere studie en voorbereiding op examens.
### 4.1 Lab oefeningen
De lab oefeningen voor vandaag omvatten een "Leho quiz" gericht op basis assembly oefeningen [16](#page=16).
### 4.2 Extra samples
Er zijn twee extra samples beschikbaar voor studie:
#### 4.2.1 Spy.exe
* **MD5:** c7b2866df97472695669a5d6def6c021 [16](#page=16).
* Dit sample is representatief en kan voorkomen op het examen [16](#page=16).
#### 4.2.2 SameGame.exe
* **MD5:** 6aa7a9e95b196e0ddd111442c8baed50 [16](#page=16).
* Dit is malware en vereist voorzichtigheid [16](#page=16).
* Het ZIP wachtwoord voor dit sample is "This.Is.Malware" [16](#page=16).
* **Let op:** Wees uiterst voorzichtig bij het omgaan met dit sample [16](#page=16).
---
## Veelgemaakte fouten om te vermijden
- Bestudeer alle onderwerpen grondig voor examens
- Let op formules en belangrijke definities
- Oefen met de voorbeelden in elke sectie
- Memoriseer niet zonder de onderliggende concepten te begrijpen
Glossary
| Term | Definition |
|------|------------|
| Statische analyse | Een methode voor het analyseren van software of code zonder deze uit te voeren. Het omvat het onderzoeken van de structuur en instructies van het programma om het gedrag te begrijpen. |
| Dynamische analyse | Een methode voor het analyseren van software of code door deze uit te voeren en het gedrag ervan te observeren, vaak in een gecontroleerde omgeving zoals een debugger. |
| Assembly | Een laag niveau programmeertaal die nauw verwant is aan machinecode. Het gebruikt mnemonics om machine-instructies te vertegenwoordigen en is essentieel voor reverse engineering. |
| Patching | Het proces van het wijzigen van de uitvoerbare code van een programma om het gedrag ervan te veranderen. Dit kan worden gedaan om functies te omzeilen, beveiligingen te doorbreken of fouten te corrigeren. |
| PE Headers | Een structuur aan het begin van een draagbaar uitvoerbaar (PE) bestand dat informatie bevat over het bestand, zoals de afbeeldingbasis, de entry point, secties en andere metagegevens die nodig zijn voor het besturingssysteem. |
| Entry Point | Het adres in de code waar de uitvoering van een programma begint wanneer het wordt geladen. |
| Debugger | Een programma dat wordt gebruikt om de uitvoering van een ander programma te controleren en te inspecteren. Het stelt ontwikkelaars in staat om stap voor stap door code te gaan, variabelen te bekijken en fouten op te sporen. |
| Mnemonics | Korte, gemakkelijk te onthouden afkortingen die machine-instructies vertegenwoordigen in assemblytaal, zoals "MOV" voor verplaatsing of "ADD" voor optelling. |
| `cmp` instructie | De "compare" instructie in assembly. Deze instructie vergelijkt twee operanden en stelt de vlaggen (zoals Zero Flag en Carry Flag) in op basis van het resultaat van de vergelijking, wat wordt gebruikt voor voorwaardelijke sprongen. |
| `je` / `jz` instructie | De "jump if equal" of "jump if zero" instructie. Deze instructie voert een sprong uit naar een ander deel van de code als de Zero Flag is ingesteld, wat aangeeft dat het resultaat van de vorige `cmp` instructie nul was (of dat de twee vergelijken operanden gelijk waren). |
| `jle` instructie | De "jump if less than or equal" instructie. Deze instructie voert een sprong uit als het resultaat van de vorige `cmp` instructie aangeeft dat de eerste operand kleiner is dan of gelijk is aan de tweede operand. |
| `jge` instructie | De "jump if greater than or equal" instructie. Deze instructie voert een sprong uit als het resultaat van de vorige `cmp` instructie aangeeft dat de eerste operand groter is dan of gelijk is aan de tweede operand. |
| `_atol` functie | Een functie die een ASCII-string omzet naar een lange integer (`long`). Het is een veelgebruikte functie om numerieke invoer van gebruikers te verwerken. |
| `argv` | Een array van strings die de command-line argumenten vertegenwoordigen die aan een programma zijn doorgegeven. `argv[0]` is doorgaans de naam van het programma zelf. |
| `argc` | Een integer die het aantal command-line argumenten vertegenwoordigt dat aan een programma is doorgegeven, inclusief de programmanaam. |
| `subroutine` | Een deel van een programma dat een specifieke taak uitvoert. Het kan vanuit verschillende delen van het hoofdprogramma worden aangeroepen en retourneert de controle na voltooiing. |
| Zero Flag (ZF) | Een processor vlag die wordt ingesteld als het resultaat van een rekenkundige of logische operatie nul is. Het wordt gebruikt door voorwaardelijke spronginstructies. |
| Carry Flag (CF) | Een processor vlag die wordt ingesteld als er een "carry out" plaatsvindt van het meest significante bit tijdens een rekenkundige operatie, of als er een "borrow" optreedt. Het wordt gebruikt voor unsigned rekenkunde en voorwaardelijke sprongen. |