首页
社区
课程
招聘
[旧帖] [求助]ring3 inline hook 0.00雪花
发表于: 2012-6-19 15:34 1990

[旧帖] [求助]ring3 inline hook 0.00雪花

2012-6-19 15:34
1990
刚接触hook,比着葫芦画瓢,出现问题了
大部分代码引用自 Ring3下Inline Hook MessageBox(演示) http://bbs.pediy.com/showthread.php?t=69666

经我测试该文作者的代码也存在同样问题

下面是我的代码:
BYTE orig_code[5] = {0x90, 0x90, 0x90, 0x90, 0x90};//存放原始的指令
BYTE hook_code[5] = {0xe9, 0, 0, 0, 0};//存放跳转到MyMessageBoxA的指令
BYTE jmp_org_code[5] = {0xe9, 0, 0, 0, 0};//存放跳转到原起始地址后5字节的指令

int _stdcall MyMessageBoxA(
	HWND hWnd,          // handle to owner window
	LPCTSTR lpText,     // text in message box
	LPCTSTR lpCaption,  // message box title
	UINT uType          // message box style
	);
int MyFunc();
void Hook();
int jmp_back();

ULONG OldFuncAddr;
ULONG MyFuncAddr;
ULONG jmp_backAddr;

int main()
{
	int rt = MessageBoxA(NULL, "Hello World1", "Title", MB_OK);

	Hook();

	rt = MessageBoxA(NULL, "Hello World2", "Title", MB_OK);

	system("pause");

	return 0;
}

void Hook()
{
	DWORD dwOldProtect;  
	OldFuncAddr = (ULONG)MessageBoxA;

	//MyMessageBoxA函数相对EIP的偏移量
	MyFuncAddr = *(ULONG*)((BYTE *)MyMessageBoxA+1);
	//当前指令地址+本条指令的长度+偏移
	MyFuncAddr = *(ULONG *)((BYTE *)MyMessageBoxA+1) + (ULONG)MyMessageBoxA + 5;
	// jmp_backAddr = jmp_back的实际地址
	jmp_backAddr = *(ULONG *)((BYTE *)jmp_back+1) + (ULONG)jmp_back + 5;
	//修改内存为PAGE_EXECUTE_READWRITE
	VirtualProtect((LPVOID)jmp_backAddr, 10, PAGE_EXECUTE_READWRITE, &dwOldProtect);

	VirtualProtect((LPVOID)OldFuncAddr, 5, PAGE_EXECUTE_READWRITE, &dwOldProtect);
	//计算跳转地址
	//hook函数离原函数的距离
	//hook函数的地址 - 原函数的地址 - JMP指令长度 = 偏移量
	*((ULONG*)(hook_code+1)) = (ULONG)MyFuncAddr - (ULONG)OldFuncAddr - 5;

	memcpy(orig_code,(BYTE *)OldFuncAddr, 5);

	memcpy((BYTE*)OldFuncAddr, hook_code, 5);
	//计算返回地址
	*((ULONG*)(jmp_org_code+1)) = (ULONG)OldFuncAddr - (ULONG)jmp_backAddr - 5;

	//还原数据
	memcpy((BYTE *)jmp_backAddr, orig_code, 5);
	//返回地址
	memcpy((BYTE *)jmp_backAddr + 5, jmp_org_code, 5);
}

__declspec(naked) int jmp_back()
{
	__asm
	{
		_emit 0x90
		_emit 0x90
		_emit 0x90
		_emit 0x90
		_emit 0x90
		_emit 0x90
		_emit 0x90
		_emit 0x90
		_emit 0x90
		_emit 0x90
	}

}

//MyMessageBoxA:在函数执行前进行自己的处理
__declspec(naked) int _stdcall MyMessageBoxA(
	HWND hWnd,          // handle to owner window
	LPCTSTR lpText,     // text in message box
	LPCTSTR lpCaption,  // message box title
	UINT uType          // message box style
	)
{   
	printf("MyMessageBoxA is called\r\n"); 

	MyFunc();////可以加入函数过程

	__asm
	{
		//跳回MessageBoxA入口点
		jmp jmp_back;
	}
}

