Giving arbitary memory access to PTE

Durum
Üzgünüz bu konu cevaplar için kapatılmıştır...
aka hernos
Süper Üye
Katılım
30 Ağu 2019
Mesajlar
628
Çözümler
10
Tepki puanı
297
Ödüller
4
Yaş
29
Sosyal
6 HİZMET YILI
NX bit flip ve Software Write bit flip bugünlerde belki bir meme olabilir fakat geçenlerde yaptığım analizler sonucu EAAC'nın EPROCESS deki mitigation flaglerine DisableDynamicCode eklemesi yüzümde bir gülümsemeye sebep oldu. Yıl 2024 saçma sapan çözümler bulmaya çalışıyolar :D Azıcık beyni olan ve Windows Internal Bookdaki memory managament kısmını okuyan bir birey bile bunu nasıl atlatıcağını az çok bilir. Aşağıdakı paylaştığım kodda önce ntoskrnl de pte base adressimizi buluyoruz pattern scan yaparak sonra bu pte base addresimize bit shift operasyonları yaparak ilgili sanal addresin PTE sanal adresini buluyoruz ve asıl işlem burada başlıyor bu PTE nin bitlerini manipulate ederek keyfimize göre bir memory sayfasına read/write/execute access izinlerini verebiliyoruz. Bizzat denedim ve başarıyla çalıştı. VAD lerdeki protection flagleri bu yol ile güncellenmediği için herhangi bir Usermodedan memory sayfası hala izinler verilmemiş olarak gözükecektir aynı şekilde Anticheatde bunu göremicektir fakat memory sayfasına istediğiniz gibi manipulate edebilceksiniz. Bu arada PTE base adressimiz her boot time sırasında yer değiştirdiği için pattern scan ile almak zorunda kalıyoruz. Aşağıda paylaştığım kod pastelemeye hazırdır. Yakında bununla ilgili daha detaylı bir yazıyı kaleme alıp blog sayfamda paylaşıcağım takipde kalınız.İyi akşamlar herkese 👋
MgnNH6O.png
Blog sayfam;
Bağlantıları görmek için lütfen Giriş Yap

C++:
typedef union _PTE
{

    // Normally, emulating PAGE_NOACCESS means turning the valid bit off in the PTE  

    ULONG64 value;

    // Bitfield in a struct
    struct
    {
        ULONG64 present : 1;            // Must be 1, region invalid if 0. (PAGE_NOACCESS)                    // bit 0
        ULONG64 rw : 1;                    // written-before                                            // bit 1
        ULONG64 user_supervisor : 1;    // If 0, user-mode accesses not allowed.
        ULONG64 page_write : 1;        // Determines the memory type used to access the memory.
        ULONG64 page_cache : 1;       // Determines the memory type used to access the memory.
        ULONG64 accessed : 1;         // If 0, this entry has not been used for translation.
        ULONG64 dirty : 1;             // If 0, the memory backing this page has not been written to.
        ULONG64 large_page : 1;            // Large page
        ULONG64 global : 1;            // If 1 and the PGE bit of CR4 is set, translations are global.
        ULONG64 cow : 1;              // copy on write
        ULONG64 prt : 1;              // protetype
        ULONG64 wrt : 1;              // write-access
        ULONG64 pfn : 36;             // The page frame number of the backing physical page.
        ULONG64 reserved : 4;
        ULONG64 ignored3 : 7;
        ULONG64 protect_key : 4;       // If the PKE bit of CR4 is set, determines the protection key.
        ULONG64 nx : 1;               // If 1, instruction fetches not allowed.                              
    };

} PTE, * PPTE;


