·汉化新世纪 ·汉化新世纪论坛 ·百家争鸣 ·论坛集萃 ·汉化问答 ·软件介绍
文章首页 >> 汉化教学 >> 编程知识 >> 用OllyDbg静态分析修改字体    Creative Commons License,创作共用协议(中文版)  署名 非商业性使用 禁止演绎

用OllyDbg静态分析修改字体

作者: 雅枫 来源:雅枫的博客 时间:2005-03-12 点击:16048

OllyDbg静态分析修改字体

Ollydbg是一个动静结合的工具,能非常快捷的分析程序,并且其内建汇编器与编辑器,能在不用十六进制编辑器的情况下修改文件,并且反汇编代码也比W32dasm清晰的多,所以我们有足够的理由抛弃W32dasm而用Ollydbg来做静态分析,有人要说了,既然Ollydbg支持动态分析,为什么还要讲静态分析呢?因为静态是动态的基础,动态可以说是进行更好的静态分析的辅助手段(我一般不会纯静态分析,不到迫不得已,我一般是一边调试一边分析的)。所以只有在掌握静态分析技术的基础上,才有可能使用动态辅助理解。好了,不说废话了。让我们试着用ollydbg分析一个程序先。

这是我用汇编写的一个程序,其中与字体有关的有两处CreateFontA(菜菜:这是什么?)的调用,一处CreateFontIndirectA(菜菜:这个更长了!俺不懂英文撒)的调用,两处GetStockObject(菜菜:又来了!不懂啊,放弃吧……)的调用。可能你还不知道这三个东东是什么,不要急嘛!我这不正想解释嘛……,上边是三个API,也就是三个字体函数,也就是三个能生成字体的功能块,你可以把它们想象成三个黑匣子,你给它不同的条件(传入一些描述字体的参数),他们就会生成不同的字体(返回想要的字体句柄)。句柄又是什么?术语是一个32位的指针或者id,如果不懂你就可以认为他就代表了这个字体。也可以在大脑中把它们等同起来,认为字体跟字体句柄就是一个东东(实际上当然不是,假设一个字体函数返回了12340000,在刚运行函数后你用这个值可以代表一种字体,时间长了可能这串数字就没啥意义了)。那一个函数是怎么调用的呢?当然是用Call指令来调用,这个没啥好说的,call这个指令就是调用函数,比如我们调用CreateFontA这个函数,我们可以写上Call CreateFontA。刚才我说了,我们用函数生成字体,要有一些参数啊,要不CreateFontA怎么知道我们要什么样的字体呢?这些参数怎么传入呢?利用堆栈!我们把函数的参数先用入栈的指令push一个一个的写入堆栈就可以传入函数了,如果我们不传入参数可不可以呢?答案是不可以,因为这些API函数默认是从堆栈取出参数来用的,假如一个函数需要4个参数,在函数内部就会取出4个参数并且在函数内部会清除这4个参数(堆栈最顶部的四个数据(标准调用约定)),如果你在调用前不幸没有把参数压入堆栈,或者少压或多压几个参数,那么堆栈就完全乱套了,运行后就是一个非法操作……。值得说一下,API调用是从右往左入栈的,即如果一个函数有3个参数,分别是P1P2P3,则你就需要在调用改函数前:

PUSH P3

PUSH P2

PUSH P1

CALL 函数

WIN32ASM中,每个参数都是固定的4个字节(32位嘛)那么长,那如果我想输入一个大于4个字节的参数(如一个字串)怎么办呢?传入指针!也就是地址,在32位的WINDOWS下,一个地址也是4个字节的。我们先看看CreateFontA函数的原型:

HFONT CreateFontA(

    int nHeight,   //字体高度

    int nWidth,    // 字体宽度(一般设置为0

    int nEscapement,  // 这个一下边一个是设置斜度

    int nOrientation,   //

    int fnWeight, //字体的粗细400是正常600是粗体,输入0则与400效果相同

    DWORD fdwItalic,     //这个以及下边两个都是是否有下画线之类的属性一般为0

    DWORD fdwUnderline,      //

    DWORD fdwStrikeOut,      //

    DWORD fdwCharSet, //语系,这是造成乱码的罪魁,中文要设成1或者86

    DWORD fdwOutputPrecision,    // 这个与下边三个也基本没啥用,都设成0即可

    DWORD fdwClipPrecision, //

    DWORD fdwQuality,   //

    DWORD fdwPitchAndFamily,    //

    LPCTSTR lpszFace    // 这个是字体名,一般我们要设置为宋体。

   );

这个函数的参数居然有14个,也就是说在Call CreateFontA前要有14PUSH!不能多也不能少,当然最下边的字体名要第一个压入堆栈,而字体高度要最后一个压入堆栈。我们再来看看某个程序调用CreateFontA的反汇编代码:

不多不少,从字体名Arial开始正好14个吧?更为可贵的是:Ollydbg给我们把每一个参数都列了出来,我们就不用去数第几个push了。就这个字体的修改来说,只要把FaceName改成“宋体”,CharSet改成1或者86hHeight改为-12就可以了。最终的修改如下图:

大家会有疑问:为什么语系改成了push –7A而不是刚才的86了呢?因为就2字节的十六进制数来说,86实际上是被认为是-7A的,观察一下最左边的十六进制窗口,你就会发现代码实际上是6A86,push 86。同样,-12的十六进制对应的是-0C。至于字体名,当然是我们的宋体。可以看到,压入字体名的那句是push 00402054,这个00402054是什么呢?当然不是“宋体”的ascii,而是“宋体”这个字串的指针,即字串的地址了。用Ollydbg的内存窗口查看该程序地址为00402054的地方可以清楚地看到该处是“宋体”:
03

