首页
论坛
课程
招聘
[原创]ring3 & ring0 通用InlineHook代码(修补)
2008-8-27 05:00 10861

[原创]ring3 & ring0 通用InlineHook代码(修补)

2008-8-27 05:00
10861
修补加强了下,支持多核,多线程
一晚上的战绩, 希望尊重版权, 写一个ring3下的例子,ring0下就不写了,很简单

#include <stdio.h>
#include "InlineHook.h"

typedef void (__stdcall *__Sleep)(DWORD);
__Sleep			realSleep = NULL;

VOID
__stdcall
MySleep(
	IN DWORD dwMilliseconds
	)
{
	printf("Sleep(%d) Called\n", dwMilliseconds);

	return realSleep(dwMilliseconds);
}

int main(int argc, char* argv[])
{
	InlineHook(Sleep, MySleep, &realSleep);
	Sleep(10);
	UnInlineHook(Sleep, realSleep);
	return 0;
}

主文件代码如下

/*++

Copyright (c) 2008/08/27 By CoolDiyer

Abstract:

Ring3 all-purpose inline hook module
					  
--*/

#if !defined(AFX_INLINEHOOK_H_INCLUDED)
#define AFX_INLINEHOOK_H_INCLUDED

#ifdef WIN32
#define RING3
#endif

#ifdef RING3
#include <windows.h>
#else
#include <windef.h>
#endif

#include "LDasm.h"

#ifdef RING3
#define __malloc(_s)	VirtualAlloc(NULL, _s, MEM_COMMIT, PAGE_EXECUTE_READWRITE)
#define __free(_p)		VirtualFree(_p, 0, MEM_RELEASE)
#define JMP_SIZE		5
#else
#define __malloc(_s)	ExAllocatePool(NonPagedPool, _s)
#define __free(_p)		ExFreePool(_p)
#define JMP_SIZE		7
#endif

#ifdef RING3

BOOL
WriteReadOnlyMemory(
	LPBYTE	lpDest,
	LPBYTE	lpSource,
	ULONG	Length
	)
/*++
	写只读内存, ring3下就不要锁了
--*/
{
	BOOL				bRet;
	DWORD				dwOldProtect;
	bRet = FALSE;

	// 使前几个字节的内存可写
	if (!VirtualProtect(lpDest, Length, PAGE_READWRITE, &dwOldProtect))
	{
		return bRet;
	}

	memcpy(lpDest, lpSource, Length);

	bRet = VirtualProtect(lpDest, Length, dwOldProtect, &dwOldProtect);

	return	bRet;
}

#else

NTSTATUS
WriteReadOnlyMemory(
	LPBYTE	lpDest,
	LPBYTE	lpSource,
	ULONG	Length
	)
/*++
	写只读内存(源于Mark代码)
--*/
{
	NTSTATUS	status;
	KSPIN_LOCK	spinLock;
	KIRQL		oldIrql;
	PMDL		pMdlMemory;
	LPBYTE		lpWritableAddress;

	status = STATUS_UNSUCCESSFUL;

	pMdlMemory = IoAllocateMdl(lpDest, Length, FALSE, FALSE, NULL);

	if (NULL == pMdlMemory) return status;

	MmBuildMdlForNonPagedPool(pMdlMemory);
    MmProbeAndLockPages(pMdlMemory, KernelMode, IoWriteAccess);
	lpWritableAddress = MmMapLockedPages(pMdlMemory, KernelMode);
    if (NULL != lpWritableAddress)
	{
		oldIrql	= 0;
		KeInitializeSpinLock(&spinLock);
		KeAcquireSpinLock(&spinLock, &oldIrql);

		memcpy(lpWritableAddress, lpSource, Length);

		KeReleaseSpinLock(&spinLock, oldIrql);
		MmUnmapLockedPages(lpWritableAddress, pMdlMemory);

		status = STATUS_SUCCESS;
	}

	MmUnlockPages(pMdlMemory);
    IoFreeMdl(pMdlMemory);

	return	status;
}

