Help file v1.0 by woody^drn

I've started some new files, it's more a file to help to gain knowledge on how to enable menu items and text. We'll start with the menu File-> Enable Me. This menu item is disabled, so lets start enabling it .. it's easy so don't be scared ;)

The thing you can do is to load your favorite resource editor and enable it. But that sucks ;) We'll do this manual .. take a look at the bottom at the help#1.exe file:

.00448E90:  4D 65 6E 75-49 74 65 6D-09 45 6E 61-62 6C 65 6D  TMenuItem Enablem
.00448EA0:  65 31 07 43-61 70 74 69-6F 6E 06 0A-45 26 6E 61  e1 Caption.E&na
.00448EB0:  62 6C 65 20-6D 65 07 45-6E 61 62 6C-65 64 08 00  ble me Enable
.00448E80:  61 70 74 69-6F 6E 06 05-26 46 69 6C-65 00 09 54  aption

Ofcause I can't display non-ascii chars here, but as you can see here it says TMenuItem Enableme1 Caption. E&nable me. This just means that it's a TMenuItem which delphi calls his menu items. The item in the menu is called Enableme1, so if I should enable the menu in delphi I would say enableme1.enabled:=true;

The last one Enable is the procedures this item has. And we want it to be enabled. The hex for Enable is 07 45 6e 61 62 6c 65 64, just right after that it has the hex value 08. This is the place to patch, 08 = Disabled, 09 = Enabled. So you just have to patch 08 to 09 and it will be enabled.

This is one way of doing it, but maybe the author of a program has made a check if the menu is enabled. That's why I've made the button "Enable Menu Item", when you press it, it will check if the menu item is enabled, if so it will disable it, if not it will enable it.

If you take a look at the Win32 Programmer's Reference, (you can get it from www.crackstore.com) it says:

The EnableMenuItem function enables, disables, or grays the specified menu item.

BOOL EnableMenuItem(

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

So in assembler this would look like this:

push uEnable
push uIDEnableItem
push hMenu
call EnableMenuItem

Parameters

hMenu

Identifies the menu.

uIDEnableItem

Specifies the menu item to be enabled, disabled, or grayed, as determined by the uEnable parameter. This parameter specifies an item in a menu bar, menu, or submenu.

uEnable

Specifies flags that control the interpretation of the uIDEnableItem parameter and indicate whether the menu item is enabled, disabled, or grayed. This parameter must be a combination of either MF_BYCOMMAND or MF_BYPOSITION and MF_ENABLED, MF_DISABLED, or MF_GRAYED.

Value Meaning
MF_BYCOMMAND Indicates that uIDEnableItem gives the identifier of the menu item. If neither the MF_BYCOMMAND nor MF_BYPOSITION flag is specified, the MF_BYCOMMAND flag is the default flag.

MF_BYPOSITION Indicates that uIDEnableItem gives the zero-based relative position of the menu item.

MF_DISABLED Indicates that the menu item is disabled, but not grayed, so it cannot be selected.

MF_ENABLED Indicates that the menu item is enabled and restored from a grayed state so that it can be selected.

MF_GRAYED Indicates that the menu item is disabled and grayed so that it cannot be selected.

Return Values

The return value specifies the previous state of the menu item (it is either MF_DISABLED, MF_ENABLED, or MF_GRAYED). If the menu item does not exist, the return value is 0xFFFFFFFF.

To enable a menu item, it uses the api enablemenuitem (duh!) ;) so if we set softice to break on that (bpx enablemenuitem), it will break on enablemenuitem then press F11 to get the caller and we are here:

* Reference To: user32.EnableMenuItem, Ord:0000h
                                  |
:0042E161 E8B27EFDFF              Call 00406018

* Referenced by a (U)nconditional or (C)onditional Jump at Addresses:
|:0042E13D(C), :0042E143(C)
|
:0042E166 33D2                    xor edx, edx
:0042E168 8BC6                    mov eax, esi
:0042E16A 8B08                    mov ecx, dword ptr [eax]
:0042E16C FF5134                  call [ecx+34]

This may seem a little confusing for you, but don't worry ... delphi makes to code look pretty weird sometimes and fucks the opcodes up. but scroll up a bit and what it does here is:

:0042E138 8B7E58                  mov edi, dword ptr [esi+58]
:0042E13B 85FF                    test edi, edi
:0042E13D 7427                    je 0042E166

Mov [esi+58] into edi, it gets the enable value for this menu, checks if it's zero - checks if the menu is enabled. If so it jumps to 42e166.

:0042E13F F6462002                test [esi+20], 02
:0042E143 7521                    jne 0042E166

Double checks ... this is not my source, it's delphi that does this .. again delphi "errors", but I'm sure it supposed to ;)

:0042E145 33C0                    xor eax, eax
:0042E147 8AC3                    mov al, bl
:0042E149 8B04855CD74300          mov eax, dword ptr [4*eax+0043D75C]
:0042E150 83C800                  or eax, 00000000

Okay here it gets the uEnable offset.

:0042E153 50                      push eax
:0042E154 0FB74644                movzx eax, word ptr [esi+44]
:0042E158 50                      push eax
:0042E159 8BC7                    mov eax, edi
:0042E15B E824F4FFFF              call 0042D584
:0042E160 50                      push eax

* Reference To: user32.EnableMenuItem, Ord:0000h
                                  |
:0042E161 E8B27EFDFF              Call 00406018

Now it pushes eax, which has the value for uEnable. Pushes the next uIDEnableItem, which has the value for which item in the menu it gonna change. Then the handle for the menu is pushed. And last it calls the api EnableMenuItem.

If we would call the EnableMenuItem like this:

push MF_GRAYED
push EnableMe1
push TMenuItem
call EnableMenuItem

it would have grayed the menu, so what we gonna change here is:

push MF_ENABLED
push EnableMe1
push TMenuItem
call EnableMenuItem

So that it will always turn it on no matter what. MF_ENABLED is equal to 0, so what we're gonna do here is to make sure it pushes 0, so we're gonna make eax 0 no matter what:

:0042E13D 7427                    je 0042E166
:0042E13F F6462002                test [esi+20], 02
:0042E143 7521                    jne 0042E166
:0042E145 33C0                    xor eax, eax
:0042E147 8AC3                    mov al, bl
:0042E149 8B04855CD74300          mov eax, dword ptr [4*eax+0043D75C]
:0042E150 83C800                  or eax, 00000000

Changes to this:

:0042E13D 90                      nop
:0042E13E 90                      nop
:0042E13F F6462002                test [esi+20], 02
:0042E143 90                      nop
:0042E144 90                      nop
:0042E145 33C0                    xor eax, eax
:0042E147 90                      nop
:0042E148 90                      nop
:0042E149 90                      nop
:0042E14A 90                      nop
:0042E14B 90                      nop
:0042E14C 90                      nop
:0042E14D 90                      nop
:0042E14E 90                      nop
:0042E14F 90                      nop
:0042E150 90                      nop
:0042E151 90                      nop
:0042E152 90                      nop

Here we xor eax with eax aka mov eax,0 .. so eax is zero.. easy. now try it out and see for your self. No matter what we do, it will always enable the menu item.

That's it ...

-wOODY^dRN