A forum for reverse engineering, OS internals and malware analysis 

Forum for discussion about kernel-mode development.
 #8659  by Tigzy
 Tue Sep 20, 2011 2:52 pm
or you can hardcode the offset (or define the structure) for each OS version.
The KTHREAD is a H.U.G.E structure , and as only need this offest, mayber it's better to get this dynamically.
Any help to walk throught the ExGetPreviousMode bytes in C (with explanation) ? I'm currently not able to do so.
 #8662  by r2nwcnydc
 Tue Sep 20, 2011 5:47 pm
Tigzy wrote: nt!ExGetPreviousMode:
8052793a 64a124010000 mov eax,dword ptr fs:[00000124h]
80527940 8a8040010000 mov al,byte ptr [eax+140h]
80527946 c3 ret
80527947 cc int 3
80527948 cc int 3
80527949 cc int 3
8052794a cc int 3
8052794b cc int 3
Assuming this is the entire function then I think this should work:
Code: Select all
offset = (ULONG)(((PCHAR)ExGetPreviousMode) + 8);
You could add some additional error checking if you want (check for the 8a80 before the offset), but if you can verify that this is the same for all OSes, then you should be ok without it.
 #8664  by Alex
 Tue Sep 20, 2011 6:49 pm
Tigzy wrote:I'm currently trying to bypass every sort ok hooks to kill a PID.
If so, you can't be sure that other lower functions will be safe (PsLookupProcessByProcessId for example). But keep in mind this is a cat and mouse game - PspTerminateThreadByPointer, PsLookupProcessByProcessId & PspTerminateThreadByPointer, 12 ways to terminate a process.
 #8674  by EP_X0FF
 Wed Sep 21, 2011 3:40 pm
Regarding to PreviousMode manipulations on x86. They works everywhere.
Originally the following code was written by a_d_13 for his DriverDetect (RootRepeal).
Code: Select all
VOID SetPreviousMode(BYTE Mode)
{
    ULONG ThreadOffset;
    PETHREAD CurrentThread = (PETHREAD)KeGetCurrentThread();

    ThreadOffset = *(DWORD *)((PCHAR)ExGetPreviousMode + 0x08);   
    *(BYTE *)((PCHAR)CurrentThread + ThreadOffset) = Mode;
}

BYTE GetPreviousMode()
{
    ULONG ThreadOffset;
    PETHREAD CurrentThread = (PETHREAD)KeGetCurrentThread();

    ThreadOffset = *(DWORD *)((PCHAR)ExGetPreviousMode + 0x08);   
    return (*(BYTE *)((PCHAR)CurrentThread + ThreadOffset));
}
 #8684  by Tigzy
 Wed Sep 21, 2011 6:26 pm
Thanks EP_X0FF :!:

PS: I'm not sure to understand the utility of GetPreviousMode as ExGetPreviousMode doing exactly this...
Well it's a direct read into the structure, but why he has recoded it?

@Alex: I'm aware of the 12 ways to kill. 6 of them are implemented into RogueKiller (my tool) , and I try to implement for now a direct call to NtTerminateProcess.
This should bypass the SSDT Hooks, but I know there's always tons of methods to avoid this (inline hook for example, or some Termination Routine notification maybe?)
 #8692  by Tigzy
 Thu Sep 22, 2011 7:15 am
S.O.L.V.E.D !

Thanks everybody
With the previousMode set to KernelMode, no more access violation

Here's my code :
Assuming the true NtOpenProcess & NtTerminateProcess adresses are known
Code: Select all
case IOCTL_KILL_PID:
			{
				PDWORD pBufferIn;	
				NTSTATUS Status;	
				HANDLE process;
				KPROCESSOR_MODE previousMode;
				
				OBJECT_ATTRIBUTES ObjectAttributes; 
				CLIENT_ID ClientId; 
				ACCESS_MASK DesiredAccess;
				
				pBufferIn = pIrp->AssociatedIrp.SystemBuffer;	
				DbgPrint("Killing %d\n", pBufferIn[0]);	
				
				if (OrigNtTerminateProcess != 0x0 && OrigNtOpenProcess != 0x0)
				{
					DesiredAccess = PROCESS_TERMINATE;				
					InitializeObjectAttributes(&ObjectAttributes, NULL, 0, NULL, NULL);
					ClientId.UniqueProcess = (HANDLE)pBufferIn[0]; 
					ClientId.UniqueThread = 0;
					
					//---- Switch previous mode ----					
					previousMode = GetPreviousMode();
					SetPreviousMode(KernelMode);						
					//--------------------------------
				
					Status  =  ((NTOPENPROCESS) OrigNtOpenProcess)( &process, DesiredAccess, &ObjectAttributes,  &ClientId); 
					if (NT_SUCCESS(Status))
					{						
						retVal = ((NTTERMINATEPROCESS)(OrigNtTerminateProcess)) (process, 0);						
						pIrp->IoStatus.Information = 1;
						ZwClose(process);
					}
					else
					{
						DbgPrint("OpenProcess failed 0x%x\n", Status);
						retVal = STATUS_UNSUCCESSFUL;
						pIrp->IoStatus.Information = 0;
					}
					
					//------- Restore previousMode -------
					SetPreviousMode(previousMode);
					//------------------------------------	
				}
				
				break;
			}