-
Notifications
You must be signed in to change notification settings - Fork 55
Use as a library
Vsevolod Djagilev edited this page Sep 28, 2023
·
4 revisions
It's possible to write golang code that allows to parse nmap xml and convert it to any format you want, or use parsed information further:
package main
import (
"encoding/xml"
"os"
"github.com/vdjagilev/nmap-formatter/v2/formatter"
)
func main() {
var nmap formatter.NMAPRun
var config formatter.Config = formatter.Config{}
// Read XML file that was produced by nmap (with -oX option)
content, err := os.ReadFile("example.xml")
if err != nil {
panic(err)
}
// Unmarshal XML and map structure(s) fields accordingly
if err = xml.Unmarshal(content, &nmap); err != nil {
panic(err)
}
// Output data to console stdout
// You can use any other io.Writer implementation
// for example: os.OpenFile("file.json", os.O_CREATE|os.O_EXCL|os.O_WRONLY, os.ModePerm)
config.Writer = os.Stdout
// Formatting data to JSON, you can use:
// CSVOutput, MarkdownOutput, HTMLOutput as well
config.OutputFormat = formatter.JSONOutput
// Setting formatter data/options
templateData := formatter.TemplateData{
NMAPRun: nmap, // NMAP output data itself
OutputOptions: formatter.OutputOptions{
JSONOptions: formatter.JSONOutputOptions{
PrettyPrint: true, // Additional option to prettify JSON
},
},
}
// New formatter instance
formatter := formatter.New(&config)
if formatter == nil {
// Not json/markdown/html/csv
panic("wrong formatter provided")
}
// Attempt to format the data
if err = formatter.Format(&templateData, "" /* no template content for JSON */); err != nil {
// html template could not be parsed or some other issue occured
panic(err)
}
}
In this example we parse example.xml
, go through all hosts that are online, filtering out only those ports that have http
services running. After that we attempt to make a request to that service via http, if that fails there is another attempt made to make a request via https, if that still fails we print those errors and continue to the next request.
package main
import (
"encoding/xml"
"fmt"
"log"
"net/http"
"os"
"github.com/vdjagilev/nmap-formatter/v2/formatter"
)
func sendRequest(address string, port int, https bool) (*http.Response, error) {
schema := "http"
if https {
schema = "https"
}
resp, err := http.Get(fmt.Sprintf("%s://%s:%d", schema, address, port))
if err != nil {
// I guess we fail
return nil, err
}
return resp, err
}
func main() {
var nmap formatter.NMAPRun
// var config formatter.Config = formatter.Config{}
// Read XML file that was produced by nmap (with -oX option)
content, err := os.ReadFile("example.xml")
if err != nil {
panic(err)
}
// Unmarshal XML and map structure(s) fields accordingly
if err = xml.Unmarshal(content, &nmap); err != nil {
panic(err)
}
for _, host := range nmap.Host {
// If host is up and receiving connections
if host.Status.State != "up" {
continue
}
// Iterating over all ports on that host
for _, port := range host.Port {
// If this port is has http service on it
if port.Service.Name == "http" {
for _, addr := range host.HostAddress {
resp, err := sendRequest(addr.Address, port.PortID, false)
if err != nil {
log.Printf("Fail http: %s:%d: %v", addr.Address, port.PortID, err)
// Attempt https then
resp, err = sendRequest(addr.Address, port.PortID, true)
if err != nil {
// Still fail, continue to the next port, if any
log.Printf("Fail https: %s:%d: %v", addr.Address, port.PortID, err)
continue
}
}
defer resp.Body.Close()
log.Printf("Req: %s:%d --->", addr.Address, port.PortID)
log.Printf("Res: %s:%d: %d <---", addr.Address, port.PortID, resp.StatusCode)
}
}
}
}
}
package main
import (
"encoding/xml"
"fmt"
"os"
"strings"
"github.com/vdjagilev/nmap-formatter/v2/formatter"
)
func main() {
// usage: go run use_as_csv.go <path_to_nmap_xml_file>
var nmap formatter.NMAPRun
content, err := os.ReadFile(os.Args[1])
if err != nil {
panic(err)
}
// Unmarshal XML and map structure(s) fields accordingly
if err = xml.Unmarshal(content, &nmap); err != nil {
panic(err)
}
// Print CSV headers for host address and joined ports
fmt.Println("address;ports")
// Use as CSV: Iterate over hosts and print their addresses and joined ports
for _, host := range nmap.Host {
if host.Status.State != "up" {
continue
}
// Print host address
fmt.Printf("%s;", host.JoinedAddresses(","))
// Print joined ports
for i, port := range host.Port {
if i != 0 {
fmt.Print(",")
}
fmt.Printf("%d/%s", port.PortID, strings.ToLower(port.Protocol))
}
fmt.Println()
}
}