KeServiceDescriptorTable touching

Hello All

i would like to pls you about help in this case. currently i know
about three approaches used in commercial/respected programs how to
modify the read only KeServiceDescriptorTable (any read only memory),
but am not sure, whether i understand properly two of them.

  1. used in jetico’s bestcrypt package, namely in bcswap.sys which
    encrypts the swap file. the c code based on disassembly follows.

int create_mdl_lock_pagez(MDL **mdl, void *base, DWORD length)
if(!(*mdl=MmCreateMdl(NULL, base, (SIZE_T) length))) return FALSE;

// should be inside a _try SEH block, but for our purpose don’t care
// purpose==modifying of KeServiceDescriptorTable
MmProbeAndLockPages(*mdl, KernelMode, IoModifyAccess);
// there’s a seh handler in the bcswap.sys but only frees via
// IoFreeMdl the Mdl
return TRUE;

void *create_mdl_map_locked_pagez(MDL **mdl, void *base, DWORD length)
return((create_mdl_lock_pagez(mdl, base, length)) ? MmMapLockedPages(*mdl, KernelMode):NULL);

will this do it’s work ? since used in commercial prog, i think it
should but what exactly does the MmProbeAndLockPages ?

according to the DDK:
Specifies the type of operation for which the caller wants the access rights probed and the
pages locked, one of IoReadAccess, IoWriteAccess, or IoModifyAccess.

so if i read well, then the virtual range described by mdl is probed
for IoAccess. we specify IoModifyAccess so it is probed for read/write
access. so if the read only virtual range is probed for write, the
exception will occur. so will it work ? is there anything else i don’t
see ? i doubt people in jetico didn’t test this.

  1. Kerio Firewall, namely fwdrv.sys

call sub_0_19EFA ; this raises the irql to dpc/dispatch
mov eax, cr0
mov [ebp+var_4], eax
and eax, 0FFFEFFFFh
mov cr0, eax

this is the only thing i don’t have problems with :slight_smile: simply clears the
Write Protect bit. is this clean ? i mean is this good to use in
commercial progs ? (i think it’s ok, just would like to know your
opinion - it opens potencial memory overwriting since it’s system
wide, but on the other side only on mp systems since on dispatch/dpc)

  1. Mark Russinovich’s (sysinternals) Regmon
    _RegmonMapMem@12 proc near

base = dword ptr 8
length = dword ptr 0Ch
ppMdl = byte ptr 10h

push esi
push [esp+length]
push [esp+4+base]
push 0
call dword ptr ds:__imp__MmCreateMdl@12 ;
test eax, eax
mov esi, dword ptr [esp+ppMdl]
mov [esi], eax
jz short loc_60
push eax ; fill in the physical pages
call dword ptr ds:__imp__MmBuildMdlForNonPagedPool@4 ;
mov eax, [esi] ; gimme the mdl
push 0 ; kernelmode
or byte ptr [eax+6], 1 ; set MDL_MAPPED_TO_SYSTEM_VA flag ??
push dword ptr [esi] ; and finally map it
call dword ptr ds:__imp__MmMapLockedPages@8 ;

loc_60: ; CODE XREF: RegmonMapMem(x,x,x)+19j
pop esi
retn 0Ch
_RegmonMapMem@12 endp

as you can see the real work here possibly does the setting of
MDL_MAPPED_TO_SYSTEM_VA flag. pls does anyone know what it exactly
means ? it does the mapping read/write possibly, but that’s not enough
info for me.

sorry for stupid questions, i’m just curious. are there any other ways
of accessing read only memory legaly ? ie not modifying for example

btw: how is fpu and other advanced registers stored while context
switch under nts ? since the context switch does SwapContext
routine, i’ve looked through the kernel and found,
that only
.text:0041FEE1 mov [esp+10h+var_4], ebx
.text:0041FEE5 mov [esp+10h+var_8], esi ; save volatile regs
.text:0041FEE9 mov [esp+10h+var_C], edi
.text:0041FEED mov [esp+10h+var_10], ebp
are stored and restored. where does the fpu regs saving occure
pls ie where should i have a look ?

thx for help

Best regards,
Ivona Prenosilova


I’m really very much amazed of a female this smart! Take my best
regards :slight_smile:

sorry for stupid questions, i’m just curious. are there any other
of accessing read only memory legaly ? ie not modifying for example

One more method to your collection:

  • manipulate the PTE’s read-only bit manually. The PTE is at

PtePtr = (PULONG)0xc0000000 + ( (ULONG)Va >> 12 );

then find the read-only bit in Intel’s manuals, and reset it, then do
not forget to execute INVLPG opcode.

Note that this approach needs additional work for 4MB pages and for
/3GB boot option, and also for PAE.

As about what approach is the best - the Russinovich’s one, probably.
Remap the kernel memory to other region as read/write using a MDL, and
then patch the table.