阶段四:Windows开发
📅 创建日期: 2025-01-XX
⏱️ 预计学时: 8-10 周
🎯 学习目标: 掌握 Win32 API 编程、窗口消息机制、进程线程管理
📋 前置要求: [[阶段三:进阶编程]]
🔗 返回: [[逆向与驱动开发学习路径(详细版)]]
📚 本阶段内容概览
- [[#4.1 Win32 API编程|4.1 Win32 API编程]]
- [[#4.1.1 窗口与消息|窗口与消息]]
- [[#4.1.2 进程与线程|进程与线程]]
- [[#4.1.3 内存管理|内存管理]]
- [[#4.1.4 文件与注册表|文件与注册表]]
- [[#4.1.5 同步机制|同步机制]]
- [[#4.2 MFC基础|4.2 MFC基础]]
- [[#4.3 逆向中的Windows知识|4.3 逆向中的Windows知识]]
4.1 Win32 API编程
4.1.1 窗口与消息
📝 学习笔记
窗口创建流程
#include <Windows.h>
// 窗口过程函数
LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) {
switch (msg) {
case WM_CREATE:
// 窗口创建时
return 0;
case WM_PAINT: {
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hWnd, &ps);
TextOut(hdc, 10, 10, L"Hello Win32!", 12);
EndPaint(hWnd, &ps);
return 0;
}
case WM_DESTROY:
PostQuitMessage(0);
return 0;
}
return DefWindowProc(hWnd, msg, wParam, lParam);
}
int WINAPI WinMain(HINSTANCE hInst, HINSTANCE, LPSTR, int nCmdShow) {
// 1. 注册窗口类
WNDCLASS wc = {};
wc.lpfnWndProc = WndProc;
wc.hInstance = hInst;
wc.lpszClassName = L"MyWindowClass";
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
RegisterClass(&wc);
// 2. 创建窗口
HWND hWnd = CreateWindowEx(
0, L"MyWindowClass", L"Win32 Window",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT, 800, 600,
NULL, NULL, hInst, NULL
);
// 3. 显示窗口
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
// 4. 消息循环
MSG msg;
while (GetMessage(&msg, NULL, 0, 0)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return (int)msg.wParam;
}
常用窗口消息
| 消息 | 值 | 触发时机 |
|---|---|---|
| WM_CREATE | 0x0001 | 窗口创建 |
| WM_DESTROY | 0x0002 | 窗口销毁 |
| WM_PAINT | 0x000F | 需要重绘 |
| WM_COMMAND | 0x0111 | 菜单/按钮点击 |
| WM_KEYDOWN | 0x0100 | 键盘按下 |
| WM_LBUTTONDOWN | 0x0201 | 鼠标左键按下 |
| WM_TIMER | 0x0113 | 定时器触发 |
| WM_CLOSE | 0x0010 | 关闭请求 |
[!tip] 逆向技巧
在逆向 GUI 程序时,搜索窗口过程中的 switch-case 结构,通常处理 WM_COMMAND 消息的分支包含关键业务逻辑。
4.1.2 进程与线程
📝 学习笔记
创建进程
STARTUPINFO si = { sizeof(si) };
PROCESS_INFORMATION pi;
// 创建新进程
BOOL result = CreateProcess(
L"C:\\Windows\\notepad.exe", // 程序路径
NULL, // 命令行参数
NULL, NULL, // 安全属性
FALSE, // 不继承句柄
0, // 创建标志
NULL, // 环境变量
NULL, // 当前目录
&si, &pi
);
if (result) {
printf("PID: %d\n", pi.dwProcessId);
printf("TID: %d\n", pi.dwThreadId);
// 等待进程结束
WaitForSingleObject(pi.hProcess, INFINITE);
// 关闭句柄
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
}
创建线程
// 线程函数
DWORD WINAPI ThreadFunc(LPVOID param) {
int* value = (int*)param;
printf("Thread started with value: %d\n", *value);
return 0;
}
// 创建线程
int param = 42;
HANDLE hThread = CreateThread(
NULL, // 安全属性
0, // 栈大小(0=默认)
ThreadFunc, // 线程函数
¶m, // 参数
0, // 创建标志
NULL // 线程ID输出
);
// 等待线程结束
WaitForSingleObject(hThread, INFINITE);
CloseHandle(hThread);
进程 / 线程常用 API
| API | 功能 |
|---|---|
| OpenProcess | 打开已有进程 |
| TerminateProcess | 终止进程 |
| GetCurrentProcess | 获取当前进程伪句柄 |
| GetCurrentProcessId | 获取当前进程ID |
| CreateRemoteThread | 在其他进程创建线程 |
| SuspendThread/ResumeThread | 挂起/恢复线程 |
| GetThreadContext/SetThreadContext | 获取/设置线程上下文 |
4.1.3 内存管理
📝 学习笔记
虚拟内存 API
// 在当前进程分配内存
LPVOID addr = VirtualAlloc(
NULL, // 让系统选择地址
4096, // 大小
MEM_COMMIT | MEM_RESERVE,// 分配类型
PAGE_READWRITE // 保护属性
);
// 修改内存保护属性
DWORD oldProtect;
VirtualProtect(addr, 4096, PAGE_EXECUTE_READ, &oldProtect);
// 释放内存
VirtualFree(addr, 0, MEM_RELEASE);
跨进程内存操作
// 打开目标进程
HANDLE hProcess = OpenProcess(
PROCESS_VM_READ | PROCESS_VM_WRITE | PROCESS_VM_OPERATION,
FALSE,
targetPid
);
// 在目标进程分配内存
LPVOID remoteAddr = VirtualAllocEx(
hProcess,
NULL,
4096,
MEM_COMMIT | MEM_RESERVE,
PAGE_EXECUTE_READWRITE
);
// 写入内存
SIZE_T written;
WriteProcessMemory(hProcess, remoteAddr, localData, dataSize, &written);
// 读取内存
SIZE_T read;
ReadProcessMemory(hProcess, remoteAddr, localBuffer, bufferSize, &read);
// 释放
VirtualFreeEx(hProcess, remoteAddr, 0, MEM_RELEASE);
CloseHandle(hProcess);
内存保护属性
| 属性 | 值 | 说明 |
|---|---|---|
| PAGE_NOACCESS | 0x01 | 禁止访问 |
| PAGE_READONLY | 0x02 | 只读 |
| PAGE_READWRITE | 0x04 | 读写 |
| PAGE_EXECUTE | 0x10 | 可执行 |
| PAGE_EXECUTE_READ | 0x20 | 可执行+可读 |
| PAGE_EXECUTE_READWRITE | 0x40 | 可执行+读写 |
| PAGE_GUARD | 0x100 | 保护页(访问触发异常) |
[!warning] 安全提示
修改其他进程的内存需要相应权限,且可能被安全软件拦截。在逆向分析时,这些 API 是常见的代码注入技术基础。
4.1.4 文件与注册表
📝 学习笔记
文件操作
// 创建/打开文件
HANDLE hFile = CreateFile(
L"test.txt",
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ,
NULL,
CREATE_ALWAYS, // 创建新文件,覆盖已有
FILE_ATTRIBUTE_NORMAL,
NULL
);
// 写入文件
const char* data = "Hello World";
DWORD written;
WriteFile(hFile, data, strlen(data), &written, NULL);
// 设置文件指针
SetFilePointer(hFile, 0, NULL, FILE_BEGIN);
// 读取文件
char buffer[256];
DWORD read;
ReadFile(hFile, buffer, sizeof(buffer), &read, NULL);
// 关闭
CloseHandle(hFile);
内存映射文件
// 创建文件映射
HANDLE hFile = CreateFile(L"large.dat", GENERIC_READ, FILE_SHARE_READ,
NULL, OPEN_EXISTING, 0, NULL);
HANDLE hMapping = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, NULL);
// 映射到内存
LPVOID data = MapViewOfFile(hMapping, FILE_MAP_READ, 0, 0, 0);
// 使用数据...
BYTE* bytes = (BYTE*)data;
// 解除映射
UnmapViewOfFile(data);
CloseHandle(hMapping);
CloseHandle(hFile);
注册表操作
HKEY hKey;
// 创建/打开键
RegCreateKeyEx(
HKEY_CURRENT_USER,
L"Software\\MyApp",
0, NULL,
REG_OPTION_NON_VOLATILE,
KEY_ALL_ACCESS,
NULL,
&hKey,
NULL
);
// 写入值
DWORD value = 42;
RegSetValueEx(hKey, L"Setting", 0, REG_DWORD, (BYTE*)&value, sizeof(value));
// 读取值
DWORD data, size = sizeof(data);
RegQueryValueEx(hKey, L"Setting", NULL, NULL, (BYTE*)&data, &size);
// 关闭
RegCloseKey(hKey);
4.1.5 同步机制
📝 学习笔记
临界区 (Critical Section)
CRITICAL_SECTION cs;
// 初始化
InitializeCriticalSection(&cs);
// 进入临界区
EnterCriticalSection(&cs);
// 临界区代码...
LeaveCriticalSection(&cs);
// 尝试进入(非阻塞)
if (TryEnterCriticalSection(&cs)) {
// 获得锁
LeaveCriticalSection(&cs);
}
// 删除
DeleteCriticalSection(&cs);
互斥量 (Mutex)
// 创建互斥量
HANDLE hMutex = CreateMutex(NULL, FALSE, L"Global\\MyMutex");
// 等待获取
WaitForSingleObject(hMutex, INFINITE);
// 释放
ReleaseMutex(hMutex);
// 关闭
CloseHandle(hMutex);
事件 (Event)
// 创建事件
HANDLE hEvent = CreateEvent(
NULL, // 安全属性
TRUE, // 手动重置
FALSE, // 初始无信号
NULL // 名称
);
// 线程A: 等待事件
WaitForSingleObject(hEvent, INFINITE);
// 线程B: 触发事件
SetEvent(hEvent);
// 重置事件(手动重置时需要)
ResetEvent(hEvent);
同步对象对比
| 对象 | 跨进程 | 特点 |
|---|---|---|
| CriticalSection | ❌ | 最快,仅进程内 |
| Mutex | ✅ | 可跨进程,支持超时 |
| Event | ✅ | 信号通知机制 |
| Semaphore | ✅ | 计数器,控制并发数 |
4.2 MFC基础
📝 学习笔记
MFC 程序结构
// 应用程序类
class CMyApp : public CWinApp {
public:
virtual BOOL InitInstance() {
CMyFrame* pFrame = new CMyFrame();
pFrame->Create(NULL, _T("MFC Window"));
pFrame->ShowWindow(SW_SHOW);
m_pMainWnd = pFrame;
return TRUE;
}
};
// 框架窗口类
class CMyFrame : public CFrameWnd {
DECLARE_MESSAGE_MAP()
public:
afx_msg void OnPaint();
afx_msg void OnLButtonDown(UINT nFlags, CPoint point);
};
// 消息映射
BEGIN_MESSAGE_MAP(CMyFrame, CFrameWnd)
ON_WM_PAINT()
ON_WM_LBUTTONDOWN()
END_MESSAGE_MAP()
// 全局应用对象
CMyApp theApp;
MFC 消息映射宏
| 宏 | 用途 |
|---|---|
| ON_WM_* | 标准Windows消息 |
| ON_COMMAND | 菜单/按钮命令 |
| ON_BN_CLICKED | 按钮点击 |
| ON_EN_CHANGE | 编辑框内容改变 |
| ON_NOTIFY | 通用通知消息 |
[!important] 逆向 MFC 程序
MFC 程序的消息映射表在二进制中有特定结构,可通过分析AFX_MSGMAP结构定位消息处理函数。
4.3 逆向中的Windows知识
📝 学习笔记
PEB/TEB 结构
// TEB (Thread Environment Block) 关键字段
struct TEB {
NT_TIB NtTib; // +0x000
PVOID EnvironmentPointer; // +0x038
CLIENT_ID ClientId; // +0x040 (进程ID, 线程ID)
// ...
PPEB ProcessEnvironmentBlock; // +0x060
// ...
};
// PEB (Process Environment Block) 关键字段
struct PEB {
BOOLEAN InheritedAddressSpace; // +0x000
BOOLEAN ReadImageFileExecOptions;// +0x001
BOOLEAN BeingDebugged; // +0x002 <-- 反调试检测
// ...
PPEB_LDR_DATA Ldr; // +0x018 <-- 模块列表
PRTL_USER_PROCESS_PARAMETERS ProcessParameters; // +0x020
// ...
DWORD NtGlobalFlag; // +0x0BC <-- 调试标志
};
获取模块列表
// 通过PEB遍历加载的模块
void EnumModules() {
PPEB peb = (PPEB)__readgsqword(0x60);
PPEB_LDR_DATA ldr = peb->Ldr;
PLIST_ENTRY head = &ldr->InLoadOrderModuleList;
PLIST_ENTRY curr = head->Flink;
while (curr != head) {
PLDR_DATA_TABLE_ENTRY entry =
CONTAINING_RECORD(curr, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks);
wprintf(L"Base: %p, Name: %s\n",
entry->DllBase,
entry->BaseDllName.Buffer);
curr = curr->Flink;
}
}
PE 文件解析要点
// 获取DOS头
PIMAGE_DOS_HEADER dosHeader = (PIMAGE_DOS_HEADER)moduleBase;
// 获取NT头
PIMAGE_NT_HEADERS ntHeaders = (PIMAGE_NT_HEADERS)
((BYTE*)moduleBase + dosHeader->e_lfanew);
// 获取导出表
DWORD exportRVA = ntHeaders->OptionalHeader.DataDirectory
[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;
PIMAGE_EXPORT_DIRECTORY exportDir = (PIMAGE_EXPORT_DIRECTORY)
((BYTE*)moduleBase + exportRVA);
// 遍历导出函数
DWORD* names = (DWORD*)((BYTE*)moduleBase + exportDir->AddressOfNames);
for (DWORD i = 0; i < exportDir->NumberOfNames; i++) {
char* name = (char*)((BYTE*)moduleBase + names[i]);
printf("Export: %s\n", name);
}
✅ 阶段检查点
Win32 API检查
- [ ] 能独立创建Windows窗口程序
- [ ] 理解消息循环和窗口过程
- [ ] 掌握进程创建和线程创建
- [ ] 熟悉VirtualAlloc/VirtualProtect等内存API
- [ ] 能进行跨进程内存读写
- [ ] 了解各种同步对象的使用场景
Windows内部结构检查
- [ ] 理解PEB/TEB结构
- [ ] 能通过PEB遍历模块列表
- [ ] 了解PE文件结构基础
- [ ] 能解析导入表/导出表
MFC基础检查
- [ ] 理解MFC程序结构
- [ ] 了解消息映射机制
- [ ] 能识别MFC程序的特征
📖 学习资料
| 资源类型 | 名称 | 说明 |
|---|---|---|
| 📕 书籍 | Windows核心编程 (第5版) | Windows开发圣经 |
| 📕 书籍 | Windows via C/C++ | 深入Windows编程 |
| 📕 书籍 | Programming Windows (Petzold) | 经典Win32教程 |
| 🌐 网站 | MSDN文档 | 官方API参考 |
| 🌐 网站 | ReactOS源码 | Windows开源实现参考 |
🔗 导航
← [[阶段三:进阶编程]] | [[逆向与驱动开发学习路径(详细版)| 返回主目录]] | [[阶段五:核心逆向技术]] →