-
Notifications
You must be signed in to change notification settings - Fork 108
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add RunAsync() method #6
Comments
Have you had time to look at this more ? If not, I’ll start looking into how to add this properly. It’s be nice to have. |
Hey @TheSecEng I didn't have time as of now, I've been working on other projects, but if you're interested in picking this one up I'd love to give you any help you need :) |
@Ullaakut you got it! |
@Ullaakut Thoughts? As I wasn't fully understanding of channels. This would be a solution I propose. However, if this doesn't meet the full need. I'll need to research further into channels and take time to really understand them. I think this method avoids some of the pains of using channels, but potentially at the sacrifice of easily putting the results into a private var then exposing it. But then again, it would require // Scanner represents an Nmap scanner.
type Scanner struct {
Cmd *exec.Cmd
args []string
binaryPath string
ctx context.Context
portFilter func(Port) bool
hostFilter func(Host) bool
Stderr, Stdout bufio.Scanner
} // RunAsync runs nmap asynchronously and returns error.
func (s *Scanner) RunAsync() error {
// Enable XML output
s.args = append(s.args, "-oX")
// Get XML output in stdout instead of writing it in a file
s.args = append(s.args, "-")
s.Cmd = exec.Command(s.binaryPath, s.args...)
stderr, err := s.Cmd.StderrPipe()
if err != nil {
return err
}
stdout, err := s.Cmd.StdoutPipe()
if err != nil {
return err
}
s.Stdout = *bufio.NewScanner(stdout)
s.Stderr = *bufio.NewScanner(stderr)
if err := s.Cmd.Start(); err != nil {
return err
}
go func() {
select {
case <-s.ctx.Done():
s.Cmd.Process.Kill()
}
}()
return nil
} Example package main
import (
"encoding/json"
"fmt"
"log"
"strings"
"github.com/Ullaakut/nmap"
)
func main() {
var resultBytes []byte
var errorBytes []byte
s, err := nmap.NewScanner(
nmap.WithTargets("google.com", "facebook.com", "youtube.co1m"),
nmap.WithPorts("80,443,843"),
)
if err != nil {
log.Fatalf("unable to create nmap scanner: %v", err)
}
if err := s.RunAsync(); err != nil {
panic(err)
}
go func() {
for s.Stdout.Scan() {
fmt.Println(s.Stdout.Text())
resultBytes = append(resultBytes, s.Stdout.Bytes()...)
}
}()
go func() {
for s.Stderr.Scan() {
errorBytes = append(errorBytes, s.Stderr.Bytes()...)
}
}()
if err := s.Cmd.Wait(); err != nil {
panic(err)
}
results, err := nmap.Parse(resultBytes)
results.NmapErrors = strings.Split(string(errorBytes), "\n")
if err != nil {
panic(err)
}
temp, err := json.MarshalIndent(results, "", " ")
if err != nil {
panic(err)
}
fmt.Printf("%s\n", temp)
} |
Hey @TheSecEng! Sorry about the delay. This looks like a good implementation! Thank you so much! It seems like a good first step to provide utility to people who might want to use it, but I'm curious how people will end up integrating it into their apps. Either way, I'd love to see it in the form of a PR and to work on it together! |
I've actually got a use case right now that I will be using this for once its finished. So there is definitely reasons to get this running. |
Allowing the users to run
nmap
asnchronously makes it possible to parse the livenmap
output, for example for building a UI on top, or computing a progress bar.I'm not sure if many people have this use-case though, so I won't prioritize this for now, but I find it really cool.
func (s *Scanner) RunAsync() (stdout chan <-[]byte, stderr chan <-[]byte, error)
nmap
process could not be started.nmap.Result
structure once the scan is doneThe text was updated successfully, but these errors were encountered: