summaryrefslogtreecommitdiff
path: root/lua
diff options
context:
space:
mode:
authorPeter Wu <peter@lekensteyn.nl>2016-12-21 13:50:02 +0100
committerPeter Wu <peter@lekensteyn.nl>2016-12-21 13:50:02 +0100
commit0361a63465aaf41c21faf4e9cb4c4bf906bb9e08 (patch)
tree97d553bf075b4b19045aa2c819ff88f2f76d088f /lua
parentbad766a9ef81f7267cdb8e4f82db692a83ba2f9a (diff)
downloadwireshark-notes-0361a63465aaf41c21faf4e9cb4c4bf906bb9e08.tar.gz
file-zip: decode local file header
Diffstat (limited to 'lua')
-rw-r--r--lua/file-zip.lua105
1 files changed, 104 insertions, 1 deletions
diff --git a/lua/file-zip.lua b/lua/file-zip.lua
index aec8ac0..3a8c465 100644
--- a/lua/file-zip.lua
+++ b/lua/file-zip.lua
@@ -1,19 +1,122 @@
--
-- Zip Archive dissector
-- Author: Peter Wu <peter@lekensteyn.nl>
+--
+-- Spec: https://en.wikipedia.org/wiki/Zip_(file_format)#File_headers
+--
--
-- Dissection of Zip file contents
--
+-- takes a table where keys are the field names and values are descriptions of
+-- fields. If a value is a table without numeric indicdes, assume that it is a
+-- nested tree.
+local function make_fields(field_abbr_prefix, field_defs, hfs_out, hfs_list_out)
+ for name, params in pairs(field_defs) do
+ if #params == 0 then
+ -- Assume nested table, flatten it
+ hfs_out[name] = {}
+ make_fields(field_abbr_prefix .. name .. ".", params,
+ hfs_out[name], hfs_list_out)
+ else
+ local proto_field_constructor = params[1]
+ local field_abbr = field_abbr_prefix .. name
+ local field
+ if type(params[2]) == "string" then
+ -- Name was given, use it
+ field = proto_field_constructor(field_abbr, unpack(params, 2))
+ else
+ -- Name was not given, use field name (the suffix)
+ field = proto_field_constructor(field_abbr, name, unpack(params, 2))
+ end
+ hfs_out[name] = field
+ table.insert(hfs_list_out, field)
+ end
+ end
+end
+
local proto_zip = Proto.new("zip_archive", "Zip Archive")
+local hf = {}
+make_fields("zip_archive", {
+ signature = {ProtoField.uint32, base.HEX},
+ entry = {
+ _ = {ProtoField.none, "File entry"},
+ version = {ProtoField.uint16, base.DEC},
+ flag = {ProtoField.uint16, base.HEX},
+ comp_method = {ProtoField.uint16, base.HEX},
+ mod_time = {ProtoField.uint16, base.HEX},
+ mod_date = {ProtoField.uint16, base.HEX},
+ crc32 = {ProtoField.uint32, base.HEX},
+ size_comp = {ProtoField.uint32, base.DEC},
+ size_uncomp = {ProtoField.uint32, base.DEC},
+ filename_len = {ProtoField.uint16, base.DEC},
+ extra_len = {ProtoField.uint16, base.DEC},
+ filename = {ProtoField.string},
+ extra = {ProtoField.bytes},
+ data = {ProtoField.bytes},
+ },
+ cd = {
+ _ = {ProtoField.none, "Central Directory Record"}
+ },
+}, 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()
+ if magic == 0x04034b50 then -- File entry
+ local subtree = tree:add_le(hf.entry._, tvb(offset, 30))
+ -- 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))
+ subtree:add_le(hf.entry.comp_method, tvb(offset + 8, 2))
+ subtree:add_le(hf.entry.mod_time, tvb(offset + 10, 2))
+ subtree:add_le(hf.entry.mod_date, tvb(offset + 12, 2))
+ subtree:add_le(hf.entry.crc32, tvb(offset + 14, 4))
+ subtree:add_le(hf.entry.size_comp, tvb(offset + 18, 4))
+ 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 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()
+
+ -- 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
+
+ subtree:set_len(offset - orig_offset)
+ return offset
+ elseif magic == 0x02014b50 then -- Central Directory
+ local subtree = tree:add_le(hf.cd._, tvb(offset, 30))
+ elseif tvb:raw(offset, 2) == "PK" then
+ -- Unknown signature
+ tree:add_le(hf.signature, tvb(offset, 4))
+ end
+end
function proto_zip.dissector(tvb, pinfo, tree)
pinfo.cols.protocol = "zip"
--pinfo.cols.info = ""
+
+ local next_offset = 0
+ while next_offset do
+ next_offset = dissect_one(tvb, next_offset, pinfo, tree)
+ end
+ return next_offset
end
-function zip_heur(tvb, pinfo, tree)
+local function zip_heur(tvb, pinfo, tree)
if tvb:raw(0, 2) ~= "PK" then
return false
end