diff --git a/.github/workflows/pkg-build.yaml b/.github/workflows/pkg-build.yaml new file mode 100644 index 00000000..53410808 --- /dev/null +++ b/.github/workflows/pkg-build.yaml @@ -0,0 +1,53 @@ +name: Packaging for Debian and Ubuntu + +on: + push: + tags: + - '*' + +jobs: + build: + runs-on: ubuntu-latest + container: + image: ${{ matrix.target }} + strategy: + fail-fast: false + matrix: + arch: + - amd64 + target: + - "debian:stretch" + - "debian:buster" + - "ubuntu:xenial" + - "ubuntu:bionic" + - "ubuntu:focal" + + steps: + - name: Checkout repo + uses: actions/checkout@v2 + - name: Install prereq packages + run: ./debpkg-setup.sh + - name: Build packages + run: ./debpkg-build.sh + - name: Store packages + run: | + export DIRNAME=`echo ${{ matrix.target }} | tr ':' '_'` + mkdir -p packages/${DIRNAME} + cp ../*.deb packages/${DIRNAME}/ + - name: Publish packages to cloudsmith + uses: wanduow/action-cloudsmith-upload-packages@v1 + with: + path: packages/ + repo: ${{ secrets.CLOUDSMITH_OWNER }}/libprotoident + username: salcock + api_key: ${{ secrets.CLOUDSMITH_API_KEY }} + - name: Publish packages to bintray + uses: wanduow/action-bintray-upload-debian-packages@v1 + with: + path: packages/ + repo: ${{ secrets.BINTRAY_OWNER }}/libprotoident + license: LGPL-3.0 + username: salcock + api_key: ${{ secrets.BINTRAY_API_KEY }} + + diff --git a/.github/workflows/rpm-build.yaml b/.github/workflows/rpm-build.yaml new file mode 100644 index 00000000..3d4dc1d0 --- /dev/null +++ b/.github/workflows/rpm-build.yaml @@ -0,0 +1,45 @@ +name: Packaging for Centos and Fedora + +on: + push: + tags: + - '*' + +jobs: + build: + runs-on: ubuntu-latest + container: + image: ${{ matrix.target }} + strategy: + fail-fast: false + matrix: + arch: + - amd64 + target: + - "centos:7" + - "centos:8" + - "fedora:33" + - "fedora:32" + + + steps: + - name: Checkout repo + uses: actions/checkout@v2 + - name: Install prereq packages + run: ./rpmpkg-setup.sh ${{ matrix.target }} + - name: Build packages + run: ./rpmpkg-build.sh ${{ matrix.target }} + - name: Store packages + run: | + export DIRNAME=`echo ${{ matrix.target }} | tr ':' '_'` + mkdir -p packages/${DIRNAME} + cp ~/rpmbuild/RPMS/x86_64/*.rpm packages/${DIRNAME}/ + - name: Publish packages to cloudsmith + uses: wanduow/action-cloudsmith-upload-packages@v1 + with: + path: packages/ + repo: ${{ secrets.CLOUDSMITH_OWNER }}/libprotoident + username: salcock + api_key: ${{ secrets.CLOUDSMITH_API_KEY }} + + diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml deleted file mode 100644 index c8f377cf..00000000 --- a/.gitlab-ci.yml +++ /dev/null @@ -1,124 +0,0 @@ -stages: - - build - - upload - -build-debian-jessie: - stage: build - image: debian:jessie - script: - - ./gitlab-build.sh - - mkdir -p built-packages/jessie/ - - mv ../*.deb built-packages/jessie/ - artifacts: - paths: - - built-packages/* - expire_in: 1 day - only: - - tags - -build-debian-stretch: - stage: build - image: debian:stretch - script: - - ./gitlab-build.sh - - mkdir -p built-packages/stretch/ - - mv ../*.deb built-packages/stretch/ - artifacts: - paths: - - built-packages/* - expire_in: 1 day - only: - - tags - -build-debian-buster: - stage: build - image: debian:buster - script: - - ./gitlab-build.sh - - mkdir -p built-packages/buster/ - - mv ../*.deb built-packages/buster/ - artifacts: - paths: - - built-packages/* - expire_in: 1 day - only: - - tags - -build-ubuntu-xenial: - stage: build - image: ubuntu:xenial - script: - - ./gitlab-build.sh - - mkdir -p built-packages/xenial/ - - mv ../*.deb built-packages/xenial/ - artifacts: - paths: - - built-packages/* - expire_in: 1 day - only: - - tags - -build-ubuntu-cosmic: - stage: build - image: ubuntu:cosmic - script: - - ./gitlab-build.sh - - mkdir -p built-packages/cosmic/ - - mv ../*.deb built-packages/cosmic/ - artifacts: - paths: - - built-packages/* - expire_in: 1 day - only: - - tags - -build-ubuntu-bionic: - stage: build - image: ubuntu:bionic - script: - - ./gitlab-build.sh - - mkdir -p built-packages/bionic/ - - mv ../*.deb built-packages/bionic/ - artifacts: - paths: - - built-packages/* - expire_in: 1 day - only: - - tags - -build-ubuntu-disco: - stage: build - image: ubuntu:disco - script: - - ./gitlab-build.sh - - mkdir -p built-packages/disco/ - - mv ../*.deb built-packages/disco/ - artifacts: - paths: - - built-packages/* - expire_in: 1 day - only: - - tags - -build-ubuntu-eoan: - stage: build - image: ubuntu:eoan - script: - - ./gitlab-build.sh - - mkdir -p built-packages/eoan/ - - mv ../*.deb built-packages/eoan/ - artifacts: - paths: - - built-packages/* - expire_in: 1 day - only: - - tags - -upload-packages: - stage: upload - image: ubuntu:bionic - script: - - ./bintray-upload.sh - only: - - tags - diff --git a/README b/README index 7af4cfac..1be10e20 100644 --- a/README +++ b/README @@ -1,7 +1,7 @@ -libprotoident 2.0.14 +libprotoident 2.0.15 --------------------------------------------------------------------------- -Copyright (c) 2011-2019 The University of Waikato, Hamilton, New Zealand. +Copyright (c) 2011-2020 The University of Waikato, Hamilton, New Zealand. All rights reserved. This code has been developed by the University of Waikato WAND diff --git a/bintray-upload.sh b/bintray-upload.sh deleted file mode 100755 index 7723833c..00000000 --- a/bintray-upload.sh +++ /dev/null @@ -1,35 +0,0 @@ -#!/bin/bash - -set -e -o pipefail - -BINTRAY_REPO="wand/libprotoident" -BINTRAY_LICENSE="LGPL-3.0" - -apt-get update && apt-get install -y curl - -curl --silent -fL -XGET \ - "https://api.bintray.com/content/jfrog/jfrog-cli-go/\$latest/jfrog-cli-linux-amd64/jfrog?bt_package=jfrog-cli-linux-amd64" \ - > /usr/local/bin/jfrog -chmod +x /usr/local/bin/jfrog -mkdir ~/.jfrog/ -cat << EOF > ~/.jfrog/jfrog-cli.conf -{ - "artifactory": null, - "bintray": { - "user": "${BINTRAY_USERNAME}", - "key": "${BINTRAY_API_KEY}" - }, - "Version": "1" -} -EOF - -for path in `find built-packages/ -maxdepth 1 -type d`; do - IFS=_ read linux_version <<< $(basename "${path}") - for deb in `find "${path}" -maxdepth 1 -type f`; do - pkg_filename=$(basename "${deb}") - IFS=_ read pkg_name pkg_version pkg_arch <<< $(basename -s ".deb" "${pkg_filename}") - jfrog bt package-create --licenses ${BINTRAY_LICENSE} --vcs-url ${CI_PROJECT_URL} ${BINTRAY_REPO}/${pkg_name} || true - jfrog bt upload --deb ${linux_version}/main/${pkg_arch} ${deb} ${BINTRAY_REPO}/${pkg_name}/${pkg_version} pool/${linux_version}/main/${pkg_name}/ - done -done - diff --git a/configure.ac b/configure.ac index 1d444c7d..16022ccf 100644 --- a/configure.ac +++ b/configure.ac @@ -1,4 +1,4 @@ -AC_INIT(libprotoident, 2.0.14, contact@wand.net.nz) +AC_INIT(libprotoident, 2.0.15, contact@wand.net.nz) AM_INIT_AUTOMAKE AC_CONFIG_SRCDIR(lib/libprotoident.cc) diff --git a/debian/changelog b/debian/changelog index 76512708..c2074bb5 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,11 @@ +libprotoident (2.0.15-1) unstable; urgency=low + + * New upstream release. + * Added new API methods: lpi_get_category_by_protocol() and + lpi_get_category_by_name(). + * Improved rules for 6 protocols, including QUIC and Zoom + * Added 5 new protocols. + libprotoident (2.0.14-1) unstable; urgency=low * New upstream release. diff --git a/debpkg-build.sh b/debpkg-build.sh new file mode 100755 index 00000000..e5a3f823 --- /dev/null +++ b/debpkg-build.sh @@ -0,0 +1,12 @@ +#!/bin/bash + +set -x -e -o pipefail + +export DEBEMAIL='packaging@wand.net.nz' +export DEBFULLNAME='WAND Packaging' +export DEBIAN_FRONTEND=noninteractive + +export SOURCENAME=`echo ${GITHUB_REF##*/} | cut -d '-' -f 1` + +mk-build-deps -i -r -t 'apt-get -f -y --force-yes' +dpkg-buildpackage -b -us -uc -rfakeroot -j4 diff --git a/debpkg-setup.sh b/debpkg-setup.sh new file mode 100755 index 00000000..3f6317d4 --- /dev/null +++ b/debpkg-setup.sh @@ -0,0 +1,30 @@ +#!/bin/bash + +set -x -e -o pipefail + +export DEBEMAIL='packaging@wand.net.nz' +export DEBFULLNAME='WAND Packaging' +export DEBIAN_FRONTEND=noninteractive + +export SOURCENAME=`echo ${GITHUB_REF##*/} | cut -d '-' -f 1` + +apt-get update +apt-get install -y equivs devscripts dpkg-dev quilt curl apt-transport-https \ + apt-utils ssl-cert ca-certificates gnupg lsb-release debhelper git \ + pkg-config + +curl -1sLf 'https://dl.cloudsmith.io/public/wand/libwandio/cfg/setup/bash.deb.sh' | bash +curl -1sLf 'https://dl.cloudsmith.io/public/wand/libwandder/cfg/setup/bash.deb.sh' | bash +curl -1sLf 'https://dl.cloudsmith.io/public/wand/libtrace/cfg/setup/bash.deb.sh' | bash +curl -1sLf 'https://dl.cloudsmith.io/public/wand/libflowmanager/cfg/setup/bash.deb.sh' | bash + +DISTRO=$(lsb_release -sc) + +case ${DISTRO} in + jessie | xenial | stretch ) + curl -1sLf 'https://dl.cloudsmith.io/public/wand/dpdk-wand/cfg/setup/bash.deb.sh' | bash + ;; +esac + +apt-get update +apt-get upgrade -y diff --git a/gitlab-build.sh b/gitlab-build.sh deleted file mode 100755 index e4a490e2..00000000 --- a/gitlab-build.sh +++ /dev/null @@ -1,26 +0,0 @@ -#!/bin/bash - -set -x -e -o pipefail - -export DEBEMAIL='packaging@wand.net.nz' -export DEBFULLNAME='WAND Packaging' -export DEBIAN_FRONTEND=noninteractive - -SOURCENAME=`echo ${CI_COMMIT_REF_NAME} | cut -d '-' -f 1` - -apt-get update -apt-get install -y equivs devscripts dpkg-dev quilt curl apt-transport-https \ - apt-utils ssl-cert ca-certificates gnupg lsb-release debhelper git - -echo "deb https://dl.bintray.com/wand/general $(lsb_release -sc) main" | tee -a /etc/apt/sources.list.d/wand.list -echo "deb https://dl.bintray.com/wand/libtrace $(lsb_release -sc) main" | tee -a /etc/apt/sources.list.d/wand.list -echo "deb https://dl.bintray.com/wand/libflowmanager $(lsb_release -sc) main" | tee -a /etc/apt/sources.list.d/wand.list -curl --silent "https://bintray.com/user/downloadSubjectPublicKey?username=wand"\ - | apt-key add - - -apt-get update -apt-get upgrade -y - -dpkg-parsechangelog -S version | grep -q ${SOURCENAME} || debchange --newversion ${SOURCENAME} -b "New upstream release" -mk-build-deps -i -r -t 'apt-get -f -y --force-yes' -dpkg-buildpackage -b -us -uc -rfakeroot -j4 diff --git a/lib/Makefile.am b/lib/Makefile.am index bb1867fd..348f8a81 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -10,5 +10,5 @@ libprotoident_la_SOURCES=libprotoident.h libprotoident.cc \ INCLUDES=@ADD_INCLS@ libprotoident_la_LIBADD = @ADD_LIBS@ tcp/libprotoident_tcp.la \ udp/libprotoident_udp.la -libprotoident_la_LDFLAGS = @ADD_LDFLAGS@ -version-info 3:0:1 +libprotoident_la_LDFLAGS = @ADD_LDFLAGS@ -version-info 4:0:2 libprotoident_la_CPPFLAGS = -Werror diff --git a/lib/libprotoident.cc b/lib/libprotoident.cc index ef9418bc..163e837d 100644 --- a/lib/libprotoident.cc +++ b/lib/libprotoident.cc @@ -51,6 +51,8 @@ lpi_module_t *lpi_unknown_udp = NULL; static LPINameMap lpi_names; static LPIProtocolMap lpi_protocols; +static LPICategoryMap lpi_categories; +static LPICategoryProtocolMap lpi_category_protocols; static int seq_cmp (uint32_t seq_a, uint32_t seq_b) { @@ -79,10 +81,12 @@ int lpi_init_library() { if (register_udp_protocols(&UDP_protocols) == -1) return -1; - init_other_protocols(&lpi_names, &lpi_protocols); + init_other_protocols(&lpi_names, &lpi_protocols, &lpi_category_protocols); - register_names(&TCP_protocols, &lpi_names, &lpi_protocols); - register_names(&UDP_protocols, &lpi_names, &lpi_protocols); + register_names(&TCP_protocols, &lpi_names, &lpi_protocols, &lpi_category_protocols); + register_names(&UDP_protocols, &lpi_names, &lpi_protocols, &lpi_category_protocols); + + register_category_names(&lpi_categories); init_called = true; @@ -484,13 +488,37 @@ lpi_protocol_t lpi_get_protocol_by_name(char *name) { it = lpi_protocols.find(name); if (it == lpi_protocols.end()) { - return LPI_PROTO_LAST; + return LPI_PROTO_UNKNOWN; } return (it->second); } +lpi_category_t lpi_get_category_by_name(char *name) { + + LPICategoryMap::iterator it; + + it = lpi_categories.find(name); + + if (it == lpi_categories.end()) { + return LPI_CATEGORY_UNKNOWN; + } + + return (it->second); +} +lpi_category_t lpi_get_category_by_protocol(lpi_protocol_t protocol) { + + LPICategoryProtocolMap::iterator it; + + it = lpi_category_protocols.find(protocol); + + if (it == lpi_category_protocols.end()) { + return LPI_CATEGORY_UNKNOWN; + } + + return (it->second); +} bool lpi_is_protocol_inactive(lpi_protocol_t proto) { diff --git a/lib/libprotoident.h b/lib/libprotoident.h index 1acbb4d9..4281c7f2 100644 --- a/lib/libprotoident.h +++ b/lib/libprotoident.h @@ -400,6 +400,9 @@ typedef enum { LPI_PROTO_BEAM, LPI_PROTO_VHDP2P, LPI_PROTO_CLASSIN, + LPI_PROTO_TRANSOCKS, + LPI_PROTO_RAGNAROK_ONLINE, + LPI_PROTO_ETHERNETIP, /* UDP Protocols */ LPI_PROTO_UDP, @@ -417,6 +420,8 @@ typedef enum { LPI_PROTO_UDP_EMULE, LPI_PROTO_UDP_EYE, LPI_PROTO_UDP_RTP, + LPI_PROTO_UDP_ETHERNETIP, + LPI_PROTO_UDP_CIP_IO, /* Common industrial protocol IO */ LPI_PROTO_UDP_MSN_VIDEO, LPI_PROTO_UDP_COD, /* Call of Duty game protocol */ LPI_PROTO_UDP_NTP, @@ -641,6 +646,7 @@ typedef enum { LPI_PROTO_UDP_COD_MOBILE, LPI_PROTO_UDP_NVIDIA_GAMESTREAM, LPI_PROTO_UDP_CLASSIN, + LPI_PROTO_UDP_ARTCP, /* Patterns that we can match, but do not know the protocol */ LPI_PROTO_REJECTION, /* All responses are 0x02 */ @@ -793,9 +799,28 @@ lpi_module_t *lpi_guess_protocol(lpi_data_t *data); * @param name The protocol name * * @returns The LPI protocol for the supplied name. + * LPI_PROTO_UNKNOWN if the name is not found. */ lpi_protocol_t lpi_get_protocol_by_name(char *name); +/* Give the category name, returns the lpi category it matches. + * + * @param name The protocol name + * + * @returns the LPI category for the supplied name on success. + * LPI_CATEGORY_UNKNOWN if the name is not found. + */ +lpi_category_t lpi_get_category_by_name(char *name); + +/* Given the lpi protocol, returns the lpi category it matches. + * + * @param protocol The lpi protocol + * + * @returns the lpi category for the supplied lpi protocol. + * LPI_CATEGORY_UNKNOWN if the category is not found. + */ +lpi_category_t lpi_get_category_by_protocol(lpi_protocol_t protocol); + /** Determines whether the protocol matching a given protocol number is no * longer supported by libprotoident. * diff --git a/lib/proto_common.cc b/lib/proto_common.cc index 9589d1cd..6fffd05b 100644 --- a/lib/proto_common.cc +++ b/lib/proto_common.cc @@ -419,7 +419,6 @@ static inline bool match_tls_handshake(uint32_t payload, uint32_t len) { * XXX This isn't always true - consecutive packets may be merged it seems :( */ static inline bool match_ssl2_handshake(uint32_t payload, uint32_t len) { - uint32_t stated_len = 0; if (MATCH(payload, 0x80, ANY, 0x01, 0x03)) return true; @@ -800,7 +799,6 @@ bool match_tpkt(uint32_t payload, uint32_t len) { bool match_qqlive_payload(uint32_t payload, uint32_t len) { - uint8_t *ptr; uint32_t swap; /* This appears to have a 3 byte header. First byte is always 0xfe. diff --git a/lib/proto_manager.cc b/lib/proto_manager.cc index 445f6a79..e184ae3e 100644 --- a/lib/proto_manager.cc +++ b/lib/proto_manager.cc @@ -120,6 +120,7 @@ int register_tcp_protocols(LPIModuleMap *mod_map) { register_dxp(mod_map); register_ea_games(mod_map); register_emule(mod_map); + register_ethernetip(mod_map); register_eye(mod_map); register_facebook_turn(mod_map); register_fb_message(mod_map); @@ -241,6 +242,7 @@ int register_tcp_protocols(LPIModuleMap *mod_map) { register_qqspeedmobile_tcp(mod_map); register_qvod(mod_map); register_rabbitmq(mod_map); + register_ragnarokonline(mod_map); register_razor(mod_map); register_rbls(mod_map); register_rdp(mod_map); @@ -305,6 +307,7 @@ int register_tcp_protocols(LPIModuleMap *mod_map) { register_tor(mod_map); register_tpkt_generic(mod_map); register_trackmania(mod_map); + register_transocks(mod_map); register_trion(mod_map); register_trojan_win32_generic_sb(mod_map); register_trojan_zeroaccess(mod_map); @@ -366,6 +369,7 @@ int register_udp_protocols(LPIModuleMap *mod_map) { register_arksurvival(mod_map); register_arma_server(mod_map); register_arma3_server(mod_map); + register_artcp(mod_map); register_assettocorsa(mod_map); register_avast_secure_dns(mod_map); register_bacnet(mod_map); @@ -382,6 +386,8 @@ int register_udp_protocols(LPIModuleMap *mod_map) { register_chargen_exploit(mod_map); register_checkpoint_rdp(mod_map); register_chivalry(mod_map); + register_ethernetip_udp(mod_map); + register_cip_io(mod_map); register_cirn(mod_map); register_cisco_ipsec(mod_map); register_cisco_sslvpn(mod_map); @@ -606,7 +612,8 @@ int register_udp_protocols(LPIModuleMap *mod_map) { return 0; } -static void register_list_names(LPIModuleList *ml, LPINameMap *names, LPIProtocolMap *protos) { +static void register_list_names(LPIModuleList *ml, LPINameMap *names, LPIProtocolMap *protos, + LPICategoryProtocolMap *category_protocols) { LPIModuleList::iterator it; for (it = ml->begin(); it != ml->end(); it ++) { @@ -614,21 +621,33 @@ static void register_list_names(LPIModuleList *ml, LPINameMap *names, LPIProtoco (*names)[mod->protocol] = mod->name; (*protos)[std::string(mod->name)] = mod->protocol; + (*category_protocols)[mod->protocol] = mod->category; } } -void register_names(LPIModuleMap *mods, LPINameMap *names, LPIProtocolMap *protocols) { +void register_names(LPIModuleMap *mods, LPINameMap *names, LPIProtocolMap *protocols, + LPICategoryProtocolMap *category_protocols) { LPIModuleMap::iterator it; for (it = mods->begin(); it != mods->end(); it ++) { - register_list_names(it->second, names, protocols); + register_list_names(it->second, names, protocols, category_protocols); } } -void init_other_protocols(LPINameMap *name_map, LPIProtocolMap *proto_map) { +void register_category_names(LPICategoryMap *categories) { + + int i; + + for (i = 0; i < LPI_CATEGORY_LAST; i++) { + (*categories)[std::string(lpi_print_category((lpi_category_t)i))] = (lpi_category_t)i; + } +} + +void init_other_protocols(LPINameMap *name_map, LPIProtocolMap *proto_map, + LPICategoryProtocolMap *category_protocols) { lpi_icmp = new lpi_module_t; @@ -639,6 +658,7 @@ void init_other_protocols(LPINameMap *name_map, LPIProtocolMap *proto_map) { lpi_icmp->lpi_callback = NULL; (*name_map)[lpi_icmp->protocol] = lpi_icmp->name; (*proto_map)[std::string(lpi_icmp->name)] = lpi_icmp->protocol; + (*category_protocols)[lpi_icmp->protocol] = lpi_icmp->category; lpi_unknown_tcp = new lpi_module_t; @@ -649,6 +669,7 @@ void init_other_protocols(LPINameMap *name_map, LPIProtocolMap *proto_map) { lpi_unknown_tcp->lpi_callback = NULL; (*name_map)[lpi_unknown_tcp->protocol] = lpi_unknown_tcp->name; (*proto_map)[std::string(lpi_unknown_tcp->name)] = lpi_unknown_tcp->protocol; + (*category_protocols)[lpi_unknown_tcp->protocol] = lpi_unknown_tcp->category; lpi_unknown_udp = new lpi_module_t; @@ -659,6 +680,7 @@ void init_other_protocols(LPINameMap *name_map, LPIProtocolMap *proto_map) { lpi_unknown_udp->lpi_callback = NULL; (*name_map)[lpi_unknown_udp->protocol] = lpi_unknown_udp->name; (*proto_map)[std::string(lpi_unknown_udp->name)] = lpi_unknown_udp->protocol; + (*category_protocols)[lpi_unknown_udp->protocol] = lpi_unknown_udp->category; lpi_unsupported = new lpi_module_t; @@ -669,5 +691,6 @@ void init_other_protocols(LPINameMap *name_map, LPIProtocolMap *proto_map) { lpi_unsupported->lpi_callback = NULL; (*name_map)[lpi_unsupported->protocol] = lpi_unsupported->name; (*proto_map)[std::string(lpi_unsupported->name)] = lpi_unsupported->protocol; + (*category_protocols)[lpi_unsupported->protocol] = lpi_unsupported->category; } diff --git a/lib/proto_manager.h b/lib/proto_manager.h index 5ef4499d..9e5ff62b 100644 --- a/lib/proto_manager.h +++ b/lib/proto_manager.h @@ -39,12 +39,17 @@ typedef std::list LPIModuleList; typedef std::map LPIModuleMap; typedef std::map LPINameMap; typedef std::map LPIProtocolMap; +typedef std::map LPICategoryMap; +typedef std::map LPICategoryProtocolMap; void register_protocol(lpi_module_t *mod, LPIModuleMap *mod_map); int register_tcp_protocols(LPIModuleMap *mod_map); int register_udp_protocols(LPIModuleMap *mod_map); -void register_names(LPIModuleMap *mod_map, LPINameMap *name_map, LPIProtocolMap *proto_map); -void init_other_protocols(LPINameMap *name_map, LPIProtocolMap *proto_map); +void register_names(LPIModuleMap *mod_map, LPINameMap *name_map, LPIProtocolMap *proto_map, + LPICategoryProtocolMap *category_protocols); +void register_category_names(LPICategoryMap *categories); +void init_other_protocols(LPINameMap *name_map, LPIProtocolMap *proto_map, + LPICategoryProtocolMap *category_protocols); void free_protocols(LPIModuleMap *mod_map); diff --git a/lib/tcp/Makefile.am b/lib/tcp/Makefile.am index a13ae19b..4531a579 100644 --- a/lib/tcp/Makefile.am +++ b/lib/tcp/Makefile.am @@ -53,6 +53,7 @@ libprotoident_tcp_la_SOURCES = \ lpi_dxp.cc \ lpi_ea_games.cc \ lpi_emule.cc \ + lpi_ethernetip.cc \ lpi_eye.cc \ lpi_facebook_turn.cc \ lpi_fb_message.cc \ @@ -174,6 +175,7 @@ libprotoident_tcp_la_SOURCES = \ lpi_qqspeedmobile_tcp.cc \ lpi_qvod.cc \ lpi_rabbitmq.cc \ + lpi_ragnarokonline.cc \ lpi_razor.cc \ lpi_rbls.cc \ lpi_rdp.cc \ @@ -238,6 +240,7 @@ libprotoident_tcp_la_SOURCES = \ lpi_tor.cc \ lpi_tpkt.cc \ lpi_trackmania.cc \ + lpi_transocks.cc \ lpi_trion.cc \ lpi_trojan_win32_generic_sb.cc \ lpi_trojan_zeroaccess.cc \ diff --git a/lib/tcp/lpi_dns.cc b/lib/tcp/lpi_dns.cc index 83faf0e8..2f2468b7 100644 --- a/lib/tcp/lpi_dns.cc +++ b/lib/tcp/lpi_dns.cc @@ -50,9 +50,7 @@ static bool match_length_single(uint32_t payload, uint32_t len) { static bool match_dns_tcp_length(lpi_data_t *data) { - uint16_t length; uint32_t id0, id1; - void *ptr; if (data->payload_len[0] == 0 || data->payload_len[1] == 0) return false; diff --git a/lib/tcp/lpi_ethernetip.cc b/lib/tcp/lpi_ethernetip.cc new file mode 100644 index 00000000..e3096653 --- /dev/null +++ b/lib/tcp/lpi_ethernetip.cc @@ -0,0 +1,96 @@ +/* + * + * 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" + +static inline bool match_command(uint32_t payload) { + + // no op + if (MATCH(payload, 0x00, 0x00, ANY, ANY)) + return true; + // list services + if (MATCH(payload, 0x04, 0x00, ANY, ANY)) + return true; + // list identity + if (MATCH(payload, 0x63, 0x00, ANY, ANY)) + return true; + // list interfaces + if (MATCH(payload, 0x64, 0x00, ANY, ANY)) + return true; + // register session + if (MATCH(payload, 0x65, 0x00, 0x04, 0x00)) + return true; + // un-register session + if (MATCH(payload, 0x66, 0x00, ANY, ANY)) + return true; + // sendrrdata + if (MATCH(payload, 0x6f, 0x00, ANY, ANY)) + return true; + // send unit data + if (MATCH(payload, 0x70, 0x00, ANY, ANY)) + return true; + // indicate status + if (MATCH(payload, 0x72, 0x00, ANY, ANY)) + return true; + // cancel + if (MATCH(payload, 0x73, 0x00, ANY, ANY)) + return true; + // error + if (MATCH(payload, 0xff, 0xff, ANY, ANY)) + return true; + + return false; +} + +static inline bool match_ethernetip(lpi_data_t *data, lpi_module_t *mod UNUSED) { + + if (data->payload_len[0] < 24 || data->payload_len[1] < 24) + return false; + + if (data->server_port != 44818 && data->client_port != 44818) + return false; + + if (match_command(data->payload[0]) && match_command(data->payload[1])) + return true; + + return false; +} + +static lpi_module_t lpi_ethernetip = { + LPI_PROTO_ETHERNETIP, + LPI_CATEGORY_ICS, + "EtherNet/IP", + 100, + match_ethernetip +}; + +void register_ethernetip(LPIModuleMap *mod_map) { + register_protocol(&lpi_ethernetip, mod_map); +} diff --git a/lib/tcp/lpi_maplestory_china.cc b/lib/tcp/lpi_maplestory_china.cc index 21437ff8..16fa3077 100644 --- a/lib/tcp/lpi_maplestory_china.cc +++ b/lib/tcp/lpi_maplestory_china.cc @@ -59,6 +59,15 @@ static inline bool match_cms_alt(uint32_t payload, uint32_t len) { return false; } +static inline bool match_cms_51(uint32_t payload, uint32_t len) { + if (len == 16) { + if (MATCH(payload, 0x0e, 0x00, 0xc1, 0x00)) { + return true; + } + } + return false; +} + static inline bool match_maplestory_china(lpi_data_t *data, lpi_module_t *mod UNUSED) { /* Can also restrict to ports 8585 and 8586 if required */ @@ -83,6 +92,16 @@ static inline bool match_maplestory_china(lpi_data_t *data, lpi_module_t *mod UN return true; } + if (match_cms_51(data->payload[0], data->payload_len[0])) { + if (data->payload_len[1] == 51) + return true; + } + + if (match_cms_51(data->payload[1], data->payload_len[1])) { + if (data->payload_len[0] == 51) + return true; + } + return false; } diff --git a/lib/tcp/lpi_qq_tcp.cc b/lib/tcp/lpi_qq_tcp.cc index e9c21cd9..494a514c 100644 --- a/lib/tcp/lpi_qq_tcp.cc +++ b/lib/tcp/lpi_qq_tcp.cc @@ -31,7 +31,6 @@ #include "proto_common.h" static inline bool check_length(uint32_t payload, uint32_t len) { - uint16_t *lenptr; uint32_t swap; uint32_t length; diff --git a/lib/tcp/lpi_ragnarokonline.cc b/lib/tcp/lpi_ragnarokonline.cc new file mode 100644 index 00000000..27945ba8 --- /dev/null +++ b/lib/tcp/lpi_ragnarokonline.cc @@ -0,0 +1,87 @@ +/* + * + * 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" + +static inline bool match_ro_0204(uint32_t payload, uint32_t len) { + + if (len < 11) { + return false; + } + + if (MATCH(payload, 0x02, 0x04, 0x00, 0x21)) { + return true; + } + return false; +} + +static inline bool match_ro_reply(uint32_t payload, uint32_t len) { + if (len == 53 && MATCH(payload, 0x00, 0x32, 0x00, 0x01)) { + return true; + } + if (len == 57 && MATCH(payload, 0x00, 0x36, 0x00, 0x01)) { + return true; + } + return false; +} + +static inline bool match_ragnarokonline(lpi_data_t *data, lpi_module_t *mod UNUSED) { + + if (data->server_port != 5222 && data->client_port != 5222) { + return false; + } + + if (match_ro_0204(data->payload[0], data->payload_len[0])) { + if (match_ro_reply(data->payload[1], data->payload_len[1])) { + return true; + } + } + + if (match_ro_0204(data->payload[1], data->payload_len[1])) { + if (match_ro_reply(data->payload[0], data->payload_len[0])) { + return true; + } + } + + return false; +} + +static lpi_module_t lpi_ragnarokonline = { + LPI_PROTO_RAGNAROK_ONLINE, + LPI_CATEGORY_GAMING, + "RagnarokOnline", + 80, + match_ragnarokonline +}; + +void register_ragnarokonline(LPIModuleMap *mod_map) { + register_protocol(&lpi_ragnarokonline, mod_map); +} + diff --git a/lib/tcp/lpi_transocks.cc b/lib/tcp/lpi_transocks.cc new file mode 100644 index 00000000..0190a828 --- /dev/null +++ b/lib/tcp/lpi_transocks.cc @@ -0,0 +1,100 @@ +/* + * + * 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" + +/* Chinese VPN for accessing mainland content */ + +static inline bool match_ts_23(uint32_t payload, uint32_t len) { + + if (len == 23 && MATCH(payload, 0x00, 0x00, 0x00, 0x00)) { + return true; + } + + return false; +} + +static inline bool match_ts_reply(uint32_t payload, uint32_t len) { + + /* Payload is random, but we could add rules to return false + * if the payload is 00000000 or ffffffff (or any other clearly + * intentional pattern), if this is generating FPs. + */ + + /* Lower path MTUs would affect this number, but let's concentrate + * on getting the lowest hanging fruit for now. + */ + if (len == 1460 || len == 1406 || len == 1356) { + return true; + } + + /* 503 is also a common length? also seen 501 and 507 occasionally.. */ + if (len == 503) { + return true; + } + + /* Starting to see a bit of variation in reply sizes now :/ */ + if (len >= 678 && len <= 688) { + return true; + } + + return false; + +} + +static inline bool match_transocks(lpi_data_t *data, lpi_module_t *mod UNUSED) { + + if (match_ts_23(data->payload[0], data->payload_len[0])) { + if (match_ts_reply(data->payload[1], data->payload_len[1])) { + return true; + } + } + + if (match_ts_23(data->payload[0], data->payload_len[0])) { + if (match_ts_reply(data->payload[1], data->payload_len[1])) { + return true; + } + } + + return false; +} + +static lpi_module_t lpi_transocks = { + LPI_PROTO_TRANSOCKS, + LPI_CATEGORY_TUNNELLING, + "Transocks", + 240, + match_transocks +}; + +void register_transocks(LPIModuleMap *mod_map) { + register_protocol(&lpi_transocks, mod_map); +} + diff --git a/lib/tcp/lpi_whois.cc b/lib/tcp/lpi_whois.cc index e20fea3d..f27c60b8 100644 --- a/lib/tcp/lpi_whois.cc +++ b/lib/tcp/lpi_whois.cc @@ -150,8 +150,6 @@ static inline bool match_digit_last(uint32_t payload) { static inline bool match_ipv4_text(uint32_t payload) { - bool seen_dot = false; - /* Gotta start with a digit */ if (!match_digit_first(payload)) return false; diff --git a/lib/tcp/tcp_protocols.h b/lib/tcp/tcp_protocols.h index ca30b72a..89c2bf7e 100644 --- a/lib/tcp/tcp_protocols.h +++ b/lib/tcp/tcp_protocols.h @@ -81,6 +81,7 @@ void register_dvrns(LPIModuleMap *mod_map); void register_dxp(LPIModuleMap *mod_map); void register_ea_games(LPIModuleMap *mod_map); void register_emule(LPIModuleMap *mod_map); +void register_ethernetip(LPIModuleMap *mod_map); void register_eye(LPIModuleMap *mod_map); void register_facebook_turn(LPIModuleMap *mod_map); void register_fb_message(LPIModuleMap *mod_map); @@ -202,6 +203,7 @@ void register_qqlive_tcp(LPIModuleMap *mod_map); void register_qqspeedmobile_tcp(LPIModuleMap *mod_map); void register_qvod(LPIModuleMap *mod_map); void register_rabbitmq(LPIModuleMap *mod_map); +void register_ragnarokonline(LPIModuleMap *mod_map); void register_razor(LPIModuleMap *mod_map); void register_rbls(LPIModuleMap *mod_map); void register_rdp(LPIModuleMap *mod_map); @@ -266,6 +268,7 @@ void register_tip(LPIModuleMap *mod_map); void register_tor(LPIModuleMap *mod_map); void register_tpkt_generic(LPIModuleMap *mod_map); void register_trackmania(LPIModuleMap *mod_map); +void register_transocks(LPIModuleMap *mod_map); void register_trion(LPIModuleMap *mod_map); void register_trojan_win32_generic_sb(LPIModuleMap *mod_map); void register_trojan_zeroaccess(LPIModuleMap *mod_map); diff --git a/lib/udp/Makefile.am b/lib/udp/Makefile.am index 86315e65..1080cbea 100644 --- a/lib/udp/Makefile.am +++ b/lib/udp/Makefile.am @@ -13,6 +13,7 @@ libprotoident_udp_la_SOURCES = \ lpi_ark.cc \ lpi_arma_server.cc \ lpi_arma3_server.cc \ + lpi_artcp.cc \ lpi_assettocorsa.cc \ lpi_avast_secure_dns.cc \ lpi_backweb.cc \ @@ -28,6 +29,8 @@ libprotoident_udp_la_SOURCES = \ lpi_chargen_exploit.cc \ lpi_checkpoint_rdp.cc \ lpi_chivalry.cc \ + lpi_ethernetip.cc \ + lpi_cip_io.cc \ lpi_cirn.cc \ lpi_cisco_ipsec.cc \ lpi_cisco_sslvpn.cc \ diff --git a/lib/udp/lpi_artcp.cc b/lib/udp/lpi_artcp.cc new file mode 100644 index 00000000..ddbfa269 --- /dev/null +++ b/lib/udp/lpi_artcp.cc @@ -0,0 +1,72 @@ +/* + * + * 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" + +/* Custom version of RTCP used by Alibaba cloud for streaming */ + +static inline bool match_artcp_payload(uint32_t payload, uint32_t len) { + if (len == 0) + return true; + if (MATCH(payload, 0x83, 0xcc, 0x00, ANY)) + return true; + return false; +} + + +static inline bool match_artcp(lpi_data_t *data, lpi_module_t *mod UNUSED) { + + + if (data->server_port == 1106 || data->client_port == 1106) { + + if (!match_artcp_payload(data->payload[0], + data->payload_len[0])) + return false; + if (!match_artcp_payload(data->payload[1], + data->payload_len[1])) + return false; + return true; + } + return false; + +} + +static lpi_module_t lpi_artcp = { + LPI_PROTO_UDP_ARTCP, + LPI_CATEGORY_STREAMING, + "ARTCP", + 200, + match_artcp +}; + +void register_artcp(LPIModuleMap *mod_map) { + register_protocol(&lpi_artcp, mod_map); +} + diff --git a/lib/udp/lpi_cip_io.cc b/lib/udp/lpi_cip_io.cc new file mode 100644 index 00000000..0a028d29 --- /dev/null +++ b/lib/udp/lpi_cip_io.cc @@ -0,0 +1,69 @@ +/* + * + * 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 . + * + * 239.192.27.192 10.1.1.215 2222 2222 17 1599194119.713 1599194136.242 0 527360 00000000 .... 0 02000280 .... 80 + * 10.1.1.215 10.1.1.200 2222 2222 17 1599194119.716 1599194136.397 187488 0 02000280 .... 56 00000000 .... 0 + */ + +#include + +#include "libprotoident.h" +#include "proto_manager.h" +#include "proto_common.h" + +static inline bool match_cip(lpi_data_t *data) { + + if (MATCH(data->payload[0], 0x02, 0x00, 0x02, 0x80) && + MATCH(data->payload[1], 0x00, 0x00, 0x00, 0x00)) + return true; + + if (MATCH(data->payload[1], 0x02, 0x00, 0x02, 0x80) && + MATCH(data->payload[0], 0x00, 0x00, 0x00, 0x00)) + return true; + + return false; +} + +static inline bool match_cip_io(lpi_data_t *data, lpi_module_t *mod UNUSED) { + + if (data->server_port != 2222 || data->client_port != 2222) + return false; + + if (match_cip(data)) + return true; + + return false; +} + +static lpi_module_t lpi_cip_io = { + LPI_PROTO_UDP_CIP_IO, + LPI_CATEGORY_ICS, + "CIP_I/O", + 100, + match_cip_io +}; + +void register_cip_io(LPIModuleMap *mod_map) { + register_protocol(&lpi_cip_io, mod_map); +} + diff --git a/lib/udp/lpi_ethernetip.cc b/lib/udp/lpi_ethernetip.cc new file mode 100644 index 00000000..1c43f4af --- /dev/null +++ b/lib/udp/lpi_ethernetip.cc @@ -0,0 +1,103 @@ +/* + * + * 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 . + * + * + * 255.255.255.255 192.168.10.105 44818 1136 17 1226525494.728 1226525530.720 0 888 00000000 .... 0 63000000 c... 24 + * 192.168.10.105 192.168.10.120 1136 44818 17 1226525494.730 1226525530.722 2775 0 63003300 c.3. 75 00000000 .... 0 + */ + +#include + +#include "libprotoident.h" +#include "proto_manager.h" +#include "proto_common.h" + +static inline bool match_command(uint32_t payload, uint16_t payload_len) { + + // the second uint16 of the ethernetip header is payload the length + // but not including the header size of 24 bytes + uint16_t len = ntohs((uint16_t)ntohl(payload)) + 24; + + if (payload_len != len) + return false; + + // no op + if (MATCH(payload, 0x00, 0x00, ANY, ANY)) + return true; + // list services + if (MATCH(payload, 0x04, 0x00, ANY, ANY)) + return true; + // list identity + if (MATCH(payload, 0x63, 0x00, ANY, ANY)) + return true; + // list interfaces + if (MATCH(payload, 0x64, 0x00, ANY, ANY)) + return true; + // register session + if (MATCH(payload, 0x65, 0x00, 0x04, 0x00)) + return true; + // un-register session + if (MATCH(payload, 0x66, 0x00, ANY, ANY)) + return true; + // sendrrdata + if (MATCH(payload, 0x6f, 0x00, ANY, ANY)) + return true; + // send unit data + if (MATCH(payload, 0x70, 0x00, ANY, ANY)) + return true; + // indicate status + if (MATCH(payload, 0x72, 0x00, ANY, ANY)) + return true; + // cancel + if (MATCH(payload, 0x73, 0x00, ANY, ANY)) + return true; + // error + if (MATCH(payload, 0xff, 0xff, ANY, ANY)) + return true; + + return false; +} + +static inline bool match_ethernetip_udp(lpi_data_t *data, lpi_module_t *mod UNUSED) { + + if (data->server_port != 44818 && data->client_port != 44818) + return false; + + if (match_command(data->payload[0], data->payload_len[0]) || + match_command(data->payload[1], data->payload_len[1])) + return true; + + return false; +} + +static lpi_module_t lpi_ethernetip_udp = { + LPI_PROTO_UDP_ETHERNETIP, + LPI_CATEGORY_ICS, + "EtherNet/IP_UDP", + 100, + match_ethernetip_udp +}; + +void register_ethernetip_udp(LPIModuleMap *mod_map) { + register_protocol(&lpi_ethernetip_udp, mod_map); +} diff --git a/lib/udp/lpi_ntp_reflect.cc b/lib/udp/lpi_ntp_reflect.cc index 92502f94..5a91cf51 100644 --- a/lib/udp/lpi_ntp_reflect.cc +++ b/lib/udp/lpi_ntp_reflect.cc @@ -51,7 +51,7 @@ static inline bool match_monlist_reply(uint32_t payload, uint32_t len) { /* NTPv2 reply */ if (MATCH(payload, 0x97, 0x00, 0x03, 0x2a)) return true; - if (MATCH(payload, 0xd7, 0x00, 0x03, 0x2a)) + if (MATCH(payload, 0xd7, ANY, 0x03, 0x2a)) return true; /* NTPv3 reply */ diff --git a/lib/udp/lpi_quic.cc b/lib/udp/lpi_quic.cc index 0812aa6c..eeb50b20 100644 --- a/lib/udp/lpi_quic.cc +++ b/lib/udp/lpi_quic.cc @@ -166,6 +166,64 @@ static inline bool match_old_gquic(lpi_data_t *data) { return false; } +static inline bool match_05X_req(uint32_t payload, uint32_t len) { + + if ((ntohl(payload) & 0xf0000000) != 0xc0000000) { + return false; + } + if (MATCH(payload, ANY, 0x51, 0x30, 0x35)) { + if (len == 42) { + return true; + } + + if (len == 1350 || len == 1330) { + return true; + } + } + + if (MATCH(payload, ANY, 0x54, 0x30, 0x35)) { + if (len == 1350 || len == 1330) { + return true; + } + } + + return false; +} + +static inline bool match_05X_reply(uint32_t payload, uint32_t len, + uint32_t other) { + + if ((ntohl(payload) & 0x00ff0000) != (ntohl(other) & 0x00ff0000)) { + return false; + } + + if ((ntohl(payload) & 0xf0000000) == 0xc0000000) { + if (MATCH(payload, ANY, 0x51, 0x30, 0x35)) { + if (len == 1350 || len == 1330) { + return true; + } + } + + if (MATCH(payload, ANY, 0x54, 0x30, 0x35)) { + if (len == 1350 || len == 1330) { + return true; + } + } + } + + if ((ntohl(payload) & 0xff000000) == 0xd5000000) { + if (!MATCH(payload, ANY, 0x51, 0x30, 0x35)) { + return false; + } + + if (len == 1350 || len == 1330) { + return true; + } + } + + return false; +} + static inline bool match_req_q044(uint32_t payload, uint32_t len) { if (MATCHSTR(payload, "\xffQ04") && len == 1350) { @@ -177,7 +235,7 @@ static inline bool match_req_q044(uint32_t payload, uint32_t len) { return true; } if (MATCH(payload, 0xc3, 'Q', '0', '4') && - (len == 1350 || len == 1330)) { + (len == 36 || len == 1350 || len == 1330)) { return true; } return false; @@ -206,6 +264,8 @@ static inline bool match_reply_q044(uint32_t payload, uint32_t len) { return false; } + + /* IETF QUIC version 44, starting to be deployed by Google */ static inline bool match_quic_044(lpi_data_t *data) { @@ -224,8 +284,25 @@ static inline bool match_quic_044(lpi_data_t *data) { return false; } +static inline bool match_quic_05X(lpi_data_t *data) { + if (match_05X_req(data->payload[0], data->payload_len[0])) { + if (match_05X_reply(data->payload[1], data->payload_len[1], + data->payload[0])) { + return true; + } + } + + if (match_05X_req(data->payload[1], data->payload_len[1])) { + if (match_05X_reply(data->payload[0], data->payload_len[0], + data->payload[1])) { + return true; + } + } + return false; +} + static inline bool match_reply_fbquic(uint32_t payload, uint32_t len) { - if (len >= 45 && len <= 50) { + if ((len >= 38 && len <= 50) || len == 1252 || len == 1232) { if ((ntohl(payload) & 0xf0000000) != 0xc0000000) { return false; } @@ -237,7 +314,7 @@ static inline bool match_reply_fbquic(uint32_t payload, uint32_t len) { } static inline bool match_req_fbquic(uint32_t payload, uint32_t len) { - if (len == 1235) { + if (len == 1232 || len == 1235) { if ((ntohl(payload) & 0xf0000000) != 0xc0000000) { return false; } @@ -273,6 +350,10 @@ static inline bool match_quic(lpi_data_t *data, lpi_module_t *mod UNUSED) { return true; } + if (match_quic_05X(data)) { + return true; + } + if (match_fb_quic(data)) { return true; } diff --git a/lib/udp/lpi_snmp.cc b/lib/udp/lpi_snmp.cc index 13fd070a..7e724340 100644 --- a/lib/udp/lpi_snmp.cc +++ b/lib/udp/lpi_snmp.cc @@ -35,7 +35,6 @@ static inline bool match_snmp_payload(uint32_t payload, uint32_t len) { /* SNMP is BER encoded, which is an ass to decode */ uint8_t snmplen = 0; uint8_t *byte; - int i; if (len == 0) return true; diff --git a/lib/udp/lpi_stun.cc b/lib/udp/lpi_stun.cc index 6c91f796..a6eedce4 100644 --- a/lib/udp/lpi_stun.cc +++ b/lib/udp/lpi_stun.cc @@ -40,6 +40,8 @@ static bool match_facetime_stun_request(uint32_t payload, uint32_t len) { return true; if (MATCH(payload, 0x0f, 0xe1, ANY, ANY)) return true; + if (MATCH(payload, 0x0f, 0xe4, ANY, ANY)) + return true; return false; } @@ -54,6 +56,22 @@ static bool match_facetime_stun_response(uint32_t payload, uint32_t len) { return true; if (MATCH(payload, 0x0e, 0xe1, ANY, ANY)) return true; + if (MATCH(payload, 0x0e, 0xe4, ANY, ANY)) + return true; + return false; + +} + +static bool match_skype_stun_request(uint32_t payload, uint32_t len) { + + /* Bytes 3 and 4 are the Message Length - the STUN header */ + if ((ntohl(payload) & 0x0000ffff) != len - 20) + return false; + + /* These flows start with an Allocate Request */ + if (MATCH(payload, 0x00, 0x03, ANY, ANY)) + return true; + return false; } @@ -80,6 +98,10 @@ static bool match_stun_payload(uint32_t payload, uint32_t len) { if (MATCH(payload, 0x01, 0x13, ANY, ANY)) return true; + /* Data Indication message (used by Skype) */ + if (MATCH(payload, 0x01, 0x15, ANY, ANY)) + return true; + return false; } diff --git a/lib/udp/lpi_warthunder.cc b/lib/udp/lpi_warthunder.cc index e645d4da..b98a78ec 100644 --- a/lib/udp/lpi_warthunder.cc +++ b/lib/udp/lpi_warthunder.cc @@ -46,6 +46,10 @@ static inline bool match_warthunder_req(uint32_t payload, uint32_t len) { return true; if (len == 52 && MATCHSTR(payload, "\xcf\xff\x00\x03")) return true; + if (len == 53 && MATCHSTR(payload, "\xcf\xff\x00\x04")) + return true; + if (len == 53 && MATCHSTR(payload, "\xcf\xff\x00\x05")) + return true; return false; } @@ -54,6 +58,8 @@ static inline bool match_warthunder_resp(uint32_t payload, uint32_t len) { if (len == 48 && MATCH(payload, 0xc0, 0x00, ANY, ANY)) return true; + if (len == 49 && MATCH(payload, 0xc0, 0x00, ANY, ANY)) + return true; if (len == 52 && MATCH(payload, 0xc0, 0x00, ANY, ANY)) return true; return false; diff --git a/lib/udp/lpi_zoom.cc b/lib/udp/lpi_zoom.cc index b02cb32e..4ad3ca54 100644 --- a/lib/udp/lpi_zoom.cc +++ b/lib/udp/lpi_zoom.cc @@ -36,6 +36,11 @@ static inline bool match_zoom_01(uint32_t payload, uint32_t len) { if (len == 107 || len == 109 || len == 169) return true; } + if (MATCH(payload, 0x01, 0x00, 0x03, ANY)) { + if (len == 187 || len == 185 || len == 123 || len == 125) { + return true; + } + } if (MATCH(payload, 0x01, 0x00, 0x6c, 0x00) && len == 111) return true; return false; @@ -46,6 +51,10 @@ static inline bool match_zoom_02(uint32_t payload, uint32_t len) { if (MATCH(payload, 0x02, 0x00, 0x01, ANY) && len == 35) return true; + if (MATCH(payload, 0x02, 0x00, 0x03, ANY) && len == 105) + return true; + if (MATCH(payload, 0x02, 0x00, 0x03, ANY) && len == 43) + return true; if (MATCH(payload, 0x02, 0x00, 0x22, 0x00) && len == 37) return true; if (MATCH(payload, 0x02, 0x00, 0x24, 0x00) && len == 39) @@ -59,14 +68,16 @@ static inline bool match_zoom_05(uint32_t payload) { return true; if (MATCH(payload, 0x05, 0x0f, 0x01, 0x00)) return true; + if (MATCH(payload, 0x05, 0x15, 0x01, 0x00)) + return true; return false; } static inline bool match_zoom_stream_hello(uint32_t payload, uint32_t len) { - /* Seen 85 and 86 so far */ - if (len >= 80 && len <= 90) { + /* Seen 72, 85 and 86 so far */ + if (len >= 72 && len <= 90) { if (MATCH(payload, 0x1f, 0x01, 0x01, 0x00)) return true; } diff --git a/lib/udp/udp_protocols.h b/lib/udp/udp_protocols.h index 5d2ac41b..9553d458 100644 --- a/lib/udp/udp_protocols.h +++ b/lib/udp/udp_protocols.h @@ -43,6 +43,7 @@ void register_ares_udp(LPIModuleMap *mod_map); void register_arksurvival(LPIModuleMap *mod_map); void register_arma_server(LPIModuleMap *mod_map); void register_arma3_server(LPIModuleMap *mod_map); +void register_artcp(LPIModuleMap *mod_map); void register_assettocorsa(LPIModuleMap *mod_map); void register_avast_secure_dns(LPIModuleMap *mod_map); void register_backweb(LPIModuleMap *mod_map); @@ -59,6 +60,8 @@ void register_canon_mfnp(LPIModuleMap *mod_map); void register_chargen_exploit(LPIModuleMap *mod_map); void register_checkpoint_rdp(LPIModuleMap *mod_map); void register_chivalry(LPIModuleMap *mod_map); +void register_ethernetip_udp(LPIModuleMap *mod_map); +void register_cip_io(LPIModuleMap *mod_map); void register_cirn(LPIModuleMap *mod_map); void register_cisco_ipsec(LPIModuleMap *mod_map); void register_cisco_sslvpn(LPIModuleMap *mod_map); diff --git a/rpm/libprotoident.spec b/rpm/libprotoident.spec new file mode 100644 index 00000000..be72677d --- /dev/null +++ b/rpm/libprotoident.spec @@ -0,0 +1,76 @@ +Name: libprotoident +Version: 2.0.15 +Release: 1%{?dist} +Summary: C/C++ Library for performing lightweight traffic classification + +License: LGPLv3 +URL: https://github.com/wanduow/libprotoident +Source0: https://github.com/wanduow/libprotoident/archive/%{version}.tar.gz + +BuildRequires: gcc +BuildRequires: gcc-c++ +BuildRequires: make +BuildRequires: libtrace4-devel +BuildRequires: libflowmanager-devel + +Provides: libprotoident + +%description +libprotoident is a library that can perform traffic classification +on each network flow observed via a packet capture process (including +pcap trace files and many common live packet capture approaches). +The classification is performed by examining the packet headers and +first four bytes of application payload only, so can be used in +environments where full payload capture is not possible. + +libprotoident is developed by the WAND Network Research Group at Waikato +University in New Zealand. + +%package devel +Summary: Development files for %{name} +Requires: %{name}%{?_isa} = %{version}-%{release} + +%description devel +The %{name}-devel package contains libraries and header files for +developing applications that use %{name}. + +%package tools +Summary: Example software utilities for %{name} +Requires: %{name}%{?_isa} = %{version}-%{release} + +%description tools +The %{name}-tools package contains example utilities that make use of the +%{name} library. + +%prep +%setup -q -n libprotoident-%{version} + +%build +%configure --disable-static +make %{?_smp_mflags} + + +%install +rm -rf $RPM_BUILD_ROOT +%make_install +find $RPM_BUILD_ROOT -name '*.la' -exec rm -f {} ';' + +%post -p /sbin/ldconfig + +%postun -p /sbin/ldconfig + +%files +%license COPYING +%{_libdir}/libprotoident.so.* + +%files devel +%{_includedir}/libprotoident* +%{_libdir}/libprotoident.so + +%files tools +%{_bindir}/* +%{_mandir}/man1/* + +%changelog +* Thu Nov 12 2020 Shane Alcock - 2.0.15-1 +- First libprotoident RPM package diff --git a/rpmpkg-build.sh b/rpmpkg-build.sh new file mode 100755 index 00000000..e3925358 --- /dev/null +++ b/rpmpkg-build.sh @@ -0,0 +1,14 @@ +#!/bin/bash + +set -x -e -o pipefail + +export QA_RPATHS=$[ 0x0001 ] +SOURCENAME=`echo ${GITHUB_REF##*/} | cut -d '-' -f 1` + +./bootstrap.sh && ./configure && make dist +cp libprotoident-*.tar.gz ~/rpmbuild/SOURCES/${SOURCENAME}.tar.gz +cp rpm/libprotoident.spec ~/rpmbuild/SPECS/ + +cd ~/rpmbuild && rpmbuild -bb --define "debug_package %{nil}" SPECS/libprotoident.spec + + diff --git a/rpmpkg-setup.sh b/rpmpkg-setup.sh new file mode 100755 index 00000000..30524d50 --- /dev/null +++ b/rpmpkg-setup.sh @@ -0,0 +1,56 @@ +#!/bin/bash +set -x -e -o pipefail + + +DISTRO=fedora +if [ "$1" = "centos:8" ]; then + DISTRO=centos +fi + +if [ "$1" = "centos:7" ]; then + DISTRO=centos +fi + +mkdir -p /run/user/${UID} +chmod 0700 /run/user/${UID} +yum install -y wget make gcc + +curl -1sLf \ + 'https://dl.cloudsmith.io/public/wand/libwandio/cfg/setup/bash.rpm.sh' \ + | bash + +curl -1sLf \ + 'https://dl.cloudsmith.io/public/wand/libwandder/cfg/setup/bash.rpm.sh' \ + | bash + +curl -1sLf \ + 'https://dl.cloudsmith.io/public/wand/libtrace/cfg/setup/bash.rpm.sh' \ + | bash + +curl -1sLf \ + 'https://dl.cloudsmith.io/public/wand/libflowmanager/cfg/setup/bash.rpm.sh' \ + | bash + +yum update -y + +if [ "$1" = "centos:8" ]; then + yum install -y https://dl.fedoraproject.org/pub/epel/epel-release-latest-8.noarch.rpm || true + dnf install -y 'dnf-command(config-manager)' || true + yum config-manager --set-enabled PowerTools || true +fi + +if [ "$1" = "centos:7" ]; then + yum install -y https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm || true +fi + +if [[ "$1" =~ fedora* ]]; then + dnf install -y rpm-build rpmdevtools 'dnf-command(builddep)' which + dnf group install -y "C Development Tools and Libraries" + dnf builddep -y rpm/libprotoident.spec +else + yum install -y rpm-build yum-utils rpmdevtools which + yum groupinstall -y 'Development Tools' + yum-builddep -y rpm/libprotoident.spec +fi + +rpmdev-setuptree diff --git a/tools/arff/lpi_arff.cc b/tools/arff/lpi_arff.cc index ada48d72..64037f3f 100644 --- a/tools/arff/lpi_arff.cc +++ b/tools/arff/lpi_arff.cc @@ -132,7 +132,6 @@ typedef struct ident { static void *start_processing(libtrace_t *trace, libtrace_thread_t *thread, void *global) { - bool opt_true = true; bool opt_false = false; struct globalopts *opts = (struct globalopts *)global; @@ -239,8 +238,6 @@ char *display_ident(Flow *f, IdentFlow *ident, struct globalopts *opts) char iat_stats_in[200]; char *str; lpi_module_t *proto; - struct ident_stats *is; - int i; if (opts->only_dir0 && ident->init_dir == 1) return NULL; @@ -290,7 +287,6 @@ void expire_ident_flows(libtrace_t *trace, libtrace_thread_t *thread, double ts, bool exp_flag) { Flow *expired; - lpi_module_t *proto; char *result = NULL; libtrace_generic_t gen; @@ -402,7 +398,7 @@ static libtrace_packet_t *per_packet(libtrace_t *trace, libtrace_packet_t *packet) { Flow *f; IdentFlow *ident = NULL; - uint8_t dir; + uint8_t dir = 255; bool is_new = false; libtrace_tcp_t *tcp = NULL; @@ -505,22 +501,16 @@ static void usage(char *prog) int main(int argc, char *argv[]) { - libtrace_t *trace; - libtrace_packet_t *packet; libtrace_filter_t *filter = NULL; struct sigaction sigact; struct globalopts opts; int threads = 1; int bufferresults = 10; - bool opt_true = true; - bool opt_false = false; - int i, opt; double ts; char *filterstring = NULL; int dir; - bool ignore_rfc1918 = false; libtrace_callback_set_t *processing, *reporter; diff --git a/tools/find_unknown/lpi_find_unknown.cc b/tools/find_unknown/lpi_find_unknown.cc index 58a019d6..9f4e96af 100644 --- a/tools/find_unknown/lpi_find_unknown.cc +++ b/tools/find_unknown/lpi_find_unknown.cc @@ -91,7 +91,6 @@ typedef struct ident { static void *start_processing(libtrace_t *trace, libtrace_thread_t *thread, void *global) { - bool opt_true = true; bool opt_false = false; struct globalopts *opts = (struct globalopts *)global; @@ -159,7 +158,6 @@ void dump_payload(lpi_data_t lpi, uint8_t dir, char *space, int spacelen) { int i; uint8_t *pl = (uint8_t *)(&(lpi.payload[dir])); - uint32_t len = lpi.payload_len[dir]; char ascii[4][5]; @@ -241,7 +239,6 @@ void expire_ident_flows(libtrace_t *trace, libtrace_thread_t *thread, struct globalopts *opts, FlowManager *fm, double ts, bool exp_flag) { Flow *expired; - lpi_module_t *proto; char *result = NULL; libtrace_generic_t gen; @@ -296,7 +293,7 @@ static libtrace_packet_t *per_packet(libtrace_t *trace, Flow *f; IdentFlow *ident = NULL; - uint8_t dir; + uint8_t dir = 255; bool is_new = false; libtrace_tcp_t *tcp = NULL; @@ -411,7 +408,6 @@ int main(int argc, char *argv[]) { struct sigaction sigact; struct globalopts opts; int i, opt; - double ts; char *filterstring = NULL; int dir; int threads = 1; diff --git a/tools/protoident/lpi_protoident.cc b/tools/protoident/lpi_protoident.cc index 9dfb6f23..9e341f32 100644 --- a/tools/protoident/lpi_protoident.cc +++ b/tools/protoident/lpi_protoident.cc @@ -91,7 +91,6 @@ typedef struct ident { static void *start_processing(libtrace_t *trace, libtrace_thread_t *thread, void *global) { - bool opt_true = true; bool opt_false = false; struct globalopts *opts = (struct globalopts *)global; @@ -159,7 +158,6 @@ void dump_payload(lpi_data_t lpi, uint8_t dir, char *space, int spacelen) { int i; uint8_t *pl = (uint8_t *)(&(lpi.payload[dir])); - uint32_t len = lpi.payload_len[dir]; char ascii[4][5]; @@ -167,7 +165,7 @@ void dump_payload(lpi_data_t lpi, uint8_t dir, char *space, int spacelen) { if (*pl > 32 && *pl < 126) { snprintf(ascii[i], 5, "%c", *pl); } else { - snprintf(ascii[i], 5, ".", NULL); + snprintf(ascii[i], 5, "."); } pl ++; } @@ -235,7 +233,6 @@ void expire_ident_flows(libtrace_t *trace, libtrace_thread_t *thread, struct globalopts *opts, FlowManager *fm, double ts, bool exp_flag) { Flow *expired; - lpi_module_t *proto; char *result = NULL; libtrace_generic_t gen; @@ -290,14 +287,14 @@ static libtrace_packet_t *per_packet(libtrace_t *trace, Flow *f; IdentFlow *ident = NULL; - uint8_t dir; + uint8_t dir = 255; bool is_new = false; libtrace_tcp_t *tcp = NULL; void *l3; double ts; - uint16_t l3_type; + uint16_t l3_type = 0; struct globalopts *opts = (struct globalopts *)global; struct threadlocal *tl = (struct threadlocal *)tls; @@ -405,7 +402,6 @@ int main(int argc, char *argv[]) { struct sigaction sigact; struct globalopts opts; int i, opt; - double ts; char *filterstring = NULL; int dir; int threads = 1; diff --git a/tools/tools_common.cc b/tools/tools_common.cc index d7de5750..444032d9 100644 --- a/tools/tools_common.cc +++ b/tools/tools_common.cc @@ -97,10 +97,12 @@ int port_get_direction(libtrace_packet_t *packet) { ip = (libtrace_ip_t *)l3; proto = ip->ip_p; } - if (ethertype == TRACE_ETHERTYPE_IPV6 && rem >= sizeof(libtrace_ip6_t)) { + else if (ethertype == TRACE_ETHERTYPE_IPV6 && rem >= sizeof(libtrace_ip6_t)) { ip6 = (libtrace_ip6_t *)l3; proto = ip6->nxt; - } + } else { + return -1; + } if (src_port == dst_port) {