代码之家  ›  专栏  ›  技术社区  ›  user2284570

如何准确地修改本地描述符表?

  •  0
  • user2284570  · 技术社区  · 5 年前

    其目的是为16位寻址启用16位段,就像使用 modify_ldt() 系统调用。

    我找不到Cygwin是否提供了一个包装器,我几乎不知道它是什么样子的 NtSetLdtEntries 使用:

    typedef struct
    {
        ULONG Start;
        ULONG Length;
        LDT_ENTRY LdtEntries[1];
    } PROCESS_LDT_INFORMATION, *PPROCESS_LDT_INFORMATION;
    

    请注意,这与vm86模式无关(这是Microsoft在32位系统上使用的另一种方法)。如上所述,这种方法在Linux上用于在保护模式下运行16位代码,而无需任何仿真。看到了吗 CONFIG_X86_16BIT 更多信息。

    0 回复  |  直到 4 年前
        1
  •  1
  •   mirh AAAfarmclub    4 年前

    x86个 -可能基于windos(在 win 8.1 x86 LDT公司 然后用这个。这可以通过 NtSetInformationProcess 具有 ProcessLdtInformation (未记录)或者,如果我们只需要设置1或2个选择器-更易于使用的未记录api:

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

    所以我们需要分配1个或更多 SEGMENT_ENTRY LDT_ENTRY -声明于 ),为段分配内存,并调用api。我没有太注意16位代码和填充实际描述符,只检查内存填充通过 LDT公司

    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;
    }
    

    然而 This is valid only on x86-based windows systems.

    如果你打电话给任何人 x64个 windows有错误吗 STATUS_NOT_IMPLEMENTED LDT公司 完全。这是无法改变的(即使 修改系统文件。


    更多信息- Local Descriptor Table on x64