auto fint_pte_base() -> uintptr_t {
        auto ntoskrnl = utils::get_kernel_module("ntoskrnl.exe");
        uintptr_t pte_base{ 0 };
        if (ntoskrnl) {
            printf("ntoskrnl base => 0x%p!", ntoskrnl);
            auto sig_base = utils::pattern_scan(ntoskrnl, "\x48\xC1\xE9\x09\x48\xB8\xF8\xFF\xFF\xFF\x7F\x00\x00\x00\x48\x23\xC8\x48\xB8", "xxxxxxxxxxxxxxxxxxx");
            if (sig_base)
            {
                pte_base = *(__int64*)(sig_base + 19);
                printf("pte base found at => 0x%p!", pte_base);
            }
            else
            {
                printf("sig_base not found!");
            }
        }
        else
        {
            printf("ntoskrnl not found!");
        }
        return pte_base;
    }

    auto resolve_pte_for_virtual(uintptr_t virtual_address) -> uintptr_t {
        auto MiGetPteAddress = [](unsigned __int64 a1) -> unsigned __int64
            {
                unsigned __int64 pte_base = fint_pte_base();

                return pte_base ? ((a1 >> 9) & 0x7FFFFFFFF8) + pte_base : 0;
            };

        return MiGetPteAddress(virtual_address);
    }

    NTSTATUS give_execute_access(uint32_t cid, uintptr_t virtual_address) {
        PEPROCESS process = { 0 }; NTSTATUS status = STATUS_UNSUCCESSFUL;
        PsLookupProcessByProcessId(HANDLE(cid), &process);
        if (process != nullptr && virtual_address != 0)
        {
            unsigned __int64 pte_virtual = resolve_pte_for_virtual(virtual_address);
            if (pte_virtual != 0)
            {
                printf("[+] pte_virtual => 0x%p", pte_virtual);
                KAPC_STATE state = { 0 };
                KeStackAttachProcess(process, &state);

                unsigned __int64 bits = *(unsigned __int64*)pte_virtual;

                PTE pte_new = { 0 };

                pte_new.value = bits;
                pte_new.nx = 0;

                *(unsigned __int64*)pte_virtual = pte_new.value;

                KeUnstackDetachProcess(&state);

                status = STATUS_SUCCESS;
            }

            ObDereferenceObject(process);
        }
        return status;
    }

    NTSTATUS give_write_access(uint32_t cid, uintptr_t virtual_address) {
        PEPROCESS process = { 0 }; NTSTATUS status = STATUS_UNSUCCESSFUL;
        PsLookupProcessByProcessId(HANDLE(cid), &process);

        if (process != nullptr && virtual_address != 0)
        {
            unsigned __int64 pte_virtual = resolve_pte_for_virtual(virtual_address);

            if (pte_virtual != 0)
            {
                KAPC_STATE state = { 0 };
                KeStackAttachProcess(process, &state);

                unsigned __int64 bits = *(unsigned __int64*)pte_virtual;

                PTE pte_new = { 0 };

                pte_new.value = bits;
                pte_new.wrt = 1;

                *(unsigned __int64*)pte_virtual = pte_new.value;

                KeUnstackDetachProcess(&state);

                status = STATUS_SUCCESS;
            }
            ObDereferenceObject(process);
        }
        return status;
    }
 
Son düzenleme:
Üye
Katılım
27 Şub 2024
Mesajlar
44
Tepki puanı
3
Ödüller
2
Yaş
26
Sosyal
2 HİZMET YILI
Öncelikle eline sağlık, bu paylaşımı açık yaptığım için teşekkürler.
 
NULL
Seçkin Üye
Katılım
14 May 2018
Mesajlar
326
Çözümler
1
Tepki puanı
120
Ödüller
6
Sosyal
8 HİZMET YILI
Güzel başarılı paylaşım olmuş eline sağlık.
 
Emre Montana
Seçkin Üye
Katılım
1 Eki 2018
Mesajlar
308
Çözümler
2
Tepki puanı
52
Ödüller
8
Yaş
20
Sosyal
7 HİZMET YILI
Güzel Paylaşım Olmuş Teşekkür Ederiz.
 
Uzman Üye
Katılım
24 Şub 2018
Mesajlar
189
Çözümler
2
Tepki puanı
9
Ödüller
7
8 HİZMET YILI
böyle şeyler paylaşan var mıydı ya
 
Onaylı Üye
Katılım
1 Mar 2024
Mesajlar
52
Tepki puanı
1
Ödüller
1
Yaş
29
2 HİZMET YILI
teşekkürler, normalde cheat'ler hakkında open source blog yazan yok, takipte olacağım :)
 
Durum
Üzgünüz bu konu cevaplar için kapatılmıştır...
Üst