-
Notifications
You must be signed in to change notification settings - Fork 56
Use as a library
Vsevolod Djagilev edited this page May 2, 2022
·
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/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/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" {
// 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" {
resp, err := sendRequest(host.HostAddress.Address, port.PortID, false)
if err != nil {
log.Printf("Fail http: %s:%d: %v", host.HostAddress.Address, port.PortID, err)
// Attempt https then
resp, err = sendRequest(host.HostAddress.Address, port.PortID, true)
if err != nil {
// Still fail, no point in continuing
log.Printf("Fail https: %s:%d: %v", host.HostAddress.Address, port.PortID, err)
continue
}
}
defer resp.Body.Close()
log.Printf("Req: %s:%d --->", host.HostAddress.Address, port.PortID)
log.Printf("Res: %s:%d: %d <---", host.HostAddress.Address, port.PortID, resp.StatusCode)
}
}
}
}
}