Da li imate neku misterioznu datoteku? Linux komanda file
će vam brzo otkriti o kojoj vrsti datoteke se radi. Međutim, ako je to binarna datoteka, možete dobiti još više informacija o njoj. Komanda file
ima čitav niz alata koji će vam pomoći u njenoj analizi. Pokazaćemo vam kako da koristite neke od tih alata.
Identifikovanje tipova datoteka
Datoteke obično poseduju karakteristike koje omogućavaju softveru da prepozna o kom tipu datoteke je reč, kao i šta tačno podaci u njoj predstavljaju. Ne bi imalo smisla pokušavati otvoriti PNG datoteku u MP3 plejeru, stoga je korisno da datoteka sadrži neki oblik identifikacije.
Ovo može biti nekoliko bajtova potpisa na samom početku datoteke. Na taj način datoteka eksplicitno naglašava svoj format i sadržaj. Ponekad se tip datoteke zaključuje iz prepoznatljivog aspekta unutrašnje strukture samih podataka, poznatog kao arhitektura datoteke.
Neki operativni sistemi, poput Windowsa, se u potpunosti oslanjaju na ekstenziju datoteke. Možemo reći da je to naivno ili puno poverenja, ali Windows pretpostavlja da je svaka datoteka sa ekstenzijom DOCX zaista dokument za obradu teksta. Linux nije takav, kao što ćete uskoro videti. On želi dokaz i traži ga unutar same datoteke.
Alati opisani ovde su već instalirani na Manjaro 20, Fedora 21 i Ubuntu 20.04 distribucijama koje smo koristili za istraživanje ovog članka. Započnimo našu istragu korišćenjem komande file
.
Upotreba komande file
U našem trenutnom direktorijumu se nalazi kolekcija različitih tipova datoteka. Među njima je miks dokumenata, izvornog koda, izvršnih i tekstualnih datoteka.
Komanda ls
će nam prikazati sadržaj direktorijuma, a opcija -hl
(ljudski čitljive veličine, duga lista) će nam prikazati veličinu svake datoteke:
ls -hl
Hajde da isprobamo komandu file
na nekoliko ovih datoteka i vidimo šta ćemo dobiti:
file build_instructions.odt
file build_instructions.pdf
file COBOL_Report_Apr60.djvu
Tri formata datoteka su ispravno identifikovana. Gde je to moguće, file
nam daje malo više informacija. Za PDF datoteku je prijavljeno da je u verziji 1.5 formata.
Čak i ako preimenujemo ODT datoteku tako da ima ekstenziju sa proizvoljnom vrednošću XYZ, datoteka će i dalje biti ispravno identifikovana, kako u pregledaču datoteka tako i na komandnoj liniji pomoću komande file
.
U okviru pregledača datoteka, datoteka dobija ispravnu ikonu. Na komandnoj liniji, komanda file
ignoriše ekstenziju i gleda unutar datoteke kako bi odredila njen tip:
file build_instructions.xyz
Upotreba komande file
na medijima, kao što su slikovne i muzičke datoteke, obično daje informacije o njihovom formatu, kodiranju, rezoluciji i tako dalje:
file screenshot.png
file screenshot.jpg
file Pachelbel_Canon_In_D.mp3
Zanimljivo je da čak i sa datotekama u obliku običnog teksta, file
ne procenjuje datoteku prema njenoj ekstenziji. Na primer, ako imate datoteku sa ekstenzijom „.c“, koja sadrži standardni običan tekst, ali ne i izvorni kod, komanda file
je neće pogrešno smatrati originalnom C datotekom izvornog koda:
file function+headers.h
file makefile
file hello.c
Komanda file
ispravno identifikuje datoteku zaglavlja (.h”) kao deo kolekcije C datoteka izvornog koda i zna da je makefile skripta.
Upotreba komande file sa binarnim datotekama
Binarne datoteke su više „crna kutija“ od drugih. Slike se mogu pregledati, zvučne datoteke se mogu reprodukovati, a datoteke dokumenata mogu se otvoriti pomoću odgovarajućeg softvera. Binarne datoteke su, međutim, veći izazov.
Na primer, datoteke „hello“ i „wd“ su binarne izvršne datoteke. Oni su programi. Datoteka pod nazivom „wd.o“ je objektna datoteka. Kada kompajler kompajlira izvorni kod, kreira se jedna ili više objektnih datoteka. One sadrže mašinski kod koji će računar na kraju izvršiti kada se završi gotov program, zajedno sa informacijama za linker. Linker proverava svaku objektnu datoteku za pozive funkcija bibliotekama. Povezuje ih sa svim bibliotekama koje program koristi. Rezultat ovog procesa je izvršna datoteka.
Datoteka „watch.exe“ je binarna izvršna datoteka koja je unakrsno kompajlirana za pokretanje na Windows-u:
file wd
file wd.o
file hello
file watch.exe
Ako prvo uzmemo poslednju, komanda file
nam govori da je datoteka „watch.exe“ PE32+ izvršni, konzolni program za x86 porodicu procesora u Microsoft Windows-u. PE je skraćenica za prenosivi izvršni format, koji ima 32- i 64-bitne verzije. PE32 je 32-bitna verzija, a PE32+ je 64-bitna verzija.
Sve ostale tri datoteke su identifikovane kao Izvršni format koji se može povezati (ELF) datoteke. Ovo je standard za izvršne datoteke i deljene objektne datoteke, kao što su biblioteke. Uskoro ćemo pogledati ELF format zaglavlja.
Ono što bi vam moglo privući pažnju je da su dva izvršna fajla („wd“ i „hello“) identifikovana kao Linux standardna baza (LSB) deljenih objekata, a objektna datoteka „wd.o” je identifikovana kao LSB koja se može premeštati. Reč izvršni je očigledna u njenom odsustvu.
Objektni fajlovi se mogu premeštati, što znači da se kod unutar njih može učitati u memoriju na bilo kojoj lokaciji. Izvršni fajlovi su navedeni kao deljeni objekti jer ih je kreirao linker iz objektnih datoteka na takav način da nasleđuju ovu sposobnost.
Ovo omogućava da Randomizacija rasporeda adresnog prostora (ASMR) sistem za učitavanje izvršnih datoteka u memoriju na adresama koje on odabere. Standardni izvršni programi imaju adresu za učitavanje kodiranu u zaglavljima, koja određuju gde se učitavaju u memoriju.
ASMR je sigurnosna tehnika. Učitavanje izvršnih datoteka u memoriju na predvidljivim adresama čini ih podložnim napadima. To je zato što će njihove ulazne tačke i lokacije njihovih funkcija uvek biti poznate napadačima. Nezavisne izvršne datoteke (PIE) pozicionirani na nasumičnoj adresi prevazilaze ovu osetljivost.
Ako mi kompajliramo naš program sa gcc kompajlerom i obezbedimo opciju -no-pie, generisaćemo konvencionalni izvršni fajl.
Opcija -o (izlazna datoteka) nam omogućava da damo ime za naš izvršni fajl:
gcc -o hello -no-pie hello.c
Koristićemo komandu file
na novom izvršnom fajlu i videti šta se promenilo:
file hello
Veličina izvršnog fajla je ista kao i ranije (17 KB):
ls -hl hello
Binarni fajl je sada identifikovan kao standardni izvršni fajl. Ovo radimo samo u svrhu demonstracije. Ako sastavite aplikacije na ovaj način, izgubiće sve prednosti ASMR-a.
Zašto je izvršna datoteka tako velika?
Naš primer hello programa je 17 KB, tako da se teško može nazvati velikim, ali onda je sve relativno. Izvorni kod je 120 bajtova:
cat hello.c
Šta je to što „nagomilava“ binarnu datoteku ako sve što radi jeste štampanje jednog stringa u prozoru terminala? Znamo da postoji ELF zaglavlje, ali to je samo 64-bajta za 64-bitnu binarnu datoteku. Očigledno, mora biti još nešto:
ls -hl hello
Omogućava skeniranje binarne datoteke pomoću komande strings
kao jednostavan prvi korak kako bismo otkrili šta se nalazi unutar nje. Prebacićemo ga na less
:
strings hello | less
Unutar binarnog zapisa ima mnogo stringova, osim „Zdravo, svete giku!“ iz našeg izvornog koda. Većina njih su oznake za regione unutar binarne datoteke, i imena i informacije o povezivanju zajedničkih objekata. To uključuje biblioteke i funkcije unutar tih biblioteka, od kojih zavisi binarnost.
Komanda ldd
nam prikazuje zavisnosti zajedničkog objekta binarne datoteke:
ldd hello
Postoje tri unosa u izlazu, a dva od njih uključuju putanju direktorijuma (prvi ne):
linux-vdso.so
: Virtualni dinamički deljeni objekat (VDSO) je mehanizam kernela koji omogućava pristup skupu rutina prostora jezgra binarnim datotekama korisničkog prostora. Ovo izbegava troškove promene konteksta iz režima korisničkog jezgra. VDSO deljeni objekti se pridržavaju formata Executable and Linkable Format (ELF), omogućavajući im da budu dinamički povezani sa binarnim datotekama tokom vremena izvršavanja. VDSO se dinamički dodeljuje i koristi prednosti ASMR-a. VDSO mogućnost je obezbeđena standardom GNU C biblioteka ako kernel podržava ASMR šemu.libc.so.6
: GNU C biblioteka zajednički objekat./lib64/ld-linux-x86-64.so.2
: Ovo je dinamički linker koji binarni program želi da koristi. Dinamički linker ispituje binarni fajl da bi otkrio koje zavisnosti ima. Pokreće te zajedničke objekte u memoriju. On priprema binarni fajl za pokretanje i može da pronađe i pristupi zavisnostima u memoriji. Zatim pokreće program.
ELF Header
Mi možemo ispitati i dekodirati ELF zaglavlje koristeći uslužni program readelf
i opciju -h
(zaglavlje datoteke):
readelf -h hello
Zaglavlje nam se interpretira.
Prvi bajt svih ELF binarnih datoteka je postavljen na heksadecimalnu vrednost 0x7F. Sledeća tri bajta su podešena na 0x45, 0x4C i 0x46. Prvi bajt je oznaka koja identifikuje datoteku kao ELF binarnu. Da bi ovo bilo kristalno jasno, u sledeća tri bajta se navodi „ELF“ u ASCII kodu:
Klasa: Označava da li je binarni fajl 32- ili 64-bitni izvršni fajl (1=32, 2=64).
Podaci: Ukazuje na endianness u upotrebi. Endian kodiranje definiše način na koji se više-bajtni brojevi čuvaju. U kodiranju sa velikim endian-om, broj se prvo čuva sa svojim najznačajnijim bitovima. Kod malog endian kodiranja, broj se prvo čuva sa najmanjim bitovima.
Verzija: Verzija ELF-a (trenutno je 1).
OS/ABI: Predstavlja tip binarni interfejs aplikacije u upotrebi. Ovo definiše interfejs između dva binarna modula, kao što su program i deljena biblioteka.
ABI verzija: Verzija ABI-ja.
Tip: Tip ELF binarnog. Uobičajene vrednosti su ET_REL za resurs koji se može premeštati (kao što je objektna datoteka), ET_EXEC za izvršni fajl kompajliran sa zastavicom -no-pie i ET_DIN za izvršni fajl koji poznaje ASMR.
Mašina: Arhitektura skupa instrukcija. Ovo ukazuje na ciljnu platformu za koju je binarni fajl kreiran.
Verzija: Uvek postavljeno na 1, za ovu verziju ELF-a.
Adresa ulazne tačke: memorijska adresa u binarnom sistemu na kojoj počinje izvršavanje.
Drugi unosi su veličine i brojevi regiona i sekcija unutar binarne datoteke, tako da se njihove lokacije mogu izračunati.
Brzo pogledanje u prvih osam bajtova binarne datoteke sa hexdump-om će prikazati bajt potpisa i string „ELF“ u prva četiri bajta datoteke. Opcija -C
(kanonska) nam daje ASCII prikaz bajtova zajedno sa njihovim heksadecimalnim vrednostima, a opcija -n
(broj) nam omogućava da odredimo koliko bajtova želimo da vidimo:
hexdump -C -n 8 hello
objdump i granulirani prikaz
Ako želite da vidite detaljne detalje, možete da koristite komandu objdump
sa opcijom -d
(rastavi):
objdump -d hello | less
Ovo rastavlja izvršni mašinski kod i prikazuje ga u heksadecimalnim bajtovima zajedno sa ekvivalentom asemblerskog jezika. Lokacija adrese prvog pozdrava u svakom redu prikazana je krajnje levo.
Ovo je korisno samo ako znate da čitate asemblerski jezik ili ste radoznali šta se dešava iza zavese. Ima mnogo izlaza, pa smo ga ubacili u less
.
Sastavljanje i povezivanje
Postoji mnogo načina za kompajliranje binarne datoteke. Na primer, programer bira da li će uključiti informacije o otklanjanju grešaka. Način na koji je binarni link povezan takođe igra ulogu u njegovom sadržaju i veličini. Ako binarne reference dele objekte kao spoljne zavisnosti, biće manje od one sa kojom se zavisnosti statički povezuju.
Većina programera već zna komande koje smo ovde opisali. Za druge, međutim, oni nude neke jednostavne načine da pretražuju i vide šta se nalazi unutar binarne „crne kutije“.