PDA

View Full Version : ProtectVirtualMemory from r0


Patafix
October 2nd, 2009, 05:56
Hi,

I'm trying to change page protection of a process memory from kernel mode.
I don't want to use NtProtectVirtualMemory since i don't have handle on the process. The binary is protected with a comercial product that hook OpenProcess and other usefull from r3... I could bypass the hooks here but it's not the point.
I can without problem attach to the process context using KeAttachProcess.
What I'd like to do is to use MiProctectVirtualMemory from ntoskrnl.exe to change the pages protection I need to read... Since MiPVM is not exported nor accessible from SSDT I'm not sure how to get his address. I'm not sure neither I can use this method.

I've searched around the Web without success atm.

Maybe you guys have some tips to give me?

Thank you

Kayaker
October 2nd, 2009, 11:10
Hi, What about disabling memory protection by setting the WP bit of CR0,
as popularized by the Hoglund/Butler Rootkit Empire?

Code:

// UN-protect memory

__asm
{
push eax
mov eax, CR0
and eax, 0FFFEFFFFh
mov CR0, eax
pop eax
}

// Do something here

// RE-protect memory

__asm
{
push eax
mov eax, CR0
or eax, NOT 0FFFEFFFFh
mov CR0, eax
pop eax
}


The entire above scheme is often preceded by a CLI and finished with an STI to renable interrupts.


Just to mention also, KeStackAttachProcess/KeUnstackDetachProcess are the preferred API's to use, rather than KeAttachProcess.

If modifying the WP bit of CR0 isn't suitable..

Once you've attached, you may be able to use NtProtectVirtualMemory with a ProcessHandle HANDLE of -1, which should be correctly interpreted as the current (attached) process. I'm not 100% sure of that without testing, but -1 is generally recognized as the current process handle in such cases. In tracing into NtProtectVirtualMemory -> ObReferenceObjectByHandle you can see that such a case is handled: cmp [ebp+arg_0], 0FFFFFFFFh

Kayaker

GamingMasteR
October 3rd, 2009, 07:37
Hi,

You can use MDLs to map and lock the virtual addresses ... look at MSDN for usage .

Patafix
October 3rd, 2009, 12:39

@Kayaker
The WP bit of CR0 dosn't work here (I tested)... I thought it was used to write in kernel memory. Am I wrong?
Yes, NtProtectVirtualMemory should work fine with the process handle set to -1 while attached to the target process 
I'll give a try just to confirm.

@GamingMasteR
yep... I finally choose this method as the most normal in kernel mode.

I'm still curious to know if I could use directly MiProtectVirtualMemory and how to do...

Thank you both of you 

here my snipet:


NTSTATUS MyReadVirtualMemory(PEPROCESS Process, IN PVOID BaseAddress, OUT PVOID Buffer, IN ULONG NumberOfBytesToRead, OUT PULONG NumberOfBytesRead)
{
    NTSTATUS Status = STATUS_SUCCESS;
    PMDL pMdl = 0, pProcessMemMdl = 0;
    PVOID SystemAddress = 0;
    PVOID MemoryAddress = 0;
    KAPC_STATE  ApcState;
    ULONG oldProtect;

    pMdl = IoAllocateMdl(Buffer, NumberOfBytesToRead, FALSE, FALSE, NULL);
    if(!pMdl)
        return STATUS_UNSUCCESSFUL;

    MmProbeAndLockPages(pMdl, UserMode, IoWriteAccess);
    
    SystemAddress = MmGetSystemAddressForMdlSafe(pMdl, NormalPagePriority);
    if(!SystemAddress)
    {
        Status = STATUS_UNSUCCESSFUL;
        goto exit2;
    }
    
    pProcessMemMdl = IoAllocateMdl(BaseAddress, NumberOfBytesToRead, FALSE, FALSE, NULL);
    if(!pProcessMemMdl)
        return STATUS_UNSUCCESSFUL;
    MmProbeAndLockPages(pProcessMemMdl, UserMode, IoReadAccess);

    MemoryAddress = MmGetSystemAddressForMdlSafe(pProcessMemMdl, NormalPagePriority);
    if(!MemoryAddress)
    {
        Status = STATUS_UNSUCCESSFUL;
        goto exit1;
    }

    KeStackAttachProcess(&Process->Pcb, &ApcState);

    __try
    {
        RtlCopyMemory(SystemAddress, MemoryAddress, NumberOfBytesToRead);
    }
    __except (EXCEPTION_EXECUTE_HANDLER)
    {
        DbgPrint("Exception occured: 0x%08X\n", GetExceptionCode());
        NumberOfBytesToRead = 0;
        Status = STATUS_UNSUCCESSFUL;
    }


    KeUnstackDetachProcess(&ApcState);

    if(pProcessMemMdl->MappedSystemVa != NULL)
    {
        MmUnmapLockedPages(pProcessMemMdl->MappedSystemVa, pMdl);
    }

     if(pMdl->MappedSystemVa != NULL)
    {
        MmUnmapLockedPages(pMdl->MappedSystemVa, pMdl);
    }

    ObDereferenceObject(Process);
    *NumberOfBytesRead = NumberOfBytesToRead;

exit1:
    MmUnlockPages(pProcessMemMdl);
    IoFreeMdl(pProcessMemMdl);

exit2:
    MmUnlockPages(pMdl);
    IoFreeMdl(pMdl);


    return Status;
}


