Grunnleggende om reverse engineering og binæranalyse · leksjon

Kontrollflyt og funksjonskall

Lær om betingede hopp, løkker og mekanismene bak funksjonskall, inkludert bruk av stakken.

Leksjon 3 av 411 trinn

Kontrollflyt og funksjonskall er en gratis leksjon i Grunnleggende om reverse engineering og binæranalyse på CoddyKit. Dette er leksjon 3 av 4. Du kan lese valgfritt 3 leksjoner fra denne læringsstien gratis i sin helhet – deretter låser CoddyKit PRO opp alle leksjoner, samt praktisk øving med en innebygd kodeeditor og en AI-veileder som er tilgjengelig døgnet rundt. Den er en del av læringsløpet i Grunnleggende om reverse engineering og binæranalyse, og fremdriften din synkroniseres mellom nettet og CoddyKit-appen. Kurset i Grunnleggende om reverse engineering og binæranalyse inneholder totalt 4 leksjoner.

Kontrollflyt: Gjør programmer intelligente

I assembly kjøres instruksjonene vanligvis etter hverandre. Dette kalles sekvensiell kjøring. Men virkelige programmer må kunne ta avgjørelser, gjenta handlinger og kalle funksjoner.

Det er her kontrollflyt kommer inn! Det beskriver hvordan et program endrer kjøringsbanen basert på betingelser, oppretter løkker og kaller subrutiner.

Betingede hopp: If-setninger

Betingede hopp tilsvarer if-setninger i høynivåspråk. De lar programmet kjøre ulike kodeblokker basert på en betingelse.

CMP-instruksjonen sammenligner to verdier og setter CPU-flagg. Deretter kontrollerer hoppinstruksjoner som JE (Jump if Equal) eller JNE (Jump if Not Equal) disse flaggene for å avgjøre om det skal hoppes.

; Example: if (EAX == EBX) goto equal_label;
MOV EAX, 10
MOV EBX, 10
CMP EAX, EBX    ; Compare EAX and EBX
JE  equal_label ; Jump if Equal
; Code here runs if EAX != EBX
JMP end_label

equal_label:
; Code here runs if EAX == EBX

end_label:
; Program continues

Flere hoppbetingelser

I tillegg til JE og JNE finnes det mange andre betingede hoppinstruksjoner for å håndtere ulike sammenligninger:

  • JG: Hopp hvis større
  • JL: Hopp hvis mindre
  • JGE: Hopp hvis større enn eller lik
  • JLE: Hopp hvis mindre enn eller lik
  • JZ: Hopp hvis null (brukes ofte etter CMP eller aritmetikk)
  • JNZ: Hopp hvis ikke null

Disse instruksjonene tolker CPU-ens flaggregister, som lagrer resultatene av tidligere operasjoner.

Bygge løkker i assembly

Du kan opprette løkker ved hjelp av betingede hopp. En løkke består vanligvis av:

  1. En initialisering (for eksempel å sette en teller).
  2. En betingelseskontroll (ved hjelp av CMP og et betinget hopp).
  3. Løkkekroppen (instruksjoner som skal gjentas).
  4. En oppdatering (for eksempel å øke telleren).
  5. Et ubetinget hopp tilbake til betingelseskontrollen.
; Example: int i = 0; while (i < 3) { i++; }
MOV ECX, 0      ; Initialize counter i = 0

loop_start:
CMP ECX, 3      ; Compare i with 3
JGE loop_end    ; Jump if i >= 3 (exit loop)

INC ECX         ; Increment i
JMP loop_start  ; Jump back to loop_start

loop_end:
; Loop has finished, continue here

Stakken: LIFO-lagring

Stakken er et viktig minneområde som brukes til midlertidig lagring, særlig under funksjonskall. Den følger LIFO-prinsippet (Last-In, First-Out).

Tenk på den som en stabel med tallerkener: Du kan bare legge en ny tallerken øverst (PUSH) eller fjerne den øverste tallerkenen (POP).

  • PUSH: Reduserer stakkpekeren (ESP/RSP) og legger data på stakken.
  • POP: Henter data fra toppen av stakken og øker stakkpekeren.

Funksjonskall: CALL og RET

Når et program må kjøre en separat kodeblokk (en funksjon eller subrutine), bruker det CALL-instruksjonen. Dette er grunnleggende for modulær programmering.

  • CALL-instruksjonen legger først returadressen (adressen til instruksjonen rett etter CALL) på stakken.
  • Deretter hopper den ubetinget til målfunksjonens startpunkt.
  • RET-instruksjonen, som vanligvis finnes på slutten av en funksjon, henter returadressen fra stakken og hopper tilbake til denne adressen. Dermed fortsetter kjøringen i den kallende funksjonen.
; Caller code:
; ... instructions
CALL my_function ; Calls the function
; ... execution continues here after my_function returns

; my_function definition:
my_function:
; ... function's body instructions
RET              ; Returns to the caller

Sende argumenter til funksjoner

Hvordan mottar funksjoner inndata? I x86/x64-assembler sendes argumenter ofte via stacken eller registre.

Når stacken brukes, blir argumentene lagt på stacken av den kallende funksjonen før CALL-instruksjonen. Den kalte funksjonen får deretter tilgang til disse argumentene relativt til stackpekeren (ESP/RSP) eller basepekeren (EBP/RBP).

