admin 管理员组

文章数量: 887053


2024年1月15日发(作者:c中split)

ORACLE协议分析

1 TNS介绍

TNS协议是ORACLE服务端和客户端通讯的协议。TNS协议传输可以使用TCP/IP协议、使用SSL的TCP/IP协议、命名管道和IPC协议传输,其中TCP/IP协议传输是使用明文传送。这里我们只分析基于TCP/IP协议上的TNS数据。

ORACLE网络通讯协议TNS有许多版本,并且大部分向下兼容,我们主要oracle

TNS协议有一个通用的头,通用头包含一个请求数据类型。不同的服务请求和数据9.2.0.1.0客户和服务间的传输协议,他的协议版本号为312,其兼容到300。

传输使用不同的请求数据类型。对于通常意义的查询操作一般使用数据类型,当出现错误或其他情况时可能使用其他类型。在分析过程中发现以下类型数据:

 查询语句出错会用标记(marker)类型

 客户端向服务器请求失败(如不存在的服务ID),服务器会发送拒绝(refuse)类型

 客户机登陆会发送连接类型,而服务器返回一个重定向类型数据

 当重定向端口连接完成后客户端重现发送连接类型数据,服务器返回接受类型数据,然后能够正常通讯。

2 TNS数据格式

TNS数据包含一个通用的包头,这个包头包含包校验,包长度和包类型等信息。

Common Packet Header 8

Data

通用包头

不同的类型的数据实现不同功能的数据传输。

可变 数据

2.1 通用包头格式

每个TNS完整数据都包含一个通用包头,他说明接受数据的长度及其相关校验和解Length

Packet check sum

Type

2

2

1

包的长度,包括通用包头

包的校验和

TNS类型

析的信息。

Flag

Header check sum

注:

Length:包长度(包括包头)

Type: 数据包的类型

类型号

1

2

3

4

5

6

7

8

9

10

11

12

13

14

1

2

状态

通用头的校验和

类型说明

连接(CONNECT)

接受(ACCEPT)

确认(ACK)

拒绝(REFUTE)

重定向(REDIRECT)

数据(DATA)

NULL

中止(ABORT)

重新发送(RESEND)

标记(MARKER)

ATTENTION

控制(CONTROL)

2.2 连接包结构(0x01)

在客户端和ORACLE要建立连接时,客户端首先发送一个连接结构,然后服务器返回重定向包(参见2.5)。

typedef struct TNS_CONNECT_header{

UCHAR NS_ver[2];

UCHAR Compatible_ver[2];

UCHAR ser_opt1;

UCHAR ser_opt2;

UCHAR SDU_size[2];

UCHAR TDU_size[2];

UCHAR NT_protocol_ch1;

UCHAR NT_protocol_ch2;

UCHAR Max_packets[2];

UCHAR Hardware_1[2];

UCHAR data_length[2];

UCHAR Offset[2];

UCHAR Max_data[4];

UCHAR flag0;

UCHAR flag1;

/*java thin interface has no items and id,

if it is not jdbc thin, use offset to override these

有些版本TNS协议中没有下面几项*/

UCHAR item1[4];

UCHAR item2[4];

UCHAR ID[8];

UCHAR unknown[8];

/*followed by decode_des_conn_data */

//连接字符串

}TNS_CONNECT_HEADER;

连接字符串格式:

连接功能

PING

SHOW

VERSION

STATUS

ESTABLISH

连接字符串

(CONNECT_DATA=(COMMAND=ping));

(CONNECT_DATA=(COMMAND=SHOW LOGFILE));

(CONNECT_DATA=(COMMAND=version));

(CONNECT_DATA=(COMMAND=STATUS));

(CONNECT_DATA=(SID=OBJ_SRVR)

(CID=(PROGRAM=)(HOST=140.211.111.111)

(USER=SOME_USER)));

