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?
*:
- Register a process callback function
- Log the PID of notepad.exe
- Open Notepad with ZwOpenProcess(PID)
- ZwQueryInformation(HANDLE) // PEB (for the base addresses of the modules I want to read)
- PsLookupProcesByProcessId // get the EP
- KeStackAttachProcess(EP) // get inside the process context
- 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