wireshark解析达梦数据库协议

  • Post author:
  • Post category:其他


达梦数据库不开源,所以wireshark没有对应的协议解析,可实际工作中又需要抓包验证程序处理流程是否正确,为了校验起来方便,自己手撸一个达梦的解析脚本。

先来展示一下解析结果:

解析脚本:dameng.lua

dameng_protocol = Proto("Dameng", "Dameng Protocol")

local head_packet_type_desc = {
    [0x01]  = "Login",
    [0x05]  = "SQL Request",
    [0xa3]  = "Login ACK",
	[0xbb]  = "Response",
    [0xc8]  = "Version",
	[0xe4]  = "Version",
}

local DAMENG_ie = {
	head_packet_type = ProtoField.uint16("dameng.head_packet_type", "HeadPacketType", base.HEX, head_packet_type_desc),
	data_len = ProtoField.uint16("dameng.date_len", "DataLen", base.DEC),
}

local login_ie = {
	username_len = ProtoField.uint32("dameng.username_len", "UserNameLen", base.DEC),
	username = ProtoField.bytes("dameng.username", "UserName"),
	password_len = ProtoField.uint32("dameng.password_len", "PassWordLen", base.DEC),
	password = ProtoField.bytes("dameng.password", "PassWord"),
	client_name_len = ProtoField.uint32("dameng.client_name_len", "ClientNameLen", base.DEC),
	client_name = ProtoField.string("dameng.client_name", "ClientName"),
	system_name_len = ProtoField.uint32("dameng.system_name_len", "SystemNameLen", base.DEC),
	system_name = ProtoField.string("dameng.system_name", "SystemName"),
	host_name_len = ProtoField.uint32("dameng.host_name_len", "HostNameLen", base.DEC),
	host_name = ProtoField.string("dameng.host_name", "HostName"),
}

local loginACK_ie = {
	db_name = ProtoField.string("dameng.db_name", "DataBaseName"),
	username = ProtoField.string("dameng.username", "UserName"),
	client_ip = ProtoField.string("dameng.client_ip", "ClientIP"),
	link_time = ProtoField.string("dameng.link_time", "LinkTime"),
}

local SQL_ie = {
	sql_data = ProtoField.string("dameng.sql_data", "SQL data"),
}

local Version_ie = {
	clinet_version = ProtoField.string("dameng.client_version", "Client Version"),
	server_version = ProtoField.string("dameng.server_version", "Server Version"),
}

dameng_protocol.fields = { 
	---------------DAMENG_ie----------------
	DAMENG_ie.head_packet_type,
	DAMENG_ie.data_len,
	---------------login_ie----------------
	login_ie.username_len,
	login_ie.username,
	login_ie.password_len,
	login_ie.password,
	login_ie.client_name_len,
	login_ie.client_name,
	login_ie.system_name_len,
	login_ie.system_name,
	login_ie.host_name_len,
	login_ie.host_name,
	---------------loginACK_ie----------------
	loginACK_ie.db_name,
	loginACK_ie.username,
	loginACK_ie.client_ip,
	loginACK_ie.link_time,
	---------------SQL_ie----------------
	SQL_ie.sql_data,
	---------------Version_ie----------------
	Version_ie.clinet_version,
	Version_ie.server_version,
}

function dameng_protocol.dissector(tvb, pinfo, tree)
    length = tvb:len()
    if length == 0 then
        return
    end
    pinfo.cols.protocol = dameng_protocol.name
	local offset = 0
	local msg_len = 0
	
    local subtree = tree:add(dameng_protocol, tvb(), "Dameng Protocol Data")
	offset = offset + 4
	local headPacketType = tvb(offset,2):le_uint()
	subtree:add_le(DAMENG_ie.head_packet_type, tvb(offset,2))
	offset = offset + 2
	local dataLen = tvb(offset,2):le_uint()
--	subtree:add_le(DAMENG_ie.data_len, tvb(offset,2))
	offset = offset + 2
	if (headPacketType == 0x01) then
	----------------dissect login-------------------
		offset = offset + 56
		----------------dissect username-------------------
		local usernameLen = tvb(offset,4):le_uint()
