对于周日下午来说,这似乎是一个有趣的项目,所以我试了一下。为了直接切入正题,这里是 SQL Server 中一个函数的调用堆栈,该函数解析然后执行查询(取自在 Windows 7 SP1 32 位上运行的 SQL Server 2008 R2 的地址和偏移量):
0x7814500a msvcr80.i386!memcpy+0x5a
0x013aa370 sqlservr!CWCharStream::CwchGetWChars+0x5c
0x013a9db5 sqlservr!CSQLStrings::CbGetChars+0x35
0x012ffa50 sqlservr!CParser::FillBuffer+0x3d
0x0138bbfd sqlservr!CParser::CParser+0x3c8
0x01352e96 sqlservr!sqlpars+0x7b
0x013530f2 sqlservr!CSQLSource::FParse+0x16d
0x013531ed sqlservr!CSQLSource::FParse+0x268
0x012ff9e8 sqlservr!`string'+0x3c
0x015894b8 sqlservr!CSQLSource::Execute+0x2c8
0x0158ad31 sqlservr!process_request+0x2ac
0x0158a328 sqlservr!process_commands+0x15f
0x015cf8b4 sqlservr!SOS_Task::Param::Execute+0xdd
0x015cf9ea sqlservr!SOS_Scheduler::RunTask+0xb4
0x015cf575 sqlservr!SOS_Scheduler::IsShrinkWorkersNecessary+0x48
0x77f06854 ntdll!ZwSignalAndWaitForSingleObject+0xc
0x77e479e2 kernel32!SignalObjectAndWait+0x82
基于此,您可能想要仔细查看CSQLSource
该类,尤其是它的Execute
方法。
有了这些信息,我还能够挖掘出Microsoft 某人关于如何从 SQL Server 的内存转储中提取查询字符串的几篇博文。那篇文章似乎证实我们走在正确的轨道上,并为您提供了一个插入的地方和一种提取查询字符串的方法。
方法
我觉得使用某种形式的动态二进制仪器 (DBI) 最容易解决这个问题;由于我们怀疑查询字符串将在 SQL Server 进程中的某处进行处理,因此我们可以查看进程进行的内存读取和写入,搜索读取或写入查询字符串的点。然后我们可以在那个时候转储调用堆栈,看看出现了哪些有趣的地址,并将它们映射回符号(因为,正如 Rolf 指出的,SQL Server 有可用的调试符号)。真的就是这么简单!
当然,诀窍是周围有一些东西可以让您轻松地对流程进行检测。我使用基于QEMU的(希望即将发布的)全系统动态分析框架解决了这个问题;这让我避免了让 SQL Server 在例如PIN下运行所涉及的任何不愉快。因为该框架包括记录和重放支持,所以我也不必担心我的检测会减慢服务器进程。获得调用堆栈后,我使用PDBParse来获取函数名称。