Üç platformun da native bağlantı noktalarını buldum: cihaz kaydının nereden başladığını, güvenlik SDK'sının isteği hangi katmanda yakaladığını, native interceptor'ın dışarı giden paketi nasıl yeniden yazdığını ve JNI'ın RegisterNatives ile çalışma zamanına hangi metotları dinamik olarak kaydettiğini çıkardım. Frida script'i bağlandı, loglar akmaya başladı, bütün hook'lar tutarlı biçimde çalışıyordu. Ardından komut kataloğunu açıp bu üç platform için çağrılabilir native uygulama endpoint'lerini saydım: sıfır.
Aynı projedeki başka bir platformdaysa sayı 11'di. Sahada doğrulanmış, koda taşınmış ve birinci sınıf komutlar olarak çalışan 11 endpoint.
Aradaki fark hook tekniği değil. Tüm hook'lar çalışıyor, bağlantı şeması da eksiksiz. Fark, çoğu kişinin fark etmediği bir eşikte yatıyor. Bir hook'un tutması ile bir yeteneğin gerçekten kullanılabilir olması arasında bir kanıt seviyesi bulunuyor. Bu yazıda o eşiğin nasıl belirleneceğini, yarım kalmış bir endpoint yayınlamak yerine neden "henüz kullanılamıyor" demenin daha az maliyetli olduğunu ve modelin bu süreçte gerçekte ne işe yaradığını ele alacağım.
Hook'un çalışması, endpoint'in kullanılabilir olduğu anlamına gelmez
Uygulama tersine mühendisliğiyle uğraşanlar için "hook tuttu" anı çoğu zaman bitiş çizgisi gibi görünür. Script hedef metoda bağlanır; logda argümanları, dönüş değerini ve çağrı yığınını görürsünüz. O "içeri girdim" hissi son derece gerçektir; ama aynı ölçüde yanıltıcıdır.
Komut kataloğu ise "içeri girdim" kabul etmez. Şunu kabul eder: Normal bir girdi verildiğinde bu komut, aşağı akışın tüketebileceği doğru yapıda ve boş olmayan bir payload'ı güvenilir biçimde üretebiliyor mu? Bu iki nokta arasında ciddi bir mesafe var.
Tipik çöküş senaryosu şöyle ilerler: Tüm hook'lar tutar, bağlantı tamamlanmıştır; hatta cihaz kayıt isteğinin çıktığını, güvenlik SDK'sının değerini hesapladığını ve native interceptor'ın imza header'ını eklediğini logdan izlersiniz. Her şey doğru görünür. Sonra gerçek cihazda çalıştırırsınız; cihaz kaydı sıfır değerli bir device ID döndürür ya da detay endpoint'i boş gövdeyle gelir. Bağlantı açıktır, veri boştur.
Bu noktada elinizde ne vardır? Uygulamanın belirli bir sürümündeki iç davranışı gözlemleyebilen bir dizi probe. Elinizde olmayan şeyse çağrılabilir bir endpoint'tir. Birincisini ikincisiymiş gibi yayınlarsanız, sizden sonra gelen herkes için gizli bir mayın döşemiş olursunuz.
11'e karşı 0: farkı yaratan kontrol grubu
İki platform grubunu yan yana koyduğunuzda eşik kendini açıkça gösteriyor.
Kontrol platformu (bir video topluluk uygulaması) | Önde gelen üç içerik uygulaması | |
|---|---|---|
Hook bağlantısı | Bulundu ve sahada doğrulandı | Tümü bulundu, tüm hook'lar çalışıyor |
Gerçek kurulum durumu | Sıfır olmayan cihaz kimliği alındı | Sıfır device ID / gerçek cihaz profili yok |
Boş olmayan yanıt | Yapılandırılmış detay verisi | Boş detay / boş gövde |
Komut kataloğundaki sayı | 11 | 0 |
Kontrol platformundaki bu 11 endpoint, "daha iyi hook'lar" değil. Her biri birinci sınıf Python komutuna taşınmadan önce bir sonraki bölümdeki dört kanıt eşiğini geçti ve yapılandırılmış doğrulama kanıtlarıyla birlikte sisteme alındı.
Diğer üç platformda da çalışma yapılmadığı söylenemez. Güvenlik SDK'sının interception katmanı, native request interceptor ve JNI'ın dinamik kaydettiği metot grubu çözüldü; Frida hook'ları hâlâ yerinde. Ancak gerçek kurulum durumu geçerli olmadığı, cihaz kaydından sıfır olmayan bir kimlik alınamadığı sürece sonraki her şey boş kalıyor. Bu nedenle native uygulama komutlarının sayısı dürüstçe 0 olarak kalıyor; şu anda kullanılabilen yol ise tamamen ayrı olan Web veya tarayıcı taşıma katmanı.
Genel tabloda bu mobil yetenek grubunun toplamı 32. Bunların 23'ü gerçekten implementasyona dönüştü; kalan 9'u ise "gerçek cihaz profili bekleniyor" aşamasında ve hiçbiri erken biçimde kataloğa alınmadı. Buradaki 9 sayısı başarısızlık değil, disiplindir. "Bağlantıyı anladık, ancak kanıt yeterli değil" alanının tam boyutunu gösterir.
Komut kataloğuna girmek için dört kanıt eşiği
Karşılaştırmayı parçaladığınızda, bir uygulama yeteneğinin komut kataloğuna girebilmesi için dört koşulu da karşılaması gerekir. Bir tanesi bile eksikse kataloğa girmez.
1. Gerçek kurulum durumu. İstek, üst sistemin tanıyacağı sıfır olmayan bir kurulum kimliğinden gelmelidir. Emülatörde ya da bozuk profilde hook'un çalışması yeterli değildir. Cihaz kaydının sıfır değerli bir ID dönmesi, bu kapının geçilemediğini gösterir; bundan sonra bağlantının ne kadar eksiksiz olduğu fark etmez, çıktı boştur. Üç platformun da takıldığı ortak nokta buydu.
2. Boş olmayan yanıt. Açık olması, veri olduğu anlamına gelmez. İstek gider, durum kodu 200 gelir, gövde ise boştur. Bu "başarılı ama boş yanıt", hatadan daha tehlikelidir; çünkü yalnızca exception atılıp atılmadığını denetleyen tüm kontrollerden sıyrılır. Eşiğin istediği şey, doğrudan aşağı akışa verilebilecek yapılandırılmış, eksiksiz ve boş olmayan veridir.
3. Eksiksiz hata sınıflandırması. Olgun bir yetenek başarısız olduğunda genel bir hata fırlatmak yerine neden başarısız olduğunu söylemelidir. Sayfa yok, oturum açılmamış, runtime hazır değil, yanıt boş: Bunlar tamamen farklı nedenlerdir ve tek bir hata altında ezilmek yerine ayırt edilebilir hata kodlarına sahip olmalıdır. Yalnızca "başarısız oldu" diyebilen bir komut kataloğa hazır değildir; çünkü çağıran tarafın yeniden denemesi, yeniden kimlik doğrulaması yapması ya da işlemi atlaması gerekip gerekmediğini belirlemesine imkân vermez.
4. Kapalı devre, tekrarlanabilir test. Bir kez şans eseri başarılı olmak, yetenek sahibi olduğunuz anlamına gelmez. Aynı girdi ve aynı akışın tekrar tekrar çalışması; bu başarının saklanan, yapılandırılmış doğrulama kanıtına dönüştürülmesi gerekir. Bir çalışıp sonraki sefer boş dönüyorsa bağlantıyı henüz kontrol etmiyorsunuzdur; yalnızca bir kez runtime durumuyla denk gelmişsinizdir.
Dördü de kapanırsa komut kataloğuna kaydedilir. Bunlardan biri açık kaldığında yetenek hâlâ bir araştırma varlığıdır, endpoint değildir. Bu iki kelime arasındaki fark, yazının tamamındaki temel ayrımdır.
Frida logu büyüdüğünde işi model katmanlarına bölün
Bu dört eşiğin hangisinde takıldığını anlamak için gereken ham malzeme, Frida'nın ürettiği trace'tir. Frida trace'i ise hızla devasa boyutlara ulaşır. Birkaç düzine metoda bağlanıp tek bir tam akışı çalıştırdığınızda on binlerce, hatta yüz binlerce satır görmek normaldir. Bunların büyük bölümü polyfill, heartbeat ve ilgisiz iş modüllerinden gelen gürültüdür.
Tüm bu veriyi tek bir modele verip "bu hook neden veri alamadı?" diye sorarsanız genel geçer bir tahmin alırsınız. Context büyüdükçe modelin alakasız iki çağrı segmentini birbirine bağlama ihtimali de artar. Doğru yöntem, trace'i parçalara ayırmak ve farklı bölümleri ihtiyaç duydukları yeteneğe göre farklı model katmanlarına vermektir.
Bu adım, "en güçlü modeli seçip her işte kullanın" yaklaşımının değil, katmanları birlikte kullanmanın ders kitabı örneğidir. Dört iş, modelden birbirinden tamamen farklı yetenekler bekler:
Frida log işleme adımı | Gereken yetenek | Tercih | model id |
|---|---|---|---|
Tam çağrı zincirinin trace'ini tek seferde okumak | Uzun context, zincirin tamamını aynı anda okuyabilme | Kimi K3 |
|
On binlerce satırı etiketlemek (cihaz kaydı / ağ / kripto / gürültü) | Uygun maliyetli, yüksek eşzamanlılıkta binlerce çağrı | Claude Sonnet 5 |
|
Bir bağlantının dört eşikten hangisinde takıldığını değerlendirmek | Güçlü muhakeme, net karar verebilme | Claude Opus 5 |
|
İki trace'in ayrıştığı noktayı karşılaştırmak, yanıtın neden boş olduğunu açıklamak | Orta düzey muhakemeyle attribution, belirli satırlara dayanarak açıklama | GPT-5.6 Sol |
|
Özellikle etiketleme adımını vurgulamak gerekiyor. İş burada on binlerce satır içindeki gürültüyü ayıklamak, yalnızca cihaz kaydı, kripto ve ağ sınıflarını bırakmaktan ibaret; hacim bunu elle yapamayacak kadar yüksek. Bu "çok yüksek frekansta basit karar" işi, uygun maliyetli katmanın tam alanıdır. Bunu muhakeme katmanında çalıştırmak doğrudan para israfıdır. Log birkaç yüz etiketli satıra sıkıştırıldıktan sonra "hangi eşikte takıldı?" değerlendirmesi için muhakeme katmanına verin; hem maliyet hem de hassasiyet yerli yerine oturur.
Bu ayrımın etkisini görmek için tek bir tur çalıştırmanız yeterli:
Tek bir akıştan birkaç bin ila on binlerce satır içeren bir trace segmenti kesin.
Önce
claude-sonnet-5ile parçalar hâlinde etiketleyin; gürültü satırlarını ayıklayıp cihaz kaydı, kripto ve ağ sınıflarını koruyun.Etiketlenmiş özeti
claude-opus-5'e verin ve "bu bağlantının şu anda dört eşikten hangisinde takıldığını, ayrıca kanıtın işaret ettiği satırları" çıkarmasını isteyin.Kontrol için aynı ham trace'i tek parça hâlinde tek bir modele verin ve aynı soruyu sorun.
Tek bir şeye bakın: Genel bir tahmin mi veriyor, yoksa belirli bir eşiğe ve belirli satırlara mı iniyor? Seçim ölçütünüz bu farktır.
Hook bir signer değil, sürüme bağlı gözlem probe'udur
Bu üç platformdaki hook'lar neden korunuyor ama komut kataloğunun dışında tutuluyor? Çünkü hook bir probe'dur, signer değildir; bu ikisi doğası gereği birbirinden farklıdır.
Bir hook, uygulamanın belirli bir build'ine, örneğin 32.x sürümüne bağlıdır. Dayandığı semboller, offset'ler ve metot yerleşimi bu sürüme aittir. Üst sistem yeni sürüm yayınladığında her şey kayar ve hook anında bozulur. Doğası gereği geçicidir ve sürüme bağımlıdır. Yanıtladığı soru şudur: "Bu sürüm şu anda içeride ne yapıyor?" Bu bir gözlem sorusudur. Enstrümantasyon araçları zaten bunun içindir: Frida dokümantasyonu, Interceptor'ı çağrıları çalışma zamanında gözlemlemek ve yeniden yazmak için bir araç olarak tanımlar. Bir fonksiyonun nasıl çağrıldığını ve argümanlarını görmenizi sağlar; ancak tek başına "girdiden imza hesaplayan" teslim edilebilir bir çözüm değildir.
Endpoint kataloğuna girecek signer ise tam tersidir: Kararlı, tekrarlanabilir, bağımsız ve CI'a uygun olmak zorundadır. Yanıtladığı soru "bana bir girdi ver, doğru imzayı hesaplayayım"dır; yani yeniden kullanılabilir yetenek sorusudur. Bir hook imza algoritmasının iskeletini çok net görünür kılıyor olsa bile, bu yalnızca algorithm-fingerprinting aşamasıdır. Bağımsız bir signer'a giden yolda hâlâ tam bir arındırma ve diferansiyel doğrulama süreci bulunur.
Bu durum, arındırma merdivenindeki sırayı da açıklar: Bir yetenek önce saf Python ile doğrudan bağlantı için mücadele etmeli, ardından yerel Node/V8 üzerinde minimal bir imza parçası çalıştırmaya düşmeli, pasif tarayıcı köprüsünü ise ancak isteksizce kabul etmelidir. Hook bu merdivende henüz yer almaz bile. Onun yeri "implementasyon" değil, ondan önceki "araştırma" aşamasıdır. Sürüme bağlı bir gözlem probe'unu signer olarak kaydetmek, yarım kalmış bir araştırma parçasına implementasyon etiketi asmaktır.
Araştırma varlığını çürütmeden arşivlemek
Bir hook'u endpoint kataloğunun dışında tutmak, onu çöpe atmak anlamına gelmez. İçinde bağlantı bilgisi, örnekler ve doğrulama kanıtları bulunan; uğruna gerçek emek harcanmış bir araştırma varlığıdır. Silmek net kayıptır. Mesele onu doğru arşivlemektir; aksi hâlde iki ay sonra siz bile tam olarak ne kadar ilerlediğinizi bilemezsiniz.
Bir uygulama araştırma varlığı en az şu dört şeyi kaydetmelidir:
Taşıma türü. Akışın native protokolde mi, yerel Node/V8 imzasında mı yoksa pasif tarayıcı köprüsünde mi çalıştığı. Bu bilgi, ileride ne kadar arındırılabileceğini belirler.
Kanıt seviyesi. Dört eşikten kaçının geçildiği. "Bağlantı bulundu" seviyesinde mi, "sıfır olmayan kurulum durumu alındı ama yanıt boş" noktasında mı, yoksa "yanıt boş değil fakat tekrarlanabilir değil" aşamasında mı? Sonraki kişiye kullanılabilir hâle gelmesinin önündeki engeli doğrudan bu bilgi anlatır.
Uygulama sürümü / build. Hook'un bağlı olduğu sürüm. Bu olmadan üst sistem güncelleme yaptığında sorunun yanlış yazılan koddan mı yoksa değişen build'den mi kaynaklandığını anlayamazsınız.
Örnek özeti. Bu çalıştırmadaki girdi ve çıktının nasıl göründüğü; hassas verileri ayıklanmış bir kopya olarak saklanmalı. Araştırmayı yeniden başlatırken en hızlı referans budur.
Bu dört bilgiyi kaydederseniz, 0 komutta kalan bir bağlantı süresi geçmiş loglardan oluşan bir yığın değil, ilerletilebilecek bir varlık olur. Aynı anda en kötü iki yaklaşımı da engeller: Hook'u silip araştırmayı hiç yapmamış gibi davranmayı veya onu zorla kataloğa koyup kullanılabilirmiş gibi göstermeyi. İkincisi özellikle maliyetlidir. "Çağrılabilir görünen ama aslında boş dönen" bir endpoint, maliyetini kataloğa güvenen her aşağı akış çağıranına yayar: Entegrasyonlarını buna göre yazarlar, retry mekanizmaları kurarlar, bir kez boş veriyle karşılaşırlar ve sonunda tüm kataloğa güvenlerini kaybederler. "Araştırma varlığı, 0 komut" diye dürüstçe işaretlenmiş bir boşluk ise yalnızca size, README'deki tek satırda ve bir kez maliyet çıkarır.
İçi boş bir yapı, bir boşluktan daha pahalıdır; bunu görmek için bundan daha net bir alan yok.
Tek anahtarla log bölme işinin sürtünmesini azaltın
Dördüncü bölümdeki log ayrımına dönelim: Tüm trace'i okumak için uzun context, toplu etiketleme için uygun maliyetli katman, sınıflandırma için muhakeme katmanı, attribution için orta muhakeme katmanı. Birkaç sağlayıcıdan dört katman; dört SDK, dört kimlik doğrulama şeması ve dört hata formatı demek. Çoğu kişi dört istemciyle Frida logu sınıflandırmanın maliyet hesabını yapar, buna değmeyeceğine karar verir ve sonunda yüz binlerce trace satırını tek modelle işlemeye çalışır. Ya para yakar ya da işi tamamlayamaz.
AIReiter bu sürtünmeyi ortadan kaldırıyor: Tek anahtar, OpenAI uyumlu tek arayüz, arkasında dört katmanın tamamı. İstek gövdesindeki model alanını değiştirmeniz katman değiştirmek için yeterli.
# Logu etiketle: uygun maliyetli katman, yüksek eşzamanlılıkta binlerce çağrı
curl https://aireiter.com/api/v1/chat/completions \
-H "Authorization: Bearer $AIREITER_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "claude-sonnet-5",
"messages": [{"role": "user", "content": "<one chunk of trace + labeling instruction>"}]
}'
# Eşiği sınıflandır: muhakeme katmanına geç, diğer her şeyi aynı bırak
# "model": "claude-opus-5"
# Tüm çağrı zincirini oku: uzun-context katmanı
# "model": "kimi-k3"
# Yanıt farkının kaynağını belirle:
# "model": "gpt-5.6-sol"
Zaten OpenAI SDK kullanıyorsanız base_url değerini https://aireiter.com/api/v1 olarak ayarlayın; başka hiçbir şeyi değiştirmeniz gerekmez. Anthropic SDK'da ise aynı anahtarla POST /api/v1/messages endpoint'ine istek atın.
Bu yazıdaki maliyet yapısı dengesiz ve indirim tam da bu dengesiz kısmı hedefliyor. Tek bir bağlantının trace'i on binlerce ila yüz binlerce satır sürer; etiketleme parça parça yapılır ve tek platform yüzlerce ya da binlerce claude-sonnet-5 çağrısına ulaşır. Maliyetin büyük bölümü buradadır. Tüm trace'i okuyan uzun-context çağrıları, girdi başına birkaç yüz bin token ile ikinci büyük maliyet kalemidir. Sınıflandırma ve attribution ise daha yüksek birim fiyatlı ancak sayıca az çağrılardır. Claude için %30 indirim, en pahalı iki bölüm olan etiketleme ve eşik sınıflandırmasına doğrudan denk geliyor. GPT'deki yarı fiyat ise attribution katmanına yarıyor. Uzun-context okuma Kimi K3 üzerinde çalışıyor ve aynı anahtarla çağrılabiliyor.
Kayıt olmadan deneyin: Bir trace segmentini etiketlemesi için
claude-sonnet-5'e verin, ardındanclaude-opus-5'in bunu sınıflandırmasını isteyin. Entegrasyonu yapmaya karar vermeden önce hangi eşikte takıldığını doğrudan gösterebiliyor mu, bakın.
Sonuç
Uygulama tersine mühendisliğinde hook'un tutması size şu gözlem yeteneğini verir: "Bu sürümün içeride ne yaptığını görebiliyorum." Endpoint kataloğunun istediği ise şu çağrı yeteneğidir: "Bana bir girdi verin, güvenilir biçimde boş olmayan ve doğru veriyi üreteyim." Bu ikisinin arasında dört kanıt eşiği bulunur: gerçek kurulum durumu, boş olmayan yanıt, hata sınıflandırması ve tekrarlanabilir test.
Üç platformun bağlantısı tamamen bulunmuş, tüm hook'lar çalışıyor ama komut sayısı hâlâ 0: Bu başarısızlık değil, disiplindir. Gerçek kurulum durumu geçmiyorsa dürüstçe 0'da durur, hook'u araştırma varlığı olarak arşivler ve cihaz profili hazır olduğunda çalışmayı ilerletirsiniz.
Modelin bu akıştaki yeri nettir. Yüz binlerce trace satırını sizin için böler, etiketler, sınıflandırır ve kaynak ataması yapar; "bu bağlantı nerede takıldı?" sorusunu bir öğleden sonralık log okuma işinden birkaç dakikaya indirir. Ancak "eşik geçildi mi?" kararı, tıpkı diferansiyel testteki "hipotez doğru mu?" kararı gibi, en sonunda modele bırakılmaz. Kararı sizin koyduğunuz dört ölçüt ve tekrarlanabilir biçimde işleyen kanıt verir. Modelin tüm tersine mühendislik iş akışında doğru yere nasıl konumlandırılacağı ise dört aşamalı genel bakışta anlatılıyor.