WORD SetupLDT(WORD seg, DWORD ldtbase) { LDT_ENTRY EvilLdt; DWORD base = ldtbase; DWORD limit = 0; int ret; EvilLdt.BaseLow = base & 0xFFFF; EvilLdt.HighWord.Bytes.BaseMid = base >> 16; EvilLdt.HighWord.Bytes.BaseHi = base >> 24; EvilLdt.LimitLow = (limit >> 12) & 0xFFFF; EvilLdt.HighWord.Bits.LimitHi = limit >> 28; EvilLdt.HighWord.Bits.Granularity = 1; // 0/1, if 1, limit=(limit<<12)|FFF EvilLdt.HighWord.Bits.Default_Big = 1; // 0=16bit 1=32bit EvilLdt.HighWord.Bits.Reserved_0 = 0; // 0/1 EvilLdt.HighWord.Bits.Sys = 0; // 0/1 EvilLdt.HighWord.Bits.Pres = 1; // 0/1 (presence bit) EvilLdt.HighWord.Bits.Dpl = 3; // only 3 allowed :-( EvilLdt.HighWord.Bits.Type = 23; // [16..27] ret = NtSetLdtEntries( seg, *(DWORD*)&EvilLdt, *(((DWORD*)&EvilLdt)+1), 0,0,0); if (ret < 0) { printf("[-] Set ldt error : %08X.\n", ret); exit(0); } return seg; }
NTSTATUS Dirtbox::AllocateLdtEntry(PWORD Selector, DWORD Base, DWORD LimitSize) { DWORD Limit = Base + LimitSize; LDT_ENTRY LdtEntry; EnterCriticalSection(&ThreadingLock); // Locate a free LDT entry int i; for(i = 0; i < MAXIMUM_XBOX_THREADS; i++) if(FreeDescriptors[i]) break; if(i == MAXIMUM_XBOX_THREADS) { LeaveCriticalSection(&ThreadingLock); DebugPrint("AllocateLdtEntry: Could not locate free LDT entry."); return STATUS_TOO_MANY_THREADS; } // Set up selector information LdtEntry.BaseLow = (WORD)(Base & 0xFFFF); LdtEntry.HighWord.Bits.BaseMid = (Base >> 16) & 0xFF; LdtEntry.HighWord.Bits.BaseHi = (Base >> 24) & 0xFF; LdtEntry.HighWord.Bits.Type = 0x13; // RW data segment LdtEntry.HighWord.Bits.Dpl = 3; // user segment LdtEntry.HighWord.Bits.Pres = 1; // present LdtEntry.HighWord.Bits.Sys = 0; LdtEntry.HighWord.Bits.Reserved_0 = 0; LdtEntry.HighWord.Bits.Default_Big = 1; // 386 segment LdtEntry.HighWord.Bits.Granularity = 0; // byte-level granularity LdtEntry.LimitLow = (WORD)(Limit & 0xFFFF); LdtEntry.HighWord.Bits.LimitHi = (Limit >> 16) & 0xF; WORD Sel = ((i + 1) << 3) | 0x7; // Allocate selector NTSTATUS Res = NtSetLdtEntries(Sel, LdtEntry, 0, 0, 0); if(!NT_SUCCESS(Res)) { LeaveCriticalSection(&ThreadingLock); DebugPrint("AllocateLdtEntry: Could not set LDT entries."); return Res; } FreeDescriptors[i] = FALSE; *Selector = Sel; LeaveCriticalSection(&ThreadingLock); return STATUS_SUCCESS; }
NTSTATUS Dirtbox::FreeLdtEntry(WORD Selector) { LDT_ENTRY LdtEntry; EnterCriticalSection(&ThreadingLock); memset(&LdtEntry, 0, sizeof(LDT_ENTRY)); NTSTATUS Res = NtSetLdtEntries(Selector, LdtEntry, 0, 0, 0); if (!NT_SUCCESS(Res)) { LeaveCriticalSection(&ThreadingLock); DebugPrint("FreeLdtEntry: Could not set LDT entries."); return Res; } FreeDescriptors[(Selector >> 3)-1] = TRUE; LeaveCriticalSection(&ThreadingLock); return STATUS_SUCCESS; }