Kayaker
October 3rd, 2009, 19:37
I was mistaken, I guess I was thinking that allowing writing to memory pages by disabling the write protect (WP) bit of CR0 might also impart read access, i.e. equate to PAGE_READWRITE, but that's obviously not the case.

The MDL mapping is indeed a good solution since you only require read access. Thanks for posting the snippet.

I'm all for running undocumented code, but it looks like getting the address of MiProtectVirtualMemory would be a little difficult on an OS version-independant basis.

Cheers,
Kayaker

GamingMasteR
October 4th, 2009, 05:32
I think walking through the process VAD nodes and setting the protection flags can work here, but this operation will need alot of work and as far as i know VAD structures changes on different O.S versions too !

BanMe
October 5th, 2009, 12:33
iono if this is even useful cause its just concept to code..and completly untested.. and written in notepad..
Code:

BYTE push_0[2] = {0x6a,0x00};
BYTE push_eax = 0x50;
BYTE push_Condw[2] = {0xff,0x35};
BYTE push_dwptr[2] = {0xff,0x75};
BYTE push_8[2] = {0x6a,0x08};
BYTE _call = 0xe8;
//6a00 push 0x0
//8d45e4 lea eax,[ebp-0x1c]
//50 push eax
//ff75d4 push dword ptr [ebp-0x2c]
//ff3558145680 push dword ptr [nt!PsProcessType (80561458)]
//6a08 push 0x8
//ff7508 push dword ptr [ebp+0x8]
//e8732effff call nt!ObReferenceObjectByHandle (80564be8)
// 50 push eax
// ff7514 push dword ptr [ebp+0x14]
// 8d45e0 lea eax,[ebp-0x20]
// 50 push eax
// 8d45dc lea eax,[ebp-0x24]
// 50 push eax
// ff75e4 push dword ptr [ebp-0x1c]
// e88dfdffff call nt!MiProtectVirtualMemory (80571b2d)
typedef struct _C_ID
{
_C_ID *_next;
void *_def_sig;
ULONG Size;
}C_ID,*PC_ID;
HANDLE hHeap = 0;
int Cycle = 0;

void Find_Addr()
{
ULONG StartAddress = 0;
C_ID CallId = {0};
CallId = InitC_ID((BYTE*)&push_0,sizeof(push_0));
CallId = AddC_ID(&Cycle,(BYTE*)&push_eax,sizeof(push_eax));
CallId = AddC_ID(&Cycle,(BYTE*)&push_Condw,sizeof(push_dwptr));
CallId = AddC_ID(&Cycle,(BYTE*)&push_8,sizeof(push_8));
CallId = AddC_ID(&Cycle,(BYTE*)&_call,sizeof(_call));
CallId = AddC_ID(&Cycle,(BYTE*)&push_eax,sizeof(push_eax));
CallId = AddC_ID(&Cycle,(BYTE*)&push_eax,sizeof(push_eax));
CallId = AddC_ID(&Cycle,(BYTE*)&push_eax,sizeof(push_eax));
CallId = AddC_ID(&Cycle,(BYTE*)&push_dwptr,sizeof(push_dwptr));
CallId = AddC_ID(&Cycle,(BYTE*)&_call,sizeof(_call));
//StartAddress = Get nt!NtProtectVirtualMemory Address;
Find_CallSigChain(StartAddress,(C_ID*)hHeap);
}

C_ID *AddC_ID(int *Cycle,BYTE* _sig,ULONG Size,C_ID *CallId)
{
if(*Cycle == 0)
{
hHeap = RtlCreateHeap(HEAP_ZERO_MEMORY|HEAP_GROWABLE,0,sizeof(C_ID)*20,sizeof(C_ID),false,0);
CallId = (C_ID*)hHeap;
CallId->_def_sig = _sig;
CallId->Size = Size;
Cycle++;
return CallId;
}
else
{
CallId->_next = RtlAllocateHeap(hHeap,0,sizeof(C_ID));
CallId = CallId->_next;
CallId->_def_sig = _sig;
CallId->Size = Size;
Cycle++;
return CallId;
}
}
C_ID *InitC_ID(BYTE* _sig,ULONG Size)
{
C_ID CallId = 0;
return AddC_ID(_sig,Size,&CallId);
}
ULONG Find_CallSigChain(void*StartAddress,C_ID*Call_Id)
{
size_t szFunc = 0;
size_t szInstr = 0;
int fid = 0;
int sid = 0;
ULONG CallAddr = 0;
szFunc = GetFunctionLength(StartAddress);
CheckC_ID:
if(Call_Id._def_sig != 0)
{

do
{
//szInstr += mlde32(StartAddress);
sid = strcmp(Call_Id._def_sig,_call);
if(sid == 0)
{
fid = memcmp(StartAddress,Call_Id._def_sig,Call_Id.Size);
StartAddress++;
}
else
{
fid = memcmp(StartAddress,Call_Id._def_sig,Call_Id.Size);
StartAddress++;
}

}while(fid != 0);
if(sid == 0)
{
return (ULONG)StartAddress+1;
}
else
{
goto NextC_ID;
}
}
else
{
return 0;
}

NextC_ID:
if(Call_Id._next != 0)
{
Call_Id = Call_Id._next;
goto CheckC_ID;
}
else
{
return 0;
}
return 0;
}


