From 65bcf271e05160f6b0127d385503422bf519604c Mon Sep 17 00:00:00 2001 From: Xappy Date: Sat, 4 Jun 2022 14:00:38 +0300 Subject: [PATCH] New version 4.8.11 Also added mirroring support --- sam_flow.lua | 503 +++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 389 insertions(+), 114 deletions(-) diff --git a/sam_flow.lua b/sam_flow.lua index e0e8725..2dc4232 100644 --- a/sam_flow.lua +++ b/sam_flow.lua @@ -1,9 +1,9 @@ -------------------------------------------------------------------------------------------------- -- -- This file was generated by SamFlowDissectorGenerator (Version 1.1.0.0) --- S*msungFlowFramework.NET.dll Creation Time: 29/04/2021 5:00:53 AM --- S*msungFlowFramework.NET.dll Version: AuthVer: 11, AuthVerMin: 9, NotifVer: 11, NotifVerMin: 9 --- Dissector generation time: 1/05/2021 10:32:57 PM +-- S*msungFlowFramework.NET.dll Creation Time: 6/3/2022 12:32:47 PM +-- S*msungFlowFramework.NET.dll Version: AuthVer: 11, AuthVerMin: 9, NotifVer: 12, NotifVerMin: 9 +-- Dissector generation time: 6/4/2022 1:45:26 PM -- -------------------------------------------------------------------------------------------------- @@ -405,7 +405,7 @@ function finfo_get_sub_finfos(json_field_info) return json_field_info[4] end -function generic_dissect(buf, pkt, subtree, text, json_field_info) +function generic_dissect(buf, pkt, subtree, dissector_state, text, json_field_info) local json_field_name = finfo_get_json_field_name(json_field_info) local proto_field = finfo_get_proto_field(json_field_info) local json_field_type = finfo_get_json_field_type(json_field_info) @@ -415,16 +415,19 @@ function generic_dissect(buf, pkt, subtree, text, json_field_info) local value, ti = dissect_json_field(subtree, buf, text, json_field_name, proto_field, json_field_type, sub_finfos ~= nil) if value ~= nil and value ~= "null" then - local post_func_name = json_field_name .. "_pre" - local post_func_ptr = _G[post_func_name] - if post_func_ptr ~= nil then - post_func_ptr(buf, pkt, subtree, text, json_field_info) + local pre_func_name = json_field_name .. "_pre" + local pre_func_ptr = _G[pre_func_name] + if pre_func_ptr ~= nil then + pre_func_ptr(buf, pkt, subtree, dissector_state, text, json_field_info) end end -- If we are dealing with an object, see if sub fields are defined if json_field_type == J_FIELD_TYPE_OBJ then - if value == nil or value == "null" then return end + if value == nil or value == "null" then + -- TODO: BUG! _post function not called in this case... + return + end local sub_finfos = finfo_get_sub_finfos(json_field_info) if (sub_finfos == nil) then return end @@ -434,7 +437,7 @@ function generic_dissect(buf, pkt, subtree, text, json_field_info) local value_tvb = ByteArray.new(value,true):tvb(json_field_name) for i,finfo in pairs(sub_finfos) do - generic_dissect(value_tvb, pkt, ti, value, finfo) + generic_dissect(value_tvb, pkt, ti, dissector_state, value, finfo) end end @@ -456,7 +459,7 @@ function generic_dissect(buf, pkt, subtree, text, json_field_info) -- Making a new TVB and trying to dissect it further for every subfield local value_tvb = ByteArray.new(value,true):tvb(json_field_name .. " Item " .. i) for i,finfo in pairs(sub_finfos) do - generic_dissect(value_tvb, pkt, ti, value, finfo) + generic_dissect(value_tvb, pkt, ti, dissector_state, value, finfo) end end i = i + 1 @@ -467,15 +470,15 @@ function generic_dissect(buf, pkt, subtree, text, json_field_info) local post_func_name = json_field_name .. "_post" local post_func_ptr = _G[post_func_name] if post_func_ptr ~= nil then - post_func_ptr(buf, pkt, subtree, text, json_field_info, value, ti) + post_func_ptr(buf, pkt, subtree, dissector_state, text, json_field_info, value, ti) end end -function generic_dissect_root(buf, pkt, subtree, text, json_field_infos_table) +function generic_dissect_root(buf, pkt, subtree, dissector_state, text, json_field_infos_table) for i, finfo in ipairs(json_field_infos_table) do for j, val in ipairs(finfo) do end - generic_dissect(buf, pkt, subtree, text, finfo) + generic_dissect(buf, pkt, subtree, dissector_state, text, finfo) end end @@ -836,20 +839,32 @@ function p_sam_flow_auth.dissector(buf, pkt, tree) subtree:add(json_tvb:range(),"Plaintext JSON"); -- Dissect JSON structure - generic_dissect_root(json_tvb, pkt, subtree, plaintext_str, auth_message_finfos) + local sender_entity = ENTITY_PC + if(known_mobile_auth_ports[pkt.src_port]) then + sender_entity = ENTITY_MOBILE + end + dissector_state = { + ['sender_entity'] = sender_entity + } + generic_dissect_root(json_tvb, pkt, subtree, dissector_state, plaintext_str, auth_message_finfos) -- Add operation to info column local operation = get_field_val_safe(fi_flow_op) if operation == nil then subtree:add_proto_expert_info(e_auth_no_op, "Opertion field missing from JSON") - operation = "NO OP !" + operation = "" end -- Append auth message type to info col pkt.cols.info:append(operation) + pkt.cols.info:fence() + pkt.cols.protocol:fence() -- Hand over data to JSON dissector json_dis(json_tvb,pkt,tree); + -- Clear usless column string added by json dissector + pkt.cols.info:clear() + pkt.cols.protocol:clear() end @@ -873,9 +888,9 @@ p_sam_flow_data.fields = { tcp_flags_psh = Field.new("tcp.flags.push") -- Used to hint the content of a data channel (as seen in the signaling in the 'flow private' connection) -data_channels_file_names_hints = { } +data_channels_file_infos_hints = { } -- Used to map the content of a data channel (as seen in the signaling in the 'flow private' connection) -data_channels_file_names = { } +data_channels_file_infos = { } -- Used to count amount of packets in every data channel so we avoid "heavy" ones -- Keys are ports, values are unique packet counters @@ -971,26 +986,201 @@ function p_sam_flow_data.dissector(buf, pkt, tree) local dec_json_ti = subtree:add(json_tvb:range(),"Decrypted Payload") -- Trying to get filename and show in tree - file_name = data_channels_file_names[pkt.src_port] - if not file_name then + local file_info = data_channels_file_infos[pkt.src_port] + if not file_info then -- table.remove is like Dequeue - file_name = table.remove(data_channels_file_names_hints) + file_info = table.remove(data_channels_file_infos_hints) -- Associate hinted file name with current TCP connection. - -- Next time this function runs the name will be retrieved from data_channels_file_names - data_channels_file_names[pkt.src_port] = file_name + -- Next time this function runs the name will be retrieved from data_channels_file_infos + data_channels_file_infos[pkt.src_port] = file_info end - subtree:add(f_data_file_name, file_name):set_generated() - pkt.cols.info:set("Contents of file '" .. file_name .. "'") + subtree:add(f_data_file_name, file_info.file_name):set_generated() + pkt.cols.info:set("[" .. entity_values[file_info.sender_entity] .. "] ") + pkt.cols.info:append("Contents of file '" .. file_info.file_name .. "'") end --- TransferCompletedDataContract Constants -F_TCDC_IS_SUCCESS = "isSuccess" -F_TCDC_SHARE_ID = "share_id" -F_TCDC_IS_SEND = "isSend" -F_TCDC_REMAIN_CNT = "remainCnt" + +local p_sam_flow_mirr = Proto("flow_mirroring", "Sam" .. "sung Flow Protocol Mirroring"); + +local f_mirr_flow_dummy = ProtoField.string("flow", "Dummy") + +local e_mirr_dec_missing_param = ProtoExpert.new("flow.exp.decmissingparam", "Missing Decryption Parameter", expert.group.DECRYPTION, expert.severity.NOTE) + +-- Mirror Base Message Constants (Manually Defined!) +F_MIRROR_BASE_MESSAG_TYPE = "TYPE" +F_MIRROR_BASE_MESSAG_MSG = "MSG" +F_MIRROR_BASE_MESSAG_PARAM = "PARAM" + +-- Mirror REQUEST_CONNECT Constants (Manually Defined!) +F_MIRROR_REQ_CON_PORT = "port" +F_MIRROR_REQ_CON_TYPE = "type" + +-- Mirror Base Message Field Definitions (Manually Defined!) +local f_mirr_protofields = { + f_mirr_type = ProtoField.string("flow.mirr.type", "Type"), + f_mirr_msg = ProtoField.string("flow.mirr.msg", "Message"), + f_mirr_param = ProtoField.string("flow.mirr.param", "Parameter"), + f_mirr_req_con_port = ProtoField.uint32("flow.mirr.req_con_port", "Port"), + f_mirr_req_con_type = ProtoField.string("flow.mirr.req_con_type", "Channel Type"), +} + +mirr_base_param_finfos = { + {F_MIRROR_REQ_CON_PORT, f_mirr_protofields.f_mirr_req_con_port, J_FIELD_TYPE_NUM}, + {F_MIRROR_REQ_CON_TYPE, f_mirr_protofields.f_mirr_req_con_type, J_FIELD_TYPE_STRING}, +} + +mirr_base_finfos = { + {F_MIRROR_BASE_MESSAG_TYPE, f_mirr_protofields.f_mirr_type, J_FIELD_TYPE_STRING}, + {F_MIRROR_BASE_MESSAG_MSG, f_mirr_protofields.f_mirr_msg, J_FIELD_TYPE_STRING}, + {F_MIRROR_BASE_MESSAG_PARAM, f_mirr_protofields.f_mirr_param, J_FIELD_TYPE_OBJ, mirr_base_param_finfos}, +} + + +p_sam_flow_mirr.experts = { + e_mirr_dec_missing_param +} + +p_sam_flow_mirr.fields = { + f_mirr_flow_dummy, + f_mirr_protofields.f_mirr_type, + f_mirr_protofields.f_mirr_msg, + f_mirr_protofields.f_mirr_param, +} + +-- Tables to be updated at runtime +known_pc_mirror_signaling_ports = {} +known_pc_mirror_data_ports = {} + +function p_sam_flow_mirr.dissector(buf, pkt, tree) + pkt.cols['protocol'] = 'FLOW-MIRROR' + is_data_port = known_pc_mirror_data_ports[pkt.src_port] ~= nil or known_pc_mirror_data_ports[pkt.dst_port] ~= nil + -- Reassembly logic before we do anything with the protocol tree + if(buf:len() >= 4) then + -- Reading 'length' field (first 4 bytes) + -- Note this bullsh*t: Length here is in LITTLE ENDIAN where in FLOW-PRIV it's in BIG ENDIAN... + expected_payload_len = buf:range(0,4):le_uint() + if is_data_port then + -- Note this bullsh*t: Length in main channel does NOT include itself (4 bytes integery) + -- but in sub-channels (audio, video,... ) it does + expected_payload_len = expected_payload_len - 4 + end + actual_payload_len = buf:len() - 4 + if actual_payload_len < expected_payload_len then + -- Did not reassemble all data yet, request TCP to give us more bytes + pkt.desegment_offset = 0 + pkt.desegment_len = expected_payload_len - actual_payload_len + return tvbuf:len() + end + -- Else case: We have a complete message and we can continue parsing below + else + -- we DON'T have enough bytes for 'length' field (4 bytes) + -- asking from TCP for more bytes + pkt.desegment_offset = 0 + pkt.desegment_len = DESEGMENT_ONE_MORE_SEGMENT + return tvbuf:len() + end + + pkt.cols['protocol'] = 'FLOW-MIRROR' + + local subtree = tree:add(p_sam_flow_mirr, buf:range()) + -- Adding dummy so we can filter with 'flow' + subtree:add(f_mirr_flow_dummy):set_hidden() + + + -- Got all data! Time to decrypt + + -- Making the rest of the TCP payload, skipping the 10-bytes header, into a string + -- (AES works with strings, even if they contain non-printable chars) + local header_len = 4 + subtree:add(buf:range(header_len), "Encrypted Payload") + local encrypted_str = get_string_from_tvbuf(buf, header_len) + + -- Padding data to the nearest multiply of 16 + local paddedData = encrypted_str + local i = #encrypted_str + while(i%16 ~= 0) + do + paddedData = paddedData .. "\x00" + i = i + 1 + end + + local sender_entity = ENTITY_MOBILE + if(known_pc_mirror_signaling_ports[pkt.src_port]) then + sender_entity = ENTITY_PC + end + pkt.cols.info:set("[" .. entity_values[sender_entity] .. "] ") + + -- Getting Key & IV from prefrences + key = string.fromhex(global_flow_settings.key) + local keyBytes = {string.byte(key,1,#key)} + + iv = string.fromhex(global_flow_settings.iv) + local ivBytes = {string.byte(iv,1,#iv)} + + if #key ~= 16 or #iv ~= 16 then + pkt.cols.info:append('[Encrypted Private Mirroring Channel]') + if #key == 0 then + subtree:add_proto_expert_info(e_data_dec_missing_param,"Data is encrypted and a key was not set in the preferences.") + elseif #iv == 0 then + subtree:add_proto_expert_info(e_data_dec_missing_param,"Data is encrypted and an iv was not set in the preferences.") + else + subtree:add_proto_expert_info(e_data_dec_missing_param,"Data is encrypted and a key/iv from the preferences was not 16 bytes in hex. " .. tostring(#key) .. ", " .. tostring(#iv)) + end + return + end + + -- Can try to decrypt + local decrypted_str = ciphermode.decryptString(subtree,keyBytes, paddedData, ciphermode.decryptCTR, ivBytes) + -- Removing the "decrypted" padding bytes + decrypted_str = string.sub(decrypted_str,0,#encrypted_str) + + -- Creating new data source from the ASCII JSON we got as a result + local json_bytes = ByteArray.new(decrypted_str, true) + local json_tvb = json_bytes:tvb("Decrypted Payload") + local dec_json_ti = subtree:add(json_tvb:range(),"Decrypted Payload") + + -- Checking if this is the "singaling" Mirroring channel. + -- If it is, the payload is JSON + -- If it isn't, we don't know how to parse it (yet) + if is_data_port then + channel_type = known_pc_mirror_data_ports[pkt.src_port] + if channel_type == nil then + channel_type = known_pc_mirror_data_ports[pkt.dst_port] + end + pkt.cols.info:append(channel_type) + else + -- Dissect JSON structure + dissector_state = { + ['is_mirroring_packet'] = true, + ['sender_entity'] = sender_entity + } + generic_dissect_root(json_tvb, pkt, subtree, dissector_state, decrypted_str, mirr_base_finfos) + + if dissector_state['channel_type'] ~= nil and dissector_state['port'] ~= nil then + pkt.cols.info:append("Setting up channel '" .. dissector_state['channel_type'] .. "' on port " .. dissector_state['port']) + tcp_port_table = DissectorTable.get("tcp.port") + tcp_port_table:add(dissector_state['port'], p_sam_flow_mirr) + known_pc_mirror_data_ports[dissector_state['port']] = dissector_state['channel_type'] + end + + pkt.cols.info:fence() + pkt.cols.protocol:fence() + -- Hand over data to JSON dissector + json_dis(json_tvb,pkt,tree); + -- Clear usless column string added by json dissector + pkt.cols.info:clear() + pkt.cols.protocol:clear() + end +end + + +-- TransferStartDataContract Constants +F_TSDC_SHARE_ID = "share_id" +F_TSDC_OFFSET = "offset" +F_TSDC_REMAIN_CNT = "remainCnt" -- HotspotDataContract Constants F_HDC_RESULT = "RESULT" @@ -1024,6 +1214,12 @@ F_MIDC_VERSION = "version" F_TDC_TITLE = "title" F_TDC_BODY = "body" +-- TransferCompletedDataContract Constants +F_TCDC_IS_SUCCESS = "isSuccess" +F_TCDC_SHARE_ID = "share_id" +F_TCDC_IS_SEND = "isSend" +F_TCDC_REMAIN_CNT = "remainCnt" + -- AlarmDataContract Constants F_ADC_S_NAME = "sName" F_ADC_S_TIME = "sTime" @@ -1031,10 +1227,9 @@ F_ADC_S_ALERT_TIME = "sAlertTime" F_ADC_S_ALARM_STATUS = "sAlarmStatus" F_ADC_B_SZ_ACTIVE = "bSzActive" --- TransferStartDataContract Constants -F_TSDC_SHARE_ID = "share_id" -F_TSDC_OFFSET = "offset" -F_TSDC_REMAIN_CNT = "remainCnt" +-- WiDiStatusDataContract Constants +F_WDSDC_STATUS = "status" +F_WDSDC_GROUP_NAME = "groupName" -- CallDataContract Constants F_CDC_B_VIDEO_CALL_FLAG = "bVideoCallFlag" @@ -1044,9 +1239,6 @@ F_CDC_S_CALL_STATE = "sCallState" F_CDC_S_NUMBER_TYPE = "sNumberType" F_CDC_S_USER_ICON = "sUserIcon" --- HdmiDataContract Constants -F_HDC2_IS_CONNECTED = "isConnected" - -- FileDataContract Constants F_FDC_FILE_NAME = "fileName" F_FDC_FILE_SIZE = "fileSize" @@ -1062,9 +1254,11 @@ F_SSIDC_TYPE = "type" F_SSIDC_ADDRESS = "address" F_SSIDC_PORT = "port" --- WiDiStatusDataContract Constants -F_WDSDC_STATUS = "status" -F_WDSDC_GROUP_NAME = "groupName" +-- SMPInfoDataContract Constants +F_SMPIDC_TOKEN = "token" + +-- HdmiDataContract Constants +F_HDC2_IS_CONNECTED = "isConnected" -- ClipboardSyncDataContract Constants F_CSDC_IS_SYNC = "isSync" @@ -1111,6 +1305,7 @@ F_NDC_MMS_CONTENTS_DATA = "MMSContentsData" F_NDC_IS_SUCCESS_GETTING_MESSAGE = "isSuccessGettingMessage" F_NDC_HAS_SOUND = "hasSound" F_NDC_HAS_VIBRATE = "hasVibrate" +F_NDC_IS_ALARM_OFF = "isAlarmOff" -- TransferDataContract Constants F_TDC2_CONTENT_TYPE = "contentType" @@ -1148,6 +1343,7 @@ F_FMB_CLIPBOARD_SYNC_DATA = "clipboardSyncData" F_FMB_DRAG_START_DATA = "dragStartData" F_FMB_REMOTE_DEVICE_DATA = "remoteDeviceData" F_FMB_SOCKET_SERVER_INFO_DATA = "socketServerInfoData" +F_FMB_SMP_INFO_DATA = "smpInfoData" -- FlowMessage Constants F_FM_CMD = "CMD" @@ -1165,11 +1361,10 @@ local f_private_totallen = ProtoField.uint32("flow.totallen", "Total Length", ba local f_private_type = ProtoField.uint16("flow.type", "Type", base.DEC) local f_private_jsonlen = ProtoField.uint32("flow.jsonlen", "JSON Length", base.DEC) --- TransferCompletedDataContract Field Definitions -local f_body_tcdc_is_success = ProtoField.string("flow.transfer_completed_data_contract.is_success", "Is Success") -local f_body_tcdc_share_id = ProtoField.string("flow.transfer_completed_data_contract.share_id", "Share Id") -local f_body_tcdc_is_send = ProtoField.string("flow.transfer_completed_data_contract.is_send", "Is Send") -local f_body_tcdc_remain_cnt = ProtoField.string("flow.transfer_completed_data_contract.remain_cnt", "Remain Cnt") +-- TransferStartDataContract Field Definitions +local f_body_tsdc_share_id = ProtoField.string("flow.transfer_start_data_contract.share_id", "Share Id") +local f_body_tsdc_offset = ProtoField.string("flow.transfer_start_data_contract.offset", "Offset") +local f_body_tsdc_remain_cnt = ProtoField.string("flow.transfer_start_data_contract.remain_cnt", "Remain Cnt") -- HotspotDataContract Field Definitions local f_body_hdc_result = ProtoField.string("flow.hotspot_data_contract.result", "RESULT") @@ -1203,6 +1398,12 @@ local f_body_midc_version = ProtoField.string("flow.mirroring_info_data_contract local f_body_tdc_title = ProtoField.string("flow.text_data_contract.title", "Title") local f_body_tdc_body = ProtoField.string("flow.text_data_contract.body", "Body") +-- TransferCompletedDataContract Field Definitions +local f_body_tcdc_is_success = ProtoField.string("flow.transfer_completed_data_contract.is_success", "Is Success") +local f_body_tcdc_share_id = ProtoField.string("flow.transfer_completed_data_contract.share_id", "Share Id") +local f_body_tcdc_is_send = ProtoField.string("flow.transfer_completed_data_contract.is_send", "Is Send") +local f_body_tcdc_remain_cnt = ProtoField.string("flow.transfer_completed_data_contract.remain_cnt", "Remain Cnt") + -- AlarmDataContract Field Definitions local f_body_adc_s_name = ProtoField.string("flow.alarm_data_contract.s_name", "S Name") local f_body_adc_s_time = ProtoField.string("flow.alarm_data_contract.s_time", "S Time") @@ -1210,10 +1411,9 @@ local f_body_adc_s_alert_time = ProtoField.string("flow.alarm_data_contract.s_al local f_body_adc_s_alarm_status = ProtoField.string("flow.alarm_data_contract.s_alarm_status", "S Alarm Status") local f_body_adc_b_sz_active = ProtoField.string("flow.alarm_data_contract.b_sz_active", "B Sz Active") --- TransferStartDataContract Field Definitions -local f_body_tsdc_share_id = ProtoField.string("flow.transfer_start_data_contract.share_id", "Share Id") -local f_body_tsdc_offset = ProtoField.string("flow.transfer_start_data_contract.offset", "Offset") -local f_body_tsdc_remain_cnt = ProtoField.string("flow.transfer_start_data_contract.remain_cnt", "Remain Cnt") +-- WiDiStatusDataContract Field Definitions +local f_body_wdsdc_status = ProtoField.string("flow.wi_di_status_data_contract.status", "Status") +local f_body_wdsdc_group_name = ProtoField.string("flow.wi_di_status_data_contract.group_name", "Group Name") -- CallDataContract Field Definitions local f_body_cdc_b_video_call_flag = ProtoField.string("flow.call_data_contract.b_video_call_flag", "B Video Call Flag") @@ -1223,9 +1423,6 @@ local f_body_cdc_s_call_state = ProtoField.string("flow.call_data_contract.s_cal local f_body_cdc_s_number_type = ProtoField.string("flow.call_data_contract.s_number_type", "S Number Type") local f_body_cdc_s_user_icon = ProtoField.string("flow.call_data_contract.s_user_icon", "S User Icon") --- HdmiDataContract Field Definitions -local f_body_hdc2_is_connected = ProtoField.string("flow.hdmi_data_contract.is_connected", "Is Connected") - -- FileDataContract Field Definitions local f_body_fdc_file_name = ProtoField.string("flow.file_data_contract.file_name", "File Name") local f_body_fdc_file_size = ProtoField.string("flow.file_data_contract.file_size", "File Size") @@ -1241,9 +1438,11 @@ local f_body_ssidc_type = ProtoField.string("flow.socket_server_info_data_contra local f_body_ssidc_address = ProtoField.string("flow.socket_server_info_data_contract.address", "Address") local f_body_ssidc_port = ProtoField.string("flow.socket_server_info_data_contract.port", "Port") --- WiDiStatusDataContract Field Definitions -local f_body_wdsdc_status = ProtoField.string("flow.wi_di_status_data_contract.status", "Status") -local f_body_wdsdc_group_name = ProtoField.string("flow.wi_di_status_data_contract.group_name", "Group Name") +-- SMPInfoDataContract Field Definitions +local f_body_smpidc_token = ProtoField.string("flow.smp_info_data_contract.token", "Token") + +-- HdmiDataContract Field Definitions +local f_body_hdc2_is_connected = ProtoField.string("flow.hdmi_data_contract.is_connected", "Is Connected") -- ClipboardSyncDataContract Field Definitions local f_body_csdc_is_sync = ProtoField.string("flow.clipboard_sync_data_contract.is_sync", "Is Sync") @@ -1290,6 +1489,7 @@ local f_body_ndc_mms_contents_data = ProtoField.string("flow.notification_data_c local f_body_ndc_is_success_getting_message = ProtoField.string("flow.notification_data_contract.is_success_getting_message", "Is Success Getting Message") local f_body_ndc_has_sound = ProtoField.string("flow.notification_data_contract.has_sound", "Has Sound") local f_body_ndc_has_vibrate = ProtoField.string("flow.notification_data_contract.has_vibrate", "Has Vibrate") +local f_body_ndc_is_alarm_off = ProtoField.string("flow.notification_data_contract.is_alarm_off", "Is Alarm Off") -- TransferDataContract Field Definitions local f_body_tdc2_content_type = ProtoField.string("flow.transfer_data_contract.content_type", "Content Type") @@ -1327,6 +1527,7 @@ local f_body_fmb_clipboard_sync_data = ProtoField.string("flow.flow_message_body local f_body_fmb_drag_start_data = ProtoField.string("flow.flow_message_body.drag_start_data", "Drag Start Data") local f_body_fmb_remote_device_data = ProtoField.string("flow.flow_message_body.remote_device_data", "Remote Device Data") local f_body_fmb_socket_server_info_data = ProtoField.string("flow.flow_message_body.socket_server_info_data", "Socket Server Info Data") +local f_body_fmb_smp_info_data = ProtoField.string("flow.flow_message_body.smp_info_data", "Smp Info Data") -- FlowMessage Field Definitions local f_body_fm_cmd = ProtoField.string("flow.flow_message.cmd", "CMD") @@ -1343,11 +1544,10 @@ f_private_totallen, f_private_type, f_private_jsonlen, --- TransferCompletedDataContract Field Variables -f_body_tcdc_is_success, -f_body_tcdc_share_id, -f_body_tcdc_is_send, -f_body_tcdc_remain_cnt, +-- TransferStartDataContract Field Variables +f_body_tsdc_share_id, +f_body_tsdc_offset, +f_body_tsdc_remain_cnt, -- HotspotDataContract Field Variables f_body_hdc_result, @@ -1381,6 +1581,12 @@ f_body_midc_version, f_body_tdc_title, f_body_tdc_body, +-- TransferCompletedDataContract Field Variables +f_body_tcdc_is_success, +f_body_tcdc_share_id, +f_body_tcdc_is_send, +f_body_tcdc_remain_cnt, + -- AlarmDataContract Field Variables f_body_adc_s_name, f_body_adc_s_time, @@ -1388,10 +1594,9 @@ f_body_adc_s_alert_time, f_body_adc_s_alarm_status, f_body_adc_b_sz_active, --- TransferStartDataContract Field Variables -f_body_tsdc_share_id, -f_body_tsdc_offset, -f_body_tsdc_remain_cnt, +-- WiDiStatusDataContract Field Variables +f_body_wdsdc_status, +f_body_wdsdc_group_name, -- CallDataContract Field Variables f_body_cdc_b_video_call_flag, @@ -1401,9 +1606,6 @@ f_body_cdc_s_call_state, f_body_cdc_s_number_type, f_body_cdc_s_user_icon, --- HdmiDataContract Field Variables -f_body_hdc2_is_connected, - -- FileDataContract Field Variables f_body_fdc_file_name, f_body_fdc_file_size, @@ -1419,9 +1621,11 @@ f_body_ssidc_type, f_body_ssidc_address, f_body_ssidc_port, --- WiDiStatusDataContract Field Variables -f_body_wdsdc_status, -f_body_wdsdc_group_name, +-- SMPInfoDataContract Field Variables +f_body_smpidc_token, + +-- HdmiDataContract Field Variables +f_body_hdc2_is_connected, -- ClipboardSyncDataContract Field Variables f_body_csdc_is_sync, @@ -1468,6 +1672,7 @@ f_body_ndc_mms_contents_data, f_body_ndc_is_success_getting_message, f_body_ndc_has_sound, f_body_ndc_has_vibrate, +f_body_ndc_is_alarm_off, -- TransferDataContract Field Variables f_body_tdc2_content_type, @@ -1505,6 +1710,7 @@ f_body_fmb_clipboard_sync_data, f_body_fmb_drag_start_data, f_body_fmb_remote_device_data, f_body_fmb_socket_server_info_data, +f_body_fmb_smp_info_data, -- FlowMessage Field Variables f_body_fm_cmd, @@ -1541,12 +1747,11 @@ end known_mobile_priv_ports = {} --- TransferCompletedDataContract Field-Infos -tcdc_finfos = { - {F_TCDC_IS_SUCCESS, f_body_tcdc_is_success, J_FIELD_TYPE_BOOL}, - {F_TCDC_SHARE_ID, f_body_tcdc_share_id, J_FIELD_TYPE_STRING}, - {F_TCDC_IS_SEND, f_body_tcdc_is_send, J_FIELD_TYPE_BOOL}, - {F_TCDC_REMAIN_CNT, f_body_tcdc_remain_cnt, J_FIELD_TYPE_NUM}, +-- TransferStartDataContract Field-Infos +tsdc_finfos = { + {F_TSDC_SHARE_ID, f_body_tsdc_share_id, J_FIELD_TYPE_STRING}, + {F_TSDC_OFFSET, f_body_tsdc_offset, J_FIELD_TYPE_NUM}, + {F_TSDC_REMAIN_CNT, f_body_tsdc_remain_cnt, J_FIELD_TYPE_NUM}, } @@ -1597,6 +1802,15 @@ tdc_finfos = { } +-- TransferCompletedDataContract Field-Infos +tcdc_finfos = { + {F_TCDC_IS_SUCCESS, f_body_tcdc_is_success, J_FIELD_TYPE_BOOL}, + {F_TCDC_SHARE_ID, f_body_tcdc_share_id, J_FIELD_TYPE_STRING}, + {F_TCDC_IS_SEND, f_body_tcdc_is_send, J_FIELD_TYPE_BOOL}, + {F_TCDC_REMAIN_CNT, f_body_tcdc_remain_cnt, J_FIELD_TYPE_NUM}, + +} + -- AlarmDataContract Field-Infos adc_finfos = { {F_ADC_S_NAME, f_body_adc_s_name, J_FIELD_TYPE_STRING}, @@ -1607,11 +1821,10 @@ adc_finfos = { } --- TransferStartDataContract Field-Infos -tsdc_finfos = { - {F_TSDC_SHARE_ID, f_body_tsdc_share_id, J_FIELD_TYPE_STRING}, - {F_TSDC_OFFSET, f_body_tsdc_offset, J_FIELD_TYPE_NUM}, - {F_TSDC_REMAIN_CNT, f_body_tsdc_remain_cnt, J_FIELD_TYPE_NUM}, +-- WiDiStatusDataContract Field-Infos +wdsdc_finfos = { + {F_WDSDC_STATUS, f_body_wdsdc_status, J_FIELD_TYPE_STRING}, + {F_WDSDC_GROUP_NAME, f_body_wdsdc_group_name, J_FIELD_TYPE_STRING}, } @@ -1626,12 +1839,6 @@ cdc_finfos = { } --- HdmiDataContract Field-Infos -hdc2_finfos = { - {F_HDC2_IS_CONNECTED, f_body_hdc2_is_connected, J_FIELD_TYPE_BOOL}, - -} - -- FileDataContract Field-Infos fdc_finfos = { {F_FDC_FILE_NAME, f_body_fdc_file_name, J_FIELD_TYPE_STRING}, @@ -1656,10 +1863,15 @@ ssidc_finfos = { } --- WiDiStatusDataContract Field-Infos -wdsdc_finfos = { - {F_WDSDC_STATUS, f_body_wdsdc_status, J_FIELD_TYPE_STRING}, - {F_WDSDC_GROUP_NAME, f_body_wdsdc_group_name, J_FIELD_TYPE_STRING}, +-- SMPInfoDataContract Field-Infos +smpidc_finfos = { + {F_SMPIDC_TOKEN, f_body_smpidc_token, J_FIELD_TYPE_STRING}, + +} + +-- HdmiDataContract Field-Infos +hdc2_finfos = { + {F_HDC2_IS_CONNECTED, f_body_hdc2_is_connected, J_FIELD_TYPE_BOOL}, } @@ -1715,6 +1927,7 @@ ndc_finfos = { {F_NDC_IS_SUCCESS_GETTING_MESSAGE, f_body_ndc_is_success_getting_message, J_FIELD_TYPE_BOOL}, {F_NDC_HAS_SOUND, f_body_ndc_has_sound, J_FIELD_TYPE_BOOL}, {F_NDC_HAS_VIBRATE, f_body_ndc_has_vibrate, J_FIELD_TYPE_BOOL}, + {F_NDC_IS_ALARM_OFF, f_body_ndc_is_alarm_off, J_FIELD_TYPE_BOOL}, } @@ -1761,6 +1974,7 @@ fmb_finfos = { {F_FMB_DRAG_START_DATA, f_body_fmb_drag_start_data, J_FIELD_TYPE_OBJ, dsdc_finfos}, {F_FMB_REMOTE_DEVICE_DATA, f_body_fmb_remote_device_data, J_FIELD_TYPE_OBJ, rddc_finfos}, {F_FMB_SOCKET_SERVER_INFO_DATA, f_body_fmb_socket_server_info_data, J_FIELD_TYPE_OBJ, ssidc_finfos}, + {F_FMB_SMP_INFO_DATA, f_body_fmb_smp_info_data, J_FIELD_TYPE_OBJ, smpidc_finfos}, } @@ -1882,65 +2096,121 @@ function p_samsung_flow_priv.dissector(buf, pkt, tree) local json_text = res - generic_dissect_root(json_tvb, pkt, subtree, json_text, fm_finfos ) + local sender_entity = ENTITY_PC + if(known_mobile_priv_ports[pkt.src_port]) then + sender_entity = ENTITY_MOBILE + end + dissector_state = { + ['sender_entity'] = sender_entity + } + generic_dissect_root(json_tvb, pkt, subtree, dissector_state, json_text, fm_finfos ) + pkt.cols.info:fence() + pkt.cols.protocol:fence() -- Hand over data to JSON dissector json_dis(json_tvb,pkt,tree); + -- Clear usless column string added by json dissector + pkt.cols.info:clear() + pkt.cols.protocol:clear() end -- Post/Pre fields delegates - -function CMD_post(buf, pkt, subtree, text, json_field_info, parsed_value, created_ti) +-- Function arguments documentation: +-- buf - Current TVBUF +-- pkt - Pinfo +-- subtree - Parent TreeItem +-- dissector_state - General purpose dictionary used to pass information between JSON fields the othe "outter" dissector (PRIV, MIRROR ,...) +-- Predefined keys: +-- "sender_entity" - Sending entity, either ENTITY_PC or ENTITY_MOBILE +-- text - string, ASCII extracted from the JSON for current field +-- json_field_info - JSON 'finfo' as described in this file. It's a table with inner fields details +-- parsed_value - [_post ONLY] parsed value depending on the JSON field type (number, string, etc...) +-- created_ti - [_post ONLY] Created TreeItem for this field + +function CMD_post(buf, pkt, subtree, dissector_state, text, json_field_info, parsed_value, created_ti) -- Adding command type to INFO column pkt.cols.info:append(parsed_value) end -function notificationData_pre(buf, pkt, subtree, text, json_field_info) +function notificationData_pre(buf, pkt, subtree, dissector_state, text, json_field_info) -- Adding '(' to INFO column pkt.cols.info:append(' (') end -function notificationData_post(buf, pkt, subtree, text, json_field_info) +function notificationData_post(buf, pkt, subtree, dissector_state, text, json_field_info) -- Adding ')' to INFO column pkt.cols.info:append(')') end -function applicationName_post(buf, pkt, subtree, text, json_field_info, parsed_value, created_ti) +function applicationName_post(buf, pkt, subtree, dissector_state, text, json_field_info, parsed_value, created_ti) pkt.cols.info:append('App: "' .. parsed_value .. '"') end -function title_post(buf, pkt, subtree, text, json_field_info, parsed_value, created_ti) +function title_post(buf, pkt, subtree, dissector_state, text, json_field_info, parsed_value, created_ti) pkt.cols.info:append(' Title: "' .. parsed_value .. '"') end -- 3 Functions below allow recognizing ports in 'SocketServerInfoData' field so we can call flow_data dissector -is_in_sockData = false -function socketServerInfoData_pre(buf, pkt, subtree, text, json_field_info, parsed_value, created_ti) - is_in_sockData = true; +function socketServerInfoData_pre(buf, pkt, subtree, dissector_state, text, json_field_info, parsed_value, created_ti) + dissector_state['is_in_sockData'] = true; end -function socketServerInfoData_post(buf, pkt, subtree, text, json_field_info, parsed_value, created_ti) - is_in_sockData = false; +function socketServerInfoData_post(buf, pkt, subtree, dissector_state, text, json_field_info, parsed_value, created_ti) + dissector_state['is_in_sockData'] = false; end -function port_post(buf, pkt, subtree, text, json_field_info, parsed_value, created_ti) - if is_in_sockData and parsed_value ~= nil then +function port_post(buf, pkt, subtree, dissector_state, text, json_field_info, parsed_value, created_ti) + if dissector_state['is_in_sockData'] and parsed_value ~= nil then tcp_port_table = DissectorTable.get("tcp.port") tcp_port_table:add(parsed_value, p_sam_flow_data) end + if dissector_state['is_mirroring_packet'] then + dissector_state['port'] = parsed_value + end end --- 3 Functions below allow passing file name to data channel (different TCP connection from the signaling (private) channel we are on) -is_in_fileInfo = false; -function fileInfoData_pre(buf, pkt, subtree, text, json_field_info, parsed_value, created_ti) - is_in_fileInfo = true; +-- 3 Functions below allow passing file name & sender to data channel (different TCP connection from the signaling (private) channel we are on) +function fileInfoData_pre(buf, pkt, subtree, dissector_state, text, json_field_info, parsed_value, created_ti) + dissector_state['is_in_fileInfo'] = true; end -function fileInfoData_post(buf, pkt, subtree, text, json_field_info, parsed_value, created_ti) - is_in_fileInfo = false; +function fileInfoData_post(buf, pkt, subtree, dissector_state, text, json_field_info, parsed_value, created_ti) + dissector_state['is_in_fileInfo'] = false; end -function fileName_post(buf, pkt, subtree, text, json_field_info, parsed_value, created_ti) - if is_in_fileInfo and parsed_value ~= nil then +function fileName_post(buf, pkt, subtree, dissector_state, text, json_field_info, parsed_value, created_ti) + if dissector_state['is_in_fileInfo'] and parsed_value ~= nil then -- table.insert is like Enqueue - table.insert(data_channels_file_names_hints, parsed_value) + table.insert(data_channels_file_infos_hints, + { + ['file_name'] = parsed_value, + ['sender_entity'] = dissector_state['ender_entity'] + } + ) + end +end + +-- Mirroring channel association +function mainPortNum_post(buf, pkt, subtree, dissector_state, text, json_field_info, parsed_value, created_ti) + tcp_port_table = DissectorTable.get("tcp.port") + tcp_port_table:add(parsed_value, p_sam_flow_mirr) + known_pc_mirror_signaling_ports[parsed_value] = true +end + + +-- Adding Mirroring Message field to info column +function TYPE_post(buf, pkt, subtree, dissector_state, text, json_field_info, parsed_value, created_ti) + if dissector_state['is_mirroring_packet'] then + pkt.cols.info:append('[' .. parsed_value .. ']') + end +end + +function MSG_post(buf, pkt, subtree, dissector_state, text, json_field_info, parsed_value, created_ti) + if dissector_state['is_mirroring_packet'] then + pkt.cols.info:append('(' .. parsed_value .. ') ') + end +end + +function type_post(buf, pkt, subtree, dissector_state, text, json_field_info, parsed_value, created_ti) + if dissector_state['is_mirroring_packet'] then + dissector_state['channel_type'] = parsed_value end end @@ -2055,8 +2325,13 @@ function p_sam_flow_bc.dissector(buf, pkt, tree) end tcp_port_table:add(auth_port, p_sam_flow_auth) + pkt.cols.info:fence() + pkt.cols.protocol:fence() -- Hand over data to JSON dissector json_dis(json_tvb,pkt,tree); + -- Clear usless column string added by json dissector + pkt.cols.info:clear() + pkt.cols.protocol:clear() end