2023-08-18 08:55:46 +02:00
|
|
|
|
package gopocs
|
|
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
|
"bytes"
|
|
|
|
|
|
"crypto/aes"
|
|
|
|
|
|
"crypto/cipher"
|
|
|
|
|
|
"dddd/common/report"
|
|
|
|
|
|
"dddd/structs"
|
|
|
|
|
|
"dddd/utils"
|
|
|
|
|
|
"encoding/base64"
|
|
|
|
|
|
"net"
|
|
|
|
|
|
"os"
|
|
|
|
|
|
"strings"
|
|
|
|
|
|
"sync"
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
var PluginList = map[string]interface{}{
|
|
|
|
|
|
"NetBios-GetHostInfo": NetBIOS,
|
|
|
|
|
|
"RPC-GetHostInfo": Findnet,
|
|
|
|
|
|
"SSH-Crack": SshScan,
|
|
|
|
|
|
"FTP-Crack": FtpScan,
|
|
|
|
|
|
"Mysql-Crack": MysqlScan,
|
|
|
|
|
|
"Mssql-Crack": MssqlScan,
|
|
|
|
|
|
"Oracle-Crack": OracleScan,
|
|
|
|
|
|
"MongoDB-Crack": MongodbScan,
|
|
|
|
|
|
"RDP-Crack": RdpScan,
|
|
|
|
|
|
"Redis-Crack": RedisScan,
|
|
|
|
|
|
"SMB-MS17-010": MS17010,
|
|
|
|
|
|
"PostgreSQL-Crack": PostgresScan,
|
|
|
|
|
|
"SMB-Crack": SmbScan,
|
|
|
|
|
|
"Telnet-Crack": TelnetScan,
|
|
|
|
|
|
"Memcache-Crack": MemcachedScan,
|
|
|
|
|
|
"JDWP-Scan": JDWPScan,
|
|
|
|
|
|
"Shiro-Key-Crack": ShiroKeyCheck,
|
2024-04-03 06:32:26 +02:00
|
|
|
|
"ADB-Scan": ADBScan,
|
2023-08-18 08:55:46 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
var WriteResultLock sync.Mutex
|
|
|
|
|
|
|
|
|
|
|
|
func ReadBytes(conn net.Conn) (result []byte, err error) {
|
|
|
|
|
|
size := 4096
|
|
|
|
|
|
buf := make([]byte, size)
|
|
|
|
|
|
for {
|
|
|
|
|
|
count, err := conn.Read(buf)
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
|
break
|
|
|
|
|
|
}
|
|
|
|
|
|
result = append(result, buf[0:count]...)
|
|
|
|
|
|
if count < size {
|
|
|
|
|
|
break
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
if len(result) > 0 {
|
|
|
|
|
|
err = nil
|
|
|
|
|
|
}
|
|
|
|
|
|
return result, err
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
var key = "0123456789abcdef"
|
|
|
|
|
|
|
|
|
|
|
|
func AesEncrypt(orig string, key string) string {
|
|
|
|
|
|
// 转成字节数组
|
|
|
|
|
|
origData := []byte(orig)
|
|
|
|
|
|
k := []byte(key)
|
|
|
|
|
|
// 分组秘钥
|
|
|
|
|
|
// NewCipher该函数限制了输入k的长度必须为16, 24或者32
|
|
|
|
|
|
block, _ := aes.NewCipher(k)
|
|
|
|
|
|
// 获取秘钥块的长度
|
|
|
|
|
|
blockSize := block.BlockSize()
|
|
|
|
|
|
// 补全码
|
|
|
|
|
|
origData = PKCS7Padding(origData, blockSize)
|
|
|
|
|
|
// 加密模式
|
|
|
|
|
|
blockMode := cipher.NewCBCEncrypter(block, k[:blockSize])
|
|
|
|
|
|
// 创建数组
|
|
|
|
|
|
cryted := make([]byte, len(origData))
|
|
|
|
|
|
// 加密
|
|
|
|
|
|
blockMode.CryptBlocks(cryted, origData)
|
|
|
|
|
|
return base64.StdEncoding.EncodeToString(cryted)
|
|
|
|
|
|
}
|
|
|
|
|
|
func AesDecrypt(cryted string, key string) string {
|
|
|
|
|
|
// 转成字节数组
|
|
|
|
|
|
crytedByte, _ := base64.StdEncoding.DecodeString(cryted)
|
|
|
|
|
|
k := []byte(key)
|
|
|
|
|
|
// 分组秘钥
|
|
|
|
|
|
block, _ := aes.NewCipher(k)
|
|
|
|
|
|
// 获取秘钥块的长度
|
|
|
|
|
|
blockSize := block.BlockSize()
|
|
|
|
|
|
// 加密模式
|
|
|
|
|
|
blockMode := cipher.NewCBCDecrypter(block, k[:blockSize])
|
|
|
|
|
|
// 创建数组
|
|
|
|
|
|
orig := make([]byte, len(crytedByte))
|
|
|
|
|
|
// 解密
|
|
|
|
|
|
blockMode.CryptBlocks(orig, crytedByte)
|
|
|
|
|
|
// 去补全码
|
|
|
|
|
|
orig = PKCS7UnPadding(orig)
|
|
|
|
|
|
return string(orig)
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 补码
|
|
|
|
|
|
// AES加密数据块分组长度必须为128bit(byte[16]),密钥长度可以是128bit(byte[16])、192bit(byte[24])、256bit(byte[32])中的任意一个。
|
|
|
|
|
|
func PKCS7Padding(ciphertext []byte, blocksize int) []byte {
|
|
|
|
|
|
padding := blocksize - len(ciphertext)%blocksize
|
|
|
|
|
|
padtext := bytes.Repeat([]byte{byte(padding)}, padding)
|
|
|
|
|
|
return append(ciphertext, padtext...)
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 去码
|
|
|
|
|
|
func PKCS7UnPadding(origData []byte) []byte {
|
|
|
|
|
|
length := len(origData)
|
|
|
|
|
|
unpadding := int(origData[length-1])
|
|
|
|
|
|
return origData[:(length - unpadding)]
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
func generateKeys(key string) []string {
|
|
|
|
|
|
var results []string
|
|
|
|
|
|
results = append(results, strings.ToLower(key))
|
|
|
|
|
|
results = append(results, strings.ToUpper(key))
|
|
|
|
|
|
results = append(results, strings.ToUpper(strings.ToUpper(key[:1])+key[1:]))
|
|
|
|
|
|
return results
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
func splitUserPass(userPasswd string) (user string, oriPass string) {
|
|
|
|
|
|
sp := strings.Split(userPasswd, " : ")
|
|
|
|
|
|
user = ""
|
|
|
|
|
|
oriPass = ""
|
|
|
|
|
|
if len(sp) != 2 {
|
|
|
|
|
|
user = sp[0]
|
|
|
|
|
|
oriPass = ""
|
|
|
|
|
|
} else {
|
|
|
|
|
|
user = sp[0]
|
|
|
|
|
|
oriPass = sp[1]
|
|
|
|
|
|
}
|
|
|
|
|
|
user = strings.TrimSuffix(user, "\r")
|
|
|
|
|
|
oriPass = strings.TrimSuffix(oriPass, "\r")
|
|
|
|
|
|
return user, oriPass
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
func sortUserPassword(info *structs.HostInfo, UserPasswdDict string, DefaultKeys []string) []structs.UserPasswd {
|
|
|
|
|
|
var userPasswdList []structs.UserPasswd
|
2024-04-03 06:32:26 +02:00
|
|
|
|
var upList []string
|
|
|
|
|
|
if structs.GlobalConfig.Password != "" {
|
|
|
|
|
|
upList = append(upList, structs.GlobalConfig.Password)
|
|
|
|
|
|
} else if structs.GlobalConfig.PasswordFile != "" {
|
|
|
|
|
|
b, err := os.ReadFile(structs.GlobalConfig.PasswordFile)
|
|
|
|
|
|
if err == nil {
|
|
|
|
|
|
t := strings.ReplaceAll(string(b), "\r\n", "\n")
|
|
|
|
|
|
for _, v := range strings.Split(t, "\n") {
|
|
|
|
|
|
if !strings.Contains(v, " : ") {
|
|
|
|
|
|
continue
|
|
|
|
|
|
}
|
|
|
|
|
|
upList = append(upList, v)
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
} else {
|
|
|
|
|
|
upList = info.UserPass
|
|
|
|
|
|
// 兼容Windows
|
|
|
|
|
|
UserPasswdDict = strings.ReplaceAll(UserPasswdDict, "\r\n", "\n")
|
|
|
|
|
|
for _, v := range strings.Split(UserPasswdDict, "\n") {
|
|
|
|
|
|
upList = append(upList, v)
|
|
|
|
|
|
}
|
2023-08-18 08:55:46 +02:00
|
|
|
|
}
|
|
|
|
|
|
upList = utils.RemoveDuplicateElement(upList)
|
|
|
|
|
|
|
|
|
|
|
|
// 统计变形后的字典
|
|
|
|
|
|
for _, userPasswd := range upList {
|
|
|
|
|
|
user, oriPass := splitUserPass(userPasswd)
|
|
|
|
|
|
|
|
|
|
|
|
if strings.Contains(oriPass, "{{key}}") {
|
|
|
|
|
|
for _, sKey := range info.InfoStr {
|
|
|
|
|
|
newKeys := generateKeys(sKey)
|
|
|
|
|
|
for _, nKey := range newKeys {
|
|
|
|
|
|
newPass := strings.Replace(oriPass, "{{key}}", nKey, -1)
|
|
|
|
|
|
userPasswdList = append(userPasswdList, structs.UserPasswd{UserName: user, Password: newPass})
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
for _, dk := range DefaultKeys {
|
|
|
|
|
|
newKeys := generateKeys(dk)
|
|
|
|
|
|
for _, nKey := range newKeys {
|
|
|
|
|
|
newPass := strings.Replace(oriPass, "{{key}}", nKey, -1)
|
|
|
|
|
|
userPasswdList = append(userPasswdList, structs.UserPasswd{UserName: user, Password: newPass})
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
userPasswdList = append(userPasswdList, structs.UserPasswd{UserName: user, Password: oriPass})
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
return RemoveDuplicateUserPass(userPasswdList)
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
func RemoveDuplicateUserPass(input []structs.UserPasswd) []structs.UserPasswd {
|
|
|
|
|
|
temp := map[structs.UserPasswd]struct{}{}
|
|
|
|
|
|
var result []structs.UserPasswd
|
|
|
|
|
|
for _, item := range input {
|
|
|
|
|
|
if _, ok := temp[item]; !ok {
|
|
|
|
|
|
temp[item] = struct{}{}
|
|
|
|
|
|
result = append(result, item)
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
return result
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
func CheckErrs(err error) bool {
|
|
|
|
|
|
if err == nil {
|
|
|
|
|
|
return false
|
|
|
|
|
|
}
|
|
|
|
|
|
errs := []string{
|
|
|
|
|
|
"closed by the remote host", "too many connections",
|
|
|
|
|
|
"i/o timeout", "EOF", "A connection attempt failed",
|
|
|
|
|
|
"established connection failed", "connection attempt failed",
|
|
|
|
|
|
"Unable to read", "is not allowed to connect to this",
|
|
|
|
|
|
"no pg_hba.conf entry",
|
|
|
|
|
|
"No connection could be made",
|
|
|
|
|
|
"invalid packet size",
|
|
|
|
|
|
"bad connection",
|
|
|
|
|
|
}
|
|
|
|
|
|
for _, key := range errs {
|
|
|
|
|
|
if strings.Contains(strings.ToLower(err.Error()), strings.ToLower(key)) {
|
|
|
|
|
|
return true
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
return false
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
func GoPocWriteResult(result structs.GoPocsResultType) {
|
|
|
|
|
|
WriteResultLock.Lock()
|
|
|
|
|
|
report.AddResultByGoPocResult(result)
|
|
|
|
|
|
WriteResultLock.Unlock()
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
func readDict(name string) string {
|
|
|
|
|
|
bt, err := os.ReadFile(name)
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
|
return ""
|
|
|
|
|
|
}
|
|
|
|
|
|
return string(bt)
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2024-04-03 06:32:26 +02:00
|
|
|
|
func fileExists(filePath string) bool {
|
|
|
|
|
|
_, err := os.Stat(filePath)
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
|
if os.IsNotExist(err) {
|
|
|
|
|
|
return false
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
return true
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2023-08-18 08:55:46 +02:00
|
|
|
|
// initDic 初始化用于爆破的字典
|
|
|
|
|
|
func initDic() {
|
|
|
|
|
|
basePath := "config/dict/"
|
2024-04-03 06:32:26 +02:00
|
|
|
|
|
|
|
|
|
|
if fileExists(basePath + "ftp.txt") {
|
|
|
|
|
|
ftpUserPasswdDict = readDict(basePath + "ftp.txt")
|
|
|
|
|
|
}
|
|
|
|
|
|
if fileExists(basePath + "") {
|
|
|
|
|
|
mssqlUserPasswdDict = readDict(basePath + "mssql.txt")
|
|
|
|
|
|
}
|
|
|
|
|
|
if fileExists(basePath + "") {
|
|
|
|
|
|
mysqlUserPasswdDict = readDict(basePath + "mysql.txt")
|
|
|
|
|
|
}
|
|
|
|
|
|
if fileExists(basePath + "") {
|
|
|
|
|
|
oracleUserPasswdDict = readDict(basePath + "oracle.txt")
|
|
|
|
|
|
}
|
|
|
|
|
|
if fileExists(basePath + "") {
|
|
|
|
|
|
postgreSQLUserPasswdDict = readDict(basePath + "postgresql.txt")
|
|
|
|
|
|
}
|
|
|
|
|
|
if fileExists(basePath + "") {
|
|
|
|
|
|
rdpUserPasswdDict = readDict(basePath + "rdp.txt")
|
|
|
|
|
|
}
|
|
|
|
|
|
if fileExists(basePath + "") {
|
|
|
|
|
|
redisUserPasswdDict = readDict(basePath + "redis.txt")
|
|
|
|
|
|
}
|
|
|
|
|
|
if fileExists(basePath + "") {
|
|
|
|
|
|
smbUserPasswdDict = readDict(basePath + "smb.txt")
|
|
|
|
|
|
}
|
|
|
|
|
|
if fileExists(basePath + "") {
|
|
|
|
|
|
sshUserPasswdDict = readDict(basePath + "ssh.txt")
|
|
|
|
|
|
}
|
|
|
|
|
|
if fileExists(basePath + "") {
|
|
|
|
|
|
telnetUserPasswdDict = readDict(basePath + "telnet.txt")
|
|
|
|
|
|
}
|
|
|
|
|
|
if fileExists(basePath + "") {
|
|
|
|
|
|
ShiroKeys = readDict(basePath + "shirokeys.txt")
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2023-08-18 08:55:46 +02:00
|
|
|
|
}
|