TNS协议解析

青春壹個敷衍的年華 提交于 2020-02-12 13:00:43

TNS协议解析

0. 通用规则

  • 每个 Oracle 包的开始四个字节(如果启用了 large_SDU )是标识整个包长度的字段, 不管客户端和服务端是大端序还是小端序, 这一字段都是大端序

1. Connect

基本构成

字段 编码方式 含义
version B2 客户端版本
version(Compatible) B2 客户端支持的最低服务端版本
Service Options B2 没用过
Session Data Unit Size B2 客户端的 SDU 大小
Max Transmission Data Unit Size B2 客户端的 TDU 大小
NT Protocol Characteristics B2 没用过
Line Turnaround Value B2 没用过
Value of 1 in Hardware B2 客户端是大端序还是小端序, 0x0001 就是大端序
Length of Connect Data B2 连接信息串的长度
Offset to Connect Data B2 连接信息串在包中开始的位置
N 没用过的数个字段
Connect Data N 客户端连接信息串, 含有 Service nameSID

补充说明

  • Value of 1 in Hardware 指明了客户端发送数据所用的是大端序还是小端序, 但是当前包不会受到该字段的影响, 全部都是大端序编码.

  • Length of Connect Data 的值超过 221 时, Connect Data 将在下一个包中发送, 而下一个包将会是一个 DataPacket

    这种情况发生时, Offset to Connect Data 字段值将与当前包长度相同, 若将后续单独的 Connect Data 拼接到当前包后, 则该字段相当于正常指向 Connect Data 开始的位置

  • Connect Data 连接信息串示例:
    (DESCRIPTION=(CONNECT_DATA=(SID=orcl10)(CID=(PROGRAM=sqlplus@kali)(HOST=kali)(USER=root)))(ADDRESS=(PROTOCOL=TCP)(HOST=10.0.72.146)(PORT=1521)))

2. Accept

基本构成

字段 编码方式 含义
version B2 服务端的版本号
Service Options B2 没用过
Session Data Unit Size B2 服务器的 SDU 大小
Maximum Transmission Data Unit Size B2 服务器的 TDU 大小
Value of 1 in Hardware B2 服务器编码是大端序还是小端序
Length of Accept Data B2 没什么用
Offset to Accept Data B2 没什么用
Connect Flags B2 可以用来判断有没有 ANO_Service 协商
timeout B2
tick B2 timeout 联合起来可以判断 server pool enabled
SDU B4 当服务版本在 315 及以上时启用此字段及其后续字段
TDU B4 ‘真正的’ TDU
compression options B1 与压缩协议有关的选项, 不知道启用效果
N 不需要处理的后续字段

补充说明

  • 对于 315 及其之后版本的服务器,后续的包会启用 large_SDU,

    此时靠后的 SDUTDU 这两个四字节的字段才是真正的数据, 前面的会是 0

    后续数据包的类型是 Data, MarkerDataDescriptor 时, 其 Oracle 包的头部长度字段编码是四个字节.

  • Value of 1 in HardwareConnectPacket 中的作用范围一样, 不包含当前包

  • 当前会话的 SDU = min(TDU, SDU)

3. Redirect Packet

基本结构

字段 编码 含义
Redirect Data Length B2 重定向信息串长度
Redirect Data N 重定向信息串

补充说明

  • 该包由服务器返回, 用于引导客户端连接真正的工作服务器.

    代理支持这一特性的流程包括:

    1. 获取服务器指定的新的将要连接的 IP 和端口
    2. 新建一个代理, 目的地址指向新的 IP 和端口
    3. 将代理的监听地址的 IP 和端口给到协议解析层
    4. 协议层改写当前重定向包, 将服务器给出的地址替换成代理的监听地址
  • 重定向信息串示例:

    (ADDRESS=(PROTOCOL=tcp)(HOST=192.168.0.4)(PORT=2143))

4. Secure Network Service Packet

Additional Network Option Negotiation

在客户端接收到AcceptPacket之后, 可能会发出一个或多个可选的ANO协商包, 协商客户端和服务端将使用的ANO驱动

具体的包结构没有完全解析, 因为目前看到的网络数据中, 此类 Oracle 包对后续的数据没有影响

从JDBC中可以看出可以选择的服务:

服务 含义
SupervisorService 监管服务
AuthenticationService 授权服务, 用以认证数据库用户身份
EncryptionService 加密通道服务?
DataIntergrityService 数据完整性服务, 可能是对数据进行hash

5. Set Protocol Packet

客户端发送的包

只包含 Accepted VersionsClient Platform

没有分析的必要

服务端返回的包

