Statistics

Members: 1927
News: 293
Web Links: 1
Visitors: 3931470

Who's Online

We have 1 guest online
Damn Vulnerable LinuxDamn Vulnerable Linux (DVL) is a Linux-based (modified Damn Small Linux) tool for IT-Security & IT-Anti- Security and Attack & Defense. [CLICK HERE FOR MORE INFOS! ]

Featured Conference Video

T16-Recon2006-Joe_Stewart-OllyBonE.gif OllyBone - Semi-Automatic Unpacking on IA-32. View the conference video here!
Home arrow About/Disclaimer
MessageBox Display
User Rating: / 1
PoorBest 
Written by Iczelion   


We will create a fully functional Windows program that displays a message box saying "Win32 assembly is great!".

Windows prepares a wealth of resources for use by Windows programs. Central to this is the Windows API (Application Programming Interface). Windows API is a huge collection of very useful functions that resides in Windows itself, ready to be used by any Windows programs.

 

 

 

These functions are stored in several dynamic-linked libraries (DLLs) such as kernel32.dll, user32.dll and gdi32.dll, to name a few. Kernel32.dll contains API functions that deal with memory and process management. User32.dll controls the user interface aspects of your programs. Gdi32.dll is responsible for graphics operation. Other than "the main three", there are other DLLs that your program can make use of, provided you have enough information about the desired API functions stored in them.

Windows programs dynamically link to these DLLs, i.e. the codes of API functions are not included in the executable file. This is very different from what's called static linking in which actual codes from software libraries are included in the executable files. In order for programs to know where to find the desired API functions at runtime, enough information must be embedded into the executable file for it to be able to select the correct DLLs and correct functions. That information is in import libraries. You must link your programs with the correct import libraries or it will not be able to locate the desired API functions.

There are two types of API functions: One for ANSI and the other for Unicode. The name of API functions for ANSI are postfixed with "A", eg. MessageBoxA. Those for Unicode are postfixed with "W" (for Wide Char, I think).

Windows 95 natively supports ANSI and Windows NT Unicode. But most of the time, you will use an include file which can determine and select the appropriate API functions for your platform. Just refer to the API function name without the postfix.

I'll present the bare program skeleton below. We will fill it out later.

.386
.model flat, stdcall
.data
.code

Main
end Main

Every Windows program must call an API function, ExitProcess, when it wants to quit to Windows. In this respect, ExitProcess is equivalent to int 21h, ah=4Ch in DOS.

Here's the function prototype of ExitProcess from winbase.h:

void WINAPI ExitProcess(UINT uExitCode);

-void means the function does not return any value to the caller. -WINAPI is an alias of STDCALL calling convention. -UINT is a data type, "unsigned integer", which is a 32-bit value under Win32 (it's a 16-bit value under Win16)
-uExitCode is the 32-bit return code to Windows. This value is not used by Windows as of now.

In order to call ExitProcess from an assembly program, you must first declare the function prototype for ExitProcess.

.386
.model flat, stdcall
ExitProcess PROTO :DWORD
.data
.code
Main:

invoke ExitProcess, 0
end Main

That's it. Your first working Win32 program. Save it under the name msgbox.asm. Assuming ml.exe is in your path, assemble msgbox.asm with:

ml /c /coff /Cp msgbox.asm

/c tells MASM to assemble the source file into an object file only. Do not

invoke Link.exe automatically.
/coff tells MASM to create .obj file in COFF format. /Cp tells MASM to preserve case of user identifiers

Then go on with link:

     link /SUBSYSTEM:WINDOWS  /LIBPATH:c:\masm\lib  msgbox.obj
kernel32.lib

/SUBSYSTEM:WINDOWS informs Link.exe on which platform the executable is

intended to run
/LIBPATH:<path to import library> tells Link where the import libraries

are. In my PC, they're located in c:\masm\lib.

Now that you get msgbox.exe. Go on, run it. You'll find that it does nothing. Well, we haven't put anything interesting in it yet. But it's a Windows program nonetheless. And look at its size! In my PC, it is 1,536 bytes. The line:

ExitProcess PROTO :DWORD

is a function prototype. You create one by declaring the function name followed by the keyword "PROTO" and lists of data types of the parameters prefixed by colons. MASM uses function prototypes to type checking which will prevent nasty stack errors that may pass unnoticed otherwise.

The best place for function prototypes is in an include file. You can create an include file full of frequently used function prototypes and data structures and include it at the beginning of your asm source code.

You call the API function by using "invoke" keyword:

invoke ExitProcess, 0

INVOKE is really a kind of high-level call. It checks number and types of parameters and pushes parameters on the stack according to the specified calling convention (in this case, stdcall). By using INVOKE instead of a normal call, you can prevent stack errors from incorrect parameter passing. Very useful. The syntax is:

INVOKE expression [,arguments]

where expression is a label or function name.

Next we're going to put a message box in our program. Its function declaration is:

int WINAPI MessageBoxA(HWND hwnd, LPCSTR lpText, LPCSTR lpCaption, UINT uType);

-hwnd is the handle to parent window
-lpText is a pointer to the text you want to display in the client area of the message box
-lpCaption is a pointer to the caption of the message box -uType specifies the icon and the number and type of buttons on the message box

Under Win32 , HWND, LPCSTR, and UINT are all 32 bits in size.

Let's modify msgbox.asm to include the message box.

.386
.model flat, stdcall

ExitProcess      PROTO      :DWORD
MessageBoxA PROTO      :DWORD, :DWORD, :DWORD, :DWORD

.data
MsgBoxCaption db "Our First Program",0 MsgBoxText db "Win32 Assembly is Great!",0 .const

NULL        equ  0
MB_OK       equ  0

.code
Main:

     INVOKE    MessageBoxA, NULL, ADDR MsgBoxText, ADDR MsgBoxCaption, MB_OK
INVOKE    ExitProcess, NULL

end Main

Assemble it by:

        ml /c /coff /Cp msgbox.asm
link /SUBSYSTEM:WINDOWS /LIBPATH:c:\masm\lib msgbox kernl32.lib

user32.lib

You have to include user32.lib in your Link parameter, since link info of MessageBoxA is in user32.lib.

You'll see a message box displaying the text "Win32 Assembly is Great!". Let's look again at the source code:

We define two zero-terminated strings in .data section. Remember that all strings in Windows must be terminated with zero (ASCIIZ).

We define two constants in .const section. We use constants to improve the clarity of the source code.

Look at the parameters of MessageBoxA. The first parameter is NULL. This means that there's no window that owns this message box.

The operator "ADDR" is used to pass the address of the label to the function. This operator is specific to MASM. No TASM-equivalent exists. It functions like "OFFSET" operator but with some differences:

  1. It doesn't accept forward reference. If you want to use "ADDR foo", you have to declare "foo" before using ADDR operator.
  2. It can be used with a local variable. A local variable is the variable that is created on the stack. OFFSET operator cannot be used in this situation because the assembler doesn't know the true address of the local variable at assemble time.