NOTE: you have to put a space between the 'if' and the '('. You must not put the space between the function name and the '('.
Example:
if (conditions) { }
func(args...);
The conditions for an 'if' statement can be either functions or comparisons. Two or more conditions can be linked together with logical operators like OR '||' and AND '&&'.
Example:
if (tcp.src == 21 && search(DATA.data, "ettercap")) {
}
Pay attention to the operator precedence. You cannot use parentheses to group conditions, so be careful with the order. An AND at the beginning of a conditions block will exclude all the other tests if it is evaluated as false. The parsing is left-to-right, when an operator is found: if it is an AND and the previous condition is false, all the statement is evaluated as false; if it is an OR the parsing goes on even if the condition is false.
Example:
if (ip.proto == UDP || ip.proto == TCP && tcp.src == 80) {
}
if (ip.proto == TCP && tcp.src == 80 || ip.proto == UDP) {
}
the former condition will match all udp or http traffic. The latter is wrong, because if the packet is not tcp, the whole condition block will be evaluated as false. If you want to make complex conditions, the best way is to split them into nested 'if' blocks.
Every instruction in a block must end with a semicolon ';'.
Comparisons are implemented with the '==' operator and can be used to compare numbers, strings or ip addresses. An ip address MUST be enclosed within two single quotes (eg. '192.168.0.7'). You can also use the 'less than' ('<'), 'greater than' ('>'), 'less or equal' ('<=') and 'greater or equal' ('>=') operators. The lvalue of a comparison must be an offset (see later)
Example:
if (DATA.data + 20 == "ettercap" && ip.ttl > 16) {
}
Assignments are implemented with the '=' operator and the lvalue can be an offset (see later). The rvalue can be a string, an integer or a hexadecimal value.
Example:
ip.ttl = 0xff;
DATA.data + 7 = "ettercap NG";
You can also use the 'inc' and 'dec' operations on the packet fields. The operators used are '+=' and '-='. The rvalue can be an integer or a hexadecimal value.
Example:
ip.ttl += 5;
Virtual pointers are in the form 'name.field.subfield'. For example 'ip.ttl' is the virtual pointer for the Time To Live field in the IP header of a packet. It will be translated as <L=3, O=9, S=1>. Indeed it is the 9th byte of level 3 and its size is 1 byte. 'ip.ttl + 1' is the same as 'ip.proto' since the 10th byte of the IP header is the protocol encapsulated in the IP packet.
The list of all supported virtual pointers is in the file etterfilter.tbl. You can add your own virtual pointers by adding a new table or modifying the existing ones. Refer to the comments at the beginning of the file for the syntax of etterfilter.tbl file.
example:
search(DATA.data, "\x41\x42\x43")
NOTE: regex can be used only against a string buffer.
example:
regex(DECODED.data, ".*login.*")
example:
pcre_regex(DATA.data, ".*foo$")
pcre_regex(DATA.data, "([^ ]*) bar ([^ ]*)", "foo $1 $2")
example:
replace("ethercap", "ettercap")
example:
inject("./fake_packet")
example:
log(DECODED.data, "/tmp/interesting.log")
example:
msg("Packet filtered successfully")
example:
drop()
example:
kill()
example:
exec("/bin/cat /tmp/foo >> /tmp/bar")
example:
exit()
Compiles the source filter.ecf into a binary filter.ef