If you continue with the Sig'Trailing' as seen "whacked out' above where im checking the 'parameter bytes for 'likely*' constant occurances from OS to OS..this will need some more work from someone to really flesh it out..but I think this is a likely canidate for Finding UNKNOWN's and being able to call the returned address..maybe..

*I say likely cause I cannot verify this on any other system then XP 2/3..

Also in this posting:
http://www.ureader.com/msg/1474610.aspx

is a way descibed to index into SSDT and extract NtProtectVirtualMemorys address using the SID identifier from ntdll....

cheers,
BanMe

Patafix
October 6th, 2009, 02:45
Hi BanMe,

I like this idea... I was thinking about signature search but like you said, I need to find constant for each Windows version. I'll give a try
Yes I know the EAT parsing method...

ps: why to use notepad to write code? You should use notepad++ or editplus ehehe

regards,

Orkblutt

BanMe
October 6th, 2009, 11:33
I wasn't at home,nor did I have my laptop.. had to download Debugging tools for windows and livekd as it was..and using notepad or something similar is a good excercise every now and then

If I could get livekd listings of nt!NtProtectVirtualMemory I would be more then willing to flesh this out more.. and maybe be able to use the listings as a testing base..I have the livekd listing for ntoskrnl XP sp2 and the ntoskrnlpa with XP sp 3..but this doesnt cover Vista (any sp) or RC7..I got a RC 7 listing and there is some good news, there is some constant 'occurances from OS to OS,atleast the x86 ones.Just have to be selective of which signature chain matches up accross all OS's ..

here is the listing I got from j00ru on RC7 x86..I can Imagine that Vista -> RC 7 isnt that much of a difference, but I would still enjoy going over the listing out of livekd as adding the opcodes to a IDA listing isn't to fun...

http://pastebin.com/d14731dc

the addition of the KeStackAttachProcess call between ObReferenceObByHandle and MiProtectVirtualMemory does complicate matters slightly, But it just makes me see 'faster' and more generic methods :]..

some progress this sig chain should work for BOTH XP and RC 7
Code:

C_ID CallId = {0};
CallId = InitC_ID((BYTE*)&push_0,sizeof(push_0));//ObReferenceObByHandle (push 0)
CallId = AddC_ID(&Cycle,(BYTE*)&push_eax,sizeof(push_eax));//ObReferenceObByHandle (push eax)
CallId = AddC_ID(&Cycle,(BYTE*)&push_dwds,sizeof(push_dwds));//ObReferenceObByHandle (push ds:_PsProcessType) but we only seek the push ds..
CallId = AddC_ID(&Cycle,(BYTE*)&push_8,sizeof(push_8)); //PROCESS_VM_OPERATION constant didnt change..
CallId = AddC_ID(&Cycle,(BYTE*)&_call,sizeof(_call));//this should be the call to ObReferenceObByHandle in NtProtectVirtualMemory
CallId = AddC_ID(&Cycle,(BYTE*)&push_dwptr,sizeof(push_dwptr));//the constant occurance of 0xff,0x75 was chosen here as this opcode sequence doesn't happen until the scanner is past the call for KeStackAttachProcess in RC 7..
CallId = AddC_ID(&Cycle,(BYTE*)&push_eax,sizeof(push_eax));in the preamble to the call to MiProtectVirtualMemory
CallId = AddC_ID(&Cycle,(BYTE*)&push_eax,sizeof(push_eax));in the preamble to the call to MiProtectVirtualMemory
CallId = AddC_ID(&Cycle,(BYTE*)&_call,sizeof(_call));


BanMe

Patafix
October 7th, 2009, 02:57
Nice!!
Here the x86 7 RTM (ultimate) listing:
http://pastebin.com/f4c9361a2

Your previous signature definition should work here too

I think 64bits is an other story (7 ultimate RTM)
http://pastebin.com/fd78eb4b


kind regards,

Orkblutt

BanMe
October 7th, 2009, 09:44
push_dwds = {0xff,0x35}; in the new sig..
removing the push_eax's would speed it up a bit

also If someone could post a listing for XP/Vista 64 bit this would help in making a 64 bit signature... It seems I am pretty good at guessing common occurances in code...
Im coding up a test for XP and 7..I still need vista's 32 bit listing as well,so that I can verify my approach will work there as well..though if it works from XP to 7 vista should follow suit..but I would like to verify that and make changes if needed..

All Help is appreciated

regards,
BanMe

p.s. ahh 64 bit is now making this FUN xD

so going 'only' off of what you provided..
this is my solution to a 64 bit signature that will work across OS versions..

Code:

BYTE MOV_EDX8[5] = {0xBA,0x08 ,0x00,0x00,0x00}; //in the preamble to the ObReferenceObjectByHandleWithTag
BYTE TEST_EAX[2] = {0x85,0xC0};//just after the call to ObReferenceObjectByHandleWithTag
BYTE XOR_ESI[2] = {0x33,0xF6};//just before the preamble to the call for MiProtectVirtualMemory
BYTE MOV_R9DEDI[3] = {0x44, 0x8B, 0xCF}
BYTE _call = 0xe8;


this should work in that order for 7 ultimate 64 bit at a minimum...

Patafix
October 7th, 2009, 11:55

