feat(d-eyes): init

This commit is contained in:
zitn
2023-11-06 16:31:16 +08:00
parent 804617ded3
commit 270bb18b98
117 changed files with 19222 additions and 0 deletions

View File

@@ -0,0 +1,132 @@
package info
import (
"bufio"
"encoding/csv"
"fmt"
"os"
"path/filepath"
"strings"
"github.com/gookit/color"
)
func CheckExchangeServerOWASSRF(path string) {
if path == "" {
path = "C:\\Program Files\\Microsoft\\Exchange Server\\V15\\Logging\\CmdletInfra\\Powershell-Proxy\\Http"
}
_, err := os.Stat(path)
if os.IsNotExist(err) {
fmt.Println("Didn't find the directory '", path, "' on this host!")
return
}
var logs []string
var paths []string
var users []string
var successDocs []string
var failDocs []string
color.Info.Println("Checking the Rps_Http logs in '", path, "'...")
files, err := filepath.Glob(path + "/*Rps_Http_20*")
if err != nil {
fmt.Println(err)
return
}
if len(files) == 0 {
fmt.Println("Not found Rps_Http logs in the directory '", path, "'")
return
}
for _, file := range files {
csvFile, err := os.Open(file)
if err != nil {
fmt.Println(err)
return
}
defer csvFile.Close()
reader := csv.NewReader(bufio.NewReader(csvFile))
reader.Comma = ','
reader.FieldsPerRecord = -1
csvData, err := reader.ReadAll()
if err != nil {
fmt.Println(err)
return
}
for _, record := range csvData {
if len(record) < 30 {
continue
}
ua := record[29]
if ua != "ClientInfo" && ua != "Microsoft WinRM Client" && ua != "Exchange BackEnd Probes" && strings.ContainsAny(ua, "a-zA-Z0-9") {
time := record[0]
src := strings.Replace(record[15], " ", " -> ", -1)
server := record[16]
frontend := record[17]
status := record[18]
user := record[12]
if status != "200" {
failDocs = append(failDocs, time+" [FAILURE: "+status+" ] Path: "+src+" -> "+frontend+" -> "+server+" as User: [ "+user+" ]")
} else {
successDocs = append(successDocs, time+" [SUCCESS: "+status+" ] Path: "+src+" -> "+frontend+" -> "+server+" as User: [ "+user+" ]")
}
paths = append(paths, src+" -> "+frontend+" -> "+server)
if strings.ContainsAny(user, "a-zA-Z0-9") {
users = append(users, user)
}
logs = append(logs, file)
}
}
}
paths = removeDuplicates(paths)
users = removeDuplicates(users)
logs = removeDuplicates(logs)
if len(successDocs) > 0 || len(failDocs) > 0 {
fmt.Println()
color.Error.Println("Something Suspicious Found !!!")
fmt.Println()
if len(successDocs) > 0 {
color.Warn.Println(len(successDocs), "instances of possible successful proxied exploitation found using UA indicator:")
for _, s := range successDocs {
fmt.Println(" ", s)
}
}
if len(failDocs) > 0 {
color.Warn.Println(len(failDocs), "instances of failed proxied exploitation attempts found using UA indicator")
for _, f := range failDocs {
fmt.Println(" ", f)
}
}
color.Warn.Println("Network paths used for exploitation attempts:")
for _, p := range paths {
fmt.Println(" ", p)
}
color.Warn.Println("Compromised users:")
for _, u := range users {
fmt.Println(" ", u)
}
color.Warn.Println("The above information is obtained from the following files:")
for _, l := range logs {
fmt.Println(" ", l)
}
} else {
fmt.Println()
color.Info.Println("Nothing Suspicious Found !")
}
}
func removeDuplicates(elements []string) []string {
encountered := map[string]bool{}
result := []string{}
for v := range elements {
if encountered[elements[v]] == true {
} else {
encountered[elements[v]] = true
result = append(result, elements[v])
}
}
return result
}

View File