#endif

BOOL 
GetPatchSize(
	IN	void *Proc,			/* 需要Hook的函数地址 */
	IN	DWORD dwNeedSize,	/* Hook函数头部占用的字节大小 */
	OUT LPDWORD lpPatchSize	/* 返回根据函数头分析需要修补的大小 */
	)
/*++
	计算函数头需要Patch的大小
--*/
{
	DWORD	Length;
	PUCHAR	pOpcode;
	DWORD	PatchSize = 0;

	if (!Proc || !lpPatchSize)
	{
		return FALSE;
	}

	do
	{
		Length = SizeOfCode(Proc, &pOpcode);
		if ((Length == 1) && (*pOpcode == 0xC3)) break;
		if ((Length == 3) && (*pOpcode == 0xC2)) break;
		Proc = (PVOID)((DWORD)Proc + Length);

		PatchSize += Length;
		if (PatchSize >= dwNeedSize)
		{
			break;
		}

	} while (Length);

	*lpPatchSize = PatchSize;

	return	TRUE;
}

BOOL
InlineHook(
	IN	void *OrgProc,			/* 需要Hook的函数地址 */
	IN	void *NewProc,		/* 代替被Hook函数的地址 */
	OUT	void **RealProc		/* 返回原始函数的入口地址 */
	)
/*++
	对函数进行Inline Hook
--*/
{
	DWORD	dwPatchSize;	// 得到需要patch的字节大小
	DWORD	dwOldProtect;	
	LPVOID	lpHookFunc;		// 分配的Hook函数的内存
	DWORD	dwBytesNeed;	// 分配的Hook函数的大小
	LPBYTE	lpPatchBuffer;	// jmp 指令的临时缓冲区

	if (!OrgProc || !NewProc || !RealProc)
	{
		return FALSE;
	}
	// 得到需要patch的字节大小
	if (!GetPatchSize(OrgProc, JMP_SIZE, &dwPatchSize))
	{
		return FALSE;
	}

	/*
	0x00000800					0x00000800		sizeof(DWORD)	// dwPatchSize
	JMP	/ FAR 0xAABBCCDD		E9 DDCCBBAA		JMP_SIZE
	...							...				dwPatchSize		// Backup instruction
	JMP	/ FAR 0xAABBCCDD		E9 DDCCBBAA		JMP_SIZE
	*/

	dwBytesNeed = sizeof(DWORD) + JMP_SIZE + dwPatchSize + JMP_SIZE;

	lpHookFunc = __malloc(dwBytesNeed);

	// 备份dwPatchSize到lpHookFunc
	*(DWORD *)lpHookFunc = dwPatchSize;

	// 跳过开头的4个字节
	lpHookFunc = (LPVOID)((DWORD)lpHookFunc + sizeof(DWORD));


	// 开始backup函数开头的字	
	memcpy((BYTE *)lpHookFunc + JMP_SIZE, OrgProc, dwPatchSize);

	lpPatchBuffer = __malloc(dwPatchSize);

	// NOP填充
	memset(lpPatchBuffer, 0x90, dwPatchSize);

#ifdef RING3
	// jmp到Hook
	*(BYTE *)lpHookFunc = 0xE9;
	*(DWORD*)((DWORD)lpHookFunc + 1) = (DWORD)NewProc - (DWORD)lpHookFunc - JMP_SIZE;

	// 跳回原始
	*(BYTE *)((DWORD)lpHookFunc + 5 + dwPatchSize) = 0xE9;
	*(DWORD*)((DWORD)lpHookFunc + 5 + dwPatchSize + 1) = ((DWORD)OrgProc + dwPatchSize) - ((DWORD)lpHookFunc + JMP_SIZE + dwPatchSize) - JMP_SIZE;


	// jmp 
	*(BYTE *)lpPatchBuffer = 0xE9;
	// 注意计算长度的时候得用OrgProc
	*(DWORD*)(lpPatchBuffer + 1) = (DWORD)lpHookFunc - (DWORD)OrgProc - JMP_SIZE;

#else
	
	// jmp到Hook
	*(BYTE *)lpHookFunc = 0xEA;
	*(DWORD*)((DWORD)lpHookFunc + 1) = (DWORD)NewProc;
	*(WORD*)((DWORD)lpHookFunc + 5) = 0x08;
	
	// 跳回原始
	*(BYTE *)((DWORD)lpHookFunc + JMP_SIZE + dwPatchSize) = 0xEA;
	*(DWORD*)((DWORD)lpHookFunc + JMP_SIZE + dwPatchSize + 1) = ((DWORD)OrgProc + dwPatchSize);
	*(WORD*)((DWORD)lpHookFunc + JMP_SIZE + dwPatchSize + 5) = 0x08;

	// jmp far
	*(BYTE *)lpPatchBuffer = 0xEA;
	
	// 跳到lpHookFunc函数
	*(DWORD*)(lpPatchBuffer + 1) = (DWORD)lpHookFunc;
	*(WORD*)(lpPatchBuffer + 5) = 0x08;
#endif

	WriteReadOnlyMemory(OrgProc, lpPatchBuffer, dwPatchSize);
	
	__free(lpPatchBuffer);


	*RealProc = (DWORD)lpHookFunc + JMP_SIZE;

	return	TRUE;
}