here the Vista 32bits(home edition) listing


PAGE:005FC3DB                         ; NTSTATUS __stdcall NtProtectVirtualMemory(HANDLE ProcessHandle,PVOID *BaseAddress,PULONG ProtectSize,ULONG NewProtect,PULONG OldProtect)

PAGE:005FC3DB                         _NtProtectVirtualMemory@20 proc near    ; DATA XREF: .text:0046DC18o

PAGE:005FC3DB

PAGE:005FC3DB                         var_48          = dword ptr -48h

PAGE:005FC3DB                         var_30          = dword ptr -30h

PAGE:005FC3DB                         BugCheckParameter1= dword ptr -2Ch

PAGE:005FC3DB                         AccessMode      = byte ptr -28h

PAGE:005FC3DB                         var_20          = dword ptr -20h

PAGE:005FC3DB                         var_1C          = dword ptr -1Ch

PAGE:005FC3DB                         ms_exc          = CPPEH_RECORD ptr -18h

PAGE:005FC3DB                         Handle          = dword ptr  8

PAGE:005FC3DB                         BaseAddress     = dword ptr  0Ch

PAGE:005FC3DB                         ProtectSize     = dword ptr  10h

PAGE:005FC3DB                         NewProtect      = dword ptr  14h

PAGE:005FC3DB                         OldProtect      = dword ptr  18h

PAGE:005FC3DB

PAGE:005FC3DB 6A 38                                   push    38h

PAGE:005FC3DD 68 68 27 45 00                          push    offset dword_452768

PAGE:005FC3E2 E8 29 BE E4 FF                          call    __SEH_prolog4

PAGE:005FC3E7 FF 75 14                                push    [ebp+NewProtect]

PAGE:005FC3EA E8 09 0B E8 FF                          call    @MiMakeProtectionMask@4 ; MiMakeProtectionMask(x)

PAGE:005FC3EF 83 F8 FF                                cmp     eax, 0FFFFFFFFh

PAGE:005FC3F2 75 0A                                   jnz     short loc_5FC3FE

PAGE:005FC3F4 B8 45 00 00 C0                          mov     eax, 0C0000045h

PAGE:005FC3F9 E9 65 01 00 00                          jmp     loc_5FC563

PAGE:005FC3FE                         ; ---------------------------------------------------------------------------

PAGE:005FC3FE

PAGE:005FC3FE                         loc_5FC3FE:                             ; CODE XREF: NtProtectVirtualMemory(x,x,x,x,x)+17j

PAGE:005FC3FE 64 A1 24 01 00 00                       mov     eax, large fs:124h

PAGE:005FC404 8B 78 48                                mov     edi, [eax+48h]

PAGE:005FC407 8A 80 E7 00 00 00                       mov     al, [eax+0E7h]

PAGE:005FC40D 88 45 D8                                mov     [ebp+AccessMode], al

PAGE:005FC410 84 C0                                   test    al, al

PAGE:005FC412 74 7E                                   jz      short loc_5FC492

PAGE:005FC414 83 65 FC 00                             and     [ebp+ms_exc.disabled], 0

PAGE:005FC418 8B 55 0C                                mov     edx, [ebp+BaseAddress]

PAGE:005FC41B 8B C2                                   mov     eax, edx

PAGE:005FC41D 8B 0D DC C6 52 00                       mov     ecx, ds:_MmUserProbeAddress

PAGE:005FC423 3B D1                                   cmp     edx, ecx

PAGE:005FC425 72 02                                   jb      short loc_5FC429

PAGE:005FC427 8B C1                                   mov     eax, ecx

PAGE:005FC429

PAGE:005FC429                         loc_5FC429:                             ; CODE XREF: NtProtectVirtualMemory(x,x,x,x,x)+4Aj

PAGE:005FC429 8B 08                                   mov     ecx, [eax]

PAGE:005FC42B 89 08                                   mov     [eax], ecx

PAGE:005FC42D 8B 75 10                                mov     esi, [ebp+ProtectSize]

PAGE:005FC430 8B C6                                   mov     eax, esi

PAGE:005FC432 8B 0D DC C6 52 00                       mov     ecx, ds:_MmUserProbeAddress

PAGE:005FC438 3B F1                                   cmp     esi, ecx

PAGE:005FC43A 72 02                                   jb      short loc_5FC43E

PAGE:005FC43C 8B C1                                   mov     eax, ecx

PAGE:005FC43E

PAGE:005FC43E                         loc_5FC43E:                             ; CODE XREF: NtProtectVirtualMemory(x,x,x,x,x)+5Fj

PAGE:005FC43E 8B 08                                   mov     ecx, [eax]

PAGE:005FC440 89 08                                   mov     [eax], ecx

PAGE:005FC442 8B 45 18                                mov     eax, [ebp+OldProtect]

PAGE:005FC445 8B 0D DC C6 52 00                       mov     ecx, ds:_MmUserProbeAddress

PAGE:005FC44B 3B C1                                   cmp     eax, ecx

PAGE:005FC44D 72 02                                   jb      short loc_5FC451

PAGE:005FC44F 8B C1                                   mov     eax, ecx

PAGE:005FC451

PAGE:005FC451                         loc_5FC451:                             ; CODE XREF: NtProtectVirtualMemory(x,x,x,x,x)+72j

