Assembly language > Assembly discussions

Calling a function from DLL at runtime

(1/6) > >>

Vortex:
Here is an example of calling the undocumented function MessageBoxTimeout at runtime.


--- Code: ---include     Test.inc

CallFunc64  PROTO :QWORD,:QWORD,:QWORD

.data

user32  db 'user32.dll',0
MyFunc  db 'MessageBoxTimeoutA',0

message db 'This message box will be destroyed after 4 seconds.',0
caption db 'Hello',0

;   int MessageBoxTimeoutA(HWND hWnd, LPCSTR lpText,
;       LPCSTR lpCaption, UINT uType,
;       WORD wLanguageId, DWORD dwMilliseconds);

array   dq 0,OFFSET message,OFFSET caption
        dq MB_ICONWARNING,LANG_NEUTRAL,TIMEOUT

.code


main PROC PARMAREA=4*QWORD

LOCAL hMod:QWORD

    invoke  LoadLibrary,ADDR user32
    mov     hMod,rax

    invoke  GetProcAddress,rax,ADDR MyFunc

    invoke  CallFunc64,rax,6,ADDR array

    invoke  FreeLibrary,hMod

    invoke  ExitProcess,0

main ENDP


END main

--- End code ---

John Z:
Thanks Vortex!

Very neat, always wanted something like this, never knew it was there.
Hope I can get it to work in C.

John Z

MrBcx:

--- Quote from: John Z on October 02, 2023, 03:46:02 PM ---
Hope I can get it to work in C.

John Z

--- End quote ---

Hi JJ,

This will get you there.  This is the A version. 
If you want the W versions, it's only minor edits.


--- Code: ---
#include <windows.h>
#include <stdio.h>

long __stdcall MessageBoxTimeoutA (HWND, char*, char*, int, int, int);

long __stdcall MessageBoxTimeoutA (HWND hwnd,char* Txt,char* Title,int MBType,int Langid,int Milliseconds)
{
  typedef int (__stdcall *MBTYPEDEF)(HWND, char *, char *, long, int, int);
  static MBTYPEDEF MsgBoxTimeout;
  static int Result;
  HMODULE  HMOD_USER32 = LoadLibrary("user32.dll");
  MsgBoxTimeout = (MBTYPEDEF)GetProcAddress(HMOD_USER32, "MessageBoxTimeoutA");
  Result=MsgBoxTimeout(hwnd,Txt,Title,MBType,Langid,Milliseconds);
  return Result;
}

#define MBTYPE MB_YESNOCANCEL|MB_SETFOREGROUND|MB_SYSTEMMODAL|MB_ICONINFORMATION


// Demo

int main(int argc, char *argv[])
{
   printf("% d",(int)MessageBoxTimeoutA(NULL, "This works with all compilers...", "Title Goes Here", MBTYPE, 0, 4000));
   return EXIT_SUCCESS;
}


--- End code ---

Vortex:
Hi Kevin,

Thanks for your code. Checking the object module with Agner Fog's objconv tool, I saw that the stack was balanced after calling MessageBoxTimeoutA. This should not happen as MessageBoxTimeoutA is a STDCALL function. The code is built as 32-bit in this case.


--- Code: ---_main   PROC NEAR
        push    4000
        push    0
        push    69699
        push    offset @1044
        push    offset @1043
        push    0           
        call    _MessageBoxTimeoutA
        add     esp, 24           
        push    eax               
        push    offset @1042       
        call    _printf           
        add     esp, 8             
        xor     eax, eax
        ret                       
_main   ENDP
--- End code ---

The solution is inserting the __stdcall statment just before MessageBoxTimeoutA :


--- Code: ---/*long __stdcall MessageBoxTimeoutA (HWND, char*, char*, int, int, int);*/

long __stdcall MessageBoxTimeoutA (HWND hwnd,char* Txt,char* Title,int MBType,int Langid,int Milliseconds)
{
  typedef int (__stdcall *MBTYPEDEF)(HWND, char *, char *, long, int, int);
  static MBTYPEDEF MsgBoxTimeout;
  static int Result;
  HMODULE  HMOD_USER32 = LoadLibrary("user32.dll");
  MsgBoxTimeout = (MBTYPEDEF)GetProcAddress(HMOD_USER32, "MessageBoxTimeoutA");
  Result=MsgBoxTimeout(hwnd,Txt,Title,MBType,Langid,Milliseconds);
  return Result;
}
--- End code ---

Objconv reports now the correct output :


--- Code: ---_main   PROC NEAR
        push    4000
        push    0   
        push    69699
        push    offset @104
        push    offset @104
        push    0   
        call    _MessageBoxTimeoutA@24  ;  no stack balance after the call to MessageBoxTimeoutA
        push    eax                   
        push    offset @1042         
        call    _printf               
        add     esp, 8               
        xor     eax, eax             
        ret                           
_main   ENDP

--- End code ---

Vortex:
Hello,

Pelle's Podump tool can be used to disassemble the object module :


--- Code: ---podump.exe /DISASM MBoxTimeOut.obj
--- End code ---


--- Code: ---Dump of MBoxTimeOut.obj

File type: OBJ

_MessageBoxTimeoutA@24:
  [00000000] 55                     push              ebp
  [00000001] 89E5                   mov               ebp,esp
  [00000003] 53                     push              ebx
  [00000004] 56                     push              esi
  [00000005] 57                     push              edi
  [00000006] 8B5D08                 mov               ebx,dword ptr [ebp+8]
  [00000009] 8B750C                 mov               esi,dword ptr [ebp+C]
  [0000000C] 8B7D10                 mov               edi,dword ptr [ebp+10]
  [0000000F] 6800000000             push              @1025
  [00000014] FF1500000000           call              dword ptr [__imp__LoadLibraryA@4]
  [0000001A] 6800000000             push              @1027
  [0000001F] 50                     push              eax
  [00000020] FF1500000000           call              dword ptr [__imp__GetProcAddress@8]
  [00000026] A300000000             mov               dword ptr [@1023],eax
  [0000002B] FF751C                 push              dword ptr [ebp+1C]
  [0000002E] FF7518                 push              dword ptr [ebp+18]
  [00000031] FF7514                 push              dword ptr [ebp+14]
  [00000034] 57                     push              edi
  [00000035] 56                     push              esi
  [00000036] 53                     push              ebx
  [00000037] FF1500000000           call              dword ptr [@1023]
  [0000003D] A300000000             mov               dword ptr [@1024],eax
  [00000042] 5F                     pop               edi
  [00000043] 5E                     pop               esi
  [00000044] 5B                     pop               ebx
  [00000045] 89EC                   mov               esp,ebp
  [00000047] 5D                     pop               ebp
  [00000048] C21800                 ret               18
  [0000004B] 0F1F440000             nop               [eax+eax+0]

_main:
  [00000050] 68A00F0000             push              FA0
  [00000055] 6A00                   push              0
  [00000057] 6843100100             push              11043
  [0000005C] 6800000000             push              @1044
  [00000061] 6800000000             push              @1043
  [00000066] 6A00                   push              0
  [00000068] E893FFFFFF             call              00000000
  [0000006D] 50                     push              eax
  [0000006E] 6800000000             push              @1042
  [00000073] E800000000             call              _printf
  [00000078] 83C408                 add               esp,8
  [0000007B] 31C0                   xor               eax,eax
  [0000007D] C3                     ret

SUMMARY
       8 .bss
      10 .debug$F
      28 .drectve
      53 .rdata
      7E .text
--- End code ---

Navigation

[0] Message Index

[#] Next page

Go to full version