void UnInlineHook(
	void *OrgProc,		/* 需要恢复Hook的函数地址 */
	void *RealProc	/* 原始函数的入口地址 */
	)
/*++
	恢复对函数进行的Inline Hook
--*/
{
	DWORD	dwPatchSize;
	DWORD	dwOldProtect;
	LPBYTE	lpBuffer;
	
	// 找到分配的空间
	lpBuffer = (DWORD)RealProc - (sizeof(DWORD) + JMP_SIZE);
	// 得到dwPatchSize
	dwPatchSize = *(DWORD *)lpBuffer;

	WriteReadOnlyMemory(OrgProc, RealProc, dwPatchSize);

	// 释放分配的跳转函数的空间
	__free(lpBuffer);
}
#endif // !defined(AFX_INLINEHOOK_H_INCLUDED)

[注意] 欢迎加入看雪团队!base上海,招聘安全工程师、逆向工程师多个坑位等你投递!

上传的附件:
收藏
点赞0
打赏
分享
最新回复 (10)
雪    币: 211
活跃值: 活跃值 (10)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
dayed 活跃值 1 2008-8-27 07:42
2
0
支持 !~~~~~~
雪    币: 201
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
robar 活跃值 2008-8-27 09:08
3
0
LZ 辛苦了
雪    币: 21
活跃值: 活跃值 (229)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
靴子 活跃值 2008-8-27 10:45
4
0
干什么用的
雪    币: 200
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
whilster 活跃值 2008-8-27 11:35
5
0
谢谢楼主分享
雪    币: 126
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
niuhacker 活跃值 2008-8-27 12:06
6
0
喜欢源代码。
雪    币: 200
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
jydyb 活跃值 2008-8-27 12:55
7
0
收藏下...GOOD
雪    币: 211
活跃值: 活跃值 (10)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
cooldiyer 活跃值 1 2008-8-27 13:28
8
0
还是看雪人多
雪    币: 4
活跃值: 活跃值 (15)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
jadesoft 活跃值 1 2008-8-27 14:25
9
0
太好了终于见到熟悉的风格了
雪    币: 125
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
asmfly 活跃值 2008-8-27 21:55
10
0
cooldiyer的主页是什么,记得以前常去的
雪    币: 201
活跃值: 活跃值 (11)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
xueff 活跃值 2008-9-21 19:22
11
0
如何能 “// 跳回原始”?根本执行不到这里来嘛。
游客
登录 | 注册 方可回帖
返回