PAGE:005FC451 8B 08                                   mov     ecx, [eax]

PAGE:005FC453 89 08                                   mov     [eax], ecx

PAGE:005FC455 8B 0A                                   mov     ecx, [edx]

PAGE:005FC457 89 4D E0                                mov     [ebp+var_20], ecx

PAGE:005FC45A 8B 16                                   mov     edx, [esi]

PAGE:005FC45C 89 55 E4                                mov     [ebp+var_1C], edx

PAGE:005FC45F C7 45 FC FE FF FF FF                    mov     [ebp+ms_exc.disabled], 0FFFFFFFEh

PAGE:005FC466 EB 3A                                   jmp     short loc_5FC4A2

PAGE:005FC466                         ; ---------------------------------------------------------------------------

PAGE:005FC468 90 90 90 90                             dd 90909090h

PAGE:005FC46C 90                                      db 90h

PAGE:005FC46D                         ; ---------------------------------------------------------------------------

PAGE:005FC46D

PAGE:005FC46D                         loc_5FC46D:                             ; DATA XREF: .text:0045277Co

PAGE:005FC46D 8B 45 EC                                mov     eax, [ebp-14h]

PAGE:005FC470 8B 00                                   mov     eax, [eax]

PAGE:005FC472 8B 00                                   mov     eax, [eax]

PAGE:005FC474 89 45 DC                                mov     [ebp-24h], eax

PAGE:005FC477 33 C0                                   xor     eax, eax

PAGE:005FC479 40                                      inc     eax

PAGE:005FC47A C3                                      retn

PAGE:005FC47A                         ; ---------------------------------------------------------------------------

PAGE:005FC47B 90 90 90 90 90                          align 10h

PAGE:005FC480

PAGE:005FC480                         loc_5FC480:                             ; DATA XREF: .text:00452780o

PAGE:005FC480 8B 65 E8                                mov     esp, [ebp-18h]

PAGE:005FC483 C7 45 FC FE FF FF FF                    mov     dword ptr [ebp-4], 0FFFFFFFEh

PAGE:005FC48A 8B 45 DC                                mov     eax, [ebp-24h]

PAGE:005FC48D E9 D1 00 00 00                          jmp     loc_5FC563

PAGE:005FC492                         ; ---------------------------------------------------------------------------

PAGE:005FC492

PAGE:005FC492                         loc_5FC492:                             ; CODE XREF: NtProtectVirtualMemory(x,x,x,x,x)+37j

PAGE:005FC492 8B 75 10                                mov     esi, [ebp+ProtectSize]

PAGE:005FC495 8B 16                                   mov     edx, [esi]

PAGE:005FC497 89 55 E4                                mov     [ebp+var_1C], edx

PAGE:005FC49A 8B 45 0C                                mov     eax, [ebp+BaseAddress]

PAGE:005FC49D 8B 08                                   mov     ecx, [eax]

PAGE:005FC49F 89 4D E0                                mov     [ebp+var_20], ecx

PAGE:005FC4A2

PAGE:005FC4A2                         loc_5FC4A2:                             ; CODE XREF: NtProtectVirtualMemory(x,x,x,x,x)+8Bj

PAGE:005FC4A2 A1 D4 C6 52 00                          mov     eax, ds:_MmHighestUserAddress

PAGE:005FC4A7 3B C8                                   cmp     ecx, eax

PAGE:005FC4A9 76 0A                                   jbe     short loc_5FC4B5

PAGE:005FC4AB B8 F0 00 00 C0                          mov     eax, 0C00000F0h

PAGE:005FC4B0 E9 AE 00 00 00                          jmp     loc_5FC563

PAGE:005FC4B5                         ; ---------------------------------------------------------------------------

PAGE:005FC4B5

PAGE:005FC4B5                         loc_5FC4B5:                             ; CODE XREF: NtProtectVirtualMemory(x,x,x,x,x)+CEj

PAGE:005FC4B5 2B C1                                   sub     eax, ecx

PAGE:005FC4B7 3B C2                                   cmp     eax, edx

PAGE:005FC4B9 73 0A                                   jnb     short loc_5FC4C5

PAGE:005FC4BB

PAGE:005FC4BB                         loc_5FC4BB:                             ; CODE XREF: NtProtectVirtualMemory(x,x,x,x,x)+ECj

PAGE:005FC4BB B8 F1 00 00 C0                          mov     eax, 0C00000F1h

PAGE:005FC4C0 E9 9E 00 00 00                          jmp     loc_5FC563

PAGE:005FC4C5                         ; ---------------------------------------------------------------------------

PAGE:005FC4C5

PAGE:005FC4C5                         loc_5FC4C5:                             ; CODE XREF: NtProtectVirtualMemory(x,x,x,x,x)+DEj

PAGE:005FC4C5 85 D2                                   test    edx, edx

PAGE:005FC4C7 74 F2                                   jz      short loc_5FC4BB

PAGE:005FC4C9 6A 00                                   push    0               ; HandleInformation

PAGE:005FC4CB 8D 45 D4                                lea     eax, [ebp+BugCheckParameter1]

PAGE:005FC4CE 50                                      push    eax             ; Object

PAGE:005FC4CF FF 75 D8                                push    dword ptr [ebp+AccessMode] ; AccessMode

