Linkittäminen C-kirjastoon
Linkittäminen C-kirjastoon
Assemblyn alusta loppuun tekeminen on opettavaista mutta hidasta. printf, malloc, fopen: kaikki on jo kirjoitettu kerran libc:ssä, miksi tehdä uudestaan?
Voit kutsua libc:n funktioita NASM:sta yksinkertaisesti merkitsemällä ne extern-symboleiksi ja linkittämällä gcc:lla, joka osaa lisätä libc:n automaattisesti:
1extern printf
2extern fflush
3extern exit
4
5section .data
6fmt: db "Lippu: %s", 10, 0
7flag: db "HAKA{...}", 0
8
9section .text
10global _start
11
12_start:
13 lea rdi, [rel fmt]
14 lea rsi, [rel flag]
15 xor eax, eax ; vector-arg-määrä: 0
16 call printf
17 xor rdi, rdi
18 call exit ; flushaa stdoutingcc -no-pie -nostartfiles greet.o -o greet linkittää libc:n mutta ei lisää crt1.o:n startupia (koska määrittelemme oman _start:n).
Pinon linjaus: ABI:n vaatimus
SysV AMD64 -kutsutapa (calling convention) sanoo: call-käskyn hetkellä RSP:n täytyy olla 16-tavuun kohdistettu (RSP % 16 == 0). Tämä ei ole NASM:n vaatimus, eikä CPU:n; se on kutsuttavan funktion oletus.
Mikä menee pieleen jos ei linjaa? glibc:n printf käyttää MOVAPS-käskyä, joka VAATII 16-tavun linjauksen ja kaatuu Segmentation fault jos saa väärän osoitteen.
Linjaus-aritmetiikka:
| Vaihe | Mitä tekee RSP:lle |
|---|---|
kernel käynnistää _start:n | RSP % 16 == 0 |
call printf pushaa 8 tavua | printf:n entry: RSP % 16 == 8 (VÄÄRIN) |
Korjaus: lisää sub rsp, 8 ennen kuin kutsut printf:ää. call:n pushin jälkeen RSP % 16 == 0: printf onnellinen.
Vaihtoehto: kirjoita main, anna libc hoitaa loput
1global main
2extern printf
3main:
4 push rbp
5 mov rbp, rsp
6 ; ... call printf ...
7 leave
8 retKäännä ilman -nostartfiles-lippua: gcc greet.o -o greet. crt1.o linjaa pinon valmiiksi ennen kuin main kutsutaan, eikä tarvitse käsittellä linjausta itse.
Hakkeroinnin oppiminen alkaa tästä
Sadat interaktiiviset kurssit, virtuaalilabrat ja CTF-haasteet selaimessasi. Aloita ilmainen kokeilu ilman korttitietoja.