I'm researching into intercepting queries that arrive at the SQL Server 2008 process.

SQLOS architecture is divided in the following system DLLs:

  • sqlmin.dll: Storage, replication, security features,etc.
  • sqllang.dll: TransactSQL query execution engine, expression evaluation, etc.
  • sqldk.dll: Task scheduling and dispatch, worked thread creation, message loops, etc.

SQLSERVR service process instances the SQLOS components through sqlboot.dll and sqldk.dll, and the worker threads receive queries through the selected connection method in the server (TCP/IP, local shared memory or named-pipes).

I've debugged the sqlservr.exe process address space searching for textual queries. It seems that query strings are readable, but I could not find a point where queries can be intercepted while they enter the SQLOS scheduler.

Listening to pipes or TCP/IP is not an option at this moment; I would like to inject at a higher level, preferably at SQLOS-component level.

Any idea on where to start looking into?

asked Apr 5 '13 at 19:45
Hernán

17815
 
2  
Why are you ruling out the obvious first choices in your next to last paragraph? – 0xC0000022L Apr 5 '13 at 22:08
    
I'm with 0c00l, but my question is why don't use enter a query with some thin shim program (an odbc connector for instance) and do a run trace. connect with a socket and do a run trace(starting with recv or whatever). then check the union between the two traces for when they begin to intersect to see if it's a viable approach? – RobotHumans Apr 6 '13 at 2:14 
1  
@0xC0000022L Hernan is obviously aware of the other alternatives. He wants to know specifically where to intercept the functions at a higher level (i.e: using hooks). It would be interesting to know it because I searched and couldn't find a resource about it, while exist a lot of resources about hooking other things. I just found a recommendation from Microsoft to not instrument SQL Server: "The use of third-party detours or similar techniques is not supported in SQL Server" support.microsoft.com/kb/920925 – sw. Apr 6 '13 at 15:29
1  
@0xC0000022L, sorry if I was rude. I think that knowing how to hook SQL Server would be interesting because of what Hernan said "I would like to inject at a higher level, preferably at SQLOS-component level." – sw. Apr 6 '13 at 15:49 
1  
Just like @sw says, I'm aware of other alternatives such as ODBC-level interception. To be more concise, I don't want to patch at multiple points (e.g: shared memory, pipes and TCP/IP I/O) but at a single point where all queries are scheduled for planning and execution, independent of the client-server interface or communication method. – Hernán Apr 8 '13 at 13:37

4 Answers

up vote9down voteaccepted

+50

This seemed like a fun project for a Sunday afternoon, so I had a go at it. To get straight to the point, here's the call stack for a function in SQL server that parses and then executes the query (addresses and offsets taken from SQL Server 2008 R2 running on Windows 7 SP1 32-bit):

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

Based on this, you probably want to take a close look at the CSQLSource class, and particularly its Execute method.

Armed with this information, I was also able to dig up a couple blog posts by someone at Microsoft on how to extract the query string from a memory dump of SQL Server. That post seems to confirm that we're on the right track, and gives you a place to interpose and a way to extract the query string.

Methodology

I felt like this would be most easily tackled using some form of Dynamic Binary Instrumentation (DBI); since we suspect the query string will be processed somewhere in the SQL Server process, we can look at memory reads and writes made by the process, searching for a point that reads or writes the query string. We can then dump the callstack at that point and see what interesting addresses show up, and map them back to symbols (since, as Rolf points out, SQL Server has debug symbols available). It really was basically as simple as that!

Of course, the trick is having something around that lets you easily instrument a process. I solved this using a (hopefully soon-to-be-released) whole-system dynamic analysis framework based on QEMU; this let me avoid any unpleasantness involved in getting SQL Server to run under, e.g., PIN. Because the framework includes record and replay support, I also didn't have to worry about slowing down the server process with my instrumentation. Once I had the callstack, I used PDBParse to get the function names.

answered Apr 15 '13 at 1:05
 
    
just to clarify: does your method only work if the server runs inside QEMU? and side question: can you actually modify the query? – Ange Apr 15 '13 at 10:15
1  
The particular method I used only works if the server runs in QEMU, yes. But you could do the same thing with, e.g., PIN, by instrumenting memory reads/writes. I'm not sure if you could modify the query at this point; I saw at least one other place where it uses the query string to construct an MD5 hash (CSQLStrings::GenerateDurableSqlHandle+0x40) so you'd have to modify it before that point. – Brendan Dolan-Gavitt Apr 15 '13 at 21:55
    
Sophisticated, very interesting approach, and technically correct. Thank you for your time and help! – Hernán Apr 17 '13 at 1:05
    
