1 puan yazan GN⁺ 2025-02-19 | 1 yorum | WhatsApp'ta paylaş
  • iOS uygulamalarında tersine mühendislik için çalışan uygulamayı gözlemleyip manipüle edebilmek gerekir; ancak bu widget uygulaması debugger engelleme, kod enjeksiyonu engelleme ve jailbreak tespitini birlikte kullanıyor
  • Temel engelleme, ptrace içindeki PT_DENY_ATTACH ya da aynı etkiyi veren doğrudan sistem çağrısı (svc #0x80) ile uygulanabiliyor; bu yüzden yalnızca basit bir ptrace breakpoint’i ile yakalanmıyor
  • Doğrudan sistem çağrısı, ikili dosyada mov w16, #26 desenini bulup svc konumuna breakpoint koyarak ve lldb jump ile ilgili komutu atlayarak aşılabiliyor
  • Jailbreak tespitinden sonra telefonu soft-reboot/respring yapan davranış, snapshotViewAfterScreenUpdates: metodunu sonsuz döngü içinde çağıran bir fonksiyonla bağlantılıydı ve fonksiyon başlangıcında thread return ile atlanabiliyordu
  • Kod enjeksiyonundan sonraki çökme, ayrı bir runtime framework denetiminden çok App Group yetkisinin kaybına yakındı; containerURLForSecurityApplicationGroupIdentifier: metodunu geçici dizine yönlendiren bir swizzle ile uygulama normal cihazlarda da çalıştırılabildi

Birden fazla korumayı üst üste kullanan iOS widget uygulaması

  • Hedef, App Store’daki bir widget uygulaması ve sıradan widget uygulamalarından daha güçlü savunma davranışları içeriyor
    • debugger attach engelleme
    • kod enjeksiyonu sırasında uygulamayı kapatma
    • jailbreak durumunda çalıştırılırsa telefonun tamamını soft-reboot/respring yapma
  • iOS uygulamalarının jailbreak tespiti ya da kod karmaşıklaştırma gibi korumalar eklemesi alışılmadık değil, ancak bu uygulama birden fazla yöntemi birlikte kullanıyor
  • Uygulama içindeki diğer ilginç davranışlar sonraki yazıya bırakılıyor

PT_DENY_ATTACH ile debugger attach engelleme

  • Jailbreak’li cihazlarda genelde ssh ile bağlanıp debugserver çalıştırarak, başka bir bilgisayardaki lldb üzerinden uygulama hata ayıklanabiliyor
  • Aynı yöntemle bu uygulamaya debugserver bağlanınca Segmentation fault oluşuyor ve attach başarısız oluyor
  • Nedeni, ptrace içindeki PT_DENY_ATTACH isteğiyle ilgili
    • ptrace, iOS’ta private API, macOS’ta ise public API
    • PT_DENY_ATTACH, sonrasında ebeveyn sürecin trace etmesini reddeden bir bayrak ayarlıyor
    • Süreç zaten trace ediliyorsa uygulama ENOTSUP durumuyla sonlanıyor
    • Bu bayrağın ayarlandığı bir süreci ebeveyn trace etmeye çalışırsa ebeveyn tarafında segmentation violation oluşuyor
  • Basit uygulama, ptrace(PT_DENY_ATTACH, 0, 0, 0) çağrısıyla mümkün
    • Bu iOS private API olduğu için gerçek çağrıda dlopen, dlsym ile libsystem_kernel.dylib içindeki ptrace sembolünü bulmak gerekiyor
    • Bu yöntem, ptrace üzerine breakpoint koyup thread return ile çağrıyı atlayarak nispeten kolay aşılabiliyor

Kolay yöntemin işe yaramamasının nedeni

  • PT_DENY_ATTACH debugger’ı ancak çağrıldıktan sonra engellediği için, uygulama kodu çalışmadan önce attach olunursa bir bypass noktası oluşturulabiliyor
  • debugserverı sürece doğrudan bağlamadan çalıştırıp, ardından lldb içinde process attach --name TopWidget --waitfor ile uygulamanın başlaması beklenirse uygulama kodu çalışmadan önce attach olunabiliyor
  • Ancak bu uygulamada b ptrace breakpoint’i ilk başta çözümlenmedi ve sonrasında çözümlense bile uygulama kapanana kadar hiç tetiklenmedi
  • Çünkü uygulama ptrace fonksiyon çağrısı yerine aynı etkiyi veren doğrudan sistem çağrısı yöntemini kullanıyordu

Doğrudan sistem çağrısının yerini bulma

  • ptrace fonksiyonunun disassembly çıktısında temel olarak svc #0x80 sistem çağrısı bulunuyor
    • x0 içine PT_DENY_ATTACH değeri olan 31 yazılıyor
    • x1, x2, x3 içine kullanılmayan 0 argümanları yazılıyor
    • x16 içine ptrace sistem çağrısı numarası olan 26 yazılıyor
  • Uygulama ptrace fonksiyonunu çağırmak yerine inline assembly ile aynı register değerlerini ayarlayıp svc #0x80 komutunu doğrudan çalıştırabiliyor
    • Bu yöntem dlopen, dlsym gibi şüpheli private API lookup’larını önlüyor
    • ptrace gibi ortak bir fonksiyona breakpoint koyma yaklaşımıyla yakalanması zorlaşıyor
  • Bypass için şifresi çözülmüş uygulama ikilisini bir disassembler’da açıp ptrace sistem çağrısının yerini bulmak gerekiyor
  • Aranacak desen mov x16, #26 ya da aynı register’ın 32 bit görünümü olan mov w16, #26
    • armconverter.com üzerinden mov x16, #26 için 50 03 80 D2 baytları elde edilip ikili aramada kullanılabiliyor
    • mov x16, #26 araması sonuç vermedi, mov w16, #26 aramasında ise 4 sonuç bulundu
  • Bunlardan ikisinde çevredeki komutlar beklenen desenle uyuşmuyordu; üçüncü sonuçta ise şu yapı doğrulandı
    • MOV X0, #0x1F
    • MOV X1, #0
    • MOV X2, #0
    • MOV X3, #0
    • MOV W16, #0x1A
    • SVC 0x80
  • Dördüncü sonuç aynı fonksiyonun başka bir branch’iydi ve bu fonksiyonun debugger attach’i engelleyen yer olduğu doğrulandı

svc komutunu atlamak

  • Disassembler’da görülen svc adresleri 0x102A2BB14 ve 0x102A2BB68
  • lldb içinde ikili dosya tabanlı adresi gerçek yükleme adresine çevirmek için breakpoint’e -s TopWidget ekleniyor
    • br s -a 0x102A2BB14 -s TopWidget
    • br s -a 0x102A2BB68 -s TopWidget
  • Çalışma sürdürüldüğünde breakpoint svc #0x80 konumunda yakalanıyor
  • En kolay bypass, bir sonraki komut adresine jump ederek sistem çağrısının kendisini hiç çalıştırmamak
    • Örnekte mevcut komuttan sonraki adres olan 0x10327bb18 için jump *0x10327bb18 çalıştırılıyor
  • Bu süreçten sonra debugger attach edilmiş halde uygulamanın içine girilebiliyor

Telefonu soft-reboot yapan davranış

  • Debugger attach bypass edildikten sonra bile uygulama telefonu soft-reboot/respring yapan koruma davranışını çalıştırıyor
  • Bu kez lldb hâlâ attach durumda olduğu için, sürecin SIGKILL aldığı an ve stacktrace görülebiliyor
  • Stacktrace’te ekran içeriğini yakalayan bir akış görünüyor
    • QuartzCore içindeki CARenderServerSnapshot
    • UIKitCore içindeki _UISnapshotScreenWindowsRectAfterCommit
    • uygulama içindeki TopWidget adlı isimsiz sembol
  • lldb image lookup ile runtime adresi, ikili dosya tabanlı 0x100041898 adresine çevrilip disassembler’da ilgili fonksiyon inceleniyor
  • Decompile sonucunda fonksiyonun sonsuz döngü içinde yalnızca şu işleri tekrar ettiği görülüyor
    • +[UIScreen mainScreen] çağrısı
    • dönen ekran nesnesi üzerinde snapshotViewAfterScreenUpdates: çağrısı
    • sonuç kullanılmadan release edilmesi
  • snapshotViewAfterScreenUpdates: view snapshot oluşturan bir public API olsa da bu uygulama bellek yoğun bu çağrıyı sonsuz biçimde tekrarlıyor
  • Bağlantılı videoda bu çağrının kökeninin com.apple.tw.twrr notification’ı ile ilişkili olduğu ve telefona yönelik risk kontrolü geçilemezse respring yaşandığı doğrulanıyor
  • Bypass, ilgili fonksiyonun başlangıcına breakpoint koyup tetiklendiğinde thread return ile fonksiyon yürütmesini atlamakla mümkün

Kod enjeksiyonu sırasında oluşan çökme

  • Hata ayıklama sırasında ekrandaki butonların erişilebilirlik bilgisini log’lamak gibi karmaşık yardımcı araçlar, uygulamaya enjekte edilen bir framework içinde uygulanıp debugger’dan çağrılabiliyor
  • Jailbreak’li cihaz olmadığında da Frida veya Flex enjekte edilerek uygulama üzerinde ilk keşif yapılabiliyor
  • Genel olarak bu tür enjeksiyon, uygulamayı yeniden imzalayan araçlarla yapılıyor; örnek olarak Sideloadly kullanılıyor
  • Bu uygulama yeniden imzalandıktan sonra çalıştırıldığında anında crash ediyor
  • Crash stack’inin üst kısmındaki 0x1002027D4 adresi disassembler’da incelendiğinde BRK komutu görülüyor; bu da nil force-unwrap gibi kasıtlı çökme durumlarıyla uyumlu
  • Decompile edilmiş kodda sorunlu görünen çağrı containerURLForSecurityApplicationGroupIdentifier:
    • Bu metot, aynı group içindeki uygulama ve extension’ın birlikte erişebildiği klasör URL’sini döndürüyor
    • App Group, kod imzalama sürecinde tanımlanıyor
    • Kod enjeksiyonundan sonra yeniden imzalama yapılınca mevcut uygulama imzası atılıyor ve App Group yetkisi de kayboluyor
    • Bu yüzden URL yerine nil dönüyor ve uygulama bunu force-unwrap ettiği için crash etmiş olma ihtimali yüksek
  • Widget uygulamaları, ana ekran widget gösterimini üstlenen extension ile App Group paylaşmak zorunda olduğundan, bu sorun savunma amaçlı kasıtlı davranıştan çok yaygın bir kod imzalama problemine benziyor

App Group sorununu aşma

  • En kolay çözüm uygulamayı yeniden imzalamamak
    • Jailbreak’li cihazlarda bir jailbreak tweak ile framework enjekte edilirken uygulamayı yeniden imzalamadan devam edilebiliyor
    • Geçersiz imzalı kod çalıştırmak ya da istenen uygulamayı istenen group’a eklemek de mümkün
  • Jailbreak’li cihaz yoksa ve yeniden imzalama gerekiyorsa, küçük bir framework ile metod swizzle yapılarak da aşılabiliyor
  • Örnek kod, NSFileManager içindeki containerURLForSecurityApplicationGroupIdentifier: metodunu değiştiriyor
    • Orijinal metot çağrıldığında yerine replacement method çalışıyor
    • Replacement method, shared container yerine temporaryDirectory döndürüyor
  • Bu değişiklik uygulamanın aslında istediği davranışla aynı değil
    • Uygulamanın istediği, uygulama ile extension’ın birlikte erişebileceği paylaşımlı klasör
    • Geçici dizin böyle bir paylaşımlı klasör değil
  • Yine de amaç yalnızca ana uygulamanın davranışını incelemekse yeterli olabiliyor
    • Bu tür küçük bir patch app extension’ı bozabilir
    • Yalnızca ana uygulamanın temel işlevleri gerekiyorsa sorun olmayabilir
  • Daha büyük bir bypass, yeni bir App Group oluşturup ana uygulama ile tüm extension’ları bu group ile yeniden imzaladıktan sonra ilgili metotların yeni group identifier’ı kullanmasını swizzle etmek
    • Bu çok daha büyük bir iş ve gerçekten gerekmedikçe jailbreak’li bir cihaz edinmek daha mantıklı olabilir
  • Bu framework Flex gibi araçlarla birlikte enjekte edildiğinde uygulama normal cihazlarda da düzgün çalışıyor
  • Jailbreak’li cihazlarda önceki anti-debugging ve respring korumalarının yeniden aşılması gerekiyor, ancak sonrasında Flex enjekte edilmiş halde uygulamanın içine girilebiliyor

Son durum

  • Sonuçta uygulama, debugger attach, jailbreak tespitini aşma ve kod enjeksiyonu açısından tamamen erişilebilir hâle geliyor
  • Uygulama içinde gerçekte neyin incelenmek istendiği ise sonraki yazının konusu olarak bırakılıyor

1 yorum

 
GN⁺ 2025-02-19
Hacker News yorumları
  • Bryce Bostwick, uygulama hata ayıklama ve tersine mühendislik konusunda gerçekten harika ve ilham verici işler yapıyor
    Onu YouTube’da keşfettim; TikTok’u yalnızca kedi videoları gösterecek şekilde modifiye ettiği videosunu (https://youtu.be/YW3jL2gI9IE) izledikten sonra Instagram’ı, kullandığım mesajlaşma özelliği dışında her şeyi kaldıracak şekilde modifiye etmeyi denedim
    Eskiden beri Windhawk (https://windhawk.net/) tarzında Windows’u modifiye etme yöntemlerini, özellikle modifikasyon ve tersine mühendisliği daha derinlemesine incelemek istiyordum; Bryce iOS’ta bu tür işleri gerçek zamanlı, adım adım videolarla çok iyi tanıtıyor

    • Android tarafında da benzer biri varsa daha fazla öğrenmek isterim
      Revanced ile harika şeyler yapılabildiğini gördüm ama bu tür işlere nasıl başlanacağını anlatan iyi bir rehber pek yok gibi görünüyor
    • Anlattıklarını bizzat denemeyi planlıyorum
      Süreci bir yere derlersen ilgimi çeker
      Fotoğraf yüklemek ya da arkadaşlarımla sohbet etmek istediğimde bile Reels’e maruz kalmak zorunda kalmaktan hoşlanmıyorum
  • Hata ayıklamayı engelleme ve hatta hata ayıklamayı engellemeyi devre dışı bırakmayı yeniden engelleme teknikleri DOS/Windows tarafında çok eskiden beri yaygındı
    Eski cracking veya unpacking kaynaklarına bakarsanız bu konuların farklı derinliklerde ele alındığını görürsünüz
    Kullanıcının uygulama davranışını ne kadar kolay denetleyebildiği, platformun kullanıcıya ne kadar düşmanca olduğuyla ters orantılıdır
    PT_DENY_ATTACH tam da bu kullanıcı düşmanlığı için yapılmış bir özellik gibi görünüyor
    Bildiğim kadarıyla Windows’ta böyle bir özellik yok; bunun yerine uygulamayı kendi kendisine attach ettirme tekniği kullanılıyor
    https://www.x86matthew.com/view_post?id=selfdebug
    https://anti-debug.checkpoint.com/techniques/interactive.htm...

    • Doğru. PT_DENY_ATTACH, eskiden Apple’ın iTunes’un DRM çözümünün bir parçası olarak kelimenin tam anlamıyla bizzat oluşturduğu bir özellik
  • Apple’ın App Store incelemesinin doğrudan sistem çağrısı yapan uygulamaları reddetmemesi biraz şaşırtıcı
    Apple platformlarındaki sistem çağrıları kararlı bir ABI değil; bu yüzden tüm sistem çağrılarının libSystem üzerinden geçmesi gerekir ve libSystem’i atlayıp doğrudan sistem çağrısı yapan uygulamalar yapmamaları gereken bir şeyi yapıyor sayılır
    Benzer şekilde, burada yazarın kodda svc 0x80 yerine neden mov w16, #26 aradığını da merak ediyorum

    • svc 0x80, herhangi bir sistem çağrısını çalıştıran komuttur; tam olarak hangi çağrının çalışacağı x16 yazmacına göre belirlenir
      Uygulama muhtemelen alakasız çok sayıda sistem çağrısı yapacağı için oraya breakpoint koymak pek yararlı olmazdı
      En azından videoda böyle açıklıyordu
    • Derleyici bazen sistem çağrısı sarmalayıcılarını inline edebildiği için bunu statik olarak doğrulamak o kadar kolay değil
      Aynı nedenle SVC komutunu ararsanız çok fazla sonuç çıkar
      X16’ya taşınan tam sistem çağrısı ID’sini bulursanız doğrudan yakalayabilirsiniz
  • Yazının yazarıyım. Sorular varsa yanıtlayabilirim. Paylaştığı için xmprt’ye teşekkürler

    • YouTube’da videoyu izledim; ilgi çekiciydi
      Yazılı sürümünü de sunman iyi olmuş
    • Çok ilginç bir yazıydı; bu tür düşük seviyeli telefon tersine mühendisliği yazılarını her zaman görmek istiyorum
      Yazara birkaç şey sormak isterim: En bilinen ticari araç gerçekten Guardsquare ise, bu tarz kolay disassembly’yi engelleyen yeni bir şey sunduğunu düşünüyor musun?
      TopWidgets’ın buna benzer bir koruma kullanıp kullanmadığını, yoksa kendi yaptığı seviyede bir şey mi olduğunu da merak ediyorum
    • Videolar çok ilginç; daha fazla kişinin izlememiş veya yazıyı okumamış olmasına şaşırdım
      Kişisel olarak Android kullandığım için teknik olarak doğrudan uygulanabilir değil, ama iOS’ta düşük seviyeli hata ayıklamanın nasıl çalıştığını öğrenmekten yine de çok değer elde ediyorum
    • iOS’ta PTRACE_SYSCALL gibi sistem çağrısı giriş noktasına takılıp dönüş değerini değiştirebilen ya da SVC’nin nerede gerçekleştiğini algılayabilen bir özellik olup olmadığını merak ediyorum
  • En üstteki video, şimdiye kadar gördüğüm programlama videoları arasında en üst seviyedekilerden biri
    Akışı hızlı, tam kararında ön bilgi varsayıyor ve videonun temposunu bozmayan harika demolar içeriyor

  • Harika bir yazı
    Bunun aşırı paranoyak normal bir uygulama mı, yoksa en başından kötü amaçlı yazılım olduğundan şüphelenildiği için mi debug edilen bir uygulama olduğunu gerçekten merak ediyorum
    Öyle değilse harcanan çaba epey abartılı görünüyor

    • Benim değerlendirmeme göre daha çok sadece aşırı paranoyak bir uygulama
      Widget’larla oldukça havalı işler yapıyor, sanırım bunu korumaya çalışmış. Ancak bu tür stratejiler de zaten yavaş yavaş sızmaya başlamıştı
      Binary içinde ilginç şeyler de vardı
      Bir ara neden Windows .iso indiriyor gibi görünen bir koda baktığımı anlamaya çalıştım; meğer gerçekten öyleymiş ve ağ hızı testi widget’ında kullanılıyormuş
    • Ya da uygulamanın kendisi başka logolar vb. ile yeniden derlenmişse telif hakkı ihlalini kanıtlamaya çalışıyor olabilirlerdi
  • “PT_DENY_ATTACH’i atlatmak (zor mod)”dan daha zor bir mod da var
    Eskiden macOS’ta kernel’i patch’leyerek PT_DENY_ATTACH’in hiçbir şey yapmamasını sağlamıştım
    Mac’te patch’lenmiş bir kernel çalıştırmak aslında oldukça kolay sayılır, ama iOS’ta KTRR gibi şeyler yüzünden bunun çok daha zahmetli olacağını düşünüyorum
    XNU teknik olarak açık kaynak olsa da yeniden derlemektense patch’i hex editörle uygulamak daha kolaydı

    • kernel task port kullanarak proc yapısındaki biti de çevirebilirsiniz
      İmzasız kod sayfalarına ve RWX’e izin vererek JIT’i de mümkün kılabilirsiniz
  • “Jailbreak açıkken çalıştırınca tüm telefon çöküyor” ise, bunu mağazaya kötü amaçlı yazılım olarak bildirmek gerekmez mi?
    Telefonu çökertmek açıkça kötü amaçlı yazılım davranışı; ayrıca saklamaya çalıştığı başka hangi kötü niyetli eylemler olabileceğinden de şüphelenmek gerekir
    Apple’ın kapalı ekosistem gerekçesi bu tür çöpleri engellemek değil miydi?

    • “Jailbreak açıkken” demek kapalı ekosistemin dışında demektir
      Apple’ın jailbreak’li telefonda uygulamanın çökmesini pek umursayacağını sanmıyorum
  • com.apple.tw.twrr bildirimi gerçekten merak uyandırıcı
    Neden com.apple ile başlıyor?
    Buradaki söz konusu uygulama Apple uygulaması değil, Top Widgets adlı uygulama gibi görünüyor

    • Bildirim adı rastgele bir dizedir
      Çakışmaları önlemek için bu tür “tam ad” kullanmak gelenektir
      Bu durumda geliştirici tesadüfen böyle bir önek seçmiş gibi görünüyor
  • Araçlar farklı olsa da bu, 1980’lerde boot tracing ile Apple II kopya korumasını kırmakla tamamen aynı his
    Bazı şeyler değişmiyor