字段 编码方式 含义
Version B2 协议版本
Server Banner string(NUL) 服务器平台
server charset B2 服务器字符集 小端序
server Flags B1 和字符集转换有关系
server charset elements length B2 字符集元素长度 小端序
server charset elements N 长度等于上一字段值乘五, jdbc中跳过了这一字段
NCHAR_CHARSET_LENGTH B2 下一个字段的长度, 大端序
NCHAR_CHARSET N jdbc中只用到了数个位置 和多字节字符与字符串的转换有关
Server Compile-time Capabilities length B1 下一字段长度
Server Compile-time Capabilities N 编译期权能标识
Server Run-time Capabilities length B1 下一字段长度
Server Run-time Capabilities N 运行时权能标识
  • 两个权能字段只在 Version 大于等于 6 时才会出现

  • Server Compile-time Capabilities

    • 决定后续 Set DataType 包中的某些字段是否存在
    • 影响 CLR 编码方式是否启用 big chunk
    • 影响 TTC Version 的取值

6. Set Datatypes

编码基础

5种数据类型: B1, B2, B4, B8, PTR
3种编码类型: native, universal, LSB

  • native类型表示大端序编码

  • universal类型表示以长度为首字节的编码,默认大端序

  • LSB类型表示小端序编码,可以和universal类型结合

  • CLR 数据类型

    • 当数据长度小于等于 252 时,就是普通的 length-byte-preceeded 编码方式.
    • 当数据长度大于 252 时,首字节是 0xFE, 然后按照 effectiveTTCC_MXIN 个字节一组使用 length-byte-preceeded 编码这一组数据, 最后一组可能不足 effectiveTTCC_MXIN 个字节. 最后用 0x00 结尾.
    • effectiveTTCC_MXIN 的长度取决与 Client Compile-Time Capabilities[37] & 32 && Server Compile-Time Capabilitites[37] & 32, 启用了 big chunks 时, 其值为 32767, 没有启用时为 64. 同时分组长度和结尾的 0 的编码方式也会变为 B4

客户端发送的包

基本结构

字段 编码方式 含义
cliRIN B2 没用过 可能是客户端的字符集
cliROUT B2 同上
cliFlags B1 与客户端是否启用字符串的 CLR 编码有关
Client Compile-time Capabilities Length B1 客户端编译期权能标识长度
Client Compile-time Capabilities N 会随服务器的权能位改变
Client Run-time Capabilities Length B1 客户端运行时权能标识长度
Client Run-time Capabilities N 客户端运行时权能标识
Time Zone Bytes B11 可能与时区有关 没用过
Time Zone Version Number B4 同上
data type representation length B2 见补充
data type representation N 见补充

补充说明

  • Time Zone Bytes
    Client Run-time Capabilities[1] & 1 控制

  • Time Zone Version Number
    Server Compile-Time Capabilities[37] != 2 && Client Compile-Time Capabilities[37] & 2控制

  • data type representation length
    后续字段的长度, 可能没有, 不知道哪里控制的
    如果读取完上一个字段后的 offset 没有超过包长度, 那么可能存在这一字段.
    可以读取后结合后续字段的单双字节编码方式, 判断是否为 0x00010x0101, 来判断读取到的是后续字段还是此字段.

  • data type representation

    • 是一个以 0x00 000x00 为分隔的 list, 用来标识各种数据类型的编码方式

    • 有些客户端不会发送这一字段, 可以通过 offset 和长度来判断是否有这一字段

    • 单双字节的编码方式受到 client compile-time capabilities[27] 的控制

    • 取值范围和 ServerCompileTimeCapability[7] 有关

      ServerCompileTimeCapability[7] runtimeTypeAndReps
      >= 8 完整的typeAndRep
      >= 7 typeAndRepFor1200
      <= 6 typeAndRepFor1100OrBefore

      数据涵盖范围递减

    • 这一 list 中的每一项的编码含义大概是:

      datatype datatype encodetype 0

      每一项的字段数量可能是 2, 4 或 6 , 但结尾字段的值一定是 0, 而且真正有用的只有前三个字段

      datatype 所表示的类型详见 oracle\jdbc\driver\TCTTIdty.java 中的以 DTY 开头的一长串 short
      encodetype 所表示的类型详见 oracle\jdbc\driver\T4CTypeRep.java 中的以 REP 为开头的一长串 static final byte

  • 现已使用的data type representation

    • 代表 B2 数据类型的 0x19, 其编码类型为 0x01 0x1C 时为 universal 编码, 0x18 时为 2 字节编码
    • 代表 B4 数据类型的 0x1D, 其编码类型为 0x01 0x1B 时为 universal 编码, 0x17 时为 4 字节编码
    • 代表 PTR 数据类型的 0x20, 其编码类型为 0x0C 时, 长度可能是 1 或 8, 0x0A 时长度为 1

服务端返回的包

只含有 Time Zone Bytesdata type representation
如果没有分析服务器编码的需求, 则没有分析的必要, 而且 JDBC 中只检查了完整性, 而没有实际使用其中的内容

7. Get Session Key

客户端发送用户名和 5 个键值对, 用以获取AUTH_SESSION_KEY

基本结构