NOTE about debugging symbols: SQL Server 2012 RTM (11.0.2100.60) has public debugging symbols. At this moment, I could not obtain PDBs for 11.0.3128.0, plus I dont know if they are available for SP1 yet (11.0.3000). So keep this in mind when playing with SQL 2012 system DLLs. For build information seesqlserverbuilds.blogspot.com.ar – Hernán Apr 17 '13 at 20:20 
1  
Following Brendan answer, Hernan working example is available at: github.com/nektra/SQLSvrIntercept – sw.Jun 27 '13 at 12:58

Sniffing traffic only ... is easy

If you merely wanted to sniff the traffic you could use the TDS protocol sniffer that comes withWireShark.

Let the laziness guide you - laziness is the reverser's friend

Listening to pipes or TCP/IP is not an option at this moment; I would like to inject at a higher level, preferably at SQLOS-component level.

I don't know why you insist on doing this a particular way when all information is readily available and all you need to do is put the jigsaw pieces together. This would seem to be the easiest, fastest - in short: laziest - method. Besides TCP/IP is the higher level, because you can intercept it even before it reaches the actual SQL server machine if you can hijack the IP/name of the SQL server and put a "proxy" in between. How high level do you want it? What you insist on is actually drilling down into the lower level guts of the MS SQL Server.

MS SQL Server uses a documented protocol and using an LSP you should/would be able to sniff, intercept and even manipulate that traffic. As far as I recall LSPs run within the process space of the application whose traffic they're filtering. You can consider them a makeshift application-level firewall, literally.

Alternatively - and probably the better choice anyway - you could write a proxy based on the existing and free FreeTDS (licensed under LGPL). The tdspool program would be a good point to start this endeavor. And yes, this should be suitable for actual interception, not just sniffing forwarded traffic. You can use the library (FreeTDS) to decode and re-encode the queries. That library would also be the one to use inside your LSP, obviously.

I'll save the time to go into details of the disassembly, although I installed MS SQL Server 2008 and briefly looked at it in IDA Pro. Brendan's answer provides a good overview, even if I disagree with this overly involved method where an easier one is available. But then, you (Hernán) asked for it.

answered Apr 17 '13 at 0:43
0xC0000022L

6,16822253
 

In general, what I would say is that problems like this one are application-specific. Therefore, despite the fact that the user broadway was down-voted for his answer, it was exactly the same advice I'd give if I wasn't aware of any nice, special solutions specific to the problem. What you're going to have to do is watch the data come into the process and then follow it as it is copied and manipulated throughout the program. This task will be easier than the general case owing to the fact that debug symbols are available for SQL Server. Have you attempted anything along these lines? Say, setting a breakpoint on network receive-type functions in the context of SQL Server, setting a hardware RW breakpoint on the data that comes in over the network, and then watching how the data moves through the mass of code?

answered Apr 13 '13 at 0:19
Rolf Rolles

3,9231525
 
    
Yea, if there is some application specific knowledge someone already has for this case, then perhaps they'll reveal it, though short of that, this is the obvious path of investigation. However, SQL servers may have fairly complex systems that execute SQL statements, so reversing may be time consuming. OR maybe it's simple. One imagines some function that accepts the SQL statement as input ;). – bitsum Apr 14 '13 at 17:31

I don't have any specific knowledge about that target, but the approach I would probably take is to send the same message over a pipe, tcp, and shared memory and trace them with pin, looking for where the basic block's hit converge with all traces should give you some starting points for fine tuning a good injection point.

answered Apr 11 '13 at 14:34
broadway

1,421517
 
2  
Maybe it's just me, but I can't follow your solution. Perhaps you could flesh this out with links, more information, descriptions, and specifics? – Lizz Apr 12 '13 at 0:49
    
I think he is just saying execute SQL commands, make notes of the code that seems to be executing, dive into that code, and trace it back to the first function in the chain of SQL command execution. Of course, who knows if it's 'that simple', it probably has a fairly complex execution system. Anyway, not my answer, just clarifying what I think I read. – bitsum Apr 14 '13 at 17:30
    