ESTABLISH_REAL_DB (CONNECT_DATA=(SID=wouprd)

(CID=(PROGRAM=)(HOST=)

(USER=some_user)));

SERVICE_REGISTER (CONNECT_DATA=(COMMAND=service_register)(LOAD=0)

(MAXLOAD=1)

(INSTANCE_LOAD=0)

(INSTANCE_MAXLOAD=0)

(SHUTDOWN_NOTIFY=ON)(FLAGS=0)

(SERVICE=obj_srvr)(INFO=PID$COLON$pid)

(DISPLAY=PRESPAWNED SERVER)

(SERVICE_ID=BBB99B99999B-99BB-B999-B99BB9999B99)

(CLASS=ORACLE)(VERSION=81500)

(ADDRESS=(PROTOCOL=tcp)

(HOST=)(PORT=$port)));

REDIRECT

如:

数据库一般的连接,即ESTABLISH的连接字符串为:

(DESCRIPTION=

)

(ADDRESS=

)

(CONNECT_DATA=

)

(SID=test)

(SERVER=DEDICATED)

(CID=

)

(PROGRAM=D:)

(HOST=TOPSEC-MYANGJP)

(USER=myangjp)

(PROTOCOL=TCP)

(HOST=topsec-syangjp)

(PORT=1521)

(ADDRESS=(PROTOCOL=tcp)

(HOST=140.211.116.176)(PORT=$port));

2.3 接受包结构(0x02)

用户重定向之后,需要用重定向端口向服务器发送连接,客户端发送连接包,服务器连接成功则返回接受包,否则返回refuse包

struct TNS_ACCEPT_header{

unsigned char NS_ver[2];

unsigned char ser_opt1;

unsigned char ser_opt2;

unsigned char SDU_size[2];

unsigned char TDU_size[2];

unsigned char Hardware_1[2];

unsigned char data_length[2];

unsigned char Offset[2];

unsigned char flag0;

unsigned char flag1;

//unsigned char unknown[8];

/*no following data*/

};

2.4 拒绝包结构(0x04)

typedef struct TNS_REFUSE_header{

UCHAR uUserRefuseReason;

UCHAR uSysRefuseReason;

unsigned short int data_length;

//拒绝字符串

}TNS_REFUSE_HEADER;

拒绝字符串:

REFUTE (DESCRIPTION=

(TMP=)

(VSNNUM=153092352)

(ERR=12505)

(ERROR_STACK=

(ERROR=

(CODE=12505)

(EMFI=4)

)

))

2.5 重定向包结构(0x05)

typedef struct TNS_REDIRECT_header{

UCHAR data_length[2];

UCHAR data; //长度为data_length;

//重定向数据

}TNS_REDIRECT_HEADER;

重定向数据:

REDIRECT (ADDRESS=(PROTOCOL=tcp)

(HOST=140.211.116.176)(PORT=$port));

2.6 标记包结构(0x0c)

typedef struct TNS_MARKER_header{

UCHAR data_length[3];

}TNS_REDIRECT_HEADER;

注:

当请求命令出错时,服务器会返回三个标记包

2.7 控制包结构(0x0d)

暂时没有发现该结构

2.8 数据包结构(0x06)

数据包负责传输数据库客户端和服务端的各种操作。每个操作由一个或几个命令组Common Header

Data flag

Command packet

Command packet

Command packet

具体各种操作命令的组成和转换现在还不能完全确定,但是对于一些基本的SQL查询我们是可以分析的,下面我们主要分析一些命令结构和相关ORACLE操作的命令组成序列。

有些有许多结构和它的具体字节不影响ORACLE基本命令的分析,所以只做了简单的分析,对于SQL的一般查询语句TNS协议主要通过数据包的0x0303和0x035e命令来传输数据,返回结果主要是通过0x06和0x08命令传输数据,0x06主要传输数据,0x08主要传输系统配置相关数据。

8

2

通用包头

状态

