@automattic/yara
Version:
Automattic's fork of YARA support for Node.js with pre-built binaries
448 lines (370 loc) • 9.84 kB
JavaScript
var assert = require("assert")
var yara = require ("../")
var scanner
before(function(done) {
yara.initialize(function(error) {
assert.ifError(error)
scanner = yara.createScanner()
scanner.configure({
rules: [
{string: "import \"pe\"\n"},
{string: "import \"elf\"\n"},
{string: "rule is_stephen : human man {\nmeta:\nm1 = \"m1\"\nm2 = true\nm3 = 123\n\nstrings:\n$s1 = \"stephen\"\ncondition:\n(age == 35) and (any of them)\n}"},
{string: "rule is_silvia : human womman{\nstrings:\n$s1 = \"silvia\"\ncondition:\nany of them\n}"},
{string: "rule is_either : human man woman {\nstrings:\n$s1 = \"stephen\"\n$s2 = \"silvia\"\ncondition:\nany of them\n}"},
],
variables: [
{type: yara.VariableType.Integer, id: "age", value: 35}
]
}, function(error) {
assert.ifError(error)
done()
})
})
})
describe("index.js", function() {
describe("Scanner.scan()", function() {
it("buffer - valid", function(done) {
var req = {
buffer: Buffer.from("my name is stephen")
}
scanner.scan(req, function(error, result) {
assert.ifError(error)
var expected = {
"rules": [
{
"id": "is_stephen",
"tags": ["human", "man"],
"matches": [
{offset: 11, length: 7, id: "$s1"}
],
"metas": [
{type: 2, id: "m1", value: "m1"},
{type: 3, id: "m2", value: true},
{type: 1, id: "m3", value: 123}
]
},
{
"id": "is_either",
"tags": ["human", "man", "woman"],
"matches": [
{offset: 11, length: 7, id: "$s1"}
],
"metas": []
}
]
}
assert.deepEqual(result, expected)
done()
})
})
it("buffer - matched bytes (enough)", function(done) {
var req = {
matchedBytes: 100,
buffer: Buffer.from("my name is stephen")
}
scanner.scan(req, function(error, result) {
assert.ifError(error)
var expected = {
"rules": [
{
"id": "is_stephen",
"tags": ["human", "man"],
"matches": [
{offset: 11, length: 7, id: "$s1", bytes: Buffer.from("stephen")}
],
"metas": [
{type: 2, id: "m1", value: "m1"},
{type: 3, id: "m2", value: true},
{type: 1, id: "m3", value: 123}
]
},
{
"id": "is_either",
"tags": ["human", "man", "woman"],
"matches": [
{offset: 11, length: 7, id: "$s1", bytes: Buffer.from("stephen")}
],
"metas": []
}
]
}
assert.deepEqual(result, expected)
done()
})
})
it("buffer - matched bytes (short)", function(done) {
var req = {
matchedBytes: 4,
buffer: Buffer.from("my name is stephen")
}
scanner.scan(req, function(error, result) {
assert.ifError(error)
var expected = {
"rules": [
{
"id": "is_stephen",
"tags": ["human", "man"],
"matches": [
{offset: 11, length: 7, id: "$s1", bytes: Buffer.from("step")}
],
"metas": [
{type: 2, id: "m1", value: "m1"},
{type: 3, id: "m2", value: true},
{type: 1, id: "m3", value: 123}
]
},
{
"id": "is_either",
"tags": ["human", "man", "woman"],
"matches": [
{offset: 11, length: 7, id: "$s1", bytes: Buffer.from("step")}
],
"metas": []
}
]
}
assert.deepEqual(result, expected)
done()
})
})
it("buffer.length - out of range (negative)", function(done) {
var req = {
buffer: Buffer.from("1234"),
length: -1
}
assert.throws(function() {
scanner.scan(req, function(error, result) {})
}, /Length is out of bounds/)
done()
})
it("buffer.length - out of range (to high)", function(done) {
var req = {
buffer: Buffer.from("1234"),
length: 5
}
assert.throws(function() {
scanner.scan(req, function(error, result) {})
}, /Length is out of bounds/)
done()
})
it("buffer.length - out of range (plus offset)", function(done) {
var req = {
buffer: Buffer.from("1234"),
length: 3,
offset: 2
}
assert.throws(function() {
scanner.scan(req, function(error, result) {})
}, /Length is out of bounds/)
done()
})
it("buffer.length - within range", function(done) {
var req = {
buffer: Buffer.from("silvia silvia"),
length: 6
}
scanner.scan(req, function(error, result) {
assert.ifError(error)
assert.equal(result.rules.length, 2)
done()
})
})
it("buffer.length - exact", function(done) {
var req = {
buffer: Buffer.from("silvia silvia"),
length: 12
}
scanner.scan(req, function(error, result) {
assert.ifError(error)
assert.equal(result.rules.length, 2)
done()
})
})
it("buffer.offset - out of range (negative)", function(done) {
var req = {
buffer: Buffer.from("1234"),
offset: -1
}
assert.throws(function() {
scanner.scan(req, function(error, result) {})
}, /Offset is out of bounds/)
done()
})
it("buffer.offset - out of range (to high)", function(done) {
var req = {
buffer: Buffer.from("1234"),
offset: 4
}
assert.throws(function() {
scanner.scan(req, function(error, result) {})
}, /Offset is out of bounds/)
done()
})
it("buffer.offset - within range (exact length)", function(done) {
var req = {
buffer: Buffer.from("silvia silvia"),
length: 8,
offset: 5
}
scanner.scan(req, function(error, result) {
assert.ifError(error)
assert.equal(result.rules.length, 2)
done()
})
})
it("buffer.offset - within range", function(done) {
var req = {
buffer: Buffer.from("silvia silvia"),
offset: 2
}
scanner.scan(req, function(error, result) {
assert.ifError(error)
assert.equal(result.rules.length, 2)
done()
})
})
it("file - missing (and no buffer)", function(done) {
var req = {}
assert.throws(function() {
scanner.scan(req, function(error, result) {})
}, /Either filename of buffer is required/)
done()
})
it("file - non-existant", function(done) {
var req = {
filename: "test/data/unit_index.js_scanner.scan/empty.txt"
}
scanner.scan(req, function(error, result) {
assert.ifError(error)
assert.equal(result.rules, 0)
done()
})
})
it("file - valid", function(done) {
var req = {
filename: "test/data/unit_index.js_scanner.scan/valid.txt"
}
scanner.scan(req, function(error, result) {
assert.ifError(error)
var expected = {
"rules": [
{
"id": "is_stephen",
"tags": ["human", "man"],
"matches": [
{offset: 20, length: 7, id: "$s1"}
],
"metas": [
{type: 2, id: "m1", value: "m1"},
{type: 3, id: "m2", value: true},
{type: 1, id: "m3", value: 123}
]
},
{
"id": "is_either",
"tags": ["human", "man", "woman"],
"matches": [
{offset: 20, length: 7, id: "$s1"}
],
"metas": []
}
]
}
assert.deepEqual(result, expected)
done()
})
})
it("flags - defaults to no FastMode", function(done) {
scanner.configure({
rules: [
{filename: "test/data/unit_index.js_scanner.scan/flags.txt"}
]
}, function(error) {
assert.ifError(error)
var req = {
buffer: Buffer.from("stephen stephen")
}
scanner.scan(req, function(error, result) {
assert.ifError(error)
var expected = {
"rules": [
{
"id": "is_stephen",
"tags": [],
"matches": [
{offset: 0, length: 7, id: "$s1"},
{offset: 8, length: 7, id: "$s1"}
],
"metas": []
}
]
}
assert.deepEqual(result, expected)
done()
})
})
})
it("flags - FastMode matches once", function(done) {
scanner.configure({
rules: [
{filename: "test/data/unit_index.js_scanner.scan/flags.txt"}
]
}, function(error) {
assert.ifError(error)
var req = {
buffer: Buffer.from("stephen stephen"),
flags: yara.ScanFlag.FastMode
}
scanner.scan(req, function(error, result) {
assert.ifError(error)
var expected = {
"rules": [
{
"id": "is_stephen",
"tags": [],
"matches": [
{offset: 0, length: 7, id: "$s1"}
],
"metas": []
}
]
}
assert.deepEqual(result, expected)
done()
})
})
})
it("rules - retains colon in meta value", function(done) {
scanner.configure({
rules: [
{string: "rule colon_in_meta {\nmeta:\nm1 = \"colon : in meta\"\n\nstrings:\n$s1 = \"colon_in_meta\"\ncondition:\nany of them\n}"}
]
}, function(error) {
assert.ifError(error)
var req = {
buffer: Buffer.from("colon_in_meta")
}
scanner.scan(req, function(error, result) {
assert.ifError(error)
var expected = {
"rules": [
{
"id": "colon_in_meta",
"tags": [],
"matches": [
{offset: 0, length: 13, id: "$s1"}
],
"metas": [
{id: "m1", type: 2, value: "colon : in meta"}
]
}
]
}
assert.deepEqual(result, expected)
done()
})
})
})
})
})