Quantcast
Channel: How to exactly modify the Local Descriptor table on 64 bits Windows? - Stack Overflow
Viewing all articles
Browse latest Browse all 2

Answer by RbMm for How to exactly modify the Local Descriptor table on 64 bits Windows?

$
0
0

on x86-based windos possible (tested on xp and win 8.1 x86) set several descriptors in LDT table and use this. this can be done via NtSetInformationProcess with ProcessLdtInformation (undocumented) or, if we need set only 1 or 2 selectors - more easy use undocumented api:

EXTERN_C
__declspec(dllimport)
NTSTATUS
NTAPI
NtSetLdtEntries
(
 __in_opt ULONG Selector1,
 __in SEGMENT_ENTRY LdtEntry1,
 __in_opt ULONG Selector2,
 __in SEGMENT_ENTRY LdtEntry2
 );

so we need allocate 1 or more SEGMENT_ENTRY (or LDT_ENTRY - declared in winnt.h), allocate memory for segment, and call api. I did not pay much attention for 16 bit code and fill actual descriptors, check only memory fill via LDT selector (assigned to ES) and then read it via "plain" selector.

typedef struct SEGMENT_ENTRY
{
    ULONG   LimitLow    :   16;
    ULONG   BaseLow     :   16;
    ULONG   BaseMid     :    8;
    ULONG   Type        :    4;
    ULONG   IsGegment   :    1;// = 1
    ULONG   DPL         :    2;
    ULONG   P           :    1;// Present 
    ULONG   LimitHi     :    4;
    ULONG   AVL         :    1;// Available For software use
    ULONG   L           :    1;// Long-mode segment 
    ULONG   D           :    1;// Default operand size 
    ULONG   G           :    1;// Granularity 
    ULONG   BaseHi      :    8;
}*PSEGMENT_ENTRY;

typedef struct PROCESS_LDT_INFORMATION
{
    ULONG StartSelector;
    ULONG Length;
    SEGMENT_ENTRY LdtEntries[];
} *PPROCESS_LDT_INFORMATION;

EXTERN_C
__declspec(dllimport)
NTSTATUS
NTAPI
NtSetLdtEntries
(
 __in_opt ULONG Selector1,
 IN SEGMENT_ENTRY LdtEntry1,
 __in_opt ULONG Selector2,
 IN SEGMENT_ENTRY LdtEntry2
 );

NTSTATUS TestLdt()
{
    PVOID BaseAddress = 0;
    SIZE_T RegionSize = 0x100000;//1mb
    NTSTATUS status = NtAllocateVirtualMemory(NtCurrentProcess(), &BaseAddress, 0, &RegionSize, MEM_COMMIT, PAGE_EXECUTE_READWRITE);

    if (0 <= status)
    {
#if 1
        SEGMENT_ENTRY LdtEntry = {};
        LdtEntry.LimitLow = 0xffff;
        LdtEntry.BaseLow = ((ULONG_PTR)BaseAddress) & 0xFFFF;
        LdtEntry.BaseMid = ((ULONG_PTR)BaseAddress >> 16) & 0xff;
        LdtEntry.BaseHi = ((ULONG_PTR)BaseAddress >> 24) & 0xff;
        LdtEntry.P = 1;
        LdtEntry.DPL = 3;
        LdtEntry.IsGegment = 1;
        LdtEntry.Type = 2;//ldt

        status = NtSetLdtEntries(8, LdtEntry, 0, LdtEntry);
#else
        const ULONG cb = sizeof(PROCESS_LDT_INFORMATION) + 1 * sizeof(LDT_ENTRY);

        PPROCESS_LDT_INFORMATION LdtInfo = (PPROCESS_LDT_INFORMATION)alloca(cb);

        LdtInfo->Length = 1 * sizeof(LDT_ENTRY);
        LdtInfo->StartSelector = 8;

        SEGMENT_ENTRY* LdtEntry = LdtInfo->LdtEntries;

        LdtEntry->LimitLow = 0xffff;
        LdtEntry->BaseLow = ((ULONG_PTR)BaseAddress) & 0xFFFF;
        LdtEntry->BaseMid = ((ULONG_PTR)BaseAddress >> 16) & 0xff;
        LdtEntry->BaseHi = ((ULONG_PTR)BaseAddress >> 24) & 0xff;
        LdtEntry->L = 0;
        LdtEntry->D = 0;
        LdtEntry->G = 0;
        LdtEntry->AVL = 0;
        LdtEntry->P = 1;
        LdtEntry->DPL = 3;
        LdtEntry->IsGegment = 1;
        LdtEntry->Type = 2;//ldt

        status = NtSetInformationProcess(NtCurrentProcess(), ProcessLdtInformation, LdtInfo, cb);
#endif

        if (0 <= status)
        {
            DbgPrint("%s\n", BaseAddress); // print empty string
#ifdef _X86_
            __asm {
                push edi
                mov ax,0xf
                mov dx,es
                mov es,ax

                mov ecx,32
                mov al,0x33
                xor edi,edi
                rep stosb

                mov es,dx
                pop edi
            }
#endif
            DbgPrint("%s\n", BaseAddress);// print 33333333...
        }

        NtFreeVirtualMemory(NtCurrentProcess(), &BaseAddress, &RegionSize, MEM_RELEASE);
    }

    return status;
}

however This is valid only on x86-based windows systems.

if you call this on any x64 windows you got error STATUS_NOT_IMPLEMENTED. here windows not support LDT at all. and this can not be changed (even by modify system files. ?!)


more info - Local Descriptor Table on x64


Viewing all articles
Browse latest Browse all 2

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>