或许看到这里你开始急了:这些都是怎么弄出来的啊?OD我还不会用啊,下边我就讲解一下具体步骤。

第一步,打开Ollydbg并装入我们的文件(这个该不用我给大家讲怎么做吧?)我打开的是附件中的我写的一个字体设置的例子.你会看见OllyDbg在分析我们的软件,因为大家的机器都比较好,我写的程序也比较短大家可能不注意看看不到这个过程哈,Ollydbg分析是相当快滴。分析完了就开始我们的操作:在反汇编代码区点击右键(注意了一定要在反汇编代码区,不同的区的右键菜单可是不同的)->搜索->所有模块间调用
04

你会发现列出了一个长长的列表,全是密密麻麻的英文,呵呵。
05

其中当然有我们要找的CreateFontA,不过如果是个大程序呢?找到相应的函数岂不很难了?我们可以排一下序,点击一下列表最上边的“目标”
06

这样就比较好找了吧?排序是以英文字母排序的因为CreateFontA的第一个字母是C所以比较靠前。我们先来分析第一个:把鼠标放在第一处调用CreateFontA的那一条上,双击,是不是切换到了主界面?并且选中了Call CreateFontA上?如图
07

这就找到了我上边刚开始说的地方啦,哈哈,是不是很简单?怎么改呢?第一个Arial改成“宋体”不用我教,你们汉化的本事都比我强。最好多余的补00,我们就试着改改别的参数。我不推荐到UE下去改,建议直接在Ollydbg下改。把鼠标在CharSet上点一下,然后按一下空格键出现了下图:
08

改成push 1或者push –7A,点击“汇编”按钮,就改好啦,用相同的方法,我又改了字体的字号,改的是push –0C.如下图:
09

接下来的工作就是把修改的结果复制回我们的程序了,操作如下:在反汇编代码区点击右键-〉复制到可执行文件-〉全部修正:
10

然后在弹出的对话框中选择复制的地方,我们选择“全部复制”弹出了下边的对话框
11

不用管他,关掉后弹出下边的对话框:
12

点击“是”即可弹出保存对话框。在98下无法覆盖原来的,2000/XP下则可以。当然我推荐你改个新名字来保存,如果出错可以返工。完成后运行我们的修改结果,你会发现第一个字体修改已经成功了。我暂时没改字体名,如可以用其他工具把字体名也改成“宋体”,这个CreateFontA也就算完美了。
13

CreateFontIndirectA的字体最好在动态下修改,先不作介绍,我在来讲讲GetStockObject的字体修改。GetStockObject这个词分开是Get Stock Object意思是“获得固有的对象”什么是固有的对象呢?就是windows自带的一些绘图对象,这个可不光包括字体,还有画笔,画刷,调色板等多种,每一种对象都对应一个数字号码,即一个id。我们所做的,就是把所有的FONT对象改成DEFAULT_GUI_FONT,11号对象,以前我们用W32dasm改这类字体,需要查相应的说明,否则容易错改,如果你把人家获得画笔的代码改成了获得字体,那不出问题才怪。但是Ollydbg的出现大大减少了我们的工作量,因为Ollydbg能给我们标出是不是我们要改的地方。我实际改一下:在Ollydbg中找到GetStockObject的调用结果如下:
14

两处都是字体,分别是OEM_FIXED_FONT,SYSTEM_FONT,反正都是FONT,统一改成PUSH 11h,修改后如下:
15

按照上边的方法保存,运行结果如下图:
16

这么样?修改字体并不是多么困难吧?呵呵(众人一起怒视:这么简单的东西尼啰里啰唆说了这么一大篇,该杀,拖出去……)看官别急,这只是最简单的字体修改,GetStockObject肯定就是这么简单了,但CreateFontA却并不总是如此简单,我们还没介绍的CreateFontIndirectA的修改一般更是麻烦。不过这留在以后介绍了,这篇就到这里了。

 


测试程序:setmyfont.rar

 

汉化新世纪 责任编辑: 乾 .:|:. 标签(Tag): OllyDbg 字体

·上一篇: 基础知识(1)认识调试器 ·下一篇: 点睛文本编码查询 1.2 源代码

· 版权申明: 本文引自《雅枫的博客》,如有版权疑问请及时联系本站,以便本站处理。

· 转载申明: 本文引自《雅枫的博客》[ 作者: 雅枫],如需转载请直接联系原始作者,并请注明原始出处。

相关文章                                                                                发表评论 打印此文 关闭窗口

| 设为首页 | 加入收藏 | 联系我们 | 友情链接
Creative Commons License,创作共用协议(中文版)  署名 非商业性使用 禁止演绎
本站内容,除转载或版权特别申明的内容外,皆遵守 创造共用协议中文版之“署名-非商业性使用-禁止演绎 2.5 中国大陆”条款
This work is licensed under a Creative Commons Attribution-NonCommercial-NoDerivs 2.5 China License.
本网站内容源自汉化新世纪论坛的摘录和汉化新世纪成员的原创文章。
凡汉化新世纪论坛的文字皆默认为汉化新世纪与原作者共同拥有并授权发布。
如对本站发布文章有所异议请来信告知,我们将及时删除。
凡商业摘录本站文字请先与我们联系,本站将保留非授权商业发布的追究权利。
凡非商业摘录本站文字请明显注明出处和原作者,并不得改动,凡改动必先征求原作者同意。
苏ICP备05002283号