消息断点在x64dbg中的应用 by lantie@15PB

消息断点在x64dbg中的应用 by lantie@15PB

Contents

介绍

你曾试图逆向一个应用程序中特定的函数,但是却无法真正找到它吗?比如,在点击按钮或者按键之后想找到正在调用的代码的。在某些程序(Delphi、CBuilder、Visual Basic等)中,可以使用工具反编译程序并在几秒钟内定位到相应事件/地址。但如果程序被加壳或是使用了反-反编译技术,亦或是程序不是事件驱动的,在这种情况下,你可以使用类似方法很快定位到地址吗?
本文介绍的方式是在程序运行中使用消息断点来定位特定函数。(好不好使,看你的了😀)

使用Windows消息

让我们来看一个简单的CrackMe作为示例。其是一个简单的exe,使用VC++编写:

sample crackme

如果我们尝试输入一个文本并点击按钮Check!,会发现没有任何反应,没有文本信息,什么也没有。这个时候,我们可以开动脑筋,有创意地寻找其他替代方案来找到我们的序列号被处理的确切位置,也许成功,也许失败。但是如果我告诉你,有一个更简单的方法可以找到按钮呢,就像Delphi、Visual Basic或者其他事件驱动的语言?然我们一起来看看这种方法吧。

在x64dbg中加载和执行文件后,我们输入一些文本,然后点击按钮Check!,之后我们转到句柄(Handles)选项卡,并刷新视图以获取调试程序的窗口列表。然后我们可以在列表中看到按钮Check!,选择按钮Check!所在列然后右键单击它,并选择Message Breakpoint选项设置消息断点:

windows widget

到此会进行消息断点的设置,具体的配置是这样的:

message bp dialog

以上设置是当WM_LBUTTONUP(鼠标左键点击)消息被发送到我们的按钮控件,程序就会停止。设置断点之后,我们点击CrackMe中的按钮Check!,不久之后,我们进入断点。

到此,我们实现了我们想要的程序暂停。按钮点击后我们刚刚停止执行,程序会停在user32.dll中,但我们的目的是在主模块代码中。 到达主模块就像在我们的可执行文件的代码部分使用断点一样简单。 我们可以使用运行到用户代码选项(Ctrl + F9)。

code section breakpoint

当尝试恢复执行时,调试器将再次停止执行,但这次正好在我们正在寻找的代码中间。 在这种情况下,我们进入了 DLGPROC 函数(负责处理发送到主窗口对话框中的每个窗口控件的消息的回调)。

dialog function

事件驱动程序设计

如果你是一个程序员,或者一直在做与编程语言和写代码相关的工作,你应该知道所谓的事件驱动编程的概念。事件驱动的编程是一种编程范例,程序执行流由事件决定;用户动作,鼠标点击,按键等。事件驱动的应用程序用于识别事件发生时,然后使用适当的事件处理过程进行管理。一些编程语言使用事件驱动编程,并给出一个IDE,它可以让代码自动生成,并且可以选择内置的对象和控件,Visual Basic,Borland Delphi / CBuilder,C#,Java等等都是可以做到。(1)

Windows消息

即使程序员没有使用上述语言之一,或者即使以非事件驱动的方式使用它们,Microsoft Windows应用程序也是事件驱动的,这意味着您将要处理窗口消息。以下是MSDN的的说明:

系统将应用程序的所有输入传递到应用程序中的各种窗口。 每个窗口都有一个称为窗口过程的函数,系统在窗口输入时调用。 窗口过程处理输入并将控制返回给系统。

系统使用一组四个参数向窗口过程发送消息:窗口句柄,消息标识符和两个称为消息参数的值。 窗口句柄标识消息所针对的窗口。 系统使用它来确定哪个窗口过程应该接收消息。

消息标识符是用于标识消息目的的命名常量。 当窗口过程接收到消息时,它使用消息标识符来确定如何处理消息。(2)

Windows窗口回调函数

根据上面的信息,拦截某个窗口的窗口消息,我们需要首先找到所需“控件”的窗口回调函数。 从包含窗口回调函数的应用程序这样做是很容易的,我们可以通过使用以下函数来定位:

LONG WINAPI GetWindowLong(
  _In_ HWND hWnd,
  _In_ int  nIndex
);

DWORD WINAPI GetClassLong(
  _In_ HWND hWnd,
  _In_ int  nIndex
);

nIndex = GWL_WNDPROC:指定获取的信息是窗口回调函数的地址,或表示窗口回调函数地址的句柄。 您必须使用CallWindowProc函数调用窗口回调函数。

BOOL WINAPI GetClassInfo(
  _In_opt_ HINSTANCE  hInstance,
  _In_     LPCTSTR    lpClassName,
  _Out_    LPWNDCLASS lpWndClass
);

BOOL WINAPI GetClassInfoEx(
  _In_opt_ HINSTANCE    hinst,
  _In_     LPCTSTR      lpszClass,
  _Out_    LPWNDCLASSEX lpwcx
);

typedef struct tagWNDCLASS {
  UINT      style;
  WNDPROC   lpfnWndProc;
  ...
} WNDCLASS, *PWNDCLASS;

lpfnWndProc:指向窗口回调函数的指针。

