本文只对与几个关键性技术的实现细节进行讨论,其它的编程细节,请参考源程序。

32位到16位的形式替换

32位代码与16位代码的数据交换

动态修改Windows内核

1. 32bit到16bit的形式替换(Thunk)

形 式替换是指那些允许从16位代码调用32位代码或从32位代码调用16位代码的技术。形式替换用于解决试图在同一操作系统或同一可执行程序上使16位代码 与32位代码同时并存的问题,即16位代码与32位代码的混合编程技术。早期的DOS程序及Window3.x上的应用程序均为16位程序, Windows95及Windows NT虽然也可运行旧的16位程序,但它们的主流发展方向是32位应用程序。与Windows NT不同的是,Windows95不是一个“纯”32位操作系统,为了兼有令人满意的速度和与旧的16位程序的良好兼容性,其内核本身就是一个16位与 32位的混合体,因此也为编程者使用形式替换提供了便利。Microsoft为编写形式替换程序提供了通用的接口及工具,但因LTW32中的形式替换并不 复杂,所以使用了一些编程技巧,而避免了使用Microsoft复杂的开发工具。

形式替换中最主要的问题有两点:①16位与32位数据类型尺寸的变化,如16位代码到32位代码的一个重要变化是整型数int的长度加倍了 ;②是堆栈操作时,16位模式使用SS:SP堆栈指针控制栈顶,而在32位模式中使用ESP寄存器作堆栈指针控制栈顶。

在LTW32 中,屏幕抓词功能由16位DLL实现,因而只需实现32位到16位的形式替换,为32位代码提供16位DLL的调用接口。CALL FWORD PTR是32位汇编代码的一种调用方法,它可让32位代码调用到16位代码。作为实现的关键,控制16位侧与32位侧各自的堆栈是编程的要点。

32位侧的调用代码:

_asm{

pusha

call fword ptr [func16bit] /* func16bit是16位被调用者的48位地址 */

popa

}

16位侧的调用代码:

int dummy;

static char stack[8192]; /* 16位代码的临时堆栈 */

static WORD stack_seg;

static WORD prev_seg;

static DWORD prev_ofs;

static WORD prev_ds;

_asm{

push ax;

push bx;

mov ax, ds;

mov bx, seg dummy;

mov ds, bx;

mov stack_seg, bx;

mov prev_ds, ax;

pop bx;

pop ax;

mov prev_seg, ss;

mov dword ptr prev_ofs, esp; /* 保存32位堆栈指针 */

mov ss, stack_seg;

mov sp, offset stack; /* 设置16位堆栈指针 */

add sp, 8192;

}

/* 此处加入16位代码要实现的功能 */

_asm{

mov ss, prev_seg;

mov esp, dword ptr prev_ofs; /* 恢复32位堆栈指针 */

mov ds, prev_ds;

lea sp, word ptr [bp-2];

pop ds;

pop bp;

dec bp;

db 66h;

retf;

}

由 于调用中传递的参数有限,所以涉及的代码并不多,唯一比较复杂之处在16位侧,它临时转向一个16位堆栈,服务于来自32位的调用者的请求。在16位侧入 口处,必须存放好32位调用者的32位堆栈的指针,并且在16位侧返回时恢复它。由代码可见,这个过程是不可重入的,即一次只支持一个调用者,由于调用者 只有LTW32的32位侧代码,所以此限制可以满足。另外,在16位代码返回时,必须恢复32位调用者的48位堆栈指针(SS:ESP)而不是32位的 CS:SP,而且必须用一个48位地址(16:32)远返回(66h RETF)到它的32位调用者。

处理好这些细节,实现32位到16位的形式替换实际上是很简单的。

2. 32位代码与16位代码的数据交换

