This section shows code snippets that use the Windows API to do the following:
VirtualAlloc, VirtualFree, and related callsCreateProcess, TerminateProcess, etc.CreateFile, ReadFile, and WriteFileHANDLE, DWORD, LPVOID, LPCSTR, and moreMessageBox using User32.dllGetLastErrorBy learning to use the API directly, you’ll gain low-level control and unlock capabilities that are simply not possible with higher-level abstractions.
MessageBoxA#include <windows.h> // Required for all WinAPI calls
int main() {
// Display a simple message box with a message, title, and OK button
MessageBoxA(
NULL, // No parent window
"Hello from WinAPI!", // Message text
"MessageBox Example", // Window title
MB_OK | MB_ICONINFORMATION // Button and icon type
);
return 0;
}
Concepts:
User32.dll via MessageBoxA#include <windows.h>
#include <iostream>
int main() {
// Create or open a file for writing
HANDLE hFile = CreateFileA(
"example.txt", // File name
GENERIC_WRITE, // Desired access
0, // Share mode
NULL, // Security attributes
CREATE_ALWAYS, // Creation disposition
FILE_ATTRIBUTE_NORMAL, // Flags and attributes
NULL // Template file
);
if (hFile == INVALID_HANDLE_VALUE) {
std::cerr << "Failed to create file. Error: " << GetLastError() << std::endl;
return 1;
}
const char* data = "Hello, WinAPI file I/O!";
DWORD bytesWritten;
// Write data to the file
BOOL success = WriteFile(
hFile,
data,
strlen(data),
&bytesWritten,
NULL
);
if (!success) {
std::cerr << "Write failed. Error: " << GetLastError() << std::endl;
} else {
std::cout << "Successfully wrote " << bytesWritten << " bytes." << std::endl;
}
CloseHandle(hFile); // Always close handles
return 0;
}
Concepts:
HANDLE, DWORD, and WinAPI error handlingVirtualAlloc#include <windows.h>
#include <iostream>
int main() {
// Allocate 1 KB of memory with read/write permissions
LPVOID mem = VirtualAlloc(
NULL, // Let the OS choose the address
1024, // Size in bytes
MEM_COMMIT | MEM_RESERVE, // Allocation type
PAGE_READWRITE // Protection
);
if (mem == NULL) {
std::cerr << "Memory allocation failed. Error: " << GetLastError() << std::endl;
return 1;
}
// Write data into the allocated memory
strcpy_s((char*)mem, 1024, "This is dynamic memory via WinAPI.");
// Output the content
std::cout << "Memory content: " << (char*)mem << std::endl;
// Free the memory
VirtualFree(mem, 0, MEM_RELEASE);
return 0;
}
Concepts:
MEM_COMMIT, MEM_RESERVE, and PAGE_READWRITEGetSystemInfo#include <windows.h>
#include <iostream>
int main() {
SYSTEM_INFO sysInfo;
// Populate the SYSTEM_INFO structure
GetSystemInfo(&sysInfo);
std::cout << "Processor Architecture: " << sysInfo.wProcessorArchitecture << std::endl;
std::cout << "Page Size: " << sysInfo.dwPageSize << " bytes" << std::endl;
std::cout << "Number of Processors: " << sysInfo.dwNumberOfProcessors << std::endl;
return 0;
}
Concepts:
SYSTEM_INFO structure#include <windows.h>
int main() {
// Pause execution for 2 seconds
Sleep(2000); // Milliseconds
// Play a beep sound (frequency 750 Hz, duration 300 ms)
Beep(750, 300);
return 0;
}
Concepts:
SleepBeepCreateProcessA#include <windows.h>
#include <iostream>
int main() {
STARTUPINFOA si = { sizeof(si) }; // Initialize STARTUPINFO
PROCESS_INFORMATION pi; // Will receive process info
// Path to executable (must exist)
LPCSTR appName = "C:\\Windows\\System32\\notepad.exe";
// Create a new process (Notepad in this case)
BOOL success = CreateProcessA(
appName, // Application name
NULL, // Command line
NULL, // Process security attributes
NULL, // Thread security attributes
FALSE, // Inherit handles
0, // Creation flags
NULL, // Environment
NULL, // Current directory
&si, // Startup info
&pi // Process info (out)
);
if (!success) {
std::cerr << "CreateProcess failed. Error: " << GetLastError() << std::endl;
return 1;
}
std::cout << "Process created! PID: " << pi.dwProcessId << std::endl;
// Wait until the process exits
WaitForSingleObject(pi.hProcess, INFINITE);
// Close handles
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
return 0;
}
Concepts:
STARTUPINFO and PROCESS_INFORMATION#include <windows.h>
#include <iostream>
int main() {
DWORD pid = GetCurrentProcessId();
DWORD tid = GetCurrentThreadId();
std::cout << "Current Process ID: " << pid << std::endl;
std::cout << "Current Thread ID: " << tid << std::endl;
return 0;
}
Concepts:
#include <windows.h>
#include <iostream>
int main() {
HANDLE hFile = CreateFileA(
"example.txt", // File to open
GENERIC_READ, // Desired access
FILE_SHARE_READ, // Share mode
NULL, // Security attributes
OPEN_EXISTING, // Open only if exists
FILE_ATTRIBUTE_NORMAL, // Attributes
NULL // Template
);
if (hFile == INVALID_HANDLE_VALUE) {
std::cerr << "Could not open file. Error: " << GetLastError() << std::endl;
return 1;
}
char buffer[128] = {0};
DWORD bytesRead;
BOOL success = ReadFile(
hFile,
buffer,
sizeof(buffer) - 1,
&bytesRead,
NULL
);
if (!success) {
std::cerr << "Read failed. Error: " << GetLastError() << std::endl;
} else {
std::cout << "Read " << bytesRead << " bytes: " << buffer << std::endl;
}
CloseHandle(hFile);
return 0;
}
Concepts:
OpenProcess to Access Another Process#include <windows.h>
#include <iostream>
int main() {
DWORD pid;
std::cout << "Enter the PID of the process to open: ";
std::cin >> pid;
// Open another process with read-only permissions
HANDLE hProcess = OpenProcess(
PROCESS_QUERY_INFORMATION | PROCESS_VM_READ,
FALSE,
pid
);
if (hProcess == NULL) {
std::cerr << "Failed to open process. Error: " << GetLastError() << std::endl;
return 1;
}
std::cout << "Process opened successfully (handle: " << hProcess << ")." << std::endl;
CloseHandle(hProcess);
return 0;
}
Concepts:
CreateThread#include <windows.h>
#include <iostream>
// Thread function must match signature
DWORD WINAPI MyThreadFunction(LPVOID lpParam) {
std::cout << "Thread running... ID: " << GetCurrentThreadId() << std::endl;
Sleep(1000);
return 0;
}
int main() {
HANDLE hThread;
DWORD threadId;
// Create a new thread
hThread = CreateThread(
NULL, // Default security
0, // Default stack size
MyThreadFunction, // Thread function
NULL, // Parameter to thread
0, // Default creation flags
&threadId // Receives thread identifier
);
if (hThread == NULL) {
std::cerr << "Thread creation failed. Error: " << GetLastError() << std::endl;
return 1;
}
std::cout << "Thread created. ID: " << threadId << std::endl;
// Wait for thread to finish
WaitForSingleObject(hThread, INFINITE);
CloseHandle(hThread);
return 0;
}
Concepts:
CreateThread and synchronization via WaitForSingleObject#include <windows.h>
#include <iostream>
int main() {
DWORD pid;
std::cout << "Enter target PID: ";
std::cin >> pid;
HANDLE hProcess = OpenProcess(
PROCESS_VM_READ | PROCESS_QUERY_INFORMATION,
FALSE,
pid
);
if (!hProcess) {
std::cerr << "Failed to open process. Error: " << GetLastError() << std::endl;
return 1;
}
// Example address (needs to be valid in target process)
LPCVOID address = (LPCVOID)0x7FFDF000;
char buffer[32] = { 0 };
SIZE_T bytesRead;
if (ReadProcessMemory(hProcess, address, buffer, sizeof(buffer), &bytesRead)) {
std::cout << "Data read (" << bytesRead << " bytes): " << buffer << std::endl;
} else {
std::cerr << "ReadProcessMemory failed. Error: " << GetLastError() << std::endl;
}
CloseHandle(hProcess);
return 0;
}
Concepts:
ReadProcessMemory and pointer management#include <windows.h>
#include <iostream>
int main() {
DWORD pid;
std::cout << "Enter PID of target process: ";
std::cin >> pid;
HANDLE hProcess = OpenProcess(
PROCESS_VM_OPERATION | PROCESS_VM_WRITE,
FALSE,
pid
);
if (!hProcess) {
std::cerr << "OpenProcess failed. Error: " << GetLastError() << std::endl;
return 1;
}
// Allocate memory in remote process
LPVOID remoteMemory = VirtualAllocEx(
hProcess,
NULL,
1024,
MEM_COMMIT | MEM_RESERVE,
PAGE_READWRITE
);
if (!remoteMemory) {
std::cerr << "VirtualAllocEx failed. Error: " << GetLastError() << std::endl;
CloseHandle(hProcess);
return 1;
}
std::cout << "Memory allocated at remote address: " << remoteMemory << std::endl;
CloseHandle(hProcess);
return 0;
}
Concepts:
VirtualAllocEx)#include <windows.h>
#include <iostream>
int main() {
DWORD pid;
std::cout << "Enter target PID: ";
std::cin >> pid;
HANDLE hProcess = OpenProcess(
PROCESS_VM_OPERATION | PROCESS_VM_WRITE | PROCESS_VM_READ,
FALSE,
pid
);
if (!hProcess) {
std::cerr << "OpenProcess failed. Error: " << GetLastError() << std::endl;
return 1;
}
// Allocate memory
LPVOID remoteAddr = VirtualAllocEx(hProcess, NULL, 256, MEM_COMMIT, PAGE_READWRITE);
const char* message = "Hello from C++ to your memory!";
SIZE_T bytesWritten;
if (WriteProcessMemory(hProcess, remoteAddr, message, strlen(message) + 1, &bytesWritten)) {
std::cout << "Successfully wrote " << bytesWritten << " bytes to remote process." << std::endl;
} else {
std::cerr << "WriteProcessMemory failed. Error: " << GetLastError() << std::endl;
}
CloseHandle(hProcess);
return 0;
}
Concepts:
WriteProcessMemoryVirtualProtect#include <windows.h>
#include <iostream>
int main() {
// Allocate memory
LPVOID mem = VirtualAlloc(NULL, 1024, MEM_COMMIT, PAGE_READWRITE);
if (!mem) {
std::cerr << "VirtualAlloc failed. Error: " << GetLastError() << std::endl;
return 1;
}
// Write something
strcpy_s((char*)mem, 1024, "Testing memory protection.");
// Change to read-only
DWORD oldProtect;
if (VirtualProtect(mem, 1024, PAGE_READONLY, &oldProtect)) {
std::cout << "Memory protection changed to read-only." << std::endl;
} else {
std::cerr << "VirtualProtect failed. Error: " << GetLastError() << std::endl;
}
// Free memory
VirtualFree(mem, 0, MEM_RELEASE);
return 0;
}
Concepts:
PAGE_READWRITE to PAGE_READONLY#include <windows.h>
#include <iostream>
int main() {
HMODULE hKernel32 = LoadLibraryA("kernel32.dll");
if (!hKernel32) {
std::cerr << "Failed to load kernel32.dll" << std::endl;
return 1;
}
// Get address of 'Beep' function from kernel32.dll
FARPROC funcAddr = GetProcAddress(hKernel32, "Beep");
if (funcAddr) {
std::cout << "'Beep' function address: " << funcAddr << std::endl;
} else {
std::cerr << "GetProcAddress failed. Error: " << GetLastError() << std::endl;
}
// Always free loaded libraries (if dynamically loaded)
FreeLibrary(hKernel32);
return 0;
}
Concepts:
LoadLibrary and GetProcAddress