NAME
SMB::Packer - Convenient data packer for network protocols like SMB
SYNOPSIS
use SMB::Packer;
# Pack an imaginative packet of the following structure:
# protocol signature (2 bytes in big-endian), header (48),
# secret key (8), flags (1), mode (2 in little-endian),
# payload offset (4) and length (4),
# filename prefixed with length (2 + length),
# padding to 4 bytes,
# payload
# SMB::Parser documentation shows how it can be parsed back.
my $packer = SMB::Packer->new;
$packer
->uint16_be(0xFACE)
->zero(48)
->mark('body-start')
->bytes([ map { chr(rand(0x100)) } 1 .. 8 ]),
->uint8(1)
->uint16($mode)
->stub('payload-offset', 'uint32')
->uint32(bytes::length($payload))
->uint16(length($filename) * 2) # 2-byte chars in utf16
->utf16($filename)
->align
->fill('payload-offset', $packer->diff('body-start'))
->bytes($payload)
;
# send the packet
send_tcp_payload($packer->data, $packer->size);
DESCRIPTION
This class allows to pack a binary data, like a network packet data.
It supports packing blobs, unsigned integers of different lengths, text in arbitrary encoding (SMB uses UTF-16LE), defining named marks inside the data for later reference/jumping, defining named stubs for later filling and more.
The current data pointer is normally at the data end, but may be between 0 and the currently packed data size. The data is automatically extended when needed, and the pointer is advanced accordingly. This is different from SMB::Parser where the initially set data is never extended even when the pointer is over its size.
This class inherits from SMB, so msg, err, mem, dump, auto-created field accessor and other methods are available as well.
METHODS
- new
-
Class constructor. Returns an SMB::Packer instance with initially empty data and state using reset.
- reset
-
Resets the gathered data, the current data pointer, as well as the named marks and stubs.
- data
-
Returns the data packed so far (binary scalar).
- size
-
Returns length of the data packed so far (in bytes).
- offset
-
Returns the current data pointer (integer starting from 0).
Please use the mechanisms of named marks or gaps (see below) instead of manipulating the current data pointer directly.
- skip N_BYTES
-
Advances the pointer in N_BYTES.
If the data needs to be extended over the currently packed data (for example, when the current data pointer is at or near the end), it is appended with the missing number of zeros using zero method.
Returns the object, to allow chaining.
- zero N_BYTES
-
Packs N_BYTES of "\0" bytes starting from the current data pointer and advances the pointer in N_BYTES.
The data is extended if needed.
- bytes BYTES
-
Packs a sub-buffer of BYTES (where BYTES is either a binary scalar or an array ref of 1-byte scalars) and advances the pointer in length of BYTES.
The data is extended if needed.
The following packing methods use this method internally, so they share the same logic about extending the data and advancing the pointer.
- str STRING [ENCODING='UTF-16LE']
-
Encodes STRING (potentially with utf8 flag set) as the text in the requested encoding starting from the current data pointer.
- utf16 STRING
-
The same as str with encoding 'UTF-16LE'.
- utf16_be STRING
-
The same as str with encoding 'UTF-16BE'.
- uint8
- uint16
- uint32
- uint16_be
- uint32_be
- uint64
-
Packs an unsigned integer of the specified length in bits (i.e. 1, 2, 4, 8 bytes).
By default, the byte order is little-endian (since it is used in SMB). The method suffix "_be" denotes the big-endian byte order for packing.
- fid1 FID1
-
Packs a file id used in SMB 1, that is an unsigned integer of 2 bytes.
- fid2 FID2
-
Packs a file id used in SMB 2, that is an array ref of two unsigned integers of 8 bytes each.
- mark MARK_NAME
-
Labels the current data position as MARK_NAME (human readable string).
- jump MARK_NAME
-
Changes the current data position to the one previously labeled with MARK_NAME (if any, otherwise defaults to 0).
- diff MARK_NAME
-
Returns the difference between the current data position and the one previously labeled with MARK_NAME (if any, otherwise defaults to 0).
- align [MARK_NAME=undef] [STEP=4]
-
Skips, if needed, to the next alighment point (that is every STEP bytes starting from MARK_NAME if given or from buffer start).
- stub STUB_NAME TYPE
-
Labels the current data position as STUB_NAME (human readable string), advances the data pointer according to TYPE by temporarily filling this region with a zero equivalent, according to TYPE.
TYPE may be either a number matching /^\d+$/, in which case the stub type is taken to be "bytes" of this size; or "uint8", "uint16" and so on, then this is the stub type (see the corresponding "uint*" methods above).
- fill STUB_NAME DATA
-
Fills the previously set stub with DATA. The DATA should correspond to the TYPE previously specified in stub(STUB_NAME, TYPE) method call. I.e. if the TYPE was size of bytes, then DATA should correspond to the bytes method argument of size TYPE (scalar or array ref of this size). And if the TYPE is, say, "uint16", then DATA should be 2-byte integer.
The packing is done at the previously stored data pointer position. The current data pointer is not changed after this method!
If no STUB_NAME was previously set using stub method, the fatal exception is thrown.
SEE ALSO
AUTHOR
Mikhael Goikhman <migo@cpan.org>