STMCTF'19 Write-Up Reverse Password
Selamlar, bu yazımda STMCTF’19 yarışmasında sorulan Reverse
kategorisinden Password
isimli sorunun çözümünü anlatacağım.
Soru dosyası : password
Soruda password
isminde bir executable dosya verilmiş. Reverse kategorisinden bir soru olduğu için öncelikle çalıştırılabilir dosyanın hangi işletim sistemine ait olduğunu öğrenmemiz gerekli. Elde ettiğimiz bilgiye göre inceleme yapacağımız makinemizi ve araçlarımızı seçmeliyiz. Linux üzerindeki file
komutu ile dosya hakkında bilgi alalım.
File komutu çıktısında ELF
türünde 64-bit
linux executable bir binary olduğunu gördük. Go
diliyle yazılmış. Ayrıca strip
edilmediğini de görüyoruz. Strip edilmemiş olması debug sembollerinin binary içinde tutulduğu anlamına gelir bu da reversing işlemi sırasında analiste kolaylık sağlar. Örneğin fonksiyon isimleri kaynak koddaki şekliyle görünür. İncelemeye başlamadan önce binary dosyamızı çalıştırıp ne yaptığına bakalım.
Binary’yi çalıştırdığımızda bir parola istedi ve doğruluğunu kontrol edip bize bilgi verdi. Soruda bizden istenen parolanın ne olduğunu tespit etmektir. Bu parolayı bulduktan sonra flag formatı(STMCTF{Flag}) içine koyduğumuzda flag değerimizi elde etmiş olacağız. GDB ile binary’yi debug ederek incelemeye başlayalım.
Go diliyle yazılmış bir binary’yi reverse etmek genellikle kolay değildir fakat burda strip edilmediği için bazı kolaylıklar karşımızda bulunmaktadır. Örneğin main fonksiyonundan analize başlayabiliriz. GDB internal komutlarından info
komutu yardımıyla main
fonksiyonunu bulalım.
Main fonksiyonunu disassemble ederken kullanacağımız main fonksiyonu isminin main.main
şeklinde olduğunu gördük. Main fonksiyonunu disassemble ederek kodu anlamaya çalışalım.
Binary’yi çalıştığımızda bizden parola istemişti ve doğru parola olup olmadığını kontrol ederek bize geri dönüş sağlamıştı. Parolanın doğru olup olmadığını karşılaştırdığı noktayı bulursak aslında hangi değer ile karşılaştırma yaptığını da görebiliriz. Bu kısımda artık assembly kodu okumamız gerekmektedir. Fakat buradaki kolaylık karşılaştırma yapılan yerlere bakarak ilerleme avantajımızın olmasıdır. Bu yüzden cmp
instruction’ını takip etmek mantıklı olacaktır.
fmt.Fscan
ifadesinin olduğu call
instruction’ı go dilindeki kullanıcıdan input almayı sağlayan fmt.Scan
fonksiyonunu göstermektedir. Bu kısımdan sonraki 3.instructionda cmp
ile karşılaştırma yapıldığını görüyoruz. Arada kalan 2 assembly koduna bakarsak aslında aradığımız parola değerini görebiliriz. RAX
registerına doğru parola değerinin ataması yapılıyor ve kullanıcıdan alınan input değeri ise RCX
registerına atanıyor. cmp instruction’ı ile RCX ve RAX register’ındaki değerlerin karşılaştırılması yapılıyor. Burda RAX register’ına atanan değer gerçek parola
bilgisidir. Burda dikkat edilmesi gereken husus parolanın hexadecimal
formatta debuggerda görünüyor olmasıdır fakat input olarak bu değer kullanıcıdan decimal
olarak alınır. Dolayısıyla hex değeri decimal değere çevirirsek parolamızı ele geçirmiş olacağız.
Değeri decimal formata çevirelim.
Parolamızı programa verip doğruluğunu kontrol edelim.
Parolamızın doğru olduğunu gördük. Flag formatı içine yerleştirip flag değerimizi elde edelim.
STMCTF{964358233091465775}
Yazımı okuduğunuz için teşekkürler, bir başka yazıda görüşmek dileğiyle..