成,可以是在同一个数据包中有几个命令结构组合起来,也可以分开传输一些命令。

可变 数据

可变 数据

… …

可变 数据

2.8.1 数据包通用结构

数据包有一个2字节的状态包和多个命令包组成:

Data flag

Command packet

Command packet

注:

 Data_flag一般情况为零,分析发现退出时为0x0040

Send token

Request Confirmation

Confirmation

Reserved

UNKNOWN

More Data to Come

End of File

Do Immediate Confirmation

Request to send

Request Nt Trailer

命令包(Command packet)结构如下:

Command

Sub command

Data

注:

0x01

0x02

0x03

0x04

0x05

0x06

0x07

0x08

0x09

0x0a

0x0b

Set Protocol

Set Data Type Representation

User to Oracle Request

Return Status

Access User Address Space

Raw Transfer Header

Raw Transfer Data

Return OPI(Oracle Program Interface) Parameter

Oracle Function Complete

N Error Return Definition

Sending I/o Vector only for fast UPI(User Program Interface)

1

1

命令

子命令

0x0001

0x0002

0x0004

0x0008

0x0010

0x0020

0x0040

0x0080

0x0100

0x0200

2

状态

可变 命令包

可变 命令包

可变 命令包数据

命令(Command)说明(以下命令为主命令的基本功能,但是还不能完全确认):

0x0c

0x0d

0x0e

0x0f

0x10

0x11

0x12

Sending Long for Fast UPI

Invoke User Callback

Network Service

Data Intergrity

Supervisor

通过分析具体的包和一些其他相关软件,得到以下相关命令和子命令,许多命令还需要进一步确认

命令

0x01

0x01

0x01

0x02

0x02

0x02

0x03

0x03

0x03

0x03

0x03

0x03

0x03

0x03

0x03

0x03

0x03

0x03

0x03

0x03

0x03

0x03

0x03

0x03

0x03

0x04

0x04

0x04

子命令

0x05

0x06

0x2c

0x00

0x01

0x54

0x01

0x02

0x03

0x04

0x05

0x08

0x09

0x0E

0x27

0x2B

0x3B

0x47

0x51

0x52

0x54

0x5E

0x73

0x76

0x77

0x01

0x02

0x05

类型

请求

CLIENT TYPE

Set Protocol

IDENT

RESET

CHAR_MAP

SQL_OPEN

QUERY

QUERY SECOND

FETCH MORE

DISCONNECT

SET_LANG

DESC_COLS

DB VERSION

FETCH

Set password

Set user

HANDSHAKE4

SQL

AUTH2

AUTH1

查询表结构信息

ACK

ACK

ACK

说明

DESC

使用

0x06

0x06

0x08

0x08

0x08

0x08

0x10

0x11

0x11

0x11

0x00

0x01

0x01

0x05

0x08

0x9c

0x19

0x69

0x6b

0x78

More Row Result Info

First Row Result Info

Db version

Field Info

SELEC返回

2.8.2 Data Format(length+data)

对于ORACLE的TNS协议结构中数据传输,其主要采用以下方式,即用一个标志 如果开始的大数据标志为0xfe,则结构如下

Big Data Identify

Data Length

Data

Data Length

Data

Data Length

Data Length

Data

1

1

Data Length

1

Data Length

1

1

Data Length

返回列数

如果

0

返回列数

和长度字符来传输数据。具体格式如下

 如果开始的大数据标志不为0xfe,则结构如下:

2.8.2.1 字符串格式

(1) Char(n),nchar

Data

Data1

注:数据和数据1总长度为n

可变

可变

实际数据

空格

(2) Varchar(n)

Data 可变(<=n) 实际数据

2.8.2.2 数字格式

(1) 正数

Id 1

Intlength=Id-c0

C0+整数部分长度

整数部分

小数部分

