当前位置:  编程技术>c/c++/嵌入式

VC实现屏幕截词功能的方法详解

    来源: 互联网  发布时间:2014-10-26

    本文导语:  VC程序设计中屏幕上的文字大都是由gdi32.dll的以下几个函数显示的:TextOutA、TextOutW、ExtTextOutA、ExtTextOutW。实现屏幕抓词的关键就是截获对这些函数的调用,得到程序发给它们的参数。 实现的方法有以下三个步骤: 一、得到鼠...

VC程序设计中屏幕上的文字大都是由gdi32.dll的以下几个函数显示的:TextOutA、TextOutW、ExtTextOutA、ExtTextOutW。实现屏幕抓词的关键就是截获对这些函数的调用,得到程序发给它们的参数。

实现的方法有以下三个步骤:

一、得到鼠标的当前位置
通过SetWindowsHookEx实现。

二、向鼠标下的窗口发重画消息,让它调用系统函数重画
通过WindowFromPoint,ScreenToClient,InvalidateRect 实现。

三、截获对系统函数的调用,取得参数(以TextOutA为例)

1.仿照TextOutA作成自己的函数MyTextOutA,与TextOutA有相同参数和返回值,放在系统钩子所在的DLL里。

SysFunc1=(DWORD)GetProcAddress(GetModuleHandle("gdi32.dll"),"TextOutA");
BOOL WINAPI MyTextOutA(HDC hdc, int nXStart, int nYStart, LPCSTR lpszString,int cbString)
{ //输出lpszString的处理
return ((FARPROC)SysFunc1)(hdc,nXStart,nYStart,lpszString,cbString);
}

2.由于系统鼠标钩子已经完成注入其它GUI进程的工作,我们不需要为注入再做工作。
如果你知道所有系统钩子的函数必须要在动态库里,就不会对"注入"感到奇怪。当进程隐式或显式调用一个动态库里的函数时,系统都要把这个动态库映射到这个进程的虚拟地址空间里(以下简称"地址空间")。这使得DLL成为进程的一部分,以这个进程的身份执行,使用这个进程的堆栈。

DLL映射到虚拟地址空间中

对系统钩子来说,系统自动将包含"钩子回调函数"的DLL映射到受钩子函数影响的所有进程的地址空间中,即将这个DLL注入了那些进程。

3.当包含钩子的DLL注入其它进程后,寻找映射到这个进程虚拟内存里的各个模块(EXE和DLL)的基地址。EXE和DLL被映射到虚拟内存空间的什么地方是由它们的基地址决定的。它们的基地址是在链接时由链接器决定的。当你新建一个Win32工程时,VC++链接器使用缺省的基地址0x00400000。可以通过链接器的BASE选项改变模块的基地址。EXE通常被映射到虚拟内存的0x00400000处,DLL也随之有不同的基地址,通常被映射到不同进程的相同的虚拟地址空间处。

那么如何知道EXE和DLL被映射到哪里了呢?
在Win32中,HMODULE和HINSTANCE是相同的。它们就是相应模块被装入进程的虚拟内存空间的基地址。比如:

HMODULE hmodule=GetModuleHandle("gdi32.dll");

返回的模块句柄强制转换为指针后,就是gdi32.dll被装入的基地址。

对于如何找到虚拟内存空间映射了哪些DLL,我们可以通过如下方式得以实现:

while(VirtualQuery (base, &mbi, sizeof (mbi))>0)
{
if(mbi.Type==MEM-IMAGE)
ChangeFuncEntry((DWORD)mbi.BaseAddress,1);
base=(DWORD)mbi.BaseAddress+mbi.RegionSize;
}

4.得到模块的基地址后,根据PE文件的格式穷举这个模块的IMAGE-IMPORT-DESCRIPTOR数组,看是否引入了gdi32.dll。如是,则穷举IMAGE-THUNK-DATA数组,看是否引入了TextOutA函数。

5.如果找到,将其替换为相应的自己的函数。
系统将EXE和DLL原封不动映射到虚拟内存空间中,它们在内存中的结构与磁盘上的静态文件结构是一样的。即PE (Portable Executable) 文件格式。
所有对给定API函数的调用总是通过可执行文件的同一个地方转移。那就是一个模块(可以是EXE或DLL)的输入地址表(import address table)。那里有所有本模块调用的其它DLL的函数名及地址。对其它DLL的函数调用实际上只是跳转到输入地址表,由输入地址表再跳转到DLL真正的函数入口。例如:

