Example #1
0
PVOID HookFunction(LPTSTR ModuleName, LPCSTR FunctionName, PVOID MyFunction)
{
	PVOID oldFunction = NULL;
	PVOID proxyFunction = NULL;
	LPBYTE opCode = NULL;
	DWORD backupLen = 0;
	DWORD oldProtect = 0;
	TCHAR tzTemp[MAX_PATH] = {0};

	// Get original function address
	oldFunction = GetProcAddress(GetModuleHandle(ModuleName), FunctionName);
	if (!oldFunction)
	{
		wsprintf(tzTemp, TEXT("Failed to find the function: %hs\n"), FunctionName);
		OutputDebugText(tzTemp);
		return NULL;
	}

	// Get the exact length
	while (backupLen < JumpCodeSize)
		backupLen += size_of_code((LPBYTE)((DWORD)oldFunction + backupLen), &opCode);

	// Fill the data
	*(DWORD *)(JumpCode + 1) = (DWORD)MyFunction;
	*(DWORD *)(JumpbackCode + 1) = (DWORD)oldFunction + backupLen;

	// Allocate space for proxy function
	proxyFunction = VirtualAlloc(NULL, backupLen + JumpCodeSize, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
	if (!proxyFunction)
	{
		wsprintf(tzTemp, TEXT("Failed to allocate space for the function: %hs\n"), FunctionName);
		OutputDebugText(tzTemp);
		return NULL;
	}
	 // Fill proxy function and flush instructions
	RtlCopyMemory(proxyFunction, oldFunction, backupLen);
	RtlCopyMemory((PVOID)((DWORD)proxyFunction + backupLen), JumpbackCode, JumpbackCodeSize);
	FlushInstructionCache(GetModuleHandle(NULL), proxyFunction, backupLen + JumpCodeSize);

	// Modify original function
	VirtualProtect(oldFunction, JumpCodeSize, PAGE_EXECUTE_READWRITE, &oldProtect);
	RtlCopyMemory(oldFunction, JumpCode, JumpCodeSize);
	VirtualProtect(oldFunction, JumpCodeSize, oldProtect, &oldProtect);
	FlushInstructionCache(GetModuleHandle(NULL), oldFunction, JumpCodeSize);

	return proxyFunction;
}
Example #2
0
ULONG
SpliceFunctionStart(
	IN	PVOID	OriginalAddress,
    IN	PVOID	HookFunction,
	OUT	PVOID	SplicingBuffer,
	IN	ULONG	MaxLength,
	OUT	PVOID	BackupBuffer,
	OUT	PULONG	BytesWritten,
	IN	BOOLEAN	WorkAtCurrentIrql
	)
{
	ULONG cr0;
	KIRQL Irql;
	ULONG Len;
	ULONG Ptr, NextAddress;
	NTSTATUS Status = STATUS_UNSUCCESSFUL;
//	ULONG CapturedBytesWritten;

	KdPrint(("Entering SpliceFunctionStart( 0x%08x, 0x%08x, 0x%08x, 0x%08x, 0x%08x )\n",
		OriginalAddress,
		HookFunction,
		SplicingBuffer,
		sizeof(MaxLength),
		BytesWritten));

	KdPrint(("Saving state\n"));

	// Save
	cr0 = IntDisableWP( ); // Disable Write-Protection on system pages
	if( !WorkAtCurrentIrql )
		KeRaiseIrql( HIGH_LEVEL, &Irql ); // Raise IRQL

	KdPrint(("cr0=0x%08x\n", cr0));

	//
    // Copy integer number of instructions to the buffer
	//

	KdPrint(("Copying instructions from OriginalAddress=%08x\n", OriginalAddress));
	*BytesWritten = 0;
	for( Ptr = (ULONG)OriginalAddress; Ptr < ((ULONG)OriginalAddress+5); Ptr+=Len )
	{
		Len = size_of_code( (UCHAR*)Ptr );

		KdPrint(("Command decoded at address 0x%08x, length 0x%08x\n", Ptr, Len));
		
		KdPrint(("Ptr=%08x,OriginalAddress=%08x, MaxLength=%08x, Ptr-OriginalAddress+5=%08x\n", Ptr, OriginalAddress, MaxLength, (Ptr-(ULONG)OriginalAddress+5)));

		if( Ptr < ((ULONG)OriginalAddress+5) )
		{
			if( (Ptr-(ULONG)OriginalAddress+5) >= MaxLength )
			{
				KdPrint(("Error: buffer is too small\n"));

				Status = STATUS_INFO_LENGTH_MISMATCH;
				goto _exit;
			}

			memcpy( (PVOID)((ULONG)SplicingBuffer+(Ptr-(ULONG)OriginalAddress)), (PVOID)Ptr, Len );
			*BytesWritten += Len;
		}
	}

	NextAddress = Ptr;
	KdPrint(("*BytesWritten = 0x%08x, Ptr = 0x%08x, NextAddress = 0x%08x\n", *BytesWritten, Ptr, NextAddress));

	/*
	// Fixup buffer commands
	KdPrint(("Fixing up instructions\n"));
	CapturedBytesWritten = *BytesWritten;
	for( Ptr = (ULONG)SplicingBuffer; Ptr < ((ULONG)SplicingBuffer+CapturedBytesWritten); Ptr+=Len )
	{
		BOOLEAN FixupPrevious;
		ULONG	PreviousFixupOffset, PreviousPreviousFixupOffset;

 		Len = size_of_code( (BYTE*)Ptr );

		FixupPrevious = DcpFixupCommand( (PVOID)Ptr, (ULONG)OriginalAddress+Ptr-(ULONG)SplicingBuffer, SplicingBuffer, FALSE, 0, 0, BytesWritten, &Len, &PreviousFixupOffset );
		if( FixupPrevious )
		{
			// Fixup all previous commands
			ULONG TempPtr, TempLen;

			for( TempPtr = (ULONG)SplicingBuffer; TempPtr < Ptr; TempPtr+=TempLen )
			{
				TempLen = size_of_code( (BYTE*)TempPtr );

				if( DcpFixupCommand( (PVOID)TempPtr, (ULONG)OriginalAddress+TempPtr-(ULONG)SplicingBuffer, SplicingBuffer, TRUE, PreviousFixupOffset, Ptr, BytesWritten, &TempLen, &PreviousPreviousFixupOffset) )
				{
					KdPrint(("Nested fixing up is not supported (nested depth >2, PreviousPreviousFixupOffset=%d)\n", PreviousPreviousFixupOffset));
					// Hard case. Break

					Status = STATUS_INVALID_PARAMETER;
					goto _exit;
				}
				KdPrint((" -> Temp command fixed up at address 0x%08x, length 0x%08x\n", TempPtr, TempLen));
			}
			KdPrint((" -> Finished fixing up previous commands\n"));
		}

		KdPrint(("Command fixed up at address 0x%08x, length 0x%08x\n", Ptr, Len));
	}
	*/

	KdPrint(("Generating splicing buffer\n"));

	//
	// Emit splicing jump to the buffer
	//

	memcpy( BackupBuffer, OriginalAddress, 5 );

	EmitJumpCommand( OriginalAddress, HookFunction );

	KdPrint(("Original address bytes: %02x %02x %02x %02x %02x\n",
		((PUCHAR)OriginalAddress)[0],
		((PUCHAR)OriginalAddress)[1],
		((PUCHAR)OriginalAddress)[2],
		((PUCHAR)OriginalAddress)[3],
		((PUCHAR)OriginalAddress)[4]
		));

	//
	// Emit continuation jump to the function continuation
	//

	Ptr = ((ULONG)SplicingBuffer+*BytesWritten);
	EmitJumpCommand( Ptr, NextAddress );

	Status = STATUS_SUCCESS;

_exit:

	// Restore
	KdPrint(("Irql = %x, cr0 = %x\n", Irql, cr0));
	
	if( !WorkAtCurrentIrql )
		KeLowerIrql( Irql ); // Lower IRQL
	IntRestoreWP( cr0 ); // Restore Write-Protection bit

	return Status;
}