32 位代码使用16位段地址加32位线性地址(16:32)的地址形式,16位代码使用16位段选择符(selector)加16位偏移(16:16)的地址 形式。在Windows 95的32位侧,段址28h是系统段,即通过CS=28h或DS=28h可以访问系统的4G空间,其它应用程序的地址空间都是映射到28h段的4G空间 中。Windows95中所有32位进程的地址空间(共4G)的高2G(80000000H~FFFFFFFFH)全部映射到28: 80000000~28:FFFFFFFFH。即这块区域是所有32位程序共享的。这里一般存放系统DLL、虚拟设备驱动程序(VxD)、内存映射文件、 16位应用程序和16位全局堆等。最后一项很重要,这为32位代码与16位代码交换数据提供了一个简便的方法。因为16位程序的段选择符的基址即是其所映 射的系统段中的线性地址,这样,只要能够得到这个线性地址,32位代码就可以轻易地访问到16位程序的数据(LTW32 的32位侧使用此方法从16位侧获得屏幕截获的信息)。而16位段选择符的线性基址可以通过使用系统调用GetSelectorBase()得到,具体实 现可参考源程序。线性地址计算的例子如下:

16位地址:07F2:1234H

段选择符 07F2H的线性基址为:82F41300H

段选择符 07F2H的尺寸为:4000H

∵ 82F41300H + 1234H = 82F42534

∴ 对应的32位线性地址为28:82F42534H

3. 动态修改Windows内核

如 前所述,Windows95不是一个“纯”32位操作系统,其内核模块中的USER和GDI均是用16位代码实现的。USER32.DLL和 GDI32.DLL只是16位的USER.EXE和GDI.EXE的32位调用接口。因此,如果屏幕截获程序用32位代码实现,则只能截获32位应用程序 对USER32.DLL和GDI32.DLL的调用,无法截获16位应用程序对USER.EXE和GDI.EXE的调用,所以如果想截获所有应用程序(包 括Windows95的桌面程序Explorer)中有关屏幕输出的系统调用,则应该用16位代码实现屏幕截获功能。这就是LTW32为什么不是“纯” 32位应用程序的原因。LTW32主要截获两个系统调用TextOut()和ExtTextOut(),方法很简单,把这两个函数的头五个字节修改为一个 JMP FAR 指令,使得对这两个函数的调用均转向屏幕截获程序。这就涉及到一个关键问题:动态修改Windows的代码。

在传统的 DOS程序中,动态修改程序代码无任何困难,但在Windows中则不然,因为在Windows中,代码可被同一程序的多个实例(进程)共享,所以系统不 允许应用程序动态的修改代码。在16位侧,内存的可读、写属性是与段选择符联系在一起的。段选择符基本上可分为两类:数据段选择符和代码段选择符。前者可 读、可写、不可执行;后者可读、可执行、不可写。Windows提供了这两类段选择符相转换的系统调用。未公开的16位系统调用 AllocCStoDSAlias()为给定的代码段选择符分配一个具有相同线性基址和尺寸的数据段别名(DS Alias)。通过DS别名可以对给定的代码段进行修改。AllocCStoDSAlias()的使用方法如下:

WORD (FAR PASCAL *AllocCStoDSAlias)(WORD);

AllocCStoDSAlias = GetProcAddress(

GetModuleHandle(“KERNEL”), ”ALLOCCSTODSALIAS”);

调用参数为给定的代码选择符,调用成功时返回一个线性基址和尺寸均与原代码选择符相同的DS别名。当不再使用此DS别名时,要用系统调用FreeSelector()把DS别名释放掉。

使用上述技术,就可实现动态修改Windows代码,从而改变GDI的系统调用TextOut()和ExtTextOut()的执行动作,实时地截获屏幕输出,为实现鼠标随动翻译提供可能。

把上述的32位到16位的形式替换、32位代码与16位代码的数据交换、动态修改Windows内核等技术综合应用在一起,配合单词查找算法和词组分析算法就可以实现鼠标随动翻译功能。