对MessageBox()的调用跳转到输入地址表,从输入地址表再跳转到MessageBox函数

IMAGE-IMPORT-DESCRIPTOR和IMAGE-THUNK-DATA分别对应于DLL和函数。它们是PE文件的输入地址表的格式(数据结构参见winnt.h)。

BOOL ChangeFuncEntry(HMODULE hmodule)
{
PIMAGE-DOS-HEADER pDOSHeader;
PIMAGE-NT-HEADERS pNTHeader;
PIMAGE-IMPORT-DESCRIPTOR pImportDesc;
/ get system functions and my functions′entry /
pSysFunc1=(DWORD)GetProcAddress(GetModuleHandle("gdi32.dll"),"TextOutA");
pMyFunc1= (DWORD)GetProcAddress(GetModuleHandle("hookdll.dll"),"MyTextOutA");
pDOSHeader=(PIMAGE-DOS-HEADER)hmodule;
if (IsBadReadPtr(hmodule, sizeof(PIMAGE-NT-HEADERS)))
return FALSE;
if (pDOSHeader->e-magic != IMAGE-DOS-SIGNATURE)
return FALSE;
pNTHeader=(PIMAGE-NT-HEADERS)((DWORD)pDOSHeader+(DWORD)pDOSHeader->e-lfanew);
if (pNTHeader->Signature != IMAGE-NT-SIGNATURE)
return FALSE;
pImportDesc = (PIMAGE-IMPORT-DESCRIPTOR)((DWORD)hmodule+(DWORD)pNTHeader->OptionalHeader.DataDirectory[IMAGE-DIRECTORY-ENTRY-IMPORT].VirtualAddress);
if (pImportDesc == (PIMAGE-IMPORT-DESCRIPTOR)pNTHeader)
return FALSE;
while (pImportDesc->Name)
{
PIMAGE-THUNK-DATA pThunk;
strcpy(buffer,(char )((DWORD)hmodule+(DWORD)pImportDesc->Name));
CharLower(buffer);
if(strcmp(buffer,"gdi32.dll"))
{
pImportDesc++;
continue;
}else{
pThunk=(PIMAGE-THUNK-DATA)((DWORD)hmodule+(DWORD)pImportDesc->FirstThunk);
while (pThunk->u1.Function)
{ 
if ((pThunk->u1.Function) == pSysFunc1)
{ 
VirtualProtect((LPVOID)(&pThunk->u1.Function),
sizeof(DWORD),PAGE-EXECUTE-READWRITE,&dwProtect);
(pThunk->u1.Function)=pMyFunc1;
VirtualProtect((LPVOID)(&pThunk->u1.Function), sizeof(DWORD),dwProtect,&temp);
}
pThunk++; 
} 
return 1;
}
}
}

替换了输入地址表中TextOutA的入口为MyTextOutA后,截获系统函数调用的主要部分已经完成,当一个被注入进程调用TextOutA时,其实调用的是MyTextOutA,只需在MyTextOutA中显示传进来的字符串,再交给TextOutA处理即可。


    
 
 

