Using different parameters for hooking

Sometimes when you want to hook a function, you don’t know what parameter to use. For example XxOpenProcess (I know I always use the same API, but thats because its an easy one and useful)

NtOpenProcess(

OUT PHANDLE ProcessHandle,
IN ACCESS_MASK AccessMask,
IN POBJECT_ATTRIBUTES ObjectAttributes,
IN PCLIENT_ID ClientId );

In my other article we were using “ClientID”, but you may also use other parameters like the first one “ProcessHandle”

The goal of this article is not to deny process termination, but to stop memory editors attaching* to our process.

Before we start, I’m going to show you 2 “custom” made functions.

ULONG gProcessNameOffset;

ULONG GetProcessNameOffset()
{

PEPROCESS curproc;
int i;

curproc = PsGetCurrentProcess();
// This will fail if the EPROCESS grows larger
// than a page size.
for( i = 0; i < 3*PAGE_SIZE; i++ )
{
if( !strncmp( “System”, (PCHAR)curproc + i, strlen(“System”) ))
{
gProcessNameOffset = i;
}
}
return 0;
}

GetProcessNameOffset returns the offset within the EPROCESS structure of the process name

BOOL GetProcessName( PCHAR theName )
{
PEPROCESS curproc;
char *nameptr;

if( gProcessNameOffset )
{
curproc = PsGetCurrentProcess();
nameptr = (PCHAR) curproc + gProcessNameOffset;
strncpy( theName, nameptr, NT_PROCNAMELEN );
theName[NT_PROCNAMELEN] = 0; /* NULL at end */
return TRUE;
}
return FALSE;
}

GetProcessName copy the process name into the specified buffer. This is very useful, you can use it like this:

CHAR ProcessName[PROCNAMELEN];
DbgPrint(“ZwOpenProcess() called from %s\n”, ProcessName);

Okay 1 more thing before we start.

// Length of process name (rounded up to next DWORD)
#define PROCNAMELEN 20
// Maximum length of NT process name
#define NT_PROCNAMELEN 16

Okay, let’s start! First lets make our function prototype. The parameters must be the same as the original function.