@@ -0,0 +1,59 @@
package info
import (
"os"
"github.com/olekukonko/tablewriter"
autoruns "d-eyes/basicinfo/utils"
)
type AutoRuns struct {
AutoRuns []*autoruns.Autorun
}
func GetAutoruns() *AutoRuns {
ret := autoruns.Autoruns()
return &AutoRuns{AutoRuns: ret}
}
func DisplayAutoruns(autoRuns *AutoRuns) {
data := make([][]string, 0)
for _, autorun := range autoRuns.AutoRuns {
autorunData := make([]string, 0)
path := StringNewLine(autorun.ImagePath, 25)
autorunData = append(autorunData, autorun.Type, autorun.ImageName, autorun.Arguments, path)
data = append(data, autorunData)
}
table := tablewriter.NewWriter(os.Stdout)
table.SetHeader([]string{"Type", "ImageName", "Arguments", "Path"})
table.SetHeaderAlignment(tablewriter.ALIGN_CENTER)
table.SetBorder(true)
table.SetRowLine(true)
table.SetAutoMergeCells(true)
table.AppendBulk(data)
table.SetCaption(true, "Autoruns list")
table.Render()
}
func StringNewLine(str string, ln uint8) string {
var sub_str string
res_str := ""
for {
if len(str) < int(ln) {
res_str += str
break
}
sub_str = str[0:ln]
str = str[ln:]
res_str += sub_str + "\n"
}
return res_str
}
func CallDisplayAutoruns() {
autoruns := GetAutoruns()
DisplayAutoruns(autoruns)
}

View File

@@ -0,0 +1,59 @@
package info
import (
"os"
"github.com/olekukonko/tablewriter"
autoruns "d-eyes/basicinfo/utils"
)
type AutoRuns struct {
AutoRuns []*autoruns.Autorun
}
func GetAutoruns() *AutoRuns {
ret := autoruns.Autoruns()
return &AutoRuns{AutoRuns: ret}
}
func DisplayAutoruns(autoRuns *AutoRuns) {
data := make([][]string, 0)
for _, autorun := range autoRuns.AutoRuns {
autorunData := make([]string, 0)
path := StringNewLine(autorun.LaunchString, 25)
autorunData = append(autorunData, autorun.Type, autorun.ImageName, path)
data = append(data, autorunData)
}
table := tablewriter.NewWriter(os.Stdout)
table.SetHeader([]string{"Type", "ImageName", "LaunchCommand"})
table.SetHeaderAlignment(tablewriter.ALIGN_CENTER)
table.SetBorder(true)
table.SetRowLine(true)
table.SetAutoMergeCells(true)
table.AppendBulk(data)
table.SetCaption(true, "Autoruns list")
table.Render()
}
func StringNewLine(str string, ln uint8) string {
var subStr string
res_str := ""
for {
if len(str) < int(ln) {
res_str += str
break
}
subStr = str[0:ln]
str = str[ln:]
res_str += subStr + "\n"
}
return res_str
}
func CallDisplayAutoruns() {
ar := GetAutoruns()
DisplayAutoruns(ar)
}

27
basicinfo/info/base.go Normal file
View File

@@ -0,0 +1,27 @@
package info
import (
"fmt"
"os/user"
"github.com/gookit/color"
"github.com/shirou/gopsutil/v3/host"
)
func DisplayBaseInfo() {
infoStat, _ := host.Info()
platform := infoStat.Platform + " " + infoStat.PlatformVersion
OsKernel := infoStat.KernelArch + " " + infoStat.KernelVersion
CurrentUser, _ := user.Current()
color.Greenp("* ")
fmt.Println("OS VERSION: ", platform)
color.Greenp("* ")
fmt.Println("KERNEL VERSION: ", OsKernel)
color.Greenp("* ")
fmt.Println("CURRENT USER: ", CurrentUser.Username)
}

View File

