Struct lancelot_flirt::FlirtSignature[][src]

pub struct FlirtSignature {
    pub byte_sig: ByteSignature,
    pub size_of_bytes_crc16: u8,
    pub crc16: u16,
    pub size_of_function: u64,
    pub names: Vec<Symbol>,
    // some fields omitted
}

Fields

byte_sig: ByteSignature

a sequence of potentially wildcarded bytes that must match at the start of the input buffer. by default, the signature size is up to 32-bytes. relocations/fixups get masked by the wildcards.

example (human readable):

48895c2408574883ec20488bd9488d3d........488bcfe8........85c07422
size_of_bytes_crc16: u8

after byte signature matching the start of the function, flirt checks the CRC16 checksum of subsequent data. usually this is up to the next relocation/fixup.

example

 06 2828

means: the CRC16 of the six bytes following the byte signature match must be 0x2828. number of bytes passed to the CRC16 checksum

crc16: u16size_of_function: u64

then size of function.

TODO: i’m not sure if this is used for matching. it would require a disassembly of the bytes and reconstruction of the control flow.

names: Vec<Symbol>

next is a sequence of (offset, type, name) tuples. the offset is relative from the start of the function/signature match. the type is one of:

  • public
  • local
  • reference

public and local names are the names applied to locations once the signature completely matched. they’re the whole point of doing FLIRT signature matching.

reference names are used to differentiate otherwise identical code. think of wrapper functions with trivial instructions that jump to a well known API. the reference is a relocation/fixup that points to some other code or data. if that thing has the given name, then the signature can match.

TODO: im not exactly sure if FLIRT relies on these names being provided by some other technology (providing the names manually works in IDA) or if the matching is recursive (“go FLIRT match over there, then come back when you have results”).

TODO: im not sure how the reference is expected to be formatted. is it always a relocation? is it ever an offset embedded within an instruction? some results: its not strictly a relocation. in 34a05606d7c41a5856f4a9a64316c6ca at 0x1400152E1 is a reference to 0x140034D00 that is _vmldSinHATab. its encoded as: 1400152E1 F2 0F 10 05 17 FA 01 00 movsd xmm0, cs:qword_140034D00 instruction is at relative offset 0x41, while rule specifies reference is at 0x45: 17 FA 01 00 there is not a relocation here, confirmed via CFF and IDA Instruction Details. so need to disassemble to find the instruction xref? or maybe guess at the address encoding. i wonder if its best left to the caller to validate these references?

pat files seem to have many more names, especially references, than actually make it into sig files. i presume that sigmake reduces the necessary reference names down to whats actually needed to differentiate signatures.

example:

:0000 __sse2_tanh2 :021d@ _2TAG_PACKET_1_0_1

means:

  • relative offset 0x0 is public name __sse2_tanh2
  • relative offset 0x21D is local (@) name _2TAG_PACKET_1_0_1

example:

:0000 __common_dsin_cout_rare ^0045 _vmldSinHATab

means:

  • relative offset 0x0 is public name __common_dsin_cout_rare
  • relative offset 0x45 should be a reference (^) to symbol _vmldSinHATab

Implementations

impl FlirtSignature[src]

pub fn create_matcher(&self) -> FlirtSignatureMatcher<'_>[src]

pub fn get_name(&self) -> Option<&str>[src]

pub fn match_crc16(&self, buf: &[u8]) -> bool[src]

pub fn match_tail_bytes(&self, buf: &[u8]) -> bool[src]

return true if all tail bytes match (if there are any).

return true if all the footer bytes match (if there are any).

pub fn render_pat(&self) -> String[src]

Trait Implementations

impl Clone for FlirtSignature[src]

impl Debug for FlirtSignature[src]

impl Display for FlirtSignature[src]

impl From<&'_ FlirtSignature> for Pattern[src]

Auto Trait Implementations

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<T> Conv for T

impl<T> Conv for T

impl<T> FmtForward for T

impl<T> From<T> for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T> Pipe for T where
    T: ?Sized

impl<T> Pipe for T

impl<T> PipeAsRef for T

impl<T> PipeBorrow for T

impl<T> PipeDeref for T

impl<T> PipeRef for T

impl<T> Tap for T

impl<T> Tap for T

impl<T, U> TapAsRef<U> for T where
    U: ?Sized

impl<T, U> TapBorrow<U> for T where
    U: ?Sized

impl<T> TapDeref for T

impl<T> ToOwned for T where
    T: Clone
[src]

type Owned = T

The resulting type after obtaining ownership.

impl<T> ToString for T where
    T: Display + ?Sized
[src]

impl<T> TryConv for T

impl<T> TryConv for T

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.