关于金山词霸的屏幕取词3相关推荐

  1. 关于金山词霸的屏幕取词1

    "金山词霸"屏幕取词技术揭密(讨论稿) (17千字) 发信人:5,555 时 间:2001-11-1 9:30:12 详细信息: "金山词霸"屏幕取词技术揭密( ...

  2. 金山词霸无法屏幕取词的解决方法

    金山词霸是个好软件啊, window server 2003sp1也是好系统, 不过他们俩在一起时就让我很郁闷了.昨天装了发现没法屏幕取词,结果让我ctrl+c, ctrl+v了一天. 今天实在受不了 ...

  3. 运用金山词霸组件开发属于自己的屏幕取词模块!!

    本软件是基于金山词霸组件进行Com 开发 , 所以需要你的机子上要装有金山词霸软件 ! 使用金山词霸的屏幕取词功能(XdictGrb.dll) 1.接口 1.1 GrabProxy取词代理对象 Fun ...

  4. 屏幕取词技术实现原理与关键源码

    转自: https://www.cnblogs.com/seacryfly/archive/2012/01/08/2316511.html 虽然屏幕取词技术早已经不是什么秘密,以至于除了汉化工具.翻译 ...

  5. 金山词霸”屏幕取词技术揭密(讨论稿)

    金山词霸"屏幕取词技术揭密(讨论稿) 主题 屏幕取词技术系列讲座(一) 作者 亦东 很多人对这个问题感兴趣. 原因是这项技术让人感觉很神奇,也很有商业价值. 现在词典市场金山词霸占了绝对优势 ...

  6. c# 实现金山词霸一样的屏幕取词

    c# 屏幕取词想做金山词霸一样的屏幕取词 告诉你两个方法: 第一: 在金山词霸中2005中带了一个XdictGrb.dll,添加引用 然后下面是代码 using System; using Syste ...

  7. 解决金山词霸和有道词典不能对pdf文档屏幕取词的方法

    解决金山词霸和有道词典不能对pdf文档屏幕取词的方法 http://www.docin.com/p-14101033.html

  8. 金山词霸”屏幕取词技术揭密

    金山词霸"屏幕取词技术揭密                               "金山词霸"屏幕取词技术揭密(讨论稿)                       ...

  9. Android金山屏幕取词,金山词霸屏幕取词方法分析

    随着使用英语的人数越来越多,它逐渐成为我们日常生活中交流.阅读的语言,现在我们出去,如果不懂点英语,还真的无法快乐地和其他小伙伴愉快的玩耍.可是自己平时工作或者学习的原因,根本没有时间静下心来去学习, ...

最新文章

  1. 程序员偷偷深爱的9个不良编程习惯
  2. python面向对象基础语言进阶
  3. ABAP--关于ABAP流程处理的一些命令的说明(stop,exit,return,check,reject)
  4. JavaScript文档对象模型DOM节点操作之创建和添加节点(5)
  5. html标题%3ctitle%3e,What's a valid HTML5 document?
  6. MFC 通用对话框之“浏览“对话框
  7. i5 10400 + B460M 黑苹果 EFI Big Sur 11.6
  8. 在水处理控制系统中正确运用信号隔离器
  9. 为一个理想而奋斗一生
  10. 2020年营收仅62.5万,九城凭什么砸1亿美金购买矿机?
  11. Python Network(一)基础入门(节点和边基本概念,网络统计量)
  12. 阿里云增强版实人认证--银行卡要素核验
  13. LED技术50年秘史回顾:从指示灯到街灯
  14. 同样诞生于顶尖大学,一个市值千亿,一个曾经仅次腾讯百度,如今却。。。...
  15. 共享自助洗车小程序源码
  16. bzoj3054 Rainbow的信号(位运算+瞎搞)
  17. 初学嵌入式开发ARM的学习方法
  18. Android模仿途牛app源码,仿途牛旅游APP项目开发
  19. 微软ERP Axapta与Sap、Oracle的比较
  20. 电子科技大学计算机与科学学院,钟秀琴 - 电子科技大学 - 计算机科学与工程学院...

热门文章

  1. 面板数据转截面数据、截面数据转面板数据、合并多个面板数据
  2. 14 行 CSS 代码实现明暗模式
  3. 3.26期货每日早盘操作建议
  4. ucf 转xdc_XDC约束技巧之I/O篇(下)
  5. excel减法函数_Excel教程:最常用的SUM函数送给你【收藏版】
  6. 上传文件到GitHub上的两种方法(纯新手可以看看)
  7. 前端如何实现微信扫描二维码下载应用,根据手机系统跳转不同页面
  8. 单片机并行口I/O接口扩展
  9. AT32 与SRAM/PSRAN/NOR FLASH的接口简介
  10. java字体大小设置快捷键_【转】Eclipse,MyEclipse快捷键及字体设置