首页 > 其他分享 >滴水逆向笔记系列-win32总结1-43.宽字节-44.事件_消息_消息处理函数

滴水逆向笔记系列-win32总结1-43.宽字节-44.事件_消息_消息处理函数

时间:2024-03-16 23:23:58浏览次数:21  
标签:wParam lParam 窗口 WM 43 win32 DbgPrintf 消息 处理函数

第四十三课 win32 宽字节

1.编码

0x00.ASCII码

1、ASCII 码使用指定的 7 位或 8 位二进制数组合来表示 128 或 256 种可能的字符
2、标准 ASCII 码使用 7 位二进制数来表示所有的大写和小写字母,数字 0 到 9、标点符号,以及在美式英语中使用的特殊控制字符。
3、扩展 ASCII 码允许将每个字符的第 8 位用于确定附加的 128 个特殊符号字符、外来语字母和图形符号。

0x01.GB2312编码

计算机发明之处及后面很长一段时间,只用应用于美国及西方一些发达国家,ASCII能够很好满足用户的需求。但是当天朝也有了计算机之后,为了显示中文,必须设计一套编码规则用于将汉字转换为计算机可以接受的数字系统的数。<br />    天朝专家把那些127号之后的奇异符号们(即EASCII)取消掉,规定:一个小于127的字符的意义与原来相同,但两个大于127的字符连在一起时,就表示一个汉字,前面的一个字节(他称之为高字节)从0xA1用到 0xF7,后面一个字节(低字节)从0xA1到0xFE,这样我们就可以组合出大约7000多个简体汉字了。<br />    在这些编码里,还把数学符号、罗马希腊的 字母、日文的假名们都编进去了,连在ASCII里本来就有的数字、标点、字母都统统重新编了两个字节长的编码,这就是常说的"全角"字符,而原来在127号以下的那些就叫"半角"字符了。<br />**上述编码规则就是GB2312或GB2312-80**<br />![image.png](https://cdn.nlark.com/yuque/0/2024/png/28321768/1705910665362-9884b637-4fcc-4a2b-b348-eec9b83b37b6.png#averageHue=%23e5e5e5&clientId=u484cabe6-6caf-4&from=paste&height=353&id=u730dcfee&originHeight=618&originWidth=763&originalType=binary&ratio=1.75&rotation=0&showTitle=false&size=173761&status=done&style=none&taskId=u39f327ee-644d-4daa-af49-60cdd9a9202&title=&width=436)

容易出现的问题:

1、容易和其他国家的符号冲突,变成乱码
2、在计算符号数时,经常会把一个中文当成两个符号,增加计算难度

0x02.Unicode

  • 国际统一只有一张表,不像gbk被很多国家分版本使用,不容易出现乱码
  • 比如1000-10000中国使用,20000-30000美国使用

2.宽字节

0x00 宽字符

image.png
很明显,使用char时中字被截断了。
image.png
使用wchar_t在内存中则写入两个字节,但是他仍然按ASCII表存入
image.png
在值前面加L,表示使用UNICODE编码
image.png

0x01 宽字符串

image.png

0x02 控制台打印

image.png

0x03 字符串长度

image.png

3. Win32 API中的宽字符和多字节字符

0x00 宽字符和多字节字符

image.png
TCHAR类型就是放到ascii环境就是ascii,放到unicode环境就是unicode
那些messageboxA和messageboxW函数,到了底层系统还是会统一转成W处理

0x01 字符数组赋值

image.png

0x02 字符串指针赋值

image.png

0x03 各种版本的MessageBox

image.png

4.win32入口程序

int CALLBACK WinMain(  				
	_In_  HINSTANCE hInstance,  			
	_In_  HINSTANCE hPrevInstance,  			
	_In_  LPSTR lpCmdLine,  			
	_In_  int nCmdShow  			
	)  			
{  				
				
	return 0;  			
}  				

:::info
hInstance参数:pe的base基址

lpCmdLine参数:命令行启动程序时后面跟的参数

:::

5.在Win32程序中打印信息

win32项目没有控制台了,没办法用printf()函数,我们用另外的OutputDebugStringA()函数来打印调试
问题:
但是没办法打印变量,比如OutputDebugStringA("我是%s",x);
image.png
解决办法:
创建一个tool的类,把头文件和cpp文件都放上去
image.png
判断是否debug版,release版则会无输出
tools.h

void  OutPutDebugStringF(const char * format, ...);
//判断是否debug版,release版则会无输出
#ifdef _DEBUG
#define DebugPrints   OutPutDebugStringF
#else
#define DebugPrints
#endif 

tools.cpp

#include "tools.h"
#include "stdio.h" 
#include <windows.h>

void OutPutDebugStringF(const char* format, ...) {

    va_list vlArgs;
    char* strBuffer = (char*)GlobalAlloc(GPTR, 4096);//GPTR:分配固定内存并初始化为0
    va_start(vlArgs, format);
    _vsnprintf_s(strBuffer, 4096, 4096 - 1, format, vlArgs);//编写使用指针参数列表的格式化输出
    va_end(vlArgs);
    OutputDebugStringA(strBuffer);
    GlobalFree(strBuffer);//释放内存
}

image.png

6.打印报错信息(GetLastError的使用

没有控制台输出,有错误了就只是不会弹窗,并不会告诉你错在哪,需要自己加一个函数,返回的值就是最后一个错误的错误代码
image.png

第四十四课 win32 事件_消息_消息处理函数

1.事件

image.png

2.消息

Windows为了能够准确的描述这些信息,提供了一个结构体:MSG,该结构体里面记录的事件的详细信息.

typedef struct tagMSG {		
  HWND   hwnd; 		
  UINT   message; 		
  WPARAM wParam; 		
  LPARAM lParam; 		
  DWORD  time; 		
  POINT  pt; 		
} MSG, *PMSG; 		

:::info
1、hwnd:
表示消息所属的窗口
一个消息一般都是与某个窗口相关联的
在Windows中 HWND类型的变量通常用来标识窗口。
2、message
在Windows中,消息是由一个数值来表示的
但是由于数值不便于记忆,所以Windows将消息对应的数值定义为WM_XXX宏(WM == Window Message
鼠标左键按下 WM_LBUTTONDOWN 键盘按下 WM_KEYDOWN
3、wParam 和 lParam
32位消息的特定附加信息,具体表示什么处决于message
4、time
消息创建时的时间
5、消息创建时的鼠标位置
:::

3.一个完整的消息流程

设计窗口类(说明要画的窗口的相关信息)->注册窗口(让windows知道这个类的存在)->创建窗口->显示窗口->写一个消息循环不断接收窗口的消息->回调函数处理消息

系统消息队列与应用程序消息队列:

image.png
image.png
最后把各个消息取出,看看是不是窗口自己关心的,是就处理,不是就丢给windows系统处理
通俗点形容:我们点击一个应用窗口的一些按钮,这些是应用窗口自己的功能,这就是应用窗口自己关心的,拖动这个窗口等操作就是windows系统处理的
image.png

4.第一个图形界面程序

0x00 步骤1

创建Windows应用程序 选择空项目

0x01 步骤2

在新建项窗口中选C++代码文件 创建一个新的cpp文件

0x02 步骤3

在新的cpp文件中添加:#include <Windows.h>

int CALLBACK WinMain(  						CALLBACK 是一个宏 			
	_In_  HINSTANCE hInstance,  			#define CALLBACK    __stdcall			
	_In_  HINSTANCE hPrevInstance,  								
	_In_  LPSTR lpCmdLine,  								
	_In_  int nCmdShow  								
	)  									所有的Win32     API函数都遵循该约定			
{  									
									
	return 0;  								
}  									

0x04 步骤4 设计窗口类

先定义一个窗口类以及这个类所需的参数,wndclass = {0}必须加,给其余参数赋值0,不然会报错

//窗口的类名								
TCHAR className[] = "My First Window"; 								
								
// 创建窗口类的对象 								
WNDCLASS wndclass = {0};								//一定要先将所有值赋值		
wndclass.hbrBackground = (HBRUSH)COLOR_MENU;			//窗口的背景色		
wndclass.lpfnWndProc = WindowProc;						//窗口过程函数		
wndclass.lpszClassName = className;						//窗口类的名字		
wndclass.hInstance = hInstance;							//定义窗口类的应用程序的实例句柄		

0x05 步骤5 注册窗口类

RegisterClass(&wndclass);

0x06 步骤6 创建窗口

// 创建窗口  							
HWND hwnd = CreateWindow(  							
	className,				//类名		
	TEXT("我的第一个窗口"),				//窗口标题		
	WS_OVERLAPPEDWINDOW,				//窗口外观样式 		
	10,				//相对于父窗口的X坐标		
	10,				//相对于父窗口的Y坐标		
	600,				//窗口的宽度  		
	300,				//窗口的高度  		
	NULL,				//父窗口句柄,为NULL  		
	NULL,				//菜单句柄,为NULL  		
	hInstance,				//当前应用程序的句柄  		
	NULL);				//附加数据一般为NULL		
							
if(hwnd == NULL)					//是否创建成功  		
	return 0;  						

0x07 步骤7 显示窗口

ShowWindow(hwnd, SW_SHOW);

0x08 步骤8 消息循环

这个步骤其实只是获取消息对其进行加工,加工后传递给系统,系统调用上面定义类时指定的WindowProc()窗口过程函数去处理

MSG msg;  			
while(GetMessage(&msg, NULL, 0, 0))  			
{  			
	TranslateMessage(&msg);  		
	DispatchMessage(&msg);  		
}  

0x09 步骤9 回调函数

1、窗口回调函数处理过的消息,必须传回0.
2、窗口回调不处理的消息,由DefWindowProc函数(windows系统)自己来处理.

LRESULT CALLBACK WindowProc(  									
							IN  HWND hwnd,  		
							IN  UINT uMsg,  		
							IN  WPARAM wParam,  		
							IN  LPARAM lParam  		
							)  		
{  									
	switch(uMsg)								
	{								
		//窗口消息							
	case WM_CREATE: 								
		{							
			DbgPrintf("WM_CREATE %d %d\n",wParam,lParam);						
			CREATESTRUCT* createst = (CREATESTRUCT*)lParam;						
			DbgPrintf("CREATESTRUCT %s\n",createst->lpszClass);						
									
			return 0;						
		}							
	case WM_MOVE:								
		{							
			DbgPrintf("WM_MOVE %d %d\n",wParam,lParam);						
			POINTS points = MAKEPOINTS(lParam);						
			DbgPrintf("X Y %d %d\n",points.x,points.y);						
									
			return 0;						
		}							
	case WM_SIZE:								
		{							
			DbgPrintf("WM_SIZE %d %d\n",wParam,lParam);						
			int newWidth  = (int)(short) LOWORD(lParam);    						
			int newHeight  = (int)(short) HIWORD(lParam);   						
			DbgPrintf("WM_SIZE %d %d\n",newWidth,newHeight);						
									
			return 0;						
		}							
	case WM_DESTROY:								
		{							
			DbgPrintf("WM_DESTROY %d %d\n",wParam,lParam);						
			PostQuitMessage(0);						
									
			return 0;						
		}							
		//键盘消息							
	case WM_KEYUP:								
		{							
			DbgPrintf("WM_KEYUP %d %d\n",wParam,lParam);						
									
			return 0;						
		}							
	case WM_KEYDOWN:								
		{							
			DbgPrintf("WM_KEYDOWN %d %d\n",wParam,lParam);						
									
			return 0;						
		}							
		//鼠标消息							
	case WM_LBUTTONDOWN:								
		{							
			DbgPrintf("WM_LBUTTONDOWN %d %d\n",wParam,lParam);						
			POINTS points = MAKEPOINTS(lParam);						
			DbgPrintf("WM_LBUTTONDOWN %d %d\n",points.x,points.y);						
									
			return 0;						
		}							
	}								
	return DefWindowProc(hwnd,uMsg,wParam,lParam);								
}  									

5.wParam和lParam字段

他们是不固定的,是消息id的附加信息,且在不同消息类型内有不同的含义

WM_CREATE消息

可以在msdn里查
image.png
所以我们可以打印出来看看
image.png

WM_MOVE消息

image.png
移动一次触发一次
image.png
msdn文档也写出了使用宏转换POINTS结构方便读取
image.png

标签:wParam,lParam,窗口,WM,43,win32,DbgPrintf,消息,处理函数
From: https://www.cnblogs.com/xiaoxin07/p/18077859

相关文章

  • 滴水逆向笔记系列-win32总结2-45.esp寻址_定位回调函数-46.子窗口_消息处理函数-47.资
    第四十五课win32esp寻址_定位回调函数自己vs编译的exe入口函数好像和课程视频哩的vc6不一样,没办法跟着视频走,可以用课件里给的作业exe勉强跟着视频学,前面的都差不多,课件下载地址:https://www.bcdaren.com/video/videoPlay/3303185150621818881.win32应用程序入口识别没加过壳......
  • 滴水逆向笔记系列-win32总结3-48.提取图标_修改标题-49.通用控件_实现LoadPE
    第四十八课win32提取图标_修改标题1.添加图标a,.右键添加icon时不要直接新建,导入b.加载图标:::infoHICONhIcon;hIcon=LoadIcon(hAppInstance,MAKEINTRESOURCE(IDI_ICON));hAppInstance 应用程序句柄IDI_ICON 图标编号MAKEINTRESOURCE 用这个宏的主要原因......
  • 波及4300万人!法国官方就业机构数据遭窃
    昨天(3月14日),法国政府机构FranceTravail(前身为PôleEmploi)警告称,有黑客入侵了其系统,并窃取了约4300万人的个人信息。此次遭遇攻击的两家机构分别为负责失业救济的FranceTravail和负责促进残疾人就业的Capemploi。根据2023年1月的数据,法国总人口约为6804万,这意......
  • P3643 [APIO2016] 划艇
    题意:在首尔城中,汉江横贯东西。在汉江的北岸,从西向东星星点点地分布着\(N\)个划艇学校,编号依次为\(1\)到\(N\)。每个学校都拥有若干艘划艇。同一所学校的所有划艇颜色相同,不同的学校的划艇颜色互不相同。颜色相同的划艇被认为是一样的。每个学校可以选择派出一些划艇参加节日......
  • python下载win32gui的库失败解决教程
    1、进入这个网站https://www.lfd.uci.edu/~gohlke/pythonlibs/界面如下:因为这些安装包都是按照字母顺序排序的,所以就向下翻到pywin32的位置就行;选择跟自己的python版本相对应的这个库的版本,点击即可下载;等待下载完成:2、进入到pycharm软件里面,运用命令实现库的安装python-......
  • C++ error C2143: 语法错误: 缺少“;”(在“*”的前面)
    errorC2143编译错误但是,我在官网的例子上没有找到我所遇见的问题!在此记录一下,问题代码如下:1classtestA1;2classworkclass3{4public:5explicitworkclass();6virtual~workclass();7private:8intM_INT;9......
  • CF436E - Cardboard Box 题解
    只讲贪心做法。一、反悔贪心考虑如何使选的星星总数多一。显然,有如下几种方式:选一个之前没选过的位置\(i\),答案加上\(a_i\)。选一个之前选过一次的位置\(i\),答案加上\(b_i-a_i\)。对于一个之前选过一次的位置\(i\),再找到一个没有选过的位置\(j\),反悔掉\(i\),并选......
  • pywin32:批量将doc文件转为docx
    学习自:python批量把doc文件转换成docx_python批量将doc转docx-CSDN博客目的:将某个目录下(包括子目录)中的所有doc转为docximportosimportdocximportwin32com.clientaswin32url='D:\规范文档'word=win32.Dispatch('Word.Application')forroot,dir2,filesinos.walk(u......
  • 438. 找到字符串中所有字母异位词(中)
    目录题目题解:滑动窗口题目给定两个字符串s和p,找到s中所有p的异位词的子串,返回这些子串的起始索引。不考虑答案输出的顺序。异位词指由相同字母重排列形成的字符串(包括相同的字符串)。示例1:输入:s="cbaebabacd",p="abc"输出:[0,6]解释:起始索引等于0......
  • STM32G431RBT6LED灯02
    cubeMX根据引脚 选取这些引脚,设置为GPIO_Output除复用引脚之外的需要设置输出为HighLED控制语句<led.c>#include<led.c>voidLED_Disp(uchardsLED){HAL_GPIO_WritePin(GPIOC,GPIO_PIN_All,GPIO_PIN_SET);HAL_GPIO_WritePin(GPIOC,dsLED<<8,GPIO_PIN_RESET);HAL_G......