├── README.md ├── cmd ├── parse.go ├── run.go ├── scan.go └── type.go ├── gans.go ├── go.mod ├── go.sum └── nmap └── nmap_definition.go /README.md: -------------------------------------------------------------------------------- 1 | README 2 | ====== 3 | 4 | GANS is a tool to automate nmap scan. 5 | 6 | Install GO 7 | ---------- 8 | Install go from the package downloader of your distribution or use official download from [https://golang.org/dl](https://golang.org/dl) 9 | 10 | Create a workspace to load your code : 11 | 12 | mkdir ~/.go 13 | export GOPATH=$HOME/.go 14 | export PATH=$PATH:$HOME/.go/bin 15 | 16 | (edit your .profile file if you want to execute this at every login) 17 | 18 | Install GANS 19 | ------------ 20 | > go get github.com/restanrm/gans 21 | 22 | It will download all the dependencies needed. 23 | 24 | Using GANS 25 | ---------- 26 | 27 | Gans is used from a daemon process and some control processes. The command ``gans run`` need root permission due to the ``nmap`` permissions that are required to do the scan. Here is a simple example to use gans. 28 | 29 | You will need 2 terminals : 30 | 31 | Here is the first one : (it needs root because it interacts with nmap) 32 | 33 | > sudo ./gans run -d data.json 34 | 35 | This deamon is now waiting for commands. It will read/write the infos it gathers/needs in the data.json file. (you can change this of course) 36 | 37 | Open a second terminal and run the command 38 | 39 | > ./gans scan \ 40 | 41 | ex : 42 | 43 | > ./gans scan 192.168.0.0/24 192.168.2.254 172.16.0.0/12 44 | 45 | You can then parse the data generated by GANS : 46 | 47 | > ./gans parse data.json 48 | 49 | 50 | 51 | -------------------------------------------------------------------------------- /cmd/parse.go: -------------------------------------------------------------------------------- 1 | package cmd 2 | 3 | import ( 4 | "database/sql" 5 | "encoding/xml" 6 | "errors" 7 | "fmt" 8 | "log" 9 | 10 | "github.com/codegangsta/cli" 11 | _ "github.com/go-sql-driver/mysql" 12 | "github.com/restanrm/gans/nmap" 13 | //"net" 14 | "strconv" 15 | "strings" 16 | ) 17 | 18 | var CmdParse = cli.Command{ 19 | Name: "parse", 20 | Usage: "Parse les données des fichiers nmap en entré et les places dans la base de données", 21 | ShortName: "xml", 22 | Action: parseRun, 23 | Flags: []cli.Flag{ 24 | cli.StringFlag{ 25 | Name: "user, u", 26 | Usage: "utilisateur de la base de données", 27 | Value: "root", 28 | }, 29 | cli.StringFlag{ 30 | Name: "password, p", 31 | Usage: "Mot de passe de connection à la base de données", 32 | Value: "defaultPassword", 33 | }, 34 | cli.StringFlag{ 35 | Name: "database, d", 36 | Usage: "Nom de la base de données de saisie des hôtes", 37 | Value: "gans", 38 | }, 39 | cli.BoolFlag{ 40 | Name: "ClearText, c", 41 | Usage: "Désactive la sauvegarde en base de données et préfère une sortie texte des donnée", 42 | }, 43 | }, 44 | } 45 | 46 | // Draft de structure de base de données 47 | // Cette structure correspond a ce qui se trouve dans la base de données locale 48 | type Service struct { 49 | Name, 50 | Version, 51 | Product, 52 | OsType string 53 | } 54 | 55 | func (s Service) String() string { 56 | return fmt.Sprintf("%v, %v, %v", s.Name, s.Version, s.Product) 57 | } 58 | 59 | type Port struct { 60 | Number int 61 | Protocol string 62 | Status string 63 | Service Service 64 | } 65 | 66 | func (p Port) String() string { 67 | // affiche le résultat si le port est ouvert. 68 | if p.Status == "open" { 69 | return fmt.Sprintf(" %-6v: %v; %v, %v\n", p.Number, p.Status, p.Protocol, p.Service) 70 | } 71 | return "" 72 | } 73 | 74 | type Host struct { 75 | Address string 76 | Status string 77 | Os string 78 | Ports []Port 79 | } 80 | 81 | func (h Host) String() string { 82 | var out string = "" 83 | out = fmt.Sprintf("%v: %v - %v\n", h.Address, h.Status, h.Os) 84 | for _, port := range h.Ports { 85 | out += port.String() 86 | } 87 | return out 88 | } 89 | 90 | func getNmapHostId(con *sql.DB, hosts []nmap.XMLHost) (int, error) { 91 | hostid := make([]int, 0, 3) 92 | for _, host := range hosts { 93 | for _, address := range host.Address { 94 | var t int 95 | err := con.QueryRow("select id from host where ipv4=?", string(address.Addr)).Scan(&t) 96 | if err != nil { 97 | return -1, err 98 | } 99 | hostid = append(hostid, t) 100 | } 101 | } 102 | 103 | switch len(hostid) { 104 | case 1: 105 | return hostid[0], nil 106 | case 2: 107 | log.Print("Multiple hostid, returning only the first") 108 | return hostid[0], nil 109 | default: 110 | return -1, errors.New("Could not get hostid") 111 | } 112 | } 113 | 114 | func listPorts(hosts []nmap.XMLHost) []Port { 115 | t_ports := make([]Port, 0, 10) 116 | for _, host := range hosts { 117 | for _, ports := range host.Ports { 118 | for _, port := range ports.Port { 119 | var service Service 120 | if port.Service != nil { 121 | service = Service{ 122 | Name: port.Service.Name, 123 | Version: port.Service.Version, 124 | Product: port.Service.Product, 125 | OsType: port.Service.Ostype, 126 | } 127 | } 128 | p_id, _ := strconv.Atoi(port.Portid) 129 | t_ports = append(t_ports, Port{ 130 | Number: p_id, 131 | Protocol: port.Protocol, 132 | Status: port.State.State, 133 | Service: service}) 134 | } 135 | } 136 | } 137 | return t_ports 138 | } 139 | 140 | func get_status(hosts []nmap.XMLHost) string { 141 | for _, host := range hosts { 142 | for _, statuses := range host.Status { 143 | return statuses.State 144 | } 145 | } 146 | return "" 147 | } 148 | 149 | func get_os(hosts []nmap.XMLHost) string { 150 | for _, host := range hosts { 151 | for _, oses := range host.Os { 152 | for _, osmatch := range oses.Osmatch { 153 | return osmatch.Name 154 | } 155 | } 156 | } 157 | return "" 158 | } 159 | 160 | // Parse data from file in parameter 161 | func parseAllXmlData(filepath string) { 162 | scans := make(Scans, 0, 100) 163 | scans.Load(filepath) 164 | for _, scan := range scans { 165 | if scan.Result.Nmap == nil { 166 | continue 167 | } 168 | s_reader := strings.NewReader(string(scan.Result.Nmap)) 169 | v := nmap.XMLNmaprun{} 170 | decoder := xml.NewDecoder(s_reader) 171 | err := decoder.Decode(&v) 172 | if err != nil { 173 | log.Printf("parsing result of %v failed: %v", scan.Host, err) 174 | return 175 | } 176 | 177 | host := Host{ 178 | Address: scan.Host, 179 | Status: get_status(v.Host), 180 | Os: get_os(v.Host), 181 | Ports: listPorts(v.Host)} 182 | 183 | fmt.Print(host) 184 | } 185 | } 186 | 187 | func parseRun(c *cli.Context) { 188 | if !c.Args().Present() { 189 | log.Fatal("Need a json file to parse") 190 | } 191 | parseAllXmlData(c.Args().First()) 192 | } 193 | -------------------------------------------------------------------------------- /cmd/run.go: -------------------------------------------------------------------------------- 1 | package cmd 2 | 3 | import ( 4 | "encoding/gob" 5 | "fmt" 6 | "github.com/codegangsta/cli" 7 | "io" 8 | "log" 9 | "net" 10 | "os" 11 | "sync" 12 | "time" 13 | ) 14 | 15 | var CmdRun = cli.Command{ 16 | Name: "run", 17 | Usage: "Lance les routines de scan des adresses de destinations", 18 | Action: runScan, 19 | Flags: []cli.Flag{ 20 | cli.StringFlag{ 21 | Name: "listen, l", 22 | Value: "localhost:3999", 23 | Usage: "Set listen address and port", 24 | }, 25 | cli.StringFlag{ 26 | Name: "database, d", 27 | Value: "test.json", 28 | Usage: "Database filename for Json output", 29 | }, 30 | cli.IntFlag{ 31 | Name: "notification-delay, n", 32 | Value: 5, 33 | Usage: "This is the notification delay to keep track of current working scan", 34 | }, 35 | cli.IntFlag{ 36 | Name: "worker, w", 37 | Value: 5, 38 | Usage: "Handle number of thread simultaneously running", 39 | }, 40 | }, 41 | } 42 | 43 | var ( 44 | database_file string 45 | scans Scans 46 | ch_scan chan *Scan 47 | mutex sync.Mutex 48 | notification_delay time.Duration 49 | ) 50 | 51 | const buffered_channel_size = 1 << 16 52 | 53 | func workerPool(workerPoolSize int) { 54 | for i := 0; i < workerPoolSize; i++ { 55 | go worker() 56 | } 57 | } 58 | 59 | // Call all commands to execute 60 | func worker() { 61 | var s *Scan 62 | for { 63 | s = <-ch_scan 64 | log.Printf("Received Work : %v\n", s.Host) 65 | // Call ping command 66 | if s.Status < icmp_done { 67 | s.DoPing() 68 | } 69 | 70 | // Call nmap command if not already done 71 | if s.Status < nmap_done { 72 | s.DoNmap() 73 | } 74 | 75 | if s.Status == nmap_done { 76 | s.Status = finished 77 | } 78 | 79 | // Write data to file 80 | mutex.Lock() 81 | scans.Save(database_file) 82 | mutex.Unlock() 83 | } 84 | } 85 | 86 | func listenGansScan(listen_address string) { 87 | log.Print("Waiting for incoming connection") 88 | ln, err := net.Listen("tcp", listen_address) 89 | if err != nil { 90 | log.Fatal("Could not start listen for incoming data to scan: ", err) 91 | } 92 | for { 93 | conn, err := ln.Accept() 94 | if err != nil { 95 | log.Print("Could not open connection for this client : ", err) 96 | } 97 | go handleConnection(conn) 98 | } 99 | } 100 | 101 | func handleConnection(conn net.Conn) { 102 | dec := gob.NewDecoder(conn) 103 | // Save all captured order to file "test.json" for now when the client is closing connection 104 | defer func() { 105 | err := scans.Save(database_file) 106 | if err != nil { 107 | log.Print("Could not save data to file : ", err) 108 | } 109 | }() 110 | for { 111 | var scan Scan 112 | err := dec.Decode(&scan) 113 | switch { 114 | case err == io.EOF: 115 | return 116 | case err != nil: 117 | log.Print("Could not decode packet from client : ", err) 118 | return 119 | } 120 | var ok bool 121 | // this allow to verify if scan is not already in the scan list 122 | for _, s := range scans { 123 | if scan.Host == s.Host { 124 | fmt.Printf("%v already in database\n", scan.Host) 125 | ok = true 126 | } 127 | } 128 | if !ok { 129 | scans = append(scans, scan) 130 | ch_scan <- &scans[len(scans)-1] 131 | } else { 132 | continue 133 | } 134 | } 135 | } 136 | 137 | func report_status() { 138 | ticker := time.Tick(notification_delay) 139 | for { 140 | var err bool = false 141 | <-ticker 142 | // make a copy of scans to avoid modification 143 | for _, scan := range scans { 144 | switch { 145 | case scan.Status == null: 146 | break 147 | case scan.Status == icmp_failed || scan.Status == nmap_failed: 148 | err = true 149 | case scan.Status == icmp_in_progress: 150 | log.Println("Icmp work in progress on host:", scan.Host) 151 | case scan.Status < nmap_in_progress: 152 | log.Println("Nmap work in progress on host:", scan.Host) 153 | } 154 | } 155 | if err { 156 | fmt.Println("Attention, des erreurs ont été détectée, Veuillez relancer « gans run »") 157 | } 158 | } 159 | } 160 | 161 | func runScan(c *cli.Context) { 162 | // Check for root now, better solution has to be found 163 | if os.Geteuid() != 0 { 164 | fmt.Println("This program need to have root permission to execute nmap for now.") 165 | os.Exit(1) 166 | } 167 | 168 | notification_delay = time.Duration(c.Int("notification-delay")) * time.Second 169 | 170 | // création de la structure de scan 171 | scans = make(Scans, 0, 100) 172 | 173 | // read work data from datafile where everything is stored. 174 | log.Print("Read data from saved files") 175 | database_file = c.String("database") 176 | scans.Load(database_file) 177 | 178 | // launch workers 179 | log.Print("Launching worker to nmap scan dest files") 180 | ch_scan = make(chan *Scan, buffered_channel_size) 181 | workerPool(c.Int("worker")) 182 | 183 | // initial feeder 184 | for i := 0; i < len(scans); i++ { 185 | if scans[i].Status != finished { 186 | ch_scan <- &scans[i] 187 | } 188 | } 189 | 190 | go report_status() 191 | 192 | // écoute des connexions réseau : 193 | listenGansScan(c.String("listen")) 194 | 195 | } 196 | -------------------------------------------------------------------------------- /cmd/scan.go: -------------------------------------------------------------------------------- 1 | package cmd 2 | 3 | import ( 4 | "bufio" 5 | "encoding/gob" 6 | "log" 7 | "net" 8 | "os" 9 | "os/exec" 10 | "regexp" 11 | 12 | "github.com/codegangsta/cli" 13 | ) 14 | 15 | var CmdScan = cli.Command{ 16 | Name: "scan", 17 | Usage: "Send IP addresses to main process", 18 | Action: runScanner, 19 | Description: "This command receive IP adresses, network range or a file with an IP address per line and send it to manager.", 20 | Flags: []cli.Flag{ 21 | cli.StringFlag{ 22 | Name: "f, file", 23 | Value: "", 24 | Usage: "Send each line of the file to manager for scanning", 25 | }, 26 | cli.StringFlag{ 27 | Name: "listen, l", 28 | Value: "localhost:3999", 29 | Usage: "Unix socket to send scan orders", 30 | }, 31 | }, 32 | } 33 | 34 | // This function extract list of IP Address from nmap command output in []byte 35 | func filter_nmap_list_command(b []byte) []string { 36 | inlist := make([]string, 0, 10) 37 | outlist := make([]string, 0, 10) 38 | index := 0 39 | inlist = append(inlist, "") 40 | reg, err := regexp.Compile("Nmap scan report for ([a-zA-Z0-9.]+)") 41 | if err != nil { 42 | return nil 43 | } 44 | for _, char := range b { // Convert []byte into a []string 45 | if char != '\n' { 46 | inlist[index] = inlist[index] + string(char) 47 | } else { 48 | index += 1 49 | inlist = append(inlist, "") 50 | } 51 | } 52 | inlist = inlist[1 : len(inlist)-2] 53 | for _, line := range inlist { 54 | res := reg.FindStringSubmatch(line) 55 | if res != nil { 56 | outlist = append(outlist, res[1]) 57 | } 58 | } 59 | return outlist 60 | } 61 | 62 | // Create a new connection to the server 63 | func newConnection(listen_address string) net.Conn { 64 | conn, err := net.Dial("tcp", listen_address) 65 | if err != nil { 66 | log.Fatal("Failed to connect to server: ", err) 67 | } 68 | return conn 69 | } 70 | 71 | func runScanner(c *cli.Context) { 72 | if !c.Args().Present() && (c.String("file") == "") { 73 | cli.ShowCommandHelp(c, "scan") 74 | } 75 | 76 | // Connexion au serveur de gestion des scan 77 | conn := newConnection(c.String("listen")) 78 | defer conn.Close() 79 | 80 | //initialisation de l'encodeur 81 | encoder := gob.NewEncoder(conn) 82 | 83 | if c.String("file") != "" { 84 | file, err := os.Open(c.String("file")) 85 | if err != nil { 86 | log.Fatal("Could not open file: ", err) 87 | } 88 | defer file.Close() 89 | scanner := bufio.NewScanner(file) 90 | for scanner.Scan() { 91 | elt := scanner.Text() // need to filter data from client. 92 | scan := Scan{elt, null, Result{}} 93 | encoder.Encode(scan) 94 | } 95 | log.Printf("IP addresses from %q has been sent\n", c.String("file")) 96 | } else { 97 | // for each argument, run nmap on it and send it to network 98 | for _, argument := range c.Args() { 99 | nmap_list_bytes, err := exec.Command("nmap", "-n", "-sL", argument).Output() 100 | if err != nil { 101 | log.Fatal("Execution of \"nmap\" command failed: ", err) 102 | } 103 | outlist := filter_nmap_list_command(nmap_list_bytes) 104 | if len(outlist) == 0 { // if outlist is void, pass 105 | continue 106 | } 107 | for _, elt := range outlist { 108 | scan := Scan{elt, null, Result{}} 109 | encoder.Encode(scan) 110 | } 111 | log.Printf("IP address from %v has been sent\n", argument) 112 | } 113 | } 114 | } 115 | -------------------------------------------------------------------------------- /cmd/type.go: -------------------------------------------------------------------------------- 1 | package cmd 2 | 3 | import ( 4 | "bytes" 5 | "encoding/json" 6 | "log" 7 | "os" 8 | "os/exec" 9 | "path" 10 | ) 11 | 12 | const ( 13 | null = iota 14 | icmp_in_progress 15 | icmp_failed 16 | icmp_done 17 | nmap_in_progress 18 | nmap_failed 19 | nmap_done 20 | finished 21 | ) 22 | 23 | type Scan struct { 24 | Host string 25 | Status int 26 | Result Result 27 | } 28 | 29 | func (s *Scan) Equal(d *Scan) bool { 30 | return s.Host == d.Host && s.Status == d.Status && s.Result.Equal(&d.Result) 31 | } 32 | 33 | func (s *Scan) DoPing() { 34 | s.Status = icmp_in_progress 35 | cmd := exec.Command("/bin/ping", "-c", "2", s.Host) 36 | var err error 37 | s.Result.Icmp, err = cmd.Output() 38 | if err != nil { 39 | log.Printf("Failed to ping destination %s: %s", s.Host, err) 40 | s.Result.Icmp = []byte("Failed") 41 | // bypass icmp_failed for now, icmp failed in case host is not responding 42 | //s.Status = icmp_failed 43 | } else { 44 | s.Status = icmp_done 45 | } 46 | } 47 | 48 | func (s *Scan) DoNmap() { 49 | if s.Status == icmp_failed { 50 | return 51 | } 52 | s.Status = nmap_in_progress 53 | cmd := exec.Command("nmap", 54 | "-n", 55 | "-T3", // Temporisation 3 moyen (0 lent, 5 rapide) 56 | "-sS", // SYN scan 57 | "-sV", // Detection de version 58 | "-oX", "-", // Sortie en XML 59 | "--verbose", // Plus de verbosité 60 | "-O", // Detection de l'OS 61 | "-p -", // Tous les ports réseau 62 | s.Host) 63 | res, err := cmd.Output() 64 | s.Result.Nmap = res 65 | if err != nil { 66 | log.Printf("Failed to nmap destination %s: %s", s.Host, err) 67 | s.Status = nmap_failed 68 | } else { 69 | log.Printf("Finished Work for %v\n", s.Host) 70 | s.Status = nmap_done 71 | } 72 | } 73 | 74 | type Result struct { 75 | Nmap []byte 76 | Icmp []byte 77 | } 78 | 79 | func (s *Result) Equal(d *Result) bool { 80 | return bytes.Equal(s.Nmap, d.Nmap) && bytes.Equal(s.Icmp, d.Icmp) 81 | } 82 | 83 | type Scans []Scan 84 | 85 | // save all scan structure to filepath in JSON format 86 | func (s *Scans) Save(filepath string) error { 87 | var err error 88 | var backup_path string = path.Clean("." + filepath) 89 | file, err := os.Create(backup_path) 90 | if err != nil { 91 | return err 92 | } 93 | defer file.Close() 94 | enc := json.NewEncoder(file) 95 | enc.Encode(s) 96 | file.Close() 97 | err = os.Rename(backup_path, filepath) 98 | if err != nil { 99 | return err 100 | } 101 | return nil 102 | } 103 | 104 | // load data from source file 105 | func (s *Scans) Load(filepath string) error { 106 | var err error 107 | file, err := os.Open(filepath) 108 | if err != nil { 109 | return err 110 | } 111 | defer file.Close() 112 | dec := json.NewDecoder(file) 113 | err = dec.Decode(s) 114 | if err != nil { 115 | return err 116 | } 117 | return nil 118 | } 119 | -------------------------------------------------------------------------------- /gans.go: -------------------------------------------------------------------------------- 1 | // GANS : Go Automated Nmap Scanner 2 | // This permit to launch a scanner and add adresses to be scanned. 3 | package main 4 | 5 | import ( 6 | "github.com/codegangsta/cli" 7 | "github.com/restanrm/gans/cmd" 8 | "os" 9 | ) 10 | 11 | func main() { 12 | app := cli.NewApp() 13 | app.Name = "Gans" 14 | app.Usage = "Go automated Nmap scanner" 15 | app.Commands = []cli.Command{ 16 | cmd.CmdScan, 17 | cmd.CmdRun, 18 | cmd.CmdParse, 19 | } 20 | app.Run(os.Args) 21 | } 22 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/restanrm/gans 2 | 3 | go 1.12 4 | 5 | require ( 6 | github.com/codegangsta/cli v1.20.0 7 | github.com/go-sql-driver/mysql v1.4.1 8 | ) 9 | -------------------------------------------------------------------------------- /go.sum: -------------------------------------------------------------------------------- 1 | github.com/codegangsta/cli v1.20.0 h1:iX1FXEgwzd5+XN6wk5cVHOGQj6Q3Dcp20lUeS4lHNTw= 2 | github.com/codegangsta/cli v1.20.0/go.mod h1:/qJNoX69yVSKu5o4jLyXAENLRyk1uhi7zkbQ3slBdOA= 3 | github.com/go-sql-driver/mysql v1.4.1 h1:g24URVg0OFbNUTx9qqY1IRZ9D9z3iPyi5zKhQZpNwpA= 4 | github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= 5 | -------------------------------------------------------------------------------- /nmap/nmap_definition.go: -------------------------------------------------------------------------------- 1 | package nmap 2 | 3 | import ( 4 | "encoding/xml" 5 | ) 6 | 7 | type XMLTable struct { 8 | XMLName xml.Name `xml:"table"` 9 | Key string `xml:"key,attr,omitempty"` 10 | Table []XMLTable `xml:"table,omitempty"` 11 | Elem []XMLElem `xml:"elem,omitempty"` 12 | } 13 | 14 | type XMLOsclass struct { 15 | XMLName xml.Name `xml:"osclass"` 16 | Osgen string `xml:"osgen,attr,omitempty"` 17 | Vendor string `xml:"vendor,attr"` 18 | Accuracy string `xml:"accuracy,attr"` 19 | Type string `xml:"type,attr,omitempty"` 20 | Osfamily string `xml:"osfamily,attr"` 21 | Cpe []XMLCpe `xml:"cpe,omitempty"` 22 | } 23 | 24 | type XMLTrace struct { 25 | XMLName xml.Name `xml:"trace"` 26 | Proto string `xml:"proto,attr,omitempty"` 27 | Port string `xml:"port,attr,omitempty"` 28 | Hop []XMLHop `xml:"hop,omitempty"` 29 | } 30 | 31 | type XMLTcptssequence struct { 32 | XMLName xml.Name `xml:"tcptssequence"` 33 | Values string `xml:"values,attr,omitempty"` 34 | Class string `xml:"class,attr"` 35 | } 36 | 37 | type XMLUptime struct { 38 | XMLName xml.Name `xml:"uptime"` 39 | Lastboot string `xml:"lastboot,attr,omitempty"` 40 | Seconds string `xml:"seconds,attr"` 41 | } 42 | 43 | type XMLPorts struct { 44 | XMLName xml.Name `xml:"ports"` 45 | Port []XMLPort `xml:"port,omitempty"` 46 | Extraports []XMLExtraports `xml:"extraports,omitempty"` 47 | } 48 | 49 | type XMLStatus struct { 50 | XMLName xml.Name `xml:"status"` 51 | ReasonTtl string `xml:"reason_ttl,attr"` 52 | Reason string `xml:"reason,attr"` 53 | State string `xml:"state,attr"` 54 | } 55 | 56 | type XMLOsmatch struct { 57 | XMLName xml.Name `xml:"osmatch"` 58 | Line string `xml:"line,attr"` 59 | Accuracy string `xml:"accuracy,attr"` 60 | Name string `xml:"name,attr"` 61 | Osclass []XMLOsclass `xml:"osclass,omitempty"` 62 | } 63 | 64 | type XMLPortused struct { 65 | XMLName xml.Name `xml:"portused"` 66 | Proto string `xml:"proto,attr"` 67 | State string `xml:"state,attr"` 68 | Portid string `xml:"portid,attr"` 69 | } 70 | 71 | type XMLOs struct { 72 | XMLName xml.Name `xml:"os"` 73 | Portused []XMLPortused `xml:"portused,omitempty"` 74 | Osmatch []XMLOsmatch `xml:"osmatch,omitempty"` 75 | Osfingerprint []XMLOsfingerprint `xml:"osfingerprint,omitempty"` 76 | } 77 | 78 | type XMLTcpsequence struct { 79 | XMLName xml.Name `xml:"tcpsequence"` 80 | Difficulty string `xml:"difficulty,attr"` 81 | Values string `xml:"values,attr"` 82 | Index string `xml:"index,attr"` 83 | } 84 | 85 | type XMLTimes struct { 86 | XMLName xml.Name `xml:"times"` 87 | Srtt string `xml:"srtt,attr"` 88 | Rttvar string `xml:"rttvar,attr"` 89 | To string `xml:"to,attr"` 90 | } 91 | 92 | type XMLOsfingerprint struct { 93 | XMLName xml.Name `xml:"osfingerprint"` 94 | Fingerprint string `xml:"fingerprint,attr"` 95 | } 96 | 97 | type XMLOutput struct { 98 | XMLName xml.Name `xml:"output"` 99 | Type string `xml:"type,attr,omitempty"` 100 | Value string `xml:",chardata"` 101 | } 102 | 103 | type XMLPrescript struct { 104 | XMLName xml.Name `xml:"prescript"` 105 | Script []XMLScript `xml:"script"` 106 | } 107 | 108 | type XMLTaskend struct { 109 | XMLName xml.Name `xml:"taskend"` 110 | Extrainfo string `xml:"extrainfo,attr,omitempty"` 111 | Time string `xml:"time,attr"` 112 | Task string `xml:"task,attr"` 113 | } 114 | 115 | type XMLTaskprogress struct { 116 | XMLName xml.Name `xml:"taskprogress"` 117 | Task string `xml:"task,attr"` 118 | Etc string `xml:"etc,attr"` 119 | Time string `xml:"time,attr"` 120 | Remaining string `xml:"remaining,attr"` 121 | Percent string `xml:"percent,attr"` 122 | } 123 | 124 | type XMLTaskbegin struct { 125 | XMLName xml.Name `xml:"taskbegin"` 126 | Time string `xml:"time,attr"` 127 | Task string `xml:"task,attr"` 128 | Extrainfo string `xml:"extrainfo,attr,omitempty"` 129 | } 130 | 131 | type XMLTarget struct { 132 | XMLName xml.Name `xml:"target"` 133 | Specification string `xml:"specification,attr"` 134 | Reason string `xml:"reason,attr,omitempty"` 135 | Status string `xml:"status,attr,omitempty"` 136 | } 137 | 138 | type XMLPostscript struct { 139 | XMLName xml.Name `xml:"postscript"` 140 | Script []XMLScript `xml:"script"` 141 | } 142 | 143 | type XMLSmurf struct { 144 | XMLName xml.Name `xml:"smurf"` 145 | Responses string `xml:"responses,attr"` 146 | } 147 | 148 | type XMLService struct { 149 | XMLName xml.Name `xml:"service"` 150 | Ostype string `xml:"ostype,attr,omitempty"` 151 | Servicefp string `xml:"servicefp,attr,omitempty"` 152 | Conf string `xml:"conf,attr"` 153 | Hostname string `xml:"hostname,attr,omitempty"` 154 | Proto string `xml:"proto,attr,omitempty"` 155 | Version string `xml:"version,attr,omitempty"` 156 | Lowver string `xml:"lowver,attr,omitempty"` 157 | Product string `xml:"product,attr,omitempty"` 158 | Name string `xml:"name,attr"` 159 | Devicetype string `xml:"devicetype,attr,omitempty"` 160 | Method string `xml:"method,attr"` 161 | Rpcnum string `xml:"rpcnum,attr,omitempty"` 162 | Tunnel string `xml:"tunnel,attr,omitempty"` 163 | Extrainfo string `xml:"extrainfo,attr,omitempty"` 164 | Highver string `xml:"highver,attr,omitempty"` 165 | Cpe []XMLCpe `xml:"cpe,omitempty"` 166 | } 167 | 168 | type XMLOwner struct { 169 | XMLName xml.Name `xml:"owner"` 170 | Name string `xml:"name,attr"` 171 | } 172 | 173 | type XMLState struct { 174 | XMLName xml.Name `xml:"state"` 175 | State string `xml:"state,attr"` 176 | ReasonIp string `xml:"reason_ip,attr,omitempty"` 177 | ReasonTtl string `xml:"reason_ttl,attr"` 178 | Reason string `xml:"reason,attr"` 179 | } 180 | 181 | type XMLPort struct { 182 | XMLName xml.Name `xml:"port"` 183 | Protocol string `xml:"protocol,attr"` 184 | Portid string `xml:"portid,attr"` 185 | Service *XMLService `xml:"service,omitempty"` 186 | Owner *XMLOwner `xml:"owner,omitempty"` 187 | State *XMLState `xml:"state"` 188 | Script []XMLScript `xml:"script,omitempty"` 189 | } 190 | 191 | type XMLRunstats struct { 192 | XMLName xml.Name `xml:"runstats"` 193 | Finished *XMLFinished `xml:"finished"` 194 | Hosts *XMLHosts `xml:"hosts"` 195 | } 196 | 197 | type XMLVerbose struct { 198 | XMLName xml.Name `xml:"verbose"` 199 | Level string `xml:"level,attr,omitempty"` 200 | } 201 | 202 | type XMLScaninfo struct { 203 | XMLName xml.Name `xml:"scaninfo"` 204 | Services string `xml:"services,attr"` 205 | Protocol string `xml:"protocol,attr"` 206 | Numservices string `xml:"numservices,attr"` 207 | Scanflags string `xml:"scanflags,attr,omitempty"` 208 | Type string `xml:"type,attr"` 209 | } 210 | 211 | type XMLNmaprun struct { 212 | XMLName xml.Name `xml:"nmaprun"` 213 | Args string `xml:"args,attr,omitempty"` 214 | Start string `xml:"start,attr,omitempty"` 215 | Xmloutputversion string `xml:"xmloutputversion,attr"` 216 | Scanner string `xml:"scanner,attr"` 217 | Version string `xml:"version,attr"` 218 | ProfileName string `xml:"profile_name,attr,omitempty"` 219 | Startstr string `xml:"startstr,attr,omitempty"` 220 | Verbose *XMLVerbose `xml:"verbose"` 221 | Scaninfo []XMLScaninfo `xml:"scaninfo,omitempty"` 222 | Runstats *XMLRunstats `xml:"runstats"` 223 | Debugging *XMLDebugging `xml:"debugging"` 224 | Target []XMLTarget `xml:"target,omitempty"` 225 | Taskbegin []XMLTaskbegin `xml:"taskbegin,omitempty"` 226 | Taskprogress []XMLTaskprogress `xml:"taskprogress,omitempty"` 227 | Taskend []XMLTaskend `xml:"taskend,omitempty"` 228 | Prescript []XMLPrescript `xml:"prescript,omitempty"` 229 | Postscript []XMLPostscript `xml:"postscript,omitempty"` 230 | Host []XMLHost `xml:"host,omitempty"` 231 | Output []XMLOutput `xml:"output,omitempty"` 232 | } 233 | 234 | type XMLIpidsequence struct { 235 | XMLName xml.Name `xml:"ipidsequence"` 236 | Class string `xml:"class,attr"` 237 | Values string `xml:"values,attr"` 238 | } 239 | 240 | type XMLHosts struct { 241 | XMLName xml.Name `xml:"hosts"` 242 | Total string `xml:"total,attr"` 243 | Down string `xml:"down,attr,omitempty"` 244 | Up string `xml:"up,attr,omitempty"` 245 | } 246 | 247 | type XMLScript struct { 248 | XMLName xml.Name `xml:"script"` 249 | Id string `xml:"id,attr"` 250 | Output string `xml:"output,attr"` 251 | Table []XMLTable `xml:"table,omitempty"` 252 | Elem []XMLElem `xml:"elem,omitempty"` 253 | } 254 | 255 | type XMLHostscript struct { 256 | XMLName xml.Name `xml:"hostscript"` 257 | Script []XMLScript `xml:"script"` 258 | } 259 | 260 | type XMLHostnames struct { 261 | XMLName xml.Name `xml:"hostnames"` 262 | Hostname []XMLHostname `xml:"hostname,omitempty"` 263 | } 264 | 265 | type XMLHostname struct { 266 | XMLName xml.Name `xml:"hostname"` 267 | Name string `xml:"name,attr,omitempty"` 268 | Type string `xml:"type,attr,omitempty"` 269 | } 270 | 271 | type XMLHost struct { 272 | XMLName xml.Name `xml:"host"` 273 | Comment string `xml:"comment,attr,omitempty"` 274 | Endtime string `xml:"endtime,attr,omitempty"` 275 | Starttime string `xml:"starttime,attr,omitempty"` 276 | Status []XMLStatus `xml:"status,omitempty"` 277 | Address []XMLAddress `xml:"address,omitempty"` 278 | Hostnames []XMLHostnames `xml:"hostnames,omitempty"` 279 | Smurf []XMLSmurf `xml:"smurf,omitempty"` 280 | Ports []XMLPorts `xml:"ports,omitempty"` 281 | Os []XMLOs `xml:"os,omitempty"` 282 | Distance []XMLDistance `xml:"distance,omitempty"` 283 | Uptime []XMLUptime `xml:"uptime,omitempty"` 284 | Tcpsequence []XMLTcpsequence `xml:"tcpsequence,omitempty"` 285 | Ipidsequence []XMLIpidsequence `xml:"ipidsequence,omitempty"` 286 | Tcptssequence []XMLTcptssequence `xml:"tcptssequence,omitempty"` 287 | Hostscript []XMLHostscript `xml:"hostscript,omitempty"` 288 | Trace []XMLTrace `xml:"trace,omitempty"` 289 | Times []XMLTimes `xml:"times,omitempty"` 290 | } 291 | 292 | type XMLHop struct { 293 | XMLName xml.Name `xml:"hop"` 294 | Ttl string `xml:"ttl,attr"` 295 | Rtt string `xml:"rtt,attr,omitempty"` 296 | Host string `xml:"host,attr,omitempty"` 297 | Ipaddr string `xml:"ipaddr,attr,omitempty"` 298 | } 299 | 300 | type XMLFinished struct { 301 | XMLName xml.Name `xml:"finished"` 302 | Timestr string `xml:"timestr,attr,omitempty"` 303 | Exit string `xml:"exit,attr,omitempty"` 304 | Time string `xml:"time,attr"` 305 | Summary string `xml:"summary,attr,omitempty"` 306 | Elapsed string `xml:"elapsed,attr"` 307 | Errormsg string `xml:"errormsg,attr,omitempty"` 308 | } 309 | 310 | type XMLExtrareasons struct { 311 | XMLName xml.Name `xml:"extrareasons"` 312 | Reason string `xml:"reason,attr"` 313 | Count string `xml:"count,attr"` 314 | } 315 | 316 | type XMLExtraports struct { 317 | XMLName xml.Name `xml:"extraports"` 318 | Count string `xml:"count,attr"` 319 | State string `xml:"state,attr"` 320 | Extrareasons []XMLExtrareasons `xml:"extrareasons,omitempty"` 321 | } 322 | 323 | type XMLElem struct { 324 | XMLName xml.Name `xml:"elem"` 325 | Key string `xml:"key,attr,omitempty"` 326 | Value string `xml:",chardata"` 327 | } 328 | 329 | type XMLDistance struct { 330 | XMLName xml.Name `xml:"distance"` 331 | Value string `xml:"value,attr"` 332 | } 333 | 334 | type XMLDebugging struct { 335 | XMLName xml.Name `xml:"debugging"` 336 | Level string `xml:"level,attr,omitempty"` 337 | } 338 | 339 | type XMLCpe struct { 340 | XMLName xml.Name `xml:"cpe"` 341 | Value string `xml:",chardata"` 342 | } 343 | 344 | type XMLAddress struct { 345 | XMLName xml.Name `xml:"address"` 346 | Addrtype string `xml:"addrtype,attr,omitempty"` 347 | Vendor string `xml:"vendor,attr,omitempty"` 348 | Addr string `xml:"addr,attr"` 349 | } 350 | --------------------------------------------------------------------------------