字段 编码方式 可能出现的形式
next sequence number B1 0x01, 0x02 等, 没什么用
PTR 1, 4, 8 在有 data type representation 时的编码方式见前一节中的描述
没有时可能是 四字节乱码加上四字节0x00 或 八/四字节的 -2
user name length B4 在有 data type representation 时的编码方式见前一节中的描述
没有时的编码长度为四字节
logon mode B4 同上
PTR
key-value list size WORD 在没有 data type representation 时与 PTR 同长
PTR PTR
user name CLR 或 纯字符串 根据前述的 (cliFlags & 2) == 2 判断是否为 CLR

补充说明

  • 以这个包为基础, B2, B4, B8, PTR 的编码方式基本固定下来了, 或是由 data type representation 所确定, 或是在没有 data type representation 时根据已知晓的编码方式加上读取部分字节来确定.

  • 后续的包中的字段只需按照既有的编码方式读取对应的 B4 或 PTR 即可

8. Generic authentication call

获取了 AUTH_SESSION_KEY 之后, 正式发送加密后的密码请求认证

含有用户名以及数个键值对, 没有分析的必要

9. 含有 SQL 语句的 Data Packet

基本概念

  • Data Packet 有多种子类型, 其中包含有 SQL 语句的类型只有两类: 0x03 USER_OCI_FUNC0x11 PIGGYBACK_FUNC, 以 Data Packet 的第十一个字节作为区分, 这两种类型还可以分成多种子类型, 以 Data Packet 的第十二个字节作为区分, 被称为 OCI_FUNC_CODE.

  • 0x03 USER_OCI_FUNC 包含 SQL 语句的子类型主要是 0x035E, 一说 0x033E 也有可能包含语句, 但是 0x3E 没有作为 OCI_FUNC_CODE 出现在 JDBC 中.

  • PIGGYBACK_FUNC 类型的数据包主要是将 USER_OCI_FUNC 作为 payload 放在自身数据的后方, 所以只要去掉 PIGGYBACK_FUNC 的头部就可以将其视为 USER_OCI_FUNC 进行处理.

  • PIGGYBACK_FUNC 可以嵌套, 即在 USER_OCI_FUNC 之前可能出现多个 PIGGYBACK_FUNC 的数据.

  • 在 JDBC 中, PIGGYBACK_FUNC 的嵌套顺序是有顺序的, 在各个子类型出现的条件都满足的情况下, 出现的顺序应该是 0x1178 0x1169 0x1187 0x119A 0x119D 0x11B0 0x11B1, 但是目前分析过的网络数据中只会出现 0x1178 + 0x11690x1169 (即 0x1178 以及后续的子类型出现的条件没满足, 只出现了 0x1169 ) 这两种类型.

0x035E

执行 SQL 语句的主体包

基本结构

字段 编码 含义
next sequence number B1 没什么用
options B4 SQL执行的命令, 指明是绑定变量语句等
cursor B4 没什么用
PTR PTR
sql length WORD SQL语句的长度
PTR
al8i4 length WORD SQL语句之后的一个数组的大小
PTR * 2
long.MAX_VALUE B4 没什么用
rows to fetch WORD 没用上
isPlsqlOrCall B4 没用上
number of bind positions PTR+WORD 如果是绑定变量语句, 标识参数的个数
PTR * 5 很多时候是 0 1 0 1 1 (指 PTR 与 NULLPTR)
defCols PTR+B4 TTC Version >= 2 时出现 没什么用
RegID B4+PTR+PTR TTC Version >= 4 时出现 没什么用
RegID PTR+B4+PTR+B4+WORD TTC Version >= 5 时出现 没什么用
current rank PTR+WORD+PTR TTC Version >= 7 时出现 没什么用
null PTR+WORD+PTR+WORD+PTR TTC Version >= 8 时出现 没什么用
null PTR+WORD TTC Version >= 9 时出现 没什么用
sql CLR 或 B1Array SQL语句本体
N 即使有绑定变量的参数也没法解

补充说明

  • SQL 语句的编码方式与 user name 字段的相同

0x1178 0x1169

这两个 PIGGYBACK_FUNC 子类型的结构一样

基本结构

字段 编码方式 含义
PTR PTR
offset 同 7 中的 key-value list size 后续字段的个数
cursor ID B4 没什么用, 数量有 offset

0x116B

单独出现, 无需遵守 0x1178 等的顺序

基本结构

字段 编码方式
sididx B4
sidser B4
sidopc B4

补充说明

PIGGYBACK_FUNC 作为出现在 USER_OCI_FUNC 之前的数据, 我们并不关注其内容, 只要能找到后续的 0x035E 数据包即可.

现有问题

  • 不支持压缩协议以及SSL连接

  • 没有 data type representation 的情况下, 对于 PTR 字段编码方式的判断是基于经验, 不排除有例外情况, 造成后续的包全解析错误.

  • 绑定变量语句的参数没有解析, 如果绑定变量的参数是数据库中的结构, 比如某个表或字段的名字, 那么可能对上层语法分析造成影响

  • OCI_FUNC_CODE 涵盖并不全面, 只处理了当前能找到的网络数据中出现的类型, 有待后续追加.

  • 0x035E 中的 options 字段对 SQL 语句的执行有一定的控制, 有待继续挖掘其含义.

参考资料

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!