Skip to content

Commit

Permalink
use slice::starts_with
Browse files Browse the repository at this point in the history
  • Loading branch information
marcospb19 committed Jun 11, 2023
1 parent 3c78fcf commit bb0b675
Show file tree
Hide file tree
Showing 3 changed files with 41 additions and 137 deletions.
4 changes: 2 additions & 2 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -637,12 +637,12 @@ mod tests {
fn test_custom_matcher_ordering() {
// overrides jpeg matcher
fn foo_matcher(buf: &[u8]) -> bool {
buf.len() > 2 && buf[0] == 0xFF && buf[1] == 0xD8 && buf[2] == 0xFF
buf.starts_with(&[0xFF, 0xD8, 0xFF])
}

// overrides png matcher
fn bar_matcher(buf: &[u8]) -> bool {
buf.len() > 3 && buf[0] == 0x89 && buf[1] == 0x50 && buf[2] == 0x4E && buf[3] == 0x47
buf.starts_with(&[0x89, 0x50, 0x4E, 0x47])
}

let mut info = Infer::new();
Expand Down
51 changes: 14 additions & 37 deletions src/matchers/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,7 @@
pub fn is_wasm(buf: &[u8]) -> bool {
// WASM has starts with `\0asm`, followed by the version.
// http://webassembly.github.io/spec/core/binary/modules.html#binary-magic
buf.len() >= 8
&& buf[0] == 0x00
&& buf[1] == 0x61
&& buf[2] == 0x73
&& buf[3] == 0x6D
&& buf[4] == 0x01
&& buf[5] == 0x00
&& buf[6] == 0x00
&& buf[7] == 0x00
buf.starts_with(&[0x00, 0x61, 0x73, 0x6D, 0x01, 0x00, 0x00, 0x00])
}

/// Returns whether a buffer is an EXE. DLL and EXE have the same magic number, so returns true also for a DLL.
Expand All @@ -29,7 +21,7 @@ pub fn is_wasm(buf: &[u8]) -> bool {
/// assert!(infer::app::is_exe(&fs::read("testdata/sample.exe").unwrap()));
/// ```
pub fn is_exe(buf: &[u8]) -> bool {
buf.len() > 1 && buf[0] == 0x4D && buf[1] == 0x5A
buf.starts_with(&[0x4D, 0x5A])
}

/// Returns whether a buffer is a DLL. DLL and EXE have the same magic number, so returns true also for an EXE.
Expand All @@ -39,23 +31,19 @@ pub fn is_dll(buf: &[u8]) -> bool {

/// Returns whether a buffer is an ELF.
pub fn is_elf(buf: &[u8]) -> bool {
buf.len() > 52 && buf[0] == 0x7F && buf[1] == 0x45 && buf[2] == 0x4C && buf[3] == 0x46
buf.len() > 52 && buf.starts_with(&[0x7F, 0x45, 0x4C, 0x46])
}

/// Returns whether a buffer is compiled Java bytecode.
pub fn is_java(buf: &[u8]) -> bool {
buf.len() >= 8
&& buf[0] == 0x43
&& buf[1] == 0x41
&& buf[2] == 0x76
&& buf[3] == 0x45
&& ((buf[4] == 0x42 && buf[5] == 0x01 && buf[6] == 0x42 && buf[7] == 0x45)
|| (buf[4] == 0x44 && buf[5] == 0x30 && buf[6] == 0x30 && buf[7] == 0x44))
buf.starts_with(&[0x43, 0x41, 0x76, 0x45])
&& (buf[4..].starts_with(&[0x42, 0x01, 0x42, 0x45])
|| buf[4..].starts_with(&[0x44, 0x30, 0x30, 0x44]))
}

/// Returns whether a buffer is LLVM Bitcode.
pub fn is_llvm(buf: &[u8]) -> bool {
buf.len() >= 2 && buf[0] == 0x42 && buf[1] == 0x43
buf.starts_with(&[0x42, 0x43])
}

/// Returns whether a buffer is a Mach-O binary.
Expand All @@ -81,7 +69,7 @@ pub fn is_dex(buf: &[u8]) -> bool {

buf.len() > 36
// magic
&& buf[0] == 0x64 && buf[1] == 0x65 && buf[2] == 0x78 && buf[3] == 0x0A
&& buf.starts_with(&[0x64, 0x65, 0x78, 0x0A])
// file sise
&& buf[36] == 0x70
}
Expand All @@ -90,7 +78,7 @@ pub fn is_dex(buf: &[u8]) -> bool {
pub fn is_dey(buf: &[u8]) -> bool {
buf.len() > 100
// magic
&& buf[0] == 0x64 && buf[1] == 0x65 && buf[2] == 0x79 && buf[3] == 0x0A
&& buf.starts_with(&[0x64, 0x65, 0x79, 0x0A])
// file sise
&& is_dex(&buf[40..100])
}
Expand All @@ -103,22 +91,22 @@ pub fn is_der(buf: &[u8]) -> bool {
// openssl req -newkey rsa:2048 -nodes -keyout domain.key -x509 -days 1 -out domain.crt
// openssl x509 -in domain.crt -outform der -out domain.der

buf.len() > 2 && buf[0] == 0x30 && buf[1] == 0x82
buf.starts_with(&[0x30, 0x82])
}

/// Returns whether a buffer is a Common Object File Format for i386 architecture.
pub fn is_coff_i386(buf: &[u8]) -> bool {
buf.len() > 2 && buf[0] == 0x4C && buf[1] == 0x01
buf.starts_with(&[0x4C, 0x01])
}

/// Returns whether a buffer is a Common Object File Format for x64 architecture.
pub fn is_coff_x64(buf: &[u8]) -> bool {
buf.len() > 2 && buf[0] == 0x64 && buf[1] == 0x86
buf.starts_with(&[0x64, 0x86])
}

/// Returns whether a buffer is a Common Object File Format for Itanium architecture.
pub fn is_coff_ia64(buf: &[u8]) -> bool {
buf.len() > 2 && buf[0] == 0x00 && buf[1] == 0x02
buf.starts_with(&[0x00, 0x02])
}

/// Returns whether a buffer is a Common Object File Format.
Expand All @@ -129,16 +117,5 @@ pub fn is_coff(buf: &[u8]) -> bool {
/// Returns whether a buffer is pem
pub fn is_pem(buf: &[u8]) -> bool {
// https://en.wikipedia.org/wiki/List_of_file_signatures
buf.len() > 11
&& buf[0] == b'-'
&& buf[1] == b'-'
&& buf[2] == b'-'
&& buf[3] == b'-'
&& buf[4] == b'-'
&& buf[5] == b'B'
&& buf[6] == b'E'
&& buf[7] == b'G'
&& buf[8] == b'I'
&& buf[9] == b'N'
&& buf[10] == b' '
buf.starts_with(b"-----BEGIN ".as_slice())
}
123 changes: 25 additions & 98 deletions src/matchers/archive.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,62 +13,41 @@ pub fn is_zip(buf: &[u8]) -> bool {
|| (buf[2] == 0x7 && buf[3] == 0x8))
|| (
// winzip
buf.len() > 7
&& (buf[2] == 0x30
&& buf[3] == 0x30
&& buf[4] == 0x50
&& buf[5] == 0x4B
&& buf[6] == 0x3
&& buf[7] == 0x4)
buf[2..].starts_with(&[0x30, 0x30, 0x50, 0x4B, 0x3, 0x4])
))
}

/// Returns whether a buffer is a tar archive.
pub fn is_tar(buf: &[u8]) -> bool {
buf.len() > 261
&& buf[257] == 0x75
&& buf[258] == 0x73
&& buf[259] == 0x74
&& buf[260] == 0x61
&& buf[261] == 0x72
buf.len() > 261 && buf.starts_with(&[0x75, 0x73, 0x74, 0x61, 0x72])
}

/// Returns whether a buffer is a RAR archive.
pub fn is_rar(buf: &[u8]) -> bool {
buf.len() > 6
&& buf[0] == 0x52
&& buf[1] == 0x61
&& buf[2] == 0x72
&& buf[3] == 0x21
&& buf[4] == 0x1A
&& buf.starts_with(&[0x52, 0x61, 0x72, 0x21, 0x1A])
&& buf[5] == 0x7
&& (buf[6] == 0x0 || buf[6] == 0x1)
}

/// Returns whether a buffer is a gzip archive.
pub fn is_gz(buf: &[u8]) -> bool {
buf.len() > 2 && buf[0] == 0x1F && buf[1] == 0x8B && buf[2] == 0x8
buf.len() > 2 && buf.starts_with(&[0x1F, 0x8B]) && buf[2] == 0x8
}

/// Returns whether a buffer is a bzip archive.
pub fn is_bz2(buf: &[u8]) -> bool {
buf.len() > 2 && buf[0] == 0x42 && buf[1] == 0x5A && buf[2] == 0x68
buf.starts_with(&[0x42, 0x5A, 0x68])
}

/// Returns whether a buffer is a 7z archive.
pub fn is_7z(buf: &[u8]) -> bool {
buf.len() > 5
&& buf[0] == 0x37
&& buf[1] == 0x7A
&& buf[2] == 0xBC
&& buf[3] == 0xAF
&& buf[4] == 0x27
&& buf[5] == 0x1C
buf.starts_with(&[0x37, 0x7A, 0xBC, 0xAF, 0x27, 0x1C])
}

/// Returns whether a buffer is a PDF.
pub fn is_pdf(buf: &[u8]) -> bool {
buf.len() > 3 && buf[0] == 0x25 && buf[1] == 0x50 && buf[2] == 0x44 && buf[3] == 0x46
buf.starts_with(&[0x25, 0x50, 0x44, 0x46])
}

/// Returns whether a buffer is a SWF.
Expand All @@ -78,29 +57,22 @@ pub fn is_swf(buf: &[u8]) -> bool {

/// Returns whether a buffer is an RTF.
pub fn is_rtf(buf: &[u8]) -> bool {
buf.len() > 4
&& buf[0] == 0x7B
&& buf[1] == 0x5C
&& buf[2] == 0x72
&& buf[3] == 0x74
&& buf[4] == 0x66
buf.starts_with(&[0x7B, 0x5C, 0x72, 0x74, 0x66])
}

/// Returns whether a buffer is a Nintendo NES ROM.
pub fn is_nes(buf: &[u8]) -> bool {
buf.len() > 3 && buf[0] == 0x4E && buf[1] == 0x45 && buf[2] == 0x53 && buf[3] == 0x1A
buf.starts_with(&[0x4E, 0x45, 0x53, 0x1A])
}

/// Returns whether a buffer is Google Chrome Extension
pub fn is_crx(buf: &[u8]) -> bool {
buf.len() > 3 && buf[0] == 0x43 && buf[1] == 0x72 && buf[2] == 0x32 && buf[3] == 0x34
buf.starts_with(&[0x43, 0x72, 0x32, 0x34])
}

/// Returns whether a buffer is a CAB.
pub fn is_cab(buf: &[u8]) -> bool {
buf.len() > 3
&& ((buf[0] == 0x4D && buf[1] == 0x53 && buf[2] == 0x43 && buf[3] == 0x46)
|| (buf[0] == 0x49 && buf[1] == 0x53 && buf[2] == 0x63 && buf[3] == 0x28))
buf.starts_with(&[0x4D, 0x53, 0x43, 0x46]) || buf.starts_with(&[0x49, 0x53, 0x63, 0x28])
}

/// Returns whether a buffer is a eot octet stream.
Expand All @@ -115,18 +87,12 @@ pub fn is_eot(buf: &[u8]) -> bool {

/// Returns whether a buffer is postscript.
pub fn is_ps(buf: &[u8]) -> bool {
buf.len() > 1 && buf[0] == 0x25 && buf[1] == 0x21
buf.starts_with(&[0x25, 0x21])
}

/// Returns whether a buffer is xz archive.
pub fn is_xz(buf: &[u8]) -> bool {
buf.len() > 5
&& buf[0] == 0xFD
&& buf[1] == 0x37
&& buf[2] == 0x7A
&& buf[3] == 0x58
&& buf[4] == 0x5A
&& buf[5] == 0x00
buf.starts_with(&[0xFD, 0x37, 0x7A, 0x58, 0x5A, 0x00])
}

/// Returns whether a buffer is a sqlite3 database.
Expand All @@ -138,45 +104,20 @@ pub fn is_xz(buf: &[u8]) -> bool {
/// assert!(infer::archive::is_sqlite(&fs::read("testdata/sample.db").unwrap()));
/// ```
pub fn is_sqlite(buf: &[u8]) -> bool {
buf.len() > 3 && buf[0] == 0x53 && buf[1] == 0x51 && buf[2] == 0x4C && buf[3] == 0x69
buf.starts_with(&[0x53, 0x51, 0x4C, 0x69])
}

/// Returns whether a buffer is a deb archive.
pub fn is_deb(buf: &[u8]) -> bool {
buf.len() > 20
&& buf[0] == 0x21
&& buf[1] == 0x3C
&& buf[2] == 0x61
&& buf[3] == 0x72
&& buf[4] == 0x63
&& buf[5] == 0x68
&& buf[6] == 0x3E
&& buf[7] == 0x0A
&& buf[8] == 0x64
&& buf[9] == 0x65
&& buf[10] == 0x62
&& buf[11] == 0x69
&& buf[12] == 0x61
&& buf[13] == 0x6E
&& buf[14] == 0x2D
&& buf[15] == 0x62
&& buf[16] == 0x69
&& buf[17] == 0x6E
&& buf[18] == 0x61
&& buf[19] == 0x72
&& buf[20] == 0x79
buf.starts_with(&[
0x21, 0x3C, 0x61, 0x72, 0x63, 0x68, 0x3E, 0x0A, 0x64, 0x65, 0x62, 0x69, 0x61, 0x6E, 0x2D,
0x62, 0x69, 0x6E, 0x61, 0x72, 0x79,
])
}

/// Returns whether a buffer is a ar archive.
pub fn is_ar(buf: &[u8]) -> bool {
buf.len() > 6
&& buf[0] == 0x21
&& buf[1] == 0x3C
&& buf[2] == 0x61
&& buf[3] == 0x72
&& buf[4] == 0x63
&& buf[5] == 0x68
&& buf[6] == 0x3E
buf.starts_with(&[0x21, 0x3C, 0x61, 0x72, 0x63, 0x68, 0x3E])
}

/// Returns whether a buffer is a z archive.
Expand All @@ -186,47 +127,33 @@ pub fn is_z(buf: &[u8]) -> bool {

/// Returns whether a buffer is a lzip archive.
pub fn is_lz(buf: &[u8]) -> bool {
buf.len() > 3 && buf[0] == 0x4C && buf[1] == 0x5A && buf[2] == 0x49 && buf[3] == 0x50
buf.starts_with(&[0x4C, 0x5A, 0x49, 0x50])
}

/// Returns whether a buffer is an RPM.
pub fn is_rpm(buf: &[u8]) -> bool {
buf.len() > 96 && buf[0] == 0xED && buf[1] == 0xAB && buf[2] == 0xEE && buf[3] == 0xDB
buf.len() > 96 && buf.starts_with(&[0xED, 0xAB, 0xEE, 0xDB])
}

/// Returns whether a buffer is a dcm archive.
pub fn is_dcm(buf: &[u8]) -> bool {
buf.len() > 131 && buf[128] == 0x44 && buf[129] == 0x49 && buf[130] == 0x43 && buf[131] == 0x4D
buf.len() > 131 && buf.starts_with(&[0x44, 0x49, 0x43, 0x4D])
}

/// Returns whether a buffer is a Zstd archive.
pub fn is_zst(buf: &[u8]) -> bool {
buf.len() > 3 && buf[0] == 0x28 && buf[1] == 0xB5 && buf[2] == 0x2F && buf[3] == 0xFD
buf.starts_with(&[0x28, 0xB5, 0x2F, 0xFD])
}

/// Returns whether a buffer is a MSI Windows Installer archive.
pub fn is_msi(buf: &[u8]) -> bool {
buf.len() > 7
&& buf[0] == 0xD0
&& buf[1] == 0xCF
&& buf[2] == 0x11
&& buf[3] == 0xE0
&& buf[4] == 0xA1
&& buf[5] == 0xB1
&& buf[6] == 0x1A
&& buf[7] == 0xE1
buf.starts_with(&[0xD0, 0xCF, 0x11, 0xE0, 0xA1, 0xB1, 0x1A, 0xE1])
}

/// Returns whether a buffer is a CPIO archive.
pub fn is_cpio(buf: &[u8]) -> bool {
(buf.len() > 1
&& ((buf[0] == 0xC7 && buf[1] == 0x71) // little endian, old format
|| (buf[0] == 0x71 && buf[1] == 0xC7))) // big endian, old format
|| (buf.len() > 6
&& buf[0] == 0x30
&& buf[1] == 0x37
&& buf[2] == 0x30
&& buf[3] == 0x37
&& buf[4] == 0x30
&& buf[5] == 0x31) // newc format
|| buf.starts_with(&[0x30, 0x37, 0x30, 0x37, 0x30, 0x31]) // newc format
}

0 comments on commit bb0b675

Please sign in to comment.