好友
阅读权限20
听众
最后登录1970-1-1
|
低调的菜鸡
发表于 2019-12-3 15:52
本帖最后由 低调的菜鸡 于 2019-12-3 16:12 编辑
上次发了一个坦克大战,感谢版主和小伙伴们的支持,确实让人太感动了,这次就跟各位小伙伴们分享一下子Windows程序的简单架构,希望大家在此基础上共同学习,共同进步,话不多说,让我们进入今天的代码分享
引言
- 众所周知,我们只要使用Windows的操作系统,必然离不开Windows的界面程序,无论是用什么语言(c 、c++、汇编、或是易语言),什么编译器,只要是带图形界面的PE文件,运行时必然带有Windows子系统,也就是说,遵循Windows界面程序的结构。
- 那么,我们如果掌握了这个结构,无论是逆向还是开发,都会显得更加游刃有余。这也是我跟大家分享这个结构的原因,当然,如有任何错误,欢迎指正。
一、一些基础知识的介绍
-
什么是Windows SDK?
- 微软推出的包含了开发该windows版本所需的windows函数和常数定义、API函数说明文档、相关工具和示例。
- 总结起来,我们如果要在Windows上编程,离不开这玩意儿。
-
什么是句柄?
- 句柄是WONDOWS用来标识被应用程序所建立或使用的对象的唯一整数,WINDOWS使用各种各样的句柄标识诸如应用程序实例,窗口,控制,位图,GDI对象等等。
-
什么是消息?
- 在Windows中发生的一切都可以用消息来表示,消息用于告诉操作系统发生了什么,所有的Windows应用程序都是消息驱动的。
- 换而言之,消息就是Windows程序运行的核心,我们对窗口的所有操作,包括点击,输入,都是会产生一个消息的,而程序就是不断处理我们产生的消息,从而实现不同的操作。
- 有些大佬调试时候喜欢直接断消息,其实也就是用的这个原理
-
如何使用和查看Windows API?
- Windows API是微软提供给我们在Windows下编程的接口,API丰富多彩,能做到的事情也很丰富。当然,如果熟悉了常见API函数的结构,对后期的逆向分析,代码注入或者HOOK也有很大的帮助。
- 查看:百度-》API函数名-》MSDN-》翻译
- 使用:程序中包含"Windows.h",直接调用即可。
二、Windows程序的结构
-
窗口对象
-
用于在系统中标识该窗口,窗口的信息全部存放于其中,需要在系统中注册(使用RegisterClass函数)
-
结构:
typedef struct tagWNDCLASSA {
UINT style; //窗口类的风格
WNDPROC lpfnWndProc; //指向窗口过程的指针(重要)
int cbClsExtra; //分派给窗口类的拓展的字节数
int cbWndExtra; //分派给窗口实例的扩展的字节数
HINSTANCE hInstance; //实例句柄
HICON hIcon; //类图标的句柄
HCURSOR hCursor; //类鼠标指针的句柄
HBRUSH hbrBackground; //刷新背景所用画刷的句柄
LPCSTR lpszMenuName; //窗口类包含的菜单的资源
LPCSTR lpszClassName; //窗口类名(重要)
} WNDCLASSA, *PWNDCLASSA, *NPWNDCLASSA, *LPWNDCLASSA;
-
窗口
- 根据窗口对象实际显示出来的窗口,需要根据窗口对象创建,创建成功后,返回一个句柄,也是该窗口的标识
- 使用CreateWindow函数创建
-
消息泵
-
对窗口获取到的各种消息进行处理
-
常见结构
MSG msg = { 0 };
while (GetMessage(&msg, NULL, 0, 0))
{
//翻译消息
TranslateMessage(&msg);
//分发消息
DispatchMessage(&msg);
}
-
消息处理函数(窗口回调函数)
-
消息泵将消息发送之后,消息处理函数开始执行,可以根据相应的消息进行处理。
-
常见结构
//窗口回调函数
LRESULT CALLBACK WndProc(
HWND hWnd, /*实例句柄*/
UINT nMsgCode, /*消息类型*/
WPARAM wParam, /*附加参数1*/
LPARAM lParam /*附加参数2*/
)
{
switch (nMsgCode)
{
case WM_CLOSE:
PostQuitMessage(0);
break;
default:
//Windows默认的消息处理
return DefWindowProc(hWnd, nMsgCode, wParam, lParam);
}
return 0;
};
三、第一个窗口程序的流程
- 在系统中注册窗口类
- 编写窗口回调函数
- 创建窗口
- 显示刷新窗口
- 建立消息循环
四、代码实现
-
说了这么多,直接看代码吧,注释很详细,大家慢慢看
#include <stdio.h>
#include <stdlib.h>
#include <Windows.h>
#include <tchar.h>
//全局的一个实例句柄,标识最初的父窗口
HWND g_hWnd = NULL;
//窗口回调函数
LRESULT CALLBACK WndProc(
HWND hWnd, /*实例句柄*/
UINT nMsgCode, /*消息类型*/
WPARAM wParam, /*附加参数1*/
LPARAM lParam /*附加参数2*/
)
{
switch (nMsgCode)
{
case WM_CLOSE:
PostQuitMessage(0);
break;
default:
//Windows默认的消息处理
return DefWindowProc(hWnd, nMsgCode, wParam, lParam);
}
return 0;
};
int WINAPI WinMain(
_In_ HINSTANCE hInstance,/*程序的实例句柄,保存的程序的加载地址*/
_In_opt_ HINSTANCE hPrevInstance,/*已被废弃,不管*/
_In_ LPSTR lpCmdLine,/*命令行参数*/
_In_ int nShowCmd/*窗口的显示标志*/
)
{
//1.在系统中注册窗口类
//1.1 新建窗口类
WNDCLASS wc = { 0 };
//窗口类类名字段赋值
wc.lpszClassName = _T("MyClass");
//窗口类回调函数字段赋值
wc.lpfnWndProc = WndProc;
//1.2 注册窗口类
RegisterClass(&wc);
//2.创建窗口
g_hWnd = CreateWindow(
wc.lpszClassName, //窗口类的类名
_T("第一个窗口程序"), //窗口名
WS_OVERLAPPEDWINDOW, //窗口类型
100, 100, //窗口在屏幕上的位置x,y
640, 480, //窗口的宽和高
NULL, //父窗口句柄
NULL, //菜单的句柄
hInstance, //实例句柄
NULL //附加参数
);
if (g_hWnd == NULL)
{
MessageBox(NULL, _T("创建窗口失败!"), _T("ERROR"), MB_OK);
exit(0);
}
//3.显示刷新窗口
ShowWindow(g_hWnd, SW_SHOW);
UpdateWindow(g_hWnd);
//4.建立消息循环
MSG msg = { 0 };
while (GetMessage(&msg, NULL, 0, 0))
{
//翻译消息
TranslateMessage(&msg);
//发送消息
DispatchMessage(&msg);
}
//5.退出
return (int)msg.wParam;
}
五、运行平台
- vs ,vc各个版本都行,复制粘贴即可运行,记得将项目属性中的链接属性,子系统改为windows子系统。
|
免费评分
-
查看全部评分
本帖被以下淘专辑推荐:
- · 学习及教程|主题: 1127, 订阅: 1119
|
发帖前要善用【论坛搜索】功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。 |
|
|
|
|