3. Calling MessageBox winAPI from GO

#systemprogramming #golang #messagebox

Windows APIs, or Application Programming Interfaces, are sets of functions, procedures, and protocols provided by the Microsoft Windows operating system to allow software applications to interact with the system and its underlying components.

A full list of (documented) windows APIs can be found on Microsoft's website.

For this example we will call the MessageBox API. Microsoft provides the Syntax to call the API from C++.

int MessageBox(
  [in, optional] HWND    hWnd,
  [in, optional] LPCTSTR lpText,
  [in, optional] LPCTSTR lpCaption,
  [in]           UINT    uType
);

There are two packages that will help us call Windows APIs from GO. Let's explore both ways.

The Windows package is the easiest way of calling windows APIs. It provides a Go interface to low level windows APIs.

PROS:

  • Easy to use

  • No need to translate between C and GO data types

  • IntelliSense will show the arguments needed in the IDE when the package is imported

CONS:

  • Not every Windows API is included in this package

As mentioned above when the package is imported we will have syntax recommendations straight in the IDE. It shows parameter data types required and any potential errors. Also the return values are shown on the far right. (ret int32, err error)

package main

import (
	"golang.org/x/sys/windows"
)

func main() {

	hWnd := uintptr(0)
	windows.MessageBox(
		windows.HWND(hWnd), 		         	  // [in, optional] HWND    hWnd,
		windows.StringToUTF16Ptr("Used Windows Package"), // [in, optional] LPCTSTR lpText,
		windows.StringToUTF16Ptr("MessageBox 1/2"),       // [in, optional] LPCTSTR lpCaption,
		windows.MB_OK) 				          // [in] UINT    uType

}

The syscall package is harder to use but more powerful

PROS:

  • Call any function from any DLL

CONS:

  • No IntelliSense

  • Manually convert Windows to GO data types

The following Table from the book "Black Hat Go: Go Programming For Hackers" (Highly recommended btw) helps with the translation of datatypes

Windows Data TypeGo Data Type

BOOLEAN

byte

BOOL

int32

BYTE

byte

DWORD

uint32

DWORD32

uint32

DWORD64

uint32

WORD

uint16

HANDLE

uintptr

LPVOID

uintptr

SIZE_T

uintptr

LPCVOID

uintptr

HMODULE

uintptr

LPCSTR

uintptr

LPDWORD

uintptr

Having All the information we need we can proceed writing the code for our messagebox. From the MessageBox reference page we can see that function MessageBox is exported in the User32.dll.

We should first import the dll and get the API address using the following code

user32dll := syscall.NewLazyDLL("User32.dll")
procMsgBox := user32dll.NewProc("MessageBoxW")

We can then get all our parameters declared before passing them to the function

hWnd = uintptr(0)
lpText, _ := syscall.UTF16PtrFromString("Used Syscall Package")
lpCaption, _:= syscall.UTF16PtrFromString("MessageBox 2/2")
uType := uint(0)

And finally we can call the function

procMsgBox.Call(
		hWnd, 
		uintptr(unsafe.Pointer(lpText)), 
		uintptr(unsafe.Pointer(lpCaption)), 
		uintptr(uType))

Complete Code:

package main

import (
	"log"
	"syscall"
	"unsafe"

	"golang.org/x/sys/windows"
)

func main() {
	// windows package
	hWnd := uintptr(0)
	windows.MessageBox(
		windows.HWND(hWnd), // [in, optional] HWND    hWnd,
		windows.StringToUTF16Ptr("Used Windows Package"), // [in, optional] LPCTSTR lpText,
		windows.StringToUTF16Ptr("MessageBox 1/2"),       // [in, optional] LPCTSTR lpCaption,
		windows.MB_OK) // [in] UINT    uType

	// syscall package
	user32dll := syscall.NewLazyDLL("User32.dll")
	procMsgBox := user32dll.NewProc("MessageBoxW")

	hWnd = uintptr(0)
	lpText, err := syscall.UTF16PtrFromString("Used Syscall Package")
	if err != nil {
		log.Fatalln("lpText UTF16PtrFromString Failed")
	}
	lpCaption, err := syscall.UTF16PtrFromString("MessageBox 2/2")
	if err != nil {
		log.Fatalln("lpCaption UTF16PtrFromString Failed")
	}
	uType := uint(0)

	procMsgBox.Call(
		hWnd, 
		uintptr(unsafe.Pointer(lpText)), 
		uintptr(unsafe.Pointer(lpCaption)), 
		uintptr(uType))
}

Last updated