Kallekonvensjonen bestemmer rekkefølgen og metoden for overføring av argumenter.

Lokale variabler og stackrammen

Funksjoner trenger også plass til sine egne lokale variabler. Denne plassen allokeres på stacken i det som kalles en stackramme.

En stackramme opprettes vanligvis ved å:

  1. Lagre den gamle basepekeren (PUSH EBP/RBP).
  2. Angi den nye basepekeren til den gjeldende stackpekeren (MOV EBP, ESP/RBP, RSP).
  3. Allokere plass til lokale variabler (SUB ESP, size).

Basepekeren (EBP/RBP) gir et stabilt referansepunkt for tilgang til argumenter og lokale variabler i den gjeldende funksjonen.

Gjennomgang av et funksjonskall

La oss se på en enkel C-funksjon og forstå hvordan kallet, argumentene og de lokale variablene henger sammen med assembler og stacken.

Når main kaller calculate_sum, legges argumentene 15 og 25 på stacken. Inne i calculate_sum allokeres det plass til local_var på stacken. Funksjonens returverdi plasseres vanligvis i et register som EAX.

#include <stdio.h>

int calculate_sum(int a, int b) {
  int local_var = a + b; // Local variable on stack
  return local_var;
}

int main() {
  int result = calculate_sum(15, 25);
  printf("Result: %d\n", result);
  return 0;
}

Hurtigsjekk: Funksjonskall

Det er avgjørende å forstå stackens rolle i funksjonskall når man arbeider med reverse engineering.

Hvilke av de følgende handlingene utføres når en x86/x64 CALL-instruksjon kjøres?

Oppsummering: Kontrollflyt og funksjoner

Godt jobbet! De har lært hvordan programmer tar beslutninger og kjører funksjoner i assembler.

  • Betingede hopp (JE, JNE, JG osv.) kombinert med CMP gjør det mulig å implementere if-setninger og løkker.
  • Stacken er en LIFO-struktur som er avgjørende for midlertidige data, og som håndteres med PUSH og POP.
  • Funksjonskall bruker CALL til å legge returadressen på stacken og hoppe, og RET til å hente den ut og returnere.
  • Argumenter og lokale variabler håndteres ofte via stacken i en funksjons stackramme.

Det er svært viktig å forstå disse konseptene for å kunne følge programkjøring og analysere binærfiler!

Gratis å komme i gang

Lær deg Assembly med en AI-veileder – gratis

Skriv og kjør ekte kode i nettleseren, få umiddelbar hjelp fra en AI-veileder som er tilgjengelig døgnet rundt, og fortsett der du slapp – på nettet eller i appen.

Kurs
12
Leksjoner
48

Ofte stilte spørsmål

Er leksjonen «Kontrollflyt og funksjonskall» gratis?

Ja – du kan lese valgfritt 3 av leksjonene i læringsstien Grunnleggende om reverse engineering og binæranalyse, inkludert «Kontrollflyt og funksjonskall», gratis i sin helhet her på nettet. Deretter låser CoddyKit PRO opp alle leksjoner, samt interaktiv øving med en innebygd kodeeditor og en AI-veileder som er tilgjengelig døgnet rundt. Kurset i Grunnleggende om reverse engineering og binæranalyse inneholder totalt 4 leksjoner.

Hva lærer jeg i «Kontrollflyt og funksjonskall»?

Lær om betingede hopp, løkker og mekanismene bak funksjonskall, inkludert bruk av stakken. Du øver på Grunnleggende om reverse engineering og binæranalyse med praktisk kode som du kjører direkte i nettleseren, mens en AI-veileder som er tilgjengelig døgnet rundt, svarer på spørsmålene dine mens du jobber deg gjennom leksjonen.

Trenger jeg erfaring for å begynne med Grunnleggende om reverse engineering og binæranalyse?

Ingen tidligere erfaring er nødvendig. Grunnleggende om reverse engineering og binæranalyse på CoddyKit er lagt opp for både nybegynnere og viderekomne, så De kan begynne her eller helt fra start og lære i Deres eget tempo. Dette er leksjon 3 av 4.

Hvor lang tid tar leksjonen «Kontrollflyt og funksjonskall»?

De fleste CoddyKit-leksjoner tar omtrent 5–10 minutter. Hver leksjon er kort og interaktiv, slik at De gjør jevne fremskritt og kan fortsette akkurat der De slapp – både på nettet og i appen.

Kan jeg skrive og kjøre kode i denne Grunnleggende om reverse engineering og binæranalyse-leksjonen?

Ja. Alle Grunnleggende om reverse engineering og binæranalyse-leksjoner har en innebygd kodeeditor, slik at De kan skrive og kjøre ekte kode direkte i nettleseren og få umiddelbar tilbakemelding fra AI – uten lokal konfigurering.

Alle leksjonene i dette kurset

  1. Grunnleggende x86/x64-assembly
  2. Registre og minneoperasjoner
  3. Kontrollflyt og funksjonskall
  4. Stakken og kallkonvensjoner
← Tilbake til Grunnleggende om reverse engineering og binæranalyse