I am trying to call the USER32.DLL function from assembly code. I launched an application (calc.exe) in Ollydbg 2.01. I chose calc.exe just because I know it loads USER32.DLL.

I see the format as:

MessageBox(HWND hWnd, LPCTSTR lpText, LPCTSTR lpCaption, uType);
        hWnd=0 usually  "If this parameter is NULL, the message box has no owner window"
        uType = MB_OK =0 for OK button only


I'm pushing the 4 values on the stack and then trying to enter the following into Olly:


But Olly won't assemble it and gives me the error "Please specify module" (as in link)

enter image description here

I know USER32.DLL is loaded: enter image description here

and I do see that messagebox procedure is in memoryenter image description here:

Edit: It appears I can't use the exact syntax Olly disassembles as. For example, calc.exe calls USER32.MessageBeep, but it does it indirectly by using an addressed stored at 00121420 = &USER32.MessageBeep.

00145C19  |.  FF15 20141200 CALL DWORD PTR DS:[<&USER32.MessageBeep> ; \USER32.MessageBeep

To get Olly to create the same instruction I would double-click and assemble:

CALL DWORD PTR DS:[00121420]

and then

00145C19  |.  FF15 20141200 CALL DWORD PTR DS:[<&USER32.MessageBeep> ; \USER32.MessageBeep

will appear. It would be nice if I could figure out how to type the label USER32.MessageBeep instead of hunting for it and copy/pasting the address.

It seems perhaps there is more to know before one can simply call a function in a loaded DLL. When I see people edit patches in Olly to call procedures from other modules they seem to be only calling procedures already called by the original program, whereas for USER32.DLL with MessageBoxA I have the extra challenge of it not being in memory. I got strange results when I tried to call the messagebox (it appeared in the background but wouldn't let the mouse go near it and returned to a strange address of 90909090 -possibly due to my next instruction opcodes). Perhaps this strange behavior is due to it having needed to do some setup for messageboxes which wasn't done by the program.

So perhaps an answer to my question depends on whether the procedure is somehow already loaded by the original program. In Blabbb's answer, s/he uses notepad.exe not calc.exe.

My question is perhaps getting more unfocused but perhaps a good answer to my question could explain how other modules are loaded, as well as how to make this happen in Ollydbg. I am still learning how PE applications are loaded into memory but I wonder if the answer is that to go between modules we shouldn't expect to see the relative CALL opcode E8 (see blabbb's comment below) since the programmer doesn't know what address in memory the DLL procedure will be loaded into, and in the original program they must go indirectly through an indirect CALL with opcode FF15 instead. I assume this may be related to the act of "registering a DLL function maybe?". In calc.exe it looks like MessageBoxA can't be called indirectly (unless if I edit memory somewhere with its address perhaps). But if I am paused inside a program already loaded into Olly I should be able to assemble these relative CALL instructions and invoke the procedure.

In my case with calc.exe I see some, but not all, USER32.DLL procedures in the calc .text part of memory. It appears programs call them indirectly through this list. For example here are some of the USER32 enter image description here

With calc.exe I can't find MessageBoxA here, but if I look for its address in the USER32.DLL module, and select names (see below)

enter image description here

I can sort by name, and start typing the name so it finds it for me

enter image description here

and then assemble call 7634FD1E

00148C40      6A 00         PUSH 0
00148C42      68 598C1400   PUSH 00148C59                            ; ASCII "cap"
00148C47      68 5D8C1400   PUSH 00148C5D                            ; ASCII "text"
00148C4C      6A 00         PUSH 0
00148C4E      E8 CB702076   CALL MessageBoxA

enter image description here

1 Answer 1


Names are meaningless unless you speak the language of the interpreter binary is universal
when in doubt choose binary
use call 12345678 instead of call @lkfklsdf.skhfkhfasfhkasjfh
or learn the language

call DWORD [user32.MessageBoxA] 

and it should take no more than a few minutes to form logic instead of hours waiting for a reply in a forum

screen shot shows a few variation of the call syntax
explore and experiment things before asking questions


ff 15 is an indirect call 
e8 is a direct call 

if the dll is loaded then you can call with E8
an indirect call needs an import already resolved
in the example though the indirect call is resolved
it will be calling a DWORD pointed by the symbol (bogus address)
behavior does not matter if it calc or notepad if you noticed i am assembling on ntdll address space

enter image description here

enter image description here

  • I do look for a while and try things before I bother the world with a question. Likely if I have trouble and ask, it will help others too. When I get it figured out completely, I'll answer my own question then if no one provides a full satisfactory answer. So far, I realize E8=opcode for CALL that is relative to the next instructions address, and FF15 is an indirect call. The indirect CALL is through an address already loaded into the memory of the process. On that I realize that the program has to have loaded it it seems, because user32.messageboxA isn't working for calc.exe, but beep is
    – Markbotix
    Jan 31, 2016 at 6:06
  • edited to add more info
    – blabb
    Jan 31, 2016 at 16:17

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.