Kako koristiti AFL i AFL++ za učinkovito fuzziranje binarnih datoteka

Zadnje ažuriranje: 28/02/2026
Autor: Isaac
  • Fuzz testiranje automatizira slanje neispravnih ulaza kako bi se otkrili sigurnosni nedostaci u softveru i sustavima.
  • AFL i AFL++ su inteligentni fuzzeri koji koriste instrumentirane kompajlere za vođenje kroz pokrivenost i pronalaženje novih putova izvršavanja.
  • Analiza rušenja sustava alatima poput AFLTriage i GDB omogućuje vam procjenu iskoristivosti ranjivosti poput Integer Underflow.
  • Integriranje fuzzinga u razvojni ciklus poboljšava robusnost, pomaže u ispunjavanju sigurnosnih standarda i smanjuje rizik od kritičnih incidenata.

Fuzzing s AFL-om u binarnom kodu

Ako vas zanima Binarno orijentirana kibernetička sigurnost i iskorištavanjePrije ili kasnije naići ćete na fuzzing, a posebno na AFL i AFL++. Ne govorimo o teorijskom laboratorijskom alatu, već o nečemu što se svakodnevno koristi za pronalaženje vrlo stvarnih nedostataka u poznatim programima, baš kao što se dogodilo s ranjivostima u... popularne aplikacije poput 7-Zip-a.

U sljedećim redcima ćemo detaljno i prijateljskim tonom vidjeti, Kako koristiti AFL i AFL++ za fuzziranje binarnih datotekaObjasnit ćemo što je točno fuzz testiranje, zašto je toliko moćno u smislu sigurnosti i kako ga integrirati u moderni razvojni tijek rada. Također ćemo ispitati slučaj ranjivosti iz stvarnog svijeta (Integer Underflow koji omogućuje udaljeno izvršavanje koda) i pregledati komplementarne alate kao što su GDB s proširenjima, AFLTriage i operativnim modulima.

Što su AFL/AFL++ i zašto se smatraju pametnim fuzzerima?

AFL alat za fuzz testiranje

AFL (američki Fuzzy Lop) i njegova evolucija AFL++ To su alati otvorenog koda za fuzzing dizajnirani za automatsko testiranje binarnih datoteka, tražeći greške poput prelijevanja, memorijskih pogrešaka ili neočekivanih ponašanja koja dovode do rušenja ili čak iskorištavanja ranjivosti.

Ljepota AFL-a nije samo slanje nasumičnih podataka, već inteligentni fuzzer ili fuzzer vođen pokrivanjemPočevši od jednog ili više valjanih primjera unosa (tzv. test slučajeva), AFL stalno generira varijacije i, zahvaljujući instrumentaciji programa, detektira kada nova mutacija uzrokuje da binarni fajl krene drugačijim putem izvršavanja.

Kako bi se postigla ova instrumentacija, AFL ima vlastite kompajlere, kao što su afl-gcc i afl-g++Oni ubacuju male "kuke" u kod tijekom kompajliranja. Ove kuke obavještavaju AFL da je otkriven određeni ulaz. nove rute u toku programaTo vam omogućuje da se usredotočite na mutacije koje zapravo pružaju dodatnu pokrivenost i da ne gubite vrijeme s podacima koji ništa ne mijenjaju.

Ovaj pristup čini AFL nečim poput "dirb binarnih datoteka": dobro poznatim alatom, jednostavnim za korištenje nakon što shvatite osnovni tok i dovoljno moćnim da otkrijete ozbiljni nedostaci u proizvodnim programimaiako postoje napredniji ili specijalizirani fuzzeri.

Uvod u fuzz testiranje i njegovu ulogu u kibernetičkoj sigurnosti

Fuzz testiranje, ili jednostavno fuzzing, je tehnika automatizirano testiranje sigurnosti i robusnostiIdeja je poslati aplikaciji poplavu neispravnih, nasumičnih ili neobičnih podataka, s ciljem da se vidi hoće li se program pokvariti, srušiti ili se ponašati neočekivano.