PAGE:005FC4D2 FF 35 28 C0 52 00                       push    ds:_PsProcessType ; ObjectType

PAGE:005FC4D8 6A 08                                   push    8               ; DesiredAccess

PAGE:005FC4DA FF 75 08                                push    [ebp+Handle]    ; Handle

PAGE:005FC4DD E8 C7 DA FE FF                          call    _ObReferenceObjectByHandle@24 ; ObReferenceObjectByHandle(x,x,x,x,x,x)

PAGE:005FC4E2 85 C0                                   test    eax, eax

PAGE:005FC4E4 7C 7D                                   jl      short loc_5FC563

PAGE:005FC4E6 8B 5D D4                                mov     ebx, [ebp+BugCheckParameter1]

PAGE:005FC4E9 3B FB                                   cmp     edi, ebx

PAGE:005FC4EB 74 0F                                   jz      short loc_5FC4FC

PAGE:005FC4ED 8D 45 B8                                lea     eax, [ebp+var_48]

PAGE:005FC4F0 50                                      push    eax             ; int

PAGE:005FC4F1 53                                      push    ebx             ; BugCheckParameter1

PAGE:005FC4F2 E8 10 36 E7 FF                          call    _KeStackAttachProcess@8 ; KeStackAttachProcess(x,x)

PAGE:005FC4F7 33 FF                                   xor     edi, edi

PAGE:005FC4F9 47                                      inc     edi

PAGE:005FC4FA EB 02                                   jmp     short loc_5FC4FE

PAGE:005FC4FC                         ; ---------------------------------------------------------------------------

PAGE:005FC4FC

PAGE:005FC4FC                         loc_5FC4FC:                             ; CODE XREF: NtProtectVirtualMemory(x,x,x,x,x)+110j

PAGE:005FC4FC 33 FF                                   xor     edi, edi

PAGE:005FC4FE

PAGE:005FC4FE                         loc_5FC4FE:                             ; CODE XREF: NtProtectVirtualMemory(x,x,x,x,x)+11Fj

PAGE:005FC4FE 8D 45 D0                                lea     eax, [ebp+var_30]

PAGE:005FC501 50                                      push    eax

PAGE:005FC502 FF 75 14                                push    [ebp+NewProtect]

PAGE:005FC505 8D 45 E4                                lea     eax, [ebp+var_1C]

PAGE:005FC508 50                                      push    eax

PAGE:005FC509 8D 45 E0                                lea     eax, [ebp+var_20]

PAGE:005FC50C 50                                      push    eax

PAGE:005FC50D 53                                      push    ebx

PAGE:005FC50E E8 5D 00 00 00                          call    _MiProtectVirtualMemory@20 ; MiProtectVirtualMemory(x,x,x,x,x)

PAGE:005FC513 89 45 10                                mov     [ebp+ProtectSize], eax

PAGE:005FC516 85 FF                                   test    edi, edi

PAGE:005FC518 74 09                                   jz      short loc_5FC523

PAGE:005FC51A 8D 45 B8                                lea     eax, [ebp+var_48]

PAGE:005FC51D 50                                      push    eax

PAGE:005FC51E E8 97 36 E7 FF                          call    _KeUnstackDetachProcess@4 ; KeUnstackDetachProcess(x)

PAGE:005FC523

PAGE:005FC523                         loc_5FC523:                             ; CODE XREF: NtProtectVirtualMemory(x,x,x,x,x)+13Dj

PAGE:005FC523 8B CB                                   mov     ecx, ebx

PAGE:005FC525 E8 E7 07 E7 FF                          call    @ObfDereferenceObject@4 ; ObfDereferenceObject(x)

PAGE:005FC52A C7 45 FC 01 00 00 00                    mov     [ebp+ms_exc.disabled], 1

PAGE:005FC531 8B 45 E4                                mov     eax, [ebp+var_1C]

PAGE:005FC534 89 06                                   mov     [esi], eax

PAGE:005FC536 8B 45 E0                                mov     eax, [ebp+var_20]

PAGE:005FC539 8B 4D 0C                                mov     ecx, [ebp+BaseAddress]

PAGE:005FC53C 89 01                                   mov     [ecx], eax

PAGE:005FC53E 8B 45 D0                                mov     eax, [ebp+var_30]

PAGE:005FC541 8B 4D 18                                mov     ecx, [ebp+OldProtect]

PAGE:005FC544 89 01                                   mov     [ecx], eax

PAGE:005FC546 EB 11                                   jmp     short loc_5FC559

PAGE:005FC546                         ; ---------------------------------------------------------------------------

PAGE:005FC548 90 90 90 90                             dd 90909090h

PAGE:005FC54C 90                                      db 90h

PAGE:005FC54D                         ; ---------------------------------------------------------------------------

PAGE:005FC54D

PAGE:005FC54D                         loc_5FC54D:                             ; DATA XREF: .text:00452788o

PAGE:005FC54D 33 C0                                   xor     eax, eax

PAGE:005FC54F 40                                      inc     eax

PAGE:005FC550 C3                                      retn

PAGE:005FC550                         ; ---------------------------------------------------------------------------

PAGE:005FC551 90 90 90                                align 4

PAGE:005FC554 90 90                                   db 2 dup(90h)

PAGE:005FC556                         ; ---------------------------------------------------------------------------

PAGE:005FC556

