KeStackAttachProcess()

Hi everyone,
I have two questions/problems. To start out with: what’s the best way to read code from a process, say notepad.exe? Here’s* is what I’m doing at the moment, is there a better way?

*:

  1. Register a process callback function
  2. Log the PID of notepad.exe
  3. Open Notepad with ZwOpenProcess(PID)
  4. ZwQueryInformation(HANDLE) // PEB (for the base addresses of the modules I want to read)
  5. PsLookupProcesByProcessId // get the EP
  6. KeStackAttachProcess(EP) // get inside the process context
  7. read the PEB & data into a buffer
    8 Detach & cleanup

This brings me to my second question/problem when I’m trying to attach my thread to that of notepad nothing happens, and when I say nothing I mean really nothing. I get no errors, no BSODS and execution just disappears, leaving behind no trace, no cleanup nothing. One moment everything goes as planned, and the next it’s just gone. This is the code I use to attach & log the PID:

  
void ModuleDumperThread(){  
  
NTSTATUS Status = STATUS_SUCCESS;  
HANDLE hProcessHandle = NULL;  
PLIST_ENTRY Next;  
PLDR_DATA_TABLE_ENTRY LdrDataTableEntry;  
CLIENT_ID clientID;   
ACCESS_MASK DesiredAccess = PROCESS_ALL_ACCESS;  
OBJECT_ATTRIBUTES ObjectAttributes;  
HANDLE hProcessId = hgtPid;  
PROCESS_BASIC_INFORMATION BasicInfoReal;  
ULONG SizeReturned;  
PPEB RealPeb;  
PEPROCESS ep;  
ULONG myPKPROCESS;  
KAPC_STATE \*ka_state = NULL;  
  
InitializeObjectAttributes (&ObjectAttributes, NULL, OBJ_KERNEL_HANDLE, NULL, NULL);  
  
clientID.UniqueProcess = hProcessId;   
 clientID.UniqueThread = NULL;   
  
__try{  
  
Status = ZwOpenProcess(&hProcessHandle, DesiredAccess, &ObjectAttributes, &clientID);  
  
if(Status != STATUS_SUCCESS){  
 DbgPrint("Failed to open process\n");  
 DbgPrint("NtStatus: 0x%x", Status);  
 return;  
 }  
  
Status = gZwQueryprocess(hProcessHandle, ProcessBasicInformation, (PVOID)&BasicInfoReal, sizeof(PROCESS_BASIC_INFORMATION), &SizeReturned);  
  
if(Status != STATUS_SUCCESS){  
 DbgPrint("gZwQueryprocess failed\n");  
 DbgPrint("Size returned: 0x%x\nNtStatus: 0x%x\n", SizeReturned, Status);  
 ZwClose(hProcessHandle);  
 return;  
 }  
  
Status = PsLookupProcessByProcessId(hProcessId, &ep);  
  
if(Status != STATUS_SUCCESS){  
 DbgPrint("PsLookupProcessByProcessId failed\n");  
 DbgPrint("NtStatus: 0x%x\n", Status);  
 return;  
 }  
  
ka_state = ExAllocatePoolWithTag(NonPagedPool, sizeof(KAPC_STATE),'trak');  
  
__asm{  
 mov eax, ep  
 mov eax, [eax] // My structures are not defined, so I dereference like this  
 mov myPKPROCESS, eax  
 }  
  
DbgPrint("Test print\n");  
  
KeStackAttachProcess(&myPKPROCESS, ka_state);  
DbgPrint("Test print\n");  
__try{  
  
__asm{  
 mov eax, fs:[0x30]  
 mov RealPeb, eax  
 }  
  
/\*Next = RealPeb-\>Ldr-\>InLoadOrderModuleList.Blink;  
 LdrDataTableEntry = CONTAINING_RECORD( Next,  
 LDR_DATA_TABLE_ENTRY,  
 LoadOrder  
 );\*/  
 DbgPrint("Module PEB: 0x%x", RealPeb);  
  
}__except( EXCEPTION_EXECUTE_HANDLER ) {  
 DbgPrint("Exception while trying to access the PEB\n");  
 }  
  
KeUnstackDetachProcess(ka_state);  
 ExFreePool(ka_state);  
  
}__except( EXCEPTION_EXECUTE_HANDLER ) {  
 DbgPrint("Exception in ModuleDumper\n");  
 }  
  
ZwClose(hProcessHandle);   
  
if(ep){  
 ObDereferenceObject(ep);   
 }   
return;  
}  

So, long story short, Is there a better way to read the instructions of notepad.exe? Or is this the best method and are there any bugs in my code?

Thanks in advance