注:

 数据的第一位标志整数部分长度

 整数部分长度+小数部分长度=数据总长度-1

 整数部分从后向前每两位(代表0到100)用一个字节(十六进制)表示,且为十六进制值-1

 小数部分从后向前每两位(代表0到100)用一个字节(十六进制)表示,且为十六进制值-1

 如果没有小数部分,Intlength+1〉length(为数字长度),则后面有(Intlength+1-length)位(只传输位)值为0的数据没有传输

(2) 负数

Id 1

Intlength=3f-id

1

3f-整数部分长度

0x66

整数部分

小数部分

Magic

DecLength=length-intlength-1

DecLength=length-intlength-1

 数据的第一位标志整数部分长度

 整数部分长度+小数部分长度=数据总长度-2

 整数部分从后向前每两位(代表0到100)用一个字节(十六进制)表示,且为101-十六进制值

 小数部分从后向前每两位(代表0到100)用一个字节(十六进制)表示,且为101-十六进制值

 如果没有小数部分,Intlength+2〉length(为数字长度),则后面有(Intlength+2-length)位(只传输位)值为0的数据没有传输

2.8.2.3

日期格式

Year1 1 Year1-100

Year2

Month

Day

Hour

Minute

Second

注:

1

1

1

1

1

1

Year2-100

Month

Day

Hour-1

Minute-1

Second-1

 Year1为年前两位,值为year1-100

 Year2为年后两位,值为year2-100

 Month为月,值为month

 Day为月,值为Day

 Hour为月,值为Hour-1

 Minute为月,值为Minute-1

 Second为月,值为Second-1

2.8.3 0x03 0x02 SQL_OPEN

发现当进行0x0303命令查询时

Request id

Magic

1

8

2.8.4 0x03 0x03 QUERY

该命令也传输一些SQL查询请求,不能确定什么时候使用0x0303命令进行查询,在分析过程中,发现在登陆之后进行一些系统请求用到了该命令。

Request id

Magic

Data Format

1

12

可变 查询语句

2.8.5 0x03 0x04 QUERY SECOND

很少出现这个包,也没具体分析

Request id 1

Magic

12

2.8.6 0x03 0x05 FETCH MORE

用户查询是通过0x035e命令来请求数据的返回的结果不能一次传输完成,客户端会不断发送该命令向服务器请求数据,直到服务器告诉客户端数据传送完成。

Request id

Magic

1

8

2.8.7 0x03 0x08 HANDSHAKE7

Request id

Magic

1

4

2.8.8 0x03 0x09 DISCONNECT

当客户端断开连接时,客户端发送请求到服务器(用0x0309),服务器发送0x0901确认。

Request id

1

2.8.9 0x03 0x3B DB VERSION

请求ORACLE数据库版本信息,通过0x089c返回结果。

Request id

Magic

1

16

2.8.10 0x03 0x47 FETCH

Request id 1

Magic

121

2.8.11 0x03 0x51 Set password

当用户使用GRANT更改密码时,客户先通过0x0352发送用户信息,然后通过0x0351发送密码信息。

Request id

Magic1

User name length

Magic2

Username

1

4

1

99

User

name

length

Session key

Host info

32

可变

用户名长度

2.8.12 0x03 0x52 Set user

当用户使用GRANT更改密码时,客户先通过0x0352发送用户信息,然后通过0x0351发送密码信息。

Request id

Magic1

User name length

Magic2

Username

1

4

1

99

User

name

length

Host info

可变

用户名长度

2.8.13 0x03 0x5E SQL

一般的SQL查询语句是封装在0x035e命令结构中,用该命令请求数据时,服务器

返回数据和确认命令数据。

 如果查询命令错误,则返回错误代码和错误消息。

 如果查询正常,服务器返回执行结果数据和确认命令。

它的结构如下:

Request id

Magic1

Data Format

Magic3

1

80

48

返回列数

总是为0x07

可变 SQL查询语句

2.8.14 0x03 0x73 AUTH2

用户登录过程发送用户密码和用户信息,包括用户名,终端名称,客户端程序,机器,客户端进程号。

