Offensive Development with C++ and C#: Getting Started with Win32 API and practical examples


RedTeam C++ Maldev Malware Dev Offensive Development Offensive Security Win32 API MessageBox CreateToolhelp32Snapshot

We introduce the basics of Win32 API and some implementations, crucial for those interested in offensive security. We will explore fundamental concepts, necessary tools, and provide practical examples using the MessageBox function

Learning Objectives

  1. Understand what the Windows API is, its use cases, and how it interacts with the OS subsystems
  2. Learn how to implement the Windows API in C++ to pop a message or list all processes.

What is Windows API?

Programs often need to access or modify Windows subsystems or hardware but are restricted to maintain machine stability. To solve this problem, Microsoft released the Win32 API. The Win32 API is a set of functions and procedures that abstract many tasks performed daily to interface between user-mode applications and the kernel on the Windows OS.

For example, the Win32API function called WriteProcessMemory writes data into a specific region of the memory’s process. There is mainly two set of functions, user mode functions and kernel functions. The first set has limited acces and sometimes Hooked/monitor by Antivirus or EDR. Below is a visual representation of how a user application can use API calls to modify kernel components.

source : tryhackme (https://tryhackme.com/r/room/windowsapi)

User Mode vs. Kernel Mode

Understanding the difference between user mode and kernel mode is essential when working with the Windows API:

  • User Mode: applications have limited access to system resources and hardware. This mode provides a controlled environment where most applications run, preventing them from performing operations that could harm the system or other applications.
  • Kernel Mode: code has unrestricted access to all system resources, including hardware. This mode is where the core of the operating system runs, along with device drivers and other low-level components. Operations requiring direct interaction with hardware or critical system components are executed in kernel mode.

To resume:

User modeKernel mode
No direct hardware accessDirect hardware access
Access to “owned/virtual” memory locationsAccess to entire physical memory

Development environment

Why C++ & C#?

C++ and C# are powerful languages for system programming and application development.
C++ is widely used for its efficiency and ability to directly manipulate hardware resources, making it an excellent choice for low-level programming and offensive security tasks.
C#, on the other hand, offers a higher level of abstraction and ease of use. C# is a Object Oriented language that is based on the .NET Framework. Understandably, it does not provide the hiding capabilities of C++. But it has other aspects like in memory execution and with the increase in tools that use C# we have also seen some cool tactics that can be utilized to bypass detection and defenses. We will use both languages depending on the example to demonstrate their respective strengths.

Environment

  • Microsoft Visual Studio: A comprehensive development environment for C++ and other languages.
  • Windows 11: The latest version of Windows OS, which includes all necessary tools and updates for modern API development.

Practical Example I: Creating a MessageBox

One of the simplest Windows API functions is MessageBox, which displays a dialog box containing a message. This function is part of the User32 library in the Win32 API.

The Microsoft Docs provide this C++ definition : link: https://learn.microsoft.com/fr-fr/windows/win32/api/winuser/nf-winuser-messageboxa

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

MessageBoxA is the ASCII implementation of the function.

Here’s a basic example of implementation in C++:

#include <windows.h>  

int main() {
	MessageBoxA(NULL, "Hello, Windows API! by R3dLevy", "Hello", MB_OK);
	return 0; 
}

This code will display a message box with the text “Hello, Windows API!” and an “OK” button.

Breaking down the code

  • #include <windows.h>: This includes the Windows API functions.
  • MessageBoxA function parameters:
    • NULL: Handle to the owner window (no owner in this case).
    • "Hello, Windows API! by R3dLevy": The message to display.
    • "Hello": The title of the message box.
    • MB_OK: Indicates that the message box will contain an OK button.

Practical Example II: Process Enumeration

To dive deeper, let’s look at more API calls for process enumeration. This is particularly useful in offensive security for understanding and interacting with processes running on a system. We will use 3 functions for this example :

  • CreateToolhelp32Snapshot : Takes a snapshot of the specified processes, heaps, modules, and threads used by the processes.
HANDLE CreateToolhelp32Snapshot(
  [in] DWORD dwFlags,
  [in] DWORD th32ProcessID
);
  • Module32First: Retrieves information about the first module associated with a process
  • Module32Next: Retrieves information about the next module associated with a process or thread.

Here is a brief overview:

#include <windows.h>
#include <tlhelp32.h>
#include <iostream>

void ListProcesses() {
    HANDLE hProcessSnap;
    PROCESSENTRY32 pe32;
    hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);

    if (hProcessSnap == INVALID_HANDLE_VALUE) {
        std::cerr << "CreateToolhelp32Snapshot failed." << std::endl;
        return;
    }

    pe32.dwSize = sizeof(PROCESSENTRY32);
    if (!Process32First(hProcessSnap, &pe32)) {
        CloseHandle(hProcessSnap);
        std::cerr << "Process32First failed." << std::endl;
        return;
    }

    do {
        std::wcout << L"Process name: " << pe32.szExeFile << L"\nProcess ID: " << pe32.th32ProcessID << std::endl;
    } while (Process32Next(hProcessSnap, &pe32));

    CloseHandle(hProcessSnap);
}

int main() {
    ListProcesses();
    return 0;
}

Listing all process in the debug terminal of visual studio:

Breaking down the code

Conclusion

This post covered the basics of Windows API, including user mode and kernel mode distinctions, and provided examples of using the MessageBox function and enumerating processes with CreateToolhelp32Snapshot.
Future posts will delve deeper into more advanced topics such as memory management and process manipulation. Specifically, the next post will focus on process injection.

All the examples can be found on my github repos : https://github.com/R3dLevy/TheOffensiveDevelopmentProject

References

© 2025 Jude Levy