Kada je softver podvrgnut fuzzingu, cilj je locirati greške kao što su prelijevanje međuspremnika, neuspjesi validacije ulaza, problemi s upravljanjem memorijom ili uvjeti utrkeMnogi od ovih nedostataka mogu dovesti do proizvoljnog izvršavanja koda, curenja informacija ili uskraćivanja usluge.

U tipičnom tijeku rada, fuzz testiranje slijedi tri jasne faze: prvo se generira skup podataka za testiranje (bilo da je potpuno slučajan, generiran prema određenom formatu ili mutiranjem valjanih ulaza); zatim... izvršava binarnu datoteku koja se testira dok se nadgleda Njegovo ponašanje se prati; i konačno, bilježe se i analiziraju rušenja ili neobična ponašanja kako bi programeri mogli istražiti izvor problema.

Postoje različite strategije fuzzinga. Neki alati se fokusiraju na generacijski neredstvaranje unosa koji poštuju dobro definirani format (na primjer, strukturu datoteke ili mrežni protokol); drugi se temelje na mutacija valjanih ulazaUpravo je to pristup u kojem AFL i AFL++ izvrsno funkcioniraju. Postoje i nasumičniji pristupi te drugi koji se oslanjaju na specifično znanje o testiranom sustavu kako bi se ciljalo na njegove najslabije točke.

U modernoj kibernetičkoj sigurnosti, fuzz testiranje je temeljni saveznik: pomaže u pronalaženju ranjivosti u proaktivno, prije nego što softver krene u produkcijui doprinosi usklađenosti s propisima i standardima kao što je ISO 27001 ili zahtjevima za zaštitu podataka. Nadalje, smanjuje reputacijski rizik koji bi nastao ako bi kritična ranjivost koju je moguće iskoristiti pala u ruke napadača.

Slučaj iz stvarnog svijeta: Ranjivost premalog cjelobrojnog broja i RCE u dekompresoru

Kako bismo razumjeli pravu vrijednost AFL-a i fuzzinga, vrlo je korisno pogledati specifičnu ranjivost na temelju Cjelobrojni podtok unutar vrlo popularnog dekompresora datotekaOvo je greška udaljenog izvršavanja koda (RCE) koja se aktivira prilikom obrade komprimiranih datoteka Zstandardnim algoritmom, s visokim, iako ne maksimalnim, CVSS rezultatom, upravo zato što zahtijeva nešto specifičniji kontekst (na primjer, da se obrađuju određene datoteke).

Do prekoračenja cjelobrojne vrijednosti dolazi kada cjelobrojna varijabla ima dobro definirane donje granice. Koristi se u operacijama oduzimanja sve dok se ne dostigne njegova minimalna vrijednost.Budući da mnogi cjelobrojni tipovi ne dopuštaju negativne vrijednosti, prilikom "padanja ispod", umjesto dobivanja broja ispod nule, dolazi do skoka na maksimalnu moguću vrijednost raspona, zbog načina na koji su ti brojevi interno predstavljeni.

  Potpišite skripte i osigurajte ExecutionPolicy pomoću AppLockera i WDAC-a

Zamislite cjelobrojnu varijablu koja, teoretski, nikada ne bi trebala biti negativna. Ako nastavite oduzimati konstantu dok ne dođete do 0 i nastavite oduzimati, Nećete dobiti -1, -2, itd.Umjesto toga, vrijednost će se invertirati i postati gigantski broj na gornjoj granici dopuštenog raspona. Ova apsurdna brojka, ako se koristi kao indeks ili veličina u memorijskim operacijama, može uzrokovati čitanja ili pisanja izvan predviđenih granica.

Problem postaje kritičan kada se ta cjelobrojna varijabla koja može uzrokovati prelijevanje koristi za za upravljanje međuspremnikom ili za izračunavanje pomakaTipičan pseudo-primjer bi bio korištenje korisnički kontrolirane varijable neizravno kao pomaka u funkciji tipa memcpy, u petlji koja smanjuje konstantu u svakoj iteraciji dok navodno ne dosegne nulu ili nepozitivan broj.

