使用 WinDbg 和基本汇编知识实时跟踪 MySQL 数据库的 SQL 查询






4.80/5 (7投票s)
汇编和 MySQL
引言
对于任何人来说,了解服务器软件的内部工作原理都非常有趣。本文的目的是展示如何运用基础的汇编知识来查找有趣的运行时信息。
几天前,我的朋友在进行 PHP+MYSQL 网站开发时遇到了一些问题。
好的,我们可以开始了。
- 您需要下载并安装任何版本的 MySQL。请确保您的 MySQLD 服务正在成功运行(换句话说,确保您的 MySQL 正常工作)。
- 从 Microsoft 网站下载最新版本的 Windbg for Windows。
- 启动 Windbg。
- 按 F6 并附加到 mysqld.exe 进程。
- 通过 File->Symbols File Path: srv*c:\windows*http://msdl.microsoft.com/download/symbols 正确设置 Windbg 符号。
- 在 Windbg 命令行中,执行
.reload
。 - 按 F5 运行进程(附加进程时,它会冻结)。使用 F5 或 G 命令,进程会运行。
- 这里是关键部分。MYSQLD.exe 进程(或在此情况下的服务)负责执行来自 PHP 页面或各种 MySQL 客户端的 SQL 查询。Navicat 是一个很棒的 MySQL 客户端,它允许我们以图形模式查看 MySQL 服务器,就像 Microsoft Management Studio 处理 SQL Server 一样。
- 为了教育目的,让我们启动 Navicat 工具(如果您愿意),或者使用您自己的 PHP 或任何其他作为 MySQL 客户端的应用程序。
EXECUTE
是魔法词。关键在于:为什么 MYSQLD.EXE 进程在执行任何类型的EXECUTE
函数时,会在其内部代码的任何部分执行 SQL 查询?让我们在那里设置一个断点。- 断点:在 Windbg 中按 CTRL+Break 停止当前的
MYSQLD
执行,并输入以下命令:bm *mysqld*!*execute*
(BM=break on mask,库为所有 *mysqld*,函数为 *execute*)。 - 按 F5 并通过 PHP 页面、Navicat 或任何其他 MySQL 客户端执行任何操作。
- 您会看到您的页面或 Navicat 冻结:为什么?因为 MYSQLD 被停止了。让我们看看 Windbg。
- 很好,MYSQLD 进程停止在
MYSQLD!MYSQL_EXECUTE_COMMAND
,让我们看看堆栈跟踪:使用 KB 命令。 - 正如您所见,我们可以直接在 Args to Child 部分观察到
MYSQL_EXECUTE_COMMAND
的输入参数。那里的每个十六进制值通常代表指向任何指定数据结构的指针。在 Args to Child 指针中的任何地方有string
吗?让我们检查一下。 - 点击 View->Memory。在 Address 中,输入指针(从 Args to child 捕获),尝试使用 01eb2630 和其他 Args to child。
- 我们在
MYSQL_EXECUTE_COMMAND
的所有 Args to Child 参数中没有看到任何有趣的东西,但前一个函数mysql_parse
呢? - Eureka!那里有些有趣的东西。如果我们打印那里的值呢?执行:
.printf “%ma”.03b62a68
。 - 是的,这无疑是从 MYSQLD 进程捕获的 SQL 查询。现在我们有了想要的功能,通过命令
BC *
删除所有断点,并使用bp mysqld!mysql_parse
,然后通过 F5 或 G windbg 命令行继续执行。 - 现在我们的 Windbg 停止在
mysqld!mysql_parse
。 - 一百万美金的问题是:每次任何 MYSQL 查询执行某项操作时,它都会冻结我的应用程序,直到我按 F5 才能继续吗?答案是“不”,如果我们使用更智能的断点。我们知道
mysql_parse
函数,但它存储在哪个内存地址?这是调用堆栈理论。 - 让我们解释一下,当进程开始一个函数时,它会推送函数参数以供使用。然后 ESP 处理器寄存器会发生什么?例如:
VOID SUM(INT X,INT *Y)
。ESP
代表堆栈的TOP
,而EBP
代表Stack
的基地址。假设ESP=1000
。 - 进程推送
Y
值指针,ESP
减少其值,减少堆栈的顶部?听起来很令人困惑,是的,在 Windows 操作系统中,堆栈的TOP
比 EBP(堆栈的基指针)在内存中的位置低,ESP=ESP-4 : 996
。 - 进程推送
X
的值ESP=ESP-4 : 992
。 - 进程推送前一个函数的返回地址:
ESP=ESP-4 : 998
。 - 当 Windbg 停止时,堆栈处于
c
状态。例如,您可以通过执行一个简单的数学运算找到第二个参数:第二个参数位于POI(ESP+8)
,正如我们在 Windbg 上一张图片中看到的,是的,我们的string
是第二个参数。让我们试试这个。 - 打印第二个参数:
.printf “%ma”,poi(esp+8)
。 - 为什么是 POI?Poi 在 Windbg 中代表或获取
ESP+8
的指针地址,%ma
表示或仅表示 ASCII 字符。%mu
表示 Unicode。 - 好的,现在我们可以将它们组合到一个简单的断点中了。
- 完整的断点:
bp mysqld!mysql_parse ".printf \"\\n%ma\",poi(esp+8);gc"
。 - 当我们设置
Bp=breakpoint
在函数mysqld!mysql_parse
中时,它会根据指向esp+8
(第二个参数)的指针打印一个 ASCIIstring
,并且gc
会继续执行而不会停止。
享受吧!