2.8.15 0x03 0x76 AUTH1

用户登录过程发送用户相关信息,包括用户名,会话密钥,终端名称,客户端程序,机器,客户端进程号和对服务器一些设置(语言,时区等)。

2.8.16 0x03 0x77 desc table

当用户通过DESC TABLE tablename命令查询用户表属性信息时,客户端发送0x0377命令到ORACLE服务器。

Request id

Magic1

Table name length

Magic2

Data Format

1

4

1

16

返回列数

表名长度

可变 SQL查询语句

2.8.17 0x04 0x01 ACK

各种数据库操作会通过0x04命令来返回结果,如是否正常运行,影响行数,影响的表格,操作类型等,如果错误还要返回错误消息,以下0x0402,0x0405均为数据库查询

返回,但是还不知道什么情况适用这三种应答。

数据应答报结构如下:

Magic1

Record num

Error num

Magic2

Type

Magic3

Obj Id

Magic4

Ack id

Magic5

Msg length

Msg

4

4

2

8

1

2

2

19

1

46

1

Msg

length

记录数,该操作影响记录数

返回错误代码

操作类型(如select,insert,create等)

操作对象ID,如表的对象ID

确认号(为该请求号+1)

消息长度

消息

2.8.18 0x04 0x02 ACK

同0x0401

2.8.19 0x04 0x05 ACK

同0x0401

2.8.20 0x06 0x00 行结果信息

如果0x06 01命令传送数据未完成则后续数据用0x06 00命令传输,且每行只传输和前一行不同的列。

行结果数据结构信息

Magic1

Column Num

Magic2

Column distributing

Magic3

2

2

23

1

返回列数

总是为0x07

可变 等于[Column Num/8]

Row Data

Row Split

Row Data

Row Split

Row Data

行数据(Row Data)结构信息

Data Format

Data Format

Data Format

注:

 对于第一行列数为Column Num

可变

可变

可变

可变

… …

可变

可变 列数据

可变 列数据

… …

可变 列数据

 非第一行,每行列数和列分布信息根据行分隔结构获取

行分隔结构信息

Id

Column Num

Column distributing

Magic3

注:

 Column distributing 为该行列分布信息,如果第i列不为空,则Column

distributing的第I bit为1

1

2

1

总是0x15

返回列数

总是为0x07

可变 等于[Column Num/8]

2.8.21 0x06 0x01开始行结果信息

SQL查询语句返回结果主要包括字段信息和数据,其中字段数据用0x1019传输,数据有0x0601和0x0600传输。

对于0x0601命令只返回开始几行数据(一般为一行),第一行显示所有的列,以后每行传输和前一行不同的列,即如果和前一行数据相同,则不传送数据,如果多行的某一列都相同,则只传送最开始一行的该列数据。

Magic1

Column Num

Magic2

Column distributing

Magic3

2

2

23

1

1

返回列数

总是为0x00

总是为0x07

2.8.22 0x08 0x01

经分析发现验证密钥、查询表的结构、0x033b、0x0302命令返回结果用命令0x0801,不过其格式非常不规则,很难分析。

2.8.23 0x08 0x05

当用户查询请求时,有时返回结果之后会出现这个命令,具体怎么使用还不是很清楚。

Magic1

Value Num

Data Format

Data Format

Data Format

23

2

返回列数

数据

数据

数据

2.8.24 0x08 0x08

当用户发送密钥成功后服务器返回响应的一些消息,如会话密钥,主机名,程序等。

Magic

Data length

Data Format

Data length

Data Format

Data length

Data Format

注:

如果data length 为0 则后面数据为

1

4

4

4

可变 数据

可变 数据

可变 数据

2.8.25 0x08 0x20 Session Key

当当前用户使用grant命令更改当前用户密码之后,系统需要重新发送用户名(0x0352)和密码(0x0351),并更新会话密钥。