PAGE:005FC556                         loc_5FC556:                             ; DATA XREF: .text:0045278Co

PAGE:005FC556 8B 65 E8                                mov     esp, [ebp-18h]

PAGE:005FC559

PAGE:005FC559                         loc_5FC559:                             ; CODE XREF: NtProtectVirtualMemory(x,x,x,x,x)+16Bj

PAGE:005FC559 C7 45 FC FE FF FF FF                    mov     [ebp+ms_exc.disabled], 0FFFFFFFEh

PAGE:005FC560 8B 45 10                                mov     eax, [ebp+ProtectSize]

PAGE:005FC563

PAGE:005FC563                         loc_5FC563:                             ; CODE XREF: NtProtectVirtualMemory(x,x,x,x,x)+1Ej

PAGE:005FC563                                                                 ; NtProtectVirtualMemory(x,x,x,x,x)+B2j ...

PAGE:005FC563 E8 ED BC E4 FF                          call    __SEH_epilog4

PAGE:005FC568 C2 14 00                                retn    14h

PAGE:005FC568                         _NtProtectVirtualMemory@20 endp



BanMe
October 7th, 2009, 12:18
excellent!! no change should be necessary for 32 bit xD so thats one down..now the 64 bit theoretical signature and a refined code base should be all you need

regards BanMe

BanMe
October 7th, 2009, 13:59
Here is a somewhat more refined code Base..as well as a User mode test of the concept..
nothing to big..
XP_SP3 = the opcodes for NtProtectVirtualMemory
Code:

char push_0[2] = {0x6a,0x00};
char push_eax = 0x50;
char push_dwds[2] = {0xff,0x35};
char push_dwptr[2] = {0xff,0x75};
char push_8[2] = {0x6a,0x08};
char _call = 0xe8;
char XP_SP3[0x16f] = {0x6a,0x44,0x68,0x68,0xa4,0x4e,0x80,0xe8,0x7e,0x07,0xf7,0xff,0x33,0xdb,\
0x89,0x5d,0xd8,0x8b,0x4d,0x14,0xe8,0x64,0x27,0xf7,0xff,0x83,0xf8,0xff,\
0x0f,0x84,0x89,0x17,0x08,0x00,0x64,0xa1,0x24,0x01,0x00,0x00,0x8b,0x48,0x44,\
0x89,0x4d,0xcc,0x8a,0x80,0x40,0x01,0x00,0x00,0x88,0x45,0xd4,0x84,0xc0,\
0x0f,0x84,0x86,0xcb,0x04,0x00,0x89,0x5d,0xfc,0x8b,0x7d,0x0c,0xa1,0xd4,0xfb,0x55,0x80,\
0x3b,0xf8,0x0f,0x83,0x63,0x17,0x08,0x00,0x8b,0x07,0x89,0x07,0x8b,0x75,0x10,\
0xa1,0xd4,0xfb,0x55,0x80,0x3b,0xf0,0x0f,0x83,0x56,0x17,0x08,0x00,0x8b,0x06,\
0x89,0x06,0x8b,0x5d,0x18,0xa1,0xd4,0xfb,0x55,0x80,0x3b,0xd8,0x0f,0x83,0x49,0x17,0x08,0x00,\
0x8b,0x03,0x89,0x03,0x8b,0x0f,0x89,0x4d,0xdc,0x8b,0x16,0x89,0x55,0xe0,\
0x83,0x4d,0xfc,0xff,0xa1,0xdc,0xfb,0x55,0x80,0x3b,0xc8,0x0f,0x87,0x5c,0x17,0x08,0x00,\
0x2b,0xc1,0x3b,0xc2,0x0f,0x82,0x5c,0x17,0x08,0x00,0x85,0xd2,0x0f,0x84,0x54,0x17,0x08,0x00,\
0x6a,0x00,0x8d,0x45,0xe4,0x50,0xff,0x75,0xd4,0xff,0x35,0x58,0x14,0x56,0x80,0x6a,0x08,\
0xff,0x75,0x08,0xe8,0x73,0x2e,0xff,0xff,0x85,0xc0,0x0f,0x8c,0x8e,0x00,0x00,0x00,\
0x8b,0x45,0xe4,0x39,0x45,0xcc,0x0f,0x85,0x9e,0xec,0x01,0x00,0x8d,0x45,0xc8,\
0x50,0xff,0x75,0x14,0x8d,0x45,0xe0,0x50,0x8d,0x45,0xdc,0x50,0xff,0x75,0xe4,\
0xe8,0x8d,0xfd,0xff,0xff,0x89,0x45,0xc4,0x83,0x7d,0xd8,0x00,0x0f,0x85,0x6c,0xec,0x01,0x00,\
0x8b,0x4d,0xe4,0xe8,0x9b,0x72,0xf6,0xff,0xc7,0x45,0xfc,0x01,0x00,0x00,0x00,\
0x80,0x7d,0xd4,0x00,0x74,0x33,0xa1,0xd4,0xfb,0x55,0x80,0x3b,0xf8,0x0f,0x83,0xeb,0x16,0x08,0x00,\
0x8b,0x07,0x89,0x07,0xa1,0xd4,0xfb,0x55,0x80,0x3b,0xf0,0x0f,0x83,0xe5,0x16,0x08,0x00,\
0x8b,0x06,0x89,0x06,0xa1,0xd4,0xfb,0x55,0x80,0x3b,0xd8,0x0f,0x83,0xdf,0x16,0x08,0x00,\
0x8b,0x03,0x89,0x03,0x8b,0x45,0xe0,0x89,0x06,0x8b,0x45,0xdc,0x89,0x07,0x8b,0x45,0xc8,\
0x89,0x03,0x83,0x4d,0xfc,0xff,0x8b,0x45,0xc4,0xe8,0x66,0x06,0xf7,0xff,0xc2,0x14,0x00};