int MyFunc()
{
	printf("Hello World\r\n");
	return 1;
}


以上代码在win7+vs2010编译运行,报错:vaule of ESP was not properly saved across a function call。请大家帮我看看问题出在哪

[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

收藏
免费 0
支持
分享
最新回复 (8)
雪    币: 35
活跃值: (29)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
都没人回啊,是不是问题太低级了
2012-6-20 08:45
0
雪    币: 1
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
帮顶帮顶帮顶帮顶
2012-6-20 22:47
0
雪    币: 35
活跃值: (29)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
我试了好多次,发现:
把代码中的  
   printf("MyMessageBoxA is called\r\n");
去掉,Debug版就不再报错,但是依旧没弄明白原因。
查看反汇编,也没发现破坏堆栈的指令:
00E417C0  mov         esi,esp  
00E417C2  push        offset string "MyMessageBoxA is called\r\n" (0E45784h)  
00E417C7  call        dword ptr [__imp__printf (0E48354h)]  
00E417CD  add         esp,4  
00E417D0  cmp         esi,esp  
00E417D2  call        @ILT+340(__RTC_CheckEsp) (0E41159h)  


而且这玩意的Release版压根就不能工作。。。
哪位大哥,知道原因请不吝赐教啊,小菜不胜感激!
2012-6-21 14:55
0
雪    币: 35
活跃值: (29)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
下面是Release版的问题:
    运行环境仍然为Win7+vs2010生成Release版,调试发现,程序在
   
//将保存的指令复制到jmp_backAddr处
    memcpy((BYTE *)jmp_backAddr, orig_code, 5);

发生内存写入异常。进一步分析定位到
   
 VirtualProtect((LPVOID)jmp_backAddr, 10, PAGE_EXECUTE_READWRITE, &dwOldProtect);

修改页保护属性失败,查看MSDN:
      
You can set the access protection value on committed pages only. If the state of any page in the specified region is not committed, the function fails and returns without modifying the access protection of any pages in the specified region.

接下来使用
   
MEMORY_BASIC_INFORMATION mbi;
VirtualQuery((LPCVOID)jmp_backAddr,&mbi,sizeof(mbi));

查看jmp_backAddr所在页面的属性,发现数据无效。经调试,在进入Hook函数后,mbi中的数据就已经有了,而Debug版的mbi的数据是真是获取的。。。问题有点匪夷所思,真的很郁闷,求拯救啊
2012-6-21 16:28
0
雪    币: 35
活跃值: (29)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
Release问题解决了,jmp_back函数去掉,申请一块内存来保存原函数头部指令和jmp_back指令......eek:
2012-6-26 14:37
0
雪    币: 35
活跃值: (29)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
好吧,我承认我太水了,问题果然很简单
改动如下:
__declspec(naked) int _stdcall MyMessageBoxA(
	HWND hWnd,          // handle to owner window
	LPCTSTR lpText,     // text in message box
	LPCTSTR lpCaption,  // message box title
	UINT uType          // message box style
	)
{   
	__asm{
		push esi
	}
	printf("MyMessageBoxA is called\n"); 
	MyFunc();         //可以加入函数过程
	
	__asm{
		pop esi
		jmp realAddress
		ret
	}
}

debug版的代码中加入了堆栈平衡的相关代码,在进入MyMessageBoxA函数以后,把ESI的值设置为了当前ESP的值,结果就是函数返回时ESP回来了,但是ESI是错误的
问题解决了,心情舒畅
2012-6-26 15:33
0
雪    币: 9479
活跃值: (757)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
加入pushad 和 popad 就好了,
你调用了API
2012-6-30 01:02
0
雪    币: 35
活跃值: (29)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
9
谢谢楼上的兄弟!
2012-7-16 18:14
0
游客
登录 | 注册 方可回帖
返回
//