软件逆向工程——Windows系统编程实验上机报告
实验要求
使用Windows核心API实现以下程序
程序1:该程序能够创建一个本机的notepad进程(使用CreateProcess,显式指定notepad可执行文件的路径)
程序2:
a. 该程序能够创建一个线程,显示MessageBox
b. 在以上子线程中,编程获得kernel32.dll在当前系统中的路径信息,作为内容显示在以上的MessageBox中
c. 在以上子线程中,编程获得子线程所加载kernel32.dll中的GetCurrentThreadId(. 函数的地址,调用该函数,获得子线程的线程编号,将线程编号连接到上一问的kernel32.dll路径后面,再将连接结果字符串显示在MessageBox中
d. 最终显示结果如下图所示:

程序1设计与实现:创建Notepad进程
设计思路
通过Windows API CreateProcess创建记事本进程,需显式指定notepad.exe的完整路径(C:\\Windows\\notepad.exe),并配置进程启动参数(窗口显示)。
核心代码(Program1.cpp)
1 |
|
关键语句说明
CreateProcess:Windows创建进程的核心API。第一个参数appPath显式指定notepad.exe路径,确保系统准确定位可执行文件。STARTUPINFO:用于配置进程启动时的窗口状态,wShowWindow = SW_SHOW确保记事本窗口可见,cb成员必须设置为结构体大小,否则API调用失败。PROCESS_INFORMATION:接收创建的进程和主线程的句柄及ID,使用后需通过CloseHandle释放句柄,避免系统资源泄漏。
程序2设计与实现:线程创建与信息显示
设计思路
- 子线程创建:通过
CreateThread创建子线程,线程函数负责执行信息获取与显示逻辑。 - 获取
kernel32.dll路径:利用GetModuleHandle获取kernel32.dll的模块句柄(该DLL默认加载到所有进程),再通过GetModuleFileName获取其完整路径。 - 获取线程ID:通过
GetProcAddress获取kernel32.dll中GetCurrentThreadId函数的地址,调用该函数获取当前线程ID,拼接路径后通过MessageBox显示。
核心代码(Program2.cpp)
1 |
|
关键语句说明
- 线程创建:
CreateThread的第三个参数ThreadFunc为线程入口函数,主线程通过WaitForSingleObject等待子线程完成,避免主线程提前退出导致子线程被终止。 - 获取
kernel32.dll路径:GetModuleHandle(L"kernel32.dll"):获取kernel32.dll的模块句柄(因kernel32.dll是系统核心DLL,所有进程都会加载,故无需显式加载即可获取)。GetModuleFileName(hKernel32, dllPath, MAX_PATH):通过模块句柄获取DLL在系统中的完整路径,存储于dllPath缓冲区。
- 获取函数地址与调用:
GetProcAddress(hKernel32, "GetCurrentThreadId"):根据函数名从kernel32.dll中获取GetCurrentThreadId的地址(该函数用于返回当前线程ID)。- 函数指针转换:通过
typedef定义函数指针类型GetCurrentThreadIdFunc,将FARPROC类型转换为具体函数指针,确保调用时参数和返回值匹配。
- 信息显示:拼接
kernel32.dll路径和线程ID为宽字符串,通过MessageBox显示,标题为"Win.prog",按钮为“确定”,与题目要求的效果图一致。
运行结果
- 程序1:成功启动记事本进程,窗口正常显示。
程序2:弹出
MessageBox,如图所示:
总结
CreateProcess需正确配置可执行文件路径和启动信息,句柄使用后需及时释放。- 线程创建需注意同步(如
WaitForSingleObject),避免主线程提前退出。 GetModuleHandle、GetModuleFileName和GetProcAddress是操作DLL的核心API,可灵活获取模块路径和函数地址,实现动态调用。
通过本实验,深入理解了Windows进程/线程管理及DLL动态链接机制,掌握了核心API的使用方法。
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 just.ok的个人博客!





