Windows编程学习记录(二)

1.MessageBox()

 

int MessageBox(
  HWND    hWnd,     //A handle to the owner window of the message box
  LPCTSTR lpText,   //The message to be displayed.
  LPCTSTR lpCaption,//The dialog box title
  UINT    uType     //The contents and behavior of the dialog box
);

注意:第四个参数如果有多个值,可以用或操作符"|"连接,如 MB_OK | MB_ICONSTOP

文档:https://docs.microsoft.com/zh-cn/windows/win32/api/winuser/nf-winuser-messagebox

 

MessageBoxW()和MessageBoxA()和MessageBox()的关系:

MessageBox()实际上是一个宏,根据传入的是Unicode字符或ASCII字符自动调用MessageboxW()和MessageBoxA()

 

下面的文章从RING3追踪到RING0,深入解析了MessageBox()的工作原理,很有认真学习一遍的价值,最好自己跟踪一次。读完后深感自己的水平之低,遂努力学习。

深入理解MessageBox():https://blog.csdn.net/AcceZn/article/details/54670776

自己写一个MessageBox()按照上面的方法跟踪学习一下:

#include <Windows.h>

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPreInstance, PSTR szCmdLine, int iCmdshow)
{
	MessageBox(NULL, TEXT("Hello world"), TEXT("Lesson1"), MB_OK);
	return 0;
}

选择Release模式编译一下,Debug模式的话会大很多,调试起来不方便看

 

下面的数据库也保留,这次主要目的不是学习逆向分析,主要是跟踪一下MessageBox()的调用流程。

放入OD,给MessageBox()下一个断点:bp MessageBoxW  然后把程序跑起来,停在了MessageBoxW的函数入口:

发现确实就是简单地把参数传入MessageBoxTimeoutW(),步入继续追踪

 

下面就进入到了文章中说到的给MSGBOXDATA结构体赋值的过程,这个成员有点多,就没有一一分析了。根据文章所说,下面将会用这个结构体作为唯一的参数调用一个user32.dll未导出的函数–MessageBoxWorker。那么未导出函数在OD里面是什么样子的呢?又找到一篇文章:https://www.cnblogs.com/gussing/archive/2009/08/18/1548869.html  文章嵌套文章感觉自己更菜了,读完了只知道未导出函数就只能看到一个call 地址。按照正常流程,应该看MessageBoxTimeoutW()如何给MSGBOXDATA结构体赋值,然后可以给这个结构体下个内存断点或者直接看它作为哪一个call的参数。

这里偷懒了,后面讲到MessageBoxWorker()调用了SoftModalMessageBox()这个导出函数。所以给这个函数下个断点,断下来看它返回在哪个函数,说明这个函数就是MessageBoxWorker()。

最后发现

76021340  |.  E8 58F3FFFF       call user32.7602069D

这个函数就是MessageBoxWorker()

在这个函数中找到了调用的NtUserModifyUserStartupInfoFlags()

这个未导出函数不知道为什么被OD识别出来了,可能是逆向中用得比较多 。

 最后MessageBoxWorker()调用了SoftModalMessageBox()弹出了对话框。

 这样就大致地跟踪了一遍MessageBox()的调用流程。其中还有很多不足的地方,比如说两大流程(参考《MessageBox深入研究》)只跟踪了一边,对NtUserModifyUserStartupInfoFlags()在内核中的一系列操作也没有弄清楚,这些都是需要进一步学习的。

 

2.ASCII&UNICODE的处理

以前对字符集和字符编码没有搞清楚。只知道ACII是7/8位,UNICODE分为UTF-X,X=8/16/32等分别有8/16/32位。原理知道了,具体实现不知道,一般都是报错了或者出了乱码,然后改一下,当然这种态度是不好的,所以认真学习了一下在标准C中和Windows编程中是如何对字符集进行处理的。

​#include <stdio.h>

int main()
{
	char str[] = "哈哈哈";
	printf("% s % c", str, str[1]);
	return 0;
}​

可以看到打印字符串成功了,字符失败。因为根据ANSI编码规则,编译器自动将字符串作为了系统的默认语言简体中文输出,而中文是两个字节表示的,所以用%c打印一个字符当然失败了。这个程序如果在非中文的系统上运行,字符串打印出来就也是乱码。 同时ANSI还带来了一系列衍生问题,如字符串长度计算问题。

因此,提出了UNICODE编码。为了方便使用,Windows 编程中,使用 TEXT() 将字符串括起来可以解决编码问题。使用 TCHAR 来定义字符及字符串。在宽字符的环境里,Windows 自动将 TCHAR 替换为 C 语言的 wchar_t 类型,TEXT() 自动在字符串前加 L 标识。

由此我们也可以知道C语言中的处理办法,其实就是用wchat_t声明一个宽字节字符变量,在字符串前加L将其变成宽字节模式。

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值