有了以上函数,获取窗口类信息和窗口函数地址会非常简单。但是Windows操作系统有一个限制:Microsoft Windows 不允许从外部应用程序(如调试器)中获取这些信息。 如果要使用上述函数之一获取另一个进程所拥有的给定窗口或控件的窗口回调函数地址,则最终会出现ACCESS_VIOLATION异常。在我们这个例子中x64dbg应该是一样的,无法获取信息。但是x64dbg可以获取的真实的地址,接下来我们看看x64dbg是怎么做的

获取外部Windows窗口回调函数

在这点上,我们不清楚为什么会出现这种情况,以及是否是操作系统的bug。事实上它可以在以前的Windows操作系统版本中使用。这其中关键函数是这个:

DWORD WINAPI GetClassLong(
  _In_ HWND hWnd,
  _In_ int  nIndex
);

在相应地调用GetClassLong(ANSI / UNICODE)的正确功能版本之前,黑客依靠对给定窗口的字符集进行测试。 x64dbg使用的代码很简单:

duint wndProc;
if(IsWindowUnicode(hWnd))
    wndProc = GetClassLongPtrW(hWnd, GCLP_WNDPROC);
else
    wndProc = GetClassLongPtrA(hWnd, GCLP_WNDPROC);

要编写与32位和64位版本的Windows兼容的代码,您必须使用GetClassLongPtr。 当编译32位Windows时,GetClassLongPtr被定义为调用通常的GetClassLong函数。

截取消息

现在已经定位到窗口回调函数,任何消息都可以用适当的条件表达式拦截,但在此之前,让我们检查一下这个逻辑。 每次通过窗口回调函数处理的结构如下所示:

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

正如我们可以看到结构给我们提供了一些有用的信息,最重要的是hwndmessage。 根据这些字段,我们可以知道哪个特定的控件发送什么消息。 在进一步介绍之前,让我们看一个发送给给定Button控件的特定消息(WM_LBUTTONUP)的示例。

message breakpoint dialog

点击OK按钮后,我们会触发断点,当我们检查堆栈参数时,我们可以看到这样的东西
breakpoint stack

第一个值可以看到的是对应于我们的Button控件的句柄,第二个值对应于消息WM_LBUTTONUP(0x202)。

WinProc 条件断点

完成此功能的最后一件事是可能暂停应用程序的时机只有在特定句柄(handles)和消息(messages)处理时。我们可以在帮助文档中阅读,x64dbg集成了一组非常好的强大的表达式来实现这一点。 如上图所示,有三个选项:

  1. Break on any window(在任何窗口中断):使用此选项,我们停止给定的消息,而不管窗口句柄。 为此,我们需要最简单的表达式:
bpcnd WINPROC, "arg.get(1) == MESSAGE"
  1. Break on current window only(仅在当前窗口中断):此功能将为表达式添加一个附加条件,以便仅在涉及特定窗口的句柄时停止执行,在这种情况下,表达式将为:
bpcnd WINPROC, "arg.get(1) == MESSAGE && arg.get(0) == HANDLE"
  1. Use TranslateMessage(使用TranslateMessage函数):有时winproc技术可能不是预期的结果,那这个时候程序可能使用的是TranslateMessage API 来截获消息,而不是在窗口回调本身。
BOOL WINAPI TranslateMessage(
  _In_ const MSG *lpMsg
);

看到这个函数使用了我们之前看到的相同的MSG结构,因此根据操作系统平台,使用表达式会增加一些微小的变化:

ifdef _WIN64
bpcnd TranslateMessage, "4:[arg.get(0)+8] == MESSAGE"
bpcnd TranslateMessage, "4:[arg.get(0)+8] == MESSAGE && 4:[arg.get(0)] == HANDLE"
#else //x86
bpcnd TranslateMessage, "[arg.get(0)+4] == MESSAGE"
bpcnd TranslateMessage, "[arg.get(0)+4] == MESSAGE && [arg.get(0)] == HANDLE"
#endif //_WIN64

案例说明

如在这篇文章中看到的,消息断点是x64dbg中非常方便和强大的功能,可以在许多场景中使用,我们可以尽可能的控制任何事件暂停调试。即使不是类似Delphi或Visual Basic一样的事件驱动程序,也可以为逆向者打开一扇门,带来更多的思路进行调试。如果想在MASM编写的应用程序的“Edit”控件中输入字符时暂停执行,只需要在控件上对消息WM_KEYUP设置消息断点即可。按钮点击、显示窗口等控制一样,有一大堆消息可以使用消息断点进行调试分析。

最后的话

书写这篇文章,是想更深入了解消息断点功能和在多种场景下如何使用消息断点,到此结束,希望对你有帮助
原作者: ThunderCls
翻译者: lantie@15PB
原文地址:https://x64dbg.com/blog/2017/07/07/messages-breakpoints-in-x64dbg.html

参考

  1. https://www.technologyuk.net/computing/software-development/event-driven-programming.shtml
  2. https://msdn.microsoft.com/en-us/library/windows/desktop/ms644927(v=vs.85).asp

注释

帮助

官网:www.15pb.com.cn,专注于信息安全教育,软件逆向,二进制安全,网络安全

下载

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,875评论 6 496
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,569评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,475评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,459评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,537评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,563评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,580评论 3 414
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,326评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,773评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,086评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,252评论 1 343
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,921评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,566评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,190评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,435评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,129评论 2 366
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,125评论 2 352

推荐阅读更多精彩内容