İnek Şaban Crackme

TARİH: 2026-05-14HEDEF: İnek Şaban Crackme

1. İlk İnceleme ve Statik Analiz

Dosyayı ilk incelediğimde klasik strings komutuyla okunabilir metinleri dump ettim.

strings crackme1


Şekil 1: Strings çıktısı

Çıktıyı incelediğimde karşıma kabak gibi FLAG{Tebrikler_Dogru_Flag} şeklinde bir string çıktı. Ayrıca başarılı veya başarısız durumlara ait herhangi bir çıktı mesajı tebrikler veya yanlış flag gibi göremedim. Bu kadar açık bir flag “Rabbit Hole” tuzağı olabiliceği konusunda şüphelendirdi

2. Dinamik Analiz ve Anti-Debug Tespitleri

Şüphemde haklı olup olmadığımı görmek için dosyayı GDB (GNU Debugger) üzerinde çalıştırdım. Aynı zamanda dinamik kütüphane çağrılarını izlemek için ltrace denemesi yaptım.


Şekil 2: Fake flag

GDB üzerinde programı çalıştırdığımda program benden flag istedi. strings çıktısında bulduğum FLAG{Tebrikler_Dogru_Flag} metnini girdiğimde program Tunelin ucu :) https://www.youtube.com/watch?v=3ksNL9uJssw mesajını verdi. Linke gittiğimde alaycı bir şekilde Kemal Sunal film repliği kullanılarak buranın gerçekten tuzak olduğu gösterilmiş.Ayrıca programı GDB içerisinde çalıştırırken araya giren SIGTRAP kesmesi içeride kasıtlı bir anti-debugging mekanizmasının bulunduğunu ve debugger tespit edildiği için sahte bir akışa yönlendirildiğimi kanıtladı. Asıl flag’i bulabilmek için Ghidra programına geçtim.


Şekil 3: Tünelin ucu kötü bi yere çıktı

3. Ghidra ve Algoritma Analizi

Dosyayı Ghidra’ya yükleyip decompile ettiğimde asıl koruma mekanizmalarını net bir şekilde gördüm. Programın entry kısmını bulduktan sonraki fonksiyona ilerlediğimde main kısımda olduğumu kod parçacığından anladım. Karşılama mesajı vs burada barınıyordu.

  signal(5,FUN_001011bc);
  FUN_00101159("=== Trackbook Crackme 1 ===\n");
  FUN_00101159("Lutfen flag giriniz: ");
  FUN_00101199(local_98,0x3f);
  local_fc = 0;
  do {
    if (0x3f < local_fc) {
LAB_001015c8:
      pcVar1 = (code *)swi(3);
      (*pcVar1)();
      return;
// Ghidra decompile işlemini burada kesti!

Koruma 1: Exception Based Control Flow

Kod içerisinde signal(5, ...) ile işletim sistemine SIGTRAP handler tanımlanmış ve hemen ardından swi(3) yani assembly karşılığı olan INT 3 kesmesi çağrılmıştı.

Decompiler’ı Düzeltme (NOP Patching)

Ghidra, INT 3 instruction’ını gördüğü an program akışının orada sonlandığını varsaydığı için asıl kontrol bloklarını decompile etmemişti. Kodun devamı için assembly üzerinden patch uyguladım.

Orijinal Assembly Akışı:

        001015bd 7e 09           jle        LAB_001015c8
        001015bf 8b 45 fc        mov        eax,dword ptr [rbp + local_fc]
        ...
                             LAB_001015c8
        001015c8 cc              INT        3  ; Breakpoint

Buradaki CC opcode’unu 90 ile değiştirdim:

Patchlenmiş Assembly Akışı:

                             LAB_001015c8
        001015c8 90              NOP        ; Ghidra artık buraan sonra devam edicek

Bu işlemin ardından Ghidra fonksiyonu yeniden otomatik analiz etti ve kesintiden sonraki asıl doğrulama bloğu ortaya çıktı. Decompile çıktısı güncellendiğinde, uygulamanın durum değişkenine göre dallandığını gördüm. Doğru akıştaki gizli fonksiyon çağrısını takip ederek FUN_001012fe ve FUN_001011d0 fonksiyonlarına ulaştım.

    if (0x3f < local_fc) {
code_r0x001015c9:
      if (_DAT_0010402c == 1) {
        iVar1 = FUN_001012fe(local_98);
        if (iVar1 == 0) {
          FUN_001011d0(&local_f8,0x13);
        }
        else {
          FUN_001011d0(&local_58,0x42);
        }
      }
      else {
        iVar1 = strcmp(local_98,"FLAG{Tebrikler_Dogru_Flag}");
        if (iVar1 == 0) {
          FUN_001011d0(&local_d8,0x3d);
        }
        else {
          FUN_001011d0(&local_f8,0x13);
        }
      }

4. String Obfuscation (XOR) ve Bayrağı Elde Etme

Debugger tespit edilmediği durumda çalışan gerçek kontrol fonksiyonuna (FUN_001012fe) girdiğimde gerçek bayrağın plain-text olarak tutulmadığını gördüm.

Koruma 2: In-Memory XOR Obfuscation

Fonksiyonun decompile edilmiş C kodu şu şekildeydi:

  local_28[0] = 0x7c;
  local_28[1] = 0x6b;
  //diğer byte lar
  local_28[0xf] = 0x4c;
  local_30 = 0;
  
  do {
    //uzunluk ve güvenlik kontrolü
    if ((int)(char)(*(byte *)(param_1 + local_30) ^ 0x31) != (uint)local_28[local_30]) {
      uVar1 = 0;
      goto LAB_0010139f; //hatalı flag
    }
    local_30 = local_30 + 1;
  } while( true );

Sistem kullanıcının girdiği her bir karakteri 0x31 key değeri ile XOR işlemine sokuyor ve belleğe statik olarak gömülmüş olan şifreli hexadecimal dizi ile eşleştiriyordu. Ayrıca ekrana basılan mesajların da 0x55 key değeri ile anlık olarak deşifre edilip yazdırıldığını tespit ettim.

void FUN_001011d0(long param_1,int param_2)
{
  long in_FS_OFFSET;
  int local_9c;
  byte local_98 [136];
  long local_10;
  
  local_10 = *(long *)(in_FS_OFFSET + 0x28);
  
  //local_98 buffer'ının 0 ile doldurulduğu kısımlar]
  
  for (local_9c = 0; local_9c < param_2; local_9c = local_9c + 1) {
    local_98[local_9c] = *(byte *)(param_1 + local_9c) ^ 0x55;
  }
  local_98[param_2] = 0;
  FUN_00101159(local_98); //Şifresi çözülen metnin ekrana basılması
  
  if (local_10 != *(long *)(in_FS_OFFSET + 0x28)) {
    __stack_chk_fail();
  }
  return;
}

Gerçek flagi elde etmek için CyberChef aracını kullanarak elde ettiğim statik hex dizisine 0x31 anahtarı ile XOR işlemi uyguladım:


Şekil 3: Gerçek flag

Deşifre Edilen Gerçek Bayrak: MZVY{Inek_Saban}

5. Doğrulama

Elde ettiğim flagi doğrulamak amacıyla programı bu kez herhangi bir debugger kullanmadan normal terminal akışında çalıştırdım.


Şekil 5: Gerçek flagin doğrulaması

Yapımcının takdirini kabul ediyo ve yerime oturuyorum :)


Şekil 6: Aferin Şaban