SetWindowHookEx远程过程调用失败总是失败

3172人阅读
我在上一篇博客《》中详细介绍了SetWindowsHookEx的失败原因,今天又发现了一个隐晦的错误原因,这也是我这么多天来一直在寻找的东西。起因是我想为一个进程的所有线程都调用SetWindowsHookEx,现象是有些线程可以调用成功,有些线程不能调用成功。前些天一直在看windows,ReactOS相关的源代码,反汇编单步跟踪SetWindowsHookEx的执行流程,但是卡在了sysenter上,ring3级别的代码都一路跟踪过去了,到ring0的门口,一直试了好久都没能进去。今天转变了一下思路,为什么不在宏观上观察这些进程,成功的与不成功的都有什么特点呢?这也给我提了个醒,要有追究到底的坚持,也要有思路转变的灵活。
好了,现在开始说这个隐晦的错误原因到底是怎么找到的。这里主要提供的是思路,如果不想看这些,就直接看后面绿色字体部分。
1. 寻找答案
线程分为成功Hook的和不成功Hook的,那么我的目标就是要找到这两类线程有什么不同之处。所以,问题转化为了得到尽可能多的有关线程的信息,比较他们的不同之处。这样,问题就定义好了。那么,如何找到问题的答案呢?
Google的好处在于,在你知道的东西很少的时候,可以给你提供思路,这对知识量少的同学来说是非常重要的,因为新的线索可以提供新的思路。并且我们遇到的问题,很大程度上已经被别人遇到并解决了。但是Google不好的地方就是信息分散,太杂太乱。对于菜鸟来说,最重要的一个问题就是:不知道什么是可以做的,什么是不可以做的,什么是已经实现的,什么是一定要自己实现的。有时候连我们自己都不知道问题的定义是什么,又怎么能让Google帮我们精确的找到呢?
说来惭愧,今天解决这个问题的一个瞬间,我才有一点明白知识要怎么学,MSDN要怎么用。前面说了,我们菜鸟不知道什么是已经实现的,什么是要自己实现的,那么,这应该怎么办?有一个字叫Reference(参考),这就是这里的关键,也是今天对我最大的启示。我们要找的是与线程有关的函数,首先Google:CreateProcess,来到。然后,就看到我要找Reference。看下面:
页面的这一行就是关键,点开里面的Process and Thread Reference 或者Process and Thread functions。只需要把functions里面的东西仔细看一看,就可以大概知道什么是已经实现的,这样做比Google的效率要高很多。因为这样更加精准,所有与Process还有Thread相关的函数都在这里了。在这里,我发现了GetThreadTimes函数,这是一个突破,因为已经发现了与线程有关的时间信息。来试试吧!调用这个函数需要线程句柄,可是我只有线程Id,这时候,又在这个页面里发现了OpenThread函数,用这个函数就可以由线程ID得到线程句柄。然后,测试,发现了问题所在。
当然,这种方法也有它不靠谱的地方,比如说,如果我刚才没有参考《WINDOWS 核心编程》就不会发现原来还有一个叫GetThreadContext的函数,这个函数并不在Process and Thread functions里,而在Debugging Function里面。
这里的结论就是:多读书,多看参考,知道有什么,等用的时候,再去仔细看怎么用。
2.问题在哪里
如果要给一个进程的所有线程Hook,首先要得到这些线程,关于这一点,可以利用一组TOOL HELP FUNCTION来解决,用上面给出的思路,点。相信应该可以解决。
1) 得到所有线程id:TOOL HELP FUNCTION
2)得到每一个线程的时间信息:GetThreadTimes,并观察
3)给每一个线程调用SetWindowsHookEx
4)再给刚调用过SetWindowsHookEx函数的线程调用GetThreadTimes函数并观察
4)观察调用SetWindowsHookEx成功的线程与失败的线程的时间有什么不同。
3. 得出结论
1)凡是SetWindowsHookEx调用成功的线程,UserTime或者KernelTime至少有一个不为0,并且此线程此时还要存活着。
2)调用失败的线程,或者已经死亡,或者仍然存活,但UserTime和KernelTime在SetWindowsHookEx前后全部都为0!
3)如果前两种情况都不符合,例如线程没有死亡,UserTime或者KernelTime至少有一个不为0,但是SetWindowsHookEx仍然调用失败了,或者UserTime或KernelTime都为0,进程存活,但是调用成功了。那么可以参考我前一篇博文,可能会有所启发,我这里也难以解释这种现象。
特别注意1:千万要注意调用 OpenThread和GetThreadTimes的时候,一定要检查是否调用成功,如果调用不成功,一定要用GetLastError去看看到底因为什么调用不成功。否则你会以为这些进程的UserTime和KernelTime都为0,而实际上他们并不为0,只是你函数调用失败了,没有得到这些时间。这就会让我们的分析误入歧途!
特别注意2:测试的过程中会发现,有些线程OpenThread和GetThreadTimes都成功了,并且UserTime和KernelTime也不为0,但是SetWindowsHookEx仍然调用失败了,这是什么原因呢?我用Process Explorer查看了这些线程,发现这些线程已经死亡了,不再出现在进程的线程列表中。
特别注意3:测试的过程会发现,在调试模式下,权限会比较大,调用OpenProcess的时候可以用THREAD_ALL_ACCESS,OpenProcess和GetThreadTime不会因为没有权限而调用失败,如果调用失败了,一般是因为这些线程已经死亡了。这时OpenProcess返回错误代码87,参数不正确,GetThreadTime使用OpenProcess的返回值会返回NULL,错误代码6,无效句柄。而在正常模式下双击程序运行,OpenProcess如果使用THREAD_ALL_ACESS,那么会调用失败,同时GetThreadTime也会调用失败,错误代码为5,没有权限。关于如何提升进程的权限,参考下面:
4.解决之道
我查资料的过程中,很多人都说使用ToolHelp函数得到进程的所有线程,但是问题在于,ToolHelp函数只得到了那一时刻进程的快照,而进程时刻都处于生老病死中。要想真正为进程的每个线程Hook,是不是应该每隔一段时间就查询一下这个进程的所有线程,然后给每一个UserTime和KernelTime不全为0并且没有Hook过的线程进行Hook呢?这个我还没有试过。
或许有更好的方法,或许我们要解决的问题根本就不需要用HOOK技术。
转载请注明出处:
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:125435次
积分:2293
积分:2293
排名:第6663名
原创:87篇
译文:11篇
评论:52条
/minixalpha
文章:13篇
阅读:5790
(3)(1)(2)(6)(5)(5)(6)(2)(2)(2)(3)(1)(2)(2)(1)(11)(29)(1)(2)(2)(1)(2)(3)(4)所属子分类:
注册时间: 17:55
回复数: 14
论坛积分:41
#include "stm32f10x.h"
#include &stdio.h&
#include "delay.h"
#include "lcd.h"
#include "ad.h"
//时钟配置
void RCC_Configuration(void)
&ErrorStatus HSEStartUpS & & & & & & & & & &//定义外部高速晶体启动状态枚举变量
&RCC_DeInit(); & & & & & & & & & & & & & & & & & &//复位RCC外部设备寄存器到默认值
&RCC_HSEConfig(RCC_HSE_ON); & & & & & & & & & & & //打开外部高速晶振
&HSEStartUpStatus = RCC_WaitForHSEStartUp(); & & &//等待外部高速时钟准备好
&if(HSEStartUpStatus == SUCCESS) & & & & & & & & &//外部高速时钟已经准别好
& &FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable); //开启FLASH预读缓冲功能,加速FLASH的读取。所有程序中必须的用法.位置:RCC初始化子函数里面,时钟起振之后
& &FLASH_SetLatency(FLASH_Latency_2); & & & & & & & & & &//flash操作的延时
& &RCC_HCLKConfig(RCC_SYSCLK_Div1); & & & & & & & //配置AHB(HCLK)时钟等于==SYSCLK
& &RCC_PCLK2Config(RCC_HCLK_Div1); & & & & & & & &//配置APB2(PCLK2)钟==AHB时钟
& &RCC_PCLK1Config(RCC_HCLK_Div2); & & & & & & & &//配置APB1(PCLK1)钟==AHB1/2时钟
& &RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_9); &//配置PLL时钟 == 外部高速晶体时钟 * 9 = 72MHz
& &RCC_PLLCmd(ENABLE); & & & & & & & & & & & & & & & & & //使能PLL时钟
& &while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET) & &//等待PLL时钟就绪
& &RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK); & & & & & &//配置系统时钟 = PLL时钟
& &while(RCC_GetSYSCLKSource() != 0x08) & & & & & & & & &//检查PLL时钟是否作为系统时钟
RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOB |RCC_APB2Periph_GPIOD|RCC_APB2Periph_GPIOE, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);//I/O口的 PD和PE是连接TFT
void GPIO_Configuration(void)
GPIO_InitTypeDef GPIO_InitS
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_A&
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;&
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;&
GPIO_Init(GPIOE, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12|GPIO_Pin_13|GPIO_Pin_14|GPIO_Pin_15;&
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;&
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;&
GPIO_Init(GPIOD, &GPIO_InitStructure);
void TIM_Configuration(void)
TIM_TimeBaseInitTypeDef TIM_TimeBaseS&
TIM_TimeBaseStructure.TIM_Period =10000;&
TIM_TimeBaseStructure.TIM_Prescaler = 7199;&
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;&
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;&
TIM_TimeBaseInit(TIM2, & TIM_TimeBaseStructure);
TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE ); //使能更新中断
TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
//TIM_ARRPreloadConfig(TIM2, ENABLE);//使能TIMx在ARR上的预装载寄存器 &
TIM_Cmd(TIM2, ENABLE); //使能定时器
void NVIC_Configuration(void)
NVIC_InitTypeDef NVIC_InitS&
NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x0);
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);&
NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;&
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;&
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;&
NVIC_Init (&NVIC_InitStructure);
void TIM2_IRQHandler(void)
if(TIM_GetITStatus(TIM2, TIM_IT_Update) == SET)
& &TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
int main(void)
RCC_Configuration();
GPIO_Configuration();
& & TIM_Configuration();
delay_init(72);
LCD_Init();
LCD_Clear(BLACK);
& & POINT_COLOR = RED;
BACK_COLOR = BLACK;
& &if(i&9)
LCD_ShowBigNum(50,50,i);
注册时间: 10:41
回复数: 53640
主题数: 374
酷贴数:27
论坛积分:57462
来自: 湖南
回复【楼主位】&isonicboy&:
---------------------------------
软件问题,建议仿真解决。
我的淘宝小店:
注册时间: 17:55
回复数: 14
论坛积分:41
回复【1楼】&正点原子&:
---------------------------------
谢谢版主建议。搞了好久就是出不来
注册时间: 10:41
回复数: 53640
主题数: 374
酷贴数:27
论坛积分:57462
来自: 湖南
回复【2楼】&isonicboy&:
---------------------------------
要学会仿真,能帮助你很多。
我的淘宝小店:
请选择一个版面...
STM32-F0/F1/F2专区
STM32-F3/F4专区
MSP430专区
ARM7/ARM9/ARM11专区
其他Cortex系列
uCOS & uCGUI & Emwin
trochili(飞鸟)操作系统
中国RTOS联盟
FPGA/CPLD/DSP专区
数字,模拟,高频电路
编程语言学习
蓝牙/WIFI/Zigbee等通信技术
开发工具专栏
UOL 单片机面向对象语言
四轴飞行器
DIY大赛专区
DIY项目资料专区
论坛建设区
二手交易专栏
& 开源电子网() |Windows 7下用SetWindowHookEx,Hook “Shell_TrayWnd”时,普通用户运行能成功,提升权限至管理员却失败了,返回ERROR_ACCESS_DENIED
Windows 7下用SetWindowHookEx,Hook &Shell_TrayWnd&时,普通用户运行能成功,提升权限至管理员却失败了,返回ERROR_ACCESS_DENIED
各位有什么建议不?
从Windows Vista
起, Windows
引入了新的强制完整性控制(Mandatory Integrity Control)。级别低的进程不能访问高级别的进程资源。此功能被用来隔离应用程序,在一个中等级别,如在标准用户环境中运行的应用,应用不能挂接到系统级并运行在管理员模式下的应用程序,高性级别应用,可以钩到较低级别的进程,如Windows
Internet Explorer 7或8。一个低权限的过程不能使用线程钩子附加到一个更高权限的进程中,不能使用钩子监视一个更高权限的进程,并不能执行DLL注入到一个更高权限的进程。
Rob Pan [MSFT]
MSDN Community Support |
Please remember to mark the replies as answers if they help and unmark them if they provide no help.
已标记为答案
BUILDIN\Administrators是内置管理员权限,您需要把您的程序也提高到相同的权限,才可以访问拥有相同权限的程序Rob Pan [MSFT]
MSDN Community Support |
Please remember to mark the replies as answers if they help and unmark them if they provide no help.
已标记为答案
从Windows Vista
起, Windows
引入了新的强制完整性控制(Mandatory Integrity Control)。级别低的进程不能访问高级别的进程资源。此功能被用来隔离应用程序,在一个中等级别,如在标准用户环境中运行的应用,应用不能挂接到系统级并运行在管理员模式下的应用程序,高性级别应用,可以钩到较低级别的进程,如Windows
Internet Explorer 7或8。一个低权限的过程不能使用线程钩子附加到一个更高权限的进程中,不能使用钩子监视一个更高权限的进程,并不能执行DLL注入到一个更高权限的进程。
Rob Pan [MSFT]
MSDN Community Support |
Please remember to mark the replies as answers if they help and unmark them if they provide no help.
已标记为答案
系统的explorer.exe是运行在Medium级别的,自己应用(coconut.exe)是运行在Hight级别的,所以不存在低级别访问高级别的问题。
用processex查看到信息如下:
explorer.exe
coconut.exe
不过在查看系统安全性的时候,发现explorer.exe的BUILDIN\Administrators组s标识是deny;而我的应用coconut.exe提权运行的BUILDIN\Administrators组标识是OWNER,不知道是否是因此访问被explorer.exe拒绝的?
BUILDIN\Administrators是内置管理员权限,您需要把您的程序也提高到相同的权限,才可以访问拥有相同权限的程序Rob Pan [MSFT]
MSDN Community Support |
Please remember to mark the replies as answers if they help and unmark them if they provide no help.
已标记为答案
有其他的解决办法么?如果hook有这样的限制的话
Microsoft 正在进行一项网上调查,以了解您对 Msdn 网站的意见。如果您选择参加,我们将会在您离开 Msdn 网站时向您显示该网上调查。是否要参加?
<input type="hidden" id="hdnTrackerText" value="请不要关闭此窗口。谢谢!完成访问时,调查将显示在此处,所以请不要关闭此窗口。" />
其他 Office 网站监控文件的打开,保存。使用hook的setWindowHookEx()的第一个参数应该是什么_百度知道
监控文件的打开,保存。使用hook的setWindowHookEx()的第一个参数应该是什么
提问者采纳
SetWindowHookEx不能监控文件的打开,保存。它只能HOOK系统的旦攻测纪爻慌诧苇超俩消息。你可以选择使用SHELL编程,或者Hook API来实现。
提问者评价
其他类似问题
hook的相关知识
等待您来回答
下载知道APP
随时随地咨询
出门在外也不愁SetWindowHookEx中的WH_GETMESSAGE对应的回调函数不执行?
[问题点数:40分,无满意结帖,结帖人bai_hua_lin]
SetWindowHookEx中的WH_GETMESSAGE对应的回调函数不执行?
[问题点数:40分,无满意结帖,结帖人bai_hua_lin]
不显示删除回复
显示所有回复
显示星级回复
显示得分回复
只显示楼主
相关帖子推荐:
本帖子已过去太久远了,不再提供回复功能。

我要回帖

更多关于 setwindowhook 的文章

 

随机推荐