U takvom scenariju, ako početna vrijednost nikada ne uspije "čisto" zadovoljiti izlazni uvjet, podlijevanje će na kraju učiniti broj ogromnim, petlja će nastaviti s izvođenjem i masovno oštećenje pamćenjaTo se prevodi u padove sustava i, uz dovoljno iskorištavanja, mogućnost izvršavanja proizvoljnog koda.

Kako AFL pomaže u lociranju ovih vrsta ranjivosti

Nakon što se shvati koncept cjelobrojnog podlijevanja, postaje jasno zašto su AFL i AFL++ toliko korisni: počevši od jedna ili nekoliko savršeno valjanih ulaznih datotekaFuzzer može generirati desetke tisuća varijacija, sve dok ne naiđe na onu koja pokreće specifičnu grešku u zahvaćenom dekompresijskom putu.

Tijekom fuzzinga, AFL prati instrumentirani binarni zapis kako bi utvrdio kada ulaz uzrokuje izvršavanje drugačijeg puta upravljanja tokom. Svaki put kada otkrije novi put, Označi taj unos kao zanimljiv i čuva ga kao osnovu za buduće mutacije. Na taj način se ne istražuju samo uobičajeni putovi izvršavanja, već i one kombinacije podataka koje aktiviraju neobične rute koda, poput procesa dekompresije s neobičnim parametrima.

U slučaju podlijevanja cijelog broja, AFL može pronaći uzorak koji uzrokuje da uključena varijabla nikada ne dosegne očekivanu izlaznu vrijednost u petlji. Rezultat je detektabilni pad sustava, koji će biti pohranjen u odgovarajućoj mapi s AFL rezultatima, spreman za daljnju analizu.

Nakon nekoliko minuta ili sati izvršavanja, uobičajeno je da AFL ukazuje na prvi relevantni sudarNisu sve greške koje pronađete iskoristive, ali su jasan pokazatelj da nešto u upravljanju memorijom, validaciji ulaza ili unutarnjoj logici binarne datoteke ne radi kako bi trebalo.

Tada na scenu stupaju alati za podršku poput AFLTriagea ili debuggera poput GDB-a, koji vam omogućuju dublji uvid u pad sustava, promatranje stanja registara i memorije te procjenu može li se kvar pouzdano iskoristiti ili je to jednostavno problem od male koristi s gledišta napadača.

Osnovna instalacija AFL / AFL++ i analitičkog okruženja

Postavljanje minimalnog okruženja za fuzzing s AFL-om na standardnom Linux sustavu je prilično jednostavno. U mnogim distribucijama dovoljno je instalirati paket koji odgovara instrumentiranim kompajlerima, na primjer, pomoću naredbe poput instalirajte afl-g++ ili ekvivalentni AFL++ paket dovedite cijeli apartman.

Time se instaliraju i alati za fuzzing (kao što su afl-fuzz) kao što su specijalizirani kompajleri (afl-gcc, afl-g++ i njihove moderne varijante u AFL++). Ove kompajlere ćete koristiti kada želite ponovno kompajlirati svoj cilj s instrumentacijom, što je bitno za maksimalno iskorištavanje fuzzinga vođenog pokrivanjem.

Osim samog fuzzera, dobro okruženje za ispravljanje pogrešaka je praktički obavezno. Prošireni GDB s dodaci poput PEDA-e ili GEF-a Uvelike olakšava život zahvaljujući dodatnim naredbama, praktičnom formatiranju memorije, vizualizacijama stoga i prečacima za provjeru registara i mapa memorije.

Ako već nemate GDB, možete ga instalirati pomoću upravitelja paketa vaše distribucije. Zatim jednostavno integrirajte odabrani dodatak (na primjer, preuzimanjem GEF-a ili PEDA-e iz njihovih repozitorija i dodavanjem u vašu GDB konfiguracijsku datoteku ili korištenjem naredbe `source` unutar samog programa za ispravljanje pogrešaka).

Posjedovanje ovog „GDB-a na steroidima“ omogućit će vam analizu instrumentiranih binarnih datoteka koje se urušavaju pod fuzzingom, preuzimanje unosi koji uzrokuju rušenje i korak po korak pratite što se događa u izvršenju točno u trenutku kvara.