@@ -0,0 +1,111 @@
//go:build windows
package info
import (
"encoding/xml"
"fmt"
"io/ioutil"
"log"
"runtime"
"strings"
"github.com/gookit/color"
"github.com/axgle/mahonia"
)
type task struct {
RegistrationInfo struct {
Description string
}
Actions struct {
Exec struct {
Command string
Arguments string
}
}
Triggers struct {
CalendarTrigger struct {
StartBoundary string
}
}
Principals struct {
Principal struct {
UserId string
}
}
}
type CronTab struct {
Name string `json:"name,omitempty"`
Command string `json:"command,omitempty"`
Arg string `json:"arg,omitempty"`
User string `json:"user,omitempty"`
Rule string `json:"rule,omitempty"`
Description string `json:"description,omitempty"`
}
func DisplayPlanTask() {
crontab := GetCronTab()
DisplayCronTab(crontab)
}
// GetCronTab 获取计划任务
func GetCronTab() (resultData []CronTab) {
var taskPath string
if runtime.GOARCH == "386" {
taskPath = `C:\Windows\SysNative\Tasks\`
} else {
taskPath = `C:\Windows\System32\Tasks\`
}
dir, err := ioutil.ReadDir(taskPath)
if err != nil {
return resultData
}
for _, f := range dir {
if f.IsDir() {
continue
}
dat, err := ioutil.ReadFile(taskPath + f.Name())
if err != nil {
continue
}
v := task{}
dec := mahonia.NewDecoder("utf-16")
data := dec.ConvertString(string(dat))
err = xml.Unmarshal([]byte(strings.Replace(data, "UTF-16", "UTF-8", 1)), &v)
if err != nil {
log.Println("Windows crontab info xml Unmarshal error: ", err.Error())
continue
}
m := CronTab{}
m.Name = f.Name()
m.Command = v.Actions.Exec.Command
m.Arg = v.Actions.Exec.Arguments
m.User = v.Principals.Principal.UserId
m.Rule = v.Triggers.CalendarTrigger.StartBoundary
m.Description = v.RegistrationInfo.Description
resultData = append(resultData, m)
}
return resultData
}
func DisplayCronTab(cronTab []CronTab) {
color.Greenp("==============================================================================================\n")
for _, item := range cronTab {
color.Greenp("* ")
fmt.Println("NAME: ", item.Name)
color.Greenp("* ")
fmt.Println("COMMAND: ", item.Command)
color.Greenp("* ")
fmt.Println("ARG: ", item.Arg)
color.Greenp("* ")
fmt.Println("USER: ", item.User)
color.Greenp("* ")
fmt.Println("RULE: ", item.Rule)
color.Greenp("* ")
fmt.Println("DESCRIPTION: ", item.Description)
color.Greenp("==============================================================================================\n")
}
}

View File

@@ -0,0 +1,81 @@
package info
import (
"fmt"
"io/ioutil"
"strings"
"github.com/gookit/color"
)
var resultData []string
func DisplayPlanTask() {
Crontab_file()
Crontab_dir()
DisplayCronTab(resultData)
}
// single crontab file
func Crontab_file() {
dat, err := ioutil.ReadFile("/etc/crontab")
if err != nil {
return
}
cronList := strings.Split(string(dat), "\n")
for _, info := range cronList {
if strings.HasPrefix(info, "#") || strings.Count(info, " ") < 6 {
continue
}
resultData = append(resultData, info)
}
}
// dir crontab files
func Crontab_dir() {
dir_list := []string{"/var/spool/cron/", "/var/spool/cron/crontabs/"}
for _, dirTmp := range dir_list {
dir, err := ioutil.ReadDir(dirTmp)
if err != nil {
continue
}
for _, f := range dir {
if f.IsDir() {
continue
}
dat, err := ioutil.ReadFile(dirTmp + f.Name())
if err != nil {
continue
}
cronList := strings.Split(string(dat), "\n")
for _, info := range cronList {
if strings.HasPrefix(info, "#") || strings.Count(info, " ") < 5 {
continue
}
info = info + " (user '" + f.Name() + "' created this task.)"
resultData = append(resultData, info)
}
}
}
}
func DisplayCronTab(cronTab []string) {
color.Greenp("==============================================================================================\n")
if len(cronTab) == 0 {
fmt.Println("There is no crontab task in this host.")
return
}
taskSum := 0
for _, item := range cronTab {
taskSum++
color.Greenp("* task", taskSum)
fmt.Println()
fmt.Println(item)
color.Greenp("==============================================================================================\n")
}
}
func GetCronTab() []string {
Crontab_file()
Crontab_dir()
return resultData
}

View File

@@ -0,0 +1,109 @@
package info
import (
"encoding/csv"
"fmt"
"os"
"strings"
"github.com/olekukonko/tablewriter"
"github.com/shirou/gopsutil/v3/process"
"d-eyes/basicinfo/utils"
)
// remote connection ip
func DisplayNetStat() {
networkData := make([][]string, 0)
var remoteIp []string
ps, err := process.Processes()
if err != nil {
fmt.Println("Error:", err)
return
}
for _, p := range ps {
pid := os.Getpid()
if pid == int(p.Pid) || p.Pid == 0 {
continue
}
connList := make([]string, 0)
connection := make([]string, 0)
_pc, _ := p.Connections()
for _, conn := range _pc {
if conn.Family == 1 {
continue
}
c := fmt.Sprintf(
"%v:%v<->%v:%v(%v)\n",
conn.Laddr.IP, conn.Laddr.Port, conn.Raddr.IP, conn.Raddr.Port, conn.Status,
)
remoteIp = append(remoteIp, conn.Raddr.IP)
connection = append(connection, c)
}
_pUname, _ := p.Username()
if len(connection) > 0 && _pUname != "" {
network := strings.Join(connection, "")
_exe, _ := p.Exe()
path := utils.StringNewLine(_exe, 25)
connList = append(connList, fmt.Sprintf("%v", p.Pid), fmt.Sprintf("%v", p.Username), network, path)
networkData = append(networkData, connList)
}
}
//output the information of current netstat
tableConn := tablewriter.NewWriter(os.Stdout)
tableConn.SetHeader([]string{"pid", "user", "local/remote(TCP Status)", "program name"})
tableConn.SetBorder(true)
tableConn.SetRowLine(true)
tableConn.AppendBulk(networkData)
tableConn.Render()
remoteIpNew := RemoveRepeatedElement(remoteIp)
if len(remoteIpNew) > 0 {
f, err := os.Create("RemoteConnectionIP.csv")
if err != nil {
panic(err)
}
_, err = f.WriteString("\xEF\xBB\xBF")
if err != nil {
panic(err)
}
writer := csv.NewWriter(f)
length := len(remoteIpNew)
for i := 0; i < length; i++ {
err := writer.Write([]string{remoteIpNew[i]})
if err != nil {
panic(err)
}
}
writer.Flush()
f.Close()
fmt.Println("The IP of the local remote connection has been exported to 'RemoteConnectionIP.csv'.")
} else {
fmt.Println("\nThere is no remote connection IP on this host.")
}
}
func RemoveRepeatedElement(arr []string) (newArr []string) {
newArr = make([]string, 0)
for i := 0; i < len(arr); i++ {
if arr[i] == "127.0.0.1" || arr[i] == "0.0.0.0" || arr[i] == "::" || arr[i] == "::1" || arr[i] == "" {
continue
}
repeat := false
for j := i + 1; j < len(arr); j++ {
if arr[i] == arr[j] {
repeat = true
break
}
}
if !repeat {
newArr = append(newArr, arr[i])
}
}
return
}

View File

@@ -0,0 +1,103 @@
package info
import (
"encoding/csv"
"fmt"
"os"
"strings"
"github.com/olekukonko/tablewriter"
"github.com/shirou/gopsutil/v3/process"
"d-eyes/basicinfo/utils"
)
// remote connection ip
func DisplayNetStat(srcPath string) {
networkData := make([][]string, 0)
var remoteIp []string
ps, err := process.Processes()
if err != nil {
fmt.Println("Error:", err)
return
}
for _, p := range ps {
pid := os.Getpid()
if pid == int(p.Pid) || p.Pid == 0 {
continue
}
connList := make([]string, 0)
connection := make([]string, 0)
_pc, _ := p.Connections()
for _, conn := range _pc {
if conn.Family == 1 {
continue
}
c := fmt.Sprintf(
"%v:%v<->%v:%v(%v)\n",
conn.Laddr.IP, conn.Laddr.Port, conn.Raddr.IP, conn.Raddr.Port, conn.Status,
)
remoteIp = append(remoteIp, conn.Raddr.IP)
connection = append(connection, c)
}
_pUname, _ := p.Username()
if len(connection) > 0 && _pUname != "" {
network := strings.Join(connection, "")
_exe, _ := p.Exe()
path := utils.StringNewLine(_exe, 25)
username, _ := p.Username()
connList = append(connList, fmt.Sprintf("%v", p.Pid), fmt.Sprintf("%v", username), network, path)
networkData = append(networkData, connList)
}
}
tableConn := tablewriter.NewWriter(os.Stdout)
tableConn.SetHeader([]string{"pid", "user", "local/remote(TCP Status)", "program name"})
tableConn.SetBorder(true)
tableConn.SetRowLine(true)
tableConn.AppendBulk(networkData)
tableConn.Render()
remoteIpNew := RemoveRepeatedElement(remoteIp)
if len(remoteIpNew) > 0 {
f, err := os.Create(srcPath + "RemoteConnectionIP.csv")
if err != nil {
panic(err)
}
f.WriteString("\xEF\xBB\xBF")
writer := csv.NewWriter(f)
length := len(remoteIpNew)
for i := 0; i < length; i++ {
writer.Write([]string{remoteIpNew[i]})
}
writer.Flush()
f.Close()
fmt.Println("The IP of the local remote connection has been exported to 'RemoteConnectionIP.csv'.")
} else {
fmt.Println("\nThere is no remote connection IP on this host.")
}
}
func RemoveRepeatedElement(arr []string) (newArr []string) {
newArr = make([]string, 0)
for i := 0; i < len(arr); i++ {
if arr[i] == "127.0.0.1" || arr[i] == "0.0.0.0" || arr[i] == "::" || arr[i] == "::1" || arr[i] == "" {
continue
}
repeat := false
for j := i + 1; j < len(arr); j++ {
if arr[i] == arr[j] {
repeat = true
break
}
}
if !repeat {
newArr = append(newArr, arr[i])
}
}
return
}

View File

@@ -0,0 +1,70 @@
package info
import (
"fmt"
"os"
"os/exec"
"os/user"
"strconv"
"github.com/shirou/gopsutil/v3/host"
)
func SaveSummaryBaseInfo() {
f, err := os.Create("SummaryBaseInfo")
if err != nil {
fmt.Errorf(err.Error())
}
baseInfo := GetBaseInfo()
_, err = f.WriteString("HostInfo: \n" + baseInfo)
users := GetLinuxUser()
_, err = f.WriteString("AllUsers: \n")
for _, user := range users {
_, err = f.WriteString(" * " + user + "\n")
}
crontab := GetCronTab()
crontabString := ""
crontabString += "Os Crontab: \n==============================================================================================\n"
taskSum := 0
for _, item := range crontab {
taskSum++
crontabString += "* task " + strconv.Itoa(taskSum) + "\n" +
"" + item + "\n" +
"==============================================================================================\n"
}
_, err = f.WriteString(crontabString)
_, err = f.WriteString("InterfaceInfo: \n")
if err == nil {
path, _ := os.Getwd()
fmt.Println("Summary file to ", path+"/SummaryBaseInfo")
fmt.Println("Summary Base Info file created!")
} else {
fmt.Errorf(err.Error())
}
f.Close()
c := exec.Command("/bin/bash", "-c", "ifconfig -a>>SummaryBaseInfo")
if err := c.Run(); err != nil {
fmt.Println("Error: ", err)
}
}
func GetBaseInfo() string {
infoStat, _ := host.Info()
platform := infoStat.Platform + " " + infoStat.PlatformVersion
OsKernel := infoStat.KernelArch + " " + infoStat.KernelVersion
user, _ := user.Current()
baseInfo := ""
baseInfo += " * OS VERSION: " + platform + "\n" +
" * KERNEL VERSION: " + OsKernel + "\n" +
" * CURRENT USER: " + user.Username + "\n"
return baseInfo
}

View File

@@ -0,0 +1,74 @@
package info
import (
"fmt"
"os"
"os/exec"
"os/user"
"github.com/shirou/gopsutil/v3/host"
)
func SaveSummaryBaseInfo() {
f, err := os.Create("SummaryBaseInfo.txt")
if err != nil {
fmt.Println(err)
return
}
baseInfo := GetBaseInfo()
_, err = f.WriteString("HostInfo: \n" + baseInfo)
users := GetWindowsUser()
_, err = f.WriteString("AllUsers: \n")
for _, userInfo := range users {
_, err = f.WriteString(" * " + userInfo + "\n")
}
crontab := GetCronTab()
crontabString := ""
crontabString += "Os Crontab: \n==============================================================================================\n"
for _, item := range crontab {
crontabString += "*NAME: " + item.Name + "\n" +
"*COMMAND: " + item.Command + "\n" +
"*ARG: " + item.Arg + "\n" +
"*USER: " + item.User + "\n" +
"*RULE: " + item.Rule + "\n" +
"*DESCRIPTION: " + item.Description + "\n" +
"==============================================================================================\n"
}
_, err = f.WriteString(crontabString)
_, err = f.WriteString("InterfaceInfo: ")
if err == nil {
path, _ := os.Getwd()
fmt.Println("Summary file to ", path+"\\SummaryBaseInfo.txt")
fmt.Println("Summary Base Info file created!")
} else {
fmt.Println(err)
return
}
f.Close()
c := exec.Command("cmd", "/C", "ipconfig /all>>SummaryBaseInfo.txt")
if err := c.Run(); err != nil {
fmt.Println("Error: ", err)
}
}
func GetBaseInfo() string {
infoStat, _ := host.Info()
platform := infoStat.Platform + " " + infoStat.PlatformVersion
OsKernel := infoStat.KernelArch + " " + infoStat.KernelVersion
userInfo, _ := user.Current()
baseInfo := ""
baseInfo += " * OS VERSION: " + platform + "\n" +
" * KERNEL VERSION: " + OsKernel + "\n" +
" * CURRENT USER: " + userInfo.Username + "\n"
return baseInfo
}

77
basicinfo/info/top.go Normal file
View File

@@ -0,0 +1,77 @@
package info
import (
"fmt"
"os"
"sort"
"time"
"github.com/gookit/color"
"github.com/shirou/gopsutil/v3/process"
)
type (
Process struct {
Process []*process.Process
}
)
func Top() {
ps, err := process.Processes()
if err != nil {
fmt.Println(err)
return
}
sort.Slice(
ps, func(i, j int) bool {
pic, _ := ps[i].CPUPercent()
pjc, _ := ps[j].CPUPercent()
return pic > pjc
},
)
pss := Process{Process: ps}
CPUSum := 0
color.Greenp("==============================================================================================\n")
for _, ps := range pss.Process {
pid := os.Getpid()
if pid == int(ps.Pid) {
continue
}
CPUSum++
color.Greenp("* CPU Top ", CPUSum)
fmt.Println()
_pct, _ := ps.CreateTime()
_pPath, _ := ps.Exe()
_pCpuP, _ := ps.CPUPercent()
startDate := time.Unix(_pct, 0).Format("2006-01-02 15:04:05")
username, _ := ps.Username()
MemPer, _ := ps.MemoryPercent()
fmt.Printf(
"[User]:%s | [Pid]:%d | [Path]:%s | [CPU]:%.5f | [Memory]:%.5f | [Createdtime]:%v \n",
username, ps.Pid, _pPath, _pCpuP, MemPer, startDate,
)
//network
_ps, _ := ps.Connections()
if len(_ps) == 0 {
fmt.Println("[netstat]: null")
} else {
netSum := 0
for _, conn := range _ps {
if conn.Family == 1 {
continue
}
netSum++
fmt.Printf(
"[netstat %d]: %v:%v<->%v:%v(%v)\n",
netSum, conn.Laddr.IP, conn.Laddr.Port, conn.Raddr.IP, conn.Raddr.Port, conn.Status,
)
}
}
color.Greenp("==============================================================================================\n")
if CPUSum == 15 {
break
}
}
}

View File

@@ -0,0 +1,42 @@
package info
import (
"fmt"
"github.com/gookit/color"
"io/ioutil"
"strings"
)
func DisplayAllUsers() {
users := GetLinuxUser()
for _, user := range users {
color.Greenp("* ")
fmt.Println(user)
}
}
// GetUser
func GetLinuxUser() (resultData []string) {
dat, err := ioutil.ReadFile("/etc/passwd")
if err != nil {
return resultData
}
userList := strings.Split(string(dat), "\n")
if len(userList) < 2 {
return
}
for _, info := range userList[0 : len(userList)-1] {
if strings.Contains(info, "/nologin") {
continue
}
if strings.Contains(info, "/bin/false") {
continue
}
s := strings.SplitN(info, ":", 2)
resultData = append(resultData, s[0])
}
return resultData
}

View File

@@ -0,0 +1,38 @@
package info
import (
"fmt"
"github.com/gookit/color"
"github.com/yusufpapurcu/wmi"
)
func DisplayAllUsers() {
users := GetWindowsUser()
for _, user := range users {
color.Greenp("* ")
fmt.Println(user)
}
}
type userAccount struct {
Name string // 用户名
Description string // 用户描述
Status string // 用户状态
}
// GetUser 获取系统用户列表
func GetWindowsUser() (resultData []string) {
var dst []userAccount
err := wmi.Query("SELECT * FROM Win32_UserAccount where LocalAccount=TRUE", &dst)
if err != nil {
return resultData
}
for _, v := range dst {
resultData = append(resultData, v.Name)
}
return resultData
}

View File

@@ -0,0 +1,18 @@
package utils
type Autorun struct {
Type string `json:"type"`
Location string `json:"location"`
ImagePath string `json:"image_path"`
ImageName string `json:"image_name"`
Arguments string `json:"arguments"`
MD5 string `json:"md5"`
SHA1 string `json:"sha1"`
SHA256 string `json:"sha256"`
Entry string `json:"entry"`
LaunchString string `json:"launch_string"`
}
func Autoruns() []*Autorun {
return getAutoruns()
}

View File

@@ -0,0 +1,111 @@
package utils
import (
"bufio"
"io/ioutil"
"os"
"path"
"path/filepath"
"regexp"
"strings"
files "github.com/botherder/go-files"
)
// This function just invokes all the platform-dependant functions.
func getAutoruns() (records []*Autorun) {
records = append(records, linuxGetSystemd()...)
return
}
var regexSection = regexp.MustCompile("\\[.*\\]")
func parseShellInvocation(shellLine string, autorun *Autorun) {
autorun.LaunchString = strings.SplitAfter(shellLine, "=")[1]
// We need to make sure to drop !! from paths
autorun.ImagePath = strings.Replace(strings.Split(autorun.LaunchString, " ")[0], "!!", "", -1)
autorun.ImageName = path.Base(autorun.ImagePath)
args := strings.Split(autorun.LaunchString, " ")
if len(args) > 1 {
autorun.Arguments = strings.Join(args[1:], " ")
}
}
func stringToAutorun(fileName string) (*Autorun, error) {
reader, err := os.Open(fileName)
if err != nil {
return nil, err
}
defer reader.Close()
autorun := Autorun{
Location: fileName,
//Type: "systemd",
Type: "Autorun services",
}
inSection := ""
scanner := bufio.NewScanner(reader)
for scanner.Scan() {
line := scanner.Text()
if regexSection.MatchString(line) {
inSection = line
}
switch inSection {
case "[Service]":
if strings.HasPrefix(line, "ExecStart=") {
parseShellInvocation(line, &autorun)
}
case "[D-BUS Service]":
if strings.HasPrefix(line, "Exec=") {
parseShellInvocation(line, &autorun)
}
}
}
autorun.MD5, _ = files.HashFile(autorun.ImagePath, "md5")
autorun.SHA1, _ = files.HashFile(autorun.ImagePath, "sha1")
autorun.SHA256, _ = files.HashFile(autorun.ImagePath, "sha256")
return &autorun, nil
}
func linuxGetSystemd() (records []*Autorun) {
folders := []string{
"/etc/systemd/system/",
"/usr/share/dbus-1/system-services/",
}
for _, folder := range folders {
// Check if the folders exists.
if _, err := os.Stat(folder); os.IsNotExist(err) {
continue
}
// Get list of files in folder.
filesList, err := ioutil.ReadDir(folder)
if err != nil {
continue
}
// Loop through all files in folder.
for _, fileEntry := range filesList {
// Skip all files that don't end with .service.
if !(strings.HasSuffix(fileEntry.Name(), ".service")) {
continue
}
filePath := filepath.Join(folder, fileEntry.Name())
record, err := stringToAutorun(filePath)
if err != nil {
continue
}
records = append(records, record)
}
}
return
}

View File

@@ -0,0 +1,276 @@
package utils
import (
"errors"
"fmt"
"io/ioutil"
"os"
"os/exec"
"path/filepath"
"strings"
files "github.com/botherder/go-files"
"github.com/mattn/go-shellwords"
"golang.org/x/sys/windows/registry"
)
// Just return a string value for a given registry root Key.
func registryToString(reg registry.Key) string {
if reg == registry.LOCAL_MACHINE {
return "LOCAL_MACHINE"
} else if reg == registry.CURRENT_USER {
return "CURRENT_USER"
} else {
return ""
}
}
func parsePath(entryValue string) ([]string, error) {
if entryValue == "" {
return nil, errors.New("empty path")
}
if strings.HasPrefix(entryValue, `\??\`) {
entryValue = entryValue[4:]
}
// do some typical replacements
if len(entryValue) >= 11 && strings.ToLower(entryValue[:11]) == "\\systemroot" {
entryValue = strings.Replace(entryValue, entryValue[:11], os.Getenv("SystemRoot"), -1)
}
if len(entryValue) >= 8 && strings.ToLower(entryValue[:8]) == "system32" {
entryValue = strings.Replace(entryValue, entryValue[:8], fmt.Sprintf("%s\\System32", os.Getenv("SystemRoot")), -1)
}
// replace environment variables
entryValue, err := registry.ExpandString(entryValue)
if err != nil {
return []string{}, err
}
// We clean the path for proper backslashes.
entryValue = strings.Replace(entryValue, "\\", "\\\\", -1)
// Check if the whole entry is an executable and clean the file path.
if v, err := cleanPath(entryValue); err == nil {
return []string{v}, nil
}
// Otherwise we can split the entry for executable and arguments
parser := shellwords.NewParser()
args, err := parser.Parse(entryValue)
if err != nil {
return []string{}, err
}
// If the split worked, find the correct path to the executable and clean
// the file path.
if len(args) > 0 {
if v, err := cleanPath(args[0]); err == nil {
args[0] = v
}
}
return args, nil
}
func stringToAutorun(entryType string, entryLocation string, entryValue string, toParse bool, entry string) *Autorun {
var imagePath = entryValue
var launchString = entryValue
var argsString = ""
// TODO: This optional parsing is quite spaghetti. To change.
if toParse == true {
args, err := parsePath(entryValue)
if err == nil {
if len(args) > 0 {
imagePath = args[0]
if len(args) > 1 {
argsString = strings.Join(args[1:], " ")
}
}
}
}
md5, _ := files.HashFile(imagePath, "md5")
sha1, _ := files.HashFile(imagePath, "sha1")
sha256, _ := files.HashFile(imagePath, "sha256")
newAutorun := Autorun{
Type: entryType,
Location: entryLocation,
ImagePath: imagePath,
ImageName: filepath.Base(imagePath),
Arguments: argsString,
MD5: md5,
SHA1: sha1,
SHA256: sha256,
Entry: entry,
LaunchString: launchString,
}
return &newAutorun
}
// This function invokes all the platform-dependant functions.
func getAutoruns() (records []*Autorun) {
records = append(records, windowsGetCurrentVersionRun()...)
//records = append(records, windowsGetServices()...)
records = append(records, windowsGetStartupFiles()...)
// records = append(records, windowsGetTasks()...)
return
}
// This function enumerates items registered through CurrentVersion\Run.
func windowsGetCurrentVersionRun() (records []*Autorun) {
regs := []registry.Key{
registry.LOCAL_MACHINE,
registry.CURRENT_USER,
}
keyNames := []string{
"Software\\Microsoft\\Windows\\CurrentVersion\\Run",
"Software\\Microsoft\\Windows\\CurrentVersion\\RunOnce",
"Software\\Wow6432Node\\Microsoft\\Windows\\CurrentVersion\\Run",
"Software\\Wow6432Node\\Microsoft\\Windows\\CurrentVersion\\RunOnce",
}
// We loop through HKLM and HKCU.
for _, reg := range regs {
// We loop through the keys we're interested in.
for _, keyName := range keyNames {
// Open registry key.
key, err := registry.OpenKey(reg, keyName, registry.READ)
if err != nil {
continue
}
// Enumerate value names.
names, err := key.ReadValueNames(0)
if err != nil {
key.Close()
continue
}
for _, name := range names {
// For each entry we get the string value.
value, _, err := key.GetStringValue(name)
if err != nil || value == "" {
continue
}
imageLocation := fmt.Sprintf("%s\\%s", registryToString(reg), keyName)
/*reTime,err:=key.Stat()
if err != nil {
fmt.Println(err)
continue
}
reTime.ModTime()*/
newAutorun := stringToAutorun("Autoruns", imageLocation, value, true, name)
// Add the new autorun to the records.
records = append(records, newAutorun)
}
key.Close()
}
}
return
}
// This function enumerates Windows Services.
func windowsGetServices() (records []*Autorun) {
var reg registry.Key = registry.LOCAL_MACHINE
var servicesKey string = "System\\CurrentControlSet\\Services"
// Open the registry key.
key, err := registry.OpenKey(reg, servicesKey, registry.READ)
if err != nil {
return
}
// Enumerate subkeys.
names, err := key.ReadSubKeyNames(0)
key.Close()
if err != nil {
return
}
for _, name := range names {
// We open each subkey.
subkeyPath := fmt.Sprintf("%s\\%s", servicesKey, name)
subkey, err := registry.OpenKey(reg, subkeyPath, registry.READ)
if err != nil {
continue
}
// Check if there is an ImagePath value.
imagePath, _, err := subkey.GetStringValue("ImagePath")
subkey.Close()
// If not, we skip to the next one.
if err != nil {
continue
}
imageLocation := fmt.Sprintf("%s\\%s", registryToString(reg), subkeyPath)
// We pass the value string to a function to return an Autorun.
newAutorun := stringToAutorun("service", imageLocation, imagePath, true, "")
// Add the new autorun to the records.
records = append(records, newAutorun)
}
return
}
// %ProgramData%\Microsoft\Windows\Start Menu\Programs\StartUp
// %AppData%\Microsoft\Windows\Start Menu\Programs\Startup
func windowsGetStartupFiles() (records []*Autorun) {
// We look for both global and user Startup folders.
folders := []string{
os.Getenv("ProgramData"),
os.Getenv("AppData"),
}
// The base path is the same for both.
var startupBasepath string = "Microsoft\\Windows\\Start Menu\\Programs\\StartUp"
for _, folder := range folders {
// Get the full path.
startupPath := filepath.Join(folder, startupBasepath)
// Get list of files in folder.
filesList, err := ioutil.ReadDir(startupPath)
if err != nil {
continue
}
// Loop through all files in folder.
for _, fileEntry := range filesList {
// We skip desktop.ini files.
if fileEntry.Name() == "desktop.ini" {
continue
}
filePath := filepath.Join(startupPath, fileEntry.Name())
// Instantiate new autorun record.
newAutorun := stringToAutorun("startup", startupPath, filePath, false, "")
// Add new record to list.
records = append(records, newAutorun)
}
}
return
}
// cleanPath uses lookPath to search for the correct path to
// the executable and cleans the file path.
func cleanPath(file string) (string, error) {
file, err := exec.LookPath(file)
if err != nil {
return "", err
}
return filepath.Clean(file), nil
}
// func windowsGetTasks() {
// }

View File

@@ -0,0 +1,16 @@
package utils
func StringNewLine(str string, ln uint8) string {
var sub_str string
res_str := ""
for {
if len(str) < int(ln) {
res_str += str
break
}
sub_str = str[0:ln]
str = str[ln:]
res_str += sub_str + "\n"
}
return res_str
}