--		subtree:add_le(login_ie.username_len, tvb(offset,4))		
		offset = offset + 4
		subtree:add(login_ie.username, tvb(offset, usernameLen))
		offset = offset + usernameLen
		----------------dissect password-------------------
		local passwordLen = tvb(offset,4):le_uint()
--		subtree:add_le(login_ie.password_len, tvb(offset,4))
		offset = offset + 4		
		subtree:add(login_ie.password, tvb(offset, passwordLen))
		offset = offset + passwordLen
		----------------dissect client_name-------------------
		local clientNameLen = tvb(offset,4):le_uint()
--		subtree:add_le(login_ie.client_name_len, tvb(offset,4))
		offset = offset + 4		
		subtree:add(login_ie.client_name, tvb(offset, clientNameLen))
		offset = offset + clientNameLen
		----------------dissect system_name-------------------
		local systemNameLen = tvb(offset,4):le_uint()
--		subtree:add_le(login_ie.system_name_len, tvb(offset,4))
		offset = offset + 4		
		subtree:add(login_ie.system_name, tvb(offset, systemNameLen))
		offset = offset + systemNameLen
		----------------dissect host_name-------------------
		local hostNameLen = tvb(offset,4):le_uint()
--		subtree:add_le(login_ie.host_name_len, tvb(offset,4))
		offset = offset + 4		
		subtree:add(login_ie.host_name, tvb(offset, hostNameLen))
		offset = offset + hostNameLen
		
	elseif (headPacketType == 0xa3) then
	----------------dissect login ACK-------------------
		offset = offset + 72
		----------------dissect database name-------------------
		local dbNameLen = tvb(offset,4):le_uint()		
		offset = offset + 4
		subtree:add(loginACK_ie.db_name, tvb(offset, dbNameLen))
		offset = offset + dbNameLen
		----------------dissect user-------------------
		local userNameLen = tvb(offset,4):le_uint()
		offset = offset + 4		
		subtree:add(loginACK_ie.username, tvb(offset, userNameLen))
		offset = offset + userNameLen
		----------------dissect client_ip-------------------
		local clientIpLen = tvb(offset,4):le_uint()
		offset = offset + 4		
		subtree:add(loginACK_ie.client_ip, tvb(offset, clientIpLen))
		offset = offset + clientIpLen
		----------------dissect link time-------------------
		local linkTimeLen = tvb(offset,4):le_uint()
		offset = offset + 4		
		subtree:add(loginACK_ie.link_time, tvb(offset, linkTimeLen))
		offset = offset + linkTimeLen	
		
	elseif (headPacketType == 0x05) then
	----------------dissect SQL Request-------------------
		offset = offset + 56
		subtree:add(SQL_ie.sql_data, tvb(offset, dataLen))
	elseif (headPacketType == 0xc8) then
	----------------dissect Client Version-------------------
		offset = offset + 56
		local clientVersionLen = tvb(offset,4):le_uint()
--		subtree:add_le(login_ie.client_name_len, tvb(offset,4))
		offset = offset + 4		
		subtree:add(Version_ie.clinet_version, tvb(offset, clientVersionLen))
		offset = offset + clientVersionLen
	elseif (headPacketType == 0xe4) then
	----------------dissect Server Version-------------------
		offset = offset + 72
		local serverVersionLen = tvb(offset,4):le_uint()
--		subtree:add_le(login_ie.client_name_len, tvb(offset,4))
		offset = offset + 4		
		subtree:add(Version_ie.server_version, tvb(offset, serverVersionLen))
		offset = offset + serverVersionLen
	end
end

local tcp_port = DissectorTable.get("tcp.port")
tcp_port:add(5236, dameng_protocol)

下面说说怎么把解析脚本嵌到wireshark中:

将damen.lua文件放在wirekshark的安装目录,在wireshark的根目录中找到init.lua,打开后将文件中的enable_lua设置为true,并在init.lua文件中增加我们编写的lua脚本,使用的命令为dofile(DATA_DIR..”dameng.lua”)。

再次用wireshak打开达梦的包,就能看到解析内容了。

注意:脚本中默认的达梦数据库端口为5236,如果实际环境为其它端口,在脚本中做对应修改即可。



版权声明:本文为superbfly原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。