mirror of
https://github.com/anotherhadi/iknowyou.git
synced 2026-04-12 00:47:26 +02:00
init ghunt
Signed-off-by: Hadi <112569860+anotherhadi@users.noreply.github.com>
This commit is contained in:
@@ -3,6 +3,7 @@ package registry
|
||||
import (
|
||||
"github.com/anotherhadi/iknowyou/internal/tools"
|
||||
breachdirectory "github.com/anotherhadi/iknowyou/internal/tools/breachdirectory"
|
||||
ghunt "github.com/anotherhadi/iknowyou/internal/tools/ghunt"
|
||||
crtsh "github.com/anotherhadi/iknowyou/internal/tools/crtsh"
|
||||
digtool "github.com/anotherhadi/iknowyou/internal/tools/dig"
|
||||
githubrecon "github.com/anotherhadi/iknowyou/internal/tools/github-recon"
|
||||
@@ -25,6 +26,7 @@ var Factories = []func() tools.ToolRunner{
|
||||
gravatarrecon.New,
|
||||
whoisfreaks.New,
|
||||
maigret.New,
|
||||
ghunt.New,
|
||||
leakcheck.New,
|
||||
crtsh.New,
|
||||
breachdirectory.New,
|
||||
|
||||
123
back/internal/tools/ghunt/tool.go
Normal file
123
back/internal/tools/ghunt/tool.go
Normal file
@@ -0,0 +1,123 @@
|
||||
package ghunt
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"github.com/anotherhadi/iknowyou/internal/tools"
|
||||
)
|
||||
|
||||
var ansiRe = regexp.MustCompile(`\x1b[\x5b-\x5f][0-9;]*[A-Za-z]|\x1b[^[\x5b-\x5f]`)
|
||||
|
||||
const (
|
||||
name = "ghunt"
|
||||
description = "Google account OSINT via GHunt. Extracts profile info, linked services, and activity from a Google email address."
|
||||
link = "https://github.com/mxrch/GHunt"
|
||||
icon = "google"
|
||||
)
|
||||
|
||||
type Config struct {
|
||||
Creds string `yaml:"creds" iky:"desc=GHunt credentials (content of ~/.malfrats/ghunt/creds.m). To obtain: (1) install GHunt and run 'ghunt login' on your machine, (2) copy the full content of ~/.malfrats/ghunt/creds.m, (3) paste it here.;required=true"`
|
||||
}
|
||||
|
||||
type Runner struct {
|
||||
cfg Config
|
||||
}
|
||||
|
||||
func New() tools.ToolRunner {
|
||||
cfg := Config{}
|
||||
tools.ApplyDefaults(&cfg)
|
||||
return &Runner{cfg: cfg}
|
||||
}
|
||||
|
||||
func (r *Runner) Name() string { return name }
|
||||
func (r *Runner) Description() string { return description }
|
||||
func (r *Runner) Link() string { return link }
|
||||
func (r *Runner) Icon() string { return icon }
|
||||
|
||||
func (r *Runner) InputTypes() []tools.InputType {
|
||||
return []tools.InputType{
|
||||
tools.InputTypeEmail,
|
||||
}
|
||||
}
|
||||
|
||||
func (r *Runner) ConfigPtr() interface{} { return &r.cfg }
|
||||
|
||||
func (r *Runner) ConfigFields() []tools.ConfigField {
|
||||
return tools.ReflectConfigFields(r.cfg)
|
||||
}
|
||||
|
||||
func (r *Runner) Available() (bool, string) {
|
||||
if _, err := exec.LookPath("ghunt"); err != nil {
|
||||
return false, "ghunt binary not found in PATH"
|
||||
}
|
||||
return true, ""
|
||||
}
|
||||
|
||||
func (r *Runner) Dependencies() []string { return []string{"ghunt"} }
|
||||
|
||||
func (r *Runner) writeCreds() error {
|
||||
home, err := os.UserHomeDir()
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot determine home directory: %w", err)
|
||||
}
|
||||
dir := filepath.Join(home, ".malfrats", "ghunt")
|
||||
if err := os.MkdirAll(dir, 0700); err != nil {
|
||||
return fmt.Errorf("cannot create ghunt dir: %w", err)
|
||||
}
|
||||
return os.WriteFile(filepath.Join(dir, "creds.m"), []byte(r.cfg.Creds), 0600)
|
||||
}
|
||||
|
||||
func (r *Runner) Run(ctx context.Context, target string, _ tools.InputType, out chan<- tools.Event) error {
|
||||
defer close(out)
|
||||
|
||||
if err := r.writeCreds(); err != nil {
|
||||
out <- tools.Event{Tool: name, Type: tools.EventTypeError, Payload: err.Error()}
|
||||
out <- tools.Event{Tool: name, Type: tools.EventTypeDone}
|
||||
return nil
|
||||
}
|
||||
|
||||
cmd := exec.CommandContext(ctx, "ghunt", "email", target)
|
||||
output, err := tools.RunWithPTY(ctx, cmd)
|
||||
|
||||
output = strings.ReplaceAll(output, "\r\n", "\n")
|
||||
output = strings.ReplaceAll(output, "\r", "\n")
|
||||
|
||||
lines := strings.Split(output, "\n")
|
||||
parsed := make([]string, len(lines))
|
||||
for i, l := range lines {
|
||||
parsed[i] = ansiRe.ReplaceAllString(l, "")
|
||||
}
|
||||
|
||||
start := 0
|
||||
for i, l := range parsed {
|
||||
if strings.Contains(l, "[+] Authenticated !") {
|
||||
start = i + 1
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
end := len(lines)
|
||||
for i := start; i < len(parsed); i++ {
|
||||
if strings.Contains(parsed[i], "Traceback (most recent call last)") {
|
||||
end = i
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
output = strings.TrimSpace(strings.Join(lines[start:end], "\n"))
|
||||
|
||||
if err != nil && ctx.Err() != nil {
|
||||
out <- tools.Event{Tool: name, Type: tools.EventTypeError, Payload: "scan cancelled"}
|
||||
} else if output != "" {
|
||||
out <- tools.Event{Tool: name, Type: tools.EventTypeOutput, Payload: output}
|
||||
out <- tools.Event{Tool: name, Type: tools.EventTypeCount, Payload: 1}
|
||||
}
|
||||
out <- tools.Event{Tool: name, Type: tools.EventTypeDone}
|
||||
return nil
|
||||
}
|
||||
Reference in New Issue
Block a user