Skip to content

Commit

Permalink
Merge pull request #18 from piaolin/dev
Browse files Browse the repository at this point in the history
Screenshot
  • Loading branch information
piaolin authored May 13, 2023
2 parents 2a4a307 + 8db35d2 commit 0e4dfc3
Show file tree
Hide file tree
Showing 8 changed files with 333 additions and 36 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,12 @@

# Output of the go coverage tool, specifically when used with LiteIDE
*.out
result.txt

# Dependency directories (remove the comment below to include it)
# vendor/
pack/

# Go workspace file
go.work
screenshots/
4 changes: 3 additions & 1 deletion .idea/DetectDee.iml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

29 changes: 29 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

DetectDee: Hunt down social media accounts by **username, email or phone** across [social networks](site.md)
![example.gif](https://s2.loli.net/2023/04/30/FZ1QtKoGud4xVPW.gif)
![screen.jpg](https://s2.loli.net/2023/05/13/XzV4EGKrbkURHQg.jpg)
## Feat
- Includes sites frequently used by **CyberSecurity practitioners**
- Hunt down social media accounts by **username, email or phone**
Expand Down Expand Up @@ -85,7 +86,35 @@ To search in specified site:
```shell
./DetectDee detect -n piaolin -s github,v2ex
```
### Screenshot
The screenshot function is used to screenshot the results of detect. Note that this function requires:
- Chrome
- A period of time
- A bit of memory usage
```shell
Usage:
DetectDee screenshot [flags]

Flags:
--chrome Show chrome
-d, --dir string Folder path of the screenshot (default "screenshots")
-f, --file string Url list file (default "result.txt")
-h, --help help for screenshot
--path string Chrome ExecPath
--proxy string Make requests over a proxy. e.g. socks5://127.0.0.1:1080
-t, --thread int Chrome number (default 3)
--timeout int Timeout (default 60)

Global Flags:
-v, --verbose verbose output
```

Screenshot the results of detect
```shell
./DetectDee screenshot
```
![result.jpg](https://s2.loli.net/2023/05/13/OWRDnU98TyCdceN.jpg)
![screen.jpg](https://s2.loli.net/2023/05/13/XzV4EGKrbkURHQg.jpg)
## Contributing
We would love to have you help us with the development of DetectDee. Each and every contribution is greatly valued!

Expand Down
30 changes: 29 additions & 1 deletion README_ZH.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

神探狄仁杰: 在[社交网络](site.md)上通过**用户名,电子邮件或电话**搜索社交媒体账户
![example.gif](https://s2.loli.net/2023/04/30/FZ1QtKoGud4xVPW.gif)
![screen.jpg](https://s2.loli.net/2023/05/13/XzV4EGKrbkURHQg.jpg)
## 特性
- 集成**网络安全从业者**常用网站
- 通过**用户名,电子邮件或电话**查找社交媒体账户
Expand Down Expand Up @@ -81,7 +82,34 @@ Global Flags:
```shell
./DetectDee detect -n piaolin -s github,v2ex
```

### 截屏
截屏功能用于将探测得来的结果进行访问截屏,请注意该功能需要:
- Chrome
- 一定时间
- 一定内存占用
```shell
Usage:
DetectDee screenshot [flags]

Flags:
--chrome Show chrome
-d, --dir string Folder path of the screenshot (default "screenshots")
-f, --file string Url list file (default "result.txt")
-h, --help help for screenshot
--path string Chrome ExecPath
--proxy string Make requests over a proxy. e.g. socks5://127.0.0.1:1080
-t, --thread int Chrome number (default 3)
--timeout int Timeout (default 60)

Global Flags:
-v, --verbose verbose output
```
对detect得到结果进行截屏
```shell
./DetectDee screenshot
```
![result.jpg](https://s2.loli.net/2023/05/13/OWRDnU98TyCdceN.jpg)
![screen.jpg](https://s2.loli.net/2023/05/13/XzV4EGKrbkURHQg.jpg)
## 贡献
希望您能帮助我们开发“神探狄仁杰”,您的每一份提交都会得到我的重视。

Expand Down
5 changes: 3 additions & 2 deletions cmd/detect.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ var (
wg sync.WaitGroup
nonSiteData = "[-] There is no site data of %s\n"
existInfo = "[+] %-15s %-15s: %s\n"
existOutputInfo = "%-15s %-15s: %s\n"
nonExistInfo = "[-] %-15s %-15s: non exists\n"
reqErrorInfo = "[!] %-15s %-15s: %s requests error, retry %d/%d\n"
sleepMap = make(map[string]int64)
Expand Down Expand Up @@ -321,12 +322,12 @@ func detectUser(name, site string, requestTimes, retryTimes, detectCount int, fl
} else if !detectArgs.precisely {
// flag=true && precisely=false
log.Infof(existInfo, name, site, userPage)
writeContent <- fmt.Sprintf(existInfo, name, site, userPage)
writeContent <- fmt.Sprintf(existOutputInfo, name, site, userPage)
return false
} else if requestTimes == detectCount {
// flag=true && precisely=true && last request
log.Infof(existInfo, name, site, userPage)
writeContent <- fmt.Sprintf(existInfo, name, site, userPage)
writeContent <- fmt.Sprintf(existOutputInfo, name, site, userPage)
return true
} else {
return true
Expand Down
231 changes: 231 additions & 0 deletions cmd/screenshot.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,231 @@
package cmd

import (
"bufio"
"context"
"fmt"
"io/ioutil"
"net/url"
"os"
"strings"
"sync"
"time"

"github.com/chromedp/chromedp"
log "github.com/sirupsen/logrus"
"github.com/spf13/cobra"
)

type screenshotArgsType struct {
proxy string
chrome bool
thread int
timeout int
path string
file string
result string
}

var (
screenshotArgs screenshotArgsType
screenshotWg sync.WaitGroup
targets = make(chan []string, 10)
execPathNotFound = "[-] Chrome executable file not found, please install Chrome or specify the chrome.exe path with --path"
urlFileReadError = "[-] failed to read targets file:%v"
createResultFolderError = "[-] failed to create result folder:%v"
)

func init() {
screenshotCmd.Flags().StringVar(&screenshotArgs.proxy, "proxy", "", "Make requests over a proxy. e.g. socks5://127.0.0.1:1080")
screenshotCmd.Flags().StringVar(&screenshotArgs.path, "path", "", "Chrome ExecPath")
screenshotCmd.Flags().StringVarP(&screenshotArgs.result, "dir", "d", "screenshots", "Folder path of the screenshot")
screenshotCmd.Flags().BoolVar(&screenshotArgs.chrome, "chrome", false, "Show chrome")
screenshotCmd.Flags().IntVarP(&screenshotArgs.thread, "thread", "t", 3, "Chrome number")
screenshotCmd.Flags().StringVarP(&screenshotArgs.file, "file", "f", "result.txt", "Url list file")
screenshotCmd.Flags().IntVar(&screenshotArgs.timeout, "timeout", 60, "Timeout")
rootCmd.AddCommand(screenshotCmd)
}

var screenshotCmd = &cobra.Command{
Use: "screenshot",
Short: "screenshot result with chrome headless",
Long: ``,
Run: screenshot,
}

func screenshot(_ *cobra.Command, _ []string) {
if Verbose {
log.Infoln("Debug Mode")
log.SetLevel(log.DebugLevel)
}

go parseFile(screenshotArgs.file)

err := CreateDirIfNotExists(screenshotArgs.result)
if err != nil {
log.Errorf(createResultFolderError, err)
return
}
log.Infoln("[+] starting screenshot tasks")

for i := 1; i < screenshotArgs.thread+1; i++ {
go navigate(i)
screenshotWg.Add(1)
}
screenshotWg.Wait()
}

func parseFile(file string) {
f, err := os.Open(file)
if err != nil {
log.Errorf(urlFileReadError, err)
return
}
defer f.Close()

scanner := bufio.NewScanner(f)
for scanner.Scan() {
if scanner.Text() != "" {
tmp := strings.Split(scanner.Text(), ": ")
name := strings.Split(strings.TrimSpace(tmp[0]), " ")

target := []string{fmt.Sprintf("%s-%s", name[0], name[len(name)-1]), tmp[1]}
targets <- target
}
}
}

func navigate(workerNum int) {
defer screenshotWg.Done()

// create context
opts := append(chromedp.DefaultExecAllocatorOptions[:],
chromedp.Flag("headless", !screenshotArgs.chrome),
chromedp.ProxyServer(screenshotArgs.proxy),
chromedp.Flag("mute-audio", true),
chromedp.IgnoreCertErrors,
chromedp.DisableGPU,
chromedp.NoFirstRun,
chromedp.ExecPath(screenshotArgs.path),
chromedp.WindowSize(1920, 1080),
chromedp.NoDefaultBrowserCheck,
chromedp.NoSandbox,
)

if screenshotArgs.proxy != "" {
opts = append(opts, chromedp.Flag("proxy-server", screenshotArgs.proxy))
}

ctx, cancel := chromedp.NewExecAllocator(context.Background(), opts...)

//ctx, cancel = context.WithTimeout(ctx, time.Duration(screenshotArgs.timeout)*time.Second)

ctx, cancel = chromedp.NewContext(ctx)

// Check & Make Browser not close
err := chromedp.Run(
ctx,
chromedp.Tasks{
chromedp.Navigate("https://github.com/piaolin"),
},
)
if err != nil {
if strings.Contains(err.Error(), "executable file not found") {
log.Fatalln(execPathNotFound)
} else {
log.Fatalln(err)
}
}

// Run
for len(targets) > 0 {
target := <-targets
name := target[0]
urlStr := target[1]

log.Debugf("[Worker%2d] starting screenshot task %s,remaining tasks:%d\n", workerNum, urlStr, len(targets))
var buf []byte
//ctx, cancel = chromedp.NewContext(
// ctx,
//)
if err := chromedp.Run(ctx, fullScreenshot(urlStr, 100, &buf)); err != nil {
log.Errorf("[-] Failed to take (URL:%s) screenshot: %v", urlStr, err)
continue
}
pngFilePath := fmt.Sprintf("./%s/%s.png", screenshotArgs.result, name)
if err := ioutil.WriteFile(pngFilePath, buf, 0644); err != nil {
log.Errorf("[-] Failed to write file %v", err)
continue
}

//if err := page.Close().Do(cdp.WithExecutor(ctx, chromedp.FromContext(ctx).Target)); err != nil {
// log.Errorln(err)
//}

log.Infof("[+] screenshot success %s", urlStr)
log.Debugf("[Worker%2d] finished screenshot task %s,remaining tasks:%d\n", workerNum, urlStr, len(targets))
}

defer cancel()
}

func fullScreenshot(urlstr string, quality int, res *[]byte) chromedp.Tasks {
return chromedp.Tasks{
chromedp.Navigate(urlstr),
//chromedp.WaitVisible("style"),
chromedp.Sleep(1 * time.Second),
//chromedp.OuterHTML(`document.querySelector("body")`, &htmlContent, chromedp.ByJSPath),
chromedp.FullScreenshot(res, quality),
//chromedp.ActionFunc(func(ctx context.Context) error {
// _, _, _, _, _, contentSize, err := page.GetLayoutMetrics().Do(ctx)
// if err != nil {
// return err
// }
//
// width, height := int64(math.Ceil(contentSize.Width)), int64(math.Ceil(contentSize.Height))
//
// err = emulation.SetDeviceMetricsOverride(width, height, 1, false).
// WithScreenOrientation(&emulation.ScreenOrientation{
// Type: emulation.OrientationTypePortraitPrimary,
// Angle: 0,
// }).
// Do(ctx)
// if err != nil {
// return err
// }
//
// *res, err = page.CaptureScreenshot().
// WithQuality(quality).
// WithClip(&page.Viewport{
// X: contentSize.X,
// Y: contentSize.Y,
// Width: contentSize.Width,
// Height: contentSize.Height,
// Scale: 1,
// }).Do(ctx)
// if err != nil {
// return err
// }
// return nil
//}),
}
}

func getDomain(urlstr string) string {
u, err := url.Parse(urlstr)
if err != nil {
fmt.Println(err)
return "getdomain_error"
}
return u.Hostname()
}

func CreateDirIfNotExists(dirName string) error {
if _, err := os.Stat(dirName); os.IsNotExist(err) {
err := os.MkdirAll(dirName, 0755)
if err != nil {
return err
}
}
return nil
}
15 changes: 12 additions & 3 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,28 @@ module DetectDee
go 1.18

require (
github.com/PuerkitoBio/goquery v1.8.1
github.com/chromedp/cdproto v0.0.0-20230506233603-4ea4c6dc2e5b
github.com/chromedp/chromedp v0.9.1
github.com/go-resty/resty/v2 v2.7.0
github.com/sirupsen/logrus v1.9.0
github.com/spf13/cobra v1.7.0
github.com/tidwall/gjson v1.14.4
)

require (
github.com/andybalholm/cascadia v1.3.1 // indirect
github.com/chromedp/sysutil v1.0.0 // indirect
github.com/gobwas/httphead v0.1.0 // indirect
github.com/gobwas/pool v0.2.1 // indirect
github.com/gobwas/ws v1.1.0 // indirect
github.com/josharian/intern v1.0.0 // indirect
github.com/mailru/easyjson v0.7.7 // indirect
)

require (
github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/spf13/pflag v1.0.5 // indirect
github.com/tidwall/match v1.1.1 // indirect
github.com/tidwall/pretty v1.2.0 // indirect
golang.org/x/net v0.7.0 // indirect
golang.org/x/sys v0.5.0 // indirect
golang.org/x/sys v0.6.0 // indirect
)
Loading

0 comments on commit 0e4dfc3

Please sign in to comment.