NTSTATUS NewZwOpenProcess(
OUT PHANDLE ProcessHandle,
IN ACCESS_MASK DesiredAccess,
IN POBJECT_ATTRIBUTES ObjectAttributes,
IN PCLIENT_ID ClientId OPTIONAL
) {

Then let’s add this (OldZwOpenProcess points to the original function)

NTSTATUS ntStatus;
NTSTATUS ntStatus2;
CHAR CallerProcessName[PROCNAMELEN];

GetProcessName(CallerProcessName);

ntStatus = ((ZWOPENPROCESS)(OldZwOpenProcess)) ( //Original ZwOpenProcess()
ProcessHandle,
DesiredAccess,
ObjectAttributes,
ClientId OPTIONAL);

if( NT_SUCCESS(ntStatus))

{

Now we are going to use ObReferenceObjectByHandle to get the EPROCESS from the handle.

ntStatus = ObReferenceObjectByHandle(
*ProcessHandle,
PROCESS_ALL_ACCESS,
NULL,
KernelMode,
&Process, //Will hold the EPROCESS
NULL);

if(NT_SUCCESS(ntStatus))
{

Now that we got the EPROCESS address (“Process” is holding it), we want to get the name. We do that like this (If you noticed, it almost does the same thing as GetProcessName):

//DbgPrint(“EPROCESS: 0x%08lX\n”, Process);
nameptr = (PCHAR)Process + gProcessNameOffset;
strncpy(Target, nameptr, NT_PROCNAMELEN);
Target[NT_PROCNAMELEN] = 0; /* NULL at end */
//DbgPrint(“Targeted Process %s”,Target);

Now we do some comparing (ProtectedProcess, is a buffer holding the name of the protected process) We check if the targeted process is our process, if it is, we close the handle and make it return STATUS_INVALID_HANDLE

if(!strncmp(Target,ProtectedProcess,NT_PROCNAMELEN)==0)
{
ZwClose(ProcessHandle); //Close Handle
DbgPrint(“OpenProcess called by %s\n”,CallerProcessName);
DbgPrint(“Targeting %s\n”,Target);
DbgPrint(“Returning STATUS_INVALID_HANDLE”);
ntStatus = STATUS_INVALID_HANDLE; //Return invalid handle
ProcessHandle = 0; //Handle = 0;
}

The full prototype code:

NTSTATUS NewZwOpenProcess(
OUT PHANDLE ProcessHandle,
IN ACCESS_MASK DesiredAccess,
IN POBJECT_ATTRIBUTES ObjectAttributes,
IN PCLIENT_ID ClientId OPTIONAL
)
{

NTSTATUS ntStatus;
NTSTATUS ntStatus2;
CHAR Target[PROCNAMELEN];
CHAR CallerProcessName[PROCNAMELEN];
PEPROCESS EProcess;
char *nameptr;

GetProcessName(CallerProcessName);

ntStatus = ((ZWOPENPROCESS)(OldZwOpenProcess)) ( //Original ZwOpenProcess()
ProcessHandle,
DesiredAccess,
ObjectAttributes,
ClientId OPTIONAL);

if( NT_SUCCESS(ntStatus))

{
ntStatus = ObReferenceObjectByHandle(
*ProcessHandle,
PROCESS_ALL_ACCESS,
NULL,
KernelMode,
&EProcess, //Will hold the EPROCESS
NULL);

if(NT_SUCCESS(ntStatus))
{
//DbgPrint(”EPROCESS: 0x%08lX\n”, EProcess);
nameptr = (PCHAR)EProcess + gProcessNameOffset;
strncpy(Target, nameptr, NT_PROCNAMELEN);
Target[NT_PROCNAMELEN] = 0; /* NULL at end */
//DbgPrint(“Targeted Process %s”,Target);

if(!strncmp(Target,ProtectedProcess,NT_PROCNAMELEN)==0)
{
ZwClose(ProcessHandle); //Close Handle
DbgPrint(“OpenProcess called by %s\n”,CallerProcessName);
DbgPrint(“Targeting %s\n”,Target);
DbgPrint(“Returning STATUS_INVALID_HANDLE”);
ntStatus = STATUS_INVALID_HANDLE; //Return invalid handle
ProcessHandle = 0; //Handle = 0;
}
}
}
return ntStatus; //STATUS_INVALID_HANDLE
}

protected

Well thats it for this post, if you like that kind of stuff, you may want to visit Dual’s blog. He has some interesting advanced articles.

Now you may be asking why we did all of this when we could of used “ClientID” parameter. Thats because not every function has multiple useful parameters.

For example XxReadVirtualMemory As you see, only the first parameter is really useful to us, therefor you are going to use the method described in this article. Thanks for reading and visiting, if you find any errors or bugs, leave a comment =)

*Memory editors such as CheatEngine, can still open your process, since it uses it’s own routine of OpenProcess (Must be enabled in options -> Extra)

5 Responses to “Using different parameters for hooking”

  1. Rhys M. Says:

    You can get the EPROCESS like such as well:

    PEPROCESS PeProcess;
    ULONG Bytes;
    PROCESS_BASIC_INFORMATION PBI;
    RtlZeroMemory(&PBI, sizeof(PROCESS_BASIC_INFORMATION));
    ZwQueryInformationProcess(ProcessHandle,ProcessBasicInformation,&PBI,sizeof(PROCESS_BASIC_INFORMATION),&Bytes);
    PsLookupProcessByProcessId( (HANDLE)PBI.UniqueProcessId, &PeProcess );

  2. Rhys M. Says:

    I forgot to mention in the above case, that it assumes you’ve got the process handle.

  3. Lakeforestsportsspot7484$anchor$basketball Betting,final Four,final Four Betting,final Four Gambling,final Four Sports Book,final Four Sportsbook,march Madness,march Madness Betting,march Madness Gambling,march Madness Sports Book,march Madness Sportsbook Says:

    Lakeforestsportsspot7484$anchor$basketball Betting,final Four,final Four Betting,final Four Gambling,final Four Sports Book,final Four Sportsbook,march Madness,march Madness Betting,march Madness Gambling,march Madness Sports Book,march Madness Sport…

    Lakeforestsportsspot7484$anchor$basketball Betting,final Four,final Four Betting,final Four Gambling,final Four Sports Book,final Four Sportsbook,march Madness,march Madness Betting,march Madness Gambling,march Madness Sports Book,march Madness Sportsb…

  4. Nooby Coder Says:

    Could you possibly post a link for the full source file?

    Thanks

  5. Jens Says:

    Hi. Nice source. Anyway, i actually tried to implemend it since i hook some functions not exported by ntoskrnl.exe and wanted to get the name from handle.
    There seem to be some bugs, since the output is just nonsense.

    Greets

Leave a Reply