• 标 题:翻译(1) (6千字)
  • 作 者:liutong
  • 时 间:2000-7-22 15:12:35
  • 链 接:http://bbs.pediy.com

膊膊膊膊膊膊膊膊膊膊膊膊膊膊膊膊膊膊膊膊膊膊膊膊膊膊膊?
    膊    ____                    __      __          膊
    膊  /  _/_ _  __ _  ___  ____/ /____ _/ /          膊
    膊  _/ //  ' \/  ' \/ _ \/ __/ __/ _ `/ /            膊
    膊 /___/_/_/_/_/_/_/\___/_/  \__/\_,_/_/            膊
    膊  ____                          __          __    膊
    膊  / __ \___ ___ _______ ___  ___/ /__ ____  / /____膊
    膊 / /_/ / -_|_-</ __/ -_) _ \/ _  / _ `/ _ \/ __(_-<膊
    膊/_____/\__/___/\__/\__/_//_/\_,_/\_,_/_//_/\__/___/膊
    膊                                                  膊
    膊      Web: http://www.ImmortalDescendants.com      膊
    膊                    Author: UmE                    膊
    膊                  Date: 03/13/00                  膊
    膊  Topic: Re-enabling functions - Cool Edit 2000  膊
    膊            Level: Beginner/Intermediate          膊
    膊                                                  膊
    膊膊膊膊膊膊膊膊膊膊膊膊膊膊膊膊膊膊膊膊膊膊膊膊膊膊膊?

介绍:现在有许多软件是以演示版(有一些功能被禁止)提供给用户的.多数
情况下,被禁止的功能按钮是灰色的.一般来说,我们能够利用EnableMenuItem
这个API函数激活它们,但是它们被激活后不能正常工作.在这篇文章中,我将
介绍如何使演示版的软件正常工作.

所用工具:SoftIce 3.24 或更高版本

试验软件:Cool Edit 2000, cool2000.exe, 3420160字节

让我们开始吧!!!

步骤1:
当你运行程序时,出现一对话框,提示你想激活那个功能.那意思就是说,你不能
使用软件的所用功能,但同时也意味着这个程序包含所有被禁止功能的程序,
它是在启动时,根据你的选择进行切换的.我们的工作就是使所有的功能都能使用.
如果我们激活选项3和4,软件就提供Filters,Noise redction,Amplify,Envelope...
但除了Save功能.我将教你如何在它被禁止的时候激活它,激活其他功能的过程与
此相同.
首先,打开一个文件,你能看到在File菜单中的Save和Save As项是灰色的.
我们想激活它,因此进入SoftIce(按CTRL+D)并设断点(bpx enablemenuitem).
EnableMenuItem函数的结构如下:

BOOL EnableMenuItem (
        HMENU hMenu            // handle to menu resource
        UINT uIDEnableItem      // menu item to enable, disable or gray
        UINT uEnable            // menu item flags
        );

在ASM中调用的格式是:

PUSH    uEnable
PUSH    uIDEnableItem
PUSH    hMenu
CALL    [KERNEL32!EnableMenuItem]

对于我们来说,重要的是找到那个激活菜单项的标志
我们知道:

uEnable=0            菜单项被激活(the item is enabled)

好吧,现在退出SoftIce,点击File菜单,马上你又回到SoftIce.按F11键返回到:

:00411580 6A01                    push 00000001        <-uEnable flag
:00411582 6875010000              push 00000175
:00411587 56                      push esi
:00411588 FFD3                    call ebx        <- Call EnableMenuItem

这不是我们要找的,因为它传递了一个常数给函数
如果你按Ctrl+D,程序将继续执行EnableMenuItem功能enable或disable各菜单项
在这个过程中,请注意EBP寄存器保存的是uIDEnableItem,直到你看到EBP=047E.
这个ID正好是Save As菜单项(你可以用W32Dasm反汇编cool2000.exe并找到此ID,
在列表开始部分的菜单信息区)
当你看到EBP=047E时按F11后程序如下


:004128A5 668B440C1C              mov ax, word ptr [esp+ecx+1C]
:004128AA 50                      push eax
:004128AB 55                      push ebp
:004128AC 56                      push esi
:004128AD FF15D0535600            Call dword ptr [005653D0]    <-EnableMenuItem

eax(uEnable标志)的值取决于ESP和ECX.我们只要将"mov ax,word ptr[esp+ecx+1c]"
改为"mov ax,0000"(注意在指令后面加nop,保证与前面指令字节数相同),这样程序将
把0传递给EnableMenuItem函数.按上面的方法修改后,重新启动程序,你将看到Save As
菜单项已经enable了.但是当你按Save As时,程序自动关闭了.到底发生了什麽事情?
跟我来你会看到!!!

步骤2:现在我们已经激活了所有菜单项,我们希望它们能工作.
正如你知道的:当点击菜单项时,程序将发出一个WM_COMMAND给系统,系统将根据相关
的ID处理它.
打开SoftIce并输入"hwnd".这条命令将返回所有在桌面上已开窗口的handle.
你可看到下列内容:

Window Handle    hQueue    Sz    QOwner    Class Name    Window Procedure

我们感兴趣的是window如何处理Cool Edit的主窗口.我们想从WM_COMMAND产生的地方
观察到底发生了什麽.注意下面:

Window Handle    hQueue    Sz    QOwner        Class Name    Window Procedure

  0414(1)      1087    32    COOL2000        COOL2000SS  32CF:0000051E

现在在message WM_COMMAND(it needs also the handel of the window)处设断点

                    bmsg 0414 WM_COMMAND

从SoftIce中退出并点击Save As菜单项......你将回到SoftIce.
记住我们要找的是处理此ID号的一小段代码:我们能在source code中找到,因为
编程者不可能修改系统dll使其适应他的程序!

设置下面的断点:bpx k32thk1632prolog(想了解为什麽?在www.ImmortalDescendants.com
站点可找到相关资料),按Ctrl+D退出SoftIce,但马上又回来了,按F11键,到:

CALL    [KERNEL32!K32Thk1632Prolog]
CALL    [.....]                 <-This is very important!!
CALL    [KERNEL32!K32Thk1632Epilog]

按F8进入[KERNEL32!K32Thk1632Prolog]后面的call,直到你找到cool2000的代码,
现在注意各个寄存器的值,继续跟踪直到:

:004C896D 8B8C24EC010000          mov ecx, dword ptr [esp+000001EC]
:004C8974 8B9424E8010000          mov edx, dword ptr [esp+000001E8]
:004C897B 51                      push ecx
:004C897C 52                      push edx                <- 1
:004C897D 57                      push edi                <- 2
:004C897E 50                      push eax                <- 3
:004C897F FF15C4545600            Call dword ptr [005654C4]        <- 4

1-将edx压入堆栈(edx=111).这是WM_COMMAND信息的HEX码
2-将edi压入堆栈(edi=047e).这是Save As菜单项的ID
3-将eax压入堆栈(eax=0414).这是cool2000的window handle
4-调用SendMessageA函数

这个功能将WM_COMMAND信息发送到系统的信息队列.下一步这个信息将被 DefWindowProcA函数
处理.按F8进入SendMessageA函数直到你再次来到cool2000的代码,在此我们将找到关键点:

:00422900 55                      push ebp
:00422901 8BEC                    mov ebp, esp
:00422903 83E4F8                  and esp, FFFFFFF8
:00422906 B854140000              mov eax, 00001454
:0042290B E890FE1100              call 005427A0
:00422910 A124AE5800              mov eax, dword ptr [0058AE24]
:00422915 53                      push ebx
:00422916 56                      push esi

注意EDI=047E,继续跟踪你将发现程序如何使用EDI
从此处我们的ID将与各种常数比较以确定我们选择的ID.
跟踪若干行后,发现:

:0042C389 81FF7E040000            cmp edi, 0000047E    <-Yeah!! Our ID!!
:0042C38F 0F8738070000            ja 0042CACD
:0042C395 0F840A080000            je 0042CBA5        <-Jump to 0042CBA5

At 0042CBA5 we find:

:0042CBA5 6A01                    push 00000001
:0042CBA7 E8C4AB0600              call 00497770
:0042CBAC 83C404                  add esp, 00000004
:0042CBAF 85C0                    test eax, eax
:0042CBB1 7511                    jne 0042CBC4

在0042CBA7的call用于选择被选的ID是处理还是跳过.
如果eax=0,ID被跳过;eax=1,ID被处理.
因此将jne改为jmp,Save As菜单项将恢复功能


希望你能喜欢此教程!

Bye!

UmE

Contact me at: ume15@hotmail.com