Po drátě 6: Řešení úlohy č. 14

Nevinně vyhlížející formulářík vybízí k vyplnění Céčkového zdrojáku. Tak mu nějaký syntakticky korektní zadáme (kdo by odolal zkusit nejdřív tradiční Hello world?) a z překladače vypadne staticky slinkovaná binárka pro Linux/i386, která dělá přesně to, co jsme napsali.

Opravdu přesně? Ne tak docela... Například strace odhalí, že než program spustí main, zapíše do file deskriptoru 99 heslo k vedlejší úloze.

No dobře, ale kde je hlavní heslo? Pokud se na program podíváme nějakým disassemblerem, zjistíme, že před spuštěním mainu prozkoumá argumenty a byl-li spuštěn s parametrem --passwd, vypíše do standardního výstupu heslo.

Co asi do programů vkládá váš domácí překladač? ;-)

Zajímavosti

Tato úloha je tichou vzpomínkou na Dennise Ritchieho (1941-2011), jenž spolu s Brianem Kernighanem vymyslel jazyk C.

Také nás k ní inspirovala přednáška Ritchieho kolegy a spoluautora UNIXu Kena Thompsona jménem Reflections on Trusting Trust, v níž moc hezky předvedl, že i když máte k dispozici zdrojáky celého operačního systému včetně překladače, nemusí to ještě znamenat, že si do něj autoři nezabudovali zadní vrátka. Příjemnou vlastností Linuxu, který kompilují lidé po celém světě různými překladači, je, že by útoky tohoto typu byly pravděpodobně snadno odhalitelné.

Samotný webový překladač je triviálním obalem okolo GCC a také cvičením na použití přepínače --wrap GNU linkeru. Místo GNU libc ale používáme diet libc, přeci jenom půlmegovým hello worldem jsme vás trápit nechtěli.

Mimochodem, to byste nevěřili, čím vším autor, testeři i hráči zkoušeli překladač potrápit. Například #include "/dev/zero", #include "/dev/random", nebo třeba __asm__(".incbin \"/etc/passwd\"");.

Úlohu vytvořil Medvěd.

Re: Po drátě 6: Řešení úlohy č. 14 Tomáš Janoušek (25. 1. 2012 - 13:10) Sbalit(9)
Hele, ostatní spoluřešící, příšli jste na to --passwd? Já to vyřešil, aniž bych o tom měl ponětí. :-)
Re: Po drátě 6: Řešení úlohy č. 14 Martin Jirman (25. 1. 2012 - 14:08) Sbalit(1)
Také jsem o to nevěděl. Já to disassembloval, pak spustil v GDB s breakpointem před jumpem, který rozhodoval, zda vypsat rozkódované heslo, změnil jsem správný flag a nechal pokračovat.
Re: Po drátě 6: Řešení úlohy č. 14 playeeer1 (25. 1. 2012 - 14:33) Sbalit(1)
Ja se zameril na casti kodu co sahaji na rodata a pak udelal ten xor rucne.
Re: Po drátě 6: Řešení úlohy č. 14 JS (25. 1. 2012 - 14:35) Sbalit(5)
Ja taky. Situaci mi navic komplikoval fakt, ze x86 assembler moc neumim. Myslel jsem, ze je to proste mrtvy kod, to vypisovani hesla (na zasobnik); kdyz se ale odstranil ten jmp, ktery ho normalne preskakuje, zacalo to padat.

Ale aspon jsem se dozvedel o __kernel_vsyscall. Zaujalo me, ze se v tom zdrojaku vyskytuje int 80, ale vubec se nepouziva (mi prijde).
Re: Po drátě 6: Řešení úlohy č. 14 JS (25. 1. 2012 - 14:37) Sbalit(3)
Jeste jsem se chtel zeptat, byla tam nejaka ochrana pred ladenim? V gdb jsem zkousel davat "si 100", ale to nejak padalo..
Re: Po drátě 6: Řešení úlohy č. 14 Martin Mares (org) (25. 1. 2012 - 14:38) Sbalit(2)
> Jeste jsem se chtel zeptat, byla tam nejaka ochrana pred ladenim? V gdb jsem
> zkousel davat "si 100", ale to nejak padalo..

Nejefektivnější ochranou před laděním je neuvěřitelné množství bugů v gdb :-)

Docela dlouho jsem se snažil gdb přimět k tomu, aby mi program začalo
krokovat, ale se staticky slinkovanou binárkou bez debug infa si alespoň
ta verze, kterou jsem zkoušel, neporadila. Breakpoint na začátek programu
si nastavit nechala, ale pak ho prostě neprovedla :)

A nebude to jediný bug report, který po hře pošlu ;)

Re: Po drátě 6: Řešení úlohy č. 14 playeeer1 (25. 1. 2012 - 14:50) Sbalit(1)
Ten bug jsem nasel nareportovany a mel by byt uz opraveny v nejake novejsi verzi.
Re: Po drátě 6: Řešení úlohy č. 14 Martin Jirman (25. 1. 2012 - 14:39) Sbalit(1)
Kousek od entry pointu se vybere, zda pouzit int 80, anebo novejsi (rychlejsi) zpusob volani. Dela se to prehozenim pointeru, ktery defaultne miri prave na ten int 80.
Re: Po drátě 6: Řešení úlohy č. 14 Michal Kubeček (25. 1. 2012 - 15:52) Sbalit(1)
U téhle jsem měl docela štěstí, že jsem neprošel tolik slepých uliček
jako obvykle. Hned jak se mi podařilo trochu zkrotit gdb, našel jsem
syscall (ten nešlo přehlédnout) a pod ním celkem snadno rozeznatelné
strcmp(). Tak jsem se podíval, odkud se volá, dal si tam breakpoint a
podíval se, co se s čím porovnává.

Re: Po drátě 6: Řešení úlohy č. 14 sine (25. 1. 2012 - 13:28) Sbalit(1)
Zakerne, cakal som nieco ovela zlozitejsie a to som si binarku este zbezne
prezeral v IDAe. Povodne som si myslel, ze sa to riesi cez #include "" a
navratove chybove hlasky, ale prislo mi to nezrealizovatelne a zistil som
maximalne par bajtov zo spustaneho perl CGI skriptu.

Re: Po drátě 6: Řešení úlohy č. 14 Tomas Cech (25. 1. 2012 - 17:46) Sbalit(1)
Pouzil jsem jiny offset pro jump, misto 99:kapradina to skakalo k heslu. Uloha byla velmi poucna a opravdu nuti k zamysleni nad binarkami, ktere pouzivame.

Prvni, co me napadlo bylo nejake pouziti #pragma a jsem rad, ze to v tom nebylo...
Re: Po drátě 6: Řešení úlohy č. 14 MP (25. 1. 2012 - 23:34) Sbalit(3)
Cim jste to disasemblovali? Pod linuxem sice existuje par disassembleru, ale zatim jsem nenarazil na zadny co by byl aspon trochu kvalitni ...
Re: Po drátě 6: Řešení úlohy č. 14 Michal Kubeček (26. 1. 2012 - 1:12) Sbalit(1)
On Wed, Jan 25, 2012 at 11:34:41PM +0100, MP wrote:
> Cim jste to disasemblovali? Pod linuxem sice existuje par
> disassembleru, ale zatim jsem nenarazil na zadny co by byl aspon
> trochu kvalitni ...

gdb

Re: Po drátě 6: Řešení úlohy č. 14 tcech (27. 1. 2012 - 21:03) Sbalit(1)
objdump