From 2c4258016fe63b726b16f4d74de5c111e28c03f3 Mon Sep 17 00:00:00 2001 From: Peter Wu Date: Wed, 21 Dec 2016 16:00:07 +0100 Subject: file-zip: WIP for data descriptor Well, this does not work because the actual data size is unknown... And it turns out that you really have to parse the EoCD first, otherwise .jar files cannot be parsed... --- lua/file-zip.lua | 72 ++++++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 60 insertions(+), 12 deletions(-) diff --git a/lua/file-zip.lua b/lua/file-zip.lua index 241142c..ee23087 100644 --- a/lua/file-zip.lua +++ b/lua/file-zip.lua @@ -43,7 +43,11 @@ make_fields("zip_archive", { entry = { _ = {ProtoField.none, "File entry"}, version = {ProtoField.uint16, base.DEC}, - flag = {ProtoField.uint16, base.HEX}, + flag = { + _ = {ProtoField.uint16, "General purpose bit flag", base.HEX}, + -- TODO fi wslua documentation, it is wrong. + has_data_desc = {ProtoField.bool, 16, nil, 0x0008, "Whether data descriptor is present"}, + }, comp_method = {ProtoField.uint16, base.HEX}, lastmod_time = {ProtoField.uint16, base.HEX}, lastmod_date = {ProtoField.uint16, base.HEX}, @@ -55,6 +59,12 @@ make_fields("zip_archive", { filename = {ProtoField.string}, extra = {ProtoField.bytes}, data = {ProtoField.bytes}, + data_desc = { + _ = {ProtoField.none, "Data descriptor"}, + crc32 = {ProtoField.uint32, base.HEX}, + size_comp = {ProtoField.uint32, base.DEC}, + size_uncomp = {ProtoField.uint32, base.DEC}, + }, }, cd = { _ = {ProtoField.none, "Central Directory Record"}, @@ -90,9 +100,6 @@ make_fields("zip_archive", { }, }, hf, proto_zip.fields) -local function dissect_entry(tvb, pinfo, tree) -end - local function dissect_one(tvb, offset, pinfo, tree) local orig_offset = offset local magic = tvb(offset, 4):le_int() @@ -101,7 +108,9 @@ local function dissect_one(tvb, offset, pinfo, tree) -- header subtree:add_le(hf.signature, tvb(offset, 4)) subtree:add_le(hf.entry.version, tvb(offset + 4, 2)) - subtree:add_le(hf.entry.flag, tvb(offset + 6, 2)) + local flgtree = subtree:add_le(hf.entry.flag._, tvb(offset + 6, 2)) + -- TODO why does flag.has_data_desc segfault if tvb is not given? + flgtree:add_le(hf.entry.flag.has_data_desc, tvb(offset + 6, 2)) subtree:add_le(hf.entry.comp_method, tvb(offset + 8, 2)) subtree:add_le(hf.entry.lastmod_time, tvb(offset + 10, 2)) subtree:add_le(hf.entry.lastmod_date, tvb(offset + 12, 2)) @@ -110,19 +119,56 @@ local function dissect_one(tvb, offset, pinfo, tree) subtree:add_le(hf.entry.size_uncomp, tvb(offset + 22, 4)) subtree:add_le(hf.entry.filename_len, tvb(offset + 26, 2)) subtree:add_le(hf.entry.extra_len, tvb(offset + 28, 2)) + local flag = tvb(offset + 6, 2):le_uint() local data_len = tvb(offset + 18, 2):le_uint() local filename_len = tvb(offset + 26, 2):le_uint() local extra_len = tvb(offset + 28, 2):le_uint() + -- Optional data descriptor follows data if GP flag bit 3 (0x8) is set + --[[ This is wrong, cannot know the location of dd, have to query CD first + local ddlen + if bit.band(flag, 8) ~= 0 then + local dd_offset = offset + 30 + filename_len + extra_len + data_len + if tvb(dd_offset, 4):le_uint() == 0x08074b50 then + -- Optional data descriptor signature... WTF, why?! + dd_offset = dd_offset + 4 + ddlen = 16 + else + ddlen = 12 + end + subtree:add_le(hf.entry.data_desc.size_comp, tvb(dd_offset + 4, 4)) + --data_len = tvb(dd_offset + 4, 4):le_uint() + end + --]] + -- skip header offset = offset + 30 subtree:add(hf.entry.filename, tvb(offset, filename_len)) subtree:append_text(": " .. tvb(offset, filename_len):string()) offset = offset + filename_len - subtree:add(hf.entry.extra, tvb(offset, extra_len)) - offset = offset + extra_len - subtree:add(hf.entry.data, tvb(offset, data_len)) - offset = offset + data_len + if extra_len > 0 then + subtree:add(hf.entry.extra, tvb(offset, extra_len)) + offset = offset + extra_len + end + if data_len > 0 then + subtree:add(hf.entry.data, tvb(offset, data_len)) + offset = offset + data_len + end + --[[ This does need really work.. + -- Optional data descriptor header + if ddlen then + local dd_offset = offset + local ddtree = subtree:add_le(hf.entry.data_desc._, tvb(dd_offset, ddlen)) + if ddlen == 16 then + ddtree:add_le(hf.signature, tvb(dd_offset, 4)) + dd_offset = dd_offset + 4 + end + ddtree:add_le(hf.entry.data_desc.crc32, tvb(dd_offset, 4)) + ddtree:add_le(hf.entry.data_desc.size_comp, tvb(dd_offset + 4, 4)) + ddtree:add_le(hf.entry.data_desc.size_uncomp, tvb(dd_offset + 8, 4)) + offset = offset + ddlen + end + --]] subtree:set_len(offset - orig_offset) return offset @@ -154,8 +200,10 @@ local function dissect_one(tvb, offset, pinfo, tree) subtree:add(hf.cd.filename, tvb(offset, filename_len)) subtree:append_text(": " .. tvb(offset, filename_len):string()) offset = offset + filename_len - subtree:add(hf.cd.extra, tvb(offset, extra_len)) - offset = offset + extra_len + if extra_len > 0 then + subtree:add(hf.cd.extra, tvb(offset, extra_len)) + offset = offset + extra_len + end if comment_len > 0 then subtree:add(hf.cd.comment, tvb(offset, comment_len)) offset = offset + comment_len @@ -192,7 +240,7 @@ function proto_zip.dissector(tvb, pinfo, tree) --pinfo.cols.info = "" local next_offset = 0 - while next_offset < tvb:len() do + while next_offset and next_offset < tvb:len() do next_offset = dissect_one(tvb, next_offset, pinfo, tree) end return next_offset -- cgit v1.2.1