Rich (BB code):
ATTEMPTED_WRITE_TO_READONLY_MEMORY (be)
An attempt was made to write to readonly memory. The guilty driver is on the
stack trace (and is typically the current instruction pointer).
When possible, the guilty driver's name (Unicode string) is printed on
the BugCheck screen and saved in KiBugCheckDriver.
Arguments:
Arg1: fffff8005c2d7348, Virtual address for the attempted write.
Arg2: 090000000ca87121, PTE contents.
Arg3: fffffb0b16338f70, (reserved)
Arg4: 000000000000000a, (reserved)
Yeşil ile işaretlediğim hatanın açıklamasından da anlaşılacağı gibi, bir sürücü salt okunur belleğin bir bölgesine yazmaya çalışıyor. Genellikle ilk parametre ile !pte komutunu çalıştırabiliyoruz ki bu komut, söz konusu adresin yazma bitinin silindiğini gösteriyor sadece. Üçüncü parametre, çöken yerin trap yapısını gösteriyor (.trap).
Stack yığınını inceleyebiliriz direkt olarak bu hata için:
Rich (BB code):
7: kd> k
# Child-SP RetAddr Call Site
00 fffffb0b`16338db8 fffff800`c10d258f nt!KeBugCheckEx
01 fffffb0b`16338dc0 fffff800`c1049586 nt!MiRaisedIrqlFault+0x2c3
02 fffffb0b`16338e00 fffff800`c14ad6cb nt!MmAccessFault+0x356
03 fffffb0b`16338f70 fffff800`c109aa28 nt!KiPageFault+0x38b
04 fffffb0b`16339100 fffff800`c109a6e6 nt!KiProcessThreadWaitList+0x148 < Çökme noktası
05 fffffb0b`163391a0 fffff800`c10f3130 nt!KiExitDispatcher+0x46 // APC'lerin kontrolü
06 fffffb0b`16339200 fffff800`5d34a0a8 nt!KeInsertQueueApc+0x250 // Battleye'in UT'e APC enjekte etme girişimi?
07 fffffb0b`163392b0 00000000`00000200 BEDaisy+0x52a0a8 // BATTLEYE SÜRÜCÜSÜ
08 fffffb0b`163392b8 ffffe186`b93d75f0 0x200
09 fffffb0b`163392c0 00000000`00000000 0xffffe186`b93d75f0
Hatanın, bir sürücünün (bu durumda BEDaisy.sys) salt okunur olarak işaretlenmiş bir bellek bölgesine yazmaya çalıştığını gösterdiğini zaten söylemiştim.
Daha spesifik olarak hata,
APC işlemleri sırasında meydana gelmiştir.
KeInsertQueueApc fonksiyonu, bir APC nesnesini bir iş parçacığının APC kuyruğuna eklemekten sorumlu olan fonksiyondur ve KiExitDispatcher genellikle iş parçacığı bekleme işlemlerinden sonra, bekleyen APC'leri teslim etmek için çağrılan bir başka fonksiyondur. Kontrol işlemi denilebilir. Peki bu ikisi neden burda?
Çünküsü BattlEye, her işlemdeki tüm kullanıcı modu iş parçacıklarında APC'leri kaydediyor... Bunun sebebi de Yürütülen APC kodunun, RtlWalkFrameChain işlevini çağırması ve bu işlevin BEDaisy'e APC'yi yürüten iş parçacığındaki tüm trap'leri sağlaması oluyor.
Eki Görüntüle 191950
Dahasına bakmak istersen :
https://research.meekolab.com/under...cheats-in-online-games?utm_source=chatgpt.com
Bunu görüp anlayabiliriz:
Rich (BB code):
nt!KeInsertQueueApc+0x54:
fffff800`c10f2f34 488b4538 mov rax,qword ptr [rbp+38h]
fffff800`c10f2f38 0fb64d51 movzx ecx,byte ptr [rbp+51h]
fffff800`c10f2f3c 4889442440 mov qword ptr [rsp+40h],rax
fffff800`c10f2f41 84c9 test cl,cl
fffff800`c10f2f43 488b4530 mov rax,qword ptr [rbp+30h]
fffff800`c10f2f47 4889442448 mov qword ptr [rsp+48h],rax
fffff800`c10f2f4c 0f958424b0000000 setne byte ptr [rsp+0B0h]
fffff800`c10f2f54 488d0565b97900 lea rax,[nt!KeSpecialUserApcKernelRoutine (fffff800`c188e8c0)]
fffff800`c10f2f5b 48394520 cmp qword ptr [rbp+20h],rax
fffff800`c10f2f5f 0f8439040000 je nt!KeInsertQueueApc+0x4be (fffff800`c10f339e)
Sonuca bakarsak APC kuyrukları
doubly linked list olarak uygulanıyorlar, bu da özellikle bağlamdaki sürücünün LIST_ENTRY ile ilgili bir istisna oluşturmasının ihtimalini arttırıyor. Prog'daki stack'e göre, sürücü zaten kaldırılmış olan bağlantılı listeden bir girişi kaldırmaya çalışmış gibi görünüyor. Bu, çift serbest bırakma olarak bilinir ve kritik bir sistem hatası olarak ifade edilebilir. Bu nedenle mavi ekran alıyorsun. Önceden de dediğim gibi, KiExitDispatcher aslında APC kuyruğunda bekleyen APC olup olmadığını kontrol ediyor ve bunları yürütüyor. Bu da bağlantılı listenin “boşaltılmasına” neden oluyor... Sonucunda da mavi ekran hatasını görüyorsun.
Ayrıca şu bağlamdan da bir sürücü çıkarımı yapılabilir gibi duruyor:
Rich (BB code):
nt!KeInsertQueueApc+250
Parameter[0] = ffffe186b93d75f0 // APC
Parameter[1] = ffffe186b93d75f0 // SA1
Parameter[2] = 0000000000000000 // SA2
Bu durumda, ilgili adres ki yani APC'nin kendisi ve aynı zamanda APC çağrısına geçirilen ilk parametre olan SA1 olarak kullanılıyor.
Yani sürücü kendi KAPC yapısının adresini hem nesne hem de argüman olarak geçiriyor. Bunu yaparken önce Apc->
ApcListEntry’yi değiştirecek Daha sonra hedeflenen thread’in
ApcState.ApcListHead’ine bağlanacak. Lakin eklenecek bu adres, artık geçerli değilse (Read-Only, korumalı bir bellek bölgesindeyse) sistem çekirdeği ring0 LIST_ENTRY güncellemesi yaparken bir page fault üretir.
Rich (BB code):
7: kd> dc ffffe186b93d75f0
ffffe186`b93d75f0 ???????? ???????? ???????? ???????? ????????????????
ffffe186`b93d7600 ???????? ???????? ???????? ???????? ????????????????
ffffe186`b93d7610 ???????? ???????? ???????? ???????? ????????????????
ffffe186`b93d7620 ???????? ???????? ???????? ???????? ????????????????
ffffe186`b93d7630 ???????? ???????? ???????? ???????? ????????????????
ffffe186`b93d7640 ???????? ???????? ???????? ???????? ????????????????
ffffe186`b93d7650 ???????? ???????? ???????? ???????? ????????????????
ffffe186`b93d7660 ???????? ???????? ???????? ???????? ????????????????
Aynı şekilde adresin geçerli olmadığı da belli. Üretilen PageFault çözülebilir lakin sistem APC girişlerini eklerken IRQL seviyesini yükselltiğinden dolayı, IRQL =2 seviyesinde PageFault çözümleyicisi çalışamaz hale geliyor. Bu da sistemi mavi ekrana iten ana sebep oluyor...
Rich (BB code):
7: kd> !irql
Debugger saved IRQL for processor 0x7 -- 2 (DISPATCH_LEVEL)
Rich (BB code):
7: kd> dt nt!_KAPC
+0x000 Type : UChar
+0x001 AllFlags : UChar
+0x001 CallbackDataContext : Pos 0, 1 Bit
+0x001 Unused : Pos 1, 7 Bits
+0x002 Size : UChar
+0x003 SpareByte1 : UChar
+0x004 SpareLong0 : Uint4B
+0x008 Thread : Ptr64 _KTHREAD // Hedef thread?
+0x010 ApcListEntry : _LIST_ENTRY // Güncellenecek liste
+0x020 KernelRoutine : Ptr64 void
+0x028 RundownRoutine : Ptr64 void
+0x030 NormalRoutine : Ptr64 void
+0x020 Reserved : [3] Ptr64 Void
+0x038 NormalContext : Ptr64 Void
+0x040 SystemArgument1 : Ptr64 Void // KAPC üzerinden enjekte edilen ilk değer
+0x048 SystemArgument2 : Ptr64 Void // KAPC üzerinden enjekte edilen ikinci değer
+0x050 ApcStateIndex : Char
+0x051 ApcMode : Char
Fark edilen bir diğer şey de APC'nin kendisi ile göndermeye ihtiyaç duyduğu tek değer olan SA1'in aynı olması... Ki bu da tipik olarak bir AC hareketi olarak yorumlanabilir. Zira sistemden bir callback çalıştığında doğrudan kendi KAPC yapısına geri referans alacaktır...
Buna örnek bir davranış biçimi çağrılan komutlardan görünebilir:
Rich (BB code):
nt!KeInsertQueueApc+0x34:
fffff800`c10f2f14 498b4a20 mov rcx,qword ptr [r10+20h]
fffff800`c10f2f18 33d2 xor edx,edx
fffff800`c10f2f1a 4883c160 add rcx,60h
fffff800`c10f2f1e 41b800300000 mov r8d,3000h
fffff800`c10f2f24 e8e7a3f3ff call nt!EtwpLevelKeywordEnabled (fffff800`c102d310)
fffff800`c10f2f29 84c0 test al,al
fffff800`c10f2f2b 0f8486030000 je nt!KeInsertQueueApc+0x3d7 (fffff800`c10f32b7)
Nihayet her şeyin sonucunda KiProcessThreadWaitList, KiExitDispatcher tarafından çağrılıyor; bu fonksiyon, bir dispatcher nesnesi, signal olduğunda o nesneye bağlı thread’leri ready state’e geçiriyor ve bekleme listesini (
wait list) işliyor. Yani olayın doğal akışı, bir thread’in beklemeden çıkması → KiProcessThreadWaitList → KiExitDispatcher → KeInsertQueueApc şeklindedir. Bu zincir sırasında sürücünün manipüle ettiği APC yapısı geçersiz bir adrese yazma denemesi yaptığında, işlem bir
page fault üretiyor ve bu çözülmezse mavi ekran ile sonuçlanıyor.
Sürücü ile ilgili daha fazla bilgi için bakabilirsin ayrıca :
https://blog.back.engineering/21/08/2020/?utm_source=chatgpt.com
BattlEye sürücüsü halihazırda zaten, Microsoft tarafından önerilen bir sürücü değil:
25H2 ile yapılan herhangi bir değişim de bunu etkiliyor olabilir ki henüz resmi bir sürüm değil. Ayrıca PUBG'nin AC sürücüsü de görünüyor dosyanda.
Rich (BB code):
rsp : 0xfffffb0b16338db8 : 0xfffff800c10d258f : nt!MiRaisedIrqlFault+0x2c3
*** WARNING: Unable to verify timestamp for navagio.sys
0xfffffb0b16338db8 : 0xfffff800c10d258f : nt!MiRaisedIrqlFault+0x2c3
Belki de çekirdek yalıtımı ayarını değiştirerek sorunun çözülüp çözülmediğine bakmayı deneyebilirsin.