diff --git a/.gitignore b/.gitignore index 77edd91a0..ca8613877 100644 --- a/.gitignore +++ b/.gitignore @@ -11,3 +11,4 @@ book book/* hacktricks-preprocessor.log hacktricks-preprocessor-error.log +searchindex.js diff --git a/src/binary-exploitation/ios-exploiting/ios-physical-uaf-iosurface.md b/src/binary-exploitation/ios-exploiting/ios-physical-uaf-iosurface.md index 08c4b7eaa..e12b4a8a5 100644 --- a/src/binary-exploitation/ios-exploiting/ios-physical-uaf-iosurface.md +++ b/src/binary-exploitation/ios-exploiting/ios-physical-uaf-iosurface.md @@ -3,95 +3,108 @@ {{#include ../../banners/hacktricks-training.md}} +## iOS Exploit Mitigations + +- **Code Signing** iOS'ta çalıştırılacak her yürütülebilir kod parçasının (uygulamalar, kütüphaneler, uzantılar vb.) Apple tarafından verilen bir sertifika ile kriptografik olarak imzalanmasını gerektirir. Kod yüklendiğinde, iOS dijital imzayı Apple’ın güvenilen köküyle doğrular. İmza geçersizse, eksikse veya değiştirilmişse, işletim sistemi kodun çalışmasına izin vermez. Bu, saldırganların meşru uygulamalara kötü amaçlı kod enjekte etmesini veya imzasız ikili dosyaları çalıştırmasını engeller. +- **CoreTrust** çalışma zamanında code signing'i zorlayan iOS alt sistemidir. Apple’ın kök sertifikasını kullanarak imzaları doğrudan doğrular; önbelleğe alınmış güven depolarına dayanmaz; bu da yalnızca Apple tarafından imzalanmış (veya geçerli yetkilerle) ikililerin çalışabilmesini sağlar. CoreTrust, bir saldırgan uygulamayı kurulum sonrası değiştirmiş olsa da, sistem kitaplıklarını bozmuş olsa da veya imzasız kod yüklemeye çalışsa da yürütmeyi engeller. +- **Data Execution Prevention (DEP)** bellek bölgelerini açıkça kod içermedikçe yürütülemez olarak işaretler. Bu, saldırganların yığın veya heap gibi veri bölgelerine shellcode enjekte edip çalıştırmasını engeller ve onları ROP gibi daha karmaşık tekniklere zorlar. +- **ASLR (Address Space Layout Randomization)** kod, kütüphaneler, stack ve heap adreslerini her çalıştırmada rastgeleleştirir. Bu, saldırganların işe yarar talimatların veya gadget'ların nerede olduğunu tahmin etmelerini zorlaştırır. +- **KASLR (Kernel ASLR)** aynı rastgeleleştirme konseptini iOS kerneline uygular. Kernel’in temel adresini her açılışta karıştırarak, saldırganların kernel fonksiyonlarını veya yapıları güvenilir şekilde bulmasını zorlaştırır. +- **Kernel Patch Protection (KPP)** iOS’ta **AMCC (Apple Mobile File Integrity)** olarak da bilinir; kernel’in kod sayfalarını sürekli izleyerek değişiklik yapılmadığından emin olur. Kernel fonksiyonlarını yamalamaya veya kötü amaçlı kod eklemeye çalışan herhangi bir müdahale tespit edilirse cihaz derhal panic yapar ve yeniden başlatılır. Bu, sürekli kernel exploit'lerini zorlaştırır çünkü saldırganlar kernel talimatlarını hook'lamadan veya yama yapmadan bunu başaramaz. +- **Kernel Text Readonly Region (KTRR)** iOS cihazlarında donanımsal bir güvenlik özelliğidir. CPU’nun bellek denetleyicisini kullanarak kernel’in kod (text) bölümünü önyüklemeden sonra kalıcı olarak salt okunur yapar. Bir kez kilitlendikten sonra, kernel bile bu bellek bölgesini değiştiremez. Bu, kernel kodunun çalışma zamanında değiştirilmesini engeller. +- **Pointer Authentication Codes (PAC)** işaretçilerin kullanılmadan önce bütünlüğünü doğrulamak için işaretçilerin kullanılmayan bitlerine gömülü kriptografik imzalar kullanır. Bir işaretçi oluşturulduğunda CPU onu gizli bir anahtarla imzalar; dereference edilmeden önce CPU imzayı kontrol eder. İşaretçi değiştirilmişse kontrol başarısız olur ve yürütme durur. Bu, saldırganların bellek bozulması exploit'lerinde sahte veya değiştirilmiş işaretçiler kullanmasını zorlaştırır. +- **Privilege Access never (PAN)** kernel’in (ayrıcalıklı mod) kullanıcı alanı belleğine doğrudan erişmesini engelleyen bir donanım özelliğidir; erişimi açıkça etkinleştirmedikçe erişim yoktur. Bu, kernel kod yürütmesini ele geçiren saldırganların kullanıcı belleğini kolayca okuyup yazmasını, ayrıcalık yükseltmelerini veya hassas verileri çalmalarını zorlaştırır. +- **Page Protection Layer (PPL)** code signing ve entitlements ile ilişkili kritik kernel yönetimli bellek bölgelerini koruyan bir iOS güvenlik mekanizmasıdır. MMU ve ek kontroller kullanarak sıkı yazma koruması uygular, böylece ayrıcalıklı kernel kodu bile hassas sayfaları keyfi olarak değiştiremez. Bu, kernel seviyesi yürütme kazanan saldırganların güvenlik kritik yapıların üzerinde değişiklik yapmasını zorlaştırır. + ## Physical use-after-free -Bu, [https://alfiecg.uk/2024/09/24/Kernel-exploit.html](https://alfiecg.uk/2024/09/24/Kernel-exploit.html) adresindeki gönderiden bir özet olup, bu teknikle ilgili daha fazla bilgiye [https://github.com/felix-pb/kfd](https://github.com/felix-pb/kfd) üzerinden ulaşılabilir. +Bu özet [https://alfiecg.uk/2024/09/24/Kernel-exploit.html](https://alfiecg.uk/2024/09/24/Kernel-exploit.html) adresindeki gönderiden alınmıştır; ayrıca bu tekniği kullanan exploit hakkında daha fazla bilgi için {#ref}https://github.com/felix-pb/kfd{#endref} bakılabilir. -### XNU'de Bellek Yönetimi +### Memory management in XNU -iOS'teki kullanıcı süreçleri için sanal bellek adres uzayı **0x0 ile 0x8000000000** arasındadır. Ancak bu adresler doğrudan fiziksel belleğe eşlenmez. Bunun yerine **kernel**, sanal adresleri gerçek **fiziksel adreslere** çevirmek için **sayfa tabloları** kullanır. +Kullanıcı süreçleri için **virtual memory address space**, iOS'ta **0x0 ile 0x8000000000** arasında yer alır. Ancak bu adresler fiziksel belleğe doğrudan eşlenmez. Bunun yerine **kernel**, sanal adresleri gerçek **physical addresses**'e çevirmek için **page tables** kullanır. -#### iOS'te Sayfa Tablosu Seviyeleri +#### Levels of Page Tables in iOS -Sayfa tabloları hiyerarşik olarak üç seviyede düzenlenir: +Page table'lar üç seviyeli hiyerarşik olarak düzenlenmiştir: 1. **L1 Page Table (Level 1)**: -* Buradaki her giriş sanal belleğin büyük bir aralığını temsil eder. +* Her giriş burada geniş bir sanal bellek aralığını temsil eder. * **0x1000000000 bytes** (veya **256 GB**) sanal belleği kapsar. 2. **L2 Page Table (Level 2)**: -* Buradaki bir giriş daha küçük bir sanal bellek bölgesini, spesifik olarak **0x2000000 bytes** (32 MB) temsil eder. -* Bir L1 girişi tüm bölgeyi kendi başına eşleyemiyorsa bir L2 tablosuna işaret edebilir. +* Buradaki bir giriş daha küçük bir sanal bellek bölgesini, özellikle **0x2000000 bytes** (32 MB) temsil eder. +* Bir L1 girişi tüm bölgeyi kendisi eşleyemiyorsa bir L2 tablosuna işaret edebilir. 3. **L3 Page Table (Level 3)**: -* En ince seviye budur; her giriş tek bir **4 KB** bellek sayfasını haritalar. -* Daha ayrıntılı kontrol gerektiğinde bir L2 girişi L3 tablosuna işaret edebilir. +* En ince seviyedir; her giriş tek bir **4 KB** bellek sayfasını eşler. +* Daha ayrıntılı kontrol gerekirse L2 girdisi bir L3 tablosuna işaret edebilir. -#### Sanalden Fiziksele Haritalama +#### Mapping Virtual to Physical Memory * **Direct Mapping (Block Mapping)**: - * Sayfa tablosundaki bazı girişler sanal adreslerin bir aralığını doğrudan fiziksel adreslerin bitişik bir aralığına eşler (kısayol gibi). +* Bazı page table girişleri sanal adreslerin bir aralığını bitişik bir fiziksel adres aralığına doğrudan eşler (kısayol gibi). * **Pointer to Child Page Table**: - * Daha ince kontrol gerekiyorsa, bir seviyedeki bir giriş (ör. L1) bir alt seviye sayfa tablosuna (ör. L2) işaret edebilir. +* Daha ince kontrol gerekiyorsa, bir seviyedeki giriş (ör. L1) bir sonraki seviyedeki **child page table**'a işaret edebilir (ör. L2). -#### Bir Sanal Adresin Haritalanması Örneği +#### Example: Mapping a Virtual Address -Diyelim ki **0x1000000000** sanal adresine erişmeye çalıştınız: +Örneğin sanal adres **0x1000000000**'a erişmeye çalıştığınızı varsayalım: 1. **L1 Table**: -* Kernel bu sanal adrese karşılık gelen L1 girişini kontrol eder. Eğer bir **L2 page table** işaretçisine sahipse, o L2 tablosuna gider. +* Kernel bu sanal adrese karşılık gelen L1 page table girişini kontrol eder. Eğer giriş bir **pointer to an L2 page table** gösteriyorsa, o L2 tablosuna gider. 2. **L2 Table**: -* Kernel daha ayrıntılı bir eşleme için L2 sayfa tablosunu kontrol eder. Eğer bu giriş bir **L3 page table** işaret ediyorsa, oraya ilerler. +* Kernel daha ayrıntılı bir eşleme için L2 page table'ı kontrol eder. Eğer bu giriş bir **L3 page table**'a işaret ediyorsa, oraya gider. 3. **L3 Table**: -* Kernel son L3 girişine bakar; bu giriş gerçek bellek sayfasının **fiziksel adresine** işaret eder. +* Kernel son L3 girişine bakar; bu giriş gerçek bellek sayfasının **physical address**'ine işaret eder. -#### Adres Haritalama Örneği +#### Example of Address Mapping -Eğer L2 tablosunun ilk indeksine fiziksel adres **0x800004000** yazarsanız: +Eğer fiziksel adres **0x800004000**'ı L2 tablosunun ilk indeksine yazarsanız, o zaman: * **0x1000000000** ile **0x1002000000** arasındaki sanal adresler **0x800004000** ile **0x802004000** arasındaki fiziksel adreslere eşlenir. * Bu, L2 seviyesinde bir **block mapping**'dir. -Alternatif olarak, L2 girişi bir L3 tablosuna işaret ediyorsa: +Alternatif olarak L2 girişi bir L3 tablosuna işaret ederse: -* **0x1000000000 -> 0x1002000000** sanal adres aralığındaki her 4 KB sayfa, L3 tablosundaki bireysel girişler tarafından haritalanır. +* **0x1000000000 -> 0x1002000000** aralığındaki her 4 KB sayfa, L3 tablosundaki bireysel girişlerle eşlenecektir. ### Physical use-after-free -Bir **physical use-after-free (UAF)** şu durumda oluşur: +Bir **physical use-after-free (UAF)** şu durumda meydana gelir: -1. Bir süreç belleği **okunabilir ve yazılabilir** olarak **ayırır**. -2. Bu belleği sürecin erişebileceği belirli bir fiziksel adrese eşlemek için **sayfa tabloları** güncellenir. -3. Süreç belleği **serbest bırakır (free)**. -4. Ancak bir **bug** nedeniyle kernel, ilgili fiziksel belleği serbest olarak işaretlese bile sayfa tablolarından bu **eşlemeyi kaldırmayı unutur**. -5. Kernel daha sonra bu "serbest" fiziksel belleği başka amaçlarla, örneğin **kernel verisi** için **yeniden ayırabilir**. -6. Eşleme kaldırılmadığı için süreç yine de bu fiziksel belleği **okuyup yazabilir**. +1. Bir süreç bazı belleği **readable and writable** olarak **allocate** eder. +2. Bu belleği sürecin erişebileceği belirli bir fiziksel adrese eşlemek için **page tables** güncellenir. +3. Süreç belleği **deallocate** (free) eder. +4. Ancak bir **bug** nedeniyle kernel, ilgili fiziksel belleği serbest olarak işaretlemesine rağmen page table’daki eşlemeyi **kaldırmayı unutur**. +5. Kernel daha sonra bu “serbest” fiziksel belleği başka amaçlar için, örneğin **kernel data** gibi, **reallocate** edebilir. +6. Eşleme kaldırılmadığı için süreç bu fiziksel belleği hâlâ **read ve write** edebilir. -Bu, sürecin içinde bulunduğu sayfalar vasıtasıyla **kernel belleğine** erişebileceği anlamına gelir; bu bellek hassas veri veya yapılar içerebilir ve saldırganın **kernel belleğini manipüle etmesine** olanak sağlayabilir. +Bu, sürecin **kernel belleği sayfalarına** erişebilmesi anlamına gelir; bu sayfalar hassas veri veya yapılar içerebilir ve saldırganın **kernel belleğini manipüle etmesine** olanak verebilir. ### IOSurface Heap Spray -Saldırganın hangi spesifik kernel sayfalarının serbest belleğe atanacağını kontrol edememesi nedeniyle, bir teknik olan **heap spray** kullanılır: +Saldırgan hangi kernel sayfalarının serbest belleğe atanacağını kontrol edemediği için, bir teknik olan **heap spray** kullanılır: -1. Saldırgan kernel belleğinde çok sayıda **IOSurface** nesnesi oluşturur. -2. Her IOSurface nesnesi alanlarından birinde bir **magic value** içerir, bu da onları tanımlamayı kolaylaştırır. -3. Serbest bırakılan sayfaları tarayarak bu IOSurface nesnelerinden herhangi birinin serbest bir sayfaya yerleşip yerleşmediğine bakarlar. -4. Bir serbest sayfada bir IOSurface nesnesi bulduklarında, bunu kullanarak **kernel belleğini okuyup yazabilirler**. +1. Saldırgan kernel belleğinde çok sayıda **IOSurface** object yaratır. +2. Her IOSurface objesi, tanımlanması kolay olması için bir alanında **magic value** içerir. +3. Serbest bırakılmış sayfaları **scan** ederek bu IOSurface objelerinden herhangi birinin serbest sayfaya düşüp düşmediğini kontrol ederler. +4. Bir IOSurface objesinin serbest sayfada olduğunu bulduklarında, bunu **kernel memory**'yi **read ve write** etmek için kullanabilirler. -Bu konu hakkında daha fazla bilgi için bakınız: [https://github.com/felix-pb/kfd/tree/main/writeups](https://github.com/felix-pb/kfd/tree/main/writeups) +Detaylı bilgi için {#ref}https://github.com/felix-pb/kfd/tree/main/writeups{#endref} bakılabilir. > [!TIP] -> iOS 16+ (A12+) cihazların donanımsal hafifletmeleri (PPL veya SPTM gibi) physical UAF tekniklerini büyük ölçüde daha az uygulanabilir hale getirdiğini unutmayın. -> PPL, code signing, entitlements ve hassas kernel verileriyle ilişkili sayfalara sıkı MMU korumaları uygular; bu yüzden bir sayfa yeniden kullanılsa bile userland veya ele geçirilmiş kernel kodundan PPL-korumalı sayfalara yapılan yazmalar engellenir. -> Secure Page Table Monitor (SPTM) PPL'yi sayfa tablosu güncellemelerini sertleştirerek genişletir. Bu, ayrıcalıklı kernel kodunun bile serbest bırakılmış sayfaları sessizce yeniden eşlememesini veya eşlemelerle oynamamasını sağlamak için güvenli kontroller gerektirir. -> KTRR (Kernel Text Read-Only Region), kernel'in kod bölümünü boot sonrası salt okunur hale kilitler. Bu, runtime'da kernel kodunun değiştirilmesini engelleyerek physical UAF exploitlerinin sıklıkla dayandığı büyük bir saldırı vektörünü kapatır. -> Ayrıca, `IOSurface` tahsisleri daha az öngörülebilir ve user-accessible bölgelere eşlemek daha zor hale geldi; bu da "magic value tarama" numarasını çok daha güvensiz kılar. Ve `IOSurface` artık entitlements ve sandbox kısıtlamaları ile korunur. +> iOS 16+ (A12+) cihazların PPL veya SPTM gibi donanımsal mitigasyonlar getirdiğini ve bunun physical UAF tekniklerini çok daha az uygulanabilir hale getirdiğini unutmayın. +> PPL, code signing, entitlements ve hassas kernel verileriyle ilişkili sayfalara MMU bazlı sıkı korumalar uygular; dolayısıyla bir sayfa tekrar kullanılsa bile, userland veya ele geçirilmiş kernel kodundan PPL korumalı sayfalara yazmalar engellenir. +> Secure Page Table Monitor (SPTM) PPL'yi genişleterek page table güncellemelerini sertleştirir. Bu, ayrıcalıklı kernel kodunun bile freed sayfaları sessizce yeniden eşlememesini veya mapping'lerle oynamamasını sağlar. +> KTRR kernel’in kod bölümünü önyüklemeden sonra salt okunur hale kilitleyerek runtime sırasında kernel kodunda herhangi bir değişikliği engeller. Bu, physical UAF exploit'lerinin sıklıkla dayandığı büyük bir saldırı vektörünü kapatır. +> Ayrıca, `IOSurface` alloc'ları artık daha öngörülemez ve kullanıcı erişimli bölgelere eşlemek zor olduğu için “magic value scanning” hilesi çok daha güvenilir değildir. Ve `IOSurface` artık entitlements ve sandbox kısıtlamalarıyla korunmaktadır. ### Step-by-Step Heap Spray Process -1. **Spray IOSurface Objects**: Saldırgan özel bir tanımlayıcı ("magic value") ile çok sayıda IOSurface nesnesi oluşturur. -2. **Scan Freed Pages**: Nesnelerden herhangi birinin serbest bir sayfaya atanıp atanmadığını kontrol ederler. -3. **Read/Write Kernel Memory**: IOSurface nesnesindeki alanları manipüle ederek kernel belleğinde **keyfi okuma ve yazma** yeteneği kazanırlar. Bu onlara şunları sağlar: -* Bir alanı kullanarak kernel belleğindeki herhangi bir 32-bit değeri **okuyabilme**. -* Başka bir alanı kullanarak 64-bit değerleri **yazabilme**, böylece kararlı bir **kernel read/write primitive** elde etme. +1. **Spray IOSurface Objects**: Saldırgan özel bir tanımlayıcı ("magic value") içeren çok sayıda IOSurface objesi oluşturur. +2. **Scan Freed Pages**: Bu objelerden herhangi birinin serbest bir sayfaya atanıp atanmadığını kontrol eder. +3. **Read/Write Kernel Memory**: IOSurface objesindeki alanları manipüle ederek, kernel belleğinde **arbitrary reads and writes** yapma yeteneği elde ederler. Bu onlara şunları sağlar: +* Bir alanı kullanarak kernel belleğindeki herhangi bir 32-bit değeri **read** edebilme. +* Başka bir alanı kullanarak 64-bit değerleri **write** edebilme; böylece kararlı bir **kernel read/write primitive** elde edilir. Generate IOSurface objects with the magic value IOSURFACE\_MAGIC to later search for: ```c @@ -114,7 +127,7 @@ io_connect_t id = result.surface_id; } } ``` -Bir serbest bırakılmış fiziksel sayfadaki **`IOSurface`** nesnelerini ara: +Bir serbest bırakılmış fiziksel sayfada **`IOSurface`** nesnelerini ara: ```c int iosurface_krw(io_connect_t client, uint64_t *puafPages, int nPages, uint64_t *self_task, uint64_t *puafPage) { io_connect_t *surfaceIDs = malloc(sizeof(io_connect_t) * 0x4000); @@ -150,23 +163,23 @@ return 0; ``` ### IOSurface ile Kernel Read/Write Elde Etme -Kullanıcı alanından erişilebilen serbest bırakılmış bir fiziksel sayfaya eşlenmiş kernel belleğindeki bir IOSurface nesnesi üzerinde kontrol elde ettikten sonra, bunu **arbitrary kernel read and write operations** için kullanabiliriz. +kernel belleğindeki bir IOSurface nesnesi üzerinde kontrol sağladıktan sonra (userspace'ten erişilebilen boşaltılmış bir fiziksel sayfaya maplenmiş), bunu **arbitrary kernel read and write operations** için kullanabiliriz. **Key Fields in IOSurface** IOSurface nesnesinin iki kritik alanı vardır: -1. **Use Count Pointer**: Allows a **32-bit read**. -2. **Indexed Timestamp Pointer**: Allows a **64-bit write**. +1. **Use Count Pointer**: Bir **32-bit read** sağlar. +2. **Indexed Timestamp Pointer**: Bir **64-bit write** sağlar. -Bu işaretçileri overwrite ederek, bunları kernel belleğindeki arbitrary adreslere yönlendirir ve read/write yeteneklerini mümkün kılabiliriz. +Bu pointer'ları overwrite ederek, onları kernel belleğindeki arbitrary adreslere yönlendirip read/write yetenekleri elde edebiliriz. #### 32-Bit Kernel Read -Okuma gerçekleştirmek için: +Okuma yapmak için: -1. **use count pointer**'ı hedef adres eksi 0x14 bayt offsetine işaret edecek şekilde overwrite edin. -2. `get_use_count` methodunu kullanarak o adresteki değeri okuyun. +1. **Use Count Pointer**'ı hedef adresin 0x14-byte offset eksiğine işaret edecek şekilde üzerine yazın. +2. `get_use_count` metodunu kullanarak o adresteki değeri okuyun. ```c uint32_t get_use_count(io_connect_t client, uint32_t surfaceID) { uint64_t args[1] = {surfaceID}; @@ -184,11 +197,11 @@ iosurface_set_use_count_pointer(info.object, orig); return value; } ``` -#### 64-Bit Çekirdek Yazma +#### 64-Bit Kernel Write -Yazma işlemini gerçekleştirmek için: +Bir yazma işlemi gerçekleştirmek için: -1. Hedef adrese **indekslenmiş zaman damgası işaretçisini** yeniden yazın. +1. Overwrite ederek **indexed timestamp pointer**'ı hedef adrese ayarlayın. 2. 64-bit bir değer yazmak için `set_indexed_timestamp` metodunu kullanın. ```c void set_indexed_timestamp(io_connect_t client, uint32_t surfaceID, uint64_t value) { @@ -203,13 +216,13 @@ set_indexed_timestamp(info.client, info.surface, value); iosurface_set_indexed_timestamp_pointer(info.object, orig); } ``` -#### Exploit Flow Recap +#### Exploit Akış Özeti -1. **Trigger Physical Use-After-Free**: Serbest bırakılmış sayfalar yeniden kullanım için mevcuttur. -2. **Spray IOSurface Objects**: Çekirdek belleğinde benzersiz bir "magic value" içeren çok sayıda IOSurface nesnesi tahsis edin. -3. **Identify Accessible IOSurface**: Kontrolünüzdeki serbest bırakılmış bir sayfada bulunan bir IOSurface'i tespit edin. -4. **Abuse Use-After-Free**: IOSurface yöntemleri aracılığıyla rastgele **kernel read/write** sağlamak için IOSurface nesnesindeki işaretçileri değiştirin. +1. **Trigger Physical Use-After-Free**: Serbest bırakılmış sayfalar yeniden kullanım için kullanılabilir. +2. **Spray IOSurface Objects**: Çekirdek belleğe benzersiz bir "magic value" içeren birçok IOSurface nesnesi ayırın. +3. **Identify Accessible IOSurface**: Kontrolünüzdeki serbest bırakılmış bir sayfada bir IOSurface bulun. +4. **Abuse Use-After-Free**: IOSurface nesnesindeki işaretçileri değiştirerek IOSurface yöntemleri aracılığıyla rastgele **kernel read/write** sağlayın. -With these primitives, the exploit provides controlled **32-bit reads** and **64-bit writes** to kernel memory. Further jailbreak steps could involve more stable read/write primitives, which may require bypassing additional protections (e.g., PPL on newer arm64e devices). +Bu primitiflerle exploit, çekirdek belleğe kontrollü **32-bit reads** ve **64-bit writes** sağlar. Daha ileri jailbreak adımları daha kararlı read/write primitifleri gerektirebilir; bu da ek korumaların (örn. daha yeni arm64e cihazlarda PPL) atlatılmasını gerektirebilir. {{#include ../../banners/hacktricks-training.md}} diff --git a/src/generic-methodologies-and-resources/phishing-methodology/detecting-phising.md b/src/generic-methodologies-and-resources/phishing-methodology/detecting-phising.md index 776cdc5f6..043b792a0 100644 --- a/src/generic-methodologies-and-resources/phishing-methodology/detecting-phising.md +++ b/src/generic-methodologies-and-resources/phishing-methodology/detecting-phising.md @@ -1,69 +1,147 @@ -# Phishing Tespit Etme +# Phishing Tespiti {{#include ../../banners/hacktricks-training.md}} ## Giriş -Bir phishing girişimini tespit etmek için **günümüzde kullanılan phishing tekniklerini anlamak önemlidir**. Bu gönderinin ana sayfasında bu bilgileri bulabilirsiniz, bu yüzden günümüzde hangi tekniklerin kullanıldığını bilmiyorsanız ana sayfaya gitmenizi ve en azından o bölümü okumanızı öneririm. +Bir phishing denemesini tespit etmek için günümüzde kullanılan phishing tekniklerini **anlamak** önemlidir. Bu yazının üst sayfasında bu bilgiyi bulabilirsiniz; bugün hangi tekniklerin kullanıldığından haberdar değilseniz, üst sayfaya gidip en azından o bölümü okumanızı öneririm. -Bu gönderi, **saldırganların bir şekilde kurbanın alan adını taklit etmeye veya kullanmaya çalışacakları** fikrine dayanmaktadır. Eğer alan adınız `example.com` ise ve bir şekilde tamamen farklı bir alan adı olan `youwonthelottery.com` kullanılarak phishing yapılıyorsa, bu teknikler bunu açığa çıkarmayacaktır. +Bu yazı, **saldırganların bir şekilde hedefin domain adını taklit etmeye ya da kullanmaya çalışacağı** fikrine dayanır. Eğer domaininiz `example.com` ise ve farklı bir domain (ör. `youwonthelottery.com`) kullanılarak hedeflenmişseniz, bu teknikler bunu ortaya çıkaramayacaktır. -## Alan adı varyasyonları +## Domain name varyasyonları -E-posta içinde **benzer bir alan adı** kullanacak olan **phishing** girişimlerini **açığa çıkarmak** oldukça **kolaydır**.\ -Saldırganın kullanabileceği en olası phishing adlarının bir listesini **oluşturmak** ve bunun **kayıtlı olup olmadığını kontrol etmek** veya sadece herhangi bir **IP** kullanıp kullanmadığını kontrol etmek yeterlidir. +E-posta içinde benzer bir domain adı kullanacak phishing girişimlerini ortaya çıkarmak bir hayli **kolaydır**.\ +Saldırganın kullanabileceği en olası phishing isimlerinin bir listesini **oluşturmak** ve bunların **kayıtlı** olup olmadığını ya da herhangi bir **IP**'nin bunları kullanıp kullanmadığını **kontrol etmek** yeterlidir. -### Şüpheli alanları bulma +### Finding suspicious domains -Bu amaçla, aşağıdaki araçlardan herhangi birini kullanabilirsiniz. Bu araçların, alan adının herhangi bir IP ile ilişkilendirilip ilişkilendirilmediğini kontrol etmek için otomatik olarak DNS istekleri de gerçekleştireceğini unutmayın: +Bu amaç için aşağıdaki araçlardan herhangi birini kullanabilirsiniz. Bu araçların domainin herhangi bir IP'ye atanmış olup olmadığını kontrol etmek için otomatik olarak DNS istekleri de yapacağını unutmayın: - [**dnstwist**](https://github.com/elceef/dnstwist) - [**urlcrazy**](https://github.com/urbanadventurer/urlcrazy) +Tip: Eğer aday bir liste oluşturursanız, bunu DNS resolver loglarınıza da göndererek **kuruluş içinden gelen NXDOMAIN sorgularını** tespit edin (kullanıcıların saldırgan gerçekten kaydını yapmadan önce bir yazım hatasına ulaşmayı denemesi). Politika izin veriyorsa bu domainleri sinkhole'layın veya önceden engelleyin. + ### Bitflipping -**Bu tekniğin kısa bir açıklamasını ana sayfada bulabilirsiniz. Ya da orijinal araştırmayı** [**https://www.bleepingcomputer.com/news/security/hijacking-traffic-to-microsoft-s-windowscom-with-bitflipping/**](https://www.bleepingcomputer.com/news/security/hijacking-traffic-to-microsoft-s-windowscom-with-bitflipping/) **okuyabilirsiniz.** +**Bu tekniğin kısa bir açıklamasını üst sayfada bulabilirsiniz. Veya özgün araştırmayı şu adreste okuyun** [**https://www.bleepingcomputer.com/news/security/hijacking-traffic-to-microsoft-s-windowscom-with-bitflipping/**](https://www.bleepingcomputer.com/news/security/hijacking-traffic-to-microsoft-s-windowscom-with-bitflipping/) -Örneğin, microsoft.com alan adında 1 bitlik bir değişiklik onu _windnws.com_ haline getirebilir.\ -**Saldırganlar, kurbanla ilgili mümkün olduğunca çok bit-flipping alan adı kaydedebilirler ve meşru kullanıcıları kendi altyapılarına yönlendirebilirler.** +Örneğin, microsoft.com domainindeki 1 bit'lik bir değişiklik onu _windnws.com_ şeklinde dönüştürebilir.\ +**Saldırganlar hedefle ilgili mümkün olduğunca çok bit-flipping domain kaydı yapabilirler ve meşru kullanıcıları kendi altyapılarına yönlendirebilirler.** -**Tüm olası bit-flipping alan adları da izlenmelidir.** +**Tüm olası bit-flipping domain isimleri de izlenmelidir.** + +Eğer homoglyph/IDN lookalikes'ları da göz önüne almanız gerekiyorsa (ör. Latin/Kiril karakterlerin karıştırılması), bakınız: + +{{#ref}} +homograph-attacks.md +{{#endref}} ### Temel kontroller -Potansiyel şüpheli alan adları listesine sahip olduğunuzda, bunları (özellikle HTTP ve HTTPS portlarını) **kontrol etmelisiniz** ve **kurbanın alanına benzer bir giriş formu kullanıp kullanmadıklarını görmek için** kontrol etmelisiniz.\ -Ayrıca, port 3333'ü kontrol ederek açık olup olmadığını ve `gophish` örneğini çalıştırıp çalıştırmadığını görebilirsiniz.\ -Her keşfedilen şüpheli alanın **ne kadar eski olduğunu bilmek de ilginçtir**, ne kadar gençse o kadar risklidir.\ -Şüpheli web sayfasının HTTP ve/veya HTTPS ekran görüntülerini alabilir ve şüpheli olup olmadığını görmek için **erişim sağlayarak daha derin bir inceleme yapabilirsiniz.** +Potansiyel şüpheli domain isimleri listesini elde ettikten sonra, bunları (özellikle HTTP ve HTTPS portlarında) **kontrol ederek hedef domainin kullandığına benzer bir login formu kullanıp kullanmadıklarını görmelisiniz**.\ +Port 3333'ü de kontrol ederek açık olup `gophish` çalıştırıp çalıştırmadığını görebilirsiniz.\ +Ayrıca keşfedilen her şüpheli domainin **ne kadar eski olduğunu** bilmek ilginçtir; ne kadar yeni ise o kadar risklidir.\ +Şüpheli web sayfalarının HTTP ve/veya HTTPS ekran görüntülerini alarak şüpheli olup olmadıklarını görebilir ve gerekirse **daha derinlemesine incelemek için erişebilirsiniz**. -### Gelişmiş kontroller +### İleri düzey kontroller -Bir adım daha ileri gitmek istiyorsanız, **şüpheli alanları izlemeyi ve zaman zaman daha fazlasını aramayı** öneririm (her gün? sadece birkaç saniye/dakika alır). Ayrıca, ilgili IP'lerin açık **portlarını kontrol etmeli** ve **`gophish` veya benzeri araçların örneklerini aramalısınız** (evet, saldırganlar da hata yapar) ve **şüpheli alanların ve alt alanların HTTP ve HTTPS web sayfalarını izlemelisiniz** ve kurbanın web sayfalarından herhangi bir giriş formunu kopyalayıp kopyalamadıklarını görmek için.\ -Bunu **otomatikleştirmek** için, kurbanın alanlarının giriş formlarının bir listesini oluşturmayı, şüpheli web sayfalarını taramayı ve şüpheli alanlardaki her giriş formunu kurbanın alanındaki her giriş formu ile karşılaştırmayı öneririm, `ssdeep` gibi bir şey kullanarak.\ -Eğer şüpheli alanların giriş formlarını bulduysanız, **saçma kimlik bilgileri göndermeyi** ve **sizi kurbanın alanına yönlendirip yönlendirmediğini kontrol etmeyi** deneyebilirsiniz. +Eğer bir adım daha ileri gitmek isterseniz, bu şüpheli domainleri düzenli olarak **izlemenizi ve zaman zaman yeni aramalar yapmanızı** öneririm (her gün mü? sadece birkaç saniye/dakika sürer). İlgili IP'lerin açık portlarını da **kontrol etmeli** ve `gophish` veya benzeri araç örneklerini **aramalısınız** (evet, saldırganlar da hata yapar) ve şüpheli domainlerin ve subdomainlerin HTTP ve HTTPS sayfalarını **izleyerek** hedefin web sayfalarından herhangi bir login formunu kopyalayıp kopyalamadıklarını kontrol edin.\ +Bunu **otomatikleştirmek** için, hedef domainlerin login formlarının bir listesini tutmanızı, şüpheli web sayfalarını taramanızı ve şüpheli domainlerde bulunan her login formunu hedef domainin her login formuyla `ssdeep` gibi bir şeyle karşılaştırmanızı öneririm.\ +Şüpheli domainlerin login formlarını bulduysanız, **sahte kimlik bilgileri gönderip** bunun sizi hedefin domainine **yönlendirip yönlendirmediğini kontrol edebilirsiniz**. -## Anahtar kelimeleri kullanan alan adları +--- -Ana sayfa, **kurbanın alan adını daha büyük bir alan adı içinde yerleştirme** tekniğini de belirtmektedir (örneğin, paypal-financial.com için paypal.com). +### Hunting by favicon and web fingerprints (Shodan/ZoomEye/Censys) -### Sertifika Şeffaflığı +Birçok phishing kit'i taklit ettikleri markanın favicon'larını yeniden kullanır. Internet çapındaki tarayıcılar base64 ile kodlanmış favicon'un MurmurHash3'ünü hesaplar. Bu hash'i üretebilir ve bunun üzerinden pivot yapabilirsiniz: -Önceki "Brute-Force" yaklaşımını almak mümkün değil, ancak aslında **bu tür phishing girişimlerini açığa çıkarmak mümkündür** aynı zamanda sertifika şeffaflığı sayesinde. Her seferinde bir CA tarafından bir sertifika verildiğinde, detaylar kamuya açık hale gelir. Bu, sertifika şeffaflığını okuyarak veya hatta izleyerek, **adında bir anahtar kelime kullanan alanları bulmanın mümkün olduğu anlamına gelir.** Örneğin, bir saldırgan [https://paypal-financial.com](https://paypal-financial.com) için bir sertifika oluşturursa, sertifikayı görmek "paypal" anahtar kelimesini bulmak ve şüpheli e-postanın kullanıldığını bilmek mümkündür. +Python örneği (mmh3): +```python +import base64, requests, mmh3 +url = "https://www.paypal.com/favicon.ico" # change to your brand icon +b64 = base64.encodebytes(requests.get(url, timeout=10).content) +print(mmh3.hash(b64)) # e.g., 309020573 +``` +- Shodan'da sorgu: `http.favicon.hash:309020573` +- Araçlarla: favfreak gibi topluluk araçlarına bakarak Shodan/ZoomEye/Censys için hash ve dork oluşturun. -Gönderi [https://0xpatrik.com/phishing-domains/](https://0xpatrik.com/phishing-domains/) Censys'i belirli bir anahtar kelimeyi etkileyen sertifikaları aramak ve tarih (sadece "yeni" sertifikalar) ve CA vereni "Let's Encrypt" ile filtrelemek için kullanabileceğinizi öneriyor: +Notlar +- Favicons yeniden kullanılır; eşleşmeleri lead olarak değerlendirin ve işlem yapmadan önce içeriği ve certs'i doğrulayın. +- Daha yüksek doğruluk için domain-age ve keyword heuristics ile birleştirin. + +### URL telemetri araştırması (urlscan.io) + +`urlscan.io` gönderilen URL'lerin geçmiş ekran görüntülerini, DOM'unu, isteklerini ve TLS meta verilerini saklar. Marka kötüye kullanımı ve klonlar için arama yapabilirsiniz: + +Örnek sorgular (UI veya API): +- Meşru domainlerinizi hariç tutarak benzer siteleri bulun: `page.domain:(/.*yourbrand.*/ AND NOT yourbrand.com AND NOT www.yourbrand.com)` +- Varlıklarınıza hotlinking yapan siteleri bulun: `domain:yourbrand.com AND NOT page.domain:yourbrand.com` +- Sonuçları yakın zamanla kısıtlamak için ekleyin: `AND date:>now-7d` + +API örneği: +```bash +# Search recent scans mentioning your brand +curl -s 'https://urlscan.io/api/v1/search/?q=page.domain:(/.*yourbrand.*/%20AND%20NOT%20yourbrand.com)%20AND%20date:>now-7d' \ +-H 'API-Key: ' | jq '.results[].page.url' +``` +JSON'dan pivot on: +- `page.tlsIssuer`, `page.tlsValidFrom`, `page.tlsAgeDays` — lookalikes için çok yeni cert'leri tespit etmek +- `task.source` değerleri, örn. `certstream-suspicious` — bulguları CT monitoring'e bağlamak için + +### RDAP üzerinden alan adı yaşı (scriptable) + +RDAP makine-okunabilir oluşturma olayları döndürür. **Yeni kayıtlı alan adlarını (NRDs)** işaretlemek için kullanışlı. +```bash +# .com/.net RDAP (Verisign) +curl -s https://rdap.verisign.com/com/v1/domain/suspicious-example.com | \ +jq -r '.events[] | select(.eventAction=="registration") | .eventDate' + +# Generic helper using rdap.net redirector +curl -s https://www.rdap.net/domain/suspicious-example.com | jq +``` +Pipeline'inizi alan adlarını kayıt yaşı kovalarına (ör., <7 days, <30 days) göre etiketleyerek zenginleştirin ve triajı buna göre önceliklendirin. + +### TLS/JAx fingerprints to spot AiTM infrastructure + +Modern credential-phishing giderek daha fazla **Adversary-in-the-Middle (AiTM)** reverse proxy'leri (ör., Evilginx) kullanarak oturum token'larını çalıyor. Ağ tarafı tespitleri ekleyebilirsiniz: + +- Egress'te TLS/HTTP fingerprint'lerini (JA3/JA4/JA4S/JA4H) kaydedin. Bazı Evilginx yapılarında stabil JA4 istemci/sunucu değerleri gözlemlenmiştir. Bilinen-kötü fingerprint'lerde yalnızca zayıf bir gösterge olarak alarm oluşturun ve her zaman içerik ile domain istihbaratıyla teyit edin. +- CT veya urlscan üzerinden keşfedilen lookalike hostlar için TLS sertifika meta verilerini (issuer, SAN sayısı, wildcard kullanımı, geçerlilik) proaktif olarak kaydedin ve bunları DNS yaşı ve coğrafi konumla korelasyonlayın. + +> Not: Fingerprint'leri zenginleştirme olarak değerlendirin, tek başına engelleyici olarak kullanmayın; framework'ler evrilebilir ve rastgeleleştirme/obfuscation yapabilir. + +### Domain names using keywords + +Ana sayfa ayrıca **kurbanın domain adını daha büyük bir domainin içine koyma** tekniğinden de bahsediyor (ör., paypal-financial.com, paypal.com için). + +#### Certificate Transparency + +Önceki "Brute-Force" yaklaşımını kullanmak her zaman mümkün olmayabilir ama sertifika şeffaflığı sayesinde bu tür phishing girişimlerini ortaya çıkarmak **mümkündür**. Her seferinde bir CA tarafından bir sertifika verildiğinde, detaylar kamuya açılır. Bu, certificate transparency'i okuyarak veya izleyerek, bir ismin içinde anahtar kelime kullanan domainleri **bulmanın mümkün olduğu** anlamına gelir. Örneğin, bir saldırgan [https://paypal-financial.com](https://paypal-financial.com) için bir sertifika oluşturduğunda, sertifikayı görerek "paypal" anahtar kelimesini bulmak ve şüpheli e-postanın kullanıldığını bilmek mümkündür. + +Post [https://0xpatrik.com/phishing-domains/](https://0xpatrik.com/phishing-domains/) Censys kullanarak belirli bir anahtar kelimeyi etkileyen sertifikaları tarih (sadece "yeni" sertifikalar) ve CA issuer "Let's Encrypt" ile filtreleyerek arayabileceğinizi öneriyor: ![https://0xpatrik.com/content/images/2018/07/cert_listing.png](<../../images/image (1115).png>) -Ancak, bunu ücretsiz web [**crt.sh**](https://crt.sh) kullanarak "aynısını" yapabilirsiniz. **Anahtar kelimeyi arayabilir** ve **sonuçları tarih ve CA ile filtreleyebilirsiniz**. +Bununla birlikte, ücretsiz web [**crt.sh**](https://crt.sh) ile de "aynı" işi yapabilirsiniz. Anahtar kelimeyi **arama** ve sonuçları isterseniz **tarih ve CA'ya göre filtreleme** imkanınız var. ![](<../../images/image (519).png>) -Bu son seçeneği kullanarak, gerçek alanın herhangi bir kimliğinin şüpheli alanlardan herhangi biriyle eşleşip eşleşmediğini görmek için Kimlikleri Eşleştirme alanını bile kullanabilirsiniz (şüpheli bir alanın yanlış pozitif olabileceğini unutmayın). +Bu son seçenekle Matching Identities alanını kullanarak gerçek domain'den herhangi bir identity'nin şüpheli domainlerle eşleşip eşleşmediğini bile görebilirsiniz (şüpheli bir domainin false positive olabileceğini unutmayın). -**Bir diğer alternatif** ise [**CertStream**](https://medium.com/cali-dog-security/introducing-certstream-3fc13bb98067) adlı harika projedir. CertStream, belirli anahtar kelimeleri (yaklaşık) gerçek zamanlı olarak tespit etmek için kullanabileceğiniz yeni oluşturulan sertifikaların gerçek zamanlı bir akışını sağlar. Aslında, tam olarak bunu yapan [**phishing_catcher**](https://github.com/x0rz/phishing_catcher) adlı bir proje bulunmaktadır. +**Bir diğer alternatif** harika proje [**CertStream**](https://medium.com/cali-dog-security/introducing-certstream-3fc13bb98067). CertStream, yeni oluşturulan sertifikaların gerçek zamanlı akışını sağlar; belirli anahtar kelimeleri (neredeyse) gerçek zamanlı olarak tespit etmek için kullanabilirsiniz. Aslında, bunu yapan [**phishing_catcher**](https://github.com/x0rz/phishing_catcher) adında bir proje var. -### **Yeni alanlar** +Pratik ipucu: CT bulgularını triajlarken NRD'leri, güvensiz/bilinmeyen registrar'ları, privacy-proxy WHOIS kayıtlarını ve çok yeni `NotBefore` zamanlarına sahip sertifikaları önceliklendirin. Gürültüyü azaltmak için sahip olduğunuz domain/markaların bir allowlist'ini tutun. -**Son bir alternatif**, bazı TLD'ler için **yeni kayıtlı alanların** bir listesini toplamak ([Whoxy](https://www.whoxy.com/newly-registered-domains/) bu hizmeti sağlar) ve **bu alanlardaki anahtar kelimeleri kontrol etmektir**. Ancak, uzun alan adları genellikle bir veya daha fazla alt alan adı kullanır, bu nedenle anahtar kelime FLD içinde görünmeyecek ve phishing alt alanını bulamayacaksınız. +#### **New domains** + +**Son bir alternatif** bazı TLD'ler için **yeni kaydedilmiş domain** listeleri toplmaktır (Whoxy bu hizmeti sağlar: https://www.whoxy.com/newly-registered-domains/) ve bu domainlerde anahtar kelimeleri **kontrol etmektir**. Ancak, uzun domainler genellikle bir veya daha fazla subdomain kullanır; dolayısıyla anahtar kelime FLD'nin içinde görünmeyebilir ve phishing alt domain'ini bulamayabilirsiniz. + +Ek heuristik: belirli **file-extension TLD'leri** (ör., `.zip`, `.mov`) uyarılarında ekstra şüpheyle ele alın. Bunlar lure'larda dosya isimleriyle karıştırılmaya eğilimlidir; daha iyi doğruluk için TLD sinyalini marka anahtar kelimeleri ve NRD yaşı ile birleştirin. + +## Referanslar + +- urlscan.io – Search API reference: https://urlscan.io/docs/search/ +- APNIC Blog – JA4+ network fingerprinting (includes Evilginx example): https://blog.apnic.net/2023/11/22/ja4-network-fingerprinting/ {{#include ../../banners/hacktricks-training.md}} diff --git a/theme/ht_searcher.js b/theme/ht_searcher.js index f47ba384a..77f10f607 100644 --- a/theme/ht_searcher.js +++ b/theme/ht_searcher.js @@ -24,13 +24,15 @@ /* 2 — load a single index (remote → local) */ async function loadIndex(remote, local, isCloud=false){ let rawLoaded = false; - try { - const r = await fetch(remote,{mode:'cors'}); - if (!r.ok) throw new Error('HTTP '+r.status); - importScripts(URL.createObjectURL(new Blob([await r.text()],{type:'application/javascript'}))); - rawLoaded = true; - } catch(e){ console.warn('remote',remote,'failed →',e); } - if(!rawLoaded){ + if(remote){ + try { + const r = await fetch(remote,{mode:'cors'}); + if (!r.ok) throw new Error('HTTP '+r.status); + importScripts(URL.createObjectURL(new Blob([await r.text()],{type:'application/javascript'}))); + rawLoaded = true; + } catch(e){ console.warn('remote',remote,'failed →',e); } + } + if(!rawLoaded && local){ try { importScripts(abs(local)); rawLoaded = true; } catch(e){ console.error('local',local,'failed →',e); } } @@ -40,13 +42,41 @@ return data; } + async function loadWithFallback(remotes, local, isCloud=false){ + if(remotes.length){ + const [primary, ...secondary] = remotes; + const primaryData = await loadIndex(primary, null, isCloud); + if(primaryData) return primaryData; + + if(local){ + const localData = await loadIndex(null, local, isCloud); + if(localData) return localData; + } + + for (const remote of secondary){ + const data = await loadIndex(remote, null, isCloud); + if(data) return data; + } + } + + return local ? loadIndex(null, local, isCloud) : null; + } + (async () => { - const MAIN_RAW = 'https://raw.githubusercontent.com/HackTricks-wiki/hacktricks/refs/heads/master/searchindex.js'; - const CLOUD_RAW = 'https://raw.githubusercontent.com/HackTricks-wiki/hacktricks-cloud/refs/heads/master/searchindex.js'; + const htmlLang = (document.documentElement.lang || 'en').toLowerCase(); + const lang = htmlLang.split('-')[0]; + const mainReleaseBase = 'https://github.com/HackTricks-wiki/hacktricks/releases/download'; + const cloudReleaseBase = 'https://github.com/HackTricks-wiki/hacktricks-cloud/releases/download'; + + const mainTags = Array.from(new Set([`searchindex-${lang}`, 'searchindex-en', 'searchindex-master'])); + const cloudTags = Array.from(new Set([`searchindex-${lang}`, 'searchindex-en', 'searchindex-master'])); + + const MAIN_REMOTE_SOURCES = mainTags.map(tag => `${mainReleaseBase}/${tag}/searchindex.js`); + const CLOUD_REMOTE_SOURCES = cloudTags.map(tag => `${cloudReleaseBase}/${tag}/searchindex.js`); const indices = []; - const main = await loadIndex(MAIN_RAW , '/searchindex.js', false); if(main) indices.push(main); - const cloud= await loadIndex(CLOUD_RAW, '/searchindex-cloud.js', true ); if(cloud) indices.push(cloud); + const main = await loadWithFallback(MAIN_REMOTE_SOURCES , '/searchindex.js', false); if(main) indices.push(main); + const cloud= await loadWithFallback(CLOUD_REMOTE_SOURCES, '/searchindex-cloud.js', true ); if(cloud) indices.push(cloud); if(!indices.length){ postMessage({ready:false, error:'no-index'}); return; }