Merge branch 'master' of github.com:zmap/zmap
This commit is contained in:
commit
42650bf402
36
examples/banner-grab-go/README
Normal file
36
examples/banner-grab-go/README
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
TCP 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.
|
152
examples/banner-grab-go/banner.go
Normal file
152
examples/banner-grab-go/banner.go
Normal file
@ -0,0 +1,152 @@
|
|||||||
|
/*
|
||||||
|
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
|
||||||
|
}
|
3
examples/banner-grab-go/http-req
Normal file
3
examples/banner-grab-go/http-req
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
GET / HTTP/1.1
|
||||||
|
Host: %s
|
||||||
|
|
@ -8,6 +8,7 @@ PREFIX=/usr/local
|
|||||||
INSTALL=install
|
INSTALL=install
|
||||||
INSTALLDATA=install -m 644
|
INSTALLDATA=install -m 644
|
||||||
mandir=$(PREFIX)/man/man1/
|
mandir=$(PREFIX)/man/man1/
|
||||||
|
oldmanfile=/usr/share/man/man1/zmap.1
|
||||||
bindir=$(PREFIX)/sbin
|
bindir=$(PREFIX)/sbin
|
||||||
|
|
||||||
# Hardening and warnings for building with gcc
|
# Hardening and warnings for building with gcc
|
||||||
@ -62,6 +63,7 @@ zopt.c zopt.h: zopt.ggo
|
|||||||
install: zmap
|
install: zmap
|
||||||
$(INSTALL) zmap $(bindir)/zmap
|
$(INSTALL) zmap $(bindir)/zmap
|
||||||
test -d /etc/zmap || (mkdir /etc/zmap && $(INSTALLDATA) ../conf/* /etc/zmap/)
|
test -d /etc/zmap || (mkdir /etc/zmap && $(INSTALLDATA) ../conf/* /etc/zmap/)
|
||||||
|
test -f $(oldmanfile) && rm -f $(oldmanfile) && mandb -f $(oldmanfile) || /bin/true # remove old man page if it's there
|
||||||
test -d $(mandir) || mkdir -p $(mandir)
|
test -d $(mandir) || mkdir -p $(mandir)
|
||||||
$(INSTALLDATA) ./zmap.1 $(mandir)
|
$(INSTALLDATA) ./zmap.1 $(mandir)
|
||||||
@echo "\n**************\nSuccess! ZMap is installed. Try running (as root):\nzmap -p 80 -N 10 -B 1M -o -\n**************"
|
@echo "\n**************\nSuccess! ZMap is installed. Try running (as root):\nzmap -p 80 -N 10 -B 1M -o -\n**************"
|
||||||
|
@ -341,13 +341,14 @@ int main(int argc, char *argv[])
|
|||||||
params->override = 0;
|
params->override = 0;
|
||||||
params->check_required = 0;
|
params->check_required = 0;
|
||||||
|
|
||||||
|
if (cmdline_parser_ext(argc, argv, &args, params) != 0) {
|
||||||
|
exit(EXIT_SUCCESS);
|
||||||
|
}
|
||||||
|
|
||||||
zconf.log_level = args.verbosity_arg;
|
zconf.log_level = args.verbosity_arg;
|
||||||
log_init(stderr, zconf.log_level);
|
log_init(stderr, zconf.log_level);
|
||||||
log_trace("zmap", "zmap main thread started");
|
log_trace("zmap", "zmap main thread started");
|
||||||
|
|
||||||
if (cmdline_parser_ext(argc, argv, &args, params) != 0) {
|
|
||||||
exit(EXIT_SUCCESS);
|
|
||||||
}
|
|
||||||
if (args.help_given) {
|
if (args.help_given) {
|
||||||
cmdline_parser_print_help();
|
cmdline_parser_print_help();
|
||||||
exit(EXIT_SUCCESS);
|
exit(EXIT_SUCCESS);
|
||||||
|
Loading…
Reference in New Issue
Block a user