diff --git a/lib/libprotoident.h b/lib/libprotoident.h index 6ea9cec..7455744 100644 --- a/lib/libprotoident.h +++ b/lib/libprotoident.h @@ -403,6 +403,8 @@ typedef enum { LPI_PROTO_TRANSOCKS, LPI_PROTO_RAGNAROK_ONLINE, LPI_PROTO_ETHERNETIP, + LPI_PROTO_KERBEROS, + LPI_PROTO_RPC, /* UDP Protocols */ LPI_PROTO_UDP, diff --git a/lib/proto_common.cc b/lib/proto_common.cc index 6fffd05..c5888dd 100644 --- a/lib/proto_common.cc +++ b/lib/proto_common.cc @@ -74,6 +74,14 @@ bool match_chars_either(lpi_data_t *data, char a, char b, char c, return false; } +bool match_chars_both(lpi_data_t *data, char a, char b, char c, char d) { + if (!MATCH(data->payload[0], a, b, c, d)) + return false; + if (!MATCH(data->payload[1], a, b, c, d)) + return false; + return true; +} + bool match_payload_length(uint32_t payload, uint32_t payload_len) { uint32_t header = 0; diff --git a/lib/proto_common.h b/lib/proto_common.h index 679f784..b01a196 100644 --- a/lib/proto_common.h +++ b/lib/proto_common.h @@ -125,6 +125,7 @@ bool match_str_both(lpi_data_t *data, const char *string1, const char *string2); bool match_chars_either(lpi_data_t *data, char a, char b, char c, char d); +bool match_chars_both(lpi_data_t *data, char a, char b, char c, char d); bool match_payload_length(uint32_t payload, uint32_t payload_len); bool match_ip_address_both(lpi_data_t *data); bool match_file_header(uint32_t payload); diff --git a/lib/proto_manager.cc b/lib/proto_manager.cc index 4d9f12a..1a4a491 100644 --- a/lib/proto_manager.cc +++ b/lib/proto_manager.cc @@ -178,6 +178,7 @@ int register_tcp_protocols(LPIModuleMap *mod_map) { register_kankan_tcp(mod_map); register_kaseya(mod_map); register_kaspersky(mod_map); + register_kerberos(mod_map); register_kik(mod_map); register_kingofglory_tcp(mod_map); register_kuaibo(mod_map); @@ -253,6 +254,7 @@ int register_tcp_protocols(LPIModuleMap *mod_map) { register_remote_manipulator(mod_map); register_revolver_nblbt(mod_map); register_rfb(mod_map); + register_rpc(mod_map); register_rpcscan(mod_map); register_rrtv(mod_map); register_rsync(mod_map); diff --git a/lib/tcp/Makefile.am b/lib/tcp/Makefile.am index 4531a57..1f891a8 100644 --- a/lib/tcp/Makefile.am +++ b/lib/tcp/Makefile.am @@ -111,6 +111,7 @@ libprotoident_tcp_la_SOURCES = \ lpi_kankan_tcp.cc \ lpi_kaseya.cc \ lpi_kaspersky.cc \ + lpi_kerberos.cc \ lpi_kik.cc \ lpi_kingofglory_tcp.cc \ lpi_kuaibo.cc \ @@ -186,6 +187,7 @@ libprotoident_tcp_la_SOURCES = \ lpi_remote_manipulator.cc \ lpi_revolver_nblbt.cc \ lpi_rfb.cc \ + lpi_rpc.cc \ lpi_rpcscan.cc \ lpi_rrtv.cc \ lpi_rsync.cc \ diff --git a/lib/tcp/lpi_kerberos.cc b/lib/tcp/lpi_kerberos.cc new file mode 100644 index 0000000..c1f052d --- /dev/null +++ b/lib/tcp/lpi_kerberos.cc @@ -0,0 +1,53 @@ +/* + * + * Copyright (c) 2011-2016 The University of Waikato, Hamilton, New Zealand. + * All rights reserved. + * + * This file is part of libprotoident. + * + * This code has been developed by the University of Waikato WAND + * research group. For further information please see http://www.wand.net.nz/ + * + * libprotoident is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * libprotoident is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + * + * + */ + +#include "libprotoident.h" +#include "proto_manager.h" +#include "proto_common.h" + +static inline bool match_kerberos(lpi_data_t *data, lpi_module_t *mod UNUSED) { + + /* Quite a weak rule, first 4 bytes of kerberos is the record length which + * is spread over multiple packets */ + + if (data->server_port == 88) + return true; + + return false; +} + +static lpi_module_t lpi_kerberos = { + LPI_PROTO_KERBEROS, + LPI_CATEGORY_KEY_EXCHANGE, + "Kerberos", + 200, + match_kerberos +}; + +void register_kerberos(LPIModuleMap *mod_map) { + register_protocol(&lpi_kerberos, mod_map); +} + diff --git a/lib/tcp/lpi_ldap.cc b/lib/tcp/lpi_ldap.cc index 80f8614..c45f4d0 100644 --- a/lib/tcp/lpi_ldap.cc +++ b/lib/tcp/lpi_ldap.cc @@ -30,7 +30,7 @@ #include "proto_manager.h" #include "proto_common.h" -static inline bool match_ldap_payload(uint32_t payload, uint32_t len) { +static inline bool match_ldap_payload(uint32_t payload, uint32_t len, uint16_t server_port) { uint8_t *byte = ((uint8_t *)&payload); uint16_t struct_len = 0; @@ -40,9 +40,10 @@ static inline bool match_ldap_payload(uint32_t payload, uint32_t len) { byte ++; + // multibyte lengths? if (((*byte) & 0x80) == 0x80) { uint8_t bytes_required = ((*byte) & 0x7f); - if (bytes_required > 2 || bytes_required == 0) + if (bytes_required == 0) return false; if (bytes_required == 1) { @@ -52,10 +53,15 @@ static inline bool match_ldap_payload(uint32_t payload, uint32_t len) { struct_len = 3 + ((uint8_t)(*byte)); if (!MATCH(payload, 0x30, ANY, ANY, 0x02)) return false; - } else { + } else if (bytes_required == 2) { struct_len = 4 + ntohs(*((uint16_t *)(byte + 1))); if (!MATCH(payload, 0x30, ANY, ANY, ANY)) return false; + } else { + // the length is now past the first 4 bytes of payload so we are unable + // to check it, fallback to port in this case + if (server_port == 389) + return true; } } else { if (!MATCH(payload, 0x30, ANY, 0x02, 0x01)) @@ -75,9 +81,9 @@ static inline bool match_ldap_payload(uint32_t payload, uint32_t len) { static inline bool match_ldap(lpi_data_t *data, lpi_module_t *mod UNUSED) { - if (!match_ldap_payload(data->payload[0], data->payload_len[0])) + if (!match_ldap_payload(data->payload[0], data->payload_len[0], data->server_port)) return false; - if (!match_ldap_payload(data->payload[1], data->payload_len[1])) + if (!match_ldap_payload(data->payload[1], data->payload_len[1], data->server_port)) return false; return true; diff --git a/lib/tcp/lpi_rpc.cc b/lib/tcp/lpi_rpc.cc new file mode 100644 index 0000000..54ae0b9 --- /dev/null +++ b/lib/tcp/lpi_rpc.cc @@ -0,0 +1,61 @@ +/* + * + * Copyright (c) 2011-2016 The University of Waikato, Hamilton, New Zealand. + * All rights reserved. + * + * This file is part of libprotoident. + * + * This code has been developed by the University of Waikato WAND + * research group. For further information please see http://www.wand.net.nz/ + * + * libprotoident is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * libprotoident is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + * + * + */ + +#include + +#include "libprotoident.h" +#include "proto_manager.h" +#include "proto_common.h" + +#define PDU_TYPE(x) (data->payload[0] & 0xff0000) >> 16 + +static inline bool match_rpc(lpi_data_t *data, lpi_module_t *mod UNUSED) { + + if (data->server_port != 135 && data->client_port != 135) + return false; + + // valid PDUs are 0 - 19 + if (PDU_TYPE(data->payload[0]) > 19 || PDU_TYPE(data->payload[1]) > 19) + return false; + + if (match_chars_both(data, 0x05, 0x00, ANY, 0x03)) + return true; + + return false; +} + +static lpi_module_t lpi_rpc = { + LPI_PROTO_RPC, + LPI_CATEGORY_SERVICES, + "RPC", + 200, + match_rpc +}; + +void register_rpc(LPIModuleMap *mod_map) { + register_protocol(&lpi_rpc, mod_map); +} + diff --git a/lib/tcp/tcp_protocols.h b/lib/tcp/tcp_protocols.h index 89c2bf7..e3086f8 100644 --- a/lib/tcp/tcp_protocols.h +++ b/lib/tcp/tcp_protocols.h @@ -139,6 +139,7 @@ void register_kakao(LPIModuleMap *mod_map); void register_kankan_tcp(LPIModuleMap *mod_map); void register_kaseya(LPIModuleMap *mod_map); void register_kaspersky(LPIModuleMap *mod_map); +void register_kerberos(LPIModuleMap *mod_map); void register_kik(LPIModuleMap *mod_map); void register_kingofglory_tcp(LPIModuleMap *mod_map); void register_kuaibo(LPIModuleMap *mod_map); @@ -214,6 +215,7 @@ void register_relay(LPIModuleMap *mod_map); void register_remote_manipulator(LPIModuleMap *mod_map); void register_revolver_nblbt(LPIModuleMap *mod_map); void register_rfb(LPIModuleMap *mod_map); +void register_rpc(LPIModuleMap *mod_map); void register_rpcscan(LPIModuleMap *mod_map); void register_rrtv(LPIModuleMap *mod_map); void register_rsync(LPIModuleMap *mod_map);