Magic

Session key

1

32

会话密钥

2.8.26 0x08 0x9c Db version

当用户请求数据库版本信息(0x033b)时通过本命令返回版本信息。

Magic

Data Format

Data Format

Data Format

1

可变 数据库版本信息

可变 数据库版本信息

可变 数据库版本信息

2.8.27 0x09 0x01

当ORACLE服务器收到用户关闭连接的消息时通过本命令确认关闭操作,然后断开TCP/IP连接。

Magic1

Magic2

1

2

总是0

2.8.28 0x10 0x19 Field Info

SQL查询语句如果有数据返回(如SELECT语句),则先返回各字段信息,然后在返回数据信息。

字段信息结构:

Magic1

Field num

Magic2

Field Info

Field Info

29

2

3

字段个数

可变 字段信息

可变 字段信息

… …

Field Info

Magic3

注:字段信息个数为field num

单个字段信息结构:

Magic1

Type

Magic2

Precision

Scale

Magic3

Charsetid

Charsetform

Spare3

Magic4

Is null

length

length

Data Format

可变 字段信息

12 07 00 00 00 07 78 6a

05 1a 0f 0b 0c

1

1

1

1

1

20

2

2

2

2

1

1

4

字段类型

可变

2.8.29 0x11 0x69

当用户查询数据时,即使用0x035e命令时通常会先发送0x1178和0x1169命令。

Request id

Magic

1

12

2.8.30 0x11 0x6b

Request id

Magic

1

12

2.8.31 0x11 0x78

当用户查询数据时,即使用0x035e命令时通常会先发送0x1178和0x1169命令。

Request id 1

Magic 12

3 典型的使用序列

3.1 数据库登陆

请求响应 序请求包

操作 列

正常连接 无记录 1 连接包

2 连接包

不正常连无记录 1 连接包

3.2 数据结构内部命令序列

请求响应 序请求包

操作 列

Select 无记录 1 0x1169+0x035e

Select 1条记1 0x1169+0x035e

2 0x3e

Select 多条记1 0x1169+0x035e

2 0x3e

3 0x0305

Insert 正确 1 0x1169+0x035e

Insert 错误 1 0x1169+0x035e

响应包

重定向包

接受包

拒绝包

响应包

0x1019+0x06010

+x0401

0x1019+0x0601

+0805+0x0401

0x0600+0x0401

0x1019+0x0601

+0805+0x0402

0x0600+0x0401

0x0600+0x0401

0x0805+0x0402

Mark

说明

正常连接

不正常连接

说明

errcode=1403

errcode=0

(errcode=1403)

errcode=0

(errcode=1403)

Mark

2

Create

table

Create

table

2

Drop

table

Drop

table

Alter

table

Alter

table

2

Update

Update

正确

错误

1

2

Desc table 正确

中断连接 正确

1

1

2

Mark

0x1169+0x035e

0x1169+0x035e

Mark

0x0377

0x0309

发送flag为0x0040的包结束

错误 1 0x1169+0x035e Mark

Mark

0x0401

0x0805+0x0401

Mark

Mark

0x0401

0x0801+0x0405

0x0901

正确

2

Mark

0x1169+0x035e

错误 1 0x1169+0x035e Mark

Mark

0x0401

0x0805+0x0401

正确 1

Mark

0x1169+0x035e

错误 1 0x1169+0x035e Mark

Mark

0x0401

0x0805+0x0401

正确 1

Mark

0x1169+0x035e

0x0402

0x0805+0x0401

通过以上命令序列我们可以知道,ORACLE基本操作主要通过0x035e,0x0303请求,而通过0x1019返回字段信息,0x0601和0x0600返回数据信息,所以我们需要着重分析这几个命令,对于ORACLE的系统数据分析其实也非常重要,但是分析发现0x08命令非常复杂,鉴于时间问题,没有具体分析。


本文标签: 数据 命令 用户 返回