From 8d4d5b977f4b7c09999c1aea50df94ef8fe93ff3 Mon Sep 17 00:00:00 2001 From: dmiller Date: Thu, 20 Sep 2018 04:05:00 +0000 Subject: [PATCH] Remove more bin.lua packings --- nselib/amqp.lua | 25 ++++++++++----------- nselib/mqtt.lua | 49 +++++++++++++++++++--------------------- nselib/ndmp.lua | 31 +++++++++++++------------- nselib/sslv2.lua | 52 +++++++++++++++++++++---------------------- nselib/xdmcp.lua | 58 ++++++++++++++++++++++++++---------------------- 5 files changed, 107 insertions(+), 108 deletions(-) diff --git a/nselib/amqp.lua b/nselib/amqp.lua index 23aaf8905..5ee65cd08 100644 --- a/nselib/amqp.lua +++ b/nselib/amqp.lua @@ -22,10 +22,10 @@ -- Created 05/04/2011 - v0.1 - created by Sebastian Dragomir -local bin = require "bin" local match = require "match" local nmap = require "nmap" local stdnse = require "stdnse" +local string = require "string" local table = require "table" _ENV = stdnse.module("amqp", stdnse.seeall); @@ -93,7 +93,7 @@ AMQP = { end read = read + 1 - tmp = select( 2, bin.unpack("C", tmp) ) + tmp = string.unpack("B", tmp) status, key = self.amqpsocket:receive_buf(match.numbytes(tmp), true) if ( not(status) ) then return status, "ERROR: AMQP:handshake connection closed unexpectedly while reading key", nil @@ -114,7 +114,7 @@ AMQP = { read = read + 4 value = {} - tmp = select( 2, bin.unpack(">I", tmp) ) + tmp = string.unpack(">I4", tmp) status, err, value = self:decodeTable(value, tmp) read = read + tmp table.insert(tbl, key .. ": ") @@ -157,7 +157,7 @@ AMQP = { end read = read + 4 - tmp = select( 2, bin.unpack(">I", tmp) ) + tmp = string.unpack(">I4", tmp) status, value = self.amqpsocket:receive_buf(match.numbytes(tmp), true) if ( not(status) ) then @@ -183,7 +183,7 @@ AMQP = { return status, "ERROR: AMQP:handshake connection closed unexpectedly while reading value for " .. key, nil, 0 end - value = select( 2, bin.unpack("C", value) ) + value = string.unpack("B", value) read = read + 1 return true, nil, value == 0x01 and "YES" or "NO", read @@ -210,14 +210,14 @@ AMQP = { -- check if the server rejected our proposed version if ( #tmp ~= 11 ) then - if ( #tmp == 8 and select( 2, bin.unpack(">I", tmp) ) == 0x414D5150 ) then + if ( #tmp == 8 and string.unpack(">I4", tmp) == 0x414D5150 ) then local vi, vii, v1, v2, v3, v4, found - _, vi = bin.unpack(">I", tmp, 5) + vi = string.unpack(">I4", tmp, 5) found = false -- check if we support the server's version for _, v in pairs( self.client_version_strings ) do - _, vii = bin.unpack(">I", v) + vii = string.unpack(">I4", v) if ( vii == vi ) then version = v found = true @@ -239,7 +239,7 @@ AMQP = { end -- version unsupported - _, v1, v2, v3, v4 = bin.unpack(">CCCC", tmp, 5) + v1, v2, v3, v4 = string.unpack(">BBBB", tmp, 5) return false, ("ERROR: AMQP:handshake unsupported version (%d.%d.%d.%d)"):format( v1, v2, v3, v4 ) else return false, ("ERROR: AMQP:handshake server might not be AMQP, received: %s"):format( tmp ) @@ -247,8 +247,7 @@ AMQP = { end -- parse frame header - local frametype, chnumber, framesize, method - _, frametype, chnumber, framesize, method = bin.unpack(">CSII", tmp) + local frametype, chnumber, framesize, method = string.unpack(">BI2I4I4", tmp) stdnse.debug1("frametype: %d, chnumber: %d, framesize: %d, method: %d", frametype, chnumber, framesize, method) if (frametype ~= 1) then @@ -264,7 +263,7 @@ AMQP = { if ( not(status) ) then return status, "ERROR: AMQP:handshake connection closed unexpectedly while reading version" end - version = select( 2, bin.unpack(">S", tmp) ) + version = string.unpack(">I2", tmp) self.protover = AMQP.versions[version] if ( not(self.protover) ) then @@ -277,7 +276,7 @@ AMQP = { return status, "ERROR: AMQP:handshake connection closed unexpectedly while reading server properties size" end - local tablesize = select( 2, bin.unpack(">I", tmp) ) + local tablesize = string.unpack(">I4", tmp) properties = {} status, err, properties = self:decodeTable(properties, tablesize) diff --git a/nselib/mqtt.lua b/nselib/mqtt.lua index b84a0d1dd..6e20ed9e7 100644 --- a/nselib/mqtt.lua +++ b/nselib/mqtt.lua @@ -1,4 +1,3 @@ -local bin = require "bin" local comm = require "comm" local match = require "match" local nmap = require "nmap" @@ -215,7 +214,7 @@ Comm = { length = length .. chunk -- If the byte has the continuation bit cleared, stop receiving. - local _, byte = bin.unpack("C", chunk) + local byte = string.unpack("B", chunk) if byte < 128 then break end @@ -302,10 +301,10 @@ Comm = { assert(pos < #buf) -- Parse the type and flags of the control packet's fixed header. - local pos, type_and_flags = bin.unpack("C", buf, pos) - if not pos then + if #buf - pos + 1 < 1 then return false, "Failed to parse control packet." end + local type_and_flags, pos = string.unpack("B", buf, pos) -- Parse the remaining length. local pos, length = MQTT.length_parse(buf, pos) @@ -371,7 +370,7 @@ Comm = { -- @return Unique identifier for a packet. packet_identifier = function(self) self.packet_id = self.packet_id + 1 - local num = bin.pack(">S", self.packet_id) + local num = string.pack(">I2", self.packet_id) return num end, } @@ -533,7 +532,7 @@ MQTT.packet["CONNECT"].build = function(options) protocol_level = 4 end assert(type(protocol_level) == "number") - head = head .. bin.pack("C", protocol_level) + head = head .. string.pack("B", protocol_level) -- 3.1.3.1 Client Identifier local client_id = options.client_id @@ -585,13 +584,13 @@ MQTT.packet["CONNECT"].build = function(options) tail = tail .. MQTT.utf8_build(options.password) end - head = head .. bin.pack("C", cflags) + head = head .. string.pack("B", cflags) -- 3.1.2.10 Keep Alive if not options.keep_alive_secs then options.keep_alive_secs = 30 end - head = head .. bin.pack(">S", options.keep_alive_secs) + head = head .. string.pack(">I2", options.keep_alive_secs) return true, MQTT.fixed_header(1, 0x0, head .. tail) end @@ -622,7 +621,7 @@ MQTT.packet["CONNACK"].parse = function(fhflags, buf) -- 3.2.2.1 Connect Acknowledge Flags local res = {["type"] = "CONNACK"} - local _, caflags, crcode = bin.unpack("CC", buf) + local caflags, crcode = string.unpack("BB", buf) -- 3.2.2.2 Session Present res.session_present = ((caflags & 0x01) == 1) @@ -656,10 +655,8 @@ end MQTT.packet["SUBSCRIBE"].build = function(options) assert(type(options) == "table") - local pkt = "" - -- 3.8.2 Variable header - pkt = pkt .. options.packet_id + local pkt = {options.packet_id} for key, val in pairs(options.filters) do local name = val.filter @@ -673,11 +670,11 @@ MQTT.packet["SUBSCRIBE"].build = function(options) assert(qos >= 0) assert(qos <= 2) - pkt = pkt .. MQTT.utf8_build(name) - pkt = pkt .. bin.pack("C", qos) + pkt[#pkt+1] = MQTT.utf8_build(name) + pkt[#pkt+1] = string.pack("B", qos) end - return true, MQTT.fixed_header(8, 0x2, pkt) + return true, MQTT.fixed_header(8, 0x2, table.concat(pkt)) end --- Parse an MQTT SUBACK control packet. @@ -708,14 +705,14 @@ MQTT.packet["SUBACK"].parse = function(fhflags, buf) if length < 2 then return false, ("Failed to parse SUBACK packet, too short.") end - local pos, packet_id = bin.unpack(">S", buf) + local packet_id, pos = string.unpack(">I2", buf) res.packet_id = packet_id -- 3.9.3 Payload local code local codes = {} while pos <= length do - pos, code = bin.unpack("C", buf, pos) + code, pos = string.unpack("B", buf, pos) if code == 0x00 then table.insert(codes, {["success"] = true, ["max_qos"] = 0}) elseif code == 0x01 then @@ -769,10 +766,10 @@ MQTT.packet["PUBLISH"].parse = function(fhflags, buf) -- 3.3.2.2 Packet Identifier if qos == 1 or qos == 2 then - pos, val = bin.unpack(">S", buf, pos) - if not pos then - return false, val + if #buf - pos + 1 < 2 then + return false, "packet truncated" end + val, pos = string.unpack(">I2", buf, pos) res.packet_id = val end @@ -814,7 +811,7 @@ MQTT.length_build = function(num) if num > 0 then byte = byte | 0x80 end - field[#field+1] = bin.pack("C", byte) + field[#field+1] = string.pack("B", byte) until num == 0 -- This field has a limit on its length in binary form. @@ -854,7 +851,7 @@ MQTT.length_parse = function(buf, pos) if pos > #buf then return false, "Reached end of buffer before variable-length numeric field was parsed." end - pos, byte = bin.unpack("C", buf, pos) + byte, pos = string.unpack("B", buf, pos) num = num + (byte & 0x7F) * multiplier if offset > 3 then return false, "Buffer contained an invalid variable-length numeric field." @@ -889,7 +886,7 @@ end MQTT.utf8_build = function(str) assert(type(str) == "string") - return bin.pack(">P", str) + return string.pack(">s2", str) end --- Parse a UTF-8 string in MQTT's length-prefixed format. @@ -918,12 +915,12 @@ MQTT.utf8_parse = function(buf, pos) return false, ("Buffer at position %d has no space for a UTF-8 length-prefixed string."):format(pos) end - local _, str_length = bin.unpack(">S", buf, pos) + local str_length = string.unpack(">I2", buf, pos) if pos + 1 + str_length > buf_length then return false, ("Buffer at position %d has no space for a %d-byte UTF-8 string."):format(pos, str_length) end - return bin.unpack(">P", buf, pos) + return string.unpack(">s2", buf, pos) end --- Prefix the body of an MQTT packet with a fixed header. @@ -944,7 +941,7 @@ MQTT.fixed_header = function(num, flags, pkt) -- 2.2.2 Flags local hdr = (num << 4) | flags - return bin.pack("C", hdr) .. MQTT.length_build(#pkt) .. pkt + return string.pack("B", hdr) .. MQTT.length_build(#pkt) .. pkt end -- Skip unit tests unless we're explicitly testing. diff --git a/nselib/ndmp.lua b/nselib/ndmp.lua index b1a17bac8..833903712 100644 --- a/nselib/ndmp.lua +++ b/nselib/ndmp.lua @@ -4,11 +4,11 @@ -- @author Patrik Karlsson -- -local bin = require "bin" local match = require "match" local nmap = require "nmap" local os = require "os" local stdnse = require "stdnse" +local string = require "string" local table = require "table" _ENV = stdnse.module("ndmp", stdnse.seeall) @@ -50,7 +50,7 @@ NDMP = { -- @return fh new instance of FragmentHeader class parse = function(data) local fh = NDMP.FragmentHeader:new() - local _, tmp = bin.unpack(">I", data) + local tmp = string.unpack(">I4", data) fh.length = (tmp & 0x7fffffff) fh.last= (tmp >> 31) return fh @@ -64,7 +64,7 @@ NDMP = { tmp = 0x80000000 end tmp = tmp + self.length - return bin.pack(">I", tmp) + return string.pack(">I4", tmp) end, }, @@ -94,15 +94,14 @@ NDMP = { -- @return hdr new instance of Header parse = function(data) local hdr = NDMP.Header:new() - local pos - pos, hdr.seq, hdr.time, hdr.type, hdr.msg, hdr.reply_seq, hdr.error = bin.unpack(">IIIIII", data) + hdr.seq, hdr.time, hdr.type, hdr.msg, hdr.reply_seq, hdr.error = string.unpack(">I4I4I4I4I4I4", data) return hdr end, -- Serializes the instance to an opaque string -- @return str string containing the serialized class instance __tostring = function(self) - return bin.pack(">IIIIII", self.seq, self.time, self.type, self.msg, self.reply_seq, self.error) + return string.pack(">I4I4I4I4I4I4", self.seq, self.time, self.type, self.msg, self.reply_seq, self.error) end, }, @@ -137,7 +136,7 @@ NDMP.Message.ConfigGetServerInfo = { msg.data = data:sub(NDMP.Header.size + 1) msg.serverinfo = {} - local pos, err = bin.unpack(">I", msg.data) + local err, pos = string.unpack(">I4", msg.data) pos, msg.serverinfo.vendor = Util.parseString(msg.data, pos) pos, msg.serverinfo.product = Util.parseString(msg.data, pos) pos, msg.serverinfo.version = Util.parseString(msg.data, pos) @@ -177,7 +176,7 @@ NDMP.Message.ConfigGetHostInfo = { msg.data = data:sub(NDMP.Header.size + 1) msg.hostinfo = {} - local pos, err = bin.unpack(">I", msg.data) + local err, pos = string.unpack(">I4", msg.data) pos, msg.hostinfo.hostname = Util.parseString(msg.data, pos) pos, msg.hostinfo.ostype = Util.parseString(msg.data, pos) pos, msg.hostinfo.osver = Util.parseString(msg.data, pos) @@ -216,18 +215,18 @@ NDMP.Message.ConfigGetFsInfo = { end msg.data = data:sub(NDMP.Header.size + 1) - local pos, err, count = bin.unpack(">II", msg.data) + local err, count, pos = string.unpack(">I4I4", msg.data) for i=1, count do local item = {} - pos, item.invalid = bin.unpack(">I", msg.data, pos) + item.invalid, pos = string.unpack(">I4", msg.data, pos) pos, item.fs_type = Util.parseString(msg.data, pos) pos, item.fs_logical_device = Util.parseString(msg.data, pos) pos, item.fs_physical_device = Util.parseString(msg.data, pos) - pos, item.total_size = bin.unpack(">L", msg.data, pos) - pos, item.used_size = bin.unpack(">L", msg.data, pos) - pos, item.avail_size = bin.unpack(">L", msg.data, pos) - pos, item.total_inodes = bin.unpack(">L", msg.data, pos) - pos, item.used_inodes = bin.unpack(">L", msg.data, pos) + item.total_size, + item.used_size, + item.avail_size, + item.total_inodes, + item.used_inodes, pos = string.unpack(">I8I8I8I8I8", msg.data, pos) pos, item.fs_env = Util.parseString(msg.data, pos) pos, item.fs_status = Util.parseString(msg.data, pos) table.insert(msg.fsinfo, item) @@ -271,7 +270,7 @@ NDMP.Message.UnhandledMessage = { Util = { parseString = function(data, pos) - local pos, str = bin.unpack(">a", data, pos) + local str, pos = string.unpack(">s4", data, pos) local pad = ( 4 - ( #str % 4 ) ~= 4 ) and 4 - ( #str % 4 ) or 0 return pos + pad, str diff --git a/nselib/sslv2.lua b/nselib/sslv2.lua index 4e0cdbb99..2040aad38 100644 --- a/nselib/sslv2.lua +++ b/nselib/sslv2.lua @@ -6,10 +6,10 @@ -- @author Daniel Miller local stdnse = require "stdnse" -local bin = require "bin" local table = require "table" local nmap = require "nmap" local sslcert = require "sslcert" +local string = require "string" local rand = require "rand" _ENV = stdnse.module("sslv2", stdnse.seeall) @@ -119,7 +119,7 @@ local function read_header(buffer, i) end local len - i, len = bin.unpack(">S", buffer, i) + len, i = string.unpack(">I2", buffer, i) local msb = (len & 0x8000) == 0x8000 local header_length, record_length, padding_length, is_escape if msb then @@ -134,7 +134,7 @@ local function read_header(buffer, i) end record_length = len & 0x3fff is_escape = not not (len & 0x4000) - i, padding_length = bin.unpack("C", buffer, i) + padding_length, i = string.unpack("B", buffer, i) end return i, { @@ -157,20 +157,20 @@ function record_read(buffer, i) return i, nil end - i, h.message_type = bin.unpack("C", buffer, i) + h.message_type, i = string.unpack("B", buffer, i) if h.message_type == SSL_MESSAGE_TYPES.SERVER_HELLO then - local j, SID_hit, certificate_type, ssl_version, certificate_len, ciphers_len, connection_id_len = bin.unpack(">CCSSSS", buffer, i) - local j, certificate = bin.unpack("A" .. certificate_len, buffer, j) + local SID_hit, certificate_type, ssl_version, certificate_len, ciphers_len, connection_id_len, j = string.unpack(">BBI2I2I2I2", buffer, i) + local certificate, j = string.unpack("c" .. certificate_len, buffer, j) local ciphers_end = j + ciphers_len local ciphers = {} while j < ciphers_end do local cipher - j, cipher = bin.unpack("A3", buffer, j) + cipher, j = string.unpack("c3", buffer, j) local cipher_name = SSL_CIPHERS[cipher] and SSL_CIPHERS[cipher].str or ("0x" .. stdnse.tohex(cipher)) ciphers[#ciphers+1] = cipher_name end - local j, connection_id = bin.unpack("A" .. connection_id_len, buffer, j) + local connection_id, j = string.unpack("c" .. connection_id_len, buffer, j) h.body = { cert_type = certificate_type, @@ -180,7 +180,7 @@ function record_read(buffer, i) } i = j elseif h.message_type == SSL_MESSAGE_TYPES.ERROR and h.record_length == 3 then - local j, err = bin.unpack(">S", buffer, i) + local err, j = string.unpack(">I2", buffer, i) h.body = { error = SSL_ERRORS[err] or err } @@ -188,7 +188,7 @@ function record_read(buffer, i) else -- TODO: Other message types? h.message_type = "encrypted" - local j, data = bin.unpack("A"..h.record_length, buffer, i) + local data, j = string.unpack("c"..h.record_length, buffer, i) h.body = { data = data } @@ -209,9 +209,9 @@ function ssl_record (payload, pad_length) "SSL record too long") assert(pad_length < 256, "SSL record padding too long") if pad_length > 0 then - return bin.pack(">SCA", length, pad_length, payload) + return string.pack(">I2B", length, pad_length) .. payload else - return bin.pack(">SA", (length | 0x8000), payload) + return string.pack(">I2", length | 0x8000) .. payload end end @@ -233,15 +233,14 @@ function client_hello (ciphers) local challenge = rand.random_string(16) - local ssl_v2_hello = bin.pack(">CSSSSAA", + local ssl_v2_hello = string.pack(">BI2I2I2I2", 1, -- MSG-CLIENT-HELLO 2, -- version: SSL 2.0 #cipher_codes * 3, -- cipher spec length 0, -- session ID length - #challenge, -- challenge length - table.concat(cipher_codes), - challenge - ) + #challenge) -- challenge length + .. table.concat(cipher_codes) + .. challenge return ssl_record(ssl_v2_hello, 0) end @@ -250,16 +249,15 @@ function client_master_secret(cipher_name, clear_key, encrypted_key, key_arg) local key_arg = key_arg or "" local ck = SSL_CIPHER_CODES[cipher_name] or cipher_name assert(#ck == 3, "Unknown cipher in client_master_secret") - return ssl_record( bin.pack(">CASSSAAA", - SSL_MESSAGE_TYPES.CLIENT_MASTER_KEY, - ck, - #clear_key, - #encrypted_key, - #key_arg, - clear_key, - encrypted_key, - key_arg - ), 0) + return ssl_record( string.pack(">Bc3I2I2I2", + SSL_MESSAGE_TYPES.CLIENT_MASTER_KEY, + ck, + #clear_key, + #encrypted_key, + #key_arg) + .. clear_key + .. encrypted_key + .. key_arg, 0) end local function read_atleast(s, n) diff --git a/nselib/xdmcp.lua b/nselib/xdmcp.lua index 551b4bcd5..30bf6c3fa 100644 --- a/nselib/xdmcp.lua +++ b/nselib/xdmcp.lua @@ -4,10 +4,10 @@ -- -- @author Patrik Karlsson -local bin = require "bin" local ipOps = require "ipOps" local nmap = require "nmap" local stdnse = require "stdnse" +local string = require "string" local table = require "table" _ENV = stdnse.module("xdmcp", stdnse.seeall) @@ -42,17 +42,19 @@ Packet = { -- Parses data based on which a new object is instantiated -- @param data opaque string containing data received over the wire -- @return hdr instance of class + -- @return pos position in the string where parsing left off parse = function(data) - local pos, hdr = nil, Packet.Header:new() - pos, hdr.version, hdr.opcode, hdr.length = bin.unpack(">SSS", data) - return hdr + local hdr = Packet.Header:new() + local pos + hdr.version, hdr.opcode, hdr.length, pos = string.unpack(">I2I2I2", data) + return hdr, pos end, -- Converts the instance to an opaque string -- @return str string containing the instance __tostring = function(self) assert(self.length, "No header length was supplied") - return bin.pack(">SSS", self.version, self.opcode, self.length) + return string.pack(">I2I2I2", self.version, self.opcode, self.length) end, }, @@ -76,12 +78,14 @@ Packet = { -- Converts the instance to an opaque string -- @return str string containing the instance __tostring = function(self) - local data = tostring(self.header) - data = data .. bin.pack("C", #self.authnames) + local data = { + tostring(self.header), + string.pack("B", #self.authnames), + } for _, name in ipairs(self.authnames) do - data = data .. bin.pack(">P", name) + data[#data+1] = string.pack(">s2", name) end - return data + return table.concat(data) end, }, @@ -117,11 +121,11 @@ Packet = { -- @return hdr instance of class parse = function(data) local willing = Packet[OpCode.WILLING]:new() - willing.header = Packet.Header.parse(data) + local pos + willing.header, pos = Packet.Header.parse(data) - local pos = 7 - pos, willing.authname, willing.hostname, - willing.status = bin.unpack("ppp", data, pos) + willing.authname, willing.hostname, + willing.status, pos = string.unpack("s1s1s1", data, pos) return willing end, @@ -190,20 +194,22 @@ Packet = { -- Converts the instance to an opaque string -- @return str string containing the instance __tostring = function(self) - local data = bin.pack(">SC", self.disp_no, #self.conns) + local data = { + string.pack(">I2B", self.disp_no, #self.conns), + } for _, conn in ipairs(self.conns) do - data = data .. bin.pack(">S", conn.iptype) + data[#data+1] = string.pack(">I2", conn.iptype) end - data = data .. bin.pack("C", #self.conns) + data[#data+1] = string.pack("B", #self.conns) for _, conn in ipairs(self.conns) do - data = data .. bin.pack(">P", ipOps.ip_to_str(conn.ip)) + data[#data+1] = string.pack(">s2", ipOps.ip_to_str(conn.ip)) end - data = data .. bin.pack(">PP", self.auth_name, self.auth_data) - data = data .. bin.pack("C", #self.authr_names) + data[#data+1] = string.pack(">s2s2B", self.auth_name, self.auth_data, #self.authr_names) for _, authr in ipairs(self.authr_names) do - data = data .. bin.pack(">P", authr) + data[#data+1] = string.pack(">s2", authr) end - data = data .. bin.pack(">P", self.manf_id) + data[#data+1] = string.pack(">s2", self.manf_id) + data = table.concat(data) self.header.length = #data return tostring(self.header) .. data @@ -239,10 +245,10 @@ Packet = { -- @return hdr instance of class parse = function(data) local accept = Packet[OpCode.ACCEPT]:new() - accept.header = Packet.Header.parse(data) - local pos = 7 - pos, accept.session_id, accept.auth_name, accept.auth_data, - accept.authr_name, accept.authr_data = bin.unpack(">IPPPP", data, pos) + local pos + accept.header, pos = Packet.Header.parse(data) + accept.session_id, accept.auth_name, accept.auth_data, + accept.authr_name, accept.authr_data, pos = string.unpack(">I4s2s2s2s2", data, pos) return accept end, @@ -270,7 +276,7 @@ Packet = { -- Converts the instance to an opaque string -- @return str string containing the instance __tostring = function(self) - local data = bin.pack(">ISP", self.session_id, self.disp_no, self.disp_class) + local data = string.pack(">I4I2s2", self.session_id, self.disp_no, self.disp_class) self.header.length = #data return tostring(self.header) .. data end,