Not exactly. I am saying use each of the input types to input the same query and examine the path through the program. Pin is a very accessible tool to do this sort of thing (although of course it's not the only one). – broadway Apr 14 '13 at 19:21

Server-side Query interception with MS SQL Server的更多相关文章

  1. MS SQL Server数据库修复/MDF数据文件数据恢复/MDF质疑/mdf无法附加

    微软的SQL Server 数据库最常用的有两种类型的文件: 1.主要数据文件,文件后缀一般是.MDF: 2.事务日志文件,文件后缀一般是.LDF. 用户数据表.视图.存储过程等等数据,都是存放在MD ...

  2. 下载-MS SQL Server 2005(大全版)含开发人员版、企业版、标准版【转】

    中文名称:微软SQL Server 2005 英文名称:MS SQL Server 2005资源类型:ISO版本:开发人员版.企业版.标准版发行时间:2006年制作发行:微软公司地区:大陆语言:普通话 ...

  3. Linux下使用FreeTDS访问MS SQL Server 2005数据库(包含C测试源码)

    Linux下使用FreeTDS访问MS SQL Server 2005数据库(包含C测试源码) http://blog.csdn.net/helonsy/article/details/7207497 ...

  4. Display Database Image using MS SQL Server 2008 Reporting Services

    原文 Display Database Image using MS SQL Server 2008 Reporting Services With the new release of MS SQL ...

  5. [MS SQL Server]SQL Server如何开启远程访问

    在日常工作中,经常需要连接到远程的MS SQL Server数据库中.当然也经常会出现下面的连接错误. 解决方法: 1. 设置数据库允许远程连接,数据库实例名-->右键--->属性---C ...

  6. MS SQL Server中数据表、视图、函数/方法、存储过程是否存在判断及创建

    前言 在操作数据库的时候经常会用到判断数据表.视图.函数/方法.存储过程是否存在,若存在,则需要删除后再重新创建.以下是MS SQL Server中的示例代码. 数据表(Table) 创建数据表的时候 ...

  7. MS SQL Server 数据库分离-SQL语句

    前言 今天在在清理数据库,是MS SQL Server,其中用到分离数据库文件.在这过程中,出现了一个小小的问题:误将数据库日志文件删除了,然后数据就打不开了,除了脱机,其他操作都报错. 数据库分离 ...

  8. 在易语言中调用MS SQL SERVER数据库存储过程方法总结

    Microsoft SQL SERVER 数据库存储过程,根据其输入输出数据,笼统的可以分为以下几种情况或其组合:无输入,有一个或多个输入参数,无输出,直接返回(return)一个值,通过output ...

  9. 在英文版操作系统中安装的MS SQL server,中文字段无法匹配

    在英文版的操作系统中安装的MS SQL server,会出现中文字段无法被匹配到.其原因在于英文环境下安装的MS SQL server的排序规则不包括中文. 所以解决办法就是更改MS SQL serv ...

随机推荐

  1. C# 判断一个单链表是否有环及环长和环的入口点

    1.为什么写这个随笔? 前几天参加一个电面,被问到这个问题,想总结一下. 2.为什么标题强调C#? 想在网上看看代码,却没找到C#版的,于是自己用C#实现一下. 一.解决问题的思路 1.一种比较耗空间 ...

  2. 图论-单源最短路-SPFA算法

    有关概念: 最短路问题:若在图中的每一条边都有对应的权值,求从一点到另一点之间权值和最小的路径 SPFA算法的功能是求固定起点到图中其余各点的的最短路(单源最短路径) 约定:图中不存在负权环,用邻接表 ...

  3. react项目中遇到的一些问题

    推荐使用facebook官方构建工具create-react-app来创建React基础工程.(然而我还是手动构建) (路由)官方旧版本和V4的比较.https://github.com/ReactT ...

  4. maven项目的多级目录

    刚刚把一个开源的项目变成maven项目来进行管理,由于是多级的目录(以前配置的都是单级的目录),所以记录一下pom文件是怎么配置的. 一.目录结构 如下,maven的结构图,红字是表示完整的项目

  5. J2EE MySQL Date数据保持一致解决方案

    1.设置MySQL时区,明确指定 MySQL 数据库的时区,不使用引发误解的 CST show variables like '%time_zone%';set global time_zone = ...

  6. js字符串与Unicode编码互相转换

    ).toString() "597d" 这段代码的意思是,把字符'好'转化成Unicode编码,toString()就是把字符转化成16进制了 看看charCodeAt()是怎么个 ...

  7. beego学习笔记(1)

    公司准备开发一个针对塔吊行业的APP. 后台采用微服务,docker容器部署. 准备采用go进行微服务的开发. 采用beego进行restful API的开发. 第一步,访问beego的官方网站: h ...

  8. 《java并发编程实战》读书笔记11--构建自定义的同步工具,条件队列,Condition,AQS

    第14章 构建自定义的同步工具 本章将介绍实现状态依赖性的各种选择,以及在使用平台提供的状态依赖机制时需要遵守的各项规则. 14.1 状态依赖性的管理 对于并发对象上依赖状态的方法,虽然有时候在前提条 ...

  9. 经验分享:如何系统学习 Web 前端技术?

    这篇文章主要是面向小白用户的,如果你有些基础,当然也建议你看看,尤其是最后一个主题,或许你能得到一些启发.本文的观点,纯属个人自以为是的想法,不是真理,仅供参考. 抛开具体技术细节,先主要谈谈程序员如 ...

  10. requere.js优化js脚本加载方案,使用篇。

    require.config({ paths: { "jquery": "jquery-3.2.1", 'index':"index" }} ...