Kompajlirajte ciljnu binarnu datoteku s AFL-om za fuzzing

Nakon što imate AFL ili AFL++ spreman, sljedeći korak za ozbiljno fuzzing je kompajlirati cilj s AFL kompajlerimai to učiniti s odgovarajućim opcijama kako bi se olakšala i analiza i potencijalno iskorištavanje, u slučaju da je cilj vježbe ofenzivno istraživanje.

  SmartScreen blokira legitimne aplikacije: što se događa i što učiniti

U velikim projektima, kao što su dekompresor ili paket uslužnih programa za arhiviranje, dobra je ideja omogućiti simbole za otklanjanje pogrešaka (opcija DEBUG ili zastavice poput -gi minimizirati optimizacije (na primjer, korištenjem -O0 umjesto -O2). To uvelike pomaže u razumijevanju što se događa u izvornom kodu u odnosu na uočeni pad sustava.

Obično ćete morati pronaći odgovarajuću makefile ili build datoteku i izmijenite retke u kojima su definirane zastavice kompilacijeTo može uključivati ​​aktiviranje DEBUG varijable, prisiljavanje određene razine optimizacije i, što je najvažnije, zamjenu CC i CXX s afl-gcc i afl-g++ (ili ekvivalentnim AFL++ alatima).

Na primjer, mogli biste pokrenuti izgradnju s nečim poput CC=afl-gcc i CXX=afl-g++ zajedno s odgovarajućom makefile datotekom. Rezultat će biti instrumentirana binarna datoteka koja uključuje potrebne hooks-ove kako bi AFL mogao mjeriti pokrivenost tijekom izvršavanja.

Kada je kompilacija završena, dobro je provjeriti da rezultirajuća binarna datoteka zapravo ima simbole za otklanjanje pogrešaka i ispravnu arhitekturu, koristeći naredbu poput datoteka preko izvršne datotekeTo osigurava da ne koristite fuzz na slijepo i da možete lako otkloniti sve pogreške koje se dogode.

Priprema testnih slučajeva i izvršavanje AFL-a

Prije pokretanja AFL-a protiv vašeg binarnog programa, potrebno je pripremiti skup minimalni broj valjanih unosaAko testirate dekompresor koji ne uspijeva s datotekama komprimiranim pomoću određenog algoritma, morat ćete stvoriti barem jednu dobro oblikovanu datoteku koja koristi tu metodu kompresije.

Uobičajena praksa je stvaranje direktorija, na primjer nazvanog testcases, i pohranjivanje jednog ili više radnih uzoraka u njemu. Oni će poslužiti kao početna točka za AFL. stvara sve agresivnije mutacijepokušavajući otkriti nove putove izvršenja i, na kraju, ruši se.

Tipična naredba za pokretanje AFL-a izgleda otprilike ovako: navedite naziv sesije ili sinkronizacije, ulaznu mapu s testnim slučajevima, izlaznu putanju gdje će se rezultati pohraniti i neke dodatne parametre poput vremenskog ograničenja kako biste izbjegli zaglavljivanje u beskonačnim petljama.

Komandna linija također određuje kako se ciljni program izvršava pomoću semafor @@koji će AFL automatski zamijeniti putanjom svakog testnog slučaja koji generira. Dakle, možete odrediti nešto poput ./binarni argumenti @@ a AFL će biti odgovoran za pokretanje izvršne datoteke tisuće puta s različitim datotekama.

Važno je znati da se AFL u početku može žaliti na konfiguraciju sustava (zbog ograničenja resursa, izvatka jezgre itd.). U tom slučaju obično postoji pomoćni skript ili alat koji prilagođava parametre jezgre i sesije kako bi se optimiziralo fuzzing okruženje, a koji treba pokrenuti s odgovarajućim dozvolama prije ponavljanja testa.

Analiza sudara s AFLTriageom i GDB-om

Nakon razdoblja nejasnog definiranja, AFL će postupno popunjavati izlaznu mapu zanimljivim novim unosima i, prije svega, s datoteke koje su uzrokovale pad sustavaObično se pohranjuju u određenom poddirektoriju (na primjer, rušenja unutar mape sesije).

Kako biste izbjegli pretjerano pregledavanje svakog unosa pojedinačno, postoje alati poput AFLTriagea koji vam omogućuju da Automatski pokreni binarnu datoteku za svaku datoteku rušenja programa i generirati strukturirana izvješća s detaljima o tome gdje i kako je došlo do kvara.

Prilikom pokretanja AFLTriagea, navodite ulazni direktorij (mapu za pad sustava), izlazni direktorij za spremanje izvješća i naredbu za pokretanje binarne datoteke pomoću @@. Alat će analizirati svaki slučaj i Generirat će tekstualne datoteke s informacijama od interesa. za analitičara.

Tipičan sadržaj ovih izvješća uključuje vrstu signala koji je uzrokovao rušenje, smjer u kojem je došlo do greške, osnovni trag stoga i, u mnogim slučajevima, funkciju ili makro gdje je došlo do greške koda (na primjer, specifična operacija kopiranja, petlja kompresije ili makro COPY_CHUNKS koji oduzima veličine u svakoj iteraciji).

Nakon što se pronađe zanimljiv pad sustava, sljedeći korak je njegova reprodukcija u GDB-u. Da bi se to postiglo, program za ispravljanje pogrešaka pokreće se s binarnom datotekom i ulaznom datotekom krivca kao argumentima, a program se izvršava unutar GDB-a. Kada se pad sustava reproducira, stanje Ključni zapisi kao što su RAX, RDX itd., provjerite točnu instrukciju koja se izvršava i pogledajte mape memorije (vmmap) kako biste vidjeli koja se regija čita ili u koju se zapisuje.

Od pada sustava do potencijalne eksploatacije: moduli za analizu u GDB-u

Pad binarne datoteke ne znači uvijek da se ranjivost može iskoristiti. Tu do izražaja dolaze GDB proširenja poput modula. upotrebljiv, osmišljen za analizu konteksta pada sustava i ponudu grube klasifikacije toga može li se kvar iskoristiti ili ne.

Ove vrste proširenja proučavaju aspekte kao što su valjanost pokazivača instrukcije, stanje pokazivača stoga, memorijske dozvole adrese na kojoj se vrši pokušaj čitanja ili pisanja i priroda signala koji je uzrokovao pad sustava. Sa svim tim informacijama, oni pružaju indikativna presuda o potencijalu iskorištavanja (na primjer, kategorizacijom buga kao vjerojatno iskoristivog, moguće iskoristivog ili od malog interesa).

  Kako spriječiti zlonamjerne poveznice u Microsoft Teamsu

U slučaju Integer Underflow-a koji na kraju zapisuje u memoriju samo za čitanje, dodatak može predložiti da je ovo potencijalno iskorištavajući slučaj jer se operacija pisanja izvodi izvan očekivanih ograničenja u području gdje se ništa ne smije dirati.

Nisu svi scenariji tako jednostavni, ali ova kombinacija AFL-a za otkrivanje pada, AFLTriage-a za grupiranje i opisivanje slučajeva i GDB-a s proširenjima za procjenu iskoristivosti, tvori Vrlo robustan binarni revizijski cjevovodNakon toga, preostali posao je isključivo istraživanje i razvoj exploita, nešto što može enormno varirati u složenosti ovisno o binarnoj i aktivnoj zaštiti.

Drugi ključni dio analize, posebno kada se objave CVE i povezana zakrpa, jest pregled kako je ranjivost ispravljena u izvornom kodu. To obično uključuje promjene u vrsti korištenih podataka (na primjer, prelazak s predznačenog bajta na predznačeni bajt, proširivanje raspona) i uključivanje dodatnih provjera (if-ova koji vraćaju kodove pogrešaka ako su prekoračena određena ograničenja) kako bi se spriječilo prelijevanje ili oštećenje memorije.

Ostali relevantni fuzzeri i alati u ekosustavu

Iako su AFL i AFL++ među najpoznatijim opcijama za fuzzing izvornih binarnih datoteka, ekosustav fuzz testiranja je mnogo širi i vrijedi ga pratiti ako redovito radite s sigurnost softvera.

Među najčešće korištenim opcijama je LibFuzzer, biblioteka koju je izvorno razvio Google, a koja se izravno integrira s C/C++ kodom i izvodi fuzzing na razini specifičnih funkcija, idealno za testiranje pojedinačnih komponenti s visoko kontroliranim ulazima.

Tu je i Peach Fuzzer, platforma općenitije namjene i s više mogućnosti konfiguracije koja vam omogućuje definiranje točni modeli protokola, formata datoteka i složenih strukturaVrlo je popularan u sektorima gdje je pouzdanost ključna, kao što su industrijski sustavi ili IoT okruženja.

U web domeni, alati poput OWASP ZAP-a uključuju fuzzing module usmjerene na web aplikacije, sposobne za slanje manipulirani zahtjevi, deformirana učitavanja i testovi injektiranja HTTP krajnje točke za otkrivanje ranjivosti kao što su SQL injekcije, problemi s validacijom unosa ili pogreške u obradi obrazaca.

Sve ovo nadopunjuje AFL/AFL++ binarno fuzzing, jer omogućuje pokrivanje od niskorazinskog izvornog koda do slojeva aplikacije koji su najizloženiji krajnjem korisniku. Zajednički cilj u svim slučajevima je isti: automatizirati traženje ranjivosti prije nego što to učine napadači.

Kako integrirati fuzz testiranje u razvojni ciklus

Da bi fuzzing dosljedno pružao stvarnu vrijednost, nije dovoljno samo povremeno pokrenuti AFL ili AFL++ i zaboraviti na to. Mnogo je učinkovitiji. Integriranje fuzz testiranja u životni ciklus razvoja softvera, na sličan način kao što se to radi s jediničnim ili integracijskim testovima.

Prvi korak je definirati koji su dijelovi sustava najkritičnijiParseri datoteka, mrežni moduli, komponente koje obrađuju korisničke podatke ili vanjski izložene usluge. Specifične fuzzing kampanje mogu se osmisliti oko ovih ciljeva, korištenjem pažljivo odabranih testnih slučajeva.

Zatim morate odabrati pravi alat za svaki slučaj. Za složene izvorne binarne datoteke, AFL++ ili LibFuzzer su obično prirodni kandidati, dok će za web API-je ili HTTP aplikacije više smisla imati web-orijentirani alat. Važno je da se fuzzing ispravno izvršava. ponovljivo i automatizirano.

Integracija sa CI/CD sustavima je vrlo korisna: cjevovod se može konfigurirati tako da se u određenim granama ili prije određenih implementacija pokreće fuzzing baterija s ograničenim vremenom, spremajući sve nove pronađene padove i neuspjevajući izgradnju ako se pojave potencijalno ozbiljne ranjivosti.

Konačno, važno je razumjeti da je fuzzing iterativni proces. Svaki put kada se ispravi greška, zahvaćena komponenta treba ponovno fuzzirati kako bi se provjerilo da li zakrpa radi i da nisu uvedene nove greške. nema novih regresija ili ranjivostiNa taj način, fuzz testiranje postaje dodatni sloj kontinuirane zaštite, a ne izolirana revizija.

Uzevši sve gore navedeno zajedno, pokazuje kako nam AFL, AFL++ i fuzz testiranje općenito omogućuju prelazak s sigurnosnog pristupa temeljenog isključivo na ručnim pregledima na sveobuhvatniji pristup. mnogo automatiziranije i temeljitijeSposoban je otkriti pogreške koje bi inače ostale skrivene. Rad sa stvarnim slučajevima, poput ranjivosti uzrokovanih nedostatkom resursa u široko korištenim dekompresorima, također pomaže u razumijevanju da ovo nije samo teorija, već problemi koji se već iskorištavaju. Stoga, ažuriranje softvera i njegovo redovito izlaganje fuzzingu može napraviti razliku između kompromitiranog i otpornog sustava.