wrote in message news:xxxxx@ntdev…
> Hi everyone,
> I have two questions/problems. To start out with: what’s the best way to
> read code from a process, say notepad.exe? Here’s* is what I’m doing at
> the moment, is there a better way?
>

A better (easier) way to read memory from another process is
ReadProcessMemory
http://msdn.microsoft.com/en-us/library/ms680553(v=vs.85).aspx

Its native undocumented analog, NtReadVirtualMemory is a bit hard to call
from
kernel mode, but with certain tricks is doable.

(worked for us - whatever it’s worth - in XP SP2, win7 x86, Vista, Win7 x64
RTM. Not tested on win7 sp1)

Good luck,
–pa

> *:
> 1. Register a process callback function
> 2. Log the PID of notepad.exe
> 3. Open Notepad with ZwOpenProcess(PID)
> 4. ZwQueryInformation(HANDLE) // PEB (for the base addresses of the
> modules I want to read)
> 5. PsLookupProcesByProcessId // get the EP
> 6. KeStackAttachProcess(EP) // get inside the process context
> 7. read the PEB & data into a buffer
> 8 Detach & cleanup
>
> This brings me to my second question/problem when I’m trying to attach my
> thread to that of notepad nothing happens, and when I say nothing I mean
> really nothing. I get no errors, no BSODS and execution just disappears,
> leaving behind no trace, no cleanup nothing. One moment everything goes as
> planned, and the next it’s just gone. This is the code I use to attach &
> log the PID:
>
> <br>&gt;<br>&gt; void ModuleDumperThread(){<br>&gt;<br>&gt; NTSTATUS Status = STATUS_SUCCESS;<br>&gt; HANDLE hProcessHandle = NULL;<br>&gt; PLIST_ENTRY Next;<br>&gt; PLDR_DATA_TABLE_ENTRY LdrDataTableEntry;<br>&gt; CLIENT_ID clientID;<br>&gt; ACCESS_MASK DesiredAccess = PROCESS_ALL_ACCESS;<br>&gt; OBJECT_ATTRIBUTES ObjectAttributes;<br>&gt; HANDLE hProcessId = hgtPid;<br>&gt; PROCESS_BASIC_INFORMATION BasicInfoReal;<br>&gt; ULONG SizeReturned;<br>&gt; PPEB RealPeb;<br>&gt; PEPROCESS ep;<br>&gt; ULONG myPKPROCESS;<br>&gt; KAPC_STATE *ka_state = NULL;<br>&gt;<br>&gt;<br>&gt; InitializeObjectAttributes (&amp;ObjectAttributes, NULL, OBJ_KERNEL_HANDLE,<br>&gt; NULL, NULL);<br>&gt;<br>&gt; clientID.UniqueProcess = hProcessId;<br>&gt; clientID.UniqueThread = NULL;<br>&gt;<br>&gt;<br>&gt; __try{<br>&gt;<br>&gt;<br>&gt; Status = ZwOpenProcess(&amp;hProcessHandle, DesiredAccess, &amp;ObjectAttributes,<br>&gt; &amp;clientID);<br>&gt;<br>&gt; if(Status != STATUS_SUCCESS){<br>&gt; DbgPrint("Failed to open process\n");<br>&gt; DbgPrint("NtStatus: 0x%x", Status);<br>&gt; return;<br>&gt; }<br>&gt;<br>&gt; Status = gZwQueryprocess(hProcessHandle, ProcessBasicInformation,<br>&gt; (PVOID)&amp;BasicInfoReal, sizeof(PROCESS_BASIC_INFORMATION), &amp;SizeReturned);<br>&gt;<br>&gt; if(Status != STATUS_SUCCESS){<br>&gt; DbgPrint("gZwQueryprocess failed\n");<br>&gt; DbgPrint("Size returned: 0x%x\nNtStatus: 0x%x\n", SizeReturned, Status);<br>&gt; ZwClose(hProcessHandle);<br>&gt; return;<br>&gt; }<br>&gt;<br>&gt;<br>&gt; Status = PsLookupProcessByProcessId(hProcessId, &amp;ep);<br>&gt;<br>&gt; if(Status != STATUS_SUCCESS){<br>&gt; DbgPrint("PsLookupProcessByProcessId failed\n");<br>&gt; DbgPrint("NtStatus: 0x%x\n", Status);<br>&gt; return;<br>&gt; }<br>&gt;<br>&gt; ka_state = ExAllocatePoolWithTag(NonPagedPool, sizeof(KAPC_STATE),'trak');<br>&gt;<br>&gt;<br>&gt;<br>&gt;__asm{<br>&gt; mov eax, ep<br>&gt; mov eax, [eax] // My structures are not defined, so I dereference like<br>&gt; this<br>&gt; mov myPKPROCESS, eax<br>&gt; }<br>&gt;<br>&gt; DbgPrint("Test print\n");<br>&gt;<br>&gt; KeStackAttachProcess(&amp;myPKPROCESS, ka_state);<br>&gt; DbgPrint("Test print\n");<br>&gt; __try{<br>&gt;<br>&gt;__ asm{<br>&gt; mov eax, fs:[0x30]<br>&gt; mov RealPeb, eax<br>&gt; }<br>&gt;<br>&gt; /*Next = RealPeb-&gt;Ldr-&gt;InLoadOrderModuleList.Blink;<br>&gt; LdrDataTableEntry = CONTAINING_RECORD( Next,<br>&gt; LDR_DATA_TABLE_ENTRY,<br>&gt; LoadOrder<br>&gt; );*/<br>&gt; DbgPrint("Module PEB: 0x%x", RealPeb);<br>&gt;<br>&gt; }__except( EXCEPTION_EXECUTE_HANDLER ) {<br>&gt; DbgPrint("Exception while trying to access the PEB\n");<br>&gt; }<br>&gt;<br>&gt; KeUnstackDetachProcess(ka_state);<br>&gt; ExFreePool(ka_state);<br>&gt;<br>&gt;<br>&gt; }__except( EXCEPTION_EXECUTE_HANDLER ) {<br>&gt; DbgPrint("Exception in ModuleDumper\n");<br>&gt; }<br>&gt;<br>&gt; ZwClose(hProcessHandle);<br>&gt;<br>&gt; if(ep){<br>&gt; ObDereferenceObject(ep);<br>&gt; }<br>&gt; return;<br>&gt; }<br>&gt;
>
>
>
> So, long story short, Is there a better way to read the instructions of
> notepad.exe? Or is this the best method and are there any bugs in my code?
>
> Thanks in advance
>
>
>

There are numerous problems with this design.

You can’t go groveling into the PEB like this from kernel mode. This is user mode data that the user could have set to anything. You’re creating a security hole by doing this (for example, the pointers hung off the PEB might be maliciously reconfigured to point to kernel mode memory, etc); this isn’t something that is feasible to use in a shipping product by any stretch.

Additionally the logic assuming that fs: somehow points to the thread TEB will plain not work in kernel mode. (Not to mention that you’re working with undocumented data structures whose layout can and does change without notice.)

  • S

-----Original Message-----
From: xxxxx@lists.osr.com [mailto:xxxxx@lists.osr.com] On Behalf Of xxxxx@live.nl
Sent: Saturday, June 11, 2011 2:18 PM
To: Windows System Software Devs Interest List
Subject: [ntdev] KeStackAttachProcess()

Hi everyone,
I have two questions/problems. To start out with: what’s the best way to read code from a process, say notepad.exe? Here’s* is what I’m doing at the moment, is there a better way?

*:

  1. Register a process callback function
  2. Log the PID of notepad.exe
  3. Open Notepad with ZwOpenProcess(PID)
  4. ZwQueryInformation(HANDLE) // PEB (for the base addresses of the modules I want to read)
  5. PsLookupProcesByProcessId // get the EP
  6. KeStackAttachProcess(EP) // get inside the process context
  7. read the PEB & data into a buffer
    8 Detach & cleanup

This brings me to my second question/problem when I’m trying to attach my thread to that of notepad nothing happens, and when I say nothing I mean really nothing. I get no errors, no BSODS and execution just disappears, leaving behind no trace, no cleanup nothing. One moment everything goes as planned, and the next it’s just gone. This is the code I use to attach & log the PID:

  
void ModuleDumperThread(){  
  
NTSTATUS Status = STATUS_SUCCESS;  
HANDLE hProcessHandle = NULL;  
PLIST_ENTRY Next;  
PLDR_DATA_TABLE_ENTRY LdrDataTableEntry; CLIENT_ID clientID; ACCESS_MASK DesiredAccess = PROCESS_ALL_ACCESS; OBJECT_ATTRIBUTES ObjectAttributes; HANDLE hProcessId = hgtPid; PROCESS_BASIC_INFORMATION BasicInfoReal; ULONG SizeReturned; PPEB RealPeb; PEPROCESS ep; ULONG myPKPROCESS; KAPC_STATE \*ka_state = NULL;  
  
InitializeObjectAttributes (&ObjectAttributes, NULL, OBJ_KERNEL_HANDLE, NULL, NULL);  
  
clientID.UniqueProcess = hProcessId;   
 clientID.UniqueThread = NULL;   
  
__try{  
  
Status = ZwOpenProcess(&hProcessHandle, DesiredAccess, &ObjectAttributes, &clientID);  
  
if(Status != STATUS_SUCCESS){  
 DbgPrint("Failed to open process\n");  
 DbgPrint("NtStatus: 0x%x", Status);  
 return;  
 }  
  
Status = gZwQueryprocess(hProcessHandle, ProcessBasicInformation, (PVOID)&BasicInfoReal, sizeof(PROCESS_BASIC_INFORMATION), &SizeReturned);  
  
if(Status != STATUS_SUCCESS){  
 DbgPrint("gZwQueryprocess failed\n");  
 DbgPrint("Size returned: 0x%x\nNtStatus: 0x%x\n", SizeReturned, Status);  
 ZwClose(hProcessHandle);  
 return;  
 }  
  
Status = PsLookupProcessByProcessId(hProcessId, &ep);  
  
if(Status != STATUS_SUCCESS){  
 DbgPrint("PsLookupProcessByProcessId failed\n");  
 DbgPrint("NtStatus: 0x%x\n", Status);  
 return;  
 }  
  
ka_state = ExAllocatePoolWithTag(NonPagedPool, sizeof(KAPC_STATE),'trak');  
  
__asm{  
 mov eax, ep  
 mov eax, [eax] // My structures are not defined, so I dereference like this  
 mov myPKPROCESS, eax  
 }  
  
DbgPrint("Test print\n");  
  
KeStackAttachProcess(&myPKPROCESS, ka_state);  
DbgPrint("Test print\n");  
__try{  
  
__asm{  
 mov eax, fs:[0x30]  
 mov RealPeb, eax  
 }  
  
/\*Next = RealPeb-\>Ldr-\>InLoadOrderModuleList.Blink;  
 LdrDataTableEntry = CONTAINING_RECORD( Next,  
 LDR_DATA_TABLE_ENTRY,  
 LoadOrder  
 );\*/  
 DbgPrint("Module PEB: 0x%x", RealPeb);  
  
}__except( EXCEPTION_EXECUTE_HANDLER ) {  
 DbgPrint("Exception while trying to access the PEB\n");  
 }  
  
KeUnstackDetachProcess(ka_state);  
 ExFreePool(ka_state);  
  
}__except( EXCEPTION_EXECUTE_HANDLER ) {  
 DbgPrint("Exception in ModuleDumper\n");  
 }  
  
ZwClose(hProcessHandle);   
  
if(ep){  
 ObDereferenceObject(ep);   
 }   
return;  
}  

So, long story short, Is there a better way to read the instructions of notepad.exe? Or is this the best method and are there any bugs in my code?

Thanks in advance


NTDEV is sponsored by OSR

For our schedule of WDF, WDM, debugging and other seminars visit:
http://www.osr.com/seminars

To unsubscribe, visit the List Server section of OSR Online at http://www.osronline.com/page.cfm?name=ListServer

@Pavel A

Could you please tell/show me how you did it, I tried resolving it’s routine address by calling MmGetSystemRoutineAddress(). But then I read that it’s not exported. I’m very new to driver development so I have no idea on how to get to it. Do you have any suggestions?

using unexported system calls from kernel mode is not recommended ,
Usually this is impelemented through a disasembling ntdll.dll to find an index in the SDT array and finding a pointer to ZwReadVirtualMemory from an SDT entry

wrote in message news:xxxxx@ntdev…
> @Pavel A
>
> Could you please tell/show me how you did it, I tried resolving it’s
> routine address by calling MmGetSystemRoutineAddress(). But then I read
> that it’s not exported. I’m very new to driver development so I have no
> idea on how to get to it. Do you have any suggestions?
>

I did exactly what suggested .

Regards,
–pa

http://msdn.microsoft.com/en-us/library/ff549659(v=vs.85).aspx

On 6/14/11, Pavel A. wrote:
> wrote in message news:xxxxx@ntdev…
>> @Pavel A
>>
>> Could you please tell/show me how you did it, I tried resolving it’s
>> routine address by calling MmGetSystemRoutineAddress(). But then I read
>> that it’s not exported. I’m very new to driver development so I have no
>> idea on how to get to it. Do you have any suggestions?
>>
>
> I did exactly what suggested .
>
> Regards,
> --pa
>
>
>
> —
> NTDEV is sponsored by OSR
>
> For our schedule of WDF, WDM, debugging and other seminars visit:
> http://www.osr.com/seminars
>
> To unsubscribe, visit the List Server section of OSR Online at
> http://www.osronline.com/page.cfm?name=ListServer
>