typedef struct _C_ID
{
_C_ID *_next;
char *_def_sig;
ULONG Size;
}C_ID,*PC_ID;

C_ID *InitC_ID(char* _sig,ULONG Size,C_ID *CallId);
C_ID *AddC_ID(char* _sig,ULONG Size,C_ID *CallId);
ULONG Find_CallSigChain(ULONG StartAddress,C_ID *CallId);
int Cycle = 0;
ULONG StartC_ID = 0;

void Find_Addr()
{
ULONG StartAddress = 0;
ULONG CallAddress = 0;
C_ID *CallId = {0};
StartAddress = (ULONG)RtlAllocateHeap(RtlProcessHeap(),HEAP_ZERO_MEMORY|HEAP_GROWABLE,sizeof(XP_SP3));
RtlCopyMemory((void*)StartAddress,(void*)&XP_SP3,sizeof(XP_SP3));
CallId = InitC_ID((char*)push_0,sizeof(push_0),CallId);
CallId = AddC_ID((char*)push_dwds,sizeof(push_dwds),CallId);
CallId = AddC_ID((char*)push_8,sizeof(push_8),CallId);
CallId = AddC_ID((char*)_call,sizeof(_call),CallId);
CallId = AddC_ID((char*)push_dwptr,sizeof(push_dwptr),CallId);
CallId = AddC_ID((char*)_call,sizeof(_call),CallId);
//StartAddress = Get NtProtectVirtualMemory Address;
CallAddress = Find_CallSigChain(StartAddress,(C_ID*)StartC_ID);
}

C_ID *AddC_ID(char *_sig,ULONG Size,C_ID *CallId)
{
if(Cycle == 0)
{
StartC_ID = (ULONG)RtlAllocateHeap(RtlProcessHeap(),HEAP_ZERO_MEMORY,sizeof(C_ID));
CallId = (C_ID*)StartC_ID;
CallId->_def_sig = _sig;
CallId->Size = Size;
Cycle++;
return CallId;
}
else
{
if(Size != 1)
{
CallId->_next = (_C_ID*)RtlAllocateHeap(RtlProcessHeap(),HEAP_ZERO_MEMORY,sizeof(C_ID));
CallId = CallId->_next;
CallId->_def_sig = _sig;
CallId->Size = Size;
Cycle++;
return CallId;
}
else
{
CallId->_next = (C_ID*)RtlAllocateHeap(RtlProcessHeap(),HEAP_ZERO_MEMORY,sizeof(C_ID));
CallId = CallId->_next;
memset(&CallId->_def_sig,0xe8,1);
CallId->Size = Size;
Cycle++;
return CallId;
}
}
}
C_ID *InitC_ID(char* _sig,ULONG Size,C_ID *CallId)
{
return AddC_ID(_sig,Size,CallId);
}
ULONG Find_CallSigChain(ULONG StartAddress,C_ID *CallId)
{
int fid = 0;
ULONG CallAddr = 0;
CheckC_ID:
if(CallId->_def_sig != 0)
{
do
{
if(CallId->_def_sig == (char*)0xe8)
{
fid = memcmp((void*)StartAddress,(void*)&CallId->_def_sig,CallId->Size);
StartAddress++;
}
else
{
fid = memcmp((void*)StartAddress,CallId->_def_sig,CallId->Size);
StartAddress++;
}
}while(fid != 0);
if(CallId->_next == 0)
{
return *(ULONG*)StartAddress;
}
else
{
goto NextC_ID;
}
}
else
{
return 0;
}
NextC_ID:
if(CallId->_next != 0)
{
CallId = CallId->_next;
goto CheckC_ID;
}
else
{
return 0;
}
return 0;
}


my opcodes for MiProtectVirtualMemory are 0x8dfdffff..the address for this is actually 0x805743fb

Patafix
October 7th, 2009, 15:20
Looks really great!!!
I'll give a try tomorrow (i can't right now) to walk through the living NtProtectVirtualMemory from a driver using your method!
Starting to think about all the uses of this method... We will be able to use/hook anything we want at a very deep level.

All the best,

Orkblutt

BanMe
October 7th, 2009, 15:45
eh it was all just fun for me..I still gotta do the 64 bit version of the function/signature but I hope you enjoy it

regards BanMe

Patafix
October 8th, 2009, 02:05
No worry, it's for fun for me too. And yes, I enjoy it ehehe

aionescu
December 13th, 2009, 22:08
Why don't you just get the PTEs you need and change the protection that way? Or grab the VADs and walk them? Seems easier than all this stuff, and the structures haven't changed

Patafix
December 14th, 2009, 03:31
Hi Alex,

you're true. I was just trying to get an idea how to use "internal" non-exported functions... Same thing in my other thread on KeStackAttachProcess.
Anyway, thanks for the tips

Orkblutt