您可能感兴趣的文章:

  • Base64编码原理详解及c++编码解码实现
  • 如何在Linux下使用脚本实现程序的自动重启!望各位详解!
  • <<TCP-IP详解卷二:实现>>是以哪个系统为基础的?
  • Android 实现永久保存数据的方法详解
  • MySql实现跨表查询的方法详解
  • sql server日期相减 的实现详解
  • c#之滚动字幕动画窗体的实现详解
  • 解析C#彩色图像灰度化算法的实现代码详解
  • php实例分享之通过递归实现删除目录下的所有文件详解
  • c#之圆形无标题栏椭圆窗体的实现详解
  • c#调用存储过程实现登录界面详解
  • 使用DateTime的ParseExact方法实现特殊日期时间的方法详解
  • c++实现strcat字符串连接库函数的方法详解
  • 桌面浮动窗口(类似恶意广告)的实现详解
  • c#实现隐藏与显示任务栏的方法详解
  • Reactor反应器的实现方法详解
  • 详解MySQL中DROP,TRUNCATE 和DELETE的区别实现mysql从零开始
  • MySQL分表实现上百万上千万记录分布存储的批量查询设计模式详解
  • 基于atoi()与itoa()函数的内部实现方法详解
  • 五种单件模式之Singleton的实现方法详解
  • C++中用两个标准容器stack,实现一个队列的方法详解
  • Android点亮屏幕或屏幕解锁和锁定以及其他相关权限实现代码
  • jquery 实现弹出div位于屏幕正中(图文)
  • JQuery实现元素屏幕居中显示的代码
  • linux下如何实现系统托盘的效果?如同屏幕下方的clock
  • 笔记本上的ubuntu系统调节电源或者屏幕亮度的显示的进度条是怎么实现的?
  • linux下如何实现屏幕取词?
  • linux下怎么实现在屏幕上指定地方输出字符?
  • Android判断屏幕是横屏或是竖屏的简单实现方法
  • 使用C#实现在屏幕上画图效果的代码实例
  • jquery实现弹出div,始终显示在屏幕正中间的简单实例
  •  
    本站(WWW.)旨在分享和传播互联网科技相关的资讯和技术,将尽最大努力为读者提供更好的信息聚合和浏览方式。
    本站(WWW.)站内文章除注明原创外,均为转载、整理或搜集自网络。欢迎任何形式的转载,转载请注明出处。












  • 相关文章推荐
  • 通过javascript库JQuery实现页面跳转功能代码
  • 我想把csdn的论坛改成一个软件平台,另外增加数据查询功能,聊天功能,不知怎样实现比较好?我想用jbuider 7+SQL server实现,不知如何?
  • 基于python实现的网络爬虫功能:自动抓取网页介绍
  • 我想做linux下的还原备份,实现与还原精灵虚拟还原等一样的功能,应该怎么做?另外现在有实现这种功能的成熟产品是哪一种?
  • struts+spring+hibernate+jquery实现分页功能的几个基本类介绍(异步加载)
  • 我想定义一个宏来实现文中功能,但是不知道我说的功能到底可不可以实现
  • Andriod UI中viewFlow实现仿淘宝的自动播放功能
  • 请问在linux下面,有没有硬盘整理的功能,或者有什么软件可以实现硬盘整理的功能?
  • 要实现无线功能部分,是单独写一个驱动,还是在原有驱动上扩充无线功能,哪个简单点?
  • 在linux下如何编程实现nslookup命令实现的IP地址和域名互相转换的功能?
  • Linux和Unix相对WIN、NETWARE有什么好处?他们之间有什么区别?WIN、NETWARE能实现的功能LINUX和UNIX能实现吗?
  • S3C2410按键驱动功能实现
  • java编程可实现一些什么样的功能?
  • 利用文件系统过滤驱动实现 类似还原卡功能 的原理是什么?
  • 请问shell能实现注册的功能吗?
  • 用KJAVA实现A6288一个功能的问题
  • 求录音机暂停功能的实现
  • 怎样实现这个功能,大家都看看。。。
  • 要做一个在applet,实现可以托拽的图形(比如长方形和线段等)?那位高手有资料?或者有没有java的第三方类库实现此功能?
  • 如何用c实现自动的telnet功能
  • 如何实现类似PHP.PB等语言中eval的函数功能?
  • 通过javascript实现DIV居中,兼容各浏览器版本
  • socket实现多文件并发传输,求助多线程实现问题?
  • Python GUI编程:tkinter实现一个窗口并居中代码
  • interface 到底有什么用???实现接口,怎么实现??
  • sharepoint 2010 使用STSNavigate函数实现文件下载举例
  • 怎么用Jsp实现在页面实现树型结构?
  • oracle iis7站长之家
  • windows 下的PortTunnel 在linux下怎么实现?或者相应的已经实现的软件?端口映射
  • flash AS3反射实现(describeType和getDefinitionByName)
  • 网站重定向用C语言实现iptables,ACL实现


  • 站内导航:


    特别声明:169IT网站部分信息来自互联网,如果侵犯您的权利,请及时告知,本站将立即删除!

    ©2012-2021,,E-mail:www_#163.com(请将#改为@)

    浙ICP备11055608号-3