1.资源文件,创建对话框
首先我们创建一个Win32 Application项目,让系统为我们创建一个程序入口函数
点击new,选择resource script(资源脚本)
这时,编辑器就为我们创建了两个文档
注意:resource.h要我们对着Source Files鼠标右键点击添加文件才能看见
记得昨天我们创建一个自己的对话框需要以下步骤:
1.创建WNDCLASS结构体,为wndclass赋值
2.注册
3.创建窗口
4.提供消息函数
5.显示窗口
6.提供消息循环
今天我们实现Dialog函数又需要哪些步骤呢?
1.创建窗口
2.提供消息处理函数
Dialog函数:
INT_PTR DialogBox(
HINSTANCE hInstance, // handle to module 当前应用的imageBase
LPCTSTR lpTemplate, // dialog box template Dialog的模板
HWND hWndParent, // handle to owner window 父窗口的句柄
DLGPROC lpDialogFunc // dialog box procedure 消息处理函数
);
创建一个对话框
1.使用DialogBox函数创建窗口(该函数会帮我们做很多事)
2.提供消息处理函数
在这里我们要做一个可以输入文本的窗口
1.
2.在消息处理函数中修改表达式
在这里我们会用到两个函数:
HWND GetDlgItem(
HWND hDlg, // handle to dialog box Dlg窗口的句柄
int nIDDlgItem // control identifier 编辑窗口编号
);
// 该函数功能是获取文本编辑框的句柄
// 较为通用
int GetWindowText(
HWND hWnd, // handle to window or control 编辑框的句柄
LPTSTR lpString, // text buffer 存储文本的缓冲区
int nMaxCount // maximum number of characters to copy 复制的大小
);
// 该函数的功能是将编辑框内的文本进行复制
// 不通用
2.对话框回调函数的定位
前面我们学习了对于消息处理函数的定位:利用设置条件断点的方式来定位函数
但是这种方法有一定的缺陷:在我们设置了条件来进行断点后,需要F8来跟步寻找下一个call
来定位到消息处理函数的位置,但是这种方法在定位很复杂的函数时,通过一直F8来跟步的方
式很容易跟丢,因此我们需要通过消息断点来对消息处理函数进行定位
打开DTDTbug,然后打开文件,运行来使窗口运行
点击W按钮,来到一个列表
在这里需要注意:消息断点其实就是条件断点,我们点击B按钮可以观察到其实就是下了一个条件断点
如果我们不知道消息类型是什么,可以在按按钮的时候鼠标长按不起,来判断是鼠标down还是鼠标up类型
然后点击窗口的按钮,就会来到该处的反汇编
此时来到反汇编处,因为我们使用的是对话框窗口,使用的回调函数是系统给我们预定制好的
调用过程是:体统会点函数----(调用)----->我们自己写的回调函数
因此,此时我们还需要点击M按钮,来到界面设置内存访问的断点
然后我们F9
这里因为系统会一直发送消息,并不是我们不点击按钮就不会发送消息,而且能进行访问内存的消息类型不止一种,因此我们需要观察右下角的堆栈
我们可以看到,堆栈中第一行是返回地址压栈,第二行下面的四行分别是回调函数的四个参数,因为是stdcall的缘故,因此第二行就是消息类型
此时我们发现并不是我们想要定位的消息类型,因为我们还需要让它继续走,并且要注意看消息类型
我们F8继续跟步
我们F8跟步时会发现从4开头的地址,跳转到了7开头的地址
此时我们可以判断又来到了系统定义的函数中
此时我们可以F9进行跳转
F9后我们又进行了一次访问内存的断点
此时我们再观察右下角的堆栈
可以发现,此时消息类型变为111,即我们鼠标up类型的编号
此时我们可以断定我们定位到了对于ok按钮的消息处理函数的定位
// Dialog.cpp : Defines the entry point for the application.
//
#include "stdafx.h"
#include"resource.h"
BOOL CALLBACK DialogProc(
HWND hwndDlg, // handle to dialog box
UINT uMsg, // message
WPARAM wParam, // first message parameter
LPARAM lParam // second message parameter
)
{
HWND User=NULL;
HWND Pass=NULL;
switch(uMsg)
{
case WM_INITDIALOG :
//MessageBox(NULL,TEXT("WM_INITDIALOG"),TEXT("INIT"),MB_OK);
return TRUE;
case WM_COMMAND :
switch (LOWORD (wParam))
{
case IDC_BUTTON_OK:
User=GetDlgItem(hwndDlg,IDC_EDIT_USER);
Pass=GetDlgItem(hwndDlg,IDC_EDIT_PASS);
TCHAR UserBuffer[0x50];
TCHAR PassBuffer[0x50];
GetWindowText(User,UserBuffer,0x50);
GetWindowText(Pass,PassBuffer,0x50);
MessageBox(NULL,TEXT("IDC_BUTTON_OK"),TEXT("OK"),MB_OK);
return TRUE;
case IDC_BUTTON_ERROR:
MessageBox(NULL,TEXT("IDC_BUTTON_ERROR"),TEXT("OUT"),MB_OK);
EndDialog(hwndDlg, 0);
return TRUE;
}
break;
}
return FALSE;
}
int APIENTRY WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
DialogBox(hInstance, MAKEINTRESOURCE (IDD_DIALOG_MAIN),NULL,DialogProc);
return 0;
}
4.定位作业
此时我们发现这里有TEST指令和JE指令
此时EAX除非为0,ZF才为0,才会跳转
因此我们要去寻找改变EAX的原因
观察发现并没有指令改变
但是前面CALL了一个地址,因此我们跟进去观察
此时我们发现有两段指令,可以断定是strlen函数的汇编
这里CMP ECX,3 CMP ECX,5
所以我们可以判断出是账号长度为3,密码长度为5的字符串