pax_global_header00006660000000000000000000000064122425006320014506gustar00rootroot0000000000000052 comment=81325324c6fddb1a2719dd0328259416f5e9a52e zmap-1.1.0/000077500000000000000000000000001224250063200124545ustar00rootroot00000000000000zmap-1.1.0/.gitignore000066400000000000000000000002261224250063200144440ustar00rootroot00000000000000*.o *.a *.pyc *~ \#* src/zmap CMakeFiles *.cmake Makefile CMakeCache.txt src/zopt.h src/zopt.c lexer.c lexer.h parser.c parser.h install_manifest.txt zmap-1.1.0/AUTHORS000066400000000000000000000002541224250063200135250ustar00rootroot00000000000000Zakir Durumeric J. Alex Halderman Eric Wustrow David Adrian HD Moore zmap-1.1.0/CHANGELOG000066400000000000000000000041721224250063200136720ustar00rootroot000000000000001.0.0 2013-8-16 Initial public release. 1.0.1 2013-8-17 BUGFIX Issue #4 "Missing module_ssldb? Redis module won't compile." - removed dependencies on ssldb SUPPORT Issue #3 "Error after running make" - added documentation that zmap requires 64-bit system SUPPORT Issue #1 "Failure at calloc for 'ip_seen' on KVM VPSs?" - added documentation on memory requirements for zmap 1.0.2 2013-8-18 BUGFIX Issue #14 "gcc 4.7.2 -Wunprototyped-calls error with recv_run." - changed recv_run header to match def in recv.c 1.0.3 2013-8-19 BUGFIX Issues 21,28 "fixed get_gateway malloc/memset errors" BUGFIX Issue 24 "Makefile does not respect LDFLAGS" - changed = to += for CFLAGS, LDFAGS, and LDLIBS 1.1.0 2013-11-18 FEATURE Updated probe and output module interface that allows arbitrary data to be passed from the probe module (e.g. additional TCP fields) that can then be output as requested. FEATURE Replaced simple_file, and redis_file output modules with csv module that allows user controlled output of what fields shoudl be output to a csv file. As well, implemented --list-output-fields that allows users to find what fields are available. FEATURE Added output-filters that allow users to control what types of packets that want output (e.g. classification = "SYNACK" && is_repeat = 0) FEATURE Drop root privileges after opening necessary sockets if run as privileged user. FEATURE Added paged bitmap for removing duplicate responses so that if small subnets are scanned, large amount of memory is no longer required. FEATURE Fast scanning of small subnets. Scanning small subnets no longer requires iterating over the entire IPv4 address space, which allows ZMap-like speed for all network sizes. FEATURE Scan CIDR blocks from the command-line instead of only through whitelist file (e.g. zmap -p 443 192.168.0.0/16 10.0.0.0/8) FEATURE Redis output module now allows connecting to arbitrary redis servers and lists from the command-line via output module parameter FEATURE JSON output module added FEATURE 32-bit support FEATURE UDP Packet Support BUGFIX Source port in UDP module corrected to use network order instead of host order zmap-1.1.0/CMakeLists.txt000066400000000000000000000041221224250063200152130ustar00rootroot00000000000000cmake_minimum_required (VERSION 2.6) project (ZMAP C) option(WITH_REDIS "Build with support for Redis DB" OFF) option(WITH_JSON "Build with support for JSON" OFF) option(ENABLE_DEVELOPMENT "Enable development specific compiler and linker flags" OFF) option(ENABLE_HARDENING "Add hardening specific compiler and linker flags" ON) if(ENABLE_DEVELOPMENT) # Hardening and warnings for building with gcc # Maybe add -Wstrict-prototypes -Wmissing-prototypes -Wmissing-declarations set(GCCWARNINGS "-Wall -Wformat=2 -Wno-format-nonliteral" "-pedantic -fno-strict-aliasing" "-Wextra" "-Wfloat-equal -Wundef -Wwrite-strings -Wredundant-decls" "-Wnested-externs -Wbad-function-cast -Winit-self" "-Wmissing-noreturn -Wnormalized=id" "-Wstack-protector" "-Werror" ) # Fix line breaks string(REPLACE ";" " " GCCWARNINGS "${GCCWARNINGS}") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${GCCWARNINGS} -g") set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -g") endif() if(ENABLE_HARDENING) set(GCCHARDENING "-U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=2 -fstack-protector-all -fwrapv -fPIC --param ssp-buffer-size=1") set(LDHARDENING "-z relro -z now") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${GCCHARDENING}") set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${LDHARDENING}") endif() if(WITH_REDIS) set(REDIS_LIBS hiredis) add_definitions("-DREDIS") endif() if(WITH_JSON) include(FindPkgConfig) pkg_check_modules(JSON json) if(JSON_FOUND) include_directories(JSON_INCLUDE_DIRS) else() message(FATAL_ERROR "Did not find libjson") endif() add_definitions("-DJSON") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${JSON_CFLAGS}") endif() # Standard FLAGS set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=gnu99") set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -pthread") # Extra target FLAGS set(CMAKE_C_FLAGS_DEBUG "-O2 -g") set(CMAKE_C_FLAGS_RELEASE "-O2") add_subdirectory(src) # Install conf files FILE(GLOB CONF_FILES RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}/conf" "conf/*") message(STATUS "${CONF_FILES}") configure_file(zmap_conf_install.cmake.in zmap_conf_install.cmake) install(SCRIPT zmap_conf_install.cmake) zmap-1.1.0/INSTALL000066400000000000000000000024331224250063200135070ustar00rootroot00000000000000SYSTEM REQUIREMENTS ZMap is designed to run on GNU/Linux systems and can be built with most recent versions of gcc. Currently, ZMap only supports 64-bit systems. Running it requires at least 600 MB of free memory. BUILDING AND INSTALLING ZMAP ZMap requires GMP, a free library for arbitrary precision arithmetic, gengetopt, and libpcap. These packages can be installed on Debian-based systems by running: sudo apt-get install libgmp3-dev gengetopt libpcap-dev flex byacc or on RHEL- and Fedora-based systems by running: sudo yum install gmp gmp-devel gengetopt libpcap-devel flex byacc Once these prerequisites have been installed, ZMap can be installed by running: cmake [-DWITH_REDIS=ON] [-DWITH_JSON=ON] [-DENABLE_DEVELOPMENT=ON] [-DENABLE_HARDENING=ON] ./ make followed by: sudo make install Redis support is not enabled by default. If you are want to use ZMap with Redis, you will first need to install Hiredis. Then run cmake with "-DWITH_REDIS=ON". JSON support is not enabled by default. If you are want to use ZMap with JSON output, you will first need to install json-c. Then, run cmake with "-DWITH_JSON=ON" Installing json-c from source requires git and autotools to be available. For more information on how to install json-c, please see http://github.com/json-c/json-c zmap-1.1.0/LICENSE000066400000000000000000000236761224250063200134770ustar00rootroot00000000000000 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS zmap-1.1.0/README000066400000000000000000000022721224250063200133370ustar00rootroot00000000000000ZMap is a fast network scanner designed for Internet-wide network surveys. On a typical desktop computer with a gigabit Ethernet connection, ZMap is capable scanning the entire public IPv4 address space in under 45 minutes. While previous network tools have been designed to scan small network segments, ZMap is specifically architected to scan the entire address space. It is built in a modular manner in order to allow incorporation with other network survey tools. ZMap operates on GNU/Linux and supports TCP SYN and ICMP echo request scanning out of the box. Documentation and examples can be found at https://zmap.io/. -- ZMap Copyright 2013 Regents of the University of Michigan Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See LICENSE for the specific language governing permissions and limitations under the License. zmap-1.1.0/conf/000077500000000000000000000000001224250063200134015ustar00rootroot00000000000000zmap-1.1.0/conf/blacklist.conf000066400000000000000000000021141224250063200162160ustar00rootroot00000000000000# From IANA IPv4 Special-Purpose Address Registry # http://www.iana.org/assignments/iana-ipv4-special-registry/iana-ipv4-special-registry.xhtml # Updated 2013-05-22 0.0.0.0/8 # RFC1122: "This host on this network" 10.0.0.0/8 # RFC1918: Private-Use 100.64.0.0/10 # RFC6598: Shared Address Space 127.0.0.0/8 # RFC1122: Loopback 169.254.0.0/16 # RFC3927: Link Local 172.16.0.0/12 # RFC1918: Private-Use 192.0.0.0/24 # RFC6890: IETF Protocol Assignments 192.0.2.0/24 # RFC5737: Documentation (TEST-NET-1) 192.88.99.0/24 # RFC3068: 6to4 Relay Anycast 192.168.0.0/16 # RFC1918: Private-Use 198.18.0.0/15 # RFC2544: Benchmarking 198.51.100.0/24 # RFC5737: Documentation (TEST-NET-2) 203.0.113.0/24 # RFC5737: Documentation (TEST-NET-3) 240.0.0.0/4 # RFC1112: Reserved 255.255.255.255/32 # RFC0919: Limited Broadcast # From IANA Multicast Address Space Registry # http://www.iana.org/assignments/multicast-addresses/multicast-addresses.xhtml # Updated 2013-06-25 224.0.0.0/4 # RFC5771: Multicast/Reserved zmap-1.1.0/conf/zmap.conf000066400000000000000000000007551224250063200152260ustar00rootroot00000000000000### Probe Module to use #probe-module tcp_synscan ### Destination port to scan #target-port 443 ### Scan rate in packets/sec #rate 10000 ### Scan rate in bandwidth (bits/sec); overrides `rate` #bandwidth 1M # 1mbps ### Blacklist file to use. We encourage you to exclude ### RFC1918, IANA reserved, and multicast networks, ### in addition to those who have opted out of your ### network scans. blacklist-file "/etc/zmap/blacklist.conf" ### Optionally print a summary at the end #summary zmap-1.1.0/examples/000077500000000000000000000000001224250063200142725ustar00rootroot00000000000000zmap-1.1.0/examples/banner-grab-go/000077500000000000000000000000001224250063200170535ustar00rootroot00000000000000zmap-1.1.0/examples/banner-grab-go/README000066400000000000000000000027371224250063200177440ustar00rootroot00000000000000TCP banner grabber implemented in Go (experimental) ====== This program will make TCP connections to IP addresses provided on stdin, optionally send a short message, and wait for responses. Each response is printed to stdout, along with the responding host's IP address. Status messages appear on stderr. USING: ----- go build banner.go zmap -p 80 -N 1000 -o - | ./banner -port 80 -concurrent 100 -data http-req > banners.out OPTIONS: ----- -concurrent Number of connections that can be going on at once. This, combined with timeouts, will decide the maximum rate at which banners are grabbed. If this value is set higher than 1000, you should use `ulimit -SHn 1000000` and `ulimit -SSn 1000000` to avoid running out of file descriptors (typically capped at 1024). Default: 100. -port The port which to connect to hosts on. Default: 80. -timeout Connection timeout (seconds). Give up on a host if grabber has not completed by this time. Default: 4 seconds. -format Format to output banner responses. One of 'hex', 'ascii', or 'base64'. Default: ascii. -data Optional data file. This data will be sent to each host upon successful connection. Occurrences of the string '%s' will be replaced with the current target host's address. zmap-1.1.0/examples/banner-grab-go/banner.go000066400000000000000000000105061224250063200206510ustar00rootroot00000000000000/* TCP banner grabber, implemented in go This program will make TCP connections to IP addresses provided on stdin, optionally send a short message, and wait for responses. Each response is printed to stdout, along with the responding host's IP address. Status messages appear on stderr. */ package main import ( "bufio" "encoding/base64" "encoding/hex" "flag" "fmt" "io" "net" "os" "strings" "syscall" "time" ) var ( nConnectFlag = flag.Int("concurrent", 100, "Number of concurrent connections") portFlag = flag.String("port", "80", "Destination port") formatFlag = flag.String("format", "ascii", "Output format for responses ('ascii', 'hex', or 'base64')") timeoutFlag = flag.Int("timeout", 4, "Seconds to wait for each host to respond") dataFileFlag = flag.String("data", "", "File containing message to send to responsive hosts ('%s' will be replaced with host IP)") ) var messageData = make([]byte, 0) // data read from file specified with dataFile flag // Before running main, parse flags and load message data, if applicable func init() { flag.Parse() if *dataFileFlag != "" { fi, err := os.Open(*dataFileFlag) if err != nil { panic(err) } buf := make([]byte, 1024) n, err := fi.Read(buf) messageData = buf[0:n] if err != nil && err != io.EOF { panic(err) } fi.Close() } // Increase file descriptor limit rlimit := syscall.Rlimit{Max: uint64(*nConnectFlag + 4), Cur: uint64(*nConnectFlag + 4)} if err := syscall.Setrlimit(syscall.RLIMIT_NOFILE, &rlimit); err != nil { fmt.Fprintf(os.Stderr, "Error setting rlimit: %s", err) } } type resultStruct struct { addr string // address of remote host data []byte // data returned from the host, if successful err error // error, if any } // Read addresses from addrChan and grab banners from these hosts. // Sends resultStructs to resultChan. Writes to doneChan when complete. func grabber(addrChan chan string, resultChan chan resultStruct, doneChan chan int) { for addr := range addrChan { deadline := time.Now().Add(time.Duration(*timeoutFlag) * time.Second) dialer := net.Dialer{Deadline: deadline} conn, err := dialer.Dial("tcp", net.JoinHostPort(addr, *portFlag)) if err != nil { resultChan <- resultStruct{addr, nil, err} continue } conn.SetDeadline(deadline) if len(messageData) > 0 { s := strings.Replace(string(messageData), "%s", addr, -1) if _, err := conn.Write([]byte(s)); err != nil { conn.Close() resultChan <- resultStruct{addr, nil, err} continue } } var buf [1024]byte n, err := conn.Read(buf[:]) conn.Close() if err != nil && (err != io.EOF || n == 0) { resultChan <- resultStruct{addr, nil, err} continue } resultChan <- resultStruct{addr, buf[0:n], nil} } doneChan <- 1 } // Read resultStructs from resultChan, print output, and maintain // status counters. Writes to doneChan when complete. func output(resultChan chan resultStruct, doneChan chan int) { ok, timeout, error := 0, 0, 0 for result := range resultChan { if result.err == nil { switch *formatFlag { case "hex": fmt.Printf("%s: %s\n", result.addr, hex.EncodeToString(result.data)) case "base64": fmt.Printf("%s: %s\n", result.addr, base64.StdEncoding.EncodeToString(result.data)) default: fmt.Printf("%s: %s\n", result.addr, string(result.data)) } ok++ } else if nerr, ok := result.err.(net.Error); ok && nerr.Timeout() { fmt.Fprintf(os.Stderr, "%s: Timeout\n", result.addr) timeout++ } else { fmt.Fprintf(os.Stderr, "%s: Error %s\n", result.addr, result.err) error++ } } fmt.Fprintf(os.Stderr, "Complete (OK=%d, timeout=%d, error=%d)\n", ok, timeout, error) doneChan <- 1 } func main() { addrChan := make(chan string, *nConnectFlag) // pass addresses to grabbers resultChan := make(chan resultStruct, *nConnectFlag) // grabbers send results to output doneChan := make(chan int, *nConnectFlag) // let grabbers signal completion // Start grabbers and output thread go output(resultChan, doneChan) for i := 0; i < *nConnectFlag; i++ { go grabber(addrChan, resultChan, doneChan) } // Read addresses from stdin and pass to grabbers scanner := bufio.NewScanner(os.Stdin) for scanner.Scan() { addrChan <- scanner.Text() } close(addrChan) // Wait for completion for i := 0; i < *nConnectFlag; i++ { <-doneChan } close(resultChan) <-doneChan } zmap-1.1.0/examples/banner-grab-go/http-req000066400000000000000000000000341224250063200205370ustar00rootroot00000000000000GET / HTTP/1.1 Host: %s zmap-1.1.0/examples/banner-grab/000077500000000000000000000000001224250063200164505ustar00rootroot00000000000000zmap-1.1.0/examples/banner-grab/Makefile000066400000000000000000000011051224250063200201050ustar00rootroot00000000000000 CFLAGS+=-I../../lib/ -Wall LDFLAGS+=-lpcap -levent -levent_extra -lm VPATH=../../lib/ # from dpkg-buildflags --get CFLAGS, but use stack-protector-all and fPIC GCCHARDENING=-g -O2 -fstack-protector-all --param=ssp-buffer-size=4 -Wformat -Wformat-security -Werror=format-security -fPIC # from gpkg-buildflags --get LDFLAGS, + -z,now LDHARDENING=-Wl,-Bsymbolic-functions -Wl,-z,relro,-z,now CFLAGS+=$(GCCHARDENING) LDFLAGS+=$(LDHARDENING) all: banner-grab-tcp banner-grab-tcp: banner-grab-tcp.o logger.o $(CC) $(CFLAGS) $^ -o $@ $(LDFLAGS) clean: rm -f banner-grab-tcp *.o zmap-1.1.0/examples/banner-grab/README000066400000000000000000000045451224250063200173400ustar00rootroot00000000000000 TCP Banner Grab ====== This utility will connect (TCP) to ip addresses provide over stdin, optionally send them a small message, and wait for their response. The response is then printed along with their IP address on stdout. Status messages appear on stderr. USING: ----- make #echo -e -n "GET / HTTP/1.1\r\nHost: %s\r\n\r\n" > http-req zmap -p 80 -N 1000 -o - | ./banner-grab-tcp -p 80 -c 100 -d http-req > http-banners.out OPTIONS: ----- -c, --concurent Number of connections that can be going on at once. This, combined with timeouts, will decide the maximum rate at which banners are grabbed. If this value is set higher than 1000, you should use `ulimit -SSn 1000000` and `ulimit -SHn 1000000` to avoid running out of file descriptors (typically capped at 1024). -p, --port The port which to connect to hosts on -t, --conn-timeout Connection timeout (seconds). Give up on a host if connect has not completed by this time. Default: 4 seconds. -r, --read-timeout Read timeout (seconds). Give up on a host if after connecting (and optionally sending data), it does not send any response by this time. Default: 4 seconds. -v, --verbosity Set status verbosity. Status/error messages are outputed on stderr. This value can be 0-5, with 5 being the most verbose (LOG_TRACE). Default: 3 (LOG_INFO) -f, --format Format to output banner responses. One of 'hex', 'ascii', or 'base64'. 'hex' outputs ascii hex characters, e.g. 48656c6c6f. 'ascii' outputs ascii, without separators, e.g. Hello 'base64' outputs base64 encoding, e.g. SGVsbG8= Default is base64. -d, --data Optional data file. This data will be sent to each host upon successful connection. Currently, this file does not allow null characters, but supports up to 4 occurances of the current host's IP address, by replacing %s with the string (inet_ntoa) of that host's IP address. zmap-1.1.0/examples/banner-grab/banner-grab-tcp.c000066400000000000000000000270701224250063200215640ustar00rootroot00000000000000/* * Banner Grab Copyright 2013 Regents of the University of Michigan * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy * of the License at http://www.apache.org/licenses/LICENSE-2.0 */ #include #include #include #include "logger.h" #include #include #include #include #include #include #include #include #define MAX_BANNER_LEN 1024 #define BASE64_ALPHABET "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/" struct config { uint16_t port; int connect_timeout; // how long to wait for connecting (seconds) int read_timeout; // how long to wait once connected for the banner (seconds) int current_running; int max_concurrent; struct event_base *base; struct bufferevent *stdin_bev; int stdin_closed; enum {FORMAT_HEX, FORMAT_BASE64, FORMAT_ASCII} format; char *send_str; long send_str_size; struct stats_st { int init_connected_hosts; // Number of hosts we have even tried to connect to int connected_hosts; // # hosts that picked up int conn_timed_out; // # hosts that timed out during connection int read_timed_out; // # hosts that connected, but sent no data (banner) int timed_out; // # hosts that timed out at all (conn_timed_out+read_timed_out)? int completed_hosts; // # hosts that presented a banner } stats; }; struct state { struct config *conf; uint32_t ip; enum {CONNECTING, CONNECTED, RECEIVED} state; }; void stdin_readcb(struct bufferevent *bev, void *arg); void print_status(evutil_socket_t fd, short events, void *arg) { struct event *ev; struct config *conf = arg; struct event_base *base = conf->base; struct timeval status_timeout = {1, 0}; ev = evtimer_new(base, print_status, conf); evtimer_add(ev, &status_timeout); (void)fd; (void)events; log_info("banner-grab-tcp", "(%d/%d in use) - Totals: %d inited, %d connected, %d conn timeout, %d read timeout %d completed", conf->current_running, conf->max_concurrent, conf->stats.init_connected_hosts, conf->stats.connected_hosts, conf->stats.conn_timed_out, conf->stats.read_timed_out, conf->stats.completed_hosts); } void decrement_cur_running(struct state *st) { struct config *conf = st->conf; conf->current_running--; log_debug("banner-grab-tcp", "done, down to %d", conf->current_running); if (evbuffer_get_length(bufferevent_get_input(conf->stdin_bev)) > 0) { stdin_readcb(conf->stdin_bev, conf); } free(st); if (conf->stdin_closed && conf->current_running == 0) { // Done log_info("banner-grab-tcp", "done"); print_status(0, 0, conf); exit(0); } } void connect_cb(struct bufferevent *bev, short events, void *arg) { struct state *st = arg; struct config *conf = st->conf; struct in_addr addr; addr.s_addr = st->ip; if (events & BEV_EVENT_CONNECTED) { struct timeval tv = {st->conf->read_timeout, 0}; log_debug("banner-grab-tcp", "%s connected", inet_ntoa(addr)); // Send data if (conf->send_str) { struct evbuffer *evout = bufferevent_get_output(bev); // HACK!!! TODO: make some messy parser that replaces ${IP} with IP etc // and allow null characters evbuffer_add_printf(evout, conf->send_str, inet_ntoa(addr), inet_ntoa(addr), inet_ntoa(addr), inet_ntoa(addr)); } // Change from connect timeout to read timeout bufferevent_set_timeouts(bev, &tv, &tv); // Update state/stats st->state = CONNECTED; st->conf->stats.connected_hosts++; } else { if (st->state == CONNECTED) { // Print out that we just didn't receive data printf("%s X\n", inet_ntoa(addr)); fflush(stdout); st->conf->stats.read_timed_out++; } else { st->conf->stats.conn_timed_out++; } log_debug("banner-grab-tcp", "%s bailing..", inet_ntoa(addr)); bufferevent_free(bev); st->conf->stats.timed_out++; decrement_cur_running(st); } } // Grab these bytes, and close the connection. // Even if we don't need to read any bytes, // we have to have this so that libevent thinks we have // a read event, so that it can timeout TCP connects // (as a read timeout) void read_cb(struct bufferevent *bev, void *arg) { struct evbuffer *in = bufferevent_get_input(bev); struct state *st = arg; size_t len = evbuffer_get_length(in); struct in_addr addr; addr.s_addr = st->ip; log_debug("banner-grab-tcp", "read_cb for %s", inet_ntoa(addr)); if (len > MAX_BANNER_LEN) { len = MAX_BANNER_LEN; } if (len > 0) { // Grab the banner unsigned int i; unsigned char *buf = malloc(len+1); st->state = RECEIVED; if (!buf) { log_fatal("banner-grab-tcp", "cannot alloc %d byte buf", len+1); return; } evbuffer_remove(in, buf, len); printf("%s ", inet_ntoa(addr)); if (st->conf->format == FORMAT_ASCII) { // Ascii buf[len] = '\0'; printf("%s\n", buf); } else if (st->conf->format == FORMAT_HEX) { // Hex output for (i=0; iconf->format == FORMAT_BASE64) { // Base64 int i=0; char out[4] = {0,0,0,0}; while (i < len) { uint32_t value = 0; value += (i < len) ? buf[i++] << 16 : 0; value += (i < len) ? buf[i++] << 8 : 0; value += (i < len) ? buf[i++] : 0; out[0] = BASE64_ALPHABET[(value >> 18) & 0x3F]; out[1] = BASE64_ALPHABET[(value >> 12) & 0x3F]; out[2] = BASE64_ALPHABET[(value >> 6) & 0x3F]; out[3] = BASE64_ALPHABET[(value ) & 0x3F]; if (i < len) { printf("%c%c%c%c", out[0], out[1], out[2], out[3]); } } if (len > 0) { switch (len % 3) { case 1: out[2] = '='; case 2: out[3] = '='; default: break; } printf("%c%c%c%c\n", out[0], out[1], out[2], out[3]); } } fflush(stdout); free(buf); st->conf->stats.completed_hosts++; } bufferevent_free(bev); decrement_cur_running(st); } void grab_banner(struct state *st) { struct sockaddr_in addr; struct bufferevent *bev; struct timeval read_to = {st->conf->connect_timeout, 0}; addr.sin_family = AF_INET; addr.sin_port = htons(st->conf->port); addr.sin_addr.s_addr = st->ip; log_debug("banner-grab-tcp", "connect %s:%d", inet_ntoa(addr.sin_addr), st->conf->port); bev = bufferevent_socket_new(st->conf->base, -1, BEV_OPT_CLOSE_ON_FREE); bufferevent_set_timeouts(bev, &read_to, &read_to); bufferevent_setcb(bev, read_cb, NULL, connect_cb, st); bufferevent_enable(bev, EV_READ); st->state = CONNECTING; st->conf->stats.init_connected_hosts++; if (bufferevent_socket_connect(bev, (struct sockaddr *)&addr, sizeof(addr)) < 0) { log_warn("banner-grab-tcp", "could not connect socket %d (%d open) %d %d", bufferevent_getfd(bev), st->conf->current_running, errno, ENFILE); perror("connect"); bufferevent_free(bev); decrement_cur_running(st); return; } } void stdin_eventcb(struct bufferevent *bev, short events, void *ptr) { struct config *conf = ptr; if (events & BEV_EVENT_EOF) { log_debug("banner-grab-tcp", "received EOF; quitting after buffer empties"); conf->stdin_closed = 1; if (conf->current_running == 0) { log_info("banner-grab-tcp", "done"); print_status(0, 0, conf); exit(0); } } } void stdin_readcb(struct bufferevent *bev, void *arg) { struct evbuffer *in = bufferevent_get_input(bev); struct config *conf = arg; log_debug("banner-grab-tcp", "stdin cb %d < %d ?", conf->current_running, conf->max_concurrent); while (conf->current_running < conf->max_concurrent && evbuffer_get_length(in) > 0) { char *ip_str; size_t line_len; char *line = evbuffer_readln(in, &line_len, EVBUFFER_EOL_LF); struct state *st; if (!line) break; log_debug("banner-grab-tcp", "line: %s", line); ip_str = line; /* port_str = strstr(line, ":") + 1; if (!port_str) port_str = strstr(line, " ") + 1; if (!port_str) break; *(port_str-1) = '\0'; port = atoi(port_str); */ //printf("scanning %s:%d\n", ip conf->current_running++; st = malloc(sizeof(*st)); st->conf = conf; st->ip = inet_addr(ip_str); grab_banner(st); } } int main(int argc, char *argv[]) { struct event_base *base; struct event *status_timer; struct timeval status_timeout = {1, 0}; int c; struct option long_options[] = { {"concurrent", required_argument, 0, 'c'}, {"port", required_argument, 0, 'p'}, {"conn-timeout", required_argument, 0, 't'}, {"read-timeout", required_argument, 0, 'r'}, {"verbosity", required_argument, 0, 'v'}, {"format", no_argument, 0, 'f'}, {"data", required_argument, 0, 'd'}, {0, 0, 0, 0} }; struct config conf; int ret; FILE *fp; log_init(stderr, LOG_INFO); ret = ulimit(4, 1000000); // Allow us to open 1 million fds (instead of 1024) if (ret < 0) { log_fatal("banner-grab-tcp", "cannot set ulimit"); perror("ulimit"); exit(1); } base = event_base_new(); conf.base = base; // buffer stdin as an event conf.stdin_bev = bufferevent_socket_new(base, 0, BEV_OPT_DEFER_CALLBACKS); bufferevent_setcb(conf.stdin_bev, stdin_readcb, NULL, stdin_eventcb, &conf); bufferevent_enable(conf.stdin_bev, EV_READ); // Status timer status_timer = evtimer_new(base, print_status, &conf); evtimer_add(status_timer, &status_timeout); // Defaults conf.max_concurrent = 1; conf.current_running = 0; memset(&conf.stats, 0, sizeof(conf.stats)); conf.connect_timeout = 4; conf.read_timeout = 4; conf.stdin_closed = 0; conf.format = FORMAT_BASE64; conf.send_str = NULL; // Parse command line args while (1) { int option_index = 0; c = getopt_long(argc, argv, "c:p:t:r:v:f:d:", long_options, &option_index); if (c < 0) { break; } switch (c) { case 'c': conf.max_concurrent = atoi(optarg); break; case 'p': conf.port = atoi(optarg); break; case 't': conf.connect_timeout = atoi(optarg); break; case 'r': conf.read_timeout = atoi(optarg); break; case 'v': if (atoi(optarg) >= 0 && atoi(optarg) <= 5) { log_init(stderr, atoi(optarg)); } break; case 'f': if (strcmp(optarg, "hex") == 0) { conf.format = FORMAT_HEX; } else if (strcmp(optarg, "base64") == 0) { conf.format = FORMAT_BASE64; } else if (strcmp(optarg, "ascii") == 0) { conf.format = FORMAT_ASCII; } else { log_fatal("banner-grab-tcp", "Unknown format '%s'; use 'hex', 'base64', or 'ascii'", optarg); } break; case 'd': fp = fopen(optarg, "r"); if (!fp) { log_error("banner-grab-tcp", "Could not open send data file '%s':", optarg); perror("fopen"); exit(-1); } fseek(fp, 0L, SEEK_END); conf.send_str_size = ftell(fp); fseek(fp, 0L, SEEK_SET); //assert(conf.send_str_size < 10000); // jumbo frames? conf.send_str = malloc(conf.send_str_size+1); if (!conf.send_str) { log_fatal("banner-grab-tcp", "Could not malloc %d bytes", conf.send_str_size+1); } if (fread(conf.send_str, conf.send_str_size, 1, fp) != 1) { log_fatal("banner-grab-tcp", "Couldn't read from send data file '%s':", optarg); } conf.send_str[conf.send_str_size] = '\0'; fclose(fp); break; case '?': printf("Usage:\n"); printf("\t%s [-c max_concurrency] [-t connect_timeout] [-r read_timeout] \n\t" "[-v verbosity=0-5] [-d send_data_file] [-f ascii|hex|base64] -p port\n", argv[0]); exit(1); default: log_info("banner-grab-tcp", "hmmm.."); break; } } log_info("banner-grab-tcp", "Using port %d with max_concurrency %d, %d s conn timeout, %d s read timeout", conf.port, conf.max_concurrent, conf.connect_timeout, conf.read_timeout); event_base_dispatch(base); return 0; } zmap-1.1.0/examples/banner-grab/http-req000066400000000000000000000000341224250063200201340ustar00rootroot00000000000000GET / HTTP/1.1 Host: %s zmap-1.1.0/examples/forge-socket/000077500000000000000000000000001224250063200166625ustar00rootroot00000000000000zmap-1.1.0/examples/forge-socket/Makefile000066400000000000000000000011161224250063200203210ustar00rootroot00000000000000 CFLAGS+=-I../../lib/ -I../../forge_socket -Wall LDFLAGS+=-lpcap -levent -levent_extra -lm VPATH=../../lib/ # from dpkg-buildflags --get CFLAGS, but use stack-protector-all and fPIC GCCHARDENING=-g -O2 -fstack-protector-all --param=ssp-buffer-size=4 -Wformat -Wformat-security -Werror=format-security -fPIC # from gpkg-buildflags --get LDFLAGS, + -z,now LDHARDENING=-Wl,-Bsymbolic-functions -Wl,-z,relro,-z,now CFLAGS+=$(GCCHARDENING) LDFLAGS+=$(LDHARDENING) all: forge-socket forge-socket: forge-socket.o logger.o $(CC) $(CFLAGS) $^ -o $@ $(LDFLAGS) clean: rm -f forge-socket *.o zmap-1.1.0/examples/forge-socket/README000066400000000000000000000064431224250063200175510ustar00rootroot00000000000000Forge-socket banner grab ====== This utility, in combination with a kernel module (https://github.com/ewust/forge_socket/) will complete the half-open connection created by ZMap during a TCP-scan, optionally send a small message, and wait for the hosts response. The response is then printed along with their IP address on stdout. Periodic status messages appear on stderr. This utility is functionally equivalent to banner-grab-tcp, however, instead of having the kernel send a RST packet for the server's SYN+ACK, and banner-grab-tcp attempting to start a fresh TCP connection with the host, forge-socket will take the parameters of the SYN+ACK packet, and use a kernel module to add it as an ESTABLISHED TCP connection socket. Then, the forge-socket user-space program can use this socket to send() and recv() as normal, and completes the banner-grab process (optionally send a small message, and receive the server's response). USING: ----- # Install forge-socket to the ZMap root directory: cd ./zmap/ git clone git@github.com:ewust/forge_socket.git cd forge_socket make sudo insmod forge_socket.ko # Don't send RST packets (forge-socket will complete these connections instead) sudo iptables -A OUTPUT -p tcp -m tcp --tcp-flags RST,RST RST,RST -j DROP # Use ZMap + forge-socket simultaneously: make #echo -e -n "GET / HTTP/1.1\r\nHost: %s\r\n\r\n" > http-req sudo su ulimit -SHn 1000000 && ulimit -SSn 1000000 zmap -p 80 -B 50M -N 1000 -O extended_file -o - | ./forge-socket -c 8000 -d http-req > http-banners.out The options are similar to banner-grab-tcp, except there is no connection timeout :) OPTIONS: ----- -c, --concurent Number of connections that can be going on at once. This, combined with timeouts, will decide the maximum rate at which banners are grabbed. If this value is set higher than 1000, you should use `ulimit -SSn 1000000` and `ulimit -SHn 1000000` to avoid running out of file descriptors (typically capped at 1024). -r, --read-timeout Read timeout (seconds). Give up on a host if after connecting (and optionally sending data), it does not send any response by this time. Default: 4 seconds. -v, --verbosity Set status verbosity. Status/error messages are outputed on stderr. This value can be 0-5, with 5 being the most verbose (LOG_TRACE). Default: 3 (LOG_INFO) -f, --format Format to output banner responses. One of 'hex', 'ascii', or 'base64'. 'hex' outputs ascii hex characters, e.g. 48656c6c6f. 'ascii' outputs ascii, without separators, e.g. Hello 'base64' outputs base64 encoding, e.g. SGVsbG8= Default is base64. -d, --data Optional data file. This data will be sent to each host upon successful connection. Currently, this file does not allow null characters, but supports up to 4 occurances of the current host's IP address, by replacing %s with the string (inet_ntoa) of that host's IP address. zmap-1.1.0/examples/forge-socket/forge-socket.c000066400000000000000000000323101224250063200214150ustar00rootroot00000000000000/* * Forge Socket Banner Grab Copyright 2013 Regents of the University of Michigan * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy * of the License at http://www.apache.org/licenses/LICENSE-2.0 */ #include #include #include #include "logger.h" #include #include #include #include #include #include #include #include #include "forge_socket.h" #define MAX_BANNER_LEN 1024 #define BASE64_ALPHABET "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/" struct config { int read_timeout; // how long to wait once connected for the banner (seconds) int current_running; int max_concurrent; struct event_base *base; struct bufferevent *stdin_bev; int stdin_closed; enum {FORMAT_HEX, FORMAT_BASE64, FORMAT_ASCII} format; char *send_str; long send_str_size; struct stats_st { int init_connected_hosts; // Number of hosts we have even tried to connect to int connected_hosts; // # hosts that picked up int conn_timed_out; // # hosts that timed out during connection int read_timed_out; // # hosts that connected, but sent no data (banner) int timed_out; // # hosts that timed out at all (conn_timed_out+read_timed_out)? int completed_hosts; // # hosts that presented a banner } stats; }; struct state { struct config *conf; uint32_t src_ip; uint32_t dst_ip; uint16_t sport; uint16_t dport; uint32_t seq; uint32_t seq_ack; enum {CONNECTING, CONNECTED, RECEIVED} state; }; void stdin_readcb(struct bufferevent *bev, void *arg); void print_status(evutil_socket_t fd, short events, void *arg) { struct event *ev; struct config *conf = arg; struct event_base *base = conf->base; struct timeval status_timeout = {1, 0}; ev = evtimer_new(base, print_status, conf); evtimer_add(ev, &status_timeout); (void)fd; (void)events; log_info("forge-socket", "(%d/%d in use) - Totals: %d inited, %d connected, %d conn timeout, %d read timeout %d completed", conf->current_running, conf->max_concurrent, conf->stats.init_connected_hosts, conf->stats.connected_hosts, conf->stats.conn_timed_out, conf->stats.read_timed_out, conf->stats.completed_hosts); } void decrement_cur_running(struct state *st) { struct config *conf = st->conf; conf->current_running--; log_debug("forge-socket", "done, down to %d", conf->current_running); if (evbuffer_get_length(bufferevent_get_input(conf->stdin_bev)) > 0) { stdin_readcb(conf->stdin_bev, conf); } free(st); if (conf->stdin_closed && conf->current_running == 0) { // Done log_info("forge-socket", "done"); print_status(0, 0, conf); exit(0); } } void event_cb(struct bufferevent *bev, short events, void *arg) { struct state *st = arg; struct config *conf = st->conf; struct in_addr addr; addr.s_addr = st->src_ip; if (events & BEV_EVENT_CONNECTED) { log_error("forge-socket", "%s connected - wat?", inet_ntoa(addr)); } else { if (st->state == CONNECTED) { // Print out that we just didn't receive data printf("%s X\n", inet_ntoa(addr)); fflush(stdout); conf->stats.read_timed_out++; } else { conf->stats.conn_timed_out++; } log_debug("forge-socket", "%s bailing..", inet_ntoa(addr)); bufferevent_free(bev); conf->stats.timed_out++; decrement_cur_running(st); } } // Grab these bytes, and close the connection. // Even if we don't need to read any bytes, // we have to have this so that libevent thinks we have // a read event, so that it can timeout TCP connects // (as a read timeout) void read_cb(struct bufferevent *bev, void *arg) { struct evbuffer *in = bufferevent_get_input(bev); struct state *st = arg; size_t len = evbuffer_get_length(in); struct in_addr addr; addr.s_addr = st->src_ip; log_debug("forge-socket", "read_cb for %s", inet_ntoa(addr)); if (len > MAX_BANNER_LEN) { len = MAX_BANNER_LEN; } if (len > 0) { // Grab the banner unsigned int i; unsigned char *buf = malloc(len+1); st->state = RECEIVED; if (!buf) { log_fatal("forge-socket", "cannot alloc %d byte buf", len+1); return; } evbuffer_remove(in, buf, len); printf("%s ", inet_ntoa(addr)); if (st->conf->format == FORMAT_ASCII) { // Ascii buf[len] = '\0'; printf("%s\n", buf); } else if (st->conf->format == FORMAT_HEX) { // Hex output for (i=0; iconf->format == FORMAT_BASE64) { // Base64 int i=0; char out[4] = {0,0,0,0}; while (i < len) { uint32_t value = 0; value += (i < len) ? buf[i++] << 16 : 0; value += (i < len) ? buf[i++] << 8 : 0; value += (i < len) ? buf[i++] : 0; out[0] = BASE64_ALPHABET[(value >> 18) & 0x3F]; out[1] = BASE64_ALPHABET[(value >> 12) & 0x3F]; out[2] = BASE64_ALPHABET[(value >> 6) & 0x3F]; out[3] = BASE64_ALPHABET[(value ) & 0x3F]; if (i < len) { printf("%c%c%c%c", out[0], out[1], out[2], out[3]); } } if (len > 0) { switch (len % 3) { case 1: out[2] = '='; case 2: out[3] = '='; default: break; } printf("%c%c%c%c\n", out[0], out[1], out[2], out[3]); } } fflush(stdout); free(buf); st->conf->stats.completed_hosts++; } bufferevent_free(bev); decrement_cur_running(st); } int set_sock_state(int sock, struct tcp_state *st) { struct sockaddr_in sin; sin.sin_family = AF_INET; sin.sin_addr.s_addr = st->src_ip; sin.sin_port = st->sport; int value = 1; if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &value, sizeof(value)) < 0) { perror("setsockopt SO_REUSEADDR"); return -1; } if (setsockopt(sock, SOL_IP, IP_TRANSPARENT, &value, sizeof(value)) < 0) { perror("setsockopt IP_TRANSPARENT"); return -1; } if (bind(sock, (struct sockaddr *)&sin, sizeof(sin)) < 0) { perror("bind"); return -1; } if (setsockopt(sock, IPPROTO_TCP, TCP_STATE, st, sizeof(struct tcp_state)) < 0) { perror("setsockopt TCP_STATE"); return -1; } return 0; } void grab_banner(struct state *st) { struct sockaddr_in addr; struct bufferevent *bev; struct timeval read_to = {st->conf->read_timeout, 0}; struct tcp_state tcp_st; int sock = socket(AF_INET, SOCK_FORGE, 0); addr.sin_addr.s_addr = st->src_ip; if (sock < 0) { perror("SOCK_FORGE socket"); log_fatal("forge_socket", "(did you insmod forge_socket.ko?)"); return; } memset(&tcp_st, 0, sizeof(tcp_st)); // These need to be in network order for forge socket" tcp_st.src_ip = st->dst_ip; tcp_st.dst_ip = st->src_ip; tcp_st.sport = htons(st->dport); tcp_st.dport = htons(st->sport); // This should be in ??? tcp_st.seq = st->seq_ack; tcp_st.ack = (st->seq + 1); tcp_st.snd_wnd = 0x1000; tcp_st.rcv_wnd = 0x1000; tcp_st.snd_una = tcp_st.seq; st->state = CONNECTING; st->conf->stats.init_connected_hosts++; // consider this a non-blocking, but completed "connect()". heh. if (set_sock_state(sock, &tcp_st) != 0) { log_error("forge_socket", "set_sock_state failed\n"); decrement_cur_running(st); return; } evutil_make_socket_nonblocking(sock); bev = bufferevent_socket_new(st->conf->base, sock, BEV_OPT_CLOSE_ON_FREE); bufferevent_set_timeouts(bev, &read_to, &read_to); bufferevent_setcb(bev, read_cb, NULL, event_cb, st); bufferevent_enable(bev, EV_READ); // Send data if (st->conf->send_str) { struct evbuffer *evout = bufferevent_get_output(bev); // HACK!!! TODO: make some messy parser that replaces ${IP} with IP etc // and allow null characters evbuffer_add_printf(evout, st->conf->send_str, inet_ntoa(addr.sin_addr), inet_ntoa(addr.sin_addr), inet_ntoa(addr.sin_addr), inet_ntoa(addr.sin_addr)); log_trace("forge-socket", "sent str to %s", inet_ntoa(addr.sin_addr)); } // Update state/stats st->state = CONNECTED; st->conf->stats.connected_hosts++; log_trace("forge-socket", "go %s go! read a byte!!", inet_ntoa(addr.sin_addr)); } void stdin_eventcb(struct bufferevent *bev, short events, void *ptr) { struct config *conf = ptr; if (events & BEV_EVENT_EOF) { log_debug("forge-socket", "received EOF; quitting after buffer empties"); conf->stdin_closed = 1; if (conf->current_running == 0) { log_info("forge-socket", "done"); print_status(0, 0, conf); exit(0); } } } void stdin_readcb(struct bufferevent *bev, void *arg) { struct evbuffer *in = bufferevent_get_input(bev); struct config *conf = arg; log_debug("forge-socket", "stdin cb %d < %d ?", conf->current_running, conf->max_concurrent); while (conf->current_running < conf->max_concurrent && evbuffer_get_length(in) > 0) { size_t line_len; char *line = evbuffer_readln(in, &line_len, EVBUFFER_EOL_LF); struct state *st; if (!line) break; log_debug("forge-socket", "line: '%s'", line); //synack, 77.176.116.205, 141.212.121.125, 443, 49588, 3628826326, 3441755636, 0, 0,2013-08-11 19:16:05.799 char synack[12]; char srcip[INET_ADDRSTRLEN], dstip[INET_ADDRSTRLEN]; uint32_t seq, seq_ack; uint16_t sport, dport; int cooldown, repeat=1; int ret = sscanf(line, "%11[^,], %15[^,], %15[^,], %hu, %hu, %u, %u, %d, %d,%*s", synack, srcip, dstip, &sport, &dport, &seq, &seq_ack, &cooldown, &repeat); log_trace("forge-socket", "%d '%s' sip: '%s', dip: '%s', sport: %d, dport: %d, seq: %d, seq_ack: %d", ret, synack, srcip, dstip, sport, dport, seq, seq_ack); if (ret==9 && !repeat && strcmp(synack, "synack") == 0) { st = malloc(sizeof(*st)); st->conf = conf; st->src_ip = inet_addr(srcip); st->dst_ip = inet_addr(dstip); st->sport = sport; st->dport = dport; st->seq = seq; st->seq_ack = seq_ack; conf->current_running++; grab_banner(st); } } } int main(int argc, char *argv[]) { struct event_base *base; struct event *status_timer; struct timeval status_timeout = {1, 0}; int c; struct option long_options[] = { {"concurrent", required_argument, 0, 'c'}, {"read-timeout", required_argument, 0, 'r'}, {"verbosity", required_argument, 0, 'v'}, {"format", no_argument, 0, 'f'}, {"data", required_argument, 0, 'd'}, {0, 0, 0, 0} }; struct config conf; int ret; FILE *fp; log_init(stderr, LOG_INFO); ret = ulimit(4, 1000000); // Allow us to open 1 million fds (instead of 1024) if (ret < 0) { log_fatal("forge-socket", "cannot set ulimit"); perror("ulimit"); exit(1); } base = event_base_new(); conf.base = base; // buffer stdin as an event conf.stdin_bev = bufferevent_socket_new(base, 0, BEV_OPT_DEFER_CALLBACKS); bufferevent_setcb(conf.stdin_bev, stdin_readcb, NULL, stdin_eventcb, &conf); bufferevent_enable(conf.stdin_bev, EV_READ); // Status timer status_timer = evtimer_new(base, print_status, &conf); evtimer_add(status_timer, &status_timeout); // Defaults conf.max_concurrent = 1; conf.current_running = 0; memset(&conf.stats, 0, sizeof(conf.stats)); conf.read_timeout = 4; conf.stdin_closed = 0; conf.format = FORMAT_BASE64; conf.send_str = NULL; // Parse command line args while (1) { int option_index = 0; c = getopt_long(argc, argv, "c:t:r:v:f:d:", long_options, &option_index); if (c < 0) { break; } switch (c) { case 'c': conf.max_concurrent = atoi(optarg); break; case 'r': conf.read_timeout = atoi(optarg); break; case 'v': if (atoi(optarg) >= 0 && atoi(optarg) <= 5) { log_init(stderr, atoi(optarg)); } break; case 'f': if (strcmp(optarg, "hex") == 0) { conf.format = FORMAT_HEX; } else if (strcmp(optarg, "base64") == 0) { conf.format = FORMAT_BASE64; } else if (strcmp(optarg, "ascii") == 0) { conf.format = FORMAT_ASCII; } else { log_fatal("forge-socket", "Unknown format '%s'; use 'hex', 'base64', or 'ascii'", optarg); } break; case 'd': fp = fopen(optarg, "r"); if (!fp) { log_error("forge-socket", "Could not open send data file '%s':", optarg); perror("fopen"); exit(-1); } fseek(fp, 0L, SEEK_END); conf.send_str_size = ftell(fp); fseek(fp, 0L, SEEK_SET); //assert(conf.send_str_size < 10000); // jumbo frames? conf.send_str = malloc(conf.send_str_size+1); if (!conf.send_str) { log_fatal("forge-socket", "Could not malloc %d bytes", conf.send_str_size+1); } if (fread(conf.send_str, conf.send_str_size, 1, fp) != 1) { log_fatal("forge-socket", "Couldn't read from send data file '%s':", optarg); } conf.send_str[conf.send_str_size] = '\0'; fclose(fp); break; case '?': printf("Usage:\n"); printf("\t%s [-c max_concurrency] [-r read_timeout] \n\t" "[-v verbosity=0-5] [-d send_data_file] [-f ascii|hex|base64]\n", argv[0]); exit(1); default: log_info("forge-socket", "hmmm.."); break; } } log_info("forge-socket", "Using max_concurrency %d, %d s read timeout", conf.max_concurrent, conf.read_timeout); event_base_dispatch(base); return 0; } zmap-1.1.0/examples/udp-probes/000077500000000000000000000000001224250063200163525ustar00rootroot00000000000000zmap-1.1.0/examples/udp-probes/README000066400000000000000000000054011224250063200172320ustar00rootroot00000000000000 UDP Data Probes ====== This directory contains a set of data files that can be used with the UDP probe module. USING: ----- $ zmap -M udp -p 137 --probe-args=file:examples/udp-probes/netbios_137.pkt PROBES: ----- citrix_1604.pkt This probe triggers a response from Citrix application discovery services on UDP port 1604 db2disco_523.pkt This probe triggers a response from IBM DB2 discovery services on UDP port 523 digi1_2362.pkt This probe triggers a response from Digi ADDP discovery services on UDP port 2362 (default magic) digi2_2362.pkt This probe triggers a response from Digi ADDP discovery services on UDP port 2362 (devkit magic) digi3_2362.pkt This probe triggers a response from Digi ADDP discovery services on UDP port 2362 (oem magic) dns_53.pkt This probe queries for the DNS vendor and version using the BIND version TXT record over UDP port 53 ipmi_623.pkt This probe triggers a Get Channel Authentication reply from IPMI endpoints on UDP port 623 mdns_5353.pkt This probe triggers a response from mDNS/Avahi/Bonjour discovery services on UDP port 5353 mssql_1434.pkt This probe triggers a response from Microsoft SQL Server discovery services on UDP port 1434 natpmp_5351.pkt This probe triggers a response from NATPMP-enabled devices on UDP port 5351 netbios_137.pkt This probe triggers a status reply from NetBIOS services on UDP port 137 ntp_123.pkt This probe triggers a response from NTP servies on UDP port 123 pca_nq_5632.pkt This probe triggers a response from PC Anywhere services on UDP port 5632 (network query) pca_st_5632.pkt This probe triggers a response from PC Anywhere services on UDP port 5632 (status) portmap_111.pkt This probe triggers a response from SunRPC portmapper services on UDP port 111 sentinel_5093.pkt This probe triggers a response from the Sentinel license manager service on UDP port 5093 snmp1_161.pkt This probe queries for the system description field of SNMP v1 services using community string public over UDP port 161 snmp2_161.pkt This probe queries for the system description field of aNMP v2 services using community string public over UDP port 161 upnp_1900.pkt This probe triggers a response from UPnP SSDP services on UDP port 1900 wdbrpc_17185.pkt This probe triggers a response from VxWorks WDBRPC services on UDP port 17185 wsd_3702.pkt This probe triggers a response from WSD/DPWS services on UDP port 3702 NOTES: ----- Most of these probes return useful data in the response. Parsing this data requires capturing the raw output and decoding this using a protocol-specific dissector. In most cases, Wireshark is capable of decoding these replies.zmap-1.1.0/examples/udp-probes/citrix_1604.pkt000077500000000000000000000000361224250063200210500ustar00rootroot000000000000000ý¨ãzmap-1.1.0/examples/udp-probes/db2disco_523.pkt000077500000000000000000000000241224250063200211530ustar00rootroot00000000000000DB2GETADDRSQL05000zmap-1.1.0/examples/udp-probes/digi1_2362.pkt000077500000000000000000000000161224250063200205430ustar00rootroot00000000000000DIGIÿÿÿÿÿÿzmap-1.1.0/examples/udp-probes/digi2_2362.pkt000077500000000000000000000000161224250063200205440ustar00rootroot00000000000000DVKTÿÿÿÿÿÿzmap-1.1.0/examples/udp-probes/digi3_2362.pkt000077500000000000000000000000161224250063200205450ustar00rootroot00000000000000DGDPÿÿÿÿÿÿzmap-1.1.0/examples/udp-probes/dns_53.pkt000077500000000000000000000000361224250063200201670ustar00rootroot000000000000004ïVERSIONBINDzmap-1.1.0/examples/udp-probes/ipmi_623.pkt000077500000000000000000000000271224250063200204240ustar00rootroot00000000000000ÿ È8޵zmap-1.1.0/examples/udp-probes/mdns_5353.pkt000077500000000000000000000000561224250063200205160ustar00rootroot00000000000000 _services_dns-sd_udplocal zmap-1.1.0/examples/udp-probes/mssql_1434.pkt000077500000000000000000000000011224250063200206760ustar00rootroot00000000000000zmap-1.1.0/examples/udp-probes/natpmp_5351.pkt000077500000000000000000000000041224250063200210430ustar00rootroot00000000000000zmap-1.1.0/examples/udp-probes/netbios_137.pkt000077500000000000000000000000621224250063200211300ustar00rootroot00000000000000åØ CKAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA!zmap-1.1.0/examples/udp-probes/ntp_123.pkt000077500000000000000000000000601224250063200202570ustar00rootroot00000000000000ãúÅO#Kq±Rózmap-1.1.0/examples/udp-probes/pca_nq_5632.pkt000077500000000000000000000000021224250063200210050ustar00rootroot00000000000000NQzmap-1.1.0/examples/udp-probes/pca_st_5632.pkt000077500000000000000000000000021224250063200210150ustar00rootroot00000000000000STzmap-1.1.0/examples/udp-probes/portmap_111.pkt000077500000000000000000000000501224250063200211340ustar00rootroot00000000000000er 7† zmap-1.1.0/examples/udp-probes/sentinel_5093.pkt000077500000000000000000000000061224250063200213720ustar00rootroot00000000000000zzmap-1.1.0/examples/udp-probes/snmp1_161.pkt000077500000000000000000000000531224250063200205200ustar00rootroot000000000000000)public VZÜ]00 +zmap-1.1.0/examples/udp-probes/snmp2_161.pkt000077500000000000000000000000501224250063200205160ustar00rootroot000000000000000&public¡Ücš0 0 +zmap-1.1.0/examples/udp-probes/upnp_1900.pkt000077500000000000000000000001431224250063200205260ustar00rootroot00000000000000M-SEARCH * HTTP/1.1 Host:239.255.255.250:1900 ST:upnp:rootdevice Man:"ssdp:discover" MX:3 zmap-1.1.0/examples/udp-probes/wdbrpc_17185.pkt000077500000000000000000000001001224250063200211120ustar00rootroot00000000000000 úºUUUUÿÿU<zmap-1.1.0/examples/udp-probes/wsd_3702.pkt000077500000000000000000000011631224250063200203460ustar00rootroot00000000000000 urn:schemas-xmlsoap-org:ws:2005:04:discoveryhttp://schemas.xmlsoap.org/ws/2005/04/discovery/Probeurn:uuid:ce04dad0-5d2c-4026-9146-1aabfc1e4111wsdp:Device zmap-1.1.0/lib/000077500000000000000000000000001224250063200132225ustar00rootroot00000000000000zmap-1.1.0/lib/blacklist.c000066400000000000000000000111621224250063200153370ustar00rootroot00000000000000/* * Blacklist Copyright 2013 Regents of the University of Michigan * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy * of the License at http://www.apache.org/licenses/LICENSE-2.0 */ #include "blacklist.h" #include #include #include #include #include #include #include #include #include #include "constraint.h" #include "logger.h" #define ADDR_DISALLOWED 0 #define ADDR_ALLOWED 1 static constraint_t *constraint = NULL; uint32_t blacklist_lookup_index(uint64_t index) { return ntohl(constraint_lookup_index(constraint, index, ADDR_ALLOWED)); } // check whether a single IP address is allowed to be scanned. // 1 => is allowed // 0 => is not allowed int blacklist_is_allowed(uint32_t s_addr) { return constraint_lookup_ip(constraint, ntohl(s_addr)) == ADDR_ALLOWED; } // blacklist a CIDR network allocation // e.g. blacklist_add("128.255.134.0", 24) void blacklist_prefix(char *ip, int prefix_len) { assert(constraint); constraint_set(constraint, ntohl(inet_addr(ip)), prefix_len, ADDR_DISALLOWED); } // whitelist a CIDR network allocation void whitelist_prefix(char *ip, int prefix_len) { assert(constraint); constraint_set(constraint, ntohl(inet_addr(ip)), prefix_len, ADDR_ALLOWED); } static int init_from_string(char *ip, int value) { int prefix_len = 32; char *slash = strchr(ip, '/'); if (slash) { // split apart network and prefix length *slash = '\0'; char *end; char *len = slash+1; errno = 0; prefix_len = strtol(len, &end, 10); if (end == len || errno != 0 || prefix_len < 0 || prefix_len > 32) { log_fatal("constraint", "'%s' is not a valid prefix length", len); return -1; } } struct in_addr addr; if (inet_aton(ip, &addr) == 0) { log_error("constraint", "'%s' is not a valid IP address", ip); return -1; } constraint_set(constraint, ntohl(addr.s_addr), prefix_len, value); const char *name; if (value == ADDR_DISALLOWED) name = "blacklisting"; else name = "whitelisting"; log_trace(name, "%s %s/%i", name, ip, prefix_len); return 0; } static int init_from_file(char *file, const char *name, int value) { FILE *fp; char line[1000]; fp = fopen(file, "r"); if (fp == NULL) { log_fatal(name, "Unable to open %s file: %s: %s", name, file, strerror(errno)); } while (fgets(line, sizeof(line), fp) != NULL) { char *comment = strchr(line, '#'); if (comment) { *comment = '\0'; } char ip[33]; if ((sscanf(line, "%32s", ip)) == EOF) { continue; } if (init_from_string(ip, value)) { log_fatal(name, "unable to parse %s file: %s", name, file); } } fclose(fp); return 0; } static void init_from_array(char **cidrs, size_t len, int value) { for (int i=0; i < (int) len; i++) { init_from_string(cidrs[i], value); } } uint64_t blacklist_count_allowed() { assert(constraint); return constraint_count_ips(constraint, ADDR_ALLOWED); } uint64_t blacklist_count_not_allowed() { assert(constraint); return constraint_count_ips(constraint, ADDR_DISALLOWED); } // Initialize address constraints from whitelist and blacklist files. // Either can be set to NULL to omit. int blacklist_init(char *whitelist_filename, char *blacklist_filename, char **whitelist_entries, size_t whitelist_entries_len, char **blacklist_entries, size_t blacklist_entries_len) { assert(!constraint); if (whitelist_filename && whitelist_entries) { log_warn("whitelist", "both a whitelist file and destination addresses " "were specified. The union of these two sources " "will be utilized."); } if (whitelist_filename || whitelist_entries) { // using a whitelist, so default to allowing nothing constraint = constraint_init(ADDR_DISALLOWED); log_trace("whitelist", "blacklisting 0.0.0.0/0"); if (whitelist_filename) { init_from_file(whitelist_filename, "whitelist", ADDR_ALLOWED); } if (whitelist_entries) { init_from_array(whitelist_entries, whitelist_entries_len, ADDR_ALLOWED); } } else { // no whitelist, so default to allowing everything constraint = constraint_init(ADDR_ALLOWED); } if (blacklist_filename) { init_from_file(blacklist_filename, "blacklist", ADDR_DISALLOWED); } if (blacklist_entries) { init_from_array(blacklist_entries, blacklist_entries_len, ADDR_DISALLOWED); } constraint_paint_value(constraint, ADDR_ALLOWED); uint64_t allowed = blacklist_count_allowed(); log_debug("blacklist", "%lu addresses allowed to be scanned (%0.0f%% of address space)", allowed, allowed*100./((long long int)1 << 32)); return EXIT_SUCCESS; } zmap-1.1.0/lib/blacklist.h000066400000000000000000000010221224250063200153360ustar00rootroot00000000000000#include #include #ifndef BLACKLIST_H #define BLACKLIST_H uint32_t blacklist_lookup_index(uint64_t index); int blacklist_is_allowed(uint32_t s_addr); void blacklist_prefix(char *ip, int prefix_len); void whitelist_prefix(char *ip, int prefix_len); int blacklist_init(char *whitelist, char *blacklist, char **whitelist_entries, size_t whitelist_entries_len, char **blacklist_entries, size_t blacklist_entries_len); uint64_t blacklist_count_allowed(); uint64_t blacklist_count_not_allowed(); #endif zmap-1.1.0/lib/constraint.c000066400000000000000000000261641224250063200155630ustar00rootroot00000000000000#include #include #include #include #include #include #include #include #include #include "../lib/constraint.h" #include "../lib/logger.h" // // Efficient address-space constraints (AH 7/2013) // // This module uses a tree-based representation to efficiently // manipulate and query constraints on the address space to be // scanned. It provides a value for every IP address, and these // values are applied by setting them for network prefixes. Order // matters: setting a value replaces any existing value for that // prefix or subsets of it. We use this to implement network // whitelisting and blacklisting. // // Think of setting values in this structure like painting // subnets with different colors. We can paint subnets black to // exclude them and white to allow them. Only the top color shows. // This makes for potentially very powerful constraint specifications. // // Internally, this is implemented using a binary tree, where each // node corresponds to a network prefix. (E.g., the root is // 0.0.0.0/0, and its children, if present, are 0.0.0.0/1 and // 128.0.0.0/1.) Each leaf of the tree stores the value that applies // to every address within the leaf's portion of the prefix space. // // As an optimization, after all values are set, we look up the // value or subtree for every /16 prefix and cache them as an array. // This lets subsequent lookups bypass the bottom half of the tree. // /* * Constraint Copyright 2013 Regents of the University of Michigan * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy * of the License at http://www.apache.org/licenses/LICENSE-2.0 */ typedef struct node { struct node *l; struct node *r; value_t value; uint64_t count; } node_t; // As an optimization, we precompute lookups for every prefix of this // length: #define RADIX_LENGTH 20 struct _constraint { node_t *root; // root node of the tree uint32_t *radix; // array of prefixes (/RADIX_LENGTH) that are painted paint_value size_t radix_len; // number of prefixes in radix array int painted; // have we precomputed counts for each node? value_t paint_value; // value for which we precomputed counts }; // Tree operations respect the invariant that every node that isn't a // leaf has exactly two children. #define IS_LEAF(node) ((node)->l == NULL) // Allocate a new leaf with the given value static node_t* _create_leaf(value_t value) { node_t *node = malloc(sizeof(node_t)); assert(node); node->l = NULL; node->r = NULL; node->value = value; return node; } // Free the subtree rooted at node. static void _destroy_subtree(node_t *node) { if (node == NULL) return; _destroy_subtree(node->l); _destroy_subtree(node->r); free(node); } // Convert from an internal node to a leaf. static void _convert_to_leaf(node_t *node) { assert(node); assert(!IS_LEAF(node)); _destroy_subtree(node->l); _destroy_subtree(node->r); node->l = NULL; node->r = NULL; } // Recursive function to set value for a given network prefix within // the tree. (Note: prefix must be in host byte order.) static void _set_recurse(node_t *node, uint32_t prefix, int len, value_t value) { assert(node); assert(0 <= len && len <= 32); if (len == 0) { // We're at the end of the prefix; make this a leaf and set the value. if (!IS_LEAF(node)) { _convert_to_leaf(node); } node->value = value; return; } if (IS_LEAF(node)) { // We're not at the end of the prefix, but we hit a leaf. if (node->value == value) { // A larger prefix has the same value, so we're done. return; } // The larger prefix has a different value, so we need to convert it // into an internal node and continue processing on one of the leaves. node->l = _create_leaf(node->value); node->r = _create_leaf(node->value); } // We're not at the end of the prefix, and we're at an internal // node. Recurse on the left or right subtree. if (prefix & 0x80000000) { _set_recurse(node->r, prefix << 1, len - 1, value); } else { _set_recurse(node->l, prefix << 1, len - 1, value); } // At this point, we're an internal node, and the value is set // by one of our children or its descendent. If both children are // leaves with the same value, we can discard them and become a left. if (IS_LEAF(node->r) && IS_LEAF(node->l) && node->r->value == node->l->value) { node->value = node->l->value; _convert_to_leaf(node); } } // Set the value for a given network prefix, overwriting any existing // values on that prefix or subsets of it. // (Note: prefix must be in host byte order.) void constraint_set(constraint_t *con, uint32_t prefix, int len, value_t value) { assert(con); _set_recurse(con->root, prefix, len, value); con->painted = 0; } // Return the value pertaining to an address, according to the tree // starting at given root. (Note: address must be in host byte order.) static int _lookup_ip(node_t *root, uint32_t address) { assert(root); node_t *node = root; uint32_t mask = 0x80000000; for (;;) { if (IS_LEAF(node)) { return node->value; } if (address & mask) { node = node->r; } else { node = node->l; } mask >>= 1; } } // Return the value pertaining to an address. // (Note: address must be in host byte order.) value_t constraint_lookup_ip(constraint_t *con, uint32_t address) { assert(con); return _lookup_ip(con->root, address); } // Return the nth painted IP address. static int _lookup_index(node_t *root, uint64_t n) { assert(root); node_t *node = root; uint32_t ip = 0; uint32_t mask = 0x80000000; for (;;) { if (IS_LEAF(node)) { return ip | n; } if (n < node->l->count) { node = node->l; } else { n -= node->l->count; node = node->r; ip |= mask; } mask >>= 1; } } // For a given value, return the IP address with zero-based index n. // (i.e., if there are three addresses with value 0xFF, looking up index 1 // will return the second one). // Note that the tree must have been previously painted with this value. uint32_t constraint_lookup_index(constraint_t *con, uint64_t index, value_t value) { assert(con); if (!con->painted || con->paint_value != value) { constraint_paint_value(con, value); } uint64_t radix_idx = index / (1 << (32 - RADIX_LENGTH)); if (radix_idx < con->radix_len) { // Radix lookup uint32_t radix_offset = index % (1 << (32 - RADIX_LENGTH)); // TODO: bitwise maths return con->radix[radix_idx] | radix_offset; } // Otherwise, do the "slow" lookup in tree. // Note that tree counts do NOT include things in the radix, // so we subtract these off here. index -= con->radix_len * (1 << (32 - RADIX_LENGTH)); assert(index < con->root->count); return _lookup_index(con->root, index); } // Implement count_ips by recursing on halves of the tree. Size represents // the number of addresses in a prefix at the current level of the tree. // If paint is specified, each node will have its count set to the number of // leaves under it set to value. // If exclude_radix is specified, the number of addresses will exlcude prefixes // that are a /RADIX_LENGTH or larger static uint64_t _count_ips_recurse(node_t *node, value_t value, uint64_t size, int paint, int exclude_radix) { assert(node); uint64_t n; if (IS_LEAF(node)) { if (node->value == value) { n = size; // Exclude prefixes already included in the radix if (exclude_radix && size >= (1 << (32 -RADIX_LENGTH))) { n = 0; } } else { n = 0; } } else { n = _count_ips_recurse(node->l, value, size >> 1, paint, exclude_radix) + _count_ips_recurse(node->r, value, size >> 1, paint, exclude_radix); } if (paint) { node->count = n; } return n; } // Return a node that determines the values for the addresses with // the given prefix. This is either the internal node that // corresponds to the end of the prefix or a leaf node that // encompasses the prefix. (Note: prefix must be in host byte order.) static node_t* _lookup_node(node_t *root, uint32_t prefix, int len) { assert(root); assert(0 <= len && len <= 32); node_t *node = root; uint32_t mask = 0x80000000; int i; for (i=0; i < len; i++) { if (IS_LEAF(node)) { return node; } if (prefix & mask) { node = node->r; } else { node = node->l; } mask >>= 1; } return node; } // For each node, precompute the count of leaves beneath it set to value. // Note that the tree can be painted for only one value at a time. void constraint_paint_value(constraint_t *con, value_t value) { assert(con); log_trace("constraint", "Painting value %lu", value); // Paint everything except what we will put in radix _count_ips_recurse(con->root, value, (uint64_t)1 << 32, 1, 1); // Fill in the radix array with a list of addresses uint32_t i; con->radix_len = 0; for (i=0; i < (1 << RADIX_LENGTH); i++) { uint32_t prefix = i << (32 - RADIX_LENGTH); node_t *node = _lookup_node(con->root, prefix, RADIX_LENGTH); if (IS_LEAF(node) && node->value == value) { // Add this prefix to the radix con->radix[con->radix_len++] = prefix; } } log_debug("constraint", "%lu IPs in radix array, %lu IPs in tree", con->radix_len * (1 << (32 - RADIX_LENGTH)), con->root->count); con->painted = 1; con->paint_value = value; } // Return the number of addresses that have a given value. uint64_t constraint_count_ips(constraint_t *con, value_t value) { assert(con); if (con->painted && con->paint_value == value) { return con->root->count + con->radix_len * (1 << (32 - RADIX_LENGTH)); } else { return _count_ips_recurse(con->root, value, (uint64_t)1 << 32, 0, 0); } } // Initialize the tree. // All addresses will initally have the given value. constraint_t* constraint_init(value_t value) { log_trace("constraint", "Initializing"); constraint_t* con = malloc(sizeof(constraint_t)); con->root = _create_leaf(value); con->radix = calloc(sizeof(uint32_t), 1 << RADIX_LENGTH); assert(con->radix); con->painted = 0; return con; } // Deinitialize and free the tree. void constraint_free(constraint_t *con) { assert(con); log_trace("constraint", "Cleaning up"); _destroy_subtree(con->root); free(con->radix); free(con); } /* int main(void) { log_init(stderr, LOG_DEBUG); constraint_t *con = constraint_init(0); constraint_set(con, ntohl(inet_addr("128.128.0.0")), 1, 22); constraint_set(con, ntohl(inet_addr("128.128.0.0")), 1, 1); constraint_set(con, ntohl(inet_addr("128.0.0.0")), 1, 1); constraint_set(con, ntohl(inet_addr("10.0.0.0")), 24, 1); constraint_set(con, ntohl(inet_addr("10.0.0.0")), 24, 0); constraint_set(con, ntohl(inet_addr("10.11.12.0")), 24, 1); constraint_set(con, ntohl(inet_addr("141.212.0.0")), 16, 0); for (int x=1; x < 2; x++) { if (x == 1) { constraint_optimize(con); } printf("count(0)=%ld\n", constraint_count_ips(con, 0)); printf("count(1)=%ld\n", constraint_count_ips(con, 1)); printf("%d\n", constraint_lookup_ip(con,ntohl(inet_addr("10.11.12.0")))); assert(constraint_count_ips(con, 0) + constraint_count_ips(con, 1) == (uint64_t)1 << 32); uint32_t i=0, count=0; do { if (constraint_lookup_ip(con, i)) count++; } while (++i != 0); printf("derived count(1)=%u\n", count); } constraint_free(con); } */ zmap-1.1.0/lib/constraint.h000066400000000000000000000011371224250063200155610ustar00rootroot00000000000000#ifndef CONSTRAINT_H #define CONSTRAINT_H #include typedef struct _constraint constraint_t; typedef unsigned int value_t; constraint_t* constraint_init(value_t value); void constraint_free(constraint_t *con); void constraint_set(constraint_t *con, uint32_t prefix, int len, value_t value); value_t constraint_lookup_ip(constraint_t *con, uint32_t address); uint64_t constraint_count_ips(constraint_t *con, value_t value); uint32_t constraint_lookup_index(constraint_t *con, uint64_t index, value_t value); void constraint_paint_value(constraint_t *con, value_t value); #endif //_CONSTRAINT_H zmap-1.1.0/lib/logger.c000066400000000000000000000061331224250063200146500ustar00rootroot00000000000000/* * Logger Copyright 2013 Regents of the University of Michigan * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy * of the License at http://www.apache.org/licenses/LICENSE-2.0 */ #include #include #include #include #include #include #include #include "logger.h" #ifndef HEADER_ZUTIL_LOGGER_H #define HEADER_ZUTIL_LOGGER_H static enum LogLevel log_output_level = LOG_INFO; static FILE *log_output_stream = NULL; static const char *log_level_name[] = { "FATAL", "ERROR", "WARN", "INFO", "DEBUG", "TRACE" }; static int LogLogVA(enum LogLevel level, const char *loggerName, const char *logMessage, va_list args) { if (!log_output_stream) { log_output_stream = stdout; } if (level <= log_output_level) { const char *levelName = log_level_name[level]; assert(level < sizeof(log_level_name)); struct timeval now; char timestamp[256]; gettimeofday(&now, NULL); time_t sec = now.tv_sec; struct tm* ptm = localtime(&sec); strftime(timestamp, 20, "%b %d %H:%M:%S", ptm); fprintf(log_output_stream, "%s.%03ld [%s] ", timestamp, now.tv_usec/1000, levelName); if (loggerName) { fprintf(log_output_stream, "%s: ", loggerName); } if (logMessage) { vfprintf(log_output_stream, logMessage, args); } if (loggerName || logMessage) { fputs("\n", log_output_stream); } fflush(log_output_stream); } return 0; } int log_fatal(const char *name, const char *message, ...) { va_list va; va_start(va, message); LogLogVA(LOG_FATAL, name, message, va); va_end(va); exit(EXIT_FAILURE); } int log_error(const char *name, const char *message, ...) { va_list va; va_start(va, message); int ret = LogLogVA(LOG_ERROR, name, message, va); va_end(va); return ret; } int log_warn(const char *name, const char *message, ...) { va_list va; va_start(va, message); int ret = LogLogVA(LOG_WARN, name, message, va); va_end(va); return ret; } int log_info(const char *name, const char *message, ...) { va_list va; va_start(va, message); int ret = LogLogVA(LOG_INFO, name, message, va); va_end(va); return ret; } int log_debug(const char *name, const char *message, ...) { va_list va; va_start(va, message); int ret = LogLogVA(LOG_DEBUG, name, message, va); va_end(va); return ret; } extern int log_trace(const char *name, const char *message, ...) { va_list va; va_start(va, message); int ret = LogLogVA(LOG_TRACE, name, message, va); va_end(va); return ret; } int log_init(FILE *stream, enum LogLevel level) { log_output_stream = stream; log_output_level = level; return 0; } double now(void) { struct timeval now; gettimeofday(&now, NULL); return (double)now.tv_sec + (double)now.tv_usec/1000000.; } size_t dstrftime(char *buf, size_t maxsize, const char *format, double tm) { struct timeval tv; double tm_floor; tm_floor = floor(tm); tv.tv_sec = (long) tm_floor; tv.tv_usec = (long) (tm - floor(tm)) * 1000000; return strftime(buf, maxsize, format, localtime((const time_t*) &tv)); } #endif zmap-1.1.0/lib/logger.h000066400000000000000000000013671224250063200146610ustar00rootroot00000000000000#include #include #ifndef LOGGER_H #define LOGGER_H enum LogLevel { LOG_FATAL, LOG_ERROR, LOG_WARN, LOG_INFO, LOG_DEBUG, LOG_TRACE, NUM_LOGLEVELS }; int log_fatal(const char *loggerName, const char *logMessage, ...) __attribute__((noreturn)); int log_error(const char *loggerName, const char *logMessage, ...); int log_warn(const char *loggerName, const char *logMessage, ...); int log_info(const char *loggerName, const char *logMessage, ...); int log_debug(const char *loggerName, const char *logMessage, ...); int log_trace(const char *loggerName, const char *logMessage, ...); int log_init(FILE *stream, enum LogLevel level); size_t dstrftime(char *, size_t, const char *, double); double now(); #endif // _LOGGER_H zmap-1.1.0/lib/pbm.c000066400000000000000000000020661224250063200141500ustar00rootroot00000000000000#include #include #include #include #include #include "logger.h" #define NUM_VALUES 0xFFFFFFFF #define PAGE_SIZE 0xFFFF #define NUM_PAGES (NUM_VALUES / PAGE_SIZE) #define SIZE (8*sizeof(uint64_t)) uint64_t** pbm_init(void) { uint64_t** retv = calloc(NUM_PAGES, sizeof(void*)); if (!retv) { log_fatal("pbm", "unable to allocate memory for base page table"); } return retv; } static int bm_check(uint64_t *bm, uint32_t v) { return bm[v/SIZE] & (1<< (v % SIZE)); } static void bm_set(uint64_t *bm, uint32_t v) { bm[v/SIZE] |= (1 << (v % SIZE)); } int pbm_check(uint64_t **b, uint32_t v) { uint32_t top = v >> 16; uint32_t bottom = v & PAGE_SIZE; return b[top] && bm_check(b[top], bottom); } void pbm_set(uint64_t **b, uint32_t v) { uint32_t top = v >> 16; uint32_t bottom = v & PAGE_SIZE; if (!b[top]) { uint64_t *bm = malloc(PAGE_SIZE/8); if (!bm) { log_fatal("bpm", "unable to allocate memory for new bitmap page"); } memset(bm, 0, PAGE_SIZE/8); b[top] = bm; } bm_set(b[top], bottom); } zmap-1.1.0/lib/pbm.h000066400000000000000000000002011224250063200141420ustar00rootroot00000000000000#include uint64_t** pbm_init(void); int pbm_check(uint64_t **b, uint32_t v); void pbm_set(uint64_t **b, uint32_t v); zmap-1.1.0/lib/random.c000066400000000000000000000011531224250063200146460ustar00rootroot00000000000000/* * ZMap Copyright 2013 Regents of the University of Michigan * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy * of the License at http://www.apache.org/licenses/LICENSE-2.0 */ #include "random.h" #include #include #include #include #include #define RANDSRC "/dev/urandom" int random_bytes(void *dst, size_t n) { FILE *f = fopen(RANDSRC, "rb"); assert(f); size_t r = fread(dst, n, 1, f); fclose(f); if (r < 1) { return 0; } return 1; } zmap-1.1.0/lib/random.h000066400000000000000000000001731224250063200146540ustar00rootroot00000000000000#include #include #ifndef RANDOM_H #define RANDOM_H int random_bytes(void *dst, size_t n); #endif zmap-1.1.0/lib/redis.c000066400000000000000000000166011224250063200145000ustar00rootroot00000000000000/* * ZMap Redis Helpers Copyright 2013 Regents of the University of Michigan * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy * of the License at http://www.apache.org/licenses/LICENSE-2.0 */ #include "redis.h" #include #include #include #include #include #include #include "logger.h" #define REDIS_TIMEOUT 2 #undef MIN #define MIN(X,Y) ((X) < (Y) ? (X) : (Y)) static redisContext *rctx; redisconf_t *redis_parse_connstr(char *connstr) { redisconf_t *retv = malloc(sizeof(redisconf_t)); if (!strncmp("tcp://", connstr, 6)) { char *servername = malloc(strlen(connstr)); assert(servername); char *list_name = malloc(strlen(connstr)); assert(list_name); uint32_t port; if (sscanf(connstr, "tcp://%[^:]:%u/%s", servername, &port, list_name) != 3) { log_fatal("redis", "unable to parse redis connection string. This " "should be of the form tcp://server:port/list-name " "for TCP connections. All fields are required."); } retv->type = T_TCP; retv->server = servername; retv->port = port; retv->list_name = list_name; retv->path = NULL; } else if (!strncmp("local://", connstr, 8)) { // looking for something along the lines of // local:///tmp/redis.sock/list-name char *path = malloc(strlen(connstr)); assert(path); char *list_name = malloc(strlen(connstr)); assert(list_name); connstr = connstr + (size_t) 8; char *listname = strrchr(connstr, '/') + (size_t) 1; connstr[strrchr(connstr, '/') - connstr] = '\0'; strcpy(path, connstr); strcpy(list_name, listname); retv->type = T_LOCAL; retv->list_name = list_name; retv->path = path; retv->server = NULL; retv->port = 0; } else { log_fatal("redis", "unable to parse connection string. does not begin with " "local:// or tcp:// as expected"); } return retv; } static redisContext* redis_connect(char *connstr) { redisconf_t *c; // handle old behavior where we only connected to a specific // socket that we #defined. if (!connstr) { c = malloc(sizeof(redisconf_t)); assert(c); c->type = T_LOCAL; c->path = strdup("/tmp/redis.sock"); } else { c = redis_parse_connstr(connstr); assert(c); } struct timeval timeout; timeout.tv_sec = REDIS_TIMEOUT; timeout.tv_usec = 0; if (c->type == T_LOCAL) { return (redisContext*) redisConnectUnixWithTimeout(c->path, timeout); } else { return (redisContext*) redisConnectWithTimeout(c->server, c->port, timeout); } } static int chkerr(redisReply *reply) { assert(rctx); if (reply == NULL || reply->type == REDIS_REPLY_ERROR) { log_error("redis", "an error occurred when " "retreiving item from redis: %s", rctx->errstr); if (reply) { freeReplyObject(reply); } return -1; } return 0; } int redis_init(char *connstr) { rctx = redis_connect(connstr); if (!rctx) { return -1; } return 0; } int redis_close(void) { redisFree(rctx); return 0; } redisContext* redis_get_context(void) { return rctx; } int redis_flush(void) { redisReply *reply = (redisReply*) redisCommand(rctx, "FLUSHDB"); if (chkerr(reply)) { return -1; } freeReplyObject(reply); return 0; } int redis_existconf(const char *name) { assert(rctx); redisReply *reply = (redisReply*) redisCommand(rctx, "EXISTS %s", name); if (chkerr(reply)) { return -1; } int v = reply->integer; freeReplyObject(reply); return v; } int redis_delconf(const char *name) { assert(rctx); redisReply *reply = (redisReply*) redisCommand(rctx, "DEL %s", name); if (chkerr(reply)) { return -1; } freeReplyObject(reply); return 0; } int redis_setconf(const char *name, char *value) { assert(rctx); redisReply *reply = (redisReply*) redisCommand(rctx, "SET %s %s", name, value); if (chkerr(reply)) { return -1; } freeReplyObject(reply); return 0; } int redis_getconf(const char *name, char *buf, size_t maxlen) { assert(rctx); redisReply *reply = (redisReply*) redisCommand(rctx, "GET %s", name); if (chkerr(reply)) { return -1; } strncpy(buf, reply->str, maxlen); freeReplyObject(reply); return 0; } uint32_t redis_getconf_uint32_t(const char *key) { assert(rctx); char buf[50]; redis_getconf(key, buf, 50); return atoi(buf); } int redis_setconf_uint32_t(const char *key, uint32_t value) { assert(rctx); char buf[50]; sprintf(buf, "%u", value); return redis_setconf(key, buf); } static long redis_get_sizeof(const char *cmd, const char *name) { assert(rctx); redisReply *reply; reply = (redisReply*) redisCommand(rctx, "%s %s", cmd, name); assert(reply); assert(reply->type == REDIS_REPLY_INTEGER); long rtr = reply->integer; freeReplyObject(reply); return rtr; } long redis_get_sizeof_list(const char *name) { return redis_get_sizeof("LLEN", name); } long redis_get_sizeof_set(const char *name) { return redis_get_sizeof("SCARD", name); } int redis_pull(char *redisqueuename, void *buf, int maxload, size_t obj_size, int *numloaded, const char* cmd) { assert(rctx); long elems_in_redis = redis_get_sizeof_list(redisqueuename); long num_to_add = MIN(elems_in_redis, maxload); log_info("redis", "INFO: redis load called on %s. Transfering %li " "of %li elements to in-memory queue.", redisqueuename, num_to_add, elems_in_redis); for(int i=0; i < num_to_add; i++) { redisAppendCommand(rctx, "%s %s", cmd, redisqueuename); } for(int i=0; i < num_to_add; i++) { redisReply *reply; int rc = redisGetReply(rctx, (void**) &reply); if (rc != REDIS_OK) { log_fatal("redis", "response from redis != REDIS_OK"); return -1; } if (!reply) { log_fatal("redis", "no reply provided by redis."); return -1; } if (reply->type != REDIS_REPLY_STRING) { log_fatal("redis", "unxpected reply type from redis."); return -1; } if ((size_t)reply->len != obj_size) { log_fatal("redis", "ERROR: unexpected lengthed " "object provided by redis.\n"); return -1; } memcpy((void*)((intptr_t)buf+i*obj_size), reply->str, obj_size); freeReplyObject(reply); } *numloaded = num_to_add; return 0; } int redis_lpull(char *redisqueuename, void *buf, int maxload, size_t obj_size, int *numloaded) { return redis_pull(redisqueuename, buf, maxload, obj_size, numloaded, "LPOP"); } int redis_spull(char *redisqueuename, void *buf, int maxload, size_t obj_size, int *numloaded) { return redis_pull(redisqueuename, buf, maxload, obj_size, numloaded, "SRAND"); } static int redis_push(char *redisqueuename, void *buf, int num, size_t len, const char *cmd) { assert(rctx); for (int i=0; i < num; i++) { void* load = (void*)((intptr_t)buf + i*len); int rc = redisAppendCommand(rctx, "%s %s %b", cmd, redisqueuename, load, len); if (rc != REDIS_OK || rctx->err) { log_fatal("redis", "%s", rctx->errstr); return -1; } } redisReply *reply; for (int i=0; i < num; i++) { if (redisGetReply(rctx, (void**) &reply) != REDIS_OK || rctx->err) { log_fatal("redis","%s", rctx->errstr); return -1; } if (reply->type == REDIS_REPLY_ERROR) { log_fatal("redis", "%s", rctx->errstr); return -1; } freeReplyObject(reply); } return 0; } int redis_lpush(char *redisqueuename, void *buf, int num, size_t len) { return redis_push(redisqueuename, buf, num, len, "RPUSH"); } int redis_spush(char *redisqueuename, void *buf, int num, size_t len) { return redis_push(redisqueuename, buf, num, len, "SADD"); } zmap-1.1.0/lib/redis.h000066400000000000000000000017401224250063200145030ustar00rootroot00000000000000#include #include #include #ifndef REDIS_ZHELPERS_H #define REDIS_ZHELPERS_H #define T_TCP 0 #define T_LOCAL 1 typedef struct redisconf { int type; char *path; char *server; uint16_t port; char *list_name; } redisconf_t; redisconf_t *redis_parse_connstr(char *connstr); int redis_init(char*); int redis_close(void); int redis_existconf(const char*); int redis_flush(void); int redis_delconf(const char*); int redis_setconf(const char*, char*); int redis_getconf(const char*, char*, size_t); long redis_get_sizeof_list(const char*); long redis_get_sizeof_set(const char*); int redis_lpush(char*, void*, int, size_t); int redis_lpull(char*, void*, int, size_t, int*); int redis_spull(char*, void*, int, size_t, int*); int redis_spush(char*, void*, int, size_t); redisContext* redis_get_context(void); uint32_t redis_getconf_uint32_t(const char*); int redis_setconf_uint32_t(const char*, uint32_t); #endif // _REDIS_ZHELPERS_H zmap-1.1.0/lib/rijndael-alg-fst.c000066400000000000000000001770541224250063200165270ustar00rootroot00000000000000/** * rijndael-alg-fst.c * * @version 3.0 (December 2000) * * Optimised ANSI C code for the Rijndael cipher (now AES) * * @author Vincent Rijmen * @author Antoon Bosselaers * @author Paulo Barreto * * This code is hereby placed in the public domain. * * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include "rijndael-alg-fst.h" /* Te0[x] = S [x].[02, 01, 01, 03]; Te1[x] = S [x].[03, 02, 01, 01]; Te2[x] = S [x].[01, 03, 02, 01]; Te3[x] = S [x].[01, 01, 03, 02]; Te4[x] = S [x].[01, 01, 01, 01]; Td0[x] = Si[x].[0e, 09, 0d, 0b]; Td1[x] = Si[x].[0b, 0e, 09, 0d]; Td2[x] = Si[x].[0d, 0b, 0e, 09]; Td3[x] = Si[x].[09, 0d, 0b, 0e]; Td4[x] = Si[x].[01, 01, 01, 01]; */ static const u32 Te0[256] = { 0xc66363a5U, 0xf87c7c84U, 0xee777799U, 0xf67b7b8dU, 0xfff2f20dU, 0xd66b6bbdU, 0xde6f6fb1U, 0x91c5c554U, 0x60303050U, 0x02010103U, 0xce6767a9U, 0x562b2b7dU, 0xe7fefe19U, 0xb5d7d762U, 0x4dababe6U, 0xec76769aU, 0x8fcaca45U, 0x1f82829dU, 0x89c9c940U, 0xfa7d7d87U, 0xeffafa15U, 0xb25959ebU, 0x8e4747c9U, 0xfbf0f00bU, 0x41adadecU, 0xb3d4d467U, 0x5fa2a2fdU, 0x45afafeaU, 0x239c9cbfU, 0x53a4a4f7U, 0xe4727296U, 0x9bc0c05bU, 0x75b7b7c2U, 0xe1fdfd1cU, 0x3d9393aeU, 0x4c26266aU, 0x6c36365aU, 0x7e3f3f41U, 0xf5f7f702U, 0x83cccc4fU, 0x6834345cU, 0x51a5a5f4U, 0xd1e5e534U, 0xf9f1f108U, 0xe2717193U, 0xabd8d873U, 0x62313153U, 0x2a15153fU, 0x0804040cU, 0x95c7c752U, 0x46232365U, 0x9dc3c35eU, 0x30181828U, 0x379696a1U, 0x0a05050fU, 0x2f9a9ab5U, 0x0e070709U, 0x24121236U, 0x1b80809bU, 0xdfe2e23dU, 0xcdebeb26U, 0x4e272769U, 0x7fb2b2cdU, 0xea75759fU, 0x1209091bU, 0x1d83839eU, 0x582c2c74U, 0x341a1a2eU, 0x361b1b2dU, 0xdc6e6eb2U, 0xb45a5aeeU, 0x5ba0a0fbU, 0xa45252f6U, 0x763b3b4dU, 0xb7d6d661U, 0x7db3b3ceU, 0x5229297bU, 0xdde3e33eU, 0x5e2f2f71U, 0x13848497U, 0xa65353f5U, 0xb9d1d168U, 0x00000000U, 0xc1eded2cU, 0x40202060U, 0xe3fcfc1fU, 0x79b1b1c8U, 0xb65b5bedU, 0xd46a6abeU, 0x8dcbcb46U, 0x67bebed9U, 0x7239394bU, 0x944a4adeU, 0x984c4cd4U, 0xb05858e8U, 0x85cfcf4aU, 0xbbd0d06bU, 0xc5efef2aU, 0x4faaaae5U, 0xedfbfb16U, 0x864343c5U, 0x9a4d4dd7U, 0x66333355U, 0x11858594U, 0x8a4545cfU, 0xe9f9f910U, 0x04020206U, 0xfe7f7f81U, 0xa05050f0U, 0x783c3c44U, 0x259f9fbaU, 0x4ba8a8e3U, 0xa25151f3U, 0x5da3a3feU, 0x804040c0U, 0x058f8f8aU, 0x3f9292adU, 0x219d9dbcU, 0x70383848U, 0xf1f5f504U, 0x63bcbcdfU, 0x77b6b6c1U, 0xafdada75U, 0x42212163U, 0x20101030U, 0xe5ffff1aU, 0xfdf3f30eU, 0xbfd2d26dU, 0x81cdcd4cU, 0x180c0c14U, 0x26131335U, 0xc3ecec2fU, 0xbe5f5fe1U, 0x359797a2U, 0x884444ccU, 0x2e171739U, 0x93c4c457U, 0x55a7a7f2U, 0xfc7e7e82U, 0x7a3d3d47U, 0xc86464acU, 0xba5d5de7U, 0x3219192bU, 0xe6737395U, 0xc06060a0U, 0x19818198U, 0x9e4f4fd1U, 0xa3dcdc7fU, 0x44222266U, 0x542a2a7eU, 0x3b9090abU, 0x0b888883U, 0x8c4646caU, 0xc7eeee29U, 0x6bb8b8d3U, 0x2814143cU, 0xa7dede79U, 0xbc5e5ee2U, 0x160b0b1dU, 0xaddbdb76U, 0xdbe0e03bU, 0x64323256U, 0x743a3a4eU, 0x140a0a1eU, 0x924949dbU, 0x0c06060aU, 0x4824246cU, 0xb85c5ce4U, 0x9fc2c25dU, 0xbdd3d36eU, 0x43acacefU, 0xc46262a6U, 0x399191a8U, 0x319595a4U, 0xd3e4e437U, 0xf279798bU, 0xd5e7e732U, 0x8bc8c843U, 0x6e373759U, 0xda6d6db7U, 0x018d8d8cU, 0xb1d5d564U, 0x9c4e4ed2U, 0x49a9a9e0U, 0xd86c6cb4U, 0xac5656faU, 0xf3f4f407U, 0xcfeaea25U, 0xca6565afU, 0xf47a7a8eU, 0x47aeaee9U, 0x10080818U, 0x6fbabad5U, 0xf0787888U, 0x4a25256fU, 0x5c2e2e72U, 0x381c1c24U, 0x57a6a6f1U, 0x73b4b4c7U, 0x97c6c651U, 0xcbe8e823U, 0xa1dddd7cU, 0xe874749cU, 0x3e1f1f21U, 0x964b4bddU, 0x61bdbddcU, 0x0d8b8b86U, 0x0f8a8a85U, 0xe0707090U, 0x7c3e3e42U, 0x71b5b5c4U, 0xcc6666aaU, 0x904848d8U, 0x06030305U, 0xf7f6f601U, 0x1c0e0e12U, 0xc26161a3U, 0x6a35355fU, 0xae5757f9U, 0x69b9b9d0U, 0x17868691U, 0x99c1c158U, 0x3a1d1d27U, 0x279e9eb9U, 0xd9e1e138U, 0xebf8f813U, 0x2b9898b3U, 0x22111133U, 0xd26969bbU, 0xa9d9d970U, 0x078e8e89U, 0x339494a7U, 0x2d9b9bb6U, 0x3c1e1e22U, 0x15878792U, 0xc9e9e920U, 0x87cece49U, 0xaa5555ffU, 0x50282878U, 0xa5dfdf7aU, 0x038c8c8fU, 0x59a1a1f8U, 0x09898980U, 0x1a0d0d17U, 0x65bfbfdaU, 0xd7e6e631U, 0x844242c6U, 0xd06868b8U, 0x824141c3U, 0x299999b0U, 0x5a2d2d77U, 0x1e0f0f11U, 0x7bb0b0cbU, 0xa85454fcU, 0x6dbbbbd6U, 0x2c16163aU, }; static const u32 Te1[256] = { 0xa5c66363U, 0x84f87c7cU, 0x99ee7777U, 0x8df67b7bU, 0x0dfff2f2U, 0xbdd66b6bU, 0xb1de6f6fU, 0x5491c5c5U, 0x50603030U, 0x03020101U, 0xa9ce6767U, 0x7d562b2bU, 0x19e7fefeU, 0x62b5d7d7U, 0xe64dababU, 0x9aec7676U, 0x458fcacaU, 0x9d1f8282U, 0x4089c9c9U, 0x87fa7d7dU, 0x15effafaU, 0xebb25959U, 0xc98e4747U, 0x0bfbf0f0U, 0xec41adadU, 0x67b3d4d4U, 0xfd5fa2a2U, 0xea45afafU, 0xbf239c9cU, 0xf753a4a4U, 0x96e47272U, 0x5b9bc0c0U, 0xc275b7b7U, 0x1ce1fdfdU, 0xae3d9393U, 0x6a4c2626U, 0x5a6c3636U, 0x417e3f3fU, 0x02f5f7f7U, 0x4f83ccccU, 0x5c683434U, 0xf451a5a5U, 0x34d1e5e5U, 0x08f9f1f1U, 0x93e27171U, 0x73abd8d8U, 0x53623131U, 0x3f2a1515U, 0x0c080404U, 0x5295c7c7U, 0x65462323U, 0x5e9dc3c3U, 0x28301818U, 0xa1379696U, 0x0f0a0505U, 0xb52f9a9aU, 0x090e0707U, 0x36241212U, 0x9b1b8080U, 0x3ddfe2e2U, 0x26cdebebU, 0x694e2727U, 0xcd7fb2b2U, 0x9fea7575U, 0x1b120909U, 0x9e1d8383U, 0x74582c2cU, 0x2e341a1aU, 0x2d361b1bU, 0xb2dc6e6eU, 0xeeb45a5aU, 0xfb5ba0a0U, 0xf6a45252U, 0x4d763b3bU, 0x61b7d6d6U, 0xce7db3b3U, 0x7b522929U, 0x3edde3e3U, 0x715e2f2fU, 0x97138484U, 0xf5a65353U, 0x68b9d1d1U, 0x00000000U, 0x2cc1ededU, 0x60402020U, 0x1fe3fcfcU, 0xc879b1b1U, 0xedb65b5bU, 0xbed46a6aU, 0x468dcbcbU, 0xd967bebeU, 0x4b723939U, 0xde944a4aU, 0xd4984c4cU, 0xe8b05858U, 0x4a85cfcfU, 0x6bbbd0d0U, 0x2ac5efefU, 0xe54faaaaU, 0x16edfbfbU, 0xc5864343U, 0xd79a4d4dU, 0x55663333U, 0x94118585U, 0xcf8a4545U, 0x10e9f9f9U, 0x06040202U, 0x81fe7f7fU, 0xf0a05050U, 0x44783c3cU, 0xba259f9fU, 0xe34ba8a8U, 0xf3a25151U, 0xfe5da3a3U, 0xc0804040U, 0x8a058f8fU, 0xad3f9292U, 0xbc219d9dU, 0x48703838U, 0x04f1f5f5U, 0xdf63bcbcU, 0xc177b6b6U, 0x75afdadaU, 0x63422121U, 0x30201010U, 0x1ae5ffffU, 0x0efdf3f3U, 0x6dbfd2d2U, 0x4c81cdcdU, 0x14180c0cU, 0x35261313U, 0x2fc3ececU, 0xe1be5f5fU, 0xa2359797U, 0xcc884444U, 0x392e1717U, 0x5793c4c4U, 0xf255a7a7U, 0x82fc7e7eU, 0x477a3d3dU, 0xacc86464U, 0xe7ba5d5dU, 0x2b321919U, 0x95e67373U, 0xa0c06060U, 0x98198181U, 0xd19e4f4fU, 0x7fa3dcdcU, 0x66442222U, 0x7e542a2aU, 0xab3b9090U, 0x830b8888U, 0xca8c4646U, 0x29c7eeeeU, 0xd36bb8b8U, 0x3c281414U, 0x79a7dedeU, 0xe2bc5e5eU, 0x1d160b0bU, 0x76addbdbU, 0x3bdbe0e0U, 0x56643232U, 0x4e743a3aU, 0x1e140a0aU, 0xdb924949U, 0x0a0c0606U, 0x6c482424U, 0xe4b85c5cU, 0x5d9fc2c2U, 0x6ebdd3d3U, 0xef43acacU, 0xa6c46262U, 0xa8399191U, 0xa4319595U, 0x37d3e4e4U, 0x8bf27979U, 0x32d5e7e7U, 0x438bc8c8U, 0x596e3737U, 0xb7da6d6dU, 0x8c018d8dU, 0x64b1d5d5U, 0xd29c4e4eU, 0xe049a9a9U, 0xb4d86c6cU, 0xfaac5656U, 0x07f3f4f4U, 0x25cfeaeaU, 0xafca6565U, 0x8ef47a7aU, 0xe947aeaeU, 0x18100808U, 0xd56fbabaU, 0x88f07878U, 0x6f4a2525U, 0x725c2e2eU, 0x24381c1cU, 0xf157a6a6U, 0xc773b4b4U, 0x5197c6c6U, 0x23cbe8e8U, 0x7ca1ddddU, 0x9ce87474U, 0x213e1f1fU, 0xdd964b4bU, 0xdc61bdbdU, 0x860d8b8bU, 0x850f8a8aU, 0x90e07070U, 0x427c3e3eU, 0xc471b5b5U, 0xaacc6666U, 0xd8904848U, 0x05060303U, 0x01f7f6f6U, 0x121c0e0eU, 0xa3c26161U, 0x5f6a3535U, 0xf9ae5757U, 0xd069b9b9U, 0x91178686U, 0x5899c1c1U, 0x273a1d1dU, 0xb9279e9eU, 0x38d9e1e1U, 0x13ebf8f8U, 0xb32b9898U, 0x33221111U, 0xbbd26969U, 0x70a9d9d9U, 0x89078e8eU, 0xa7339494U, 0xb62d9b9bU, 0x223c1e1eU, 0x92158787U, 0x20c9e9e9U, 0x4987ceceU, 0xffaa5555U, 0x78502828U, 0x7aa5dfdfU, 0x8f038c8cU, 0xf859a1a1U, 0x80098989U, 0x171a0d0dU, 0xda65bfbfU, 0x31d7e6e6U, 0xc6844242U, 0xb8d06868U, 0xc3824141U, 0xb0299999U, 0x775a2d2dU, 0x111e0f0fU, 0xcb7bb0b0U, 0xfca85454U, 0xd66dbbbbU, 0x3a2c1616U, }; static const u32 Te2[256] = { 0x63a5c663U, 0x7c84f87cU, 0x7799ee77U, 0x7b8df67bU, 0xf20dfff2U, 0x6bbdd66bU, 0x6fb1de6fU, 0xc55491c5U, 0x30506030U, 0x01030201U, 0x67a9ce67U, 0x2b7d562bU, 0xfe19e7feU, 0xd762b5d7U, 0xabe64dabU, 0x769aec76U, 0xca458fcaU, 0x829d1f82U, 0xc94089c9U, 0x7d87fa7dU, 0xfa15effaU, 0x59ebb259U, 0x47c98e47U, 0xf00bfbf0U, 0xadec41adU, 0xd467b3d4U, 0xa2fd5fa2U, 0xafea45afU, 0x9cbf239cU, 0xa4f753a4U, 0x7296e472U, 0xc05b9bc0U, 0xb7c275b7U, 0xfd1ce1fdU, 0x93ae3d93U, 0x266a4c26U, 0x365a6c36U, 0x3f417e3fU, 0xf702f5f7U, 0xcc4f83ccU, 0x345c6834U, 0xa5f451a5U, 0xe534d1e5U, 0xf108f9f1U, 0x7193e271U, 0xd873abd8U, 0x31536231U, 0x153f2a15U, 0x040c0804U, 0xc75295c7U, 0x23654623U, 0xc35e9dc3U, 0x18283018U, 0x96a13796U, 0x050f0a05U, 0x9ab52f9aU, 0x07090e07U, 0x12362412U, 0x809b1b80U, 0xe23ddfe2U, 0xeb26cdebU, 0x27694e27U, 0xb2cd7fb2U, 0x759fea75U, 0x091b1209U, 0x839e1d83U, 0x2c74582cU, 0x1a2e341aU, 0x1b2d361bU, 0x6eb2dc6eU, 0x5aeeb45aU, 0xa0fb5ba0U, 0x52f6a452U, 0x3b4d763bU, 0xd661b7d6U, 0xb3ce7db3U, 0x297b5229U, 0xe33edde3U, 0x2f715e2fU, 0x84971384U, 0x53f5a653U, 0xd168b9d1U, 0x00000000U, 0xed2cc1edU, 0x20604020U, 0xfc1fe3fcU, 0xb1c879b1U, 0x5bedb65bU, 0x6abed46aU, 0xcb468dcbU, 0xbed967beU, 0x394b7239U, 0x4ade944aU, 0x4cd4984cU, 0x58e8b058U, 0xcf4a85cfU, 0xd06bbbd0U, 0xef2ac5efU, 0xaae54faaU, 0xfb16edfbU, 0x43c58643U, 0x4dd79a4dU, 0x33556633U, 0x85941185U, 0x45cf8a45U, 0xf910e9f9U, 0x02060402U, 0x7f81fe7fU, 0x50f0a050U, 0x3c44783cU, 0x9fba259fU, 0xa8e34ba8U, 0x51f3a251U, 0xa3fe5da3U, 0x40c08040U, 0x8f8a058fU, 0x92ad3f92U, 0x9dbc219dU, 0x38487038U, 0xf504f1f5U, 0xbcdf63bcU, 0xb6c177b6U, 0xda75afdaU, 0x21634221U, 0x10302010U, 0xff1ae5ffU, 0xf30efdf3U, 0xd26dbfd2U, 0xcd4c81cdU, 0x0c14180cU, 0x13352613U, 0xec2fc3ecU, 0x5fe1be5fU, 0x97a23597U, 0x44cc8844U, 0x17392e17U, 0xc45793c4U, 0xa7f255a7U, 0x7e82fc7eU, 0x3d477a3dU, 0x64acc864U, 0x5de7ba5dU, 0x192b3219U, 0x7395e673U, 0x60a0c060U, 0x81981981U, 0x4fd19e4fU, 0xdc7fa3dcU, 0x22664422U, 0x2a7e542aU, 0x90ab3b90U, 0x88830b88U, 0x46ca8c46U, 0xee29c7eeU, 0xb8d36bb8U, 0x143c2814U, 0xde79a7deU, 0x5ee2bc5eU, 0x0b1d160bU, 0xdb76addbU, 0xe03bdbe0U, 0x32566432U, 0x3a4e743aU, 0x0a1e140aU, 0x49db9249U, 0x060a0c06U, 0x246c4824U, 0x5ce4b85cU, 0xc25d9fc2U, 0xd36ebdd3U, 0xacef43acU, 0x62a6c462U, 0x91a83991U, 0x95a43195U, 0xe437d3e4U, 0x798bf279U, 0xe732d5e7U, 0xc8438bc8U, 0x37596e37U, 0x6db7da6dU, 0x8d8c018dU, 0xd564b1d5U, 0x4ed29c4eU, 0xa9e049a9U, 0x6cb4d86cU, 0x56faac56U, 0xf407f3f4U, 0xea25cfeaU, 0x65afca65U, 0x7a8ef47aU, 0xaee947aeU, 0x08181008U, 0xbad56fbaU, 0x7888f078U, 0x256f4a25U, 0x2e725c2eU, 0x1c24381cU, 0xa6f157a6U, 0xb4c773b4U, 0xc65197c6U, 0xe823cbe8U, 0xdd7ca1ddU, 0x749ce874U, 0x1f213e1fU, 0x4bdd964bU, 0xbddc61bdU, 0x8b860d8bU, 0x8a850f8aU, 0x7090e070U, 0x3e427c3eU, 0xb5c471b5U, 0x66aacc66U, 0x48d89048U, 0x03050603U, 0xf601f7f6U, 0x0e121c0eU, 0x61a3c261U, 0x355f6a35U, 0x57f9ae57U, 0xb9d069b9U, 0x86911786U, 0xc15899c1U, 0x1d273a1dU, 0x9eb9279eU, 0xe138d9e1U, 0xf813ebf8U, 0x98b32b98U, 0x11332211U, 0x69bbd269U, 0xd970a9d9U, 0x8e89078eU, 0x94a73394U, 0x9bb62d9bU, 0x1e223c1eU, 0x87921587U, 0xe920c9e9U, 0xce4987ceU, 0x55ffaa55U, 0x28785028U, 0xdf7aa5dfU, 0x8c8f038cU, 0xa1f859a1U, 0x89800989U, 0x0d171a0dU, 0xbfda65bfU, 0xe631d7e6U, 0x42c68442U, 0x68b8d068U, 0x41c38241U, 0x99b02999U, 0x2d775a2dU, 0x0f111e0fU, 0xb0cb7bb0U, 0x54fca854U, 0xbbd66dbbU, 0x163a2c16U, }; static const u32 Te3[256] = { 0x6363a5c6U, 0x7c7c84f8U, 0x777799eeU, 0x7b7b8df6U, 0xf2f20dffU, 0x6b6bbdd6U, 0x6f6fb1deU, 0xc5c55491U, 0x30305060U, 0x01010302U, 0x6767a9ceU, 0x2b2b7d56U, 0xfefe19e7U, 0xd7d762b5U, 0xababe64dU, 0x76769aecU, 0xcaca458fU, 0x82829d1fU, 0xc9c94089U, 0x7d7d87faU, 0xfafa15efU, 0x5959ebb2U, 0x4747c98eU, 0xf0f00bfbU, 0xadadec41U, 0xd4d467b3U, 0xa2a2fd5fU, 0xafafea45U, 0x9c9cbf23U, 0xa4a4f753U, 0x727296e4U, 0xc0c05b9bU, 0xb7b7c275U, 0xfdfd1ce1U, 0x9393ae3dU, 0x26266a4cU, 0x36365a6cU, 0x3f3f417eU, 0xf7f702f5U, 0xcccc4f83U, 0x34345c68U, 0xa5a5f451U, 0xe5e534d1U, 0xf1f108f9U, 0x717193e2U, 0xd8d873abU, 0x31315362U, 0x15153f2aU, 0x04040c08U, 0xc7c75295U, 0x23236546U, 0xc3c35e9dU, 0x18182830U, 0x9696a137U, 0x05050f0aU, 0x9a9ab52fU, 0x0707090eU, 0x12123624U, 0x80809b1bU, 0xe2e23ddfU, 0xebeb26cdU, 0x2727694eU, 0xb2b2cd7fU, 0x75759feaU, 0x09091b12U, 0x83839e1dU, 0x2c2c7458U, 0x1a1a2e34U, 0x1b1b2d36U, 0x6e6eb2dcU, 0x5a5aeeb4U, 0xa0a0fb5bU, 0x5252f6a4U, 0x3b3b4d76U, 0xd6d661b7U, 0xb3b3ce7dU, 0x29297b52U, 0xe3e33eddU, 0x2f2f715eU, 0x84849713U, 0x5353f5a6U, 0xd1d168b9U, 0x00000000U, 0xeded2cc1U, 0x20206040U, 0xfcfc1fe3U, 0xb1b1c879U, 0x5b5bedb6U, 0x6a6abed4U, 0xcbcb468dU, 0xbebed967U, 0x39394b72U, 0x4a4ade94U, 0x4c4cd498U, 0x5858e8b0U, 0xcfcf4a85U, 0xd0d06bbbU, 0xefef2ac5U, 0xaaaae54fU, 0xfbfb16edU, 0x4343c586U, 0x4d4dd79aU, 0x33335566U, 0x85859411U, 0x4545cf8aU, 0xf9f910e9U, 0x02020604U, 0x7f7f81feU, 0x5050f0a0U, 0x3c3c4478U, 0x9f9fba25U, 0xa8a8e34bU, 0x5151f3a2U, 0xa3a3fe5dU, 0x4040c080U, 0x8f8f8a05U, 0x9292ad3fU, 0x9d9dbc21U, 0x38384870U, 0xf5f504f1U, 0xbcbcdf63U, 0xb6b6c177U, 0xdada75afU, 0x21216342U, 0x10103020U, 0xffff1ae5U, 0xf3f30efdU, 0xd2d26dbfU, 0xcdcd4c81U, 0x0c0c1418U, 0x13133526U, 0xecec2fc3U, 0x5f5fe1beU, 0x9797a235U, 0x4444cc88U, 0x1717392eU, 0xc4c45793U, 0xa7a7f255U, 0x7e7e82fcU, 0x3d3d477aU, 0x6464acc8U, 0x5d5de7baU, 0x19192b32U, 0x737395e6U, 0x6060a0c0U, 0x81819819U, 0x4f4fd19eU, 0xdcdc7fa3U, 0x22226644U, 0x2a2a7e54U, 0x9090ab3bU, 0x8888830bU, 0x4646ca8cU, 0xeeee29c7U, 0xb8b8d36bU, 0x14143c28U, 0xdede79a7U, 0x5e5ee2bcU, 0x0b0b1d16U, 0xdbdb76adU, 0xe0e03bdbU, 0x32325664U, 0x3a3a4e74U, 0x0a0a1e14U, 0x4949db92U, 0x06060a0cU, 0x24246c48U, 0x5c5ce4b8U, 0xc2c25d9fU, 0xd3d36ebdU, 0xacacef43U, 0x6262a6c4U, 0x9191a839U, 0x9595a431U, 0xe4e437d3U, 0x79798bf2U, 0xe7e732d5U, 0xc8c8438bU, 0x3737596eU, 0x6d6db7daU, 0x8d8d8c01U, 0xd5d564b1U, 0x4e4ed29cU, 0xa9a9e049U, 0x6c6cb4d8U, 0x5656faacU, 0xf4f407f3U, 0xeaea25cfU, 0x6565afcaU, 0x7a7a8ef4U, 0xaeaee947U, 0x08081810U, 0xbabad56fU, 0x787888f0U, 0x25256f4aU, 0x2e2e725cU, 0x1c1c2438U, 0xa6a6f157U, 0xb4b4c773U, 0xc6c65197U, 0xe8e823cbU, 0xdddd7ca1U, 0x74749ce8U, 0x1f1f213eU, 0x4b4bdd96U, 0xbdbddc61U, 0x8b8b860dU, 0x8a8a850fU, 0x707090e0U, 0x3e3e427cU, 0xb5b5c471U, 0x6666aaccU, 0x4848d890U, 0x03030506U, 0xf6f601f7U, 0x0e0e121cU, 0x6161a3c2U, 0x35355f6aU, 0x5757f9aeU, 0xb9b9d069U, 0x86869117U, 0xc1c15899U, 0x1d1d273aU, 0x9e9eb927U, 0xe1e138d9U, 0xf8f813ebU, 0x9898b32bU, 0x11113322U, 0x6969bbd2U, 0xd9d970a9U, 0x8e8e8907U, 0x9494a733U, 0x9b9bb62dU, 0x1e1e223cU, 0x87879215U, 0xe9e920c9U, 0xcece4987U, 0x5555ffaaU, 0x28287850U, 0xdfdf7aa5U, 0x8c8c8f03U, 0xa1a1f859U, 0x89898009U, 0x0d0d171aU, 0xbfbfda65U, 0xe6e631d7U, 0x4242c684U, 0x6868b8d0U, 0x4141c382U, 0x9999b029U, 0x2d2d775aU, 0x0f0f111eU, 0xb0b0cb7bU, 0x5454fca8U, 0xbbbbd66dU, 0x16163a2cU, }; static const u32 Te4[256] = { 0x63636363U, 0x7c7c7c7cU, 0x77777777U, 0x7b7b7b7bU, 0xf2f2f2f2U, 0x6b6b6b6bU, 0x6f6f6f6fU, 0xc5c5c5c5U, 0x30303030U, 0x01010101U, 0x67676767U, 0x2b2b2b2bU, 0xfefefefeU, 0xd7d7d7d7U, 0xababababU, 0x76767676U, 0xcacacacaU, 0x82828282U, 0xc9c9c9c9U, 0x7d7d7d7dU, 0xfafafafaU, 0x59595959U, 0x47474747U, 0xf0f0f0f0U, 0xadadadadU, 0xd4d4d4d4U, 0xa2a2a2a2U, 0xafafafafU, 0x9c9c9c9cU, 0xa4a4a4a4U, 0x72727272U, 0xc0c0c0c0U, 0xb7b7b7b7U, 0xfdfdfdfdU, 0x93939393U, 0x26262626U, 0x36363636U, 0x3f3f3f3fU, 0xf7f7f7f7U, 0xccccccccU, 0x34343434U, 0xa5a5a5a5U, 0xe5e5e5e5U, 0xf1f1f1f1U, 0x71717171U, 0xd8d8d8d8U, 0x31313131U, 0x15151515U, 0x04040404U, 0xc7c7c7c7U, 0x23232323U, 0xc3c3c3c3U, 0x18181818U, 0x96969696U, 0x05050505U, 0x9a9a9a9aU, 0x07070707U, 0x12121212U, 0x80808080U, 0xe2e2e2e2U, 0xebebebebU, 0x27272727U, 0xb2b2b2b2U, 0x75757575U, 0x09090909U, 0x83838383U, 0x2c2c2c2cU, 0x1a1a1a1aU, 0x1b1b1b1bU, 0x6e6e6e6eU, 0x5a5a5a5aU, 0xa0a0a0a0U, 0x52525252U, 0x3b3b3b3bU, 0xd6d6d6d6U, 0xb3b3b3b3U, 0x29292929U, 0xe3e3e3e3U, 0x2f2f2f2fU, 0x84848484U, 0x53535353U, 0xd1d1d1d1U, 0x00000000U, 0xededededU, 0x20202020U, 0xfcfcfcfcU, 0xb1b1b1b1U, 0x5b5b5b5bU, 0x6a6a6a6aU, 0xcbcbcbcbU, 0xbebebebeU, 0x39393939U, 0x4a4a4a4aU, 0x4c4c4c4cU, 0x58585858U, 0xcfcfcfcfU, 0xd0d0d0d0U, 0xefefefefU, 0xaaaaaaaaU, 0xfbfbfbfbU, 0x43434343U, 0x4d4d4d4dU, 0x33333333U, 0x85858585U, 0x45454545U, 0xf9f9f9f9U, 0x02020202U, 0x7f7f7f7fU, 0x50505050U, 0x3c3c3c3cU, 0x9f9f9f9fU, 0xa8a8a8a8U, 0x51515151U, 0xa3a3a3a3U, 0x40404040U, 0x8f8f8f8fU, 0x92929292U, 0x9d9d9d9dU, 0x38383838U, 0xf5f5f5f5U, 0xbcbcbcbcU, 0xb6b6b6b6U, 0xdadadadaU, 0x21212121U, 0x10101010U, 0xffffffffU, 0xf3f3f3f3U, 0xd2d2d2d2U, 0xcdcdcdcdU, 0x0c0c0c0cU, 0x13131313U, 0xececececU, 0x5f5f5f5fU, 0x97979797U, 0x44444444U, 0x17171717U, 0xc4c4c4c4U, 0xa7a7a7a7U, 0x7e7e7e7eU, 0x3d3d3d3dU, 0x64646464U, 0x5d5d5d5dU, 0x19191919U, 0x73737373U, 0x60606060U, 0x81818181U, 0x4f4f4f4fU, 0xdcdcdcdcU, 0x22222222U, 0x2a2a2a2aU, 0x90909090U, 0x88888888U, 0x46464646U, 0xeeeeeeeeU, 0xb8b8b8b8U, 0x14141414U, 0xdedededeU, 0x5e5e5e5eU, 0x0b0b0b0bU, 0xdbdbdbdbU, 0xe0e0e0e0U, 0x32323232U, 0x3a3a3a3aU, 0x0a0a0a0aU, 0x49494949U, 0x06060606U, 0x24242424U, 0x5c5c5c5cU, 0xc2c2c2c2U, 0xd3d3d3d3U, 0xacacacacU, 0x62626262U, 0x91919191U, 0x95959595U, 0xe4e4e4e4U, 0x79797979U, 0xe7e7e7e7U, 0xc8c8c8c8U, 0x37373737U, 0x6d6d6d6dU, 0x8d8d8d8dU, 0xd5d5d5d5U, 0x4e4e4e4eU, 0xa9a9a9a9U, 0x6c6c6c6cU, 0x56565656U, 0xf4f4f4f4U, 0xeaeaeaeaU, 0x65656565U, 0x7a7a7a7aU, 0xaeaeaeaeU, 0x08080808U, 0xbabababaU, 0x78787878U, 0x25252525U, 0x2e2e2e2eU, 0x1c1c1c1cU, 0xa6a6a6a6U, 0xb4b4b4b4U, 0xc6c6c6c6U, 0xe8e8e8e8U, 0xddddddddU, 0x74747474U, 0x1f1f1f1fU, 0x4b4b4b4bU, 0xbdbdbdbdU, 0x8b8b8b8bU, 0x8a8a8a8aU, 0x70707070U, 0x3e3e3e3eU, 0xb5b5b5b5U, 0x66666666U, 0x48484848U, 0x03030303U, 0xf6f6f6f6U, 0x0e0e0e0eU, 0x61616161U, 0x35353535U, 0x57575757U, 0xb9b9b9b9U, 0x86868686U, 0xc1c1c1c1U, 0x1d1d1d1dU, 0x9e9e9e9eU, 0xe1e1e1e1U, 0xf8f8f8f8U, 0x98989898U, 0x11111111U, 0x69696969U, 0xd9d9d9d9U, 0x8e8e8e8eU, 0x94949494U, 0x9b9b9b9bU, 0x1e1e1e1eU, 0x87878787U, 0xe9e9e9e9U, 0xcecececeU, 0x55555555U, 0x28282828U, 0xdfdfdfdfU, 0x8c8c8c8cU, 0xa1a1a1a1U, 0x89898989U, 0x0d0d0d0dU, 0xbfbfbfbfU, 0xe6e6e6e6U, 0x42424242U, 0x68686868U, 0x41414141U, 0x99999999U, 0x2d2d2d2dU, 0x0f0f0f0fU, 0xb0b0b0b0U, 0x54545454U, 0xbbbbbbbbU, 0x16161616U, }; static const u32 Td0[256] = { 0x51f4a750U, 0x7e416553U, 0x1a17a4c3U, 0x3a275e96U, 0x3bab6bcbU, 0x1f9d45f1U, 0xacfa58abU, 0x4be30393U, 0x2030fa55U, 0xad766df6U, 0x88cc7691U, 0xf5024c25U, 0x4fe5d7fcU, 0xc52acbd7U, 0x26354480U, 0xb562a38fU, 0xdeb15a49U, 0x25ba1b67U, 0x45ea0e98U, 0x5dfec0e1U, 0xc32f7502U, 0x814cf012U, 0x8d4697a3U, 0x6bd3f9c6U, 0x038f5fe7U, 0x15929c95U, 0xbf6d7aebU, 0x955259daU, 0xd4be832dU, 0x587421d3U, 0x49e06929U, 0x8ec9c844U, 0x75c2896aU, 0xf48e7978U, 0x99583e6bU, 0x27b971ddU, 0xbee14fb6U, 0xf088ad17U, 0xc920ac66U, 0x7dce3ab4U, 0x63df4a18U, 0xe51a3182U, 0x97513360U, 0x62537f45U, 0xb16477e0U, 0xbb6bae84U, 0xfe81a01cU, 0xf9082b94U, 0x70486858U, 0x8f45fd19U, 0x94de6c87U, 0x527bf8b7U, 0xab73d323U, 0x724b02e2U, 0xe31f8f57U, 0x6655ab2aU, 0xb2eb2807U, 0x2fb5c203U, 0x86c57b9aU, 0xd33708a5U, 0x302887f2U, 0x23bfa5b2U, 0x02036abaU, 0xed16825cU, 0x8acf1c2bU, 0xa779b492U, 0xf307f2f0U, 0x4e69e2a1U, 0x65daf4cdU, 0x0605bed5U, 0xd134621fU, 0xc4a6fe8aU, 0x342e539dU, 0xa2f355a0U, 0x058ae132U, 0xa4f6eb75U, 0x0b83ec39U, 0x4060efaaU, 0x5e719f06U, 0xbd6e1051U, 0x3e218af9U, 0x96dd063dU, 0xdd3e05aeU, 0x4de6bd46U, 0x91548db5U, 0x71c45d05U, 0x0406d46fU, 0x605015ffU, 0x1998fb24U, 0xd6bde997U, 0x894043ccU, 0x67d99e77U, 0xb0e842bdU, 0x07898b88U, 0xe7195b38U, 0x79c8eedbU, 0xa17c0a47U, 0x7c420fe9U, 0xf8841ec9U, 0x00000000U, 0x09808683U, 0x322bed48U, 0x1e1170acU, 0x6c5a724eU, 0xfd0efffbU, 0x0f853856U, 0x3daed51eU, 0x362d3927U, 0x0a0fd964U, 0x685ca621U, 0x9b5b54d1U, 0x24362e3aU, 0x0c0a67b1U, 0x9357e70fU, 0xb4ee96d2U, 0x1b9b919eU, 0x80c0c54fU, 0x61dc20a2U, 0x5a774b69U, 0x1c121a16U, 0xe293ba0aU, 0xc0a02ae5U, 0x3c22e043U, 0x121b171dU, 0x0e090d0bU, 0xf28bc7adU, 0x2db6a8b9U, 0x141ea9c8U, 0x57f11985U, 0xaf75074cU, 0xee99ddbbU, 0xa37f60fdU, 0xf701269fU, 0x5c72f5bcU, 0x44663bc5U, 0x5bfb7e34U, 0x8b432976U, 0xcb23c6dcU, 0xb6edfc68U, 0xb8e4f163U, 0xd731dccaU, 0x42638510U, 0x13972240U, 0x84c61120U, 0x854a247dU, 0xd2bb3df8U, 0xaef93211U, 0xc729a16dU, 0x1d9e2f4bU, 0xdcb230f3U, 0x0d8652ecU, 0x77c1e3d0U, 0x2bb3166cU, 0xa970b999U, 0x119448faU, 0x47e96422U, 0xa8fc8cc4U, 0xa0f03f1aU, 0x567d2cd8U, 0x223390efU, 0x87494ec7U, 0xd938d1c1U, 0x8ccaa2feU, 0x98d40b36U, 0xa6f581cfU, 0xa57ade28U, 0xdab78e26U, 0x3fadbfa4U, 0x2c3a9de4U, 0x5078920dU, 0x6a5fcc9bU, 0x547e4662U, 0xf68d13c2U, 0x90d8b8e8U, 0x2e39f75eU, 0x82c3aff5U, 0x9f5d80beU, 0x69d0937cU, 0x6fd52da9U, 0xcf2512b3U, 0xc8ac993bU, 0x10187da7U, 0xe89c636eU, 0xdb3bbb7bU, 0xcd267809U, 0x6e5918f4U, 0xec9ab701U, 0x834f9aa8U, 0xe6956e65U, 0xaaffe67eU, 0x21bccf08U, 0xef15e8e6U, 0xbae79bd9U, 0x4a6f36ceU, 0xea9f09d4U, 0x29b07cd6U, 0x31a4b2afU, 0x2a3f2331U, 0xc6a59430U, 0x35a266c0U, 0x744ebc37U, 0xfc82caa6U, 0xe090d0b0U, 0x33a7d815U, 0xf104984aU, 0x41ecdaf7U, 0x7fcd500eU, 0x1791f62fU, 0x764dd68dU, 0x43efb04dU, 0xccaa4d54U, 0xe49604dfU, 0x9ed1b5e3U, 0x4c6a881bU, 0xc12c1fb8U, 0x4665517fU, 0x9d5eea04U, 0x018c355dU, 0xfa877473U, 0xfb0b412eU, 0xb3671d5aU, 0x92dbd252U, 0xe9105633U, 0x6dd64713U, 0x9ad7618cU, 0x37a10c7aU, 0x59f8148eU, 0xeb133c89U, 0xcea927eeU, 0xb761c935U, 0xe11ce5edU, 0x7a47b13cU, 0x9cd2df59U, 0x55f2733fU, 0x1814ce79U, 0x73c737bfU, 0x53f7cdeaU, 0x5ffdaa5bU, 0xdf3d6f14U, 0x7844db86U, 0xcaaff381U, 0xb968c43eU, 0x3824342cU, 0xc2a3405fU, 0x161dc372U, 0xbce2250cU, 0x283c498bU, 0xff0d9541U, 0x39a80171U, 0x080cb3deU, 0xd8b4e49cU, 0x6456c190U, 0x7bcb8461U, 0xd532b670U, 0x486c5c74U, 0xd0b85742U, }; static const u32 Td1[256] = { 0x5051f4a7U, 0x537e4165U, 0xc31a17a4U, 0x963a275eU, 0xcb3bab6bU, 0xf11f9d45U, 0xabacfa58U, 0x934be303U, 0x552030faU, 0xf6ad766dU, 0x9188cc76U, 0x25f5024cU, 0xfc4fe5d7U, 0xd7c52acbU, 0x80263544U, 0x8fb562a3U, 0x49deb15aU, 0x6725ba1bU, 0x9845ea0eU, 0xe15dfec0U, 0x02c32f75U, 0x12814cf0U, 0xa38d4697U, 0xc66bd3f9U, 0xe7038f5fU, 0x9515929cU, 0xebbf6d7aU, 0xda955259U, 0x2dd4be83U, 0xd3587421U, 0x2949e069U, 0x448ec9c8U, 0x6a75c289U, 0x78f48e79U, 0x6b99583eU, 0xdd27b971U, 0xb6bee14fU, 0x17f088adU, 0x66c920acU, 0xb47dce3aU, 0x1863df4aU, 0x82e51a31U, 0x60975133U, 0x4562537fU, 0xe0b16477U, 0x84bb6baeU, 0x1cfe81a0U, 0x94f9082bU, 0x58704868U, 0x198f45fdU, 0x8794de6cU, 0xb7527bf8U, 0x23ab73d3U, 0xe2724b02U, 0x57e31f8fU, 0x2a6655abU, 0x07b2eb28U, 0x032fb5c2U, 0x9a86c57bU, 0xa5d33708U, 0xf2302887U, 0xb223bfa5U, 0xba02036aU, 0x5ced1682U, 0x2b8acf1cU, 0x92a779b4U, 0xf0f307f2U, 0xa14e69e2U, 0xcd65daf4U, 0xd50605beU, 0x1fd13462U, 0x8ac4a6feU, 0x9d342e53U, 0xa0a2f355U, 0x32058ae1U, 0x75a4f6ebU, 0x390b83ecU, 0xaa4060efU, 0x065e719fU, 0x51bd6e10U, 0xf93e218aU, 0x3d96dd06U, 0xaedd3e05U, 0x464de6bdU, 0xb591548dU, 0x0571c45dU, 0x6f0406d4U, 0xff605015U, 0x241998fbU, 0x97d6bde9U, 0xcc894043U, 0x7767d99eU, 0xbdb0e842U, 0x8807898bU, 0x38e7195bU, 0xdb79c8eeU, 0x47a17c0aU, 0xe97c420fU, 0xc9f8841eU, 0x00000000U, 0x83098086U, 0x48322bedU, 0xac1e1170U, 0x4e6c5a72U, 0xfbfd0effU, 0x560f8538U, 0x1e3daed5U, 0x27362d39U, 0x640a0fd9U, 0x21685ca6U, 0xd19b5b54U, 0x3a24362eU, 0xb10c0a67U, 0x0f9357e7U, 0xd2b4ee96U, 0x9e1b9b91U, 0x4f80c0c5U, 0xa261dc20U, 0x695a774bU, 0x161c121aU, 0x0ae293baU, 0xe5c0a02aU, 0x433c22e0U, 0x1d121b17U, 0x0b0e090dU, 0xadf28bc7U, 0xb92db6a8U, 0xc8141ea9U, 0x8557f119U, 0x4caf7507U, 0xbbee99ddU, 0xfda37f60U, 0x9ff70126U, 0xbc5c72f5U, 0xc544663bU, 0x345bfb7eU, 0x768b4329U, 0xdccb23c6U, 0x68b6edfcU, 0x63b8e4f1U, 0xcad731dcU, 0x10426385U, 0x40139722U, 0x2084c611U, 0x7d854a24U, 0xf8d2bb3dU, 0x11aef932U, 0x6dc729a1U, 0x4b1d9e2fU, 0xf3dcb230U, 0xec0d8652U, 0xd077c1e3U, 0x6c2bb316U, 0x99a970b9U, 0xfa119448U, 0x2247e964U, 0xc4a8fc8cU, 0x1aa0f03fU, 0xd8567d2cU, 0xef223390U, 0xc787494eU, 0xc1d938d1U, 0xfe8ccaa2U, 0x3698d40bU, 0xcfa6f581U, 0x28a57adeU, 0x26dab78eU, 0xa43fadbfU, 0xe42c3a9dU, 0x0d507892U, 0x9b6a5fccU, 0x62547e46U, 0xc2f68d13U, 0xe890d8b8U, 0x5e2e39f7U, 0xf582c3afU, 0xbe9f5d80U, 0x7c69d093U, 0xa96fd52dU, 0xb3cf2512U, 0x3bc8ac99U, 0xa710187dU, 0x6ee89c63U, 0x7bdb3bbbU, 0x09cd2678U, 0xf46e5918U, 0x01ec9ab7U, 0xa8834f9aU, 0x65e6956eU, 0x7eaaffe6U, 0x0821bccfU, 0xe6ef15e8U, 0xd9bae79bU, 0xce4a6f36U, 0xd4ea9f09U, 0xd629b07cU, 0xaf31a4b2U, 0x312a3f23U, 0x30c6a594U, 0xc035a266U, 0x37744ebcU, 0xa6fc82caU, 0xb0e090d0U, 0x1533a7d8U, 0x4af10498U, 0xf741ecdaU, 0x0e7fcd50U, 0x2f1791f6U, 0x8d764dd6U, 0x4d43efb0U, 0x54ccaa4dU, 0xdfe49604U, 0xe39ed1b5U, 0x1b4c6a88U, 0xb8c12c1fU, 0x7f466551U, 0x049d5eeaU, 0x5d018c35U, 0x73fa8774U, 0x2efb0b41U, 0x5ab3671dU, 0x5292dbd2U, 0x33e91056U, 0x136dd647U, 0x8c9ad761U, 0x7a37a10cU, 0x8e59f814U, 0x89eb133cU, 0xeecea927U, 0x35b761c9U, 0xede11ce5U, 0x3c7a47b1U, 0x599cd2dfU, 0x3f55f273U, 0x791814ceU, 0xbf73c737U, 0xea53f7cdU, 0x5b5ffdaaU, 0x14df3d6fU, 0x867844dbU, 0x81caaff3U, 0x3eb968c4U, 0x2c382434U, 0x5fc2a340U, 0x72161dc3U, 0x0cbce225U, 0x8b283c49U, 0x41ff0d95U, 0x7139a801U, 0xde080cb3U, 0x9cd8b4e4U, 0x906456c1U, 0x617bcb84U, 0x70d532b6U, 0x74486c5cU, 0x42d0b857U, }; static const u32 Td2[256] = { 0xa75051f4U, 0x65537e41U, 0xa4c31a17U, 0x5e963a27U, 0x6bcb3babU, 0x45f11f9dU, 0x58abacfaU, 0x03934be3U, 0xfa552030U, 0x6df6ad76U, 0x769188ccU, 0x4c25f502U, 0xd7fc4fe5U, 0xcbd7c52aU, 0x44802635U, 0xa38fb562U, 0x5a49deb1U, 0x1b6725baU, 0x0e9845eaU, 0xc0e15dfeU, 0x7502c32fU, 0xf012814cU, 0x97a38d46U, 0xf9c66bd3U, 0x5fe7038fU, 0x9c951592U, 0x7aebbf6dU, 0x59da9552U, 0x832dd4beU, 0x21d35874U, 0x692949e0U, 0xc8448ec9U, 0x896a75c2U, 0x7978f48eU, 0x3e6b9958U, 0x71dd27b9U, 0x4fb6bee1U, 0xad17f088U, 0xac66c920U, 0x3ab47dceU, 0x4a1863dfU, 0x3182e51aU, 0x33609751U, 0x7f456253U, 0x77e0b164U, 0xae84bb6bU, 0xa01cfe81U, 0x2b94f908U, 0x68587048U, 0xfd198f45U, 0x6c8794deU, 0xf8b7527bU, 0xd323ab73U, 0x02e2724bU, 0x8f57e31fU, 0xab2a6655U, 0x2807b2ebU, 0xc2032fb5U, 0x7b9a86c5U, 0x08a5d337U, 0x87f23028U, 0xa5b223bfU, 0x6aba0203U, 0x825ced16U, 0x1c2b8acfU, 0xb492a779U, 0xf2f0f307U, 0xe2a14e69U, 0xf4cd65daU, 0xbed50605U, 0x621fd134U, 0xfe8ac4a6U, 0x539d342eU, 0x55a0a2f3U, 0xe132058aU, 0xeb75a4f6U, 0xec390b83U, 0xefaa4060U, 0x9f065e71U, 0x1051bd6eU, 0x8af93e21U, 0x063d96ddU, 0x05aedd3eU, 0xbd464de6U, 0x8db59154U, 0x5d0571c4U, 0xd46f0406U, 0x15ff6050U, 0xfb241998U, 0xe997d6bdU, 0x43cc8940U, 0x9e7767d9U, 0x42bdb0e8U, 0x8b880789U, 0x5b38e719U, 0xeedb79c8U, 0x0a47a17cU, 0x0fe97c42U, 0x1ec9f884U, 0x00000000U, 0x86830980U, 0xed48322bU, 0x70ac1e11U, 0x724e6c5aU, 0xfffbfd0eU, 0x38560f85U, 0xd51e3daeU, 0x3927362dU, 0xd9640a0fU, 0xa621685cU, 0x54d19b5bU, 0x2e3a2436U, 0x67b10c0aU, 0xe70f9357U, 0x96d2b4eeU, 0x919e1b9bU, 0xc54f80c0U, 0x20a261dcU, 0x4b695a77U, 0x1a161c12U, 0xba0ae293U, 0x2ae5c0a0U, 0xe0433c22U, 0x171d121bU, 0x0d0b0e09U, 0xc7adf28bU, 0xa8b92db6U, 0xa9c8141eU, 0x198557f1U, 0x074caf75U, 0xddbbee99U, 0x60fda37fU, 0x269ff701U, 0xf5bc5c72U, 0x3bc54466U, 0x7e345bfbU, 0x29768b43U, 0xc6dccb23U, 0xfc68b6edU, 0xf163b8e4U, 0xdccad731U, 0x85104263U, 0x22401397U, 0x112084c6U, 0x247d854aU, 0x3df8d2bbU, 0x3211aef9U, 0xa16dc729U, 0x2f4b1d9eU, 0x30f3dcb2U, 0x52ec0d86U, 0xe3d077c1U, 0x166c2bb3U, 0xb999a970U, 0x48fa1194U, 0x642247e9U, 0x8cc4a8fcU, 0x3f1aa0f0U, 0x2cd8567dU, 0x90ef2233U, 0x4ec78749U, 0xd1c1d938U, 0xa2fe8ccaU, 0x0b3698d4U, 0x81cfa6f5U, 0xde28a57aU, 0x8e26dab7U, 0xbfa43fadU, 0x9de42c3aU, 0x920d5078U, 0xcc9b6a5fU, 0x4662547eU, 0x13c2f68dU, 0xb8e890d8U, 0xf75e2e39U, 0xaff582c3U, 0x80be9f5dU, 0x937c69d0U, 0x2da96fd5U, 0x12b3cf25U, 0x993bc8acU, 0x7da71018U, 0x636ee89cU, 0xbb7bdb3bU, 0x7809cd26U, 0x18f46e59U, 0xb701ec9aU, 0x9aa8834fU, 0x6e65e695U, 0xe67eaaffU, 0xcf0821bcU, 0xe8e6ef15U, 0x9bd9bae7U, 0x36ce4a6fU, 0x09d4ea9fU, 0x7cd629b0U, 0xb2af31a4U, 0x23312a3fU, 0x9430c6a5U, 0x66c035a2U, 0xbc37744eU, 0xcaa6fc82U, 0xd0b0e090U, 0xd81533a7U, 0x984af104U, 0xdaf741ecU, 0x500e7fcdU, 0xf62f1791U, 0xd68d764dU, 0xb04d43efU, 0x4d54ccaaU, 0x04dfe496U, 0xb5e39ed1U, 0x881b4c6aU, 0x1fb8c12cU, 0x517f4665U, 0xea049d5eU, 0x355d018cU, 0x7473fa87U, 0x412efb0bU, 0x1d5ab367U, 0xd25292dbU, 0x5633e910U, 0x47136dd6U, 0x618c9ad7U, 0x0c7a37a1U, 0x148e59f8U, 0x3c89eb13U, 0x27eecea9U, 0xc935b761U, 0xe5ede11cU, 0xb13c7a47U, 0xdf599cd2U, 0x733f55f2U, 0xce791814U, 0x37bf73c7U, 0xcdea53f7U, 0xaa5b5ffdU, 0x6f14df3dU, 0xdb867844U, 0xf381caafU, 0xc43eb968U, 0x342c3824U, 0x405fc2a3U, 0xc372161dU, 0x250cbce2U, 0x498b283cU, 0x9541ff0dU, 0x017139a8U, 0xb3de080cU, 0xe49cd8b4U, 0xc1906456U, 0x84617bcbU, 0xb670d532U, 0x5c74486cU, 0x5742d0b8U, }; static const u32 Td3[256] = { 0xf4a75051U, 0x4165537eU, 0x17a4c31aU, 0x275e963aU, 0xab6bcb3bU, 0x9d45f11fU, 0xfa58abacU, 0xe303934bU, 0x30fa5520U, 0x766df6adU, 0xcc769188U, 0x024c25f5U, 0xe5d7fc4fU, 0x2acbd7c5U, 0x35448026U, 0x62a38fb5U, 0xb15a49deU, 0xba1b6725U, 0xea0e9845U, 0xfec0e15dU, 0x2f7502c3U, 0x4cf01281U, 0x4697a38dU, 0xd3f9c66bU, 0x8f5fe703U, 0x929c9515U, 0x6d7aebbfU, 0x5259da95U, 0xbe832dd4U, 0x7421d358U, 0xe0692949U, 0xc9c8448eU, 0xc2896a75U, 0x8e7978f4U, 0x583e6b99U, 0xb971dd27U, 0xe14fb6beU, 0x88ad17f0U, 0x20ac66c9U, 0xce3ab47dU, 0xdf4a1863U, 0x1a3182e5U, 0x51336097U, 0x537f4562U, 0x6477e0b1U, 0x6bae84bbU, 0x81a01cfeU, 0x082b94f9U, 0x48685870U, 0x45fd198fU, 0xde6c8794U, 0x7bf8b752U, 0x73d323abU, 0x4b02e272U, 0x1f8f57e3U, 0x55ab2a66U, 0xeb2807b2U, 0xb5c2032fU, 0xc57b9a86U, 0x3708a5d3U, 0x2887f230U, 0xbfa5b223U, 0x036aba02U, 0x16825cedU, 0xcf1c2b8aU, 0x79b492a7U, 0x07f2f0f3U, 0x69e2a14eU, 0xdaf4cd65U, 0x05bed506U, 0x34621fd1U, 0xa6fe8ac4U, 0x2e539d34U, 0xf355a0a2U, 0x8ae13205U, 0xf6eb75a4U, 0x83ec390bU, 0x60efaa40U, 0x719f065eU, 0x6e1051bdU, 0x218af93eU, 0xdd063d96U, 0x3e05aeddU, 0xe6bd464dU, 0x548db591U, 0xc45d0571U, 0x06d46f04U, 0x5015ff60U, 0x98fb2419U, 0xbde997d6U, 0x4043cc89U, 0xd99e7767U, 0xe842bdb0U, 0x898b8807U, 0x195b38e7U, 0xc8eedb79U, 0x7c0a47a1U, 0x420fe97cU, 0x841ec9f8U, 0x00000000U, 0x80868309U, 0x2bed4832U, 0x1170ac1eU, 0x5a724e6cU, 0x0efffbfdU, 0x8538560fU, 0xaed51e3dU, 0x2d392736U, 0x0fd9640aU, 0x5ca62168U, 0x5b54d19bU, 0x362e3a24U, 0x0a67b10cU, 0x57e70f93U, 0xee96d2b4U, 0x9b919e1bU, 0xc0c54f80U, 0xdc20a261U, 0x774b695aU, 0x121a161cU, 0x93ba0ae2U, 0xa02ae5c0U, 0x22e0433cU, 0x1b171d12U, 0x090d0b0eU, 0x8bc7adf2U, 0xb6a8b92dU, 0x1ea9c814U, 0xf1198557U, 0x75074cafU, 0x99ddbbeeU, 0x7f60fda3U, 0x01269ff7U, 0x72f5bc5cU, 0x663bc544U, 0xfb7e345bU, 0x4329768bU, 0x23c6dccbU, 0xedfc68b6U, 0xe4f163b8U, 0x31dccad7U, 0x63851042U, 0x97224013U, 0xc6112084U, 0x4a247d85U, 0xbb3df8d2U, 0xf93211aeU, 0x29a16dc7U, 0x9e2f4b1dU, 0xb230f3dcU, 0x8652ec0dU, 0xc1e3d077U, 0xb3166c2bU, 0x70b999a9U, 0x9448fa11U, 0xe9642247U, 0xfc8cc4a8U, 0xf03f1aa0U, 0x7d2cd856U, 0x3390ef22U, 0x494ec787U, 0x38d1c1d9U, 0xcaa2fe8cU, 0xd40b3698U, 0xf581cfa6U, 0x7ade28a5U, 0xb78e26daU, 0xadbfa43fU, 0x3a9de42cU, 0x78920d50U, 0x5fcc9b6aU, 0x7e466254U, 0x8d13c2f6U, 0xd8b8e890U, 0x39f75e2eU, 0xc3aff582U, 0x5d80be9fU, 0xd0937c69U, 0xd52da96fU, 0x2512b3cfU, 0xac993bc8U, 0x187da710U, 0x9c636ee8U, 0x3bbb7bdbU, 0x267809cdU, 0x5918f46eU, 0x9ab701ecU, 0x4f9aa883U, 0x956e65e6U, 0xffe67eaaU, 0xbccf0821U, 0x15e8e6efU, 0xe79bd9baU, 0x6f36ce4aU, 0x9f09d4eaU, 0xb07cd629U, 0xa4b2af31U, 0x3f23312aU, 0xa59430c6U, 0xa266c035U, 0x4ebc3774U, 0x82caa6fcU, 0x90d0b0e0U, 0xa7d81533U, 0x04984af1U, 0xecdaf741U, 0xcd500e7fU, 0x91f62f17U, 0x4dd68d76U, 0xefb04d43U, 0xaa4d54ccU, 0x9604dfe4U, 0xd1b5e39eU, 0x6a881b4cU, 0x2c1fb8c1U, 0x65517f46U, 0x5eea049dU, 0x8c355d01U, 0x877473faU, 0x0b412efbU, 0x671d5ab3U, 0xdbd25292U, 0x105633e9U, 0xd647136dU, 0xd7618c9aU, 0xa10c7a37U, 0xf8148e59U, 0x133c89ebU, 0xa927eeceU, 0x61c935b7U, 0x1ce5ede1U, 0x47b13c7aU, 0xd2df599cU, 0xf2733f55U, 0x14ce7918U, 0xc737bf73U, 0xf7cdea53U, 0xfdaa5b5fU, 0x3d6f14dfU, 0x44db8678U, 0xaff381caU, 0x68c43eb9U, 0x24342c38U, 0xa3405fc2U, 0x1dc37216U, 0xe2250cbcU, 0x3c498b28U, 0x0d9541ffU, 0xa8017139U, 0x0cb3de08U, 0xb4e49cd8U, 0x56c19064U, 0xcb84617bU, 0x32b670d5U, 0x6c5c7448U, 0xb85742d0U, }; static const u32 Td4[256] = { 0x52525252U, 0x09090909U, 0x6a6a6a6aU, 0xd5d5d5d5U, 0x30303030U, 0x36363636U, 0xa5a5a5a5U, 0x38383838U, 0xbfbfbfbfU, 0x40404040U, 0xa3a3a3a3U, 0x9e9e9e9eU, 0x81818181U, 0xf3f3f3f3U, 0xd7d7d7d7U, 0xfbfbfbfbU, 0x7c7c7c7cU, 0xe3e3e3e3U, 0x39393939U, 0x82828282U, 0x9b9b9b9bU, 0x2f2f2f2fU, 0xffffffffU, 0x87878787U, 0x34343434U, 0x8e8e8e8eU, 0x43434343U, 0x44444444U, 0xc4c4c4c4U, 0xdedededeU, 0xe9e9e9e9U, 0xcbcbcbcbU, 0x54545454U, 0x7b7b7b7bU, 0x94949494U, 0x32323232U, 0xa6a6a6a6U, 0xc2c2c2c2U, 0x23232323U, 0x3d3d3d3dU, 0xeeeeeeeeU, 0x4c4c4c4cU, 0x95959595U, 0x0b0b0b0bU, 0x42424242U, 0xfafafafaU, 0xc3c3c3c3U, 0x4e4e4e4eU, 0x08080808U, 0x2e2e2e2eU, 0xa1a1a1a1U, 0x66666666U, 0x28282828U, 0xd9d9d9d9U, 0x24242424U, 0xb2b2b2b2U, 0x76767676U, 0x5b5b5b5bU, 0xa2a2a2a2U, 0x49494949U, 0x6d6d6d6dU, 0x8b8b8b8bU, 0xd1d1d1d1U, 0x25252525U, 0x72727272U, 0xf8f8f8f8U, 0xf6f6f6f6U, 0x64646464U, 0x86868686U, 0x68686868U, 0x98989898U, 0x16161616U, 0xd4d4d4d4U, 0xa4a4a4a4U, 0x5c5c5c5cU, 0xccccccccU, 0x5d5d5d5dU, 0x65656565U, 0xb6b6b6b6U, 0x92929292U, 0x6c6c6c6cU, 0x70707070U, 0x48484848U, 0x50505050U, 0xfdfdfdfdU, 0xededededU, 0xb9b9b9b9U, 0xdadadadaU, 0x5e5e5e5eU, 0x15151515U, 0x46464646U, 0x57575757U, 0xa7a7a7a7U, 0x8d8d8d8dU, 0x9d9d9d9dU, 0x84848484U, 0x90909090U, 0xd8d8d8d8U, 0xababababU, 0x00000000U, 0x8c8c8c8cU, 0xbcbcbcbcU, 0xd3d3d3d3U, 0x0a0a0a0aU, 0xf7f7f7f7U, 0xe4e4e4e4U, 0x58585858U, 0x05050505U, 0xb8b8b8b8U, 0xb3b3b3b3U, 0x45454545U, 0x06060606U, 0xd0d0d0d0U, 0x2c2c2c2cU, 0x1e1e1e1eU, 0x8f8f8f8fU, 0xcacacacaU, 0x3f3f3f3fU, 0x0f0f0f0fU, 0x02020202U, 0xc1c1c1c1U, 0xafafafafU, 0xbdbdbdbdU, 0x03030303U, 0x01010101U, 0x13131313U, 0x8a8a8a8aU, 0x6b6b6b6bU, 0x3a3a3a3aU, 0x91919191U, 0x11111111U, 0x41414141U, 0x4f4f4f4fU, 0x67676767U, 0xdcdcdcdcU, 0xeaeaeaeaU, 0x97979797U, 0xf2f2f2f2U, 0xcfcfcfcfU, 0xcecececeU, 0xf0f0f0f0U, 0xb4b4b4b4U, 0xe6e6e6e6U, 0x73737373U, 0x96969696U, 0xacacacacU, 0x74747474U, 0x22222222U, 0xe7e7e7e7U, 0xadadadadU, 0x35353535U, 0x85858585U, 0xe2e2e2e2U, 0xf9f9f9f9U, 0x37373737U, 0xe8e8e8e8U, 0x1c1c1c1cU, 0x75757575U, 0xdfdfdfdfU, 0x6e6e6e6eU, 0x47474747U, 0xf1f1f1f1U, 0x1a1a1a1aU, 0x71717171U, 0x1d1d1d1dU, 0x29292929U, 0xc5c5c5c5U, 0x89898989U, 0x6f6f6f6fU, 0xb7b7b7b7U, 0x62626262U, 0x0e0e0e0eU, 0xaaaaaaaaU, 0x18181818U, 0xbebebebeU, 0x1b1b1b1bU, 0xfcfcfcfcU, 0x56565656U, 0x3e3e3e3eU, 0x4b4b4b4bU, 0xc6c6c6c6U, 0xd2d2d2d2U, 0x79797979U, 0x20202020U, 0x9a9a9a9aU, 0xdbdbdbdbU, 0xc0c0c0c0U, 0xfefefefeU, 0x78787878U, 0xcdcdcdcdU, 0x5a5a5a5aU, 0xf4f4f4f4U, 0x1f1f1f1fU, 0xddddddddU, 0xa8a8a8a8U, 0x33333333U, 0x88888888U, 0x07070707U, 0xc7c7c7c7U, 0x31313131U, 0xb1b1b1b1U, 0x12121212U, 0x10101010U, 0x59595959U, 0x27272727U, 0x80808080U, 0xececececU, 0x5f5f5f5fU, 0x60606060U, 0x51515151U, 0x7f7f7f7fU, 0xa9a9a9a9U, 0x19191919U, 0xb5b5b5b5U, 0x4a4a4a4aU, 0x0d0d0d0dU, 0x2d2d2d2dU, 0xe5e5e5e5U, 0x7a7a7a7aU, 0x9f9f9f9fU, 0x93939393U, 0xc9c9c9c9U, 0x9c9c9c9cU, 0xefefefefU, 0xa0a0a0a0U, 0xe0e0e0e0U, 0x3b3b3b3bU, 0x4d4d4d4dU, 0xaeaeaeaeU, 0x2a2a2a2aU, 0xf5f5f5f5U, 0xb0b0b0b0U, 0xc8c8c8c8U, 0xebebebebU, 0xbbbbbbbbU, 0x3c3c3c3cU, 0x83838383U, 0x53535353U, 0x99999999U, 0x61616161U, 0x17171717U, 0x2b2b2b2bU, 0x04040404U, 0x7e7e7e7eU, 0xbabababaU, 0x77777777U, 0xd6d6d6d6U, 0x26262626U, 0xe1e1e1e1U, 0x69696969U, 0x14141414U, 0x63636363U, 0x55555555U, 0x21212121U, 0x0c0c0c0cU, 0x7d7d7d7dU, }; static const u32 rcon[] = { 0x01000000, 0x02000000, 0x04000000, 0x08000000, 0x10000000, 0x20000000, 0x40000000, 0x80000000, 0x1B000000, 0x36000000, /* for 128-bit blocks, Rijndael never uses more than 10 rcon values */ }; #define SWAP(x) (_lrotl(x, 8) & 0x00ff00ff | _lrotr(x, 8) & 0xff00ff00) #ifdef _MSC_VER #define GETU32(p) SWAP(*((u32 *)(p))) #define PUTU32(ct, st) { *((u32 *)(ct)) = SWAP((st)); } #else #define GETU32(pt) (((u32)(pt)[0] << 24) ^ ((u32)(pt)[1] << 16) ^ ((u32)(pt)[2] << 8) ^ ((u32)(pt)[3])) #define PUTU32(ct, st) { (ct)[0] = (u8)((st) >> 24); (ct)[1] = (u8)((st) >> 16); (ct)[2] = (u8)((st) >> 8); (ct)[3] = (u8)(st); } #endif /** * Expand the cipher key into the encryption key schedule. * * @return the number of rounds for the given cipher key size. */ int rijndaelKeySetupEnc(u32 rk[/*4*(Nr + 1)*/], const u8 cipherKey[], int keyBits) { int i = 0; u32 temp; rk[0] = GETU32(cipherKey ); rk[1] = GETU32(cipherKey + 4); rk[2] = GETU32(cipherKey + 8); rk[3] = GETU32(cipherKey + 12); if (keyBits == 128) { for (;;) { temp = rk[3]; rk[4] = rk[0] ^ (Te4[(temp >> 16) & 0xff] & 0xff000000) ^ (Te4[(temp >> 8) & 0xff] & 0x00ff0000) ^ (Te4[(temp ) & 0xff] & 0x0000ff00) ^ (Te4[(temp >> 24) ] & 0x000000ff) ^ rcon[i]; rk[5] = rk[1] ^ rk[4]; rk[6] = rk[2] ^ rk[5]; rk[7] = rk[3] ^ rk[6]; if (++i == 10) { return 10; } rk += 4; } } rk[4] = GETU32(cipherKey + 16); rk[5] = GETU32(cipherKey + 20); if (keyBits == 192) { for (;;) { temp = rk[ 5]; rk[ 6] = rk[ 0] ^ (Te4[(temp >> 16) & 0xff] & 0xff000000) ^ (Te4[(temp >> 8) & 0xff] & 0x00ff0000) ^ (Te4[(temp ) & 0xff] & 0x0000ff00) ^ (Te4[(temp >> 24) ] & 0x000000ff) ^ rcon[i]; rk[ 7] = rk[ 1] ^ rk[ 6]; rk[ 8] = rk[ 2] ^ rk[ 7]; rk[ 9] = rk[ 3] ^ rk[ 8]; if (++i == 8) { return 12; } rk[10] = rk[ 4] ^ rk[ 9]; rk[11] = rk[ 5] ^ rk[10]; rk += 6; } } rk[6] = GETU32(cipherKey + 24); rk[7] = GETU32(cipherKey + 28); if (keyBits == 256) { for (;;) { temp = rk[ 7]; rk[ 8] = rk[ 0] ^ (Te4[(temp >> 16) & 0xff] & 0xff000000) ^ (Te4[(temp >> 8) & 0xff] & 0x00ff0000) ^ (Te4[(temp ) & 0xff] & 0x0000ff00) ^ (Te4[(temp >> 24) ] & 0x000000ff) ^ rcon[i]; rk[ 9] = rk[ 1] ^ rk[ 8]; rk[10] = rk[ 2] ^ rk[ 9]; rk[11] = rk[ 3] ^ rk[10]; if (++i == 7) { return 14; } temp = rk[11]; rk[12] = rk[ 4] ^ (Te4[(temp >> 24) ] & 0xff000000) ^ (Te4[(temp >> 16) & 0xff] & 0x00ff0000) ^ (Te4[(temp >> 8) & 0xff] & 0x0000ff00) ^ (Te4[(temp ) & 0xff] & 0x000000ff); rk[13] = rk[ 5] ^ rk[12]; rk[14] = rk[ 6] ^ rk[13]; rk[15] = rk[ 7] ^ rk[14]; rk += 8; } } return 0; } /** * Expand the cipher key into the decryption key schedule. * * @return the number of rounds for the given cipher key size. */ int rijndaelKeySetupDec(u32 rk[/*4*(Nr + 1)*/], const u8 cipherKey[], int keyBits) { int Nr, i, j; u32 temp; /* expand the cipher key: */ Nr = rijndaelKeySetupEnc(rk, cipherKey, keyBits); /* invert the order of the round keys: */ for (i = 0, j = 4*Nr; i < j; i += 4, j -= 4) { temp = rk[i ]; rk[i ] = rk[j ]; rk[j ] = temp; temp = rk[i + 1]; rk[i + 1] = rk[j + 1]; rk[j + 1] = temp; temp = rk[i + 2]; rk[i + 2] = rk[j + 2]; rk[j + 2] = temp; temp = rk[i + 3]; rk[i + 3] = rk[j + 3]; rk[j + 3] = temp; } /* apply the inverse MixColumn transform to all round keys but the first and the last: */ for (i = 1; i < Nr; i++) { rk += 4; rk[0] = Td0[Te4[(rk[0] >> 24) ] & 0xff] ^ Td1[Te4[(rk[0] >> 16) & 0xff] & 0xff] ^ Td2[Te4[(rk[0] >> 8) & 0xff] & 0xff] ^ Td3[Te4[(rk[0] ) & 0xff] & 0xff]; rk[1] = Td0[Te4[(rk[1] >> 24) ] & 0xff] ^ Td1[Te4[(rk[1] >> 16) & 0xff] & 0xff] ^ Td2[Te4[(rk[1] >> 8) & 0xff] & 0xff] ^ Td3[Te4[(rk[1] ) & 0xff] & 0xff]; rk[2] = Td0[Te4[(rk[2] >> 24) ] & 0xff] ^ Td1[Te4[(rk[2] >> 16) & 0xff] & 0xff] ^ Td2[Te4[(rk[2] >> 8) & 0xff] & 0xff] ^ Td3[Te4[(rk[2] ) & 0xff] & 0xff]; rk[3] = Td0[Te4[(rk[3] >> 24) ] & 0xff] ^ Td1[Te4[(rk[3] >> 16) & 0xff] & 0xff] ^ Td2[Te4[(rk[3] >> 8) & 0xff] & 0xff] ^ Td3[Te4[(rk[3] ) & 0xff] & 0xff]; } return Nr; } void rijndaelEncrypt(const u32 rk[/*4*(Nr + 1)*/], int Nr, const u8 pt[16], u8 ct[16]) { u32 s0, s1, s2, s3, t0, t1, t2, t3; #ifndef FULL_UNROLL int r; #endif /* ?FULL_UNROLL */ /* * map byte array block to cipher state * and add initial round key: */ s0 = GETU32(pt ) ^ rk[0]; s1 = GETU32(pt + 4) ^ rk[1]; s2 = GETU32(pt + 8) ^ rk[2]; s3 = GETU32(pt + 12) ^ rk[3]; #ifdef FULL_UNROLL /* round 1: */ t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[ 4]; t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[ 5]; t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[ 6]; t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[ 7]; /* round 2: */ s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[ 8]; s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[ 9]; s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[10]; s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[11]; /* round 3: */ t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[12]; t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[13]; t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[14]; t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[15]; /* round 4: */ s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[16]; s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[17]; s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[18]; s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[19]; /* round 5: */ t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[20]; t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[21]; t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[22]; t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[23]; /* round 6: */ s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[24]; s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[25]; s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[26]; s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[27]; /* round 7: */ t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[28]; t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[29]; t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[30]; t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[31]; /* round 8: */ s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[32]; s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[33]; s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[34]; s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[35]; /* round 9: */ t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[36]; t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[37]; t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[38]; t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[39]; if (Nr > 10) { /* round 10: */ s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[40]; s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[41]; s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[42]; s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[43]; /* round 11: */ t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[44]; t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[45]; t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[46]; t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[47]; if (Nr > 12) { /* round 12: */ s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[48]; s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[49]; s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[50]; s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[51]; /* round 13: */ t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[52]; t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[53]; t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[54]; t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[55]; } } rk += Nr << 2; #else /* !FULL_UNROLL */ /* * Nr - 1 full rounds: */ r = Nr >> 1; for (;;) { t0 = Te0[(s0 >> 24) ] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[(s3 ) & 0xff] ^ rk[4]; t1 = Te0[(s1 >> 24) ] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[(s0 ) & 0xff] ^ rk[5]; t2 = Te0[(s2 >> 24) ] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[(s1 ) & 0xff] ^ rk[6]; t3 = Te0[(s3 >> 24) ] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[(s2 ) & 0xff] ^ rk[7]; rk += 8; if (--r == 0) { break; } s0 = Te0[(t0 >> 24) ] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[(t3 ) & 0xff] ^ rk[0]; s1 = Te0[(t1 >> 24) ] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[(t0 ) & 0xff] ^ rk[1]; s2 = Te0[(t2 >> 24) ] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[(t1 ) & 0xff] ^ rk[2]; s3 = Te0[(t3 >> 24) ] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[(t2 ) & 0xff] ^ rk[3]; } #endif /* ?FULL_UNROLL */ /* * apply last round and * map cipher state to byte array block: */ s0 = (Te4[(t0 >> 24) ] & 0xff000000) ^ (Te4[(t1 >> 16) & 0xff] & 0x00ff0000) ^ (Te4[(t2 >> 8) & 0xff] & 0x0000ff00) ^ (Te4[(t3 ) & 0xff] & 0x000000ff) ^ rk[0]; PUTU32(ct , s0); s1 = (Te4[(t1 >> 24) ] & 0xff000000) ^ (Te4[(t2 >> 16) & 0xff] & 0x00ff0000) ^ (Te4[(t3 >> 8) & 0xff] & 0x0000ff00) ^ (Te4[(t0 ) & 0xff] & 0x000000ff) ^ rk[1]; PUTU32(ct + 4, s1); s2 = (Te4[(t2 >> 24) ] & 0xff000000) ^ (Te4[(t3 >> 16) & 0xff] & 0x00ff0000) ^ (Te4[(t0 >> 8) & 0xff] & 0x0000ff00) ^ (Te4[(t1 ) & 0xff] & 0x000000ff) ^ rk[2]; PUTU32(ct + 8, s2); s3 = (Te4[(t3 >> 24) ] & 0xff000000) ^ (Te4[(t0 >> 16) & 0xff] & 0x00ff0000) ^ (Te4[(t1 >> 8) & 0xff] & 0x0000ff00) ^ (Te4[(t2 ) & 0xff] & 0x000000ff) ^ rk[3]; PUTU32(ct + 12, s3); } void rijndaelDecrypt(const u32 rk[/*4*(Nr + 1)*/], int Nr, const u8 ct[16], u8 pt[16]) { u32 s0, s1, s2, s3, t0, t1, t2, t3; #ifndef FULL_UNROLL int r; #endif /* ?FULL_UNROLL */ /* * map byte array block to cipher state * and add initial round key: */ s0 = GETU32(ct ) ^ rk[0]; s1 = GETU32(ct + 4) ^ rk[1]; s2 = GETU32(ct + 8) ^ rk[2]; s3 = GETU32(ct + 12) ^ rk[3]; #ifdef FULL_UNROLL /* round 1: */ t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >> 8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[ 4]; t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >> 8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[ 5]; t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >> 8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[ 6]; t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >> 8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[ 7]; /* round 2: */ s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >> 8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[ 8]; s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >> 8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[ 9]; s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >> 8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[10]; s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >> 8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[11]; /* round 3: */ t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >> 8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[12]; t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >> 8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[13]; t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >> 8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[14]; t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >> 8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[15]; /* round 4: */ s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >> 8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[16]; s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >> 8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[17]; s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >> 8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[18]; s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >> 8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[19]; /* round 5: */ t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >> 8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[20]; t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >> 8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[21]; t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >> 8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[22]; t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >> 8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[23]; /* round 6: */ s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >> 8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[24]; s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >> 8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[25]; s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >> 8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[26]; s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >> 8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[27]; /* round 7: */ t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >> 8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[28]; t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >> 8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[29]; t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >> 8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[30]; t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >> 8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[31]; /* round 8: */ s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >> 8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[32]; s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >> 8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[33]; s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >> 8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[34]; s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >> 8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[35]; /* round 9: */ t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >> 8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[36]; t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >> 8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[37]; t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >> 8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[38]; t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >> 8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[39]; if (Nr > 10) { /* round 10: */ s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >> 8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[40]; s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >> 8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[41]; s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >> 8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[42]; s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >> 8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[43]; /* round 11: */ t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >> 8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[44]; t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >> 8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[45]; t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >> 8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[46]; t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >> 8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[47]; if (Nr > 12) { /* round 12: */ s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >> 8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[48]; s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >> 8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[49]; s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >> 8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[50]; s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >> 8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[51]; /* round 13: */ t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >> 8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[52]; t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >> 8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[53]; t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >> 8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[54]; t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >> 8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[55]; } } rk += Nr << 2; #else /* !FULL_UNROLL */ /* * Nr - 1 full rounds: */ r = Nr >> 1; for (;;) { t0 = Td0[(s0 >> 24) ] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >> 8) & 0xff] ^ Td3[(s1 ) & 0xff] ^ rk[4]; t1 = Td0[(s1 >> 24) ] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >> 8) & 0xff] ^ Td3[(s2 ) & 0xff] ^ rk[5]; t2 = Td0[(s2 >> 24) ] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >> 8) & 0xff] ^ Td3[(s3 ) & 0xff] ^ rk[6]; t3 = Td0[(s3 >> 24) ] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >> 8) & 0xff] ^ Td3[(s0 ) & 0xff] ^ rk[7]; rk += 8; if (--r == 0) { break; } s0 = Td0[(t0 >> 24) ] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >> 8) & 0xff] ^ Td3[(t1 ) & 0xff] ^ rk[0]; s1 = Td0[(t1 >> 24) ] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >> 8) & 0xff] ^ Td3[(t2 ) & 0xff] ^ rk[1]; s2 = Td0[(t2 >> 24) ] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >> 8) & 0xff] ^ Td3[(t3 ) & 0xff] ^ rk[2]; s3 = Td0[(t3 >> 24) ] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >> 8) & 0xff] ^ Td3[(t0 ) & 0xff] ^ rk[3]; } #endif /* ?FULL_UNROLL */ /* * apply last round and * map cipher state to byte array block: */ s0 = (Td4[(t0 >> 24) ] & 0xff000000) ^ (Td4[(t3 >> 16) & 0xff] & 0x00ff0000) ^ (Td4[(t2 >> 8) & 0xff] & 0x0000ff00) ^ (Td4[(t1 ) & 0xff] & 0x000000ff) ^ rk[0]; PUTU32(pt , s0); s1 = (Td4[(t1 >> 24) ] & 0xff000000) ^ (Td4[(t0 >> 16) & 0xff] & 0x00ff0000) ^ (Td4[(t3 >> 8) & 0xff] & 0x0000ff00) ^ (Td4[(t2 ) & 0xff] & 0x000000ff) ^ rk[1]; PUTU32(pt + 4, s1); s2 = (Td4[(t2 >> 24) ] & 0xff000000) ^ (Td4[(t1 >> 16) & 0xff] & 0x00ff0000) ^ (Td4[(t0 >> 8) & 0xff] & 0x0000ff00) ^ (Td4[(t3 ) & 0xff] & 0x000000ff) ^ rk[2]; PUTU32(pt + 8, s2); s3 = (Td4[(t3 >> 24) ] & 0xff000000) ^ (Td4[(t2 >> 16) & 0xff] & 0x00ff0000) ^ (Td4[(t1 >> 8) & 0xff] & 0x0000ff00) ^ (Td4[(t0 ) & 0xff] & 0x000000ff) ^ rk[3]; PUTU32(pt + 12, s3); } #ifdef INTERMEDIATE_VALUE_KAT void rijndaelEncryptRound(const u32 rk[/*4*(Nr + 1)*/], int Nr, u8 block[16], int rounds) { int r; u32 s0, s1, s2, s3, t0, t1, t2, t3; /* * map byte array block to cipher state * and add initial round key: */ s0 = GETU32(block ) ^ rk[0]; s1 = GETU32(block + 4) ^ rk[1]; s2 = GETU32(block + 8) ^ rk[2]; s3 = GETU32(block + 12) ^ rk[3]; rk += 4; /* * Nr - 1 full rounds: */ for (r = (rounds < Nr ? rounds : Nr - 1); r > 0; r--) { t0 = Te0[(s0 >> 24) ] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[(s3 ) & 0xff] ^ rk[0]; t1 = Te0[(s1 >> 24) ] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[(s0 ) & 0xff] ^ rk[1]; t2 = Te0[(s2 >> 24) ] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[(s1 ) & 0xff] ^ rk[2]; t3 = Te0[(s3 >> 24) ] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[(s2 ) & 0xff] ^ rk[3]; s0 = t0; s1 = t1; s2 = t2; s3 = t3; rk += 4; } /* * apply last round and * map cipher state to byte array block: */ if (rounds == Nr) { t0 = (Te4[(s0 >> 24) ] & 0xff000000) ^ (Te4[(s1 >> 16) & 0xff] & 0x00ff0000) ^ (Te4[(s2 >> 8) & 0xff] & 0x0000ff00) ^ (Te4[(s3 ) & 0xff] & 0x000000ff) ^ rk[0]; t1 = (Te4[(s1 >> 24) ] & 0xff000000) ^ (Te4[(s2 >> 16) & 0xff] & 0x00ff0000) ^ (Te4[(s3 >> 8) & 0xff] & 0x0000ff00) ^ (Te4[(s0 ) & 0xff] & 0x000000ff) ^ rk[1]; t2 = (Te4[(s2 >> 24) ] & 0xff000000) ^ (Te4[(s3 >> 16) & 0xff] & 0x00ff0000) ^ (Te4[(s0 >> 8) & 0xff] & 0x0000ff00) ^ (Te4[(s1 ) & 0xff] & 0x000000ff) ^ rk[2]; t3 = (Te4[(s3 >> 24) ] & 0xff000000) ^ (Te4[(s0 >> 16) & 0xff] & 0x00ff0000) ^ (Te4[(s1 >> 8) & 0xff] & 0x0000ff00) ^ (Te4[(s2 ) & 0xff] & 0x000000ff) ^ rk[3]; s0 = t0; s1 = t1; s2 = t2; s3 = t3; } PUTU32(block , s0); PUTU32(block + 4, s1); PUTU32(block + 8, s2); PUTU32(block + 12, s3); } void rijndaelDecryptRound(const u32 rk[/*4*(Nr + 1)*/], int Nr, u8 block[16], int rounds) { int r; u32 s0, s1, s2, s3, t0, t1, t2, t3; /* * map byte array block to cipher state * and add initial round key: */ s0 = GETU32(block ) ^ rk[0]; s1 = GETU32(block + 4) ^ rk[1]; s2 = GETU32(block + 8) ^ rk[2]; s3 = GETU32(block + 12) ^ rk[3]; rk += 4; /* * Nr - 1 full rounds: */ for (r = (rounds < Nr ? rounds : Nr) - 1; r > 0; r--) { t0 = Td0[(s0 >> 24) ] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >> 8) & 0xff] ^ Td3[(s1 ) & 0xff] ^ rk[0]; t1 = Td0[(s1 >> 24) ] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >> 8) & 0xff] ^ Td3[(s2 ) & 0xff] ^ rk[1]; t2 = Td0[(s2 >> 24) ] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >> 8) & 0xff] ^ Td3[(s3 ) & 0xff] ^ rk[2]; t3 = Td0[(s3 >> 24) ] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >> 8) & 0xff] ^ Td3[(s0 ) & 0xff] ^ rk[3]; s0 = t0; s1 = t1; s2 = t2; s3 = t3; rk += 4; } /* * complete the last round and * map cipher state to byte array block: */ t0 = (Td4[(s0 >> 24) ] & 0xff000000) ^ (Td4[(s3 >> 16) & 0xff] & 0x00ff0000) ^ (Td4[(s2 >> 8) & 0xff] & 0x0000ff00) ^ (Td4[(s1 ) & 0xff] & 0x000000ff); t1 = (Td4[(s1 >> 24) ] & 0xff000000) ^ (Td4[(s0 >> 16) & 0xff] & 0x00ff0000) ^ (Td4[(s3 >> 8) & 0xff] & 0x0000ff00) ^ (Td4[(s2 ) & 0xff] & 0x000000ff); t2 = (Td4[(s2 >> 24) ] & 0xff000000) ^ (Td4[(s1 >> 16) & 0xff] & 0x00ff0000) ^ (Td4[(s0 >> 8) & 0xff] & 0x0000ff00) ^ (Td4[(s3 ) & 0xff] & 0x000000ff); t3 = (Td4[(s3 >> 24) ] & 0xff000000) ^ (Td4[(s2 >> 16) & 0xff] & 0x00ff0000) ^ (Td4[(s1 >> 8) & 0xff] & 0x0000ff00) ^ (Td4[(s0 ) & 0xff] & 0x000000ff); if (rounds == Nr) { t0 ^= rk[0]; t1 ^= rk[1]; t2 ^= rk[2]; t3 ^= rk[3]; } PUTU32(block , t0); PUTU32(block + 4, t1); PUTU32(block + 8, t2); PUTU32(block + 12, t3); } #endif /* INTERMEDIATE_VALUE_KAT */ zmap-1.1.0/lib/rijndael-alg-fst.h000066400000000000000000000037241224250063200165240ustar00rootroot00000000000000/** * rijndael-alg-fst.h * * @version 3.0 (December 2000) * * Optimised ANSI C code for the Rijndael cipher (now AES) * * @author Vincent Rijmen * @author Antoon Bosselaers * @author Paulo Barreto * * This code is hereby placed in the public domain. * * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef RIJNDAEL_ALG_FST_H #define RIJNDAEL_ALG_FST_H #define MAXKC (256/32) #define MAXKB (256/8) #define MAXNR 14 typedef unsigned char u8; typedef unsigned short u16; typedef unsigned int u32; int rijndaelKeySetupEnc(u32 rk[/*4*(Nr + 1)*/], const u8 cipherKey[], int keyBits); int rijndaelKeySetupDec(u32 rk[/*4*(Nr + 1)*/], const u8 cipherKey[], int keyBits); void rijndaelEncrypt(const u32 rk[/*4*(Nr + 1)*/], int Nr, const u8 pt[16], u8 ct[16]); void rijndaelDecrypt(const u32 rk[/*4*(Nr + 1)*/], int Nr, const u8 ct[16], u8 pt[16]); #ifdef INTERMEDIATE_VALUE_KAT void rijndaelEncryptRound(const u32 rk[/*4*(Nr + 1)*/], int Nr, u8 block[16], int rounds); void rijndaelDecryptRound(const u32 rk[/*4*(Nr + 1)*/], int Nr, u8 block[16], int rounds); #endif /* INTERMEDIATE_VALUE_KAT */ #endif /* RIJNDAEL_ALG_FST_H */ zmap-1.1.0/lib/stack.c000066400000000000000000000012431224250063200144730ustar00rootroot00000000000000#include "stack.h" #include "../lib/xalloc.h" #include struct stack { size_t max_size; size_t cur_size; void** arr; }; stack_t* alloc_stack(size_t size) { stack_t* stack = xmalloc(sizeof(stack_t)); stack->arr = xcalloc(size, sizeof(void*)); stack->max_size = size; stack->cur_size = 0; return stack; } void free_stack(stack_t* stack) { xfree(stack->arr); xfree(stack); } void push(stack_t* stack, void* elt) { if (stack->cur_size == stack->max_size) { stack->max_size *= 2; xrealloc(stack->arr, stack->max_size); } stack->arr[stack->cur_size++] = elt; } void* pop(stack_t* stack) { void* res = stack->arr[--stack->cur_size]; return res; } zmap-1.1.0/lib/stack.h000066400000000000000000000004151224250063200145000ustar00rootroot00000000000000#ifndef ZMAP_STACK_H #define ZMAP_STACK_H #include struct stack; typedef struct stack stack_t; stack_t* alloc_stack(size_t size); void free_stack(stack_t* stack); void push(stack_t* stack, void* elt); void* pop(stack_t* stack); #endif /* ZMAP_STACK_H */zmap-1.1.0/lib/xalloc.c000066400000000000000000000010471224250063200146520ustar00rootroot00000000000000#include "xalloc.h" #include "../lib/logger.h" #include void die() __attribute__((noreturn)); void* xcalloc(size_t count, size_t size) { void* res = calloc(count, size); if (res == NULL) { die(); } return res; } void xfree(void *ptr) { free(ptr); } void* xmalloc(size_t size) { void* res = malloc(size); if (res == NULL) { die(); } return res; } void* xrealloc(void *ptr, size_t size) { void* res = realloc(ptr, size); if (res == NULL) { die(); } return res; } void die() { log_fatal("zmap", "Out of memory"); } zmap-1.1.0/lib/xalloc.h000066400000000000000000000003171224250063200146560ustar00rootroot00000000000000#ifndef ZMAP_ALLOC_H #define ZMAP_ALLOC_H #include void* xcalloc(size_t count, size_t size); void xfree(void *ptr); void* xmalloc(size_t size); void* xrealloc(void *ptr, size_t size); #endifzmap-1.1.0/src/000077500000000000000000000000001224250063200132435ustar00rootroot00000000000000zmap-1.1.0/src/.gitignore000066400000000000000000000000421224250063200152270ustar00rootroot00000000000000lexer.c lexer.h parser.c parser.h zmap-1.1.0/src/CMakeLists.txt000066400000000000000000000041501224250063200160030ustar00rootroot00000000000000include_directories( "${CMAKE_CURRENT_BINARY_DIR}" ${PROJECT_SOURCE_DIR}/lib ${PROJECT_SOURCE_DIR}/src ${PROJECT_SOURCE_DIR}/src/output_modules ) SET(LIB_SOURCES ${PROJECT_SOURCE_DIR}/lib/blacklist.c ${PROJECT_SOURCE_DIR}/lib/constraint.c ${PROJECT_SOURCE_DIR}/lib/logger.c ${PROJECT_SOURCE_DIR}/lib/pbm.c ${PROJECT_SOURCE_DIR}/lib/random.c ${PROJECT_SOURCE_DIR}/lib/rijndael-alg-fst.c ${PROJECT_SOURCE_DIR}/lib/stack.c ${PROJECT_SOURCE_DIR}/lib/xalloc.c ) # ADD YOUR PROBE MODULE HERE SET(EXTRA_PROBE_MODULES ) # ADD YOUR OUTPUT MODULE HERE SET(EXTRA_OUTPUT_MODULES ) SET(OUTPUT_MODULE_SOURCES output_modules/module_csv.c output_modules/output_modules.c ) SET(PROBE_MODULE_SOURCES probe_modules/module_icmp_echo.c probe_modules/module_tcp_synscan.c probe_modules/module_udp.c probe_modules/packet.c probe_modules/probe_modules.c ) SET(SOURCES aesrand.c cyclic.c expression.c fieldset.c filter.c get_gateway.c monitor.c recv.c send.c state.c validate.c zmap.c zopt_compat.c "${CMAKE_CURRENT_BINARY_DIR}/zopt.h" "${CMAKE_CURRENT_BINARY_DIR}/lexer.c" "${CMAKE_CURRENT_BINARY_DIR}/parser.c" ${EXTRA_PROBE_MODULES} ${EXTRA_OUTPUT_MODULES} ${PROBE_MODULE_SOURCES} ${OUTPUT_MODULE_SOURCES} ${LIB_SOURCES} ) if (WITH_JSON) SET(SOURCES ${SOURCES} output_modules/module_json.c) endif() if (WITH_REDIS) SET(SOURCES ${SOURCES} ${PROJECT_SOURCE_DIR}/lib/redis.c output_modules/module_redis.c output_modules/module_csvredis.c) endif() add_custom_command(OUTPUT zopt.h COMMAND gengetopt -C --no-help --no-version --unamed-opts=SUBNETS -i "${CMAKE_CURRENT_SOURCE_DIR}/zopt.ggo" -F "${CMAKE_CURRENT_BINARY_DIR}/zopt" ) add_custom_command(OUTPUT lexer.c COMMAND flex -o "${CMAKE_CURRENT_BINARY_DIR}/lexer.c" --header-file="${CMAKE_CURRENT_BINARY_DIR}/lexer.h" lexer.l ) add_custom_command(OUTPUT parser.c COMMAND byacc -d -o parser.c parser.y ) add_executable(zmap ${SOURCES}) target_link_libraries( zmap pcap gmp m ${REDIS_LIBS} ${JSON_LIBRARIES} ) # Install binary install( TARGETS zmap RUNTIME DESTINATION sbin ) # Install Manpages install( FILES zmap.1 DESTINATION share/man/man1 ) zmap-1.1.0/src/aesrand.c000066400000000000000000000027451224250063200150340ustar00rootroot00000000000000/* * ZMap Copyright 2013 Regents of the University of Michigan * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy * of the License at http://www.apache.org/licenses/LICENSE-2.0 */ #include #include #include #include #include "../lib/rijndael-alg-fst.h" #include "../lib/random.h" #include "../lib/logger.h" #define AES_ROUNDS 10 #define AES_BLOCK_WORDS 4 #define AES_KEY_BYTES 16 #define OUTPUT_BYTES 16 static uint32_t aes_input[AES_BLOCK_WORDS]; static uint32_t aes_sched[(AES_ROUNDS+1)*4]; static uint8_t aes_output[OUTPUT_BYTES]; static int init = 0; void aesrand_init(uint32_t seed) { memset(&aes_input, 0, sizeof(aes_input)); uint8_t key[AES_KEY_BYTES]; if (seed) { memset(key, 0, AES_KEY_BYTES*sizeof(uint8_t)); memcpy(key, &seed, sizeof(uint32_t)); } else { if (!random_bytes(key, AES_KEY_BYTES)) { log_fatal("aesrand", "couldn't get random bytes"); } } if (rijndaelKeySetupEnc(aes_sched, key, AES_KEY_BYTES*8) != AES_ROUNDS) { log_fatal("aesrand", "could not initialize AES key"); } memset(aes_output, 0, OUTPUT_BYTES*sizeof(uint8_t)); init = 1; } uint64_t aesrand_getword(void) { assert(init); memcpy(aes_input, aes_output, sizeof(aes_input)); rijndaelEncrypt(aes_sched, AES_ROUNDS, (uint8_t *)aes_input, aes_output); uint64_t retval; memcpy(&retval, aes_output, sizeof(retval)); return retval; } zmap-1.1.0/src/aesrand.h000066400000000000000000000006541224250063200150360ustar00rootroot00000000000000/* * ZMap Copyright 2013 Regents of the University of Michigan * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy * of the License at http://www.apache.org/licenses/LICENSE-2.0 */ #include #ifndef AESRAND_H #define AESRAND_H void aesrand_init(uint32_t seed); uint64_t aesrand_getword(void); #endif zmap-1.1.0/src/cyclic.c000066400000000000000000000155271224250063200146670ustar00rootroot00000000000000/* * ZMap Copyright 2013 Regents of the University of Michigan * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy * of the License at http://www.apache.org/licenses/LICENSE-2.0 */ /* * cyclic provides an inexpensive approach to iterating over the IPv4 address * space in a random(-ish) manner such that we connect to every host once in * a scan execution without having to keep track of the IPs that have been * scanned or need to be scanned and such that each scan has a different * ordering. We accomplish this by utilizing a cyclic multiplicative group * of integers modulo a prime and generating a new primitive root (generator) * for each scan. * * We know that 3 is a generator of (Z mod 2^32 + 15 - {0}, *) * and that we have coverage over the entire address space because 2**32 + 15 * is prime and ||(Z mod PRIME - {0}, *)|| == PRIME - 1. Therefore, we * just need to find a new generator (primitive root) of the cyclic group for * each scan that we perform. * * Because generators map to generators over an isomorphism, we can efficiently * find random primitive roots of our mult. group by finding random generators * of the group (Zp-1, +) which is isomorphic to (Zp*, *). Specifically the * generators of (Zp-1, +) are { s | (s, p-1) == 1 } which implies that * the generators of (Zp*, *) are { d^s | (s, p-1) == 1 }. where d is a known * generator of the multiplicative group. We efficiently find * generators of the additive group by precalculating the psub1_f of * p - 1 and randomly checking random numbers against the psub1_f until * we find one that is coprime and map it into Zp*. Because * totient(totient(p)) ~= 10^9, this should take relatively few * iterations to find a new generator. */ #include "cyclic.h" #include #include #include #include #include #include #include #include #include #include #include #include "../lib/logger.h" #include "../lib/blacklist.h" #include "state.h" #include "aesrand.h" #define LSRC "cyclic" typedef struct cyclic_group { uint64_t prime; uint64_t known_primroot; size_t num_prime_factors; // number of unique prime factors of (prime-1) uint64_t prime_factors[10]; // unique prime factors of (prime-1) } cyclic_group_t; // We will pick the first cyclic group from this list that is // larger than the number of IPs in our whitelist. E.g. for an // entire Internet scan, this would be cyclic32 // Note: this list should remain ordered by size (primes) ascending. static cyclic_group_t groups[] = { { // 2^16 + 1 .prime = 65537, .known_primroot = 3, .prime_factors = {2}, .num_prime_factors = 1 }, { // 2^24 + 43 .prime = 16777259, .known_primroot = 2, .prime_factors = {2, 23, 103, 3541}, .num_prime_factors = 4 }, { // 2^28 + 3 .prime = 268435459, .known_primroot = 2, .prime_factors = {2, 3, 19, 87211}, .num_prime_factors = 4 }, { // 2^32 + 15 .prime = 4294967311, .known_primroot = 3, .prime_factors = {2, 3, 5, 131, 364289}, .num_prime_factors = 5 } }; // selected prime/primitive root that we'll use as the generator static uint64_t prime = 0; static uint64_t primroot = 0; static uint64_t current = 0; static uint64_t num_addrs = 0; #define COPRIME 1 #define NOT_COPRIME 0 // check whether two integers are coprime static int check_coprime(uint64_t check, const cyclic_group_t *group) { for (unsigned i=0; i < group->num_prime_factors; i++) { if (group->prime_factors[i] > check && !(group->prime_factors[i] % check)) { return NOT_COPRIME; } else if (group->prime_factors[i] < check && !(check % group->prime_factors[i])) { return NOT_COPRIME; } else if (group->prime_factors[i] == check) { return NOT_COPRIME; } } return COPRIME; } // find gen of cyclic group Z modulo PRIME static uint64_t find_primroot(const cyclic_group_t *group) { // what luck, rand() returns a uint32_t! uint32_t candidate = (uint32_t) aesrand_getword() & 0xFFFFFFFF; while(check_coprime(candidate, group) != COPRIME) { ++candidate; } // pre-modded result is gigantic so use GMP mpz_t base, power, prime, primroot; mpz_init_set_d(base, (double) group->known_primroot); mpz_init_set_d(power, (double) candidate); mpz_init_set_d(prime, (double) group->prime); mpz_init(primroot); mpz_powm(primroot, base, power, prime); uint64_t retv = (uint64_t) mpz_get_ui(primroot); mpz_clear(base); mpz_clear(power); mpz_clear(prime); mpz_clear(primroot); return retv; } int cyclic_init(uint32_t primroot_, uint32_t current_) { assert(!(!primroot_ && current_)); // Initialize blacklist if (blacklist_init(zconf.whitelist_filename, zconf.blacklist_filename, zconf.destination_cidrs, zconf.destination_cidrs_len, NULL, 0)) { return -1; } num_addrs = blacklist_count_allowed(); if (!num_addrs) { log_error("blacklist", "no addresses are eligible to be scanned in the " "current configuration. This may be because the " "blacklist being used by ZMap (%s) prevents " "any addresses from receiving probe packets.", zconf.blacklist_filename ); exit(EXIT_FAILURE); } const cyclic_group_t *cur_group = NULL; for (uint32_t i=0; i num_addrs) { cur_group = &groups[i]; log_debug("cyclic", "using prime %lu, known_primroot %lu", cur_group->prime, cur_group->known_primroot); prime = groups[i].prime; break; } } if (zconf.use_seed) { aesrand_init(zconf.seed+1); } else { aesrand_init(0); } if (!primroot_) { do { primroot = find_primroot(cur_group); } while (primroot >= (1LL << 32)); log_debug(LSRC, "primitive root: %lld", primroot); current = (uint32_t) aesrand_getword() & 0xFFFFFFFF; log_debug(LSRC, "starting point: %lld", current); } else { primroot = primroot_; log_debug(LSRC, "primitive root %lld specified by caller", primroot); if (!current_) { current = (uint32_t) aesrand_getword() & 0xFFFFFFFF; log_debug(LSRC, "no cyclic starting point, " "selected random startpoint: %lld", current); } else { current = current_; log_debug(LSRC, "starting point %lld specified by caller", current); } } zconf.generator = primroot; // make sure current is an allowed ip cyclic_get_next_ip(); return 0; } uint32_t cyclic_get_curr_ip(void) { return (uint32_t) blacklist_lookup_index(current-1); } uint32_t cyclic_get_primroot(void) { return (uint32_t) primroot; } static inline uint32_t cyclic_get_next_elem(void) { do { current *= primroot; current %= prime; } while (current >= (1LL << 32)); return (uint32_t) current; } uint32_t cyclic_get_next_ip(void) { while (1) { uint32_t candidate = cyclic_get_next_elem(); if (candidate-1 < num_addrs) { return blacklist_lookup_index(candidate-1); } zsend.blacklisted++; } } zmap-1.1.0/src/cyclic.h000066400000000000000000000011701224250063200146610ustar00rootroot00000000000000/* * ZMap Copyright 2013 Regents of the University of Michigan * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy * of the License at http://www.apache.org/licenses/LICENSE-2.0 */ #include #ifndef CYCLIC_H #define CYCLIC_H int cyclic_init(uint32_t, uint32_t); // get next IP address to scan uint32_t cyclic_get_next_ip(void); // what IP address was returned last uint32_t cyclic_get_curr_ip(void); // what primitive root was generated for this current scan uint32_t cyclic_get_primroot(void); #endif zmap-1.1.0/src/expression.c000066400000000000000000000072071224250063200156140ustar00rootroot00000000000000#include "expression.h" #include "fieldset.h" #include "../lib/xalloc.h" /* Static helper functions */ static node_t* alloc_node(); static int eval_gt_node(node_t *node, fieldset_t *fields); static int eval_lt_node(node_t *node, fieldset_t *fields); static int eval_eq_node(node_t *node, fieldset_t *fields); static int eval_lt_eq_node(node_t *node, fieldset_t *fields); static int eval_gt_eq_node(node_t *node, fieldset_t *fields); static node_t* alloc_node() { node_t *node = xmalloc(sizeof(node_t)); memset(node, 0, sizeof(node_t)); return node; } static int eval_gt_node(node_t *node, fieldset_t *fields) { int index = node->left_child->value.field.index; uint64_t expected = node->right_child->value.int_literal; uint64_t actual = fs_get_uint64_by_index(fields, index); return (actual > expected); } static int eval_lt_node(node_t *node, fieldset_t *fields) { int index = node->left_child->value.field.index; uint64_t expected = node->right_child->value.int_literal; uint64_t actual = fs_get_uint64_by_index(fields, index); return (actual < expected); } static int eval_eq_node(node_t *node, fieldset_t *fields) { node_t *literal = node->right_child; int index = node->left_child->value.field.index; char *expected, *actual; switch (literal->type) { case STRING: expected = literal->value.string_literal; actual = fs_get_string_by_index(fields, index); return (strcmp(expected, actual) == 0); break; case INT: return (fs_get_uint64_by_index(fields, index) == literal->value.int_literal); break; default: printf("wat\n"); break; } return 0; } static int eval_lt_eq_node(node_t *node, fieldset_t *fields) { return !(eval_gt_node(node, fields)); } static int eval_gt_eq_node(node_t *node, fieldset_t *fields) { return !(eval_lt_node(node, fields)); } /* Exposed functions */ node_t* make_op_node(enum operation op) { node_t* node = alloc_node(); node->type = OP; node->value.op = op; return node; } node_t* make_field_node(char *fieldname) { node_t *node = alloc_node(); node->type = FIELD; node->value.field.fieldname = fieldname; return node; } node_t* make_string_node(char *literal) { node_t *node = alloc_node(); node->type = STRING; node->value.string_literal = literal; return node; } node_t* make_int_node(int literal) { node_t *node = alloc_node(); node->type = INT; node->value.int_literal = literal; return node; } int evaluate_expression(node_t *root, fieldset_t *fields) { if (!root) return 1; switch (root->type) { /* XXX Not sure if runs */ case FIELD: case STRING: case INT: return 1; case OP: break; } switch (root->value.op) { case GT: return eval_gt_node(root, fields); case LT: return eval_lt_node(root, fields); case EQ: return eval_eq_node(root, fields); case NEQ: return (!eval_eq_node(root, fields)); case LT_EQ: return eval_lt_eq_node(root, fields); case GT_EQ: return eval_gt_eq_node(root, fields); case AND: return (evaluate_expression(root->left_child, fields) && evaluate_expression(root->right_child, fields)); case OR: return (evaluate_expression(root->left_child, fields) || evaluate_expression(root->right_child, fields)); } return 0; } void print_expression(node_t *root) { if (!root) return; printf("%s", "( "); print_expression(root->left_child); switch (root->type) { case OP: printf(" %i ", root->value.op); break; case FIELD: printf(" (%s", root->value.field.fieldname); break; case STRING: printf("%s) ", root->value.string_literal); break; case INT: printf(" %llu) ", (long long unsigned) root->value.int_literal); break; default: break; } print_expression(root->right_child); printf("%s", " )"); } zmap-1.1.0/src/expression.h000066400000000000000000000015031224250063200156120ustar00rootroot00000000000000#ifndef ZMAP_TREE_H #define ZMAP_TREE_H #include "fieldset.h" #include #include #include #include enum operation { GT, LT, EQ, NEQ, AND, OR, LT_EQ, GT_EQ }; enum node_type { OP, FIELD, STRING, INT }; struct field_id { int index; char *fieldname; }; union node_value { struct field_id field; char *string_literal; uint64_t int_literal; enum operation op; }; typedef struct node { struct node *left_child; struct node *right_child; enum node_type type; union node_value value; } node_t; node_t* make_op_node(enum operation op); node_t* make_field_node(char *fieldname); node_t* make_string_node(char *literal); node_t* make_int_node(int literal); int evaluate_expression(node_t *root, fieldset_t *fields); void print_expression(node_t *root); #endif /* ZMAP_TREE_H */zmap-1.1.0/src/fieldset.c000066400000000000000000000114161224250063200152110ustar00rootroot00000000000000/* * ZMap Copyright 2013 Regents of the University of Michigan * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy * of the License at http://www.apache.org/licenses/LICENSE-2.0 */ #include "fieldset.h" #include #include #include #include #include "../lib/logger.h" void gen_fielddef_set(fielddefset_t *fds, fielddef_t fs[], int len) { if (fds->len + len > MAX_FIELDS) { log_fatal("fieldset", "out of room in field def set"); } fielddef_t *open = &(fds->fielddefs[fds->len]); memcpy(open, fs, len*sizeof(fielddef_t)); fds->len += len; } fieldset_t *fs_new_fieldset(void) { fieldset_t *f = malloc(sizeof(fieldset_t)); if (!f) { log_fatal("fieldset", "unable to allocate new fieldset"); } memset(f, 0, sizeof(fieldset_t)); return f; } static inline void fs_add_word(fieldset_t *fs, const char *name, int type, int free_, size_t len, field_val_t value) { if (fs->len + 1 >= MAX_FIELDS) { log_fatal("fieldset", "out of room in fieldset"); } field_t *f = &(fs->fields[fs->len]); fs->len++; f->type = type; f->name = name; f->len = len; f->value = value; f->free_ = free_; } static void fs_modify_word(fieldset_t *fs, const char *name, int type, int free_, size_t len, field_val_t value) { for (int i=0; ilen; i++) { if (!strcmp(fs->fields[i].name, name)) { if (fs->fields[i].free_) { free(fs->fields[i].value.ptr); fs->fields[i].value.ptr = NULL; } fs->fields[i].type = type; fs->fields[i].free_ = free_; fs->fields[i].len = len; fs->fields[i].value = value; return; } } fs_add_word(fs, name, type, free_, len, value); } void fs_add_null(fieldset_t *fs, const char *name) { field_val_t val = { .ptr = NULL }; fs_add_word(fs, name, FS_NULL, 0, 0, val); } void fs_add_string(fieldset_t *fs, const char *name, char *value, int free_) { field_val_t val = { .ptr = value }; fs_add_word(fs, name, FS_STRING, free_, strlen(value), val); } void fs_add_uint64(fieldset_t *fs, const char *name, uint64_t value) { field_val_t val = { .num = value }; fs_add_word(fs, name, FS_UINT64, 0, sizeof(uint64_t), val); } void fs_add_binary(fieldset_t *fs, const char *name, size_t len, void *value, int free_) { field_val_t val = { .ptr = value }; fs_add_word(fs, name, FS_BINARY, free_, len, val); } // Modify void fs_modify_null(fieldset_t *fs, const char *name) { field_val_t val = { .ptr = NULL }; fs_modify_word(fs, name, FS_NULL, 0, 0, val); } void fs_modify_string(fieldset_t *fs, const char *name, char *value, int free_) { field_val_t val = { .ptr = value }; fs_modify_word(fs, name, FS_STRING, free_, strlen(value), val); } void fs_modify_uint64(fieldset_t *fs, const char *name, uint64_t value) { field_val_t val = { .num = value }; fs_modify_word(fs, name, FS_UINT64, 0, sizeof(uint64_t), val); } void fs_modify_binary(fieldset_t *fs, const char *name, size_t len, void *value, int free_) { field_val_t val = { .ptr = value }; fs_modify_word(fs, name, FS_BINARY, free_, len, val); } uint64_t fs_get_uint64_by_index(fieldset_t *fs, int index) { return (uint64_t) fs->fields[index].value.num; } char* fs_get_string_by_index(fieldset_t *fs, int index) { return (char*) fs->fields[index].value.ptr; } int fds_get_index_by_name(fielddefset_t *fds, char *name) { for (int i=0; i < fds->len; i++) { if (!strcmp(fds->fielddefs[i].name, name)) { return i; } } return -1; } void fs_free(fieldset_t *fs) { if (!fs) { return; } for (int i=0; i < fs->len; i++) { field_t *f = &(fs->fields[i]); if (f->free_) { free(f->value.ptr); } } free(fs); } void fs_generate_fieldset_translation(translation_t *t, fielddefset_t *avail, char** req, int reqlen) { memset(t, 0, sizeof(translation_t)); if (!t) { log_fatal("fieldset", "unable to allocate memory for translation"); } for (int i=0; i < reqlen; i++) { int l = fds_get_index_by_name(avail, req[i]); if (l < 0) { log_fatal("fieldset", "specified field (%s) not " "available in selected " "probe module.", req[i]); } t->translation[t->len++] = l; } } void fs_generate_full_fieldset_translation(translation_t *t, fielddefset_t *avail) { memset(t, 0, sizeof(translation_t)); if (!t) { log_fatal("fieldset", "unable to allocate memory for translation"); } t->len = avail->len; for (int i=0; i < avail->len; i++) { t->translation[i] = i; } } fieldset_t *translate_fieldset(fieldset_t *fs, translation_t *t) { fieldset_t *retv = fs_new_fieldset(); if (!retv) { log_fatal("fieldset", "unable to allocate space for translated field set"); } for (int i=0; i < t->len; i++) { int o = t->translation[i]; memcpy(&(retv->fields[i]), &(fs->fields[o]), sizeof(field_t)); } retv->len = t->len; return retv; } zmap-1.1.0/src/fieldset.h000066400000000000000000000060661224250063200152230ustar00rootroot00000000000000/* * ZMap Copyright 2013 Regents of the University of Michigan * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy * of the License at http://www.apache.org/licenses/LICENSE-2.0 */ #include #include #include "types.h" #ifndef FIELDSET_H #define FIELDSET_H // maximum number of records that can be stored in a fieldset #define MAX_FIELDS 128 // types of data that can be stored in a field #define FS_STRING 0 #define FS_UINT64 1 #define FS_BINARY 2 #define FS_NULL 3 // definition of a field that's provided by a probe module // these are used so that users can ask at the command-line // what fields are available for consumption typedef struct field_def { const char *name; const char *type; const char *desc; } fielddef_t; typedef struct fielddef_set { fielddef_t fielddefs[MAX_FIELDS]; int len; } fielddefset_t; typedef union field_val { void *ptr; uint64_t num; } field_val_t; // the internal field type used by fieldset typedef struct field { const char *name; int type; int free_; size_t len; union field_val value; } field_t; // data structure that is populated by the probe module // and translated into the data structure that's passed // to the output module typedef struct fieldset { int len; field_t fields[MAX_FIELDS]; } fieldset_t; // we pass a different fieldset to an output module than // the probe module generates for us because a user may // only want certain fields and will expect them in a certain // order. We generate a translated fieldset that contains // only the fields we want to export to the output module. // a translation specifies how to efficiently convert the fs // povided by the probe module to the fs for the output module. typedef struct translation { int len; int translation[MAX_FIELDS]; } translation_t; fieldset_t *fs_new_fieldset(void); char* fs_get_string_by_index(fieldset_t *fs, int index); int fds_get_index_by_name(fielddefset_t *fds, char *name); void gen_fielddef_set(fielddefset_t *fds, fielddef_t fs[], int len); void fs_add_null(fieldset_t *fs, const char *name); void fs_add_uint64(fieldset_t *fs, const char *name, uint64_t value); void fs_add_string(fieldset_t *fs, const char *name, char *value, int free_); void fs_add_binary(fieldset_t *fs, const char *name, size_t len, void *value, int free_); // Modify void fs_modify_null(fieldset_t *fs, const char *name); void fs_modify_uint64(fieldset_t *fs, const char *name, uint64_t value); void fs_modify_string(fieldset_t *fs, const char *name, char *value, int free_); void fs_modify_binary(fieldset_t *fs, const char *name, size_t len, void *value, int free_); uint64_t fs_get_uint64_by_index(fieldset_t *fs, int index); void fs_free(fieldset_t *fs); void fs_generate_fieldset_translation(translation_t *t, fielddefset_t *avail, char** req, int reqlen); fieldset_t *translate_fieldset(fieldset_t *fs, translation_t *t); void fs_generate_full_fieldset_translation(translation_t *t, fielddefset_t *avail); #endif // FIELDSET_H zmap-1.1.0/src/filter.c000066400000000000000000000042571224250063200147040ustar00rootroot00000000000000#include "filter.h" #include "state.h" #include "lexer.h" #include "parser.h" #include "expression.h" #include "../lib/logger.h" #include extern int yyparse(); node_t *zfilter; static int validate_node(node_t *node, fielddefset_t *fields) { int index, found = 0; if (node->type == OP) { // These end up getting validated later if (node->value.op == AND || node->value.op == OR) { return 1; } // Comparison node (=, >, <, etc.) // Validate that the field (left child) exists in the fieldset for (index = 0; index < fields->len; index++) { if (fields->fielddefs[index].name) { if (strcmp(fields->fielddefs[index].name, node->left_child->value.field.fieldname) == 0) { node->left_child->value.field.index = index; found = 1; break; } } } if (!found) { fprintf(stderr, "Field '%s' does not exist\n", node->left_child->value.field.fieldname); return 0; } // Fieldname is fine, match the type. switch (node->right_child->type) { case STRING: if (strcmp(fields->fielddefs[index].type, "string") == 0) { return 1; } else { fprintf(stderr, "Field '%s' is not of type 'string'\n", fields->fielddefs[index].name); return 0; } case INT: if (strcmp(fields->fielddefs[index].type, "int") == 0) { return 1; } else { fprintf(stderr, "Field '%s' is not of type 'int'\n", fields->fielddefs[index].name); return 0; } default: return 0; } } else { // All non-op nodes are valid return 1; } // Didn't validate return 0; } int parse_filter_string(char *filter) { YY_BUFFER_STATE buffer_state = yy_scan_string(filter); int status = yyparse(); yy_delete_buffer(buffer_state); if (status) { // Error log_error("zmap", "Unable to parse filter string: '%s'", filter); return 0; } zconf.filter.expression = zfilter; return 1; } /* * 0 Valid * -1 Invalid Field Name * -2 Type Mismatch */ int validate_filter(node_t *root, fielddefset_t *fields) { int valid; if (!root) { return 1; } valid = validate_node(root, fields); if (!valid) { return 0; } return (validate_filter(root->left_child, fields) && validate_filter(root->right_child, fields)); } zmap-1.1.0/src/filter.h000066400000000000000000000004111224250063200146750ustar00rootroot00000000000000#ifndef ZMAP_FILTER_H #define ZMAP_FILTER_H #include "expression.h" #include "fieldset.h" struct output_filter { node_t *expression; }; int parse_filter_string(char *filter); int validate_filter(node_t *root, fielddefset_t *fields); #endif /* ZMAP_FILTER_H */zmap-1.1.0/src/get_gateway.c000066400000000000000000000136421224250063200157150ustar00rootroot00000000000000/* * ZMap Copyright 2013 Regents of the University of Michigan * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy * of the License at http://www.apache.org/licenses/LICENSE-2.0 */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "../lib/logger.h" int read_nl_sock(int sock, char *buf, int buf_len) { int msg_len = 0; char *pbuf = buf; do { int len = recv(sock, pbuf, buf_len - msg_len, 0); if (len <= 0) { log_debug("get-gw", "recv failed: %s", strerror(errno)); return -1; } struct nlmsghdr *nlhdr = (struct nlmsghdr *)pbuf; if (NLMSG_OK(nlhdr, ((unsigned int)len)) == 0 || nlhdr->nlmsg_type == NLMSG_ERROR) { log_debug("get-gw", "recv failed: %s", strerror(errno)); return -1; } if (nlhdr->nlmsg_type == NLMSG_DONE) { break; } else { msg_len += len; pbuf += len; } if ((nlhdr->nlmsg_flags & NLM_F_MULTI) == 0) { break; } } while (1); return msg_len; } int send_nl_req(uint16_t msg_type, uint32_t seq, void *payload, uint32_t payload_len) { int sock = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE); if (sock < 0) { log_error("get-gw", "unable to get socket: %s", strerror(errno)); return -1; } if (NLMSG_SPACE(payload_len) < payload_len) { // Integer overflow return -1; } struct nlmsghdr *nlmsg; nlmsg = malloc(NLMSG_SPACE(payload_len)); if (!nlmsg) { return -1; } memset(nlmsg, 0, NLMSG_SPACE(payload_len)); memcpy(NLMSG_DATA(nlmsg), payload, payload_len); nlmsg->nlmsg_type = msg_type; nlmsg->nlmsg_len = NLMSG_LENGTH(payload_len); nlmsg->nlmsg_flags = NLM_F_DUMP | NLM_F_REQUEST; nlmsg->nlmsg_seq = seq; nlmsg->nlmsg_pid = getpid(); if (send(sock, nlmsg, nlmsg->nlmsg_len, 0) < 0) { log_error("get-gw", "failure sending: %s", strerror(errno)); return -1; } free(nlmsg); return sock; } int get_hw_addr(struct in_addr *gw_ip, char *iface, unsigned char *hw_mac) { char buf[8192]; struct ndmsg req; struct nlmsghdr *nlhdr; if (!gw_ip || !hw_mac) { return -1; } // Send RTM_GETNEIGH request req.ndm_family = AF_INET; req.ndm_ifindex = if_nametoindex(iface); req.ndm_state = NUD_REACHABLE; req.ndm_type = NDA_LLADDR; int sock = send_nl_req(RTM_GETNEIGH, 1, &req, sizeof(req)); // Read responses unsigned nl_len = read_nl_sock(sock, buf, sizeof(buf)); if (nl_len <= 0) { return -1; } // Parse responses nlhdr = (struct nlmsghdr *)buf; while (NLMSG_OK(nlhdr, nl_len)) { struct rtattr *rt_attr; struct rtmsg *rt_msg; int rt_len; unsigned char mac[6]; struct in_addr dst_ip; int correct_ip = 0; rt_msg = (struct rtmsg *) NLMSG_DATA(nlhdr); if ((rt_msg->rtm_family != AF_INET)) { return -1; } rt_attr = (struct rtattr *) RTM_RTA(rt_msg); rt_len = RTM_PAYLOAD(nlhdr); while (RTA_OK(rt_attr, rt_len)) { switch (rt_attr->rta_type) { case NDA_LLADDR: if (RTA_PAYLOAD(rt_attr) != IFHWADDRLEN) { // could be using a VPN log_fatal("get_gateway", "Unexpected hardware address length (%d).\n\n" \ " If you are using a VPN, supply the --vpn flag (and provide an interface via -i)", RTA_PAYLOAD(rt_attr)); exit(1); } memcpy(mac, RTA_DATA(rt_attr), IFHWADDRLEN); break; case NDA_DST: if (RTA_PAYLOAD(rt_attr) != sizeof(dst_ip)) { // could be using a VPN log_fatal("get_gateway", "Unexpected IP address length (%d).\n" \ " If you are using a VPN, supply the --vpn flag (and provide an interface via -i)", RTA_PAYLOAD(rt_attr)); exit(1); } memcpy(&dst_ip, RTA_DATA(rt_attr), sizeof(dst_ip)); if (memcmp(&dst_ip, gw_ip, sizeof(dst_ip)) == 0) { correct_ip = 1; } break; } rt_attr = RTA_NEXT(rt_attr, rt_len); } if (correct_ip) { memcpy(hw_mac, mac, IFHWADDRLEN); return 0; } nlhdr = NLMSG_NEXT(nlhdr, nl_len); } return -1; } // gw and iface[IF_NAMESIZE] MUST be allocated int get_default_gw(struct in_addr *gw, char *iface) { struct rtmsg req; unsigned int nl_len; char buf[8192]; struct nlmsghdr *nlhdr; if (!gw || !iface) { return -1; } // Send RTM_GETROUTE request memset(&req, 0, sizeof(req)); int sock = send_nl_req(RTM_GETROUTE, 0, &req, sizeof(req)); // Read responses nl_len = read_nl_sock(sock, buf, sizeof(buf)); if (nl_len <= 0) { return -1; } // Parse responses nlhdr = (struct nlmsghdr *)buf; while (NLMSG_OK(nlhdr, nl_len)) { struct rtattr *rt_attr; struct rtmsg *rt_msg; int rt_len; int has_gw = 0; rt_msg = (struct rtmsg *) NLMSG_DATA(nlhdr); if ((rt_msg->rtm_family != AF_INET) || (rt_msg->rtm_table != RT_TABLE_MAIN)) { return -1; } rt_attr = (struct rtattr *) RTM_RTA(rt_msg); rt_len = RTM_PAYLOAD(nlhdr); while (RTA_OK(rt_attr, rt_len)) { switch (rt_attr->rta_type) { case RTA_OIF: if_indextoname(*(int *) RTA_DATA(rt_attr), iface); break; case RTA_GATEWAY: gw->s_addr = *(unsigned int *) RTA_DATA(rt_attr); has_gw = 1; break; } rt_attr = RTA_NEXT(rt_attr, rt_len); } if (has_gw) { return 0; } nlhdr = NLMSG_NEXT(nlhdr, nl_len); } return -1; } // Returns the first IP address for a given iface int get_iface_ip(char *iface, struct in_addr *ip) { int sock; struct ifreq ifr; sock = socket(AF_INET, SOCK_DGRAM, 0); if (sock < 0) { log_error("get-gw", "failure opening socket: %s", strerror(errno)); return -1; } ifr.ifr_addr.sa_family = AF_INET; strncpy(ifr.ifr_name, iface, IFNAMSIZ-1); if (ioctl(sock, SIOCGIFADDR, &ifr) < 0) { log_error("get-gw", "ioctl failure: %s", strerror(errno)); close(sock); return -1; } close(sock); memcpy(ip, &((struct sockaddr_in*)&ifr.ifr_addr)->sin_addr, sizeof(*ip)); return 0; } zmap-1.1.0/src/get_gateway.h000066400000000000000000000010511224250063200157110ustar00rootroot00000000000000/* * ZMap Copyright 2013 Regents of the University of Michigan * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy * of the License at http://www.apache.org/licenses/LICENSE-2.0 */ #ifndef GET_GATEWAY_H #define GET_GATEWAY_H #include int get_hw_addr(struct in_addr *gw_ip, char *iface, unsigned char *hw_mac); int get_default_gw(struct in_addr *gw, char *iface); int get_iface_ip(char *iface, struct in_addr *ip); #endif zmap-1.1.0/src/lexer.l000066400000000000000000000013401224250063200145350ustar00rootroot00000000000000%{ #pragma GCC diagnostic ignored "-Wredundant-decls" #include #include "parser.h" %} %option noinput %option nounput %% [0-9]+ yylval.int_literal = (uint64_t) atoll(yytext); return T_NUMBER; \n /* Ignore end of line */ [ \t]+ /* Ignore whitespace */ != return T_NOT_EQ; >= return T_GT_EQ; "<=" return T_LT_EQ; && return T_AND; "||" return T_OR; = return '='; ">" return '>'; "<" return '<'; "(" return '('; ")" return ')'; [a-zA-Z][a-zA-Z0-9]+ yylval.string_literal = strdup(yytext); return T_FIELD; %%zmap-1.1.0/src/monitor.c000066400000000000000000000144511224250063200151030ustar00rootroot00000000000000/* * ZMap Copyright 2013 Regents of the University of Michigan * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy * of the License at http://www.apache.org/licenses/LICENSE-2.0 */ // module responsible for printing on-screen updates during the scan process #include #include #include #include #include "recv.h" #include "monitor.h" #include "state.h" #include "../lib/logger.h" #define UPDATE_INTERVAL 1 //seconds static double last_now = 0.0; static uint32_t last_sent = 0; static uint32_t last_rcvd = 0; static uint32_t last_drop = 0; static uint32_t last_failures = 0; static double min_d(double array[], int n) { double value=INFINITY; for (int i=0; i 0) { snprintf(buf, len, "%d years", y); } else if (d > 9) { snprintf(buf, len, "%dd", d); } else if (d > 0) { snprintf(buf, len, "%dd%02dh", d, h); } else if (h > 9) { snprintf(buf, len, "%dh", h); } else if (h > 0) { snprintf(buf, len, "%dh%02dm", h, m); } else if (m > 9) { snprintf(buf, len, "%dm", m); } else if (m > 0) { snprintf(buf, len, "%dm%02ds", m, s); } else { snprintf(buf, len, "%ds", s); } } else { if (d > 0) { snprintf(buf, len, "%dd%d:%02d:%02d", d, h, m, s); } else if (h > 0) { snprintf(buf, len, "%d:%02d:%02d", h, m, s); } else { snprintf(buf, len, "%d:%02d", m, s); } } } // pretty print quantities static void number_string(uint32_t n, char *buf, size_t len) { int figs = 0; if (n < 1000) { snprintf(buf, len, "%u ", n); } else if (n < 1000000) { if (n < 10000) { figs = 2; } else if (n < 100000) { figs = 1; } snprintf(buf, len, "%0.*f K", figs, (float)n/1000.); } else { if (figs < 10000000) { figs = 2; } else if (figs < 100000000) { figs = 1; } snprintf(buf, len, "%0.*f M", figs, (float)n/1000000.); } } // estimate time remaining time based on config and state double compute_remaining_time(double age) { if (!zsend.complete) { double remaining[] = {INFINITY, INFINITY, INFINITY}; if (zsend.targets) { double done = (double)zsend.sent/zsend.targets; remaining[0] = (1. - done)*(age/done) + zconf.cooldown_secs; } if (zconf.max_runtime) { remaining[1] = (zconf.max_runtime - age)+zconf.cooldown_secs; } if (zconf.max_results) { double done = (double)zrecv.success_unique/zconf.max_results; remaining[2] = (1. - done)*(age/done); } return min_d(remaining, sizeof(remaining)/sizeof(double)); } else { return zconf.cooldown_secs - (now() - zsend.finish); } } static void monitor_update(void) { if (last_now > 0.0) { double age = now() - zsend.start; double delta = now() - last_now; double remaining_secs = compute_remaining_time(age); double percent_complete = 100.*age/(age + remaining_secs); // ask pcap for fresh values recv_update_pcap_stats(); // format times for display char time_left[20]; if (age < 5) { time_left[0] = '\0'; } else { char buf[20]; time_string((int)remaining_secs, 1, buf, sizeof(buf)); snprintf(time_left, sizeof(time_left), " (%s left)", buf); } char time_past[20]; time_string((int)age, 0, time_past, sizeof(time_past)); char send_rate[20], send_avg[20], recv_rate[20], recv_avg[20], pcap_drop[20], pcap_drop_avg[20]; // recv stats number_string((zrecv.success_unique - last_rcvd)/delta, recv_rate, sizeof(recv_rate)); number_string((zrecv.success_unique/age), recv_avg, sizeof(recv_avg)); // dropped stats number_string((zrecv.pcap_drop + zrecv.pcap_ifdrop - last_drop)/delta, pcap_drop, sizeof(pcap_drop)); number_string(((zrecv.pcap_drop + zrecv.pcap_ifdrop)/age), pcap_drop_avg, sizeof(pcap_drop_avg)); // Warn if we drop > 5% of our average receive rate uint32_t drop_rate = (uint32_t)((zrecv.pcap_drop + zrecv.pcap_ifdrop - last_drop) / delta); if (drop_rate > (uint32_t)((zrecv.success_unique - last_rcvd) / delta) / 20) { log_warn("monitor", "Dropped %d packets in the last second, (%d total dropped (pcap: %d + iface: %d))", drop_rate, zrecv.pcap_drop + zrecv.pcap_ifdrop, zrecv.pcap_drop, zrecv.pcap_ifdrop); } // Warn if we fail to send > 1% of our average send rate uint32_t fail_rate = (uint32_t)((zsend.sendto_failures - last_failures) / delta); // failures/sec if (fail_rate > ((zsend.sent / age) / 100)) { log_warn("monitor", "Failed to send %d packets/sec (%d total failures)", fail_rate, zsend.sendto_failures); } float hits; if (!zsend.sent) { hits = 0; } else { hits = zrecv.success_unique*100./zsend.sent; } if (!zsend.complete) { // main display (during sending) number_string((zsend.sent - last_sent)/delta, send_rate, sizeof(send_rate)); number_string((zsend.sent/age), send_avg, sizeof(send_avg)); fprintf(stderr, "%5s %0.0f%%%s; send: %u %sp/s (%sp/s avg); " "recv: %u %sp/s (%sp/s avg); " "drops: %sp/s (%sp/s avg); " "hits: %0.2f%%\n", time_past, percent_complete, time_left, zsend.sent, send_rate, send_avg, zrecv.success_unique, recv_rate, recv_avg, pcap_drop, pcap_drop_avg, hits); } else { // alternate display (during cooldown) number_string((zsend.sent/(zsend.finish - zsend.start)), send_avg, sizeof(send_avg)); fprintf(stderr, "%5s %0.0f%%%s; send: %u done (%sp/s avg); " "recv: %u %sp/s (%sp/s avg); " "drops: %sp/s (%sp/s avg); " "hits: %0.2f%%\n", time_past, percent_complete, time_left, zsend.sent, send_avg, zrecv.success_unique, recv_rate, recv_avg, pcap_drop, pcap_drop_avg, hits); } } last_now = now(); last_sent = zsend.sent; last_rcvd = zrecv.success_unique; last_drop = zrecv.pcap_drop + zrecv.pcap_ifdrop; last_failures = zsend.sendto_failures; } void monitor_run(void) { while (!(zsend.complete && zrecv.complete)) { monitor_update(); sleep(UPDATE_INTERVAL); } } zmap-1.1.0/src/monitor.h000066400000000000000000000005501224250063200151030ustar00rootroot00000000000000/* * ZMap Copyright 2013 Regents of the University of Michigan * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy * of the License at http://www.apache.org/licenses/LICENSE-2.0 */ #ifndef MONITOR_H #define MONITOR_H void monitor_run(); #endif zmap-1.1.0/src/output_modules/000077500000000000000000000000001224250063200163335ustar00rootroot00000000000000zmap-1.1.0/src/output_modules/module_csv.c000066400000000000000000000046601224250063200206450ustar00rootroot00000000000000/* * ZMap Copyright 2013 Regents of the University of Michigan * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy * of the License at http://www.apache.org/licenses/LICENSE-2.0 */ #include #include #include #include #include #include #include #include #include "../../lib/logger.h" #include "../fieldset.h" #include "output_modules.h" static FILE *file = NULL; int csv_init(struct state_conf *conf, char **fields, int fieldlens) { assert(conf); if (conf->output_filename) { if (!strcmp(conf->output_filename, "-")) { file = stdout; } else { if (!(file = fopen(conf->output_filename, "w"))) { log_fatal("csv", "could not open output file (%s)", conf->output_filename); } } } else { log_warn("csv", "no output file selected. " "no results will be provided."); } if (fieldlens > 0 && file) { log_debug("csv", "more than one field, will add headers"); for (int i=0; i < fieldlens; i++) { if (i) { fprintf(file, ", "); } fprintf(file, "%s", fields[i]); } fprintf(file, "\n"); } return EXIT_SUCCESS; } int csv_close(__attribute__((unused)) struct state_conf* c, __attribute__((unused)) struct state_send* s, __attribute__((unused)) struct state_recv* r) { if (file) { fflush(file); fclose(file); } return EXIT_SUCCESS; } static void hex_encode(FILE *f, unsigned char* readbuf, size_t len) { for(size_t i=0; i < len; i++) { fprintf(f, "%02x", readbuf[i]); } } int csv_process(fieldset_t *fs) { if (!file) { return EXIT_SUCCESS; } for (int i=0; i < fs->len; i++) { field_t *f = &(fs->fields[i]); if (i) { fprintf(file, ", "); } if (f->type == FS_STRING) { fprintf(file, "%s", (char*) f->value.ptr); } else if (f->type == FS_UINT64) { fprintf(file, "%" PRIu64, (uint64_t) f->value.num); } else if (f->type == FS_BINARY) { hex_encode(file, (unsigned char*) f->value.ptr, f->len); } else if (f->type == FS_NULL) { // do nothing } else { log_fatal("csv", "received unknown output type"); } } fprintf(file, "\n"); return EXIT_SUCCESS; } output_module_t module_csv_file = { .name = "csv", .init = &csv_init, .start = NULL, .update = NULL, .update_interval = 0, .close = &csv_close, .process_ip = &csv_process, .helptext = NULL }; zmap-1.1.0/src/output_modules/module_csv.h000066400000000000000000000003551224250063200206470ustar00rootroot00000000000000#include "../fieldset.h" #include "output_modules.h" int csv_init(struct state_conf *conf, char **fields, int fieldlens); int csv_process(fieldset_t *fs); int csv_close(struct state_conf* c, struct state_send *s, struct state_recv *r); zmap-1.1.0/src/output_modules/module_csvredis.c000066400000000000000000000032751224250063200216750ustar00rootroot00000000000000/* * ZMap Copyright 2013 Regents of the University of Michigan * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy * of the License at http://www.apache.org/licenses/LICENSE-2.0 */ #include #include #include #include "../fieldset.h" #include "module_redis.h" #include "module_csv.h" #include "output_modules.h" #include "../../lib/logger.h" static int success_index = -1, repeat_index = -1; int csvredis_init(struct state_conf *conf, char **fields, int fieldlens) { csv_init(conf, fields, fieldlens); redismodule_init(conf, fields, fieldlens); for (int i=0; i < fieldlens; i++) { if (!strcmp("success", fields[i])) { success_index = i; } else if (!strcmp("repeat", fields[i])) { repeat_index = i; } } if (success_index < 0 || repeat_index < 0) { log_fatal("csvredis", "success or repeat not included in fieldset"); } log_info("csvredis", "output module successfully initialized"); return EXIT_SUCCESS; } int csvredis_close(struct state_conf* c, struct state_send* s, struct state_recv* r) { csv_close(c,s,r); redismodule_close(c,s,r); return EXIT_SUCCESS; } int csvredis_process(fieldset_t *fs) { csv_process(fs); int is_success = fs_get_uint64_by_index(fs, success_index); int is_repeat = fs_get_uint64_by_index(fs, repeat_index); if (is_success && !is_repeat) { redismodule_process(fs); } return EXIT_SUCCESS; } output_module_t module_csv_redis = { .name = "csvredis", .init = &csvredis_init, .start = NULL, .update = NULL, .update_interval = 0, .close = &csvredis_close, .process_ip = &csvredis_process, .helptext = NULL }; zmap-1.1.0/src/output_modules/module_json.c000066400000000000000000000142521224250063200210210ustar00rootroot00000000000000/* * ZMap Copyright 2013 Regents of the University of Michigan * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy * of the License at http://www.apache.org/licenses/LICENSE-2.0 */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include "../../lib/logger.h" #include "output_modules.h" #include "../probe_modules/probe_modules.h" static FILE *file = NULL; #define UNUSED __attribute__((unused)) int json_output_file_init(struct state_conf *conf, UNUSED char **fields, UNUSED int fieldlens) { int i; char mac_buf[ (IFHWADDRLEN * 2) + (IFHWADDRLEN - 1) + 1 ]; char *p; json_object *obj = json_object_new_object(); assert(conf); if (conf->output_filename) { if (!strcmp(conf->output_filename, "-")) { file = stdout; } else { if (!(file = fopen(conf->output_filename, "w"))) { perror("Couldn't open output file"); exit(EXIT_FAILURE); } } // Create a header json object to describe this output file json_object_object_add(obj, "type", json_object_new_string("header")); json_object_object_add(obj, "log_level", json_object_new_int(conf->log_level)); json_object_object_add(obj, "target_port", json_object_new_int(conf->target_port)); json_object_object_add(obj, "source_port_first", json_object_new_int(conf->source_port_first)); json_object_object_add(obj, "source_port_last", json_object_new_int(conf->source_port_last)); json_object_object_add(obj, "max_targets", json_object_new_int(conf->max_targets)); json_object_object_add(obj, "max_runtime", json_object_new_int(conf->max_runtime)); json_object_object_add(obj, "max_results", json_object_new_int(conf->max_results)); if (conf->iface) { json_object_object_add(obj, "iface", json_object_new_string(conf->iface)); } json_object_object_add(obj, "rate", json_object_new_int(conf->rate)); json_object_object_add(obj, "bandwidth", json_object_new_int(conf->bandwidth)); json_object_object_add(obj, "cooldown_secs", json_object_new_int(conf->cooldown_secs)); json_object_object_add(obj, "senders", json_object_new_int(conf->senders)); json_object_object_add(obj, "use_seed", json_object_new_int(conf->use_seed)); json_object_object_add(obj, "seed", json_object_new_int(conf->seed)); json_object_object_add(obj, "generator", json_object_new_int(conf->generator)); json_object_object_add(obj, "packet_streams", json_object_new_int(conf->packet_streams)); json_object_object_add(obj, "probe_module", json_object_new_string(((probe_module_t *)conf->probe_module)->name)); json_object_object_add(obj, "output_module", json_object_new_string(((output_module_t *)conf->output_module)->name)); if (conf->probe_args) { json_object_object_add(obj, "probe_args", json_object_new_string(conf->probe_args)); } if (conf->output_args) { json_object_object_add(obj, "output_args", json_object_new_string(conf->output_args)); } if (conf->gw_mac) { memset(mac_buf, 0, sizeof(mac_buf)); p = mac_buf; for(i=0; i < IFHWADDRLEN; i++) { if (i == IFHWADDRLEN-1) { snprintf(p, 3, "%.2x", conf->gw_mac[i]); p += 2; } else { snprintf(p, 4, "%.2x:", conf->gw_mac[i]); p += 3; } } json_object_object_add(obj, "gw_mac", json_object_new_string(mac_buf)); } json_object_object_add(obj, "source_ip_first", json_object_new_string(conf->source_ip_first)); json_object_object_add(obj, "source_ip_last", json_object_new_string(conf->source_ip_last)); json_object_object_add(obj, "output_filename", json_object_new_string(conf->output_filename)); if (conf->blacklist_filename) json_object_object_add(obj, "blacklist_filename", json_object_new_string(conf->blacklist_filename)); if (conf->whitelist_filename) json_object_object_add(obj, "whitelist_filename", json_object_new_string(conf->whitelist_filename)); json_object_object_add(obj, "dryrun", json_object_new_int(conf->dryrun)); json_object_object_add(obj, "summary", json_object_new_int(conf->summary)); json_object_object_add(obj, "quiet", json_object_new_int(conf->quiet)); json_object_object_add(obj, "recv_ready", json_object_new_int(conf->recv_ready)); fprintf(file, "%s\n", json_object_to_json_string(obj)); } return EXIT_SUCCESS; } static void json_output_file_store_data(json_object *obj, const u_char *packet, size_t buflen) { unsigned int i; char *buf; buf = malloc((buflen*2)+1); buf[buflen*2] = 0; for (i=0; ilen; i++) { field_t *f = &(fs->fields[i]); if (f->type == FS_STRING) { json_object_object_add(obj, f->name, json_object_new_string((char *) f->value.ptr)); } else if (f->type == FS_UINT64) { json_object_object_add(obj, f->name, json_object_new_int((int) f->value.num)); } else if (f->type == FS_BINARY) { json_output_file_store_data(obj, (const u_char*) f->value.ptr, f->len); } else if (f->type == FS_NULL) { // do nothing } else { log_fatal("json", "received unknown output type"); } } fprintf(file, "%s\n", json_object_to_json_string(obj)); fflush(file); // free memory json_object_put(obj); return EXIT_SUCCESS; } int json_output_file_close(UNUSED struct state_conf* c, UNUSED struct state_send* s, UNUSED struct state_recv* r) { if (file) { fflush(file); fclose(file); } return EXIT_SUCCESS; } output_module_t module_json_file = { .name = "json", .init = &json_output_file_init, .start = NULL, .update = NULL, .update_interval = 0, .close = &json_output_file_close, .process_ip = &json_output_file_ip, .helptext = NULL }; zmap-1.1.0/src/output_modules/module_redis.c000066400000000000000000000047171224250063200211630ustar00rootroot00000000000000/* * ZMap Copyright 2013 Regents of the University of Michigan * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy * of the License at http://www.apache.org/licenses/LICENSE-2.0 */ #include #include #include #include #include #include #include #include "../../lib/logger.h" #include "../../lib/redis.h" #include "output_modules.h" #define UNUSED __attribute__((unused)) #define BUFFER_SIZE 500 static uint32_t *buffer; static int buffer_fill = 0; static char *queue_name = NULL; static int field_index = -1; int redismodule_init(struct state_conf *conf, char **fields, int fieldlens) { buffer = calloc(BUFFER_SIZE, sizeof(uint32_t)); assert(buffer); buffer_fill = 0; for (int i=0; i < fieldlens; i++) { if (!strcmp(fields[i], "saddr-raw")) { field_index = i; break; } } if (field_index < 0) { log_fatal("redis-module", "saddr-raw not included in output-fields"); } if (conf->output_args) { redisconf_t *rconf = redis_parse_connstr(conf->output_args); if (rconf->type == T_TCP) { log_info("redis-module", "{type: TCP, server: %s, " "port: %u, list: %s}", rconf->server, rconf->port, rconf->list_name); } else { log_info("redis-module", "{type: LOCAL, path: %s, " "list: %s}", rconf->path, rconf->list_name); } queue_name = rconf->list_name; } else { queue_name = strdup("zmap_output"); } return redis_init(conf->output_args); } static int redismodule_flush(void) { if (redis_lpush((char *)queue_name, buffer, buffer_fill, sizeof(uint32_t))) { return EXIT_FAILURE; } buffer_fill = 0; return EXIT_SUCCESS; } int redismodule_process(fieldset_t *fs) { field_t *f = &(fs->fields[field_index]); buffer[buffer_fill] = (uint32_t) f->value.num; if (++buffer_fill == BUFFER_SIZE) { if (redismodule_flush()) { return EXIT_FAILURE; } } return EXIT_SUCCESS; } int redismodule_close(UNUSED struct state_conf* c, UNUSED struct state_send* s, UNUSED struct state_recv* r) { if (redismodule_flush()) { return EXIT_FAILURE; } if (redis_close()) { return EXIT_FAILURE; } return EXIT_SUCCESS; } output_module_t module_redis = { .name = "redis-packed", .init = &redismodule_init, .start = NULL, .update = NULL, .update_interval = 0, .close = &redismodule_close, .process_ip = &redismodule_process, .helptext = NULL }; zmap-1.1.0/src/output_modules/module_redis.h000066400000000000000000000003621224250063200211600ustar00rootroot00000000000000#include "output_modules.h" int redismodule_init(struct state_conf *conf, char **fields, int fieldlens); int redismodule_process(fieldset_t *fs); int redismodule_close(struct state_conf* c, struct state_send* s, struct state_recv* r); zmap-1.1.0/src/output_modules/output_modules.c000066400000000000000000000023161224250063200215710ustar00rootroot00000000000000/* * ZMap Copyright 2013 Regents of the University of Michigan * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy * of the License at http://www.apache.org/licenses/LICENSE-2.0 */ #include #include #include "output_modules.h" extern output_module_t module_csv_file; #ifdef REDIS extern output_module_t module_redis; extern output_module_t module_csv_redis; #endif #ifdef JSON extern output_module_t module_json_file; #endif output_module_t* output_modules[] = { &module_csv_file, #ifdef REDIS &module_redis, &module_csv_redis, #endif #ifdef JSON &module_json_file #endif // ADD YOUR MODULE HERE }; output_module_t* get_output_module_by_name(const char* name) { int num_modules = (int) (sizeof(output_modules)/sizeof(output_modules[0])); for (int i=0; i < num_modules; i++) { if (!strcmp(output_modules[i]->name, name)) { return output_modules[i]; } } return NULL; } void print_output_modules(void) { int num_modules = (int) (sizeof(output_modules)/sizeof(output_modules[0])); for (int i=0; i < num_modules; i++) { printf("%s\n", output_modules[i]->name); } } zmap-1.1.0/src/output_modules/output_modules.h000066400000000000000000000021151224250063200215730ustar00rootroot00000000000000/* * ZMap Copyright 2013 Regents of the University of Michigan * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy * of the License at http://www.apache.org/licenses/LICENSE-2.0 */ #ifndef OUTPUT_MODULES_H #define OUTPUT_MODULES_H #include "../state.h" #include "../fieldset.h" // called at scanner initialization typedef int (*output_init_cb)(struct state_conf *, char **fields, int fieldslen); // called on packet receipt typedef int (*output_packet_cb)(fieldset_t *fs); // called periodically during the scan typedef int (*output_update_cb)(struct state_conf*, struct state_send*, struct state_recv*); typedef struct output_module { const char *name; unsigned update_interval; output_init_cb init; output_update_cb start; output_update_cb update; output_update_cb close; output_packet_cb process_ip; const char *helptext; } output_module_t; output_module_t* get_output_module_by_name(const char*); void print_output_modules(void); #endif // HEADER_OUTPUT_MODULES_H zmap-1.1.0/src/parser.y000066400000000000000000000042521224250063200147340ustar00rootroot00000000000000%{ #include #include #include "expression.h" #include "lexer.h" #include "filter.h" void yyerror(const char *str) { fprintf(stderr,"Parse error: %s\n",str); } int yywrap() { return 1; } extern node_t *zfilter; %} %union { int int_literal; char *string_literal; struct node *expr; } %token '(' ')' T_AND T_OR %token T_NUMBER %token T_FIELD %token T_NOT_EQ T_GT_EQ '>' '<' '=' T_LT_EQ %left T_OR %left T_AND %type filter %type number_filter %type string_filter %type filter_expr %% expression: filter_expr { zfilter = $1; } filter_expr: filter_expr T_OR filter_expr { $$ = make_op_node(OR); $$->left_child = $1; $$->right_child = $3; } | filter_expr T_AND filter_expr { $$ = make_op_node(AND); $$->left_child = $1; $$->right_child = $3; } | '(' filter_expr ')' { $$ = $2; } | filter { $$ = $1; } ; filter: number_filter { $$ = $1; } | string_filter { $$ = $1; } ; number_filter: T_FIELD '=' T_NUMBER { $$ = make_op_node(EQ); $$->left_child = make_field_node($1); $$->right_child = make_int_node($3); } | T_FIELD '>' T_NUMBER { $$ = make_op_node(GT); $$->left_child = make_field_node($1); $$->right_child = make_int_node($3); } | T_FIELD '<' T_NUMBER { $$ = make_op_node(LT); $$->left_child = make_field_node($1); $$->right_child = make_int_node($3); } | T_FIELD T_NOT_EQ T_NUMBER { $$ = make_op_node(NEQ); $$->left_child = make_field_node($1); $$->right_child = make_int_node($3); } | T_FIELD T_GT_EQ T_NUMBER { $$ = make_op_node(GT_EQ); $$->left_child = make_field_node($1); $$->right_child = make_int_node($3); } | T_FIELD T_LT_EQ T_NUMBER { $$ = make_op_node(LT_EQ); $$->left_child = make_field_node($1); $$->right_child = make_int_node($3); } ; string_filter: T_FIELD '=' T_FIELD { $$ = make_op_node(EQ); $$->left_child = make_field_node($1); $$->right_child = make_string_node($3); } | T_FIELD T_NOT_EQ T_FIELD { $$ = make_op_node(NEQ); $$->left_child = make_field_node($1); $$->right_child = make_string_node($3); } ; %% zmap-1.1.0/src/probe_modules/000077500000000000000000000000001224250063200161025ustar00rootroot00000000000000zmap-1.1.0/src/probe_modules/module_icmp_echo.c000066400000000000000000000134441224250063200215470ustar00rootroot00000000000000/* * ZMap Copyright 2013 Regents of the University of Michigan * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy * of the License at http://www.apache.org/licenses/LICENSE-2.0 */ // probe module for performing ICMP echo request (ping) scans #include #include #include #include #include #include #include #include #include #include #include #include #include "probe_modules.h" #include "../fieldset.h" #include "packet.h" #include "validate.h" probe_module_t module_icmp_echo; int icmp_echo_init_perthread(void* buf, macaddr_t *src, macaddr_t *gw, __attribute__((unused)) port_h_t dst_port) { memset(buf, 0, MAX_PACKET_SIZE); struct ethhdr *eth_header = (struct ethhdr *)buf; make_eth_header(eth_header, src, gw); struct iphdr *ip_header = (struct iphdr*)(ð_header[1]); uint16_t len = htons(sizeof(struct iphdr) + sizeof(struct icmp) - 8); make_ip_header(ip_header, IPPROTO_ICMP, len); struct icmp *icmp_header = (struct icmp*)(&ip_header[1]); make_icmp_header(icmp_header); return EXIT_SUCCESS; } int icmp_echo_make_packet(void *buf, ipaddr_n_t src_ip, ipaddr_n_t dst_ip, uint32_t *validation, __attribute__((unused))int probe_num) { struct ethhdr *eth_header = (struct ethhdr *)buf; struct iphdr *ip_header = (struct iphdr*)(ð_header[1]); struct icmp *icmp_header = (struct icmp*)(&ip_header[1]); uint16_t icmp_idnum = validation[2] & 0xFFFF; ip_header->saddr = src_ip; ip_header->daddr = dst_ip; icmp_header->icmp_id = icmp_idnum; icmp_header->icmp_cksum = 0; icmp_header->icmp_cksum = icmp_checksum((unsigned short *) icmp_header); ip_header->check = 0; ip_header->check = ip_checksum((unsigned short *) ip_header); return EXIT_SUCCESS; } void icmp_echo_print_packet(FILE *fp, void* packet) { struct ethhdr *ethh = (struct ethhdr *) packet; struct iphdr *iph = (struct iphdr *) ðh[1]; struct icmp *icmp_header = (struct icmp*)(&iph[1]); fprintf(fp, "icmp { type: %u | code: %u " "| checksum: %u | id: %u | seq: %u }\n", icmp_header->icmp_type, icmp_header->icmp_code, ntohs(icmp_header->icmp_cksum), ntohs(icmp_header->icmp_id), ntohs(icmp_header->icmp_seq)); fprintf_ip_header(fp, iph); fprintf_eth_header(fp, ethh); fprintf(fp, "------------------------------------------------------\n"); } int icmp_validate_packet(const struct iphdr *ip_hdr, uint32_t len, uint32_t *src_ip, uint32_t *validation) { if (ip_hdr->protocol != IPPROTO_ICMP) { return 0; } if ((4*ip_hdr->ihl + sizeof(struct icmphdr)) > len) { // buffer not large enough to contain expected icmp header return 0; } struct icmphdr *icmp_h = (struct icmphdr*)((char *)ip_hdr + 4*ip_hdr->ihl); uint16_t icmp_idnum = icmp_h->un.echo.id; // ICMP validation is tricky: for some packet types, we must look inside // the payload if (icmp_h->type == ICMP_TIME_EXCEEDED || icmp_h->type == ICMP_DEST_UNREACH) { if ((4*ip_hdr->ihl + sizeof(struct icmphdr) + sizeof(struct iphdr)) > len) { return 0; } struct iphdr *ip_inner = (struct iphdr *)(icmp_h + 1); if ((4*ip_hdr->ihl + sizeof(struct icmphdr) + 4*ip_inner->ihl + sizeof(struct icmphdr)) > len) { return 0; } struct icmphdr *icmp_inner = (struct icmphdr*)((char *)ip_inner + 4 *ip_hdr->ihl); // Regenerate validation and icmp id based off inner payload icmp_idnum = icmp_inner->un.echo.id; *src_ip = ip_inner->daddr; validate_gen(ip_hdr->daddr, ip_inner->daddr, (uint8_t *)validation); } // validate icmp id if (icmp_idnum != (validation[2] & 0xFFFF)) { return 0; } return 1; } void icmp_echo_process_packet(const u_char *packet, __attribute__((unused)) uint32_t len, fieldset_t *fs) { struct iphdr *ip_hdr = (struct iphdr *)&packet[sizeof(struct ethhdr)]; struct icmphdr *icmp_hdr = (struct icmphdr*)((char *)ip_hdr + 4 *ip_hdr->ihl); fs_add_uint64(fs, "type", icmp_hdr->type); fs_add_uint64(fs, "code", icmp_hdr->code); fs_add_uint64(fs, "icmp-id", ntohs(icmp_hdr->un.echo.id)); fs_add_uint64(fs, "seq", ntohs(icmp_hdr->un.echo.sequence)); switch (icmp_hdr->type) { case ICMP_ECHOREPLY: fs_add_string(fs, "classification", (char*) "echoreply", 0); fs_add_uint64(fs, "success", 1); case ICMP_UNREACH: fs_add_string(fs, "classification", (char*) "unreach", 0); fs_add_uint64(fs, "success", 0); case ICMP_SOURCEQUENCH: fs_add_string(fs, "classification", (char*) "sourcequench", 0); fs_add_uint64(fs, "success", 0); case ICMP_REDIRECT: fs_add_string(fs, "classification", (char*) "redirect", 0); fs_add_uint64(fs, "success", 0); case ICMP_TIMXCEED: fs_add_string(fs, "classification", (char*) "timxceed", 0); fs_add_uint64(fs, "success", 0); default: fs_add_string(fs, "classification", (char*) "other", 0); fs_add_uint64(fs, "success", 0); } } fielddef_t fields[] = { {.name="type", .type="int", .desc="icmp message type"}, {.name="code", .type="int", .desc="icmp message sub type code"}, {.name="icmp-id", .type="int", .desc="icmp id number"}, {.name="seq", .type="int", .desc="icmp sequence number"}, {.name="classification", .type="string", .desc="probe module classification"}, {.name="success", .type="int", .desc="did probe module classify response as success"} }; probe_module_t module_icmp_echo = { .name = "icmp_echoscan", .packet_length = 62, .pcap_filter = "icmp and icmp[0]!=8", .pcap_snaplen = 96, .port_args = 0, .thread_initialize = &icmp_echo_init_perthread, .make_packet = &icmp_echo_make_packet, .print_packet = &icmp_echo_print_packet, .process_packet = &icmp_echo_process_packet, .validate_packet = &icmp_validate_packet, .close = NULL, .fields = fields, .numfields = 6}; zmap-1.1.0/src/probe_modules/module_tcp_synscan.c000066400000000000000000000125541224250063200221460ustar00rootroot00000000000000/* * ZMap Copyright 2013 Regents of the University of Michigan * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy * of the License at http://www.apache.org/licenses/LICENSE-2.0 */ // probe module for performing TCP SYN scans #include #include #include #include #include #include #include #include #include #include #include #include #include "../fieldset.h" #include "probe_modules.h" #include "packet.h" probe_module_t module_tcp_synscan; static uint32_t num_ports; int synscan_global_initialize(struct state_conf *state) { num_ports = state->source_port_last - state->source_port_first + 1; return EXIT_SUCCESS; } int synscan_init_perthread(void* buf, macaddr_t *src, macaddr_t *gw, port_h_t dst_port) { memset(buf, 0, MAX_PACKET_SIZE); struct ethhdr *eth_header = (struct ethhdr *)buf; make_eth_header(eth_header, src, gw); struct iphdr *ip_header = (struct iphdr*)(ð_header[1]); uint16_t len = htons(sizeof(struct iphdr) + sizeof(struct tcphdr)); make_ip_header(ip_header, IPPROTO_TCP, len); struct tcphdr *tcp_header = (struct tcphdr*)(&ip_header[1]); make_tcp_header(tcp_header, dst_port); return EXIT_SUCCESS; } int synscan_make_packet(void *buf, ipaddr_n_t src_ip, ipaddr_n_t dst_ip, uint32_t *validation, int probe_num) { struct ethhdr *eth_header = (struct ethhdr *)buf; struct iphdr *ip_header = (struct iphdr*)(ð_header[1]); struct tcphdr *tcp_header = (struct tcphdr*)(&ip_header[1]); uint32_t tcp_seq = validation[0]; ip_header->saddr = src_ip; ip_header->daddr = dst_ip; tcp_header->source = htons(get_src_port(num_ports, probe_num, validation)); tcp_header->seq = tcp_seq; tcp_header->check = 0; tcp_header->check = tcp_checksum(sizeof(struct tcphdr), ip_header->saddr, ip_header->daddr, tcp_header); ip_header->check = 0; ip_header->check = ip_checksum((unsigned short *) ip_header); return EXIT_SUCCESS; } void synscan_print_packet(FILE *fp, void* packet) { struct ethhdr *ethh = (struct ethhdr *) packet; struct iphdr *iph = (struct iphdr *) ðh[1]; struct tcphdr *tcph = (struct tcphdr *) &iph[1]; fprintf(fp, "tcp { source: %u | dest: %u | seq: %u | checksum: %u }\n", ntohs(tcph->source), ntohs(tcph->dest), ntohl(tcph->seq), ntohl(tcph->check)); fprintf_ip_header(fp, iph); fprintf_eth_header(fp, ethh); fprintf(fp, "------------------------------------------------------\n"); } int synscan_validate_packet(const struct iphdr *ip_hdr, uint32_t len, __attribute__((unused))uint32_t *src_ip, uint32_t *validation) { if (ip_hdr->protocol != IPPROTO_TCP) { return 0; } if ((4*ip_hdr->ihl + sizeof(struct tcphdr)) > len) { // buffer not large enough to contain expected tcp header return 0; } struct tcphdr *tcp = (struct tcphdr*)((char *)ip_hdr + 4*ip_hdr->ihl); uint16_t sport = tcp->source; uint16_t dport = tcp->dest; // validate source port if (ntohs(sport) != zconf.target_port) { return 0; } // validate destination port if (!check_dst_port(ntohs(dport), num_ports, validation)) { return 0; } // validate tcp acknowledgement number if (htonl(tcp->ack_seq) != htonl(validation[0])+1) { return 0; } return 1; } void synscan_process_packet(const u_char *packet, __attribute__((unused)) uint32_t len, fieldset_t *fs) { struct iphdr *ip_hdr = (struct iphdr *)&packet[sizeof(struct ethhdr)]; struct tcphdr *tcp = (struct tcphdr*)((char *)ip_hdr + 4*ip_hdr->ihl); fs_add_uint64(fs, "sport", (uint64_t) ntohs(tcp->source)); fs_add_uint64(fs, "dport", (uint64_t) ntohs(tcp->dest)); fs_add_uint64(fs, "seqnum", (uint64_t) ntohl(tcp->seq)); fs_add_uint64(fs, "acknum", (uint64_t) ntohl(tcp->ack_seq)); fs_add_uint64(fs, "window", (uint64_t) ntohs(tcp->window)); if (tcp->rst) { // RST packet fs_add_string(fs, "classification", (char*) "rst", 0); fs_add_uint64(fs, "success", 0); } else { // SYNACK packet fs_add_string(fs, "classification", (char*) "synack", 0); fs_add_uint64(fs, "success", 1); } } static fielddef_t fields[] = { {.name = "sport", .type = "int", .desc = "TCP source port"}, {.name = "dport", .type = "int", .desc = "TCP destination port"}, {.name = "seqnum", .type = "int", .desc = "TCP sequence number"}, {.name = "acknum", .type = "int", .desc = "TCP acknowledgement number"}, {.name = "window", .type = "int", .desc = "TCP window"}, {.name = "classification", .type="string", .desc = "packet classification"}, {.name = "success", .type="int", .desc = "is response considered success"} }; probe_module_t module_tcp_synscan = { .name = "tcp_synscan", .packet_length = 54, .pcap_filter = "tcp && tcp[13] & 4 != 0 || tcp[13] == 18", .pcap_snaplen = 96, .port_args = 1, .global_initialize = &synscan_global_initialize, .thread_initialize = &synscan_init_perthread, .make_packet = &synscan_make_packet, .print_packet = &synscan_print_packet, .process_packet = &synscan_process_packet, .validate_packet = &synscan_validate_packet, .close = NULL, .helptext = "Probe module that sends a TCP SYN packet to a specific " "port. Possible classifications are: synack and rst. A " "SYN-ACK packet is considered a success and a reset packet " "is considered a failed response.", .fields = fields, .numfields = 7}; zmap-1.1.0/src/probe_modules/module_udp.c000066400000000000000000000242311224250063200204050ustar00rootroot00000000000000/* * ZMap Copyright 2013 Regents of the University of Michigan * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy * of the License at http://www.apache.org/licenses/LICENSE-2.0 */ /* send module for performing arbitrary UDP scans */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include "probe_modules.h" #include "packet.h" #include "logger.h" #define MAX_UDP_PAYLOAD_LEN 1472 #define UNUSED __attribute__((unused)) char *udp_send_msg = NULL; int udp_send_msg_len = 0; const char *udp_send_msg_default = "GET / HTTP/1.1\r\nHost: www\r\n\r\n"; const char *udp_unreach_strings[] = { "network unreachable", "host unreachable", "protocol unreachable", "port unreachable", "fragments required", "source route failed", "network unknown", "host unknown", "source host isolated", "network admin. prohibited", "host admin. prohibited", "network unreachable TOS", "host unreachable TOS", "communication admin. prohibited", "host presdence violation", "precedence cutoff"}; static int num_ports; probe_module_t module_udp; int udp_global_initialize(struct state_conf *conf) { char *args, *c; int i; unsigned int n; FILE *inp; num_ports = conf->source_port_last - conf->source_port_first + 1; udp_send_msg = strdup(udp_send_msg_default); udp_send_msg_len = strlen(udp_send_msg); if (!(conf->probe_args && strlen(conf->probe_args) > 0)) return(0); args = strdup(conf->probe_args); if (! args) exit(1); c = strchr(args, ':'); if (! c) { free(args); free(udp_send_msg); log_fatal("udp", "unknown UDP probe specification (expected file:/path or text:STRING or hex:01020304)"); exit(1); } *c++ = 0; if (strcmp(args, "text") == 0) { free(udp_send_msg); udp_send_msg = strdup(c); udp_send_msg_len = strlen(udp_send_msg); } else if (strcmp(args, "file") == 0) { inp = fopen(c, "rb"); if (!inp) { free(args); free(udp_send_msg); log_fatal("udp", "could not open UDP data file '%s'\n", c); exit(1); } free(udp_send_msg); udp_send_msg = malloc(MAX_UDP_PAYLOAD_LEN); if (! udp_send_msg) { free(args); log_fatal("udp", "failed to malloc payload buffer"); exit(1); } udp_send_msg_len = fread(udp_send_msg, 1, MAX_UDP_PAYLOAD_LEN, inp); fclose(inp); } else if (strcmp(args, "hex") == 0) { udp_send_msg_len = strlen(c) / 2; free(udp_send_msg); udp_send_msg = malloc(udp_send_msg_len); if (! udp_send_msg) { free(args); log_fatal("udp", "failed to malloc payload buffer"); exit(1); } for (i=0; i < udp_send_msg_len; i++) { if (sscanf(c + (i*2), "%2x", &n) != 1) { free(args); free(udp_send_msg); log_fatal("udp", "non-hex character: '%c'", c[i*2]); exit(1); } udp_send_msg[i] = (n & 0xff); } } else { log_fatal("udp", "unknown UDP probe specification " "(expected file:/path, text:STRING, " "or hex:01020304)"); free(udp_send_msg); free(args); exit(1); } if (udp_send_msg_len > MAX_UDP_PAYLOAD_LEN) { log_warn("udp", "warning: reducing UDP payload to %d " "bytes (from %d) to fit on the wire\n", MAX_UDP_PAYLOAD_LEN, udp_send_msg_len); udp_send_msg_len = MAX_UDP_PAYLOAD_LEN; } free(args); return(0); } int udp_global_cleanup(__attribute__((unused)) struct state_conf *zconf, __attribute__((unused)) struct state_send *zsend, __attribute__((unused)) struct state_recv *zrecv) { if (udp_send_msg) free(udp_send_msg); udp_send_msg = NULL; return(0); } int udp_init_perthread(void* buf, macaddr_t *src, macaddr_t *gw, __attribute__((unused)) port_h_t dst_port) { memset(buf, 0, MAX_PACKET_SIZE); struct ethhdr *eth_header = (struct ethhdr *)buf; make_eth_header(eth_header, src, gw); struct iphdr *ip_header = (struct iphdr*)(ð_header[1]); uint16_t len = htons(sizeof(struct iphdr) + sizeof(struct udphdr) + udp_send_msg_len); make_ip_header(ip_header, IPPROTO_UDP, len); struct udphdr *udp_header = (struct udphdr*)(&ip_header[1]); len = sizeof(struct udphdr) + udp_send_msg_len; make_udp_header(udp_header, zconf.target_port, len); char* payload = (char*)(&udp_header[1]); module_udp.packet_length = sizeof(struct ethhdr) + sizeof(struct iphdr) + sizeof(struct udphdr) + udp_send_msg_len; assert(module_udp.packet_length <= MAX_PACKET_SIZE); memcpy(payload, udp_send_msg, udp_send_msg_len); return EXIT_SUCCESS; } int udp_make_packet(void *buf, ipaddr_n_t src_ip, ipaddr_n_t dst_ip, uint32_t *validation, int probe_num) { struct ethhdr *eth_header = (struct ethhdr *)buf; struct iphdr *ip_header = (struct iphdr*)(ð_header[1]); struct udphdr *udp_header = (struct udphdr*)(&ip_header[1]); ip_header->saddr = src_ip; ip_header->daddr = dst_ip; udp_header->source = htons(get_src_port(num_ports, probe_num, validation)); ip_header->check = 0; ip_header->check = ip_checksum((unsigned short *) ip_header); return EXIT_SUCCESS; } void udp_print_packet(FILE *fp, void* packet) { struct ethhdr *ethh = (struct ethhdr *) packet; struct iphdr *iph = (struct iphdr *) ðh[1]; struct udphdr *udph = (struct udphdr*)(&iph[1]); fprintf(fp, "udp { source: %u | dest: %u | checksum: %u }\n", ntohs(udph->source), ntohs(udph->dest), ntohl(udph->check)); fprintf_ip_header(fp, iph); fprintf_eth_header(fp, ethh); fprintf(fp, "------------------------------------------------------\n"); } void udp_process_packet(const u_char *packet, UNUSED uint32_t len, fieldset_t *fs) { struct iphdr *ip_hdr = (struct iphdr *)&packet[sizeof(struct ethhdr)]; if (ip_hdr->protocol == IPPROTO_UDP) { struct udphdr *udp = (struct udphdr *)((char *)ip_hdr + ip_hdr->ihl * 4); fs_add_string(fs, "classification", (char*) "udp", 0); fs_add_uint64(fs, "success", 1); fs_add_uint64(fs, "sport", ntohs(udp->source)); fs_add_uint64(fs, "dport", ntohs(udp->dest)); fs_add_null(fs, "icmp_responder"); fs_add_null(fs, "icmp_type"); fs_add_null(fs, "icmp_code"); fs_add_null(fs, "icmp_unreach_str"); fs_add_binary(fs, "data", (ntohs(udp->len) - sizeof(struct udphdr)), (void*) &udp[1], 0); } else if (ip_hdr->protocol == IPPROTO_ICMP) { struct icmphdr *icmp = (struct icmphdr *)((char *)ip_hdr + ip_hdr->ihl * 4); struct iphdr *ip_inner = (struct iphdr*)&icmp[1]; // ICMP unreach comes from another server (not the one we sent a probe to); // But we will fix up saddr to be who we sent the probe to, in case you care. fs_modify_string(fs, "saddr", make_ip_str(ip_inner->daddr), 1); fs_add_string(fs, "classification", (char*) "icmp-unreach", 0); fs_add_uint64(fs, "success", 0); fs_add_null(fs, "sport"); fs_add_null(fs, "dport"); fs_add_string(fs, "icmp_responder", make_ip_str(ip_hdr->saddr), 1); fs_add_uint64(fs, "icmp_type", icmp->type); fs_add_uint64(fs, "icmp_code", icmp->code); if (icmp->code <= ICMP_PREC_CUTOFF) { fs_add_string(fs, "icmp_unreach_str", (char *)udp_unreach_strings[icmp->code], 0); } else { fs_add_string(fs, "icmp_unreach_str", (char *)"unknown", 0); } fs_add_null(fs, "data"); } else { fs_add_string(fs, "classification", (char*) "other", 0); fs_add_uint64(fs, "success", 0); fs_add_null(fs, "sport"); fs_add_null(fs, "dport"); fs_add_null(fs, "icmp_responder"); fs_add_null(fs, "icmp_type"); fs_add_null(fs, "icmp_code"); fs_add_null(fs, "icmp_unreach_str"); fs_add_null(fs, "data"); } } int udp_validate_packet(const struct iphdr *ip_hdr, uint32_t len, __attribute__((unused))uint32_t *src_ip, uint32_t *validation) { uint16_t dport, sport; if (ip_hdr->protocol == IPPROTO_UDP) { if ((4*ip_hdr->ihl + sizeof(struct udphdr)) > len) { // buffer not large enough to contain expected udp header return 0; } struct udphdr *udp = (struct udphdr*)((char *)ip_hdr + 4*ip_hdr->ihl); sport = ntohs(udp->dest); dport = ntohs(udp->source); } else if (ip_hdr->protocol == IPPROTO_ICMP) { // UDP can return ICMP Destination unreach // IP( ICMP( IP( UDP ) ) ) for a destination unreach uint32_t min_len = 4*ip_hdr->ihl + sizeof(struct icmphdr) + sizeof(struct iphdr) + sizeof(struct udphdr); if (len < min_len) { // Not enough information for us to validate return 0; } struct icmphdr *icmp = (struct icmphdr*)((char *)ip_hdr + 4*ip_hdr->ihl); if (icmp->type != ICMP_DEST_UNREACH) { return 0; } struct iphdr *ip_inner = (struct iphdr*)&icmp[1]; // Now we know the actual inner ip length, we should recheck the buffer if (len < 4*ip_inner->ihl - sizeof(struct iphdr) + min_len) { return 0; } // This is the packet we sent struct udphdr *udp = (struct udphdr *)((char*)ip_inner + 4*ip_inner->ihl); sport = ntohs(udp->source); dport = ntohs(udp->dest); } else { return 0; } if (dport != zconf.target_port) { return 0; } if (!check_dst_port(sport, num_ports, validation)) { return 0; } return 1; } static fielddef_t fields[] = { {.name = "classification", .type="string", .desc = "packet classification"}, {.name = "success", .type="int", .desc = "is response considered success"}, {.name = "sport", .type = "int", .desc = "UDP source port"}, {.name = "dport", .type = "int", .desc = "UDP destination port"}, {.name = "icmp_responder", .type = "string", .desc = "Source IP of ICMP_UNREACH message"}, {.name = "icmp_type", .type = "int", .desc = "icmp message type"}, {.name = "icmp_code", .type = "int", .desc = "icmp message sub type code"}, {.name = "icmp_unreach_str", .type = "string", .desc = "for icmp_unreach responses, the string version of icmp_code (e.g. network-unreach)"}, {.name = "data", .type="binary", .desc = "UDP payload"} }; probe_module_t module_udp = { .name = "udp", .packet_length = 1, .pcap_filter = "udp || icmp", .pcap_snaplen = 1500, .port_args = 1, .thread_initialize = &udp_init_perthread, .global_initialize = &udp_global_initialize, .make_packet = &udp_make_packet, .print_packet = &udp_print_packet, .validate_packet = &udp_validate_packet, .process_packet = &udp_process_packet, .close = &udp_global_cleanup, .fields = fields, .numfields = sizeof(fields)/sizeof(fields[0]) }; zmap-1.1.0/src/probe_modules/packet.c000066400000000000000000000075651224250063200175320ustar00rootroot00000000000000/* * ZMap Copyright 2013 Regents of the University of Michigan * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy * of the License at http://www.apache.org/licenses/LICENSE-2.0 */ #include "packet.h" #include #include #include #include #include #include #include #include #include #include #include #include "state.h" void print_macaddr(struct ifreq* i) { printf("Device %s -> Ethernet %02x:%02x:%02x:%02x:%02x:%02x\n", i->ifr_name, (int) ((unsigned char *) &i->ifr_hwaddr.sa_data)[0], (int) ((unsigned char *) &i->ifr_hwaddr.sa_data)[1], (int) ((unsigned char *) &i->ifr_hwaddr.sa_data)[2], (int) ((unsigned char *) &i->ifr_hwaddr.sa_data)[3], (int) ((unsigned char *) &i->ifr_hwaddr.sa_data)[4], (int) ((unsigned char *) &i->ifr_hwaddr.sa_data)[5]); } void fprintf_ip_header(FILE *fp, struct iphdr *iph) { struct in_addr *s = (struct in_addr *) &(iph->saddr); struct in_addr *d = (struct in_addr *) &(iph->daddr); char srcip[20]; char dstip[20]; // inet_ntoa is a const char * so we if just call it in // fprintf, you'll get back wrong results since we're // calling it twice. strncpy(srcip, inet_ntoa(*s), 19); strncpy(dstip, inet_ntoa(*d), 19); fprintf(fp, "ip { saddr: %s | daddr: %s | checksum: %u }\n", srcip, dstip, ntohl(iph->check)); } void fprintf_eth_header(FILE *fp, struct ethhdr *ethh) { fprintf(fp, "eth { shost: %02x:%02x:%02x:%02x:%02x:%02x | " "dhost: %02x:%02x:%02x:%02x:%02x:%02x }\n", (int) ((unsigned char *) ethh->h_source)[0], (int) ((unsigned char *) ethh->h_source)[1], (int) ((unsigned char *) ethh->h_source)[2], (int) ((unsigned char *) ethh->h_source)[3], (int) ((unsigned char *) ethh->h_source)[4], (int) ((unsigned char *) ethh->h_source)[5], (int) ((unsigned char *) ethh->h_dest)[0], (int) ((unsigned char *) ethh->h_dest)[1], (int) ((unsigned char *) ethh->h_dest)[2], (int) ((unsigned char *) ethh->h_dest)[3], (int) ((unsigned char *) ethh->h_dest)[4], (int) ((unsigned char *) ethh->h_dest)[5]); } void make_eth_header(struct ethhdr *ethh, macaddr_t *src, macaddr_t *dst) { memcpy(ethh->h_source, src, ETH_ALEN); memcpy(ethh->h_dest, dst, ETH_ALEN); ethh->h_proto = htons(ETH_P_IP); } void make_ip_header(struct iphdr *iph, uint8_t protocol, uint16_t len) { iph->ihl = 5; // Internet Header Length iph->version = 4; // IPv4 iph->tos = 0; // Type of Service iph->tot_len = len; iph->id = htons(54321); // identification number iph->frag_off = 0; //fragmentation falg iph->ttl = MAXTTL; // time to live (TTL) iph->protocol = protocol; // upper layer protocol => TCP // we set the checksum = 0 for now because that's // what it needs to be when we run the IP checksum iph->check = 0; } void make_icmp_header(struct icmp *buf) { buf->icmp_type = ICMP_ECHO; buf->icmp_code = 0; buf->icmp_seq = 0; } void make_tcp_header(struct tcphdr *tcp_header, port_h_t dest_port) { tcp_header->seq = random(); tcp_header->ack_seq = 0; tcp_header->res2 = 0; tcp_header->doff = 5; // data offset tcp_header->syn = 1; tcp_header->window = htons(65535); // largest possible window tcp_header->check = 0; tcp_header->urg_ptr = 0; tcp_header->dest = htons(dest_port); } void make_udp_header(struct udphdr *udp_header, port_h_t dest_port, uint16_t len) { udp_header->dest = htons(dest_port); udp_header->len = htons(len); // checksum ignored in IPv4 if 0 udp_header->check = 0; } // Note: caller must free return value char *make_ip_str(uint32_t ip) { struct in_addr t; t.s_addr = ip; const char *temp = inet_ntoa(t); char *retv = malloc(strlen(temp)+1); assert (retv); strcpy(retv, temp); return retv; } zmap-1.1.0/src/probe_modules/packet.h000066400000000000000000000060031224250063200175210ustar00rootroot00000000000000#include "state.h" #include #include #include #include #include #ifndef PACKET_H #define PACKET_H #define MAX_PACKET_SIZE 4096 typedef unsigned short __attribute__((__may_alias__)) alias_unsigned_short; void make_eth_header(struct ethhdr *ethh, macaddr_t *src, macaddr_t *dst); void make_ip_header(struct iphdr *iph, uint8_t, uint16_t); void make_tcp_header(struct tcphdr*, port_h_t); void make_icmp_header(struct icmp *); void make_udp_header(struct udphdr *udp_header, port_h_t dest_port, uint16_t len); void fprintf_ip_header(FILE *fp, struct iphdr *iph); void fprintf_eth_header(FILE *fp, struct ethhdr *ethh); static inline unsigned short in_checksum(unsigned short *ip_pkt, int len) { unsigned long sum = 0; for (int nwords = len/2; nwords > 0; nwords--) { sum += *ip_pkt++; } sum = (sum >> 16) + (sum & 0xffff); sum += (sum >> 16); return (unsigned short) (~sum); } __attribute__((unused)) static inline unsigned short ip_checksum( unsigned short *buf) { return in_checksum(buf, (int) sizeof(struct iphdr)); } __attribute__((unused)) static inline unsigned short icmp_checksum( unsigned short *buf) { return in_checksum(buf, (int) sizeof(struct icmp)); } static __attribute__((unused)) uint16_t tcp_checksum(unsigned short len_tcp, uint32_t saddr, uint32_t daddr, struct tcphdr *tcp_pkt) { alias_unsigned_short *src_addr = (alias_unsigned_short *) &saddr; alias_unsigned_short *dest_addr = (alias_unsigned_short *) &daddr; unsigned char prot_tcp = 6; unsigned long sum = 0; int nleft = len_tcp; unsigned short *w; w = (unsigned short *) tcp_pkt; // calculate the checksum for the tcp header and tcp data while(nleft > 1) { sum += *w++; nleft -= 2; } // if nleft is 1 there ist still on byte left. // We add a padding byte (0xFF) to build a 16bit word if (nleft > 0) { sum += *w & ntohs(0xFF00); } // add the pseudo header sum += src_addr[0]; sum += src_addr[1]; sum += dest_addr[0]; sum += dest_addr[1]; sum += htons(len_tcp); sum += htons(prot_tcp); sum = (sum >> 16) + (sum & 0xFFFF); sum += (sum >> 16); // Take the one's complement of sum return (unsigned short) (~sum); } // Returns 0 if dst_port is outside the expected valid range, non-zero otherwise static __attribute__((unused)) inline int check_dst_port(uint16_t port, int num_ports, uint32_t *validation) { if (port > zconf.source_port_last || port < zconf.source_port_first) { return -1; } int32_t to_validate = port - zconf.source_port_first; int32_t min = validation[1] % num_ports; int32_t max = (validation[1] + zconf.packet_streams - 1) % num_ports; return (((max - min) % num_ports) >= ((to_validate - min) % num_ports)); } static __attribute__((unused)) inline uint16_t get_src_port(int num_ports, int probe_num, uint32_t *validation) { return zconf.source_port_first + ((validation[1] + probe_num) % num_ports); } // Note: caller must free return value char *make_ip_str(uint32_t ip); #endif zmap-1.1.0/src/probe_modules/probe_modules.c000066400000000000000000000071721224250063200211140ustar00rootroot00000000000000/* * ZMap Copyright 2013 Regents of the University of Michigan * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy * of the License at http://www.apache.org/licenses/LICENSE-2.0 */ #include #include #include #include #include #include #include #include #include #include #include "../../lib/logger.h" #include "../fieldset.h" #include "probe_modules.h" #include "packet.h" extern probe_module_t module_tcp_synscan; extern probe_module_t module_icmp_echo; extern probe_module_t module_udp; // ADD YOUR MODULE HERE probe_module_t* probe_modules[] = { &module_tcp_synscan, &module_icmp_echo, &module_udp // ADD YOUR MODULE HERE }; probe_module_t* get_probe_module_by_name(const char* name) { int len = (int) (sizeof(probe_modules)/sizeof(probe_modules[0])); for (int i=0; i < len; i++) { if (!strcmp(probe_modules[i]->name, name)) { return probe_modules[i]; } } return NULL; } void print_probe_modules(void) { int len = (int) (sizeof(probe_modules)/sizeof(probe_modules[0])); for (int i=0; i < len; i++) { printf("%s\n", probe_modules[i]->name); } } void fs_add_ip_fields(fieldset_t *fs, struct iphdr *ip) { // WARNING: you must update fs_ip_fields_len as well // as the definitions set (ip_fiels) if you // change the fields added below: fs_add_string(fs, "saddr", make_ip_str(ip->saddr), 1); fs_add_uint64(fs, "saddr-raw", (uint64_t) ip->saddr); fs_add_string(fs, "daddr", make_ip_str(ip->daddr), 1); fs_add_uint64(fs, "daddr-raw", (uint64_t) ip->daddr); fs_add_uint64(fs, "ipid", ntohs(ip->id)); fs_add_uint64(fs, "ttl", ip->ttl); } #define TIMESTR_LEN 55 void fs_add_system_fields(fieldset_t *fs, int is_repeat, int in_cooldown) { fs_add_uint64(fs, "repeat", is_repeat); fs_add_uint64(fs, "cooldown", in_cooldown); char *timestr = malloc(TIMESTR_LEN+1); char *timestr_ms = malloc(TIMESTR_LEN+1); if (!timestr || !timestr_ms) { log_fatal("recv", "unable to allocate memory for " "timestamp string in fieldset."); } struct timeval t; gettimeofday(&t, NULL); struct tm *ptm = localtime(&t.tv_sec); strftime(timestr, TIMESTR_LEN, "%Y-%m-%dT%H:%M:%S.%%03d%z", ptm); snprintf(timestr_ms, TIMESTR_LEN, timestr, t.tv_usec/1000); free(timestr); fs_add_string(fs, "timestamp-str", timestr_ms, 1); fs_add_uint64(fs, "timestamp-ts", (uint64_t) t.tv_sec); fs_add_uint64(fs, "timestamp-us", (uint64_t) t.tv_usec); } int ip_fields_len = 6; fielddef_t ip_fields[] = { {.name="saddr", .type="string", .desc="source IP address of response"}, {.name="saddr-raw", .type="int", .desc="network order integer form of source IP address"}, {.name="daddr", .type="string", .desc="destination IP address of response"}, {.name="daddr-raw", .type="int", .desc="network order integer form of destination IP address"}, {.name="ipid", .type="int", .desc="IP identification number of response"}, {.name="ttl", .type="int", .desc="time-to-live of response packet"} }; int sys_fields_len = 5; fielddef_t sys_fields[] = { {.name="repeat", .type="int", .desc="Is response a repeat response from host"}, {.name="cooldown", .type="int", .desc="Was response received during the cooldown period"}, {.name="timestamp-str", .type="string", .desc="timestamp of when response arrived in ISO8601 format."}, {.name="timestamp-ts", .type="int", .desc="timestamp of when response arrived in seconds since Epoch"}, {.name="timestamp-us", .type="int", .desc="microsecond part of timestamp (e.g. microseconds since 'timestamp-ts')"} }; zmap-1.1.0/src/probe_modules/probe_modules.h000066400000000000000000000034621224250063200211170ustar00rootroot00000000000000#include "../state.h" #include "../fieldset.h" #ifndef PROBE_MODULES_H #define PROBE_MODULES_H typedef struct probe_response_type { const uint8_t is_success; const char *name; } response_type_t; typedef int (*probe_global_init_cb)(struct state_conf *); typedef int (*probe_thread_init_cb)(void* packetbuf, macaddr_t* src_mac, macaddr_t* gw_mac, port_n_t src_port); typedef int (*probe_make_packet_cb)(void* packetbuf, ipaddr_n_t src_ip, ipaddr_n_t dst_ip, uint32_t *validation, int probe_num); typedef void (*probe_print_packet_cb)(FILE *, void* packetbuf); typedef int (*probe_close_cb)(struct state_conf*, struct state_send*, struct state_recv*); typedef int (*probe_validate_packet_cb)(const struct iphdr *ip_hdr, uint32_t len, uint32_t *src_ip, uint32_t *validation); typedef void (*probe_classify_packet_cb)(const u_char* packetbuf, uint32_t len, fieldset_t*); typedef struct probe_module { const char *name; size_t packet_length; const char *pcap_filter; size_t pcap_snaplen; // Should ZMap complain if the user hasn't specified valid // source and target port numbers? uint8_t port_args; probe_global_init_cb global_initialize; probe_thread_init_cb thread_initialize; probe_make_packet_cb make_packet; probe_print_packet_cb print_packet; probe_validate_packet_cb validate_packet; probe_classify_packet_cb process_packet; probe_close_cb close; fielddef_t *fields; int numfields; const char *helptext; } probe_module_t; probe_module_t* get_probe_module_by_name(const char*); void fs_add_ip_fields(fieldset_t *fs, struct iphdr *ip); void fs_add_system_fields(fieldset_t *fs, int is_repeat, int in_cooldown); void print_probe_modules(void); extern int ip_fields_len; extern int sys_fields_len; extern fielddef_t ip_fields[]; extern fielddef_t sys_fields[]; #endif // HEADER_PROBE_MODULES_H zmap-1.1.0/src/recv.c000066400000000000000000000154201224250063200143500ustar00rootroot00000000000000/* * ZMap Copyright 2013 Regents of the University of Michigan * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy * of the License at http://www.apache.org/licenses/LICENSE-2.0 */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "../lib/logger.h" #include "../lib/pbm.h" #include "state.h" #include "validate.h" #include "fieldset.h" #include "expression.h" #include "probe_modules/probe_modules.h" #include "output_modules/output_modules.h" #define PCAP_PROMISC 1 #define PCAP_TIMEOUT 1000 static uint32_t num_src_ports; static pcap_t *pc = NULL; // bitmap of observed IP addresses static uint64_t **seen = NULL; static u_char fake_eth_hdr[65535]; void packet_cb(u_char __attribute__((__unused__)) *user, const struct pcap_pkthdr *p, const u_char *bytes) { if (!p) { return; } if (zrecv.success_unique >= zconf.max_results) { // Libpcap can process multiple packets per pcap_dispatch; // we need to throw out results once we've // gotten our --max-results worth. return; } // length of entire packet captured by libpcap uint32_t buflen = (uint32_t) p->caplen; if ((sizeof(struct iphdr) + (zconf.send_ip_pkts ? 0 : sizeof(struct ethhdr))) > buflen) { // buffer not large enough to contain ethernet // and ip headers. further action would overrun buf return; } struct iphdr *ip_hdr = (struct iphdr *)&bytes[(zconf.send_ip_pkts ? 0 : sizeof(struct ethhdr))]; uint32_t src_ip = ip_hdr->saddr; uint32_t validation[VALIDATE_BYTES/sizeof(uint8_t)]; // TODO: for TTL exceeded messages, ip_hdr->saddr is going to be different // and we must calculate off potential payload message instead validate_gen(ip_hdr->daddr, ip_hdr->saddr, (uint8_t *)validation); if (!zconf.probe_module->validate_packet(ip_hdr, buflen - (zconf.send_ip_pkts ? 0 : sizeof(struct ethhdr)), &src_ip, validation)) { return; } int is_repeat = pbm_check(seen, ntohl(src_ip)); fieldset_t *fs = fs_new_fieldset(); fs_add_ip_fields(fs, ip_hdr); // HACK: // probe modules (for whatever reason) expect the full ethernet frame // in process_packet. For VPN, we only get back an IP frame. // Here, we fake an ethernet frame (which is initialized to // have ETH_P_IP proto and 00s for dest/src). if (zconf.send_ip_pkts) { if (buflen > sizeof(fake_eth_hdr)) { buflen = sizeof(fake_eth_hdr); } memcpy(&fake_eth_hdr[sizeof(struct ethhdr)], bytes, buflen); bytes = fake_eth_hdr; } zconf.probe_module->process_packet(bytes, buflen, fs); fs_add_system_fields(fs, is_repeat, zsend.complete); int success_index = zconf.fsconf.success_index; assert(success_index < fs->len); int is_success = fs_get_uint64_by_index(fs, success_index); if (is_success) { zrecv.success_total++; if (!is_repeat) { zrecv.success_unique++; pbm_set(seen, ntohl(src_ip)); } if (zsend.complete) { zrecv.cooldown_total++; if (!is_repeat) { zrecv.cooldown_unique++; } } } else { zrecv.failure_total++; } fieldset_t *o = NULL; // we need to translate the data provided by the probe module // into a fieldset that can be used by the output module if (!is_success && zconf.filter_unsuccessful) { goto cleanup; } if (is_repeat && zconf.filter_duplicates) { goto cleanup; } if (!evaluate_expression(zconf.filter.expression, fs)) { goto cleanup; } o = translate_fieldset(fs, &zconf.fsconf.translation); if (zconf.output_module && zconf.output_module->process_ip) { zconf.output_module->process_ip(o); } cleanup: fs_free(fs); free(o); if (zconf.output_module && zconf.output_module->update && !(zrecv.success_unique % zconf.output_module->update_interval)) { zconf.output_module->update(&zconf, &zsend, &zrecv); } } int recv_update_pcap_stats(void) { if (!pc) { return EXIT_FAILURE; } struct pcap_stat pcst; if (pcap_stats(pc, &pcst)) { log_error("recv", "unable to retrieve pcap statistics: %s", pcap_geterr(pc)); return EXIT_FAILURE; } else { zrecv.pcap_recv = pcst.ps_recv; zrecv.pcap_drop = pcst.ps_drop; zrecv.pcap_ifdrop = pcst.ps_ifdrop; } return EXIT_SUCCESS; } int recv_run(pthread_mutex_t *recv_ready_mutex) { log_debug("recv", "thread started"); num_src_ports = zconf.source_port_last - zconf.source_port_first + 1; log_debug("recv", "using dev %s", zconf.iface); if (!zconf.dryrun) { char errbuf[PCAP_ERRBUF_SIZE]; pc = pcap_open_live(zconf.iface, zconf.probe_module->pcap_snaplen, PCAP_PROMISC, PCAP_TIMEOUT, errbuf); if (pc == NULL) { log_fatal("recv", "could not open device %s: %s", zconf.iface, errbuf); } struct bpf_program bpf; if (pcap_compile(pc, &bpf, zconf.probe_module->pcap_filter, 1, 0) < 0) { log_fatal("recv", "couldn't compile filter"); } if (pcap_setfilter(pc, &bpf) < 0) { log_fatal("recv", "couldn't install filter"); } // set pcap_dispatch to not hang if it never receives any packets // this could occur if you ever scan a small number of hosts as // documented in issue #74. if (pcap_setnonblock (pc, 1, errbuf) == -1) { log_fatal("recv", "pcap_setnonblock error:%s", errbuf); } } if (zconf.send_ip_pkts) { struct ethhdr *eth = (struct ethhdr *)fake_eth_hdr; memset(fake_eth_hdr, 0, sizeof(fake_eth_hdr)); eth->h_proto = htons(ETH_P_IP); } // initialize paged bitmap seen = pbm_init(); log_debug("recv", "receiver ready"); if (zconf.filter_duplicates) { log_debug("recv", "duplicate responses will be excluded from output"); } else { log_debug("recv", "duplicate responses will be included in output"); } if (zconf.filter_unsuccessful) { log_debug("recv", "unsuccessful responses will be excluded from output"); } else { log_debug("recv", "unsuccessful responses will be included in output"); } pthread_mutex_lock(recv_ready_mutex); zconf.recv_ready = 1; pthread_mutex_unlock(recv_ready_mutex); zrecv.start = now(); if (zconf.max_results == 0) { zconf.max_results = -1; } do { if (zconf.dryrun) { sleep(1); } else { if (pcap_dispatch(pc, 0, packet_cb, NULL) == -1) { log_fatal("recv", "pcap_dispatch error"); } if (zconf.max_results && zrecv.success_unique >= zconf.max_results) { zsend.complete = 1; break; } } } while (!(zsend.complete && (now()-zsend.finish > zconf.cooldown_secs))); zrecv.finish = now(); // get final pcap statistics before closing recv_update_pcap_stats(); pcap_close(pc); zrecv.complete = 1; log_debug("recv", "thread finished"); return 0; } zmap-1.1.0/src/recv.h000066400000000000000000000006531224250063200143570ustar00rootroot00000000000000/* * ZMap Copyright 2013 Regents of the University of Michigan * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy * of the License at http://www.apache.org/licenses/LICENSE-2.0 */ #ifndef RECV_H #define RECV_H int recv_update_pcap_stats(void); int recv_run(pthread_mutex_t *recv_ready_mutex); #endif //_RECV_H zmap-1.1.0/src/send.c000066400000000000000000000213261224250063200143440ustar00rootroot00000000000000/* * ZMap Copyright 2013 Regents of the University of Michigan * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy * of the License at http://www.apache.org/licenses/LICENSE-2.0 */ #include "send.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "../lib/logger.h" #include "../lib/random.h" #include "../lib/blacklist.h" #include "cyclic.h" #include "state.h" #include "probe_modules/packet.h" #include "probe_modules/probe_modules.h" #include "validate.h" // lock to manage access to share send state (e.g. counters and cyclic) pthread_mutex_t send_mutex = PTHREAD_MUTEX_INITIALIZER; // lock to provide thread safety to the user provided send callback pthread_mutex_t syncb_mutex = PTHREAD_MUTEX_INITIALIZER; // globals to handle sending from multiple ip addresses (shared across threads) static uint16_t num_src_ports; static uint32_t num_addrs; static in_addr_t srcip_first; static in_addr_t srcip_last; // offset send addresses according to a random chosen per scan execution // in order to help prevent cross-scan interference static uint32_t srcip_offset; // global sender initialize (not thread specific) int send_init(void) { // generate a new primitive root and starting position cyclic_init(0, 0); zsend.first_scanned = cyclic_get_curr_ip(); // compute number of targets uint64_t allowed = blacklist_count_allowed(); if (allowed == (1LL << 32)) { zsend.targets = 0xFFFFFFFF; } else { zsend.targets = allowed; } if (zsend.targets > zconf.max_targets) { zsend.targets = zconf.max_targets; } // process the dotted-notation addresses passed to ZMAP and determine // the source addresses from which we'll send packets; srcip_first = inet_addr(zconf.source_ip_first); if (srcip_first == INADDR_NONE) { log_fatal("send", "invalid begin source ip address: `%s'", zconf.source_ip_first); } srcip_last = inet_addr(zconf.source_ip_last); if (srcip_last == INADDR_NONE) { log_fatal("send", "invalid end source ip address: `%s'", zconf.source_ip_last); } if (srcip_first == srcip_last) { srcip_offset = 0; num_addrs = 1; } else { srcip_offset = rand() % (srcip_last - srcip_first); num_addrs = ntohl(srcip_last) - ntohl(srcip_first) + 1; } // process the source port range that ZMap is allowed to use num_src_ports = zconf.source_port_last - zconf.source_port_first + 1; log_debug("send", "will send from %i address%s on %u source ports", num_addrs, ((num_addrs==1)?"":"es"), num_src_ports); // global initialization for send module assert(zconf.probe_module); if (zconf.probe_module->global_initialize) { zconf.probe_module->global_initialize(&zconf); } // concert specified bandwidth to packet rate if (zconf.bandwidth > 0) { int pkt_len = zconf.probe_module->packet_length; pkt_len *= 8; pkt_len += 8*24; // 7 byte MAC preamble, 1 byte Start frame, // 4 byte CRC, 12 byte inter-frame gap if (pkt_len < 84*8) { pkt_len = 84*8; } if (zconf.bandwidth / pkt_len > 0xFFFFFFFF) { zconf.rate = 0; } else { zconf.rate = zconf.bandwidth / pkt_len; if (zconf.rate == 0) { log_warn("send", "bandwidth %lu bit/s is slower than 1 pkt/s, " "setting rate to 1 pkt/s", zconf.bandwidth); zconf.rate = 1; } } log_debug("send", "using bandwidth %lu bits/s, rate set to %d pkt/s", zconf.bandwidth, zconf.rate); } if (zconf.dryrun) { log_info("send", "dryrun mode -- won't actually send packets"); } // initialize random validation key validate_init(); zsend.start = now(); return EXIT_SUCCESS; } int get_socket(void) { int sock = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL)); if (sock <= 0) { log_fatal("send", "couldn't create socket. " "Are you root? Error: %s\n", strerror(errno)); } return sock; } int get_dryrun_socket(void) { // we need a socket in order to gather details about the system // such as source MAC address and IP address. However, because // we don't want to require root access in order to run dryrun, // we just create a TCP socket. int sock = socket(AF_INET, SOCK_STREAM, 0); if (sock <= 0) { log_fatal("send", "couldn't create socket. " "Error: %s\n", strerror(errno)); } return sock; } static inline ipaddr_n_t get_src_ip(ipaddr_n_t dst, int local_offset) { if (srcip_first == srcip_last) { return srcip_first; } return htonl(((ntohl(dst) + srcip_offset + local_offset) % num_addrs)) + srcip_first; } // one sender thread int send_run(int sock) { log_debug("send", "thread started"); pthread_mutex_lock(&send_mutex); struct sockaddr_ll sockaddr; // get source interface index struct ifreq if_idx; memset(&if_idx, 0, sizeof(struct ifreq)); if (strlen(zconf.iface) >= IFNAMSIZ) { log_error("send", "device interface name (%s) too long\n", zconf.iface); return -1; } strncpy(if_idx.ifr_name, zconf.iface, IFNAMSIZ-1); if (ioctl(sock, SIOCGIFINDEX, &if_idx) < 0) { perror("SIOCGIFINDEX"); return -1; } int ifindex = if_idx.ifr_ifindex; // get source interface mac struct ifreq if_mac; memset(&if_mac, 0, sizeof(struct ifreq)); strncpy(if_mac.ifr_name, zconf.iface, IFNAMSIZ-1); if (ioctl(sock, SIOCGIFHWADDR, &if_mac) < 0) { perror("SIOCGIFHWADDR"); return -1; } // find source IP address associated with the dev from which we're sending. // while we won't use this address for sending packets, we need the address // to set certain socket options and it's easiest to just use the primary // address the OS believes is associated. struct ifreq if_ip; memset(&if_ip, 0, sizeof(struct ifreq)); strncpy(if_ip.ifr_name, zconf.iface, IFNAMSIZ-1); if (ioctl(sock, SIOCGIFADDR, &if_ip) < 0) { perror("SIOCGIFADDR"); return -1; } // destination address for the socket memset((void*) &sockaddr, 0, sizeof(struct sockaddr_ll)); sockaddr.sll_ifindex = ifindex; sockaddr.sll_halen = ETH_ALEN; memcpy(sockaddr.sll_addr, zconf.gw_mac, ETH_ALEN); char buf[MAX_PACKET_SIZE]; memset(buf, 0, MAX_PACKET_SIZE); zconf.probe_module->thread_initialize(buf, (unsigned char *)if_mac.ifr_hwaddr.sa_data, zconf.gw_mac, zconf.target_port); pthread_mutex_unlock(&send_mutex); // adaptive timing to hit target rate uint32_t count = 0; uint32_t last_count = count; double last_time = now(); uint32_t delay = 0; int interval = 0; volatile int vi; if (zconf.rate > 0) { // estimate initial rate delay = 10000; for (vi = delay; vi--; ) ; delay *= 1 / (now() - last_time) / (zconf.rate / zconf.senders); interval = (zconf.rate / zconf.senders) / 20; last_time = now(); } while (1) { // adaptive timing delay if (delay > 0) { count++; for (vi = delay; vi--; ) ; if (!interval || (count % interval == 0)) { double t = now(); delay *= (double)(count - last_count) / (t - last_time) / (zconf.rate / zconf.senders); if (delay < 1) delay = 1; last_count = count; last_time = t; } } // generate next ip from cyclic group and update global state // (everything locked happens here) pthread_mutex_lock(&send_mutex); if (zsend.complete) { pthread_mutex_unlock(&send_mutex); break; } if (zsend.sent >= zconf.max_targets) { zsend.complete = 1; zsend.finish = now(); pthread_mutex_unlock(&send_mutex); break; } if (zconf.max_runtime && zconf.max_runtime <= now() - zsend.start) { zsend.complete = 1; zsend.finish = now(); pthread_mutex_unlock(&send_mutex); break; } uint32_t curr = cyclic_get_next_ip(); if (curr == zsend.first_scanned) { zsend.complete = 1; zsend.finish = now(); } zsend.sent++; pthread_mutex_unlock(&send_mutex); for (int i=0; i < zconf.packet_streams; i++) { uint32_t src_ip = get_src_ip(curr, i); uint32_t validation[VALIDATE_BYTES/sizeof(uint32_t)]; validate_gen(src_ip, curr, (uint8_t *)validation); zconf.probe_module->make_packet(buf, src_ip, curr, validation, i); if (zconf.dryrun) { zconf.probe_module->print_packet(stdout, buf); } else { int l = zconf.probe_module->packet_length; int rc = sendto(sock, buf + zconf.send_ip_pkts*sizeof(struct ethhdr), l, 0, (struct sockaddr *)&sockaddr, sizeof(struct sockaddr_ll)); if (rc < 0) { struct in_addr addr; addr.s_addr = curr; log_debug("send", "sendto failed for %s. %s", inet_ntoa(addr), strerror(errno)); pthread_mutex_lock(&send_mutex); zsend.sendto_failures++; pthread_mutex_unlock(&send_mutex); } } } } log_debug("send", "thread finished"); return EXIT_SUCCESS; } zmap-1.1.0/src/send.h000066400000000000000000000006621224250063200143510ustar00rootroot00000000000000/* * ZMap Copyright 2013 Regents of the University of Michigan * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy * of the License at http://www.apache.org/licenses/LICENSE-2.0 */ #ifndef SEND_H #define SEND_H int get_socket(void); int get_dryrun_socket(void); int send_init(void); int send_run(int); #endif //SEND_H zmap-1.1.0/src/state.c000066400000000000000000000032011224250063200145230ustar00rootroot00000000000000/* * ZMap Copyright 2013 Regents of the University of Michigan * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy * of the License at http://www.apache.org/licenses/LICENSE-2.0 */ #include "state.h" #include "../lib/logger.h" // global configuration and defaults struct state_conf zconf = { .log_level = LOG_INFO, .source_port_first = 32768, // (these are the default .source_port_last = 61000, // ephemeral range on Linux) .output_filename = NULL, .blacklist_filename = NULL, .whitelist_filename = NULL, .target_port = 0, .max_targets = 0xFFFFFFFF, .max_runtime = 0, .max_results = 0, .iface = NULL, .rate = 0, .bandwidth = 0, .cooldown_secs = 0, .senders = 1, .packet_streams = 1, .use_seed = 0, .seed = 0, .output_module = NULL, .output_args = NULL, .probe_module = NULL, .probe_args = NULL, .gw_mac = {0}, .gw_mac_set = 0, .send_ip_pkts = 0, .source_ip_first = NULL, .source_ip_last = NULL, .raw_output_fields = NULL, .output_fields = NULL, .output_fields_len = 0, .dryrun = 0, .quiet = 0, .summary = 0, .filter_duplicates = 0, .filter_unsuccessful = 0, .recv_ready = 0, }; // global sender stats and defaults struct state_send zsend = { .start = 0.0, .finish = 0.0, .sent = 0, .blacklisted = 0, .complete = 0, .sendto_failures = 0, .targets = 0, }; // global receiver stats and defaults struct state_recv zrecv = { .success_unique = 0, .success_total = 0, .cooldown_unique = 0, .cooldown_total = 0, .failure_total = 0, .complete = 0, .pcap_recv = 0, .pcap_drop = 0, .pcap_ifdrop = 0, }; zmap-1.1.0/src/state.h000066400000000000000000000071731224250063200145440ustar00rootroot00000000000000/* * ZMap Copyright 2013 Regents of the University of Michigan * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy * of the License at http://www.apache.org/licenses/LICENSE-2.0 */ #include #include #include #include #include #include #include "types.h" #include "fieldset.h" #include "filter.h" #ifndef STATE_H #define STATE_H #define MAX_PACKET_SIZE 4096 struct probe_module; struct output_module; struct fieldset_conf { fielddefset_t defs; fielddefset_t outdefs; translation_t translation; int success_index; int classification_index; }; // global configuration struct state_conf { int log_level; port_h_t target_port; port_h_t source_port_first; port_h_t source_port_last; // maximum number of packets that the scanner will send before terminating uint32_t max_targets; // maximum number of seconds that scanner will run before terminating uint32_t max_runtime; // maximum number of results before terminating uint32_t max_results; // name of network interface that // will be utilized for sending/receiving char *iface; // rate in packets per second // that the sender will maintain int rate; // rate in bits per second uint64_t bandwidth; // how many seconds after the termination of the sender will the receiver // continue to process responses int cooldown_secs; // number of sending threads int senders; // should use CLI provided randomization seed instead of generating // a random seed. int use_seed; uint32_t seed; // generator of the cyclic multiplicative group that is utilized for // address generation uint32_t generator; int packet_streams; struct probe_module *probe_module; struct output_module *output_module; char *probe_args; char *output_args; macaddr_t gw_mac[IFHWADDRLEN]; int gw_mac_set; int send_ip_pkts; char *source_ip_first; char *source_ip_last; char *output_filename; char *blacklist_filename; char *whitelist_filename; char **destination_cidrs; int destination_cidrs_len; char *raw_output_fields; char **output_fields; struct output_filter filter; struct fieldset_conf fsconf; int output_fields_len; int dryrun; int summary; int quiet; int filter_duplicates; int filter_unsuccessful; int recv_ready; }; extern struct state_conf zconf; // global sender stats struct state_send { double start; double finish; uint32_t sent; uint32_t blacklisted; int complete; uint32_t first_scanned; uint32_t targets; uint32_t sendto_failures; }; extern struct state_send zsend; // global receiver stats struct state_recv { // valid responses classified as "success" uint32_t success_total; // unique IPs that sent valid responses classified as "success" uint32_t success_unique; // valid responses classified as "success" received during cooldown uint32_t cooldown_total; // unique IPs that first sent valid "success"es during cooldown uint32_t cooldown_unique; // valid responses NOT classified as "success" uint32_t failure_total; int complete; // has the scanner finished sending? double start; // timestamp of when recv started double finish; // timestamp of when recv terminated // number of packets captured by pcap filter uint32_t pcap_recv; // number of packets dropped because there was no room in // the operating system's buffer when they arrived, because // packets weren't being read fast enough uint32_t pcap_drop; // number of packets dropped by the network interface or its driver. uint32_t pcap_ifdrop; }; extern struct state_recv zrecv; #endif // _STATE_H zmap-1.1.0/src/types.h000066400000000000000000000004621224250063200145620ustar00rootroot00000000000000#include #ifndef TYPES_H_ #define TYPES_H_ typedef uint32_t ipaddr_n_t; // IPv4 address network order typedef uint32_t ipaddr_h_t; // IPv4 address host order typedef uint16_t port_n_t; // port network order typedef uint16_t port_h_t; // port host order typedef unsigned char macaddr_t; #endif zmap-1.1.0/src/validate.c000066400000000000000000000023201224250063200151750ustar00rootroot00000000000000/* * ZMap Copyright 2013 Regents of the University of Michigan * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy * of the License at http://www.apache.org/licenses/LICENSE-2.0 */ #include #include #include "../lib/rijndael-alg-fst.h" #include "../lib/random.h" #include "../lib/logger.h" #include "validate.h" #define AES_ROUNDS 10 #define AES_BLOCK_WORDS 4 #define AES_KEY_BYTES 16 static int inited = 0; static uint32_t aes_input[AES_BLOCK_WORDS]; static uint32_t aes_sched[(AES_ROUNDS+1)*4]; void validate_init() { for (int i=0; i < AES_BLOCK_WORDS; i++) { aes_input[i] = 0; } uint8_t key[AES_KEY_BYTES]; if (!random_bytes(key, AES_KEY_BYTES)) { log_fatal("validate", "couldn't get random bytes"); } if (rijndaelKeySetupEnc(aes_sched, key, AES_KEY_BYTES*8) != AES_ROUNDS) { log_fatal("validate", "couldn't initialize AES key"); } inited = 1; } void validate_gen(const uint32_t src, const uint32_t dst, uint8_t output[VALIDATE_BYTES]) { assert(inited); aes_input[0] = src; aes_input[1] = dst; rijndaelEncrypt(aes_sched, AES_ROUNDS, (uint8_t *)aes_input, output); } zmap-1.1.0/src/validate.h000066400000000000000000000007571224250063200152160ustar00rootroot00000000000000/* * ZMap Copyright 2013 Regents of the University of Michigan * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy * of the License at http://www.apache.org/licenses/LICENSE-2.0 */ #ifndef VALIDATE_H #define VALIDATE_H #define VALIDATE_BYTES 16 void validate_init(); void validate_gen(const uint32_t src, const uint32_t dst, uint8_t output[VALIDATE_BYTES]); #endif//_VALIDATE_H zmap-1.1.0/src/zmap.1000066400000000000000000000103051224250063200142730ustar00rootroot00000000000000.TH zmap 1 "06 Aug 2013" "1.0" "zmap man page" .SH NAME zmap \- A fast Internet-wide scanner .SH SYNOPSIS .B zmap [ .I "OPTIONS \&..." ] .SH DESCRIPTION .I ZMap is a network tool for scanning the entire Internet (or large samples). .SH OPTIONS .SS "Basic options" .TP .B \-p, --target-port=port TCP port number to scan (for SYN scans) .TP .B \-o, --output-file=name When using an output module that uses a file (such as the default), write results to this file. Use - for stdout. .TP .B \-b, --blacklist-file=path File of subnets to exclude, in CIDR notation (e.g. 192.168.0.0/16), one-per line. It is recommended you use this to exclude RFC 1918 addresses, multicast, IANA reserved space, and other IANA special-purpose addresses. An example blacklist file is provided in .B conf/blacklist.conf for this purpose. .TP .B -w, --whitelist-file=path File of subnets to constrain scan to, in CIDR notation, e.g. 192.168.0.0/16 .SS "Scan options" .TP .B \-n, --max-targets=n Cap number of targets to probe (as a number or a percentage of the address space) .TP .B \-N, --max-results=n Cap number of results to return .TP .B \-t, --max-runtime=secs Cap length of time for sending packets .TP .B \-r, --rate=pps Set send rate in packets/sec .TP .B \-B, --bandwidth=bps Set send rate in bits/second (supports suffixes G, M and K). This overrides the .B --rate flag. .TP .B \-c, --cooldown-time=secs How long to continue receiving after sending last probe (default=8) .TP .B \-e, --seed=n Seed used to select address permutation. Specify the same seed in order to scan the same sample repeatedly. .TP .B \-T, --sender-threads=n Threads used to send packets (default=1) .TP .B \-P, --probes=n Number of probes to send to each IP (default=1) .TP .B \-d, --dryrun Print out each packet to stdout instead of sending it. (May be useful for debugging.) .SS "Network options" .TP .B \-s, --source-port=port|range Source port(s) for scan packets .TP .B \-S, --source-ip=ip|range Source address(es) for scan packets .TP .B \-G, --gateway-mac=addr Specify gateway MAC address. All packets will be sent to this Ethernet address. .TP .B \-i, --interface=name Specify network interface to use. .TP .B \-X, --vpn If using ZMap through a VPN, use this option. Instead of sending raw Ethernet frames, ZMap will send IP packets. When using this option, it is generally also necessary to provide the interface (through the -i flag). .SS "Advanced options" .TP .B \-M, --probe-module=name Select probe module (default=tcp_synscan) .TP .B \-O, --output-module=name Select output module (default=simple_file) .TP .B \-f, --output-fields=fields Fields that should be output in result set; see .B --list-output-fields .TP .B --probe-args=args Arguments to pass to probe module .TP .B --output-args=args Arguments to pass to output module .TP .B --list-output-modules List available output modules .TP .B --list-probe-modules List available probe modules .TP .B --list-output-fields List all fields that can be output (using .B --output-fields ) by selected probe module .SS "Additional options" .TP .B \-C, --config=filename Read a configuration file, which can specify any of these options (default=/etc/zmap/zmap.conf) .TP .B \-q, --quiet Do not print status updates .TP .B \-g, --summary Print configuration and summary at end of scan .TP .B \-v, --verbosity=n Level of log detail (0-5) (default=3) .TP .B \-h, --help Print help and exit .TP .B \-V, --version Print version and exit .SH EXAMPLES Scan the whole Internet for hosts with port 443 open (results discarded): .PP .\" -p: example of .B zmap \-p 443 .PP Find 5 HTTP servers (port 80), scanning at 10 Mb/s, print the results to stdout: .PP .\" -N: example of .\" -B: example of .B zmap -N 5 -B 10M -p 80 -o - .SH WARNING By default, ZMap attempts to scan at the line speed of your Ethernet interface and can easily use 1 Gbit/second of bandwidth. If your network is not able to support sending packets this quickly, your local network may become congested, causing connectivity problems for you and those around you. Use the -B (--bandwidth) option to set ZMap's maximum bandwidth to an appropriate limit for your network and upstream connection. . .SH AUTHOR Zakir Durumeric, Eric Wustrow, J. Alex Halderman .B (https://www.zmap.io) zmap-1.1.0/src/zmap.c000066400000000000000000000561321224250063200143650ustar00rootroot00000000000000/* * ZMap Copyright 2013 Regents of the University of Michigan * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy * of the License at http://www.apache.org/licenses/LICENSE-2.0 */ #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "../lib/logger.h" #include "../lib/random.h" #include "zopt.h" #include "send.h" #include "recv.h" #include "state.h" #include "monitor.h" #include "get_gateway.h" #include "filter.h" #include "output_modules/output_modules.h" #include "probe_modules/probe_modules.h" pthread_mutex_t cpu_affinity_mutex = PTHREAD_MUTEX_INITIALIZER; pthread_mutex_t recv_ready_mutex = PTHREAD_MUTEX_INITIALIZER; // splits comma delimited string into char*[]. Does not handle // escaping or complicated setups: designed to process a set // of fields that the user wants output static void split_string(char* in, int *len, char***results) { char** fields = calloc(MAX_FIELDS, sizeof(char*)); memset(fields, 0, MAX_FIELDS*sizeof(fields)); int retvlen = 0; char *currloc = in; // parse csv into a set of strings while (1) { size_t len = strcspn(currloc, ", "); if (len == 0) { currloc++; } else { char *new = malloc(len+1); assert(new); strncpy(new, currloc, len); new[len] = '\0'; fields[retvlen++] = new; assert(fields[retvlen-1]); } if (len == strlen(currloc)) { break; } currloc += len; } *results = fields; *len = retvlen; } static void set_cpu(void) { pthread_mutex_lock(&cpu_affinity_mutex); static int core=0; int num_cores = sysconf(_SC_NPROCESSORS_ONLN); cpu_set_t cpuset; CPU_ZERO(&cpuset); CPU_SET(core, &cpuset); if (pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset) != 0) { log_error("zmap", "can't set thread CPU affinity"); } log_trace("zmap", "set thread %u affinity to core %d", pthread_self(), core); core = (core + 1) % num_cores; pthread_mutex_unlock(&cpu_affinity_mutex); } static void* start_send(void *arg) { uintptr_t v = (uintptr_t) arg; int sock = (int) v & 0xFFFF; set_cpu(); send_run(sock); return NULL; } static void* start_recv(__attribute__((unused)) void *arg) { set_cpu(); recv_run(&recv_ready_mutex); return NULL; } static void drop_privs() { struct passwd *pw; if (geteuid() != 0) { log_warn("zmap", "unable to drop privs, not root"); return; } if ((pw = getpwnam("nobody")) != NULL) { if (setuid(pw->pw_uid) == 0) { return; // success } } log_fatal("zmap", "Couldn't change UID to 'nobody'"); } static void *start_mon(__attribute__((unused)) void *arg) { set_cpu(); monitor_run(); return NULL; } #define SI(w,x,y) printf("%s\t%s\t%i\n", w, x, y); #define SD(w,x,y) printf("%s\t%s\t%f\n", w, x, y); #define SU(w,x,y) printf("%s\t%s\t%u\n", w, x, y); #define SLU(w,x,y) printf("%s\t%s\t%lu\n", w, x, (long unsigned int) y); #define SS(w,x,y) printf("%s\t%s\t%s\n", w, x, y); #define STRTIME_LEN 1024 static void summary(void) { char send_start_time[STRTIME_LEN+1]; assert(dstrftime(send_start_time, STRTIME_LEN, "%c", zsend.start)); char send_end_time[STRTIME_LEN+1]; assert(dstrftime(send_end_time, STRTIME_LEN, "%c", zsend.finish)); char recv_start_time[STRTIME_LEN+1]; assert(dstrftime(recv_start_time, STRTIME_LEN, "%c", zrecv.start)); char recv_end_time[STRTIME_LEN+1]; assert(dstrftime(recv_end_time, STRTIME_LEN, "%c", zrecv.finish)); double hitrate = ((double) 100 * zrecv.success_unique)/((double)zsend.sent); SU("cnf", "target-port", zconf.target_port); SU("cnf", "source-port-range-begin", zconf.source_port_first); SU("cnf", "source-port-range-end", zconf.source_port_last); SS("cnf", "source-addr-range-begin", zconf.source_ip_first); SS("cnf", "source-addr-range-end", zconf.source_ip_last); SU("cnf", "maximum-targets", zconf.max_targets); SU("cnf", "maximum-runtime", zconf.max_runtime); SU("cnf", "maximum-results", zconf.max_results); SU("cnf", "permutation-seed", zconf.seed); SI("cnf", "cooldown-period", zconf.cooldown_secs); SS("cnf", "send-interface", zconf.iface); SI("cnf", "rate", zconf.rate); SLU("cnf", "bandwidth", zconf.bandwidth); SU("env", "nprocessors", (unsigned) sysconf(_SC_NPROCESSORS_ONLN)); SS("exc", "send-start-time", send_start_time); SS("exc", "send-end-time", send_end_time); SS("exc", "recv-start-time", recv_start_time); SS("exc", "recv-end-time", recv_end_time); SU("exc", "sent", zsend.sent); SU("exc", "blacklisted", zsend.blacklisted); SU("exc", "first-scanned", zsend.first_scanned); SD("exc", "hit-rate", hitrate); SU("exc", "success-total", zrecv.success_total); SU("exc", "success-unique", zrecv.success_unique); SU("exc", "success-cooldown-total", zrecv.cooldown_total); SU("exc", "success-cooldown-unique", zrecv.cooldown_unique); SU("exc", "failure-total", zrecv.failure_total); SU("exc", "sendto-failures", zsend.sendto_failures); SU("adv", "permutation-gen", zconf.generator); SS("exc", "scan-type", zconf.probe_module->name); } static void start_zmap(void) { log_info("zmap", "started"); if (zconf.iface == NULL) { char errbuf[PCAP_ERRBUF_SIZE]; char *iface = pcap_lookupdev(errbuf); if (iface == NULL) { log_fatal("zmap", "could not detect default network interface " "(e.g. eth0). Try running as root or setting" " interface using -i flag."); } log_debug("zmap", "no interface provided. will use default" " interface (%s).", iface); zconf.iface = iface; } if (zconf.source_ip_first == NULL) { struct in_addr default_ip; zconf.source_ip_first = malloc(INET_ADDRSTRLEN); zconf.source_ip_last = zconf.source_ip_first; if (get_iface_ip(zconf.iface, &default_ip) < 0) { log_fatal("zmap", "could not detect default IP address for for %s." " Try specifying a source address (-S).", zconf.iface); } inet_ntop(AF_INET, &default_ip, zconf.source_ip_first, INET_ADDRSTRLEN); log_debug("zmap", "no source IP address given. will use default address: %s.", zconf.source_ip_first); } if (!zconf.gw_mac_set) { struct in_addr gw_ip; char iface[IF_NAMESIZE]; if (get_default_gw(&gw_ip, iface) < 0) { log_fatal("zmap", "could not detect default gateway address for %s." " Try setting default gateway mac address (-G).", zconf.iface); } log_debug("zmap", "found gateway IP %s on %s", inet_ntoa(gw_ip), iface); if (get_hw_addr(&gw_ip, iface, zconf.gw_mac) < 0) { log_fatal("zmap", "could not detect GW MAC address for %s on %s." " Try setting default gateway mac address (-G).", inet_ntoa(gw_ip), zconf.iface); } zconf.gw_mac_set = 1; log_debug("zmap", "MAC address of selected gateway %02x:%02x:%02x:%02x:%02x:%02x", zconf.gw_mac[0], zconf.gw_mac[1], zconf.gw_mac[2], zconf.gw_mac[3], zconf.gw_mac[4], zconf.gw_mac[5]); } // initialization log_info("zmap", "zmap selected output module: %s", zconf.output_module->name); if (zconf.output_module && zconf.output_module->init) { zconf.output_module->init(&zconf, zconf.output_fields, zconf.output_fields_len); } if (send_init()) { exit(EXIT_FAILURE); } if (zconf.output_module && zconf.output_module->start) { zconf.output_module->start(&zconf, &zsend, &zrecv); } // start threads pthread_t *tsend, trecv, tmon; int r = pthread_create(&trecv, NULL, start_recv, NULL); if (r != 0) { log_fatal("zmap", "unable to create recv thread"); exit(EXIT_FAILURE); } for (;;) { pthread_mutex_lock(&recv_ready_mutex); if (zconf.recv_ready) { break; } pthread_mutex_unlock(&recv_ready_mutex); } tsend = malloc(zconf.senders * sizeof(pthread_t)); assert(tsend); log_debug("zmap", "using %d sender threads", zconf.senders); for (int i=0; i < zconf.senders; i++) { uintptr_t sock; if (zconf.dryrun) { sock = get_dryrun_socket(); } else { sock = get_socket(); } int r = pthread_create(&tsend[i], NULL, start_send, (void*) sock); if (r != 0) { log_fatal("zmap", "unable to create send thread"); exit(EXIT_FAILURE); } } if (!zconf.quiet) { int r = pthread_create(&tmon, NULL, start_mon, NULL); if (r != 0) { log_fatal("zmap", "unable to create monitor thread"); exit(EXIT_FAILURE); } } drop_privs(); // wait for completion for (int i=0; i < zconf.senders; i++) { int r = pthread_join(tsend[i], NULL); if (r != 0) { log_fatal("zmap", "unable to join send thread"); exit(EXIT_FAILURE); } } log_debug("zmap", "senders finished"); r = pthread_join(trecv, NULL); if (r != 0) { log_fatal("zmap", "unable to join recv thread"); exit(EXIT_FAILURE); } if (!zconf.quiet) { pthread_join(tmon, NULL); if (r != 0) { log_fatal("zmap", "unable to join monitor thread"); exit(EXIT_FAILURE); } } // finished if (zconf.summary) { summary(); } if (zconf.output_module && zconf.output_module->close) { zconf.output_module->close(&zconf, &zsend, &zrecv); } if (zconf.probe_module && zconf.probe_module->close) { zconf.probe_module->close(&zconf, &zsend, &zrecv); } log_info("zmap", "completed"); } static void enforce_range(const char *name, int v, int min, int max) { if (v < min || v > max) { fprintf(stderr, "%s: argument `%s' must be between %d and %d\n", CMDLINE_PARSER_PACKAGE, name, min, max); exit(EXIT_FAILURE); } } static int file_exists(char *name) { FILE *file = fopen(name, "r"); if (!file) return 0; fclose(file); return 1; } #define MAC_LEN IFHWADDRLEN int parse_mac(macaddr_t *out, char *in) { if (strlen(in) < MAC_LEN*3-1) return 0; char octet[3]; octet[2] = '\0'; for (int i=0; i < MAC_LEN; i++) { if (i < MAC_LEN-1 && in[i*3+2] != ':') { return 0; } strncpy(octet, &in[i*3], 2); char *err = NULL; long b = strtol(octet, &err, 16); if (err && *err != '\0') { return 0; } out[i] = b & 0xFF; } return 1; } #define SET_IF_GIVEN(DST,ARG) \ { if (args.ARG##_given) { (DST) = args.ARG##_arg; }; } #define SET_BOOL(DST,ARG) \ { if (args.ARG##_given) { (DST) = 1; }; } int main(int argc, char *argv[]) { struct gengetopt_args_info args; struct cmdline_parser_params *params; params = cmdline_parser_params_create(); params->initialize = 1; params->override = 0; params->check_required = 0; if (cmdline_parser_ext(argc, argv, &args, params) != 0) { exit(EXIT_SUCCESS); } if (args.config_given || file_exists(args.config_arg)) { params->initialize = 0; params->override = 0; if (cmdline_parser_config_file(args.config_arg, &args, params) != 0) { exit(EXIT_FAILURE); } } zconf.log_level = args.verbosity_arg; log_init(stderr, zconf.log_level); log_trace("zmap", "zmap main thread started"); // parse the provided probe and output module s.t. that we can support // other command-line helpers (e.g. probe help) log_trace("zmap", "requested ouput-module: %s\n", args.output_module_arg); // we changed output module setup after the original version of ZMap was // made public. After this setup was removed, many of the original // output modules became unnecessary. However, in order to support // backwards compatibility, we still allows this output-modules to be // specified and then map these into new-style output modules and warn // users that they need to be switching to the new module interface. // zmap's default behavior is to provide a simple file of the unique IP // addresses that responded successfully. if (!strcmp(args.output_module_arg, "default")) { log_debug("zmap", "no output module provided. will use csv."); zconf.output_module = get_output_module_by_name("csv"); zconf.raw_output_fields = (char*) "saddr"; zconf.filter_duplicates = 1; zconf.filter_unsuccessful = 1; } else if (!strcmp(args.output_module_arg, "simple_file")) { log_warn("zmap", "the simple_file output interface has been deprecated and " "will be removed in the future. Users should use the csv " "output module. Newer scan options such as output-fields " "are not supported with this output module."); zconf.output_module = get_output_module_by_name("csv"); zconf.raw_output_fields = (char*) "saddr"; zconf.filter_duplicates = 1; zconf.filter_unsuccessful = 1; } else if (!strcmp(args.output_module_arg, "extended_file")) { log_warn("zmap", "the extended_file output interface has been deprecated and " "will be removed in the future. Users should use the csv " "output module. Newer scan options such as output-fields " "are not supported with this output module."); zconf.output_module = get_output_module_by_name("csv"); zconf.raw_output_fields = (char*) "classification, saddr, " "daddr, sport, dport, " "seqnum, acknum, cooldown, " "repeat, timestamp-str"; zconf.filter_duplicates = 0; } else if (!strcmp(args.output_module_arg, "redis")) { log_warn("zmap", "the redis output interface has been deprecated and " "will be removed in the future. Users should " "either use redis-packed or redis-json in the " "future."); zconf.output_module = get_output_module_by_name("redis-packed"); if (!zconf.output_module) { log_fatal("zmap", "%s: specified output module (%s) does not exist\n", CMDLINE_PARSER_PACKAGE, args.output_module_arg); } zconf.raw_output_fields = (char*) "saddr"; zconf.filter_duplicates = 1; zconf.filter_unsuccessful = 1; if (args.output_fields_given) { log_fatal("redis", "module does not support user defined " "output fields"); } if (args.output_filter_given) { log_fatal("redis", "module does not support user defined " "filters."); } } else if (!strcmp(args.output_module_arg, "csvredis")) { if (args.output_fields_given) { log_fatal("csvredis", "module does not support user defined " "output fields"); } // output all available fields to the CSV file zconf.raw_output_fields = (char*) "*"; // module does not support filtering if (args.output_filter_given) { log_fatal("csvredis", "module does not support user defined " "filters."); } zconf.output_module = get_output_module_by_name("csvredis"); } else { zconf.output_module = get_output_module_by_name(args.output_module_arg); if (!zconf.output_module) { fprintf(stderr, "%s: specified output module (%s) does not exist\n", CMDLINE_PARSER_PACKAGE, args.output_module_arg); exit(EXIT_FAILURE); } } zconf.probe_module = get_probe_module_by_name(args.probe_module_arg); if (!zconf.probe_module) { fprintf(stderr, "%s: specified probe module (%s) does not exist\n", CMDLINE_PARSER_PACKAGE, args.probe_module_arg); exit(EXIT_FAILURE); } if (args.help_given) { cmdline_parser_print_help(); printf("\nselected probe-module (%s) help\n", zconf.probe_module->name); if (zconf.probe_module->helptext) { printf("%s\n", zconf.probe_module->helptext); } else { printf("no help text available\n"); } printf("\nselected output-module (%s) help\n", zconf.output_module->name); if (zconf.output_module->helptext) { printf("%s\n", zconf.output_module->helptext); } else { printf("no help text available\n"); } exit(EXIT_SUCCESS); } if (args.version_given) { cmdline_parser_print_version(); exit(EXIT_SUCCESS); } if (args.list_output_modules_given) { print_output_modules(); exit(EXIT_SUCCESS); } if (args.list_probe_modules_given) { print_probe_modules(); exit(EXIT_SUCCESS); } if (args.vpn_given) { zconf.send_ip_pkts = 1; zconf.gw_mac_set = 1; memset(zconf.gw_mac, 0, IFHWADDRLEN); } if (cmdline_parser_required(&args, CMDLINE_PARSER_PACKAGE) != 0) { exit(EXIT_FAILURE); } // now that we know the probe module, let's find what it supports memset(&zconf.fsconf, 0, sizeof(struct fieldset_conf)); // the set of fields made available to a user is constructed // of IP header fields + probe module fields + system fields fielddefset_t *fds = &(zconf.fsconf.defs); gen_fielddef_set(fds, (fielddef_t*) &(ip_fields), ip_fields_len); gen_fielddef_set(fds, zconf.probe_module->fields, zconf.probe_module->numfields); gen_fielddef_set(fds, (fielddef_t*) &(sys_fields), sys_fields_len); if (args.list_output_fields_given) { for (int i = 0; i < fds->len; i++) { printf("%-15s %6s: %s\n", fds->fielddefs[i].name, fds->fielddefs[i].type, fds->fielddefs[i].desc); } exit(EXIT_SUCCESS); } // find the fields we need for the framework zconf.fsconf.success_index = fds_get_index_by_name(fds, (char*) "success"); if (zconf.fsconf.success_index < 0) { log_fatal("fieldset", "probe module does not supply " "required success field."); } zconf.fsconf.classification_index = fds_get_index_by_name(fds, (char*) "classification"); if (zconf.fsconf.classification_index < 0) { log_fatal("fieldset", "probe module does not supply " "required packet classification field."); } // process the list of requested output fields. if (args.output_fields_given) { zconf.raw_output_fields = args.output_fields_arg; } else if (!zconf.raw_output_fields) { zconf.raw_output_fields = (char*) "saddr"; } if (!strcmp(zconf.raw_output_fields, "*")) { zconf.output_fields_len = zconf.fsconf.defs.len; zconf.output_fields = calloc(zconf.fsconf.defs.len, sizeof(char*)); assert(zconf.output_fields); for (int i=0; i < zconf.fsconf.defs.len; i++) { zconf.output_fields[i] = (char*) zconf.fsconf.defs.fielddefs[i].name; } fs_generate_full_fieldset_translation(&zconf.fsconf.translation, &zconf.fsconf.defs); } else { split_string(zconf.raw_output_fields, &(zconf.output_fields_len), &(zconf.output_fields)); for (int i=0; i < zconf.output_fields_len; i++) { log_debug("zmap", "requested output field (%i): %s", i, zconf.output_fields[i]); } // generate a translation that can be used to convert output // from a probe module to the input for an output module fs_generate_fieldset_translation(&zconf.fsconf.translation, &zconf.fsconf.defs, zconf.output_fields, zconf.output_fields_len); } // Parse and validate the output filter, if any if (args.output_filter_arg) { // Run it through yyparse to build the expression tree if (!parse_filter_string(args.output_filter_arg)) { log_fatal("zmap", "Unable to parse filter expression"); } // Check the fields used against the fieldset in use if (!validate_filter(zconf.filter.expression, &zconf.fsconf.defs)) { log_fatal("zmap", "Invalid filter"); } } SET_BOOL(zconf.dryrun, dryrun); SET_BOOL(zconf.quiet, quiet); SET_BOOL(zconf.summary, summary); zconf.cooldown_secs = args.cooldown_time_arg; zconf.senders = args.sender_threads_arg; SET_IF_GIVEN(zconf.output_filename, output_file); SET_IF_GIVEN(zconf.blacklist_filename, blacklist_file); SET_IF_GIVEN(zconf.probe_args, probe_args); SET_IF_GIVEN(zconf.output_args, output_args); SET_IF_GIVEN(zconf.iface, interface); SET_IF_GIVEN(zconf.max_runtime, max_runtime); SET_IF_GIVEN(zconf.max_results, max_results); SET_IF_GIVEN(zconf.rate, rate); SET_IF_GIVEN(zconf.packet_streams, probes); // find if zmap wants any specific cidrs scanned instead // of the entire Internet zconf.destination_cidrs = args.inputs; zconf.destination_cidrs_len = args.inputs_num; if (zconf.destination_cidrs && zconf.blacklist_filename && !strcmp(zconf.blacklist_filename, "/etc/zmap/blacklist.conf")) { log_warn("blacklist", "ZMap is currently using the default blacklist located " "at /etc/zmap/blacklist.conf. By default, this blacklist excludes locally " "scoped networks (e.g. 10.0.0.0/8, 127.0.0.1/8, and 192.168.0.0/16). If you are" " trying to scan local networks, you can change the default blacklist by " "editing the default ZMap configuration at /etc/zmap/zmap.conf."); } SET_IF_GIVEN(zconf.whitelist_filename, whitelist_file); if (zconf.probe_module->port_args) { if (args.source_port_given) { char *dash = strchr(args.source_port_arg, '-'); if (dash) { // range *dash = '\0'; zconf.source_port_first = atoi(args.source_port_arg); enforce_range("starting source-port", zconf.source_port_first, 0, 0xFFFF); zconf.source_port_last = atoi(dash+1); enforce_range("ending source-port", zconf.source_port_last, 0, 0xFFFF); if (zconf.source_port_first > zconf.source_port_last) { fprintf(stderr, "%s: invalid source port range: " "last port is less than first port\n", CMDLINE_PARSER_PACKAGE); exit(EXIT_FAILURE); } } else { // single port int port = atoi(args.source_port_arg); enforce_range("source-port", port, 0, 0xFFFF); zconf.source_port_first = port; zconf.source_port_last = port; } } if (!args.target_port_given) { fprintf(stderr, "%s: target port is required for this type of probe\n", CMDLINE_PARSER_PACKAGE); exit(EXIT_FAILURE); } enforce_range("target-port", args.target_port_arg, 0, 0xFFFF); zconf.target_port = args.target_port_arg; } if (args.source_ip_given) { char *dash = strchr(args.source_ip_arg, '-'); if (dash) { // range *dash = '\0'; zconf.source_ip_first = args.source_ip_arg; zconf.source_ip_last = dash+1; } else { // single address zconf.source_ip_first = args.source_ip_arg; zconf.source_ip_last = args.source_ip_arg; } } if (args.gateway_mac_given) { if (!parse_mac(zconf.gw_mac, args.gateway_mac_arg)) { fprintf(stderr, "%s: invalid MAC address `%s'\n", CMDLINE_PARSER_PACKAGE, args.gateway_mac_arg); exit(EXIT_FAILURE); } zconf.gw_mac_set = 1; } if (args.seed_given) { zconf.seed = args.seed_arg; zconf.use_seed = 1; } if (args.bandwidth_given) { // Supported: G,g=*1000000000; M,m=*1000000 K,k=*1000 bits per second zconf.bandwidth = atoi(args.bandwidth_arg); char *suffix = args.bandwidth_arg; while (*suffix >= '0' && *suffix <= '9') { suffix++; } if (*suffix) { switch (*suffix) { case 'G': case 'g': zconf.bandwidth *= 1000000000; break; case 'M': case 'm': zconf.bandwidth *= 1000000; break; case 'K': case 'k': zconf.bandwidth *= 1000; break; default: fprintf(stderr, "%s: unknown bandwidth suffix '%s' " "(supported suffixes are G, M and K)\n", CMDLINE_PARSER_PACKAGE, suffix); exit(EXIT_FAILURE); } } } if (args.max_targets_given) { errno = 0; char *end; double v = strtod(args.max_targets_arg, &end); if (end == args.max_targets_arg || errno != 0) { fprintf(stderr, "%s: can't convert max-targets to a number\n", CMDLINE_PARSER_PACKAGE); exit(EXIT_FAILURE); } if (end[0] == '%' && end[1] == '\0') { // treat as percentage v = v * ((unsigned long long int)1 << 32) / 100.; } else if (end[0] != '\0') { fprintf(stderr, "%s: extra characters after max-targets\n", CMDLINE_PARSER_PACKAGE); exit(EXIT_FAILURE); } if (v <= 0) { zconf.max_targets = 0; } else if (v >= ((unsigned long long int)1 << 32)) { zconf.max_targets = 0xFFFFFFFF; } else { zconf.max_targets = v; } } start_zmap(); cmdline_parser_free(&args); free(params); return EXIT_SUCCESS; } zmap-1.1.0/src/zopt.ggo000066400000000000000000000104711224250063200147400ustar00rootroot00000000000000# ZMap Copyright 2013 Regents of the University of Michigan # Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 # zmap option description to be processed by gengetopt package "zmap" version "1.1.0" purpose "A fast Internet-wide scanner." section "Basic arguments" option "target-port" p "TCP port number to scan (for SYN scans)" typestr="port" optional int option "output-file" o "Output file" typestr="name" optional string option "blacklist-file" b "File of subnets to exclude, in CIDR notation, e.g. 192.168.0.0/16" typestr="path" optional string option "whitelist-file" w "File of subnets to constrain scan to, in CIDR notation, e.g. 192.168.0.0/16" typestr="path" optional string option "output-fields" f "Fields that should be output in result set" typestr="fields" optional string section "Scan options" option "max-targets" n "Cap number of targets to probe (as a number or a percentage of the address space)" typestr="n" optional string option "max-results" N "Cap number of results to return" typestr="n" optional int option "max-runtime" t "Cap length of time for sending packets" typestr="ses" optional int option "rate" r "Set send rate in packets/sec" typestr="pps" optional int option "bandwidth" B "Set send rate in bits/second (supports suffixes G, M and K)" typestr="bps" optional string option "cooldown-time" c "How long to continue receiving after sending last probe" typestr="secs" default="8" optional int option "seed" e "Seed used to select address permutation" typestr="n" optional int option "sender-threads" T "Threads used to send packets" typestr="n" default="1" optional int option "probes" P "Number of probes to send to each IP" typestr="n" default="1" optional int option "dryrun" d "Don't actually send packets" optional section "Network options" option "source-port" s "Source port(s) for scan packets" typestr="port|range" optional string option "source-ip" S "Source address(es) for scan packets" typestr="ip|range" optional string option "gateway-mac" G "Specify gateway MAC address" typestr="addr" optional string option "interface" i "Specify network interface to use" typestr="name" optional string option "vpn" X "Sends IP packets instead of Ethernet (for VPNs)" optional section "Advanced options" option "probe-module" M "Select probe module" typestr="name" default="tcp_synscan" optional string option "output-module" O "Select output module" typestr="name" default="default" optional string option "probe-args" - "Arguments to pass to probe module" typestr="args" optional string option "output-args" - "Arguments to pass to output module" typestr="args" optional string option "output-filter" - "Specify a filter over the response fields to limit what responses get sent to the output module" typestr="filter" optional string option "list-output-modules" - "List available output modules" optional option "list-probe-modules" - "List available probe modules" optional option "list-output-fields" - "List all fields that can be output by selected probe module" optional section "Additional options" option "config" C "Read a configuration file, which can specify any of these options" typestr="filename" default="/etc/zmap/zmap.conf" optional string option "quiet" q "Do not print status updates" optional option "summary" g "Print configuration and summary at end of scan" optional option "verbosity" v "Level of log detail (0-5)" typestr="n" default="3" optional int option "help" h "Print help and exit" optional option "version" V "Print version and exit" optional text "\nExamples:\n\ zmap -p 443 (scans the whole Internet for hosts with port 443 open)\n\ zmap -N 5 -B 10M -p 80 -o - (find 5 HTTP servers, scanning at 10 Mb/s)\n zmap -p 80 10.0.0.0/8 192.168.0.0/16 -o (scan 10.0.0.0/8 and 192.168.0.0/16 on port 80)\n zmap -p 80 192.168.1.2 192.168.1.3 (scan 192.168.1.2 and 192.168.1.3 on port 80)" zmap-1.1.0/src/zopt_compat.c000066400000000000000000000002461224250063200157500ustar00rootroot00000000000000#if __GNUC__ < 4 #error "gcc version >= 4 is required" #elif __GNUC_MINOR__ >= 6 #pragma GCC diagnostic ignored "-Wunused-but-set-variable" #endif #include "zopt.c" zmap-1.1.0/zmap_conf_install.cmake.in000066400000000000000000000002741224250063200175700ustar00rootroot00000000000000foreach(conf_file ${CONF_FILES}) message(STATUS "${conf_file}") if(NOT EXISTS "/etc/zmap/${conf_file}") file(INSTALL "conf/${conf_file}" DESTINATION "/etc/zmap") endif() endforeach()