├── LICENSE ├── README.md ├── core ├── asp.go ├── cfm.go ├── core.go ├── generic.go ├── java.go ├── npi.go ├── php.go └── utils.go ├── detector ├── main.go └── webshell_detector ├── go.mod ├── sample ├── alpine │ └── README.md ├── centos │ └── README.md ├── main.go ├── train.csv ├── ubuntu │ └── README.md ├── webshell │ └── README.md └── xsample └── trainer ├── main.go ├── module.json └── xtrainer /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # WXEL 2 | 3 | 基于机器学习的Webshell检测工具(linux) 4 | 5 | # 描述 6 | WXEL是基于神经网络学习算法对文件压缩比、熵、最长字符、内容特征等进行学习评估,协助安全人员针对Webshell的监察。 7 | 8 | # 使用 9 | 10 | ## 获取训练样本 11 | 1.需要在sample/webshell目录放入具有webshell特征的文件,在sample下其他目录下放入常规文件 12 | 2.编译 13 | ```shell 14 | go build -o xsample sample/main.go 15 | ```` 16 | 3.获取训练样本 17 | ```shell 18 | ./xsample 19 | ``` 20 | 当然也可以直接使用`xsample`(基于linux go 1.20.4编译), 样本文件为`train.csv` 21 | 22 | ## 训练 23 | 1. 编译 24 | ```shell 25 | go build -o xtrainer trainer/main.go 26 | ``` 27 | 2.开始训练 28 | ```shell 29 | ./xtrainer 30 | ``` 31 | 当然也可以直接使用`xtrainer`(基于linux go 1.20.4编译) 32 | 3.获取模型,模型文件位于当前目录下`module.json` 33 | 34 | ## 检测 35 | 1. 将模型赋予变量`ModuleContent` 36 | 2. 编译 37 | ```shell 38 | go build -o webshell_detector detector/main.go 39 | ``` 40 | 3.使用`webshell_detecotr -i `检测文件或目录 41 | 42 | ## 注意 43 | 1. 当前模型仍然存在误报,需进一步训练 44 | 2. 性能优化,可针对扫描对象起多个goroutine进行扫描 45 | 3. 仅学习使用 46 | 47 | ## 联系我们 48 | 邮箱:549286007@qq.com 49 | -------------------------------------------------------------------------------- /core/asp.go: -------------------------------------------------------------------------------- 1 | package core 2 | 3 | import "regexp" 4 | 5 | const ( 6 | ASP = "asp" 7 | ) 8 | 9 | var asp = &Plugin{ 10 | Name: ASP, 11 | Desc: "A plugin that detects webshell of vbscript type", 12 | Decoders: []Decoder{ 13 | { 14 | Name: "asp/base64_decode", 15 | Regex: regexp.MustCompile(`(?i)(?:=|\s+)(base64_decode\('('?\"?[A-Za-z0-9+\/=]+'?\"?))`), 16 | DataFilter: regexp.MustCompile(`(?i)((?:'|")[A-Za-z0-9+\/=]+(?:'|"))`), 17 | PreDecodeActions: []Action{ 18 | {Func: StringReplace, Arguments: []interface{}{"\"", "", -1}}, 19 | {Func: StringReplace, Arguments: []interface{}{"'", "", -1}}, 20 | }, 21 | Functions: []BaseFunc{DecodeBase64}, 22 | }, { 23 | Name: "asp/gz_inflate_base64_decode", 24 | Regex: regexp.MustCompile(`(?i)(gzinflate\(base64_decode\('('?\"?[A-Za-z0-9+\/=]+'?\"?))\)`), 25 | DataFilter: regexp.MustCompile(`(?i)((?:'|")[A-Za-z0-9+\/=]+(?:'|"))`), 26 | PreDecodeActions: []Action{ 27 | {Func: StringReplace, Arguments: []interface{}{"\"", "", -1}}, 28 | {Func: StringReplace, Arguments: []interface{}{"'", "", -1}}, 29 | }, 30 | Functions: []BaseFunc{DecodeBase64, GzInflate}, 31 | }, { 32 | Name: "asp/comment_obfuscation_1", 33 | Regex: regexp.MustCompile(`(?i).*(?:"|')\&(?:"|')\w+(?:"|')`), 34 | DataFilter: regexp.MustCompile(`(?i).*(?:"|')\&(?:"|')\w+(?:"|')`), 35 | PreDecodeActions: []Action{ 36 | {Func: StringReplace, Arguments: []interface{}{"\"", "", -1}}, 37 | {Func: StringReplace, Arguments: []interface{}{"'", "", -1}}, 38 | }, 39 | Functions: []BaseFunc{}, 40 | }, { 41 | Name: "asp/comment_obfuscation_2", 42 | Regex: regexp.MustCompile(`(?i).+(?:(?:'|")\.(?:'|")(?:\w+\.?)\w+(?:\s)?(?:/\w+\s+)?)+`), 43 | DataFilter: regexp.MustCompile(`(?i).+(?:(?:'|")\.(?:'|")(?:\w+\.?)\w+(?:\s)?(?:/\w+\s+)?)+`), 44 | PreDecodeActions: []Action{ 45 | {Func: StringReplace, Arguments: []interface{}{"\"", "", -1}}, 46 | {Func: StringReplace, Arguments: []interface{}{"'", "", -1}}, 47 | }, 48 | Functions: []BaseFunc{}, 49 | }, { 50 | Name: "asp/vbscript_encode", 51 | Regex: regexp.MustCompile(`(?i).*\+?(?:"|')\w+(?:"|')\+\w+\+(?:"|')\w+(?:"|')`), 52 | DataFilter: regexp.MustCompile(`(?i).*\+?(?:"|')\w+(?:"|')\+\w+\+(?:"|')\w+(?:"|')`), 53 | PreDecodeActions: []Action{ 54 | {Func: StringReplaceWithRegex, Arguments: []interface{}{`(?i)(?:"|')\+\w+\+(?:"|')`, "", -1}}, 55 | {Func: StringReplace, Arguments: []interface{}{"+", "", -1}}, 56 | {Func: StringReplace, Arguments: []interface{}{"\"++\"", "", -1}}, 57 | }, 58 | Functions: []BaseFunc{}, 59 | }, 60 | }, 61 | Tags: []Tag{ 62 | {Name: "asp/execution", Regex: regexp.MustCompile(`(?i)(?:e["+/*-]+v["+/*-]+a["+/*-]+l["+/*-]+\(|system\.diagnostics\.processstartinfo\(\w+\.substring\(|startinfo\.filename=\"?'?cmd\.exe"?'?|\seval\(request\.item\["?'?\w+"?'?\](?:,"?'?unsafe"?'?)?|execute(?:\(|\s+request\(\"\w+\"\))|RunCMD\(|\seval\(|COM\('?"?WScript\.(?:shell|network)"?'?|response\.write\()`), Scored: 80}, 63 | {Name: "asp/command", Regex: regexp.MustCompile(`(?i)\w+\.(?:ExecuteNonQuery|CreateCommand)\(`), Scored: 20}, 64 | {Name: "asp/disk_operations", Regex: regexp.MustCompile(`(?i)(?:createtextfile\(|server\.createobject\(\"Scripting\.FileSystemObject\"\))`), Scored: 50}, 65 | {Name: "asp/suspicious", Regex: regexp.MustCompile(`(?i)(?:deletefile\(server\.mappath\(\"\w+\.\w+\"\)\)|language\s+=\s+vbscript\.encode\s+%>(?:\s*|\r|\n)<%\s+response\.buffer=true:server\.scripttimeout=|(?i)language\s+=\s+vbscript\.encode%><%\n?\r?server\.scripttimeout=|executeglobal\(|server\.createobject\(\w+\(\w{1,5},\w{1,5}\)\))`), Scored: 60}, 66 | {Name: "asp/object_created", Regex: regexp.MustCompile(`(?i)server\.createobject\(\"(?:msxml2\.xmlhttp|microsoft\.xmlhttp|WSCRIPT\.SHELL|ADODB\.Connection)\"\)`), Scored: 55}, 67 | {Name: "asp/suspicious_import", Regex: regexp.MustCompile(`(?i)name(?:space)?="(?:system\.(?:serviceprocess|threading|(?:net\.sockets)))"?"`), Scored: 50}, 68 | {Name: "asp/process_threads", Regex: regexp.MustCompile(`(?:new\s+process\(\)|startinfo\.(?:filename|UseShellExecute|Redirect(?:StandardInput|StandardOutput|StandardError)|CreateNoWindow)|WaitForExit())`), Scored: 40}, 69 | {Name: "asp/database", Regex: regexp.MustCompile(`(?:(?:SqlDataAdapter|SqlConnection|SqlCommand)\(|System\.Data\.SqlClient|System\.Data\.OleDb|OleDbConnection\(\))`), Scored: 30}, 70 | {Name: "asp/behinder", Regex: regexp.MustCompile(`(?i)(session\.getValue\(.*AES.*\)|base64decoder|newInstance|session.Add\()`), Scored: 20, Repeat: true}, 71 | {Name: "asp/execution_2", Regex: regexp.MustCompile(`eval\((.*)Request.Item\[(.*)\](.*)\)`), Scored: 85}, 72 | }, 73 | Supports: []string{"asp", "aspx"}, 74 | } 75 | -------------------------------------------------------------------------------- /core/cfm.go: -------------------------------------------------------------------------------- 1 | package core 2 | 3 | import "regexp" 4 | 5 | const ( 6 | CFM = "cfm" 7 | ) 8 | 9 | var cfm = &Plugin{ 10 | Name: CFM, 11 | Desc: "A plugin that detects webshell of cfm type", 12 | Decoders: []Decoder{}, 13 | Tags: []Tag{ 14 | {Name: "cfm/execution", Regex: regexp.MustCompile(`(?i)(?:"?/c\s+"?'?#?cmd#?'?"?)`), Scored: 50}, 15 | }, 16 | Supports: []string{"cfm"}, 17 | } 18 | -------------------------------------------------------------------------------- /core/core.go: -------------------------------------------------------------------------------- 1 | package core 2 | 3 | import ( 4 | "bytes" 5 | "compress/flate" 6 | "encoding/base64" 7 | "fmt" 8 | "io/ioutil" 9 | "net/url" 10 | "reflect" 11 | "regexp" 12 | "strconv" 13 | "strings" 14 | ) 15 | 16 | type BaseFunc func(in []byte, args ...interface{}) ([]byte, error) 17 | 18 | type Action struct { 19 | Func BaseFunc 20 | Arguments []interface{} 21 | } 22 | 23 | type Decoder struct { 24 | Name string 25 | Regex *regexp.Regexp 26 | DataFilter *regexp.Regexp 27 | PreDecodeActions []Action 28 | PostDecodeActions []Action 29 | Functions []BaseFunc 30 | } 31 | 32 | type Tag struct { 33 | Name string 34 | Regex *regexp.Regexp 35 | Scored float64 // 计分 36 | Repeat bool // 标记规则是否需要重复计数 37 | } 38 | 39 | type Plugin struct { 40 | Name string 41 | Desc string 42 | Decoders []Decoder 43 | Tags []Tag 44 | Supports []string 45 | } 46 | 47 | var DecodeBase64 BaseFunc = func(in []byte, args ...interface{}) ([]byte, error) { 48 | return base64.StdEncoding.DecodeString(string(in)) 49 | } 50 | 51 | var GzInflate BaseFunc = func(in []byte, args ...interface{}) ([]byte, error) { 52 | return ioutil.ReadAll(flate.NewReader(bytes.NewReader(in))) 53 | } 54 | 55 | var UrlDecode BaseFunc = func(in []byte, args ...interface{}) ([]byte, error) { 56 | decodeString, err := url.QueryUnescape(string(in)) 57 | if err != nil { 58 | return nil, err 59 | } 60 | 61 | b := []byte(decodeString) 62 | return b, nil 63 | } 64 | 65 | var StringReplace BaseFunc = func(in []byte, args ...interface{}) ([]byte, error) { 66 | if len(args) != 3 { 67 | return nil, fmt.Errorf("[StringReplace] Bad number of main arguments: %v\n", args) 68 | } 69 | 70 | if reflect.TypeOf(args[0]).Kind() != reflect.String { 71 | return nil, fmt.Errorf("[StringReplace] Bad type found with first arguments: %v\n", args) 72 | } 73 | 74 | if reflect.TypeOf(args[1]).Kind() != reflect.String { 75 | return nil, fmt.Errorf("[StringReplace] Bad type found with second arguments: %v\n", args) 76 | } 77 | 78 | if reflect.TypeOf(args[2]).Kind() != reflect.Int { 79 | return nil, fmt.Errorf("[StringReplace] Bad type found with third arguments: %v\n", args) 80 | } 81 | 82 | cleanedItem := strings.Replace(string(in), args[0].(string), args[1].(string), args[2].(int)) 83 | 84 | return []byte(cleanedItem), nil 85 | } 86 | 87 | var StringReplaceWithRegex BaseFunc = func(in []byte, args ...interface{}) ([]byte, error) { 88 | if len(args) < 2 { 89 | return nil, fmt.Errorf("[StringReplaceWithRegex] Bad number of main arguments: %v\n", args) 90 | } 91 | 92 | if reflect.TypeOf(args[0]).Kind() != reflect.String { 93 | return nil, fmt.Errorf("[StringReplaceWithRegex] Bad type found with first arguments: %v\n", args) 94 | } 95 | 96 | if reflect.TypeOf(args[1]).Kind() != reflect.String { 97 | return nil, fmt.Errorf("[StringReplaceWithRegex] Bad type found with second arguments: %v\n", args) 98 | } 99 | 100 | regexItem, err := regexp.Compile(args[0].(string)) 101 | if err != nil { 102 | return nil, err 103 | } 104 | 105 | res := regexItem.ReplaceAllString(string(in), args[1].(string)) 106 | return []byte(res), nil 107 | } 108 | 109 | var CharDecode BaseFunc = func(in []byte, args ...interface{}) ([]byte, error) { 110 | var cleanedItem []string 111 | items := strings.Split(string(in), "|") 112 | for _, i := range items { 113 | getInt, err := strconv.Atoi(i) 114 | if err != nil { 115 | continue 116 | } 117 | ch := rune(getInt) 118 | cleanedItem = append(cleanedItem, fmt.Sprintf("%c", ch)) 119 | } 120 | 121 | if len(cleanedItem) == 0 { 122 | return in, nil 123 | } 124 | 125 | joinedItems := strings.Join(cleanedItem, "") 126 | return []byte(joinedItems), nil 127 | } 128 | 129 | func GetPlugins() []*Plugin { 130 | return []*Plugin{generic, asp, cfm, java, php} 131 | } 132 | 133 | func GetCalculators() []*Calculator { 134 | return []*Calculator{languageIC, entropy, longestWord, signatureNasty, useEval, compression} 135 | } -------------------------------------------------------------------------------- /core/generic.go: -------------------------------------------------------------------------------- 1 | package core 2 | 3 | import "regexp" 4 | 5 | const ( 6 | GENERIC = "generic" 7 | ) 8 | 9 | var generic = &Plugin{ 10 | Name: GENERIC, 11 | Desc: "A plugin that detects webshell of python or perl type", 12 | Decoders: []Decoder{ 13 | { 14 | Name: "generic/url_decode", 15 | Regex: regexp.MustCompile(`(?i)(https?(?:%3A%2F%2F|://%).+(?:\s+|'|"|=|\?))`), 16 | DataFilter: regexp.MustCompile(`(?i)(https?(?:%3A%2F%2F|://%).+(?:\s+|'|"|=|\?))`), 17 | PreDecodeActions: []Action{ 18 | {Func: StringReplace, Arguments: []interface{}{"\"", "", -1}}, 19 | {Func: StringReplace, Arguments: []interface{}{"'", "", -1}}, 20 | }, 21 | Functions: []BaseFunc{UrlDecode}, 22 | }, { 23 | Name: "generic/base64_decode", 24 | Regex: regexp.MustCompile(`(?i)((?:'|")[A-Za-z0-9+\/=]{8,}(?:'|"))`), 25 | DataFilter: regexp.MustCompile(`(?i)((?:'|")[A-Za-z0-9+\/=]{8,}(?:'|"))`), 26 | PreDecodeActions: []Action{ 27 | {Func: StringReplace, Arguments: []interface{}{"\"", "", -1}}, 28 | {Func: StringReplace, Arguments: []interface{}{"'", "", -1}}, 29 | }, 30 | Functions: []BaseFunc{DecodeBase64}, 31 | }, { 32 | Name: "generic/multiline_base64_decode", 33 | Regex: regexp.MustCompile(`(?i)(?:(?:'|')(?:[A-Za-z0-9+\/=]{4,})+(?:'|")\.?(?:\r|\n)?)+`), 34 | DataFilter: regexp.MustCompile(`(?i)(?:(?:'|')(?:[A-Za-z0-9+\/=]{4,})+(?:'|")\.?(?:\r|\n)?)+`), 35 | PreDecodeActions: []Action{ 36 | {Func: StringReplace, Arguments: []interface{}{"\r\n", "", -1}}, 37 | {Func: StringReplace, Arguments: []interface{}{"\n", "", -1}}, 38 | {Func: StringReplace, Arguments: []interface{}{"\r", "", -1}}, 39 | {Func: StringReplace, Arguments: []interface{}{"\"", "", -1}}, 40 | {Func: StringReplace, Arguments: []interface{}{"'", "", -1}}, 41 | {Func: StringReplace, Arguments: []interface{}{".", "", -1}}, 42 | }, 43 | Functions: []BaseFunc{DecodeBase64}, 44 | }, 45 | }, 46 | Tags: []Tag{ 47 | {Name: "generic/execution", Regex: regexp.MustCompile(`(?i)(?:\w+\.run\("%comspec% /c)`), Scored: 45}, 48 | {Name: "generic/keywords", Regex: regexp.MustCompile(`(?i)(?:xp_cmdshell|Database\s+Dump|ShiSanObjstr|Net\s+Sploit|SQLI\+Scan|shell\s?code|envlpass|files?man|c0derz\s?shell|md5\s?cracker|umer\s?rock|asp\s?cmd\s?shell|JspSpy|uZE\s?Shell|AK-74\s?Security\s?Team\s?Web\s?Shell|WinX\s?Shell|PHP C0nsole|cfmshell|cmdshell|Gamma\s?Web\s?Shell|ASPXSpy|IISSpy|Webshell|ASPX?\s?Shell|STNC WebShell|GRP\s?WebShell|National Cracker Crew)`), Scored: 16, Repeat: true}, 49 | {Name: "generic/domain", Regex: regexp.MustCompile(`(?i)(https?://(?:\d+\.\d+\.\d+\.\d+|\w+(?:\.\w+\.\w+|\.\w+)?)[/\w+\?=\.]+)`), Scored: 10, Repeat: true}, 50 | {Name: "generic/embedded_executable", Regex: regexp.MustCompile(`(?i)(?:(?:0x)?4D5A)`), Scored: 10, Repeat: true}, 51 | {Name: "generic/reconnaissance", Regex: regexp.MustCompile(`(?i)(?:tasklist|netstat|ipconfig|whoami|net\s+(?:localgroup|user)(?:\s|\w)+/add|net\s+start\s+)`), Scored: 10, Repeat: true}, 52 | {Name: "generic/commands", Regex: regexp.MustCompile(`(?i)(?:[wc]script\.(?:shell|network)|(?:cmd|powershell|[wc]script)(?:\.exe)?|cmd\.exe\s+/c)`), Scored: 15, Repeat: true}, 53 | {Name: "generic/registry_persistence", Regex: regexp.MustCompile(`(?i)(?:\\currentversion\\(?:run|runonce))`), Scored: 10, Repeat: true}, 54 | {Name: "generic/defense_evasion", Regex: regexp.MustCompile(`(?i)(?:strpos\(\$_SERVER\['HTTP_USER_AGENT'\],'Google'\))`), Scored: 50}, 55 | {Name: "generic/c_embedded_code", Regex: regexp.MustCompile(`(?i)(?:socket\(AF_INET,SOCK_STREAM|bind\(|listen\(|daemon\(1,0\))`), Scored: 20}, 56 | {Name: "generic/perl_embedded_code", Regex: regexp.MustCompile(`(?i)(?:getprotobyname\('tcp'\))|exec\s+\{'/bin/sh'\}\s+'-bash'`), Scored: 40}, 57 | {Name: "generic/python_embedded_code", Regex: regexp.MustCompile(`(?i)(?:)cgitb\.enable\(\)|print_exc\(|import\ssubprocess|os\.system\(|subprocess\.Popen\(|urllib\.urlretrieve\(`), Scored: 12, Repeat: true}, 58 | {Name: "generic/tcp_connected", Regex: regexp.MustCompile(`/dev/tcp/\d+\.\d+\.\d+\.\d+/\d+`), Scored: 55}, 59 | }, 60 | Supports: []string{}, 61 | } 62 | -------------------------------------------------------------------------------- /core/java.go: -------------------------------------------------------------------------------- 1 | package core 2 | 3 | import "regexp" 4 | 5 | const ( 6 | JAVA = "java" 7 | ) 8 | 9 | var java = &Plugin{ 10 | Name: JAVA, 11 | Desc: "A plugin that detects webshell of java type", 12 | Decoders: []Decoder{}, 13 | Tags: []Tag{ 14 | {Name: "java/execution", Regex: regexp.MustCompile(`(?i)(?:runtime\.exec\()`), Scored: 50}, 15 | {Name: "java/one", Regex: regexp.MustCompile(`(?i)(request.getParameter\(|new java.io.FileOutputStream\()`), Scored: 14, Repeat: true}, 16 | }, 17 | Supports: []string{"jsp", "jspx", "java"}, 18 | } 19 | -------------------------------------------------------------------------------- /core/npi.go: -------------------------------------------------------------------------------- 1 | package core 2 | 3 | import ( 4 | "bytes" 5 | "compress/zlib" 6 | "math" 7 | "regexp" 8 | ) 9 | 10 | const ( 11 | RateAsValue = iota 12 | FuncAsValue 13 | ExistAsValue 14 | CompareAsValue 15 | ) 16 | 17 | type CalculateFunc func(data string) float64 18 | type Calculator struct { 19 | Weight float64 20 | CalculateMethod int 21 | Coefficient float64 22 | Func CalculateFunc 23 | } 24 | 25 | func (c *Calculator) Uniformization(data string) float64 { 26 | value := float64(0) 27 | switch c.CalculateMethod { 28 | case RateAsValue: 29 | value = c.Func(data) * c.Coefficient * c.Weight 30 | case FuncAsValue: 31 | value = 1 / (1 + math.Pow(math.E, (c.Coefficient-4.0)-c.Func(data))) * c.Weight 32 | case ExistAsValue: 33 | if c.Func(data) > 0 { 34 | value = c.Weight * c.Coefficient 35 | } 36 | case CompareAsValue: 37 | if c.Func(data) > c.Coefficient { 38 | value = c.Weight 39 | } 40 | default: 41 | value = c.Func(data) * c.Weight 42 | } 43 | 44 | return value 45 | } 46 | 47 | var languageIC = &Calculator{ 48 | Weight: 1, 49 | CalculateMethod: RateAsValue, 50 | Coefficient: 1, 51 | Func: func(data string) float64 { 52 | if data == "" { 53 | return 0 54 | } 55 | 56 | charCount := 0 57 | charCountMap := make(map[byte]int) 58 | dataBytes := []byte(data) 59 | totalChar := len(dataBytes) 60 | fc := float64(totalChar*(totalChar-1)) 61 | if fc <= 0 { 62 | return 0 63 | } 64 | 65 | for _, b := range dataBytes { 66 | if _, ok := charCountMap[b]; ok { 67 | charCountMap[b] += 1 68 | } else { 69 | charCountMap[b] = 1 70 | } 71 | } 72 | 73 | for _, v := range charCountMap { 74 | charCount += v * (v - 1) 75 | } 76 | 77 | ic := float64(charCount) / fc 78 | return ic 79 | }, 80 | } 81 | 82 | var entropy = &Calculator{ 83 | Weight: 1, 84 | CalculateMethod: FuncAsValue, 85 | Coefficient: 6, 86 | Func: func(data string) float64 { 87 | if data == "" { 88 | return 0 89 | } 90 | 91 | entropy := float64(0) 92 | dataBytes := []byte(data) 93 | totalLength := 0 94 | charCountMap := make(map[byte]int) 95 | for _, b := range dataBytes { 96 | if b == ' ' { 97 | continue 98 | } 99 | totalLength += 1 100 | if _, ok := charCountMap[b]; ok { 101 | charCountMap[b] += 1 102 | } else { 103 | charCountMap[b] = 1 104 | } 105 | } 106 | 107 | if totalLength == 0 { 108 | return 0 109 | } 110 | 111 | for _, v := range charCountMap { 112 | px := float64(v) / float64(totalLength) 113 | if px > 0 { 114 | entropy += -px * math.Log2(px) 115 | } 116 | } 117 | return entropy 118 | }, 119 | } 120 | 121 | var longestWord = &Calculator{ 122 | Weight: 1, 123 | CalculateMethod: CompareAsValue, 124 | Coefficient: 256, 125 | Func: func(data string) float64 { 126 | if data == "" { 127 | return 0 128 | } 129 | longest := 0 130 | re := regexp.MustCompile(`[\s\n\r]`) 131 | words := re.Split(data, -1) 132 | for _, word := range words { 133 | length := len(word) 134 | if length > longest { 135 | longest = length 136 | } 137 | } 138 | return float64(longest) 139 | }, 140 | } 141 | 142 | var signatureNasty = &Calculator{ 143 | Weight: 1, 144 | CalculateMethod: ExistAsValue, 145 | Coefficient: 1, 146 | Func: func(data string) float64 { 147 | validRegex := regexp.MustCompile(`(?i)(eval\(|file_put_contents|base64_decode|python_eval|exec\(|passthru|popen|proc_open|pcntl|assert\(|system\(|shell)`) 148 | matches := validRegex.FindAllString(data, -1) 149 | matchesLength := len(matches) 150 | return float64(matchesLength) 151 | }, 152 | } 153 | 154 | var useEval = &Calculator{ 155 | Weight: 1, 156 | CalculateMethod: ExistAsValue, 157 | Coefficient: 1, 158 | Func: func(data string) float64 { 159 | validRegex := regexp.MustCompile(`(?i)(eval\(\$(\w|\d))`) 160 | matches := validRegex.FindAllString(data, -1) 161 | matchesLength := len(matches) 162 | return float64(matchesLength) 163 | }, 164 | } 165 | 166 | var compression = &Calculator{ 167 | Weight: 1, 168 | CalculateMethod: RateAsValue, 169 | Coefficient: 1, 170 | Func: func(data string) float64 { 171 | if data == "" { 172 | return 0 173 | } 174 | 175 | var buf bytes.Buffer 176 | writer := zlib.NewWriter(&buf) 177 | _, _ = writer.Write([]byte(data)) 178 | _ = writer.Close() 179 | return float64(len(buf.String())) / float64(len(data)) 180 | }, 181 | } 182 | 183 | -------------------------------------------------------------------------------- /core/php.go: -------------------------------------------------------------------------------- 1 | package core 2 | 3 | import "regexp" 4 | 5 | const ( 6 | PHP = "php" 7 | ) 8 | 9 | var php = &Plugin{ 10 | Name: PHP, 11 | Desc: "A plugin that detects webshell of php type", 12 | Decoders: []Decoder{ 13 | { 14 | Name: "php/base64_decode", 15 | Regex: regexp.MustCompile(`(?i)(?:=|\s+)(base64_decode\('('?\"?[A-Za-z0-9+\/=]+'?\"?))`), 16 | DataFilter: regexp.MustCompile(`(?i)((?:'|")[A-Za-z0-9+\/=]+(?:'|"))`), 17 | PreDecodeActions: []Action{ 18 | {Func: StringReplace, Arguments: []interface{}{"\"", "", -1}}, 19 | {Func: StringReplace, Arguments: []interface{}{"'", "", -1}}, 20 | }, 21 | Functions: []BaseFunc{DecodeBase64}, 22 | }, { 23 | Name: "php/gz_inflate_base64_decode", 24 | Regex: regexp.MustCompile(`(?i)(gzinflate\(base64_decode\('('?\"?[A-Za-z0-9+\/=]+'?\"?))\)`), 25 | DataFilter: regexp.MustCompile(`(?i)((?:'|")[A-Za-z0-9+\/=]+(?:'|"))`), 26 | PreDecodeActions: []Action{ 27 | {Func: StringReplace, Arguments: []interface{}{"\"", "", -1}}, 28 | {Func: StringReplace, Arguments: []interface{}{"'", "", -1}}, 29 | }, 30 | Functions: []BaseFunc{DecodeBase64, GzInflate}, 31 | }, { 32 | Name: "php/url_decode", 33 | Regex: regexp.MustCompile(`(?i)(urldecode\('?"?[%\w+]+'?"?\))`), 34 | DataFilter: regexp.MustCompile(`(?i)((?:'|")'?"?[%\w+]+'?"?)`), 35 | PreDecodeActions: []Action{ 36 | {Func: StringReplace, Arguments: []interface{}{"\"", "", -1}}, 37 | {Func: StringReplace, Arguments: []interface{}{"'", "", -1}}, 38 | }, 39 | Functions: []BaseFunc{UrlDecode}, 40 | }, { 41 | Name: "php/dot_concatenation", 42 | Regex: regexp.MustCompile(`(?i).+(?:(?:'|")\.(?:'|")(?:\w+\.?)\w+(?:\s)?(?:/\w+\s+)?)+`), 43 | DataFilter: regexp.MustCompile(`(?i).+(?:(?:'|")\.(?:'|")(?:\w+\.?)\w+(?:\s)?(?:/\w+\s+)?)+`), 44 | PreDecodeActions: []Action{ 45 | {Func: StringReplace, Arguments: []interface{}{"\"", "", -1}}, 46 | {Func: StringReplace, Arguments: []interface{}{"'", "", -1}}, 47 | }, 48 | Functions: []BaseFunc{}, 49 | }, { 50 | Name: "php/char_decode", 51 | Regex: regexp.MustCompile(`(?:(?:\.chr\(\d+\))+|array\((?:\r|\n|\r\n|\n\r|\s+)chr\(\d+\)\.(chr\(\d+\)(?:\.|,)(?:\s+)?)+chr\(\d+\))`), 52 | DataFilter: regexp.MustCompile(`(?:(?:\.chr\(\d+\))+|chr\(\d+\)\.(chr\(\d+\)(?:\.|,)(?:\s+)?)+chr\(\d+\))`), 53 | PreDecodeActions: []Action{ 54 | {Func: StringReplace, Arguments: []interface{}{"chr", "", -1}}, 55 | {Func: StringReplace, Arguments: []interface{}{" ", "", -1}}, 56 | {Func: StringReplace, Arguments: []interface{}{")", "", -1}}, 57 | {Func: StringReplace, Arguments: []interface{}{"(", "|", -1}}, 58 | {Func: StringReplace, Arguments: []interface{}{",", "", -1}}, 59 | {Func: StringReplace, Arguments: []interface{}{".", "", -1}}, 60 | }, 61 | Functions: []BaseFunc{CharDecode}, 62 | }, 63 | }, 64 | Tags: []Tag{ 65 | {Name: "php/functions_1", Regex: regexp.MustCompile(`(?i)(?:allow_url_fopen\(|fsockopen\(|getrusage\(|get_current_user\(|set_time_limit\(|getmyuid\(|getmypid\(|dl\(|leak\(|listen\(|chown\(|chgrp\(|realpath\(|link\(|exec\(|passthru\(|curl_init\()`), Scored: 40}, 66 | {Name: "php/reconnaissance", Regex: regexp.MustCompile(`(?i)(?:@ini_get\("disable_functions"\)|gethostbyname\(|phpversion\(|disk_total_space\(|posix_getpwuid\(|posix_getgrgid\(|phpinfo\()`), Scored: 30}, 67 | {Name: "php/database", Regex: regexp.MustCompile(`(?i)(?:'mssql_connect\('|ocilogon\(|mysql_list_dbs\(mysql_num_rows\(|mysql_dbname\(|mysql_create_db\(|mysql_drop_db\(|mysql_query\(|mysql_exec\()`), Scored: 20}, 68 | {Name: "php/disk_operation", Regex: regexp.MustCompile(`(?i)(?:(?:\s|@)rename\(|(%s|@)chmod\(|(%s|@)fileowner\(|(%s|@)filegroup\(|fopen\(|fwrite\(\))`), Scored: 20, Repeat: true}, 69 | {Name: "php/execution", Regex: regexp.MustCompile(`(?i)(?:(?:\s|\()(?:curl_exec\(|eval\(|exec\(|system\(|shell_exec\(|execute\(|passthru\()|(?:assert|array)\(\$_REQUEST\['?"?\w+"?'?\]|\$\{"?'?_REQUEST'?"?\})`), Scored: 50}, 70 | {Name: "php/defense_evasion", Regex: regexp.MustCompile(`(?i)(?:gzinflate\(base64_decode\(|preg_replace\(|\(md5\(md5\(\$\w+\))`), Scored: 5, Repeat: true}, 71 | {Name: "php/network_operation", Regex: regexp.MustCompile(`(?i)(?:fsockopen\()`), Scored: 10, Repeat: true}, 72 | {Name: "php/functions_2", Regex: regexp.MustCompile(`(?i)function\_exists\s*\(\s*[\'|\"](popen|exec|proc\_open|system|passthru)+[\'|\"]\s*\)`), Scored: 40}, 73 | {Name: "php/network", Regex: regexp.MustCompile(`(?i)((udp|tcp)\:\/\/(.*)\;)+`), Scored: 10, Repeat: true}, 74 | {Name: "php/include_source", Regex: regexp.MustCompile(`(?i)(include|require|include\_once|require\_once)+\s*\(\s*[\'|\"](\w+)\.(jpg|gif|ico|bmp|png|txt|zip|rar|htm|css|js)+[\'|\"]\s*\)`), Scored: 12, Repeat: true}, 75 | {Name: "php/file_operation", Regex: regexp.MustCompile(`(?i)\(\s*\$\_FILES\[(.*)\]\[(.*)\]\s*\,\s*\$\_(GET|POST|REQUEST|FILES)+\[(.*)\]\[(.*)\]\s*\)`), Scored: 13, Repeat: true}, 76 | {Name: "php/execution_2", Regex: regexp.MustCompile(`eval\((.*)\$\_POST\[(.*)\](.*)\)`), Scored: 85}, 77 | {Name: "php/execution_3", Regex: regexp.MustCompile(`(?i)(server.MapPath\(Request\[(.*)\](.*)\))`), Scored: 80}, 78 | {Name: "php/execution_4", Regex: regexp.MustCompile(`(system\(|assert\(|eval\()(.*)\$\_(POST|REQUEST)\[`), Scored: 75}, 79 | }, 80 | Supports: []string{"php"}, 81 | } 82 | -------------------------------------------------------------------------------- /core/utils.go: -------------------------------------------------------------------------------- 1 | package core 2 | 3 | import ( 4 | "crypto/sha256" 5 | "fmt" 6 | "math" 7 | "strings" 8 | ) 9 | 10 | func sha256HashString(data []byte) string { 11 | h := sha256.New() 12 | h.Write(data) 13 | hash := fmt.Sprintf("%x", h.Sum(nil)) 14 | return hash 15 | } 16 | 17 | func runActionFunctions(functions []Action, rawBytes []byte) ([]byte, bool, error) { 18 | if len(functions) == 0 { 19 | return rawBytes, false, nil 20 | } 21 | 22 | oHash := sha256HashString(rawBytes) 23 | 24 | for _, f := range functions { 25 | decoded, err := f.Func(rawBytes, f.Arguments...) 26 | if err != nil { 27 | return rawBytes, false, err 28 | } 29 | rawBytes = decoded 30 | } 31 | 32 | changed := false 33 | nHash := sha256HashString(rawBytes) 34 | if oHash != nHash { 35 | changed = true 36 | } 37 | 38 | return rawBytes, changed, nil 39 | } 40 | 41 | func runDecodingFunctions(functions []BaseFunc, rawBytes []byte) ([]byte, error) { 42 | for _, f := range functions { 43 | decoded, err := f(rawBytes) 44 | if len(decoded) == 0 { 45 | return rawBytes, nil 46 | } 47 | 48 | if err != nil { 49 | return rawBytes, err 50 | } 51 | rawBytes = decoded 52 | } 53 | 54 | return rawBytes, nil 55 | } 56 | 57 | func hasElement(src []string, dst string) bool { 58 | for _, elm := range src { 59 | if elm == dst { 60 | return true 61 | } 62 | } 63 | 64 | return false 65 | } 66 | 67 | func guessFileType(filename, content string) string { 68 | fileExt := "" 69 | if strings.Index(filename, ".") >= 0 { 70 | fileSplits := strings.Split(filename, ".") 71 | fileExt = fileSplits[len(fileSplits)-1] 72 | } 73 | if strings.HasPrefix(content, " 0 && !hasElement(plugin.Supports, fileType) { 100 | continue 101 | } 102 | for _, ti := range plugin.Tags { 103 | tagMatches := ti.Regex.FindAllString(data, -1) 104 | if len(tagMatches) == 0 { 105 | continue 106 | } 107 | 108 | p := float64(1) 109 | for _, tm := range tagMatches { 110 | if tm == "" || len(tm) > 256 { 111 | continue 112 | } 113 | 114 | if !ti.Repeat { 115 | if _, ok := fileMatches[tm]; ok { 116 | fileMatches[tm] = fileMatches[tm] + 1 117 | p = float64(fileMatches[tm])*0.002 + p 118 | } else { 119 | fileMatches[tm] = 1 120 | } 121 | } 122 | } 123 | matchValue += ti.Scored * p 124 | } 125 | for _, tr := range plugin.Decoders { 126 | obfuscateMatches := tr.Regex.FindAllString(data, -1) 127 | if len(obfuscateMatches) == 0 { 128 | continue 129 | } 130 | for _, om := range obfuscateMatches { 131 | filters := tr.DataFilter.FindAllString(om, -1) 132 | if len(filters) == 0 { 133 | continue 134 | } 135 | 136 | for _, filterMatched := range filters { 137 | changedBytes, _, err := runActionFunctions(tr.PreDecodeActions, []byte(filterMatched)) 138 | if err != nil { 139 | fmt.Printf("pre runActionFunctions error : %v\n", err) 140 | continue 141 | } 142 | 143 | decoded, err := runDecodingFunctions(tr.Functions, changedBytes) 144 | if err != nil || len(decoded) == 0 || om == string(decoded) { 145 | continue 146 | } else { 147 | postDecoded, changed, err := runActionFunctions(tr.PostDecodeActions, decoded) 148 | if err != nil { 149 | continue 150 | } 151 | 152 | if changed && count <= maxLoop { 153 | dataChan <- string(postDecoded) 154 | count++ 155 | } 156 | 157 | if count <= maxLoop { 158 | dataChan <- string(decoded) 159 | count++ 160 | } 161 | } 162 | } 163 | } 164 | } 165 | } 166 | 167 | if len(dataChan) == 0 { 168 | close(dataChan) 169 | break 170 | } 171 | } 172 | 173 | return fileMatches, math.Min(matchValue, 100) 174 | } 175 | -------------------------------------------------------------------------------- /detector/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "encoding/json" 5 | "flag" 6 | "fmt" 7 | "github.com/patrikeh/go-deep" 8 | "io/fs" 9 | "io/ioutil" 10 | "os" 11 | "path/filepath" 12 | "sync" 13 | "wxel/core" 14 | ) 15 | 16 | const ( 17 | MaxFileSize = 10 * 1024 * 1024 18 | EndSig = "__WXX__" 19 | ModuleContent = ` 20 | { 21 | "Layers": [ 22 | { 23 | "Neurons": [ 24 | { 25 | "In": [ 26 | { 27 | "Weight": 0.07802227838030487, 28 | "IsBias": false 29 | }, 30 | { 31 | "Weight": 1.4095429709623049, 32 | "IsBias": false 33 | }, 34 | { 35 | "Weight": 0.38148619141265666, 36 | "IsBias": false 37 | }, 38 | { 39 | "Weight": -6.362409388325939, 40 | "IsBias": false 41 | }, 42 | { 43 | "Weight": 4.080571054281222, 44 | "IsBias": false 45 | }, 46 | { 47 | "Weight": -1.107085408804461, 48 | "IsBias": false 49 | }, 50 | { 51 | "Weight": -2.807126016126731, 52 | "IsBias": false 53 | }, 54 | { 55 | "Weight": -1.9763170163830057, 56 | "IsBias": true 57 | } 58 | ], 59 | "Out": [ 60 | { 61 | "Weight": 2.823264326167646, 62 | "IsBias": false 63 | }, 64 | { 65 | "Weight": -0.6608600824674566, 66 | "IsBias": false 67 | }, 68 | { 69 | "Weight": 2.874326287374728, 70 | "IsBias": false 71 | }, 72 | { 73 | "Weight": 0.08416886315759835, 74 | "IsBias": false 75 | }, 76 | { 77 | "Weight": 0.8153010040531086, 78 | "IsBias": false 79 | }, 80 | { 81 | "Weight": -4.472337116575626, 82 | "IsBias": false 83 | }, 84 | { 85 | "Weight": 0.541617145636806, 86 | "IsBias": false 87 | } 88 | ] 89 | }, 90 | { 91 | "In": [ 92 | { 93 | "Weight": -0.6543721724426969, 94 | "IsBias": false 95 | }, 96 | { 97 | "Weight": -0.11351002316301177, 98 | "IsBias": false 99 | }, 100 | { 101 | "Weight": -2.778411050495509, 102 | "IsBias": false 103 | }, 104 | { 105 | "Weight": -1.5991736481774113, 106 | "IsBias": false 107 | }, 108 | { 109 | "Weight": 0.9136739867878497, 110 | "IsBias": false 111 | }, 112 | { 113 | "Weight": -0.644907220299406, 114 | "IsBias": false 115 | }, 116 | { 117 | "Weight": -0.8640656179897181, 118 | "IsBias": false 119 | }, 120 | { 121 | "Weight": -0.9315779426960278, 122 | "IsBias": true 123 | } 124 | ], 125 | "Out": [ 126 | { 127 | "Weight": -1.4567022684114097, 128 | "IsBias": false 129 | }, 130 | { 131 | "Weight": -0.6468592746969144, 132 | "IsBias": false 133 | }, 134 | { 135 | "Weight": 0.6201992476017124, 136 | "IsBias": false 137 | }, 138 | { 139 | "Weight": 0.9125011159360927, 140 | "IsBias": false 141 | }, 142 | { 143 | "Weight": 2.607038733396296, 144 | "IsBias": false 145 | }, 146 | { 147 | "Weight": -1.0749890159529927, 148 | "IsBias": false 149 | }, 150 | { 151 | "Weight": -1.0208558454295986, 152 | "IsBias": false 153 | } 154 | ] 155 | }, 156 | { 157 | "In": [ 158 | { 159 | "Weight": -1.1872150471109126, 160 | "IsBias": false 161 | }, 162 | { 163 | "Weight": -7.463649545207768, 164 | "IsBias": false 165 | }, 166 | { 167 | "Weight": 2.541632683678553, 168 | "IsBias": false 169 | }, 170 | { 171 | "Weight": 4.160943382846905, 172 | "IsBias": false 173 | }, 174 | { 175 | "Weight": -2.5973806466094373, 176 | "IsBias": false 177 | }, 178 | { 179 | "Weight": 1.653957746597271, 180 | "IsBias": false 181 | }, 182 | { 183 | "Weight": -6.884847050043971, 184 | "IsBias": false 185 | }, 186 | { 187 | "Weight": -0.2102350505281358, 188 | "IsBias": true 189 | } 190 | ], 191 | "Out": [ 192 | { 193 | "Weight": 2.554024565257, 194 | "IsBias": false 195 | }, 196 | { 197 | "Weight": -8.859300727382568, 198 | "IsBias": false 199 | }, 200 | { 201 | "Weight": 2.124795830106873, 202 | "IsBias": false 203 | }, 204 | { 205 | "Weight": -1.9398906019689914, 206 | "IsBias": false 207 | }, 208 | { 209 | "Weight": -0.4523080851775894, 210 | "IsBias": false 211 | }, 212 | { 213 | "Weight": 1.9595764594365557, 214 | "IsBias": false 215 | }, 216 | { 217 | "Weight": 1.5940597677757709, 218 | "IsBias": false 219 | } 220 | ] 221 | }, 222 | { 223 | "In": [ 224 | { 225 | "Weight": -0.8161856401698268, 226 | "IsBias": false 227 | }, 228 | { 229 | "Weight": 0.3635586661044913, 230 | "IsBias": false 231 | }, 232 | { 233 | "Weight": -0.8561591068732642, 234 | "IsBias": false 235 | }, 236 | { 237 | "Weight": 3.2480544414176213, 238 | "IsBias": false 239 | }, 240 | { 241 | "Weight": 2.7176779107757576, 242 | "IsBias": false 243 | }, 244 | { 245 | "Weight": 2.114108264406231, 246 | "IsBias": false 247 | }, 248 | { 249 | "Weight": -2.7332781368465193, 250 | "IsBias": false 251 | }, 252 | { 253 | "Weight": -1.7746029214858727, 254 | "IsBias": true 255 | } 256 | ], 257 | "Out": [ 258 | { 259 | "Weight": 0.4858741702633786, 260 | "IsBias": false 261 | }, 262 | { 263 | "Weight": -1.9626762022939586, 264 | "IsBias": false 265 | }, 266 | { 267 | "Weight": 1.564911000482225, 268 | "IsBias": false 269 | }, 270 | { 271 | "Weight": -0.5474493229412074, 272 | "IsBias": false 273 | }, 274 | { 275 | "Weight": 0.9770208354067265, 276 | "IsBias": false 277 | }, 278 | { 279 | "Weight": 5.264125280855112, 280 | "IsBias": false 281 | }, 282 | { 283 | "Weight": 0.8485257255411578, 284 | "IsBias": false 285 | } 286 | ] 287 | }, 288 | { 289 | "In": [ 290 | { 291 | "Weight": 1.5126562493704359, 292 | "IsBias": false 293 | }, 294 | { 295 | "Weight": 1.163872021778959, 296 | "IsBias": false 297 | }, 298 | { 299 | "Weight": -1.383147543863053, 300 | "IsBias": false 301 | }, 302 | { 303 | "Weight": -0.9361762294091227, 304 | "IsBias": false 305 | }, 306 | { 307 | "Weight": -3.427184157113483, 308 | "IsBias": false 309 | }, 310 | { 311 | "Weight": 1.0491574601330103, 312 | "IsBias": false 313 | }, 314 | { 315 | "Weight": 2.888658925819805, 316 | "IsBias": false 317 | }, 318 | { 319 | "Weight": -0.2488760831751973, 320 | "IsBias": true 321 | } 322 | ], 323 | "Out": [ 324 | { 325 | "Weight": 0.42286271187185837, 326 | "IsBias": false 327 | }, 328 | { 329 | "Weight": 4.420592558849064, 330 | "IsBias": false 331 | }, 332 | { 333 | "Weight": -0.005199491406042553, 334 | "IsBias": false 335 | }, 336 | { 337 | "Weight": -1.8270924471744798, 338 | "IsBias": false 339 | }, 340 | { 341 | "Weight": -1.8412769059668865, 342 | "IsBias": false 343 | }, 344 | { 345 | "Weight": -0.0002618591164747282, 346 | "IsBias": false 347 | }, 348 | { 349 | "Weight": 1.652621845539065, 350 | "IsBias": false 351 | } 352 | ] 353 | }, 354 | { 355 | "In": [ 356 | { 357 | "Weight": 0.1508130089938433, 358 | "IsBias": false 359 | }, 360 | { 361 | "Weight": -23.046630100513514, 362 | "IsBias": false 363 | }, 364 | { 365 | "Weight": 6.5465449241651905, 366 | "IsBias": false 367 | }, 368 | { 369 | "Weight": -0.8300577963162118, 370 | "IsBias": false 371 | }, 372 | { 373 | "Weight": 1.1659991302927029, 374 | "IsBias": false 375 | }, 376 | { 377 | "Weight": 3.388516829744258, 378 | "IsBias": false 379 | }, 380 | { 381 | "Weight": 2.560645561046732, 382 | "IsBias": false 383 | }, 384 | { 385 | "Weight": -8.268192950753948, 386 | "IsBias": true 387 | } 388 | ], 389 | "Out": [ 390 | { 391 | "Weight": 2.0967476989197014, 392 | "IsBias": false 393 | }, 394 | { 395 | "Weight": -13.24364434981652, 396 | "IsBias": false 397 | }, 398 | { 399 | "Weight": 0.6450334785481243, 400 | "IsBias": false 401 | }, 402 | { 403 | "Weight": -0.46401719447258427, 404 | "IsBias": false 405 | }, 406 | { 407 | "Weight": 1.2716511370872574, 408 | "IsBias": false 409 | }, 410 | { 411 | "Weight": -9.002423228035425, 412 | "IsBias": false 413 | }, 414 | { 415 | "Weight": 1.177512973282399, 416 | "IsBias": false 417 | } 418 | ] 419 | }, 420 | { 421 | "In": [ 422 | { 423 | "Weight": 0.8647526321507062, 424 | "IsBias": false 425 | }, 426 | { 427 | "Weight": 0.8490082021930392, 428 | "IsBias": false 429 | }, 430 | { 431 | "Weight": 0.49293798758077706, 432 | "IsBias": false 433 | }, 434 | { 435 | "Weight": -2.0811563073490933, 436 | "IsBias": false 437 | }, 438 | { 439 | "Weight": 0.10231197547215905, 440 | "IsBias": false 441 | }, 442 | { 443 | "Weight": -0.7495060056871233, 444 | "IsBias": false 445 | }, 446 | { 447 | "Weight": 1.9173447282930045, 448 | "IsBias": false 449 | }, 450 | { 451 | "Weight": 1.9931956279109675, 452 | "IsBias": true 453 | } 454 | ], 455 | "Out": [ 456 | { 457 | "Weight": 0.17944219243805762, 458 | "IsBias": false 459 | }, 460 | { 461 | "Weight": 4.812901564860926, 462 | "IsBias": false 463 | }, 464 | { 465 | "Weight": -0.6599655385106953, 466 | "IsBias": false 467 | }, 468 | { 469 | "Weight": -0.8285849645117789, 470 | "IsBias": false 471 | }, 472 | { 473 | "Weight": -0.5752556075921808, 474 | "IsBias": false 475 | }, 476 | { 477 | "Weight": 0.12363989988964785, 478 | "IsBias": false 479 | }, 480 | { 481 | "Weight": -1.3640735170392506, 482 | "IsBias": false 483 | } 484 | ] 485 | } 486 | ], 487 | "A": 1 488 | }, 489 | { 490 | "Neurons": [ 491 | { 492 | "In": [ 493 | { 494 | "Weight": 2.823264326167646, 495 | "IsBias": false 496 | }, 497 | { 498 | "Weight": -1.4567022684114097, 499 | "IsBias": false 500 | }, 501 | { 502 | "Weight": 2.554024565257, 503 | "IsBias": false 504 | }, 505 | { 506 | "Weight": 0.4858741702633786, 507 | "IsBias": false 508 | }, 509 | { 510 | "Weight": 0.42286271187185837, 511 | "IsBias": false 512 | }, 513 | { 514 | "Weight": 2.0967476989197014, 515 | "IsBias": false 516 | }, 517 | { 518 | "Weight": 0.17944219243805762, 519 | "IsBias": false 520 | }, 521 | { 522 | "Weight": -1.2094826988114533, 523 | "IsBias": true 524 | } 525 | ], 526 | "Out": [ 527 | { 528 | "Weight": 2.9625838315842685, 529 | "IsBias": false 530 | } 531 | ] 532 | }, 533 | { 534 | "In": [ 535 | { 536 | "Weight": -0.6608600824674566, 537 | "IsBias": false 538 | }, 539 | { 540 | "Weight": -0.6468592746969144, 541 | "IsBias": false 542 | }, 543 | { 544 | "Weight": -8.859300727382568, 545 | "IsBias": false 546 | }, 547 | { 548 | "Weight": -1.9626762022939586, 549 | "IsBias": false 550 | }, 551 | { 552 | "Weight": 4.420592558849064, 553 | "IsBias": false 554 | }, 555 | { 556 | "Weight": -13.24364434981652, 557 | "IsBias": false 558 | }, 559 | { 560 | "Weight": 4.812901564860926, 561 | "IsBias": false 562 | }, 563 | { 564 | "Weight": 5.228805923360504, 565 | "IsBias": true 566 | } 567 | ], 568 | "Out": [ 569 | { 570 | "Weight": -9.999487077716411, 571 | "IsBias": false 572 | } 573 | ] 574 | }, 575 | { 576 | "In": [ 577 | { 578 | "Weight": 2.874326287374728, 579 | "IsBias": false 580 | }, 581 | { 582 | "Weight": 0.6201992476017124, 583 | "IsBias": false 584 | }, 585 | { 586 | "Weight": 2.124795830106873, 587 | "IsBias": false 588 | }, 589 | { 590 | "Weight": 1.564911000482225, 591 | "IsBias": false 592 | }, 593 | { 594 | "Weight": -0.005199491406042553, 595 | "IsBias": false 596 | }, 597 | { 598 | "Weight": 0.6450334785481243, 599 | "IsBias": false 600 | }, 601 | { 602 | "Weight": -0.6599655385106953, 603 | "IsBias": false 604 | }, 605 | { 606 | "Weight": 0.22539821471540675, 607 | "IsBias": true 608 | } 609 | ], 610 | "Out": [ 611 | { 612 | "Weight": 0.9142345072830496, 613 | "IsBias": false 614 | } 615 | ] 616 | }, 617 | { 618 | "In": [ 619 | { 620 | "Weight": 0.08416886315759835, 621 | "IsBias": false 622 | }, 623 | { 624 | "Weight": 0.9125011159360927, 625 | "IsBias": false 626 | }, 627 | { 628 | "Weight": -1.9398906019689914, 629 | "IsBias": false 630 | }, 631 | { 632 | "Weight": -0.5474493229412074, 633 | "IsBias": false 634 | }, 635 | { 636 | "Weight": -1.8270924471744798, 637 | "IsBias": false 638 | }, 639 | { 640 | "Weight": -0.46401719447258427, 641 | "IsBias": false 642 | }, 643 | { 644 | "Weight": -0.8285849645117789, 645 | "IsBias": false 646 | }, 647 | { 648 | "Weight": 0.4088587013744612, 649 | "IsBias": true 650 | } 651 | ], 652 | "Out": [ 653 | { 654 | "Weight": -0.9946146958150462, 655 | "IsBias": false 656 | } 657 | ] 658 | }, 659 | { 660 | "In": [ 661 | { 662 | "Weight": 0.8153010040531086, 663 | "IsBias": false 664 | }, 665 | { 666 | "Weight": 2.607038733396296, 667 | "IsBias": false 668 | }, 669 | { 670 | "Weight": -0.4523080851775894, 671 | "IsBias": false 672 | }, 673 | { 674 | "Weight": 0.9770208354067265, 675 | "IsBias": false 676 | }, 677 | { 678 | "Weight": -1.8412769059668865, 679 | "IsBias": false 680 | }, 681 | { 682 | "Weight": 1.2716511370872574, 683 | "IsBias": false 684 | }, 685 | { 686 | "Weight": -0.5752556075921808, 687 | "IsBias": false 688 | }, 689 | { 690 | "Weight": -1.867772136167738, 691 | "IsBias": true 692 | } 693 | ], 694 | "Out": [ 695 | { 696 | "Weight": -0.6289069630331902, 697 | "IsBias": false 698 | } 699 | ] 700 | }, 701 | { 702 | "In": [ 703 | { 704 | "Weight": -4.472337116575626, 705 | "IsBias": false 706 | }, 707 | { 708 | "Weight": -1.0749890159529927, 709 | "IsBias": false 710 | }, 711 | { 712 | "Weight": 1.9595764594365557, 713 | "IsBias": false 714 | }, 715 | { 716 | "Weight": 5.264125280855112, 717 | "IsBias": false 718 | }, 719 | { 720 | "Weight": -0.0002618591164747282, 721 | "IsBias": false 722 | }, 723 | { 724 | "Weight": -9.002423228035425, 725 | "IsBias": false 726 | }, 727 | { 728 | "Weight": 0.12363989988964785, 729 | "IsBias": false 730 | }, 731 | { 732 | "Weight": -1.7528277681637259, 733 | "IsBias": true 734 | } 735 | ], 736 | "Out": [ 737 | { 738 | "Weight": -8.924683714488317, 739 | "IsBias": false 740 | } 741 | ] 742 | }, 743 | { 744 | "In": [ 745 | { 746 | "Weight": 0.541617145636806, 747 | "IsBias": false 748 | }, 749 | { 750 | "Weight": -1.0208558454295986, 751 | "IsBias": false 752 | }, 753 | { 754 | "Weight": 1.5940597677757709, 755 | "IsBias": false 756 | }, 757 | { 758 | "Weight": 0.8485257255411578, 759 | "IsBias": false 760 | }, 761 | { 762 | "Weight": 1.652621845539065, 763 | "IsBias": false 764 | }, 765 | { 766 | "Weight": 1.177512973282399, 767 | "IsBias": false 768 | }, 769 | { 770 | "Weight": -1.3640735170392506, 771 | "IsBias": false 772 | }, 773 | { 774 | "Weight": -0.1756287167395903, 775 | "IsBias": true 776 | } 777 | ], 778 | "Out": [ 779 | { 780 | "Weight": 2.6923075873996263, 781 | "IsBias": false 782 | } 783 | ] 784 | } 785 | ], 786 | "A": 1 787 | }, 788 | { 789 | "Neurons": [ 790 | { 791 | "In": [ 792 | { 793 | "Weight": 2.9625838315842685, 794 | "IsBias": false 795 | }, 796 | { 797 | "Weight": -9.999487077716411, 798 | "IsBias": false 799 | }, 800 | { 801 | "Weight": 0.9142345072830496, 802 | "IsBias": false 803 | }, 804 | { 805 | "Weight": -0.9946146958150462, 806 | "IsBias": false 807 | }, 808 | { 809 | "Weight": -0.6289069630331902, 810 | "IsBias": false 811 | }, 812 | { 813 | "Weight": -8.924683714488317, 814 | "IsBias": false 815 | }, 816 | { 817 | "Weight": 2.6923075873996263, 818 | "IsBias": false 819 | }, 820 | { 821 | "Weight": 3.718106292738009, 822 | "IsBias": true 823 | } 824 | ], 825 | "Out": null 826 | } 827 | ], 828 | "A": 1 829 | } 830 | ], 831 | "Biases": [ 832 | [ 833 | { 834 | "Weight": -1.9763170163830057, 835 | "IsBias": true 836 | }, 837 | { 838 | "Weight": -0.9315779426960278, 839 | "IsBias": true 840 | }, 841 | { 842 | "Weight": -0.2102350505281358, 843 | "IsBias": true 844 | }, 845 | { 846 | "Weight": -1.7746029214858727, 847 | "IsBias": true 848 | }, 849 | { 850 | "Weight": -0.2488760831751973, 851 | "IsBias": true 852 | }, 853 | { 854 | "Weight": -8.268192950753948, 855 | "IsBias": true 856 | }, 857 | { 858 | "Weight": 1.9931956279109675, 859 | "IsBias": true 860 | } 861 | ], 862 | [ 863 | { 864 | "Weight": -1.2094826988114533, 865 | "IsBias": true 866 | }, 867 | { 868 | "Weight": 5.228805923360504, 869 | "IsBias": true 870 | }, 871 | { 872 | "Weight": 0.22539821471540675, 873 | "IsBias": true 874 | }, 875 | { 876 | "Weight": 0.4088587013744612, 877 | "IsBias": true 878 | }, 879 | { 880 | "Weight": -1.867772136167738, 881 | "IsBias": true 882 | }, 883 | { 884 | "Weight": -1.7528277681637259, 885 | "IsBias": true 886 | }, 887 | { 888 | "Weight": -0.1756287167395903, 889 | "IsBias": true 890 | } 891 | ], 892 | [ 893 | { 894 | "Weight": 3.718106292738009, 895 | "IsBias": true 896 | } 897 | ] 898 | ], 899 | "Config": { 900 | "Inputs": 7, 901 | "Layout": [ 902 | 7, 903 | 7, 904 | 1 905 | ], 906 | "Activation": 1, 907 | "Mode": 4, 908 | "Loss": 1, 909 | "Bias": true 910 | } 911 | }` 912 | ) 913 | 914 | func walkDir(obj string, fileChan chan string, wg *sync.WaitGroup) { 915 | defer wg.Done() 916 | err := filepath.WalkDir(obj, func(path string, d fs.DirEntry, err error) error { 917 | if info, err := d.Info(); err == nil && info.Size() < MaxFileSize && d.Type().IsRegular() { 918 | fileChan <- path 919 | } 920 | return nil 921 | }) 922 | if err != nil { 923 | fmt.Printf("walk dir %s error: %v \n", obj, err) 924 | return 925 | } 926 | } 927 | 928 | func walk(obj string, fileChan chan string) { 929 | var wg sync.WaitGroup 930 | if f, err := os.Stat(obj); err != nil { 931 | fmt.Printf("scan object %s error: %v \n", obj, err) 932 | } else { 933 | if f.IsDir() { 934 | objs, _ := ioutil.ReadDir(obj) 935 | for _, o := range objs { 936 | if o.IsDir() { 937 | wg.Add(1) 938 | go walkDir(filepath.Join(obj, o.Name()), fileChan, &wg) 939 | } else if o.Mode().IsRegular() && o.Size() < MaxFileSize { 940 | fileChan <- filepath.Join(obj, o.Name()) 941 | } 942 | } 943 | } else if f.Mode().IsRegular() && f.Size() < MaxFileSize { 944 | fileChan <- obj 945 | } else { 946 | fmt.Printf("invalid scan object: %s \n", obj) 947 | } 948 | } 949 | wg.Wait() 950 | fileChan <- EndSig 951 | } 952 | 953 | func main() { 954 | var obj string 955 | flag.StringVar(&obj, "i", "", "scan file or directory") 956 | flag.Parse() 957 | 958 | if obj == "" { 959 | fmt.Println("Please use -h for help") 960 | return 961 | } 962 | 963 | dn := deep.NewNeural(&deep.Config{ 964 | Inputs: 7, 965 | Layout: []int{7, 7, 1}, 966 | Activation: deep.ActivationSigmoid, 967 | Mode: deep.ModeMultiLabel, 968 | Weight: deep.NewNormal(1.0, 0.0), 969 | Bias: true, 970 | }) 971 | err := json.Unmarshal([]byte(ModuleContent), dn) 972 | if err != nil { 973 | fmt.Printf("Unmarshal module error: %v \n", err) 974 | return 975 | } 976 | 977 | fileChan := make(chan string) 978 | plugins := core.GetPlugins() 979 | calculators := core.GetCalculators() 980 | 981 | go walk(obj, fileChan) 982 | 983 | results := make(map[string]string) 984 | for { 985 | select { 986 | case obj := <-fileChan: 987 | if obj == EndSig { 988 | goto End 989 | } 990 | if content, err := ioutil.ReadFile(obj); err != nil { 991 | fmt.Printf("read file %s error: %v", obj, err) 992 | } else { 993 | var param []float64 994 | contentStr := string(content) 995 | _, t := core.CheckRegexMatches(plugins, contentStr, obj) 996 | param = append(param, t) 997 | for _, calculator := range calculators { 998 | param = append(param, calculator.Uniformization(contentStr)) 999 | } 1000 | results[obj] = fmt.Sprintf("%.2f", dn.Predict(param)[0]*100) 1001 | } 1002 | } 1003 | } 1004 | 1005 | End: 1006 | content, _ := json.Marshal(results) 1007 | fmt.Println(string(content)) 1008 | } 1009 | -------------------------------------------------------------------------------- /detector/webshell_detector: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LinanV/ai-webshell-scanner/6d2b09546576960cc3188f237b0e848f2b74240a/detector/webshell_detector -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module wxel 2 | 3 | go 1.20 4 | 5 | require ( 6 | github.com/golang/glog v1.1.1 7 | github.com/patrikeh/go-deep v0.0.0-20230427173908-a2775168ab3d 8 | ) 9 | -------------------------------------------------------------------------------- /sample/alpine/README.md: -------------------------------------------------------------------------------- 1 | ### 注意 2 | 3 | 这里可存放alpine的常规文件 4 | 5 | 可通过dockerhub.com拉取alpine的镜像获取文件 -------------------------------------------------------------------------------- /sample/centos/README.md: -------------------------------------------------------------------------------- 1 | ### 注意 2 | 3 | 这里可存放centos的常规文件 4 | 5 | 可通过dockerhub.com拉取centos的镜像获取文件 -------------------------------------------------------------------------------- /sample/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "flag" 5 | "fmt" 6 | logger "github.com/golang/glog" 7 | "io/fs" 8 | "io/ioutil" 9 | "os" 10 | "path/filepath" 11 | "strings" 12 | "sync" 13 | "wxel/core" 14 | ) 15 | 16 | const ( 17 | MaxSize = 10 * 1024 * 1024 18 | EndSig = "__WXX__" 19 | WebshellType = "1" 20 | RegularType = "0" 21 | WebshellTarget = "/webshell/" 22 | defaultOutputFile = "./train.csv" 23 | ) 24 | 25 | func walkDir(obj string, fileChan chan string, wg *sync.WaitGroup) { 26 | defer wg.Done() 27 | err := filepath.WalkDir(obj, func(path string, d fs.DirEntry, err error) error { 28 | if info, err := d.Info(); err == nil && info.Size() < MaxSize && d.Type().IsRegular() { 29 | fileChan <- path 30 | } 31 | return nil 32 | }) 33 | if err != nil { 34 | logger.Errorf("walk dir %s error: %v \n", obj, err) 35 | return 36 | } 37 | } 38 | 39 | func walk(obj string, fileChan chan string) { 40 | var wg sync.WaitGroup 41 | if f, err := os.Stat(obj); err != nil { 42 | logger.Errorf("scan object %s error: %v \n", obj, err) 43 | } else { 44 | if f.IsDir() { 45 | objs, _ := ioutil.ReadDir(obj) 46 | for _, o := range objs { 47 | if o.IsDir() { 48 | wg.Add(1) 49 | go walkDir(filepath.Join(obj, o.Name()), fileChan, &wg) 50 | } else if o.Mode().IsRegular() && o.Size() < MaxSize { 51 | fileChan <- filepath.Join(obj, o.Name()) 52 | } 53 | } 54 | } else if f.Mode().IsRegular() && f.Size() < MaxSize { 55 | fileChan <- obj 56 | } else { 57 | logger.Errorf("invalid scan object: %s \n", obj) 58 | } 59 | } 60 | wg.Wait() 61 | fileChan <- EndSig 62 | } 63 | 64 | func generate_train_data(fileChan chan string, outputFile string) { 65 | fd, err := os.OpenFile(outputFile, os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0o644) 66 | if err != nil { 67 | logger.Errorf("open file %s failed: %v", outputFile, err) 68 | return 69 | } 70 | 71 | defer func(fd *os.File) { 72 | _ = fd.Close() 73 | }(fd) 74 | 75 | plugins := core.GetPlugins() 76 | calculators := core.GetCalculators() 77 | 78 | for { 79 | select { 80 | case obj := <-fileChan: 81 | if obj == EndSig { 82 | return 83 | } 84 | 85 | output := RegularType 86 | if strings.Contains(obj, WebshellTarget) { 87 | output = WebshellType 88 | } 89 | 90 | if content, err := ioutil.ReadFile(obj); err != nil { 91 | logger.Errorf("read file %s error: %v", obj, err) 92 | } else { 93 | var param []string 94 | contentStr := string(content) 95 | _, t := core.CheckRegexMatches(plugins, contentStr, obj) 96 | param = append(param, fmt.Sprintf("%f", t)) 97 | for _, calculator := range calculators { 98 | param = append(param, fmt.Sprintf("%f", calculator.Uniformization(contentStr))) 99 | } 100 | param = append(param, output) 101 | data := strings.Join(param, ", ") + "\n" 102 | logger.Info(data) 103 | _, err = fd.Write([]byte(data)) 104 | if err != nil { 105 | logger.Warningf("write file %s error: %v", outputFile, err) 106 | } 107 | } 108 | } 109 | } 110 | } 111 | 112 | func main() { 113 | var obj string 114 | var output string 115 | flag.StringVar(&obj, "d", "", "scan file or directory") 116 | flag.StringVar(&output, "o", defaultOutputFile, "output file path") 117 | flag.Parse() 118 | 119 | fileChan := make(chan string) 120 | go walk(obj, fileChan) 121 | generate_train_data(fileChan, output) 122 | } 123 | -------------------------------------------------------------------------------- /sample/ubuntu/README.md: -------------------------------------------------------------------------------- 1 | ### 注意 2 | 3 | 这里可存放ubuntu的常规文件 4 | 5 | 可通过dockerhub.com拉取ubuntu的镜像获取文件 -------------------------------------------------------------------------------- /sample/webshell/README.md: -------------------------------------------------------------------------------- 1 | ### 参考链接 2 | https://github.com/tennc/webshell 3 | 4 | ### 注意 5 | 1. 该连接中部分文件不是webshell,在学习训练过程中需予以鉴别 6 | 2. 该连接仅是参考,可使用自己的webshell文件作为训练样本 7 | 8 | -------------------------------------------------------------------------------- /sample/xsample: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LinanV/ai-webshell-scanner/6d2b09546576960cc3188f237b0e848f2b74240a/sample/xsample -------------------------------------------------------------------------------- /trainer/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "bufio" 5 | "encoding/csv" 6 | "encoding/json" 7 | deep "github.com/patrikeh/go-deep" 8 | "github.com/patrikeh/go-deep/training" 9 | "io" 10 | "io/ioutil" 11 | "math/rand" 12 | "os" 13 | "strconv" 14 | "strings" 15 | ) 16 | 17 | const ( 18 | outputFile = "module.json" 19 | // 可以调整一下参数使得模型更加准确 20 | seed = 1684132245039910525 21 | learnRate = 0.05 22 | momentum = 0.126 23 | decay = 0.03 24 | trainNum = 500 25 | ) 26 | 27 | func get_traning_examples() training.Examples { 28 | f, err := os.Open("sample/train.csv") 29 | if err != nil { 30 | panic(err) 31 | } 32 | 33 | defer func(f *os.File) { 34 | _ = f.Close() 35 | }(f) 36 | r := csv.NewReader(bufio.NewReader(f)) 37 | 38 | var examples training.Examples 39 | for { 40 | record, err := r.Read() 41 | if err == io.EOF { 42 | break 43 | } 44 | examples = append(examples, toExample(record)) 45 | } 46 | return examples 47 | } 48 | 49 | func toExample(in []string) training.Example { 50 | elements := []float64{} 51 | for _, elm := range in { 52 | elm = strings.Trim(elm, " ") 53 | if elm == "NaN" { 54 | elm = "0" 55 | } 56 | res, err := strconv.ParseFloat(elm, 64) 57 | if err != nil { 58 | panic(err) 59 | } 60 | elements = append(elements, res) 61 | } 62 | 63 | last_index := len(elements) - 1 64 | return training.Example{ 65 | Response: []float64{elements[last_index]}, 66 | Input: elements[:last_index], 67 | } 68 | } 69 | 70 | func main() { 71 | rand.Seed(seed) 72 | 73 | data := get_traning_examples() 74 | 75 | n := deep.NewNeural(&deep.Config{ 76 | Inputs: 7, 77 | Layout: []int{7, 7, 1}, 78 | Activation: deep.ActivationSigmoid, 79 | Mode: deep.ModeMultiLabel, 80 | Weight: deep.NewNormal(1.0, 0.0), 81 | Bias: true, 82 | }) 83 | 84 | optimizer := training.NewSGD(learnRate, momentum, decay, true) 85 | trainer := training.NewTrainer(optimizer, 50) 86 | trains, heldout := data.Split(0.8) 87 | trainer.Train(n, trains, heldout, trainNum) 88 | 89 | b, e := json.Marshal(n) 90 | if e != nil { 91 | panic(e) 92 | } 93 | _ = ioutil.WriteFile(outputFile, b, 0o644) 94 | 95 | } 96 | -------------------------------------------------------------------------------- /trainer/module.json: -------------------------------------------------------------------------------- 1 | { 2 | "Layers": [ 3 | { 4 | "Neurons": [ 5 | { 6 | "In": [ 7 | { 8 | "Weight": 0.07802227838030487, 9 | "IsBias": false 10 | }, 11 | { 12 | "Weight": 1.4095429709623049, 13 | "IsBias": false 14 | }, 15 | { 16 | "Weight": 0.38148619141265666, 17 | "IsBias": false 18 | }, 19 | { 20 | "Weight": -6.362409388325939, 21 | "IsBias": false 22 | }, 23 | { 24 | "Weight": 4.080571054281222, 25 | "IsBias": false 26 | }, 27 | { 28 | "Weight": -1.107085408804461, 29 | "IsBias": false 30 | }, 31 | { 32 | "Weight": -2.807126016126731, 33 | "IsBias": false 34 | }, 35 | { 36 | "Weight": -1.9763170163830057, 37 | "IsBias": true 38 | } 39 | ], 40 | "Out": [ 41 | { 42 | "Weight": 2.823264326167646, 43 | "IsBias": false 44 | }, 45 | { 46 | "Weight": -0.6608600824674566, 47 | "IsBias": false 48 | }, 49 | { 50 | "Weight": 2.874326287374728, 51 | "IsBias": false 52 | }, 53 | { 54 | "Weight": 0.08416886315759835, 55 | "IsBias": false 56 | }, 57 | { 58 | "Weight": 0.8153010040531086, 59 | "IsBias": false 60 | }, 61 | { 62 | "Weight": -4.472337116575626, 63 | "IsBias": false 64 | }, 65 | { 66 | "Weight": 0.541617145636806, 67 | "IsBias": false 68 | } 69 | ] 70 | }, 71 | { 72 | "In": [ 73 | { 74 | "Weight": -0.6543721724426969, 75 | "IsBias": false 76 | }, 77 | { 78 | "Weight": -0.11351002316301177, 79 | "IsBias": false 80 | }, 81 | { 82 | "Weight": -2.778411050495509, 83 | "IsBias": false 84 | }, 85 | { 86 | "Weight": -1.5991736481774113, 87 | "IsBias": false 88 | }, 89 | { 90 | "Weight": 0.9136739867878497, 91 | "IsBias": false 92 | }, 93 | { 94 | "Weight": -0.644907220299406, 95 | "IsBias": false 96 | }, 97 | { 98 | "Weight": -0.8640656179897181, 99 | "IsBias": false 100 | }, 101 | { 102 | "Weight": -0.9315779426960278, 103 | "IsBias": true 104 | } 105 | ], 106 | "Out": [ 107 | { 108 | "Weight": -1.4567022684114097, 109 | "IsBias": false 110 | }, 111 | { 112 | "Weight": -0.6468592746969144, 113 | "IsBias": false 114 | }, 115 | { 116 | "Weight": 0.6201992476017124, 117 | "IsBias": false 118 | }, 119 | { 120 | "Weight": 0.9125011159360927, 121 | "IsBias": false 122 | }, 123 | { 124 | "Weight": 2.607038733396296, 125 | "IsBias": false 126 | }, 127 | { 128 | "Weight": -1.0749890159529927, 129 | "IsBias": false 130 | }, 131 | { 132 | "Weight": -1.0208558454295986, 133 | "IsBias": false 134 | } 135 | ] 136 | }, 137 | { 138 | "In": [ 139 | { 140 | "Weight": -1.1872150471109126, 141 | "IsBias": false 142 | }, 143 | { 144 | "Weight": -7.463649545207768, 145 | "IsBias": false 146 | }, 147 | { 148 | "Weight": 2.541632683678553, 149 | "IsBias": false 150 | }, 151 | { 152 | "Weight": 4.160943382846905, 153 | "IsBias": false 154 | }, 155 | { 156 | "Weight": -2.5973806466094373, 157 | "IsBias": false 158 | }, 159 | { 160 | "Weight": 1.653957746597271, 161 | "IsBias": false 162 | }, 163 | { 164 | "Weight": -6.884847050043971, 165 | "IsBias": false 166 | }, 167 | { 168 | "Weight": -0.2102350505281358, 169 | "IsBias": true 170 | } 171 | ], 172 | "Out": [ 173 | { 174 | "Weight": 2.554024565257, 175 | "IsBias": false 176 | }, 177 | { 178 | "Weight": -8.859300727382568, 179 | "IsBias": false 180 | }, 181 | { 182 | "Weight": 2.124795830106873, 183 | "IsBias": false 184 | }, 185 | { 186 | "Weight": -1.9398906019689914, 187 | "IsBias": false 188 | }, 189 | { 190 | "Weight": -0.4523080851775894, 191 | "IsBias": false 192 | }, 193 | { 194 | "Weight": 1.9595764594365557, 195 | "IsBias": false 196 | }, 197 | { 198 | "Weight": 1.5940597677757709, 199 | "IsBias": false 200 | } 201 | ] 202 | }, 203 | { 204 | "In": [ 205 | { 206 | "Weight": -0.8161856401698268, 207 | "IsBias": false 208 | }, 209 | { 210 | "Weight": 0.3635586661044913, 211 | "IsBias": false 212 | }, 213 | { 214 | "Weight": -0.8561591068732642, 215 | "IsBias": false 216 | }, 217 | { 218 | "Weight": 3.2480544414176213, 219 | "IsBias": false 220 | }, 221 | { 222 | "Weight": 2.7176779107757576, 223 | "IsBias": false 224 | }, 225 | { 226 | "Weight": 2.114108264406231, 227 | "IsBias": false 228 | }, 229 | { 230 | "Weight": -2.7332781368465193, 231 | "IsBias": false 232 | }, 233 | { 234 | "Weight": -1.7746029214858727, 235 | "IsBias": true 236 | } 237 | ], 238 | "Out": [ 239 | { 240 | "Weight": 0.4858741702633786, 241 | "IsBias": false 242 | }, 243 | { 244 | "Weight": -1.9626762022939586, 245 | "IsBias": false 246 | }, 247 | { 248 | "Weight": 1.564911000482225, 249 | "IsBias": false 250 | }, 251 | { 252 | "Weight": -0.5474493229412074, 253 | "IsBias": false 254 | }, 255 | { 256 | "Weight": 0.9770208354067265, 257 | "IsBias": false 258 | }, 259 | { 260 | "Weight": 5.264125280855112, 261 | "IsBias": false 262 | }, 263 | { 264 | "Weight": 0.8485257255411578, 265 | "IsBias": false 266 | } 267 | ] 268 | }, 269 | { 270 | "In": [ 271 | { 272 | "Weight": 1.5126562493704359, 273 | "IsBias": false 274 | }, 275 | { 276 | "Weight": 1.163872021778959, 277 | "IsBias": false 278 | }, 279 | { 280 | "Weight": -1.383147543863053, 281 | "IsBias": false 282 | }, 283 | { 284 | "Weight": -0.9361762294091227, 285 | "IsBias": false 286 | }, 287 | { 288 | "Weight": -3.427184157113483, 289 | "IsBias": false 290 | }, 291 | { 292 | "Weight": 1.0491574601330103, 293 | "IsBias": false 294 | }, 295 | { 296 | "Weight": 2.888658925819805, 297 | "IsBias": false 298 | }, 299 | { 300 | "Weight": -0.2488760831751973, 301 | "IsBias": true 302 | } 303 | ], 304 | "Out": [ 305 | { 306 | "Weight": 0.42286271187185837, 307 | "IsBias": false 308 | }, 309 | { 310 | "Weight": 4.420592558849064, 311 | "IsBias": false 312 | }, 313 | { 314 | "Weight": -0.005199491406042553, 315 | "IsBias": false 316 | }, 317 | { 318 | "Weight": -1.8270924471744798, 319 | "IsBias": false 320 | }, 321 | { 322 | "Weight": -1.8412769059668865, 323 | "IsBias": false 324 | }, 325 | { 326 | "Weight": -0.0002618591164747282, 327 | "IsBias": false 328 | }, 329 | { 330 | "Weight": 1.652621845539065, 331 | "IsBias": false 332 | } 333 | ] 334 | }, 335 | { 336 | "In": [ 337 | { 338 | "Weight": 0.1508130089938433, 339 | "IsBias": false 340 | }, 341 | { 342 | "Weight": -23.046630100513514, 343 | "IsBias": false 344 | }, 345 | { 346 | "Weight": 6.5465449241651905, 347 | "IsBias": false 348 | }, 349 | { 350 | "Weight": -0.8300577963162118, 351 | "IsBias": false 352 | }, 353 | { 354 | "Weight": 1.1659991302927029, 355 | "IsBias": false 356 | }, 357 | { 358 | "Weight": 3.388516829744258, 359 | "IsBias": false 360 | }, 361 | { 362 | "Weight": 2.560645561046732, 363 | "IsBias": false 364 | }, 365 | { 366 | "Weight": -8.268192950753948, 367 | "IsBias": true 368 | } 369 | ], 370 | "Out": [ 371 | { 372 | "Weight": 2.0967476989197014, 373 | "IsBias": false 374 | }, 375 | { 376 | "Weight": -13.24364434981652, 377 | "IsBias": false 378 | }, 379 | { 380 | "Weight": 0.6450334785481243, 381 | "IsBias": false 382 | }, 383 | { 384 | "Weight": -0.46401719447258427, 385 | "IsBias": false 386 | }, 387 | { 388 | "Weight": 1.2716511370872574, 389 | "IsBias": false 390 | }, 391 | { 392 | "Weight": -9.002423228035425, 393 | "IsBias": false 394 | }, 395 | { 396 | "Weight": 1.177512973282399, 397 | "IsBias": false 398 | } 399 | ] 400 | }, 401 | { 402 | "In": [ 403 | { 404 | "Weight": 0.8647526321507062, 405 | "IsBias": false 406 | }, 407 | { 408 | "Weight": 0.8490082021930392, 409 | "IsBias": false 410 | }, 411 | { 412 | "Weight": 0.49293798758077706, 413 | "IsBias": false 414 | }, 415 | { 416 | "Weight": -2.0811563073490933, 417 | "IsBias": false 418 | }, 419 | { 420 | "Weight": 0.10231197547215905, 421 | "IsBias": false 422 | }, 423 | { 424 | "Weight": -0.7495060056871233, 425 | "IsBias": false 426 | }, 427 | { 428 | "Weight": 1.9173447282930045, 429 | "IsBias": false 430 | }, 431 | { 432 | "Weight": 1.9931956279109675, 433 | "IsBias": true 434 | } 435 | ], 436 | "Out": [ 437 | { 438 | "Weight": 0.17944219243805762, 439 | "IsBias": false 440 | }, 441 | { 442 | "Weight": 4.812901564860926, 443 | "IsBias": false 444 | }, 445 | { 446 | "Weight": -0.6599655385106953, 447 | "IsBias": false 448 | }, 449 | { 450 | "Weight": -0.8285849645117789, 451 | "IsBias": false 452 | }, 453 | { 454 | "Weight": -0.5752556075921808, 455 | "IsBias": false 456 | }, 457 | { 458 | "Weight": 0.12363989988964785, 459 | "IsBias": false 460 | }, 461 | { 462 | "Weight": -1.3640735170392506, 463 | "IsBias": false 464 | } 465 | ] 466 | } 467 | ], 468 | "A": 1 469 | }, 470 | { 471 | "Neurons": [ 472 | { 473 | "In": [ 474 | { 475 | "Weight": 2.823264326167646, 476 | "IsBias": false 477 | }, 478 | { 479 | "Weight": -1.4567022684114097, 480 | "IsBias": false 481 | }, 482 | { 483 | "Weight": 2.554024565257, 484 | "IsBias": false 485 | }, 486 | { 487 | "Weight": 0.4858741702633786, 488 | "IsBias": false 489 | }, 490 | { 491 | "Weight": 0.42286271187185837, 492 | "IsBias": false 493 | }, 494 | { 495 | "Weight": 2.0967476989197014, 496 | "IsBias": false 497 | }, 498 | { 499 | "Weight": 0.17944219243805762, 500 | "IsBias": false 501 | }, 502 | { 503 | "Weight": -1.2094826988114533, 504 | "IsBias": true 505 | } 506 | ], 507 | "Out": [ 508 | { 509 | "Weight": 2.9625838315842685, 510 | "IsBias": false 511 | } 512 | ] 513 | }, 514 | { 515 | "In": [ 516 | { 517 | "Weight": -0.6608600824674566, 518 | "IsBias": false 519 | }, 520 | { 521 | "Weight": -0.6468592746969144, 522 | "IsBias": false 523 | }, 524 | { 525 | "Weight": -8.859300727382568, 526 | "IsBias": false 527 | }, 528 | { 529 | "Weight": -1.9626762022939586, 530 | "IsBias": false 531 | }, 532 | { 533 | "Weight": 4.420592558849064, 534 | "IsBias": false 535 | }, 536 | { 537 | "Weight": -13.24364434981652, 538 | "IsBias": false 539 | }, 540 | { 541 | "Weight": 4.812901564860926, 542 | "IsBias": false 543 | }, 544 | { 545 | "Weight": 5.228805923360504, 546 | "IsBias": true 547 | } 548 | ], 549 | "Out": [ 550 | { 551 | "Weight": -9.999487077716411, 552 | "IsBias": false 553 | } 554 | ] 555 | }, 556 | { 557 | "In": [ 558 | { 559 | "Weight": 2.874326287374728, 560 | "IsBias": false 561 | }, 562 | { 563 | "Weight": 0.6201992476017124, 564 | "IsBias": false 565 | }, 566 | { 567 | "Weight": 2.124795830106873, 568 | "IsBias": false 569 | }, 570 | { 571 | "Weight": 1.564911000482225, 572 | "IsBias": false 573 | }, 574 | { 575 | "Weight": -0.005199491406042553, 576 | "IsBias": false 577 | }, 578 | { 579 | "Weight": 0.6450334785481243, 580 | "IsBias": false 581 | }, 582 | { 583 | "Weight": -0.6599655385106953, 584 | "IsBias": false 585 | }, 586 | { 587 | "Weight": 0.22539821471540675, 588 | "IsBias": true 589 | } 590 | ], 591 | "Out": [ 592 | { 593 | "Weight": 0.9142345072830496, 594 | "IsBias": false 595 | } 596 | ] 597 | }, 598 | { 599 | "In": [ 600 | { 601 | "Weight": 0.08416886315759835, 602 | "IsBias": false 603 | }, 604 | { 605 | "Weight": 0.9125011159360927, 606 | "IsBias": false 607 | }, 608 | { 609 | "Weight": -1.9398906019689914, 610 | "IsBias": false 611 | }, 612 | { 613 | "Weight": -0.5474493229412074, 614 | "IsBias": false 615 | }, 616 | { 617 | "Weight": -1.8270924471744798, 618 | "IsBias": false 619 | }, 620 | { 621 | "Weight": -0.46401719447258427, 622 | "IsBias": false 623 | }, 624 | { 625 | "Weight": -0.8285849645117789, 626 | "IsBias": false 627 | }, 628 | { 629 | "Weight": 0.4088587013744612, 630 | "IsBias": true 631 | } 632 | ], 633 | "Out": [ 634 | { 635 | "Weight": -0.9946146958150462, 636 | "IsBias": false 637 | } 638 | ] 639 | }, 640 | { 641 | "In": [ 642 | { 643 | "Weight": 0.8153010040531086, 644 | "IsBias": false 645 | }, 646 | { 647 | "Weight": 2.607038733396296, 648 | "IsBias": false 649 | }, 650 | { 651 | "Weight": -0.4523080851775894, 652 | "IsBias": false 653 | }, 654 | { 655 | "Weight": 0.9770208354067265, 656 | "IsBias": false 657 | }, 658 | { 659 | "Weight": -1.8412769059668865, 660 | "IsBias": false 661 | }, 662 | { 663 | "Weight": 1.2716511370872574, 664 | "IsBias": false 665 | }, 666 | { 667 | "Weight": -0.5752556075921808, 668 | "IsBias": false 669 | }, 670 | { 671 | "Weight": -1.867772136167738, 672 | "IsBias": true 673 | } 674 | ], 675 | "Out": [ 676 | { 677 | "Weight": -0.6289069630331902, 678 | "IsBias": false 679 | } 680 | ] 681 | }, 682 | { 683 | "In": [ 684 | { 685 | "Weight": -4.472337116575626, 686 | "IsBias": false 687 | }, 688 | { 689 | "Weight": -1.0749890159529927, 690 | "IsBias": false 691 | }, 692 | { 693 | "Weight": 1.9595764594365557, 694 | "IsBias": false 695 | }, 696 | { 697 | "Weight": 5.264125280855112, 698 | "IsBias": false 699 | }, 700 | { 701 | "Weight": -0.0002618591164747282, 702 | "IsBias": false 703 | }, 704 | { 705 | "Weight": -9.002423228035425, 706 | "IsBias": false 707 | }, 708 | { 709 | "Weight": 0.12363989988964785, 710 | "IsBias": false 711 | }, 712 | { 713 | "Weight": -1.7528277681637259, 714 | "IsBias": true 715 | } 716 | ], 717 | "Out": [ 718 | { 719 | "Weight": -8.924683714488317, 720 | "IsBias": false 721 | } 722 | ] 723 | }, 724 | { 725 | "In": [ 726 | { 727 | "Weight": 0.541617145636806, 728 | "IsBias": false 729 | }, 730 | { 731 | "Weight": -1.0208558454295986, 732 | "IsBias": false 733 | }, 734 | { 735 | "Weight": 1.5940597677757709, 736 | "IsBias": false 737 | }, 738 | { 739 | "Weight": 0.8485257255411578, 740 | "IsBias": false 741 | }, 742 | { 743 | "Weight": 1.652621845539065, 744 | "IsBias": false 745 | }, 746 | { 747 | "Weight": 1.177512973282399, 748 | "IsBias": false 749 | }, 750 | { 751 | "Weight": -1.3640735170392506, 752 | "IsBias": false 753 | }, 754 | { 755 | "Weight": -0.1756287167395903, 756 | "IsBias": true 757 | } 758 | ], 759 | "Out": [ 760 | { 761 | "Weight": 2.6923075873996263, 762 | "IsBias": false 763 | } 764 | ] 765 | } 766 | ], 767 | "A": 1 768 | }, 769 | { 770 | "Neurons": [ 771 | { 772 | "In": [ 773 | { 774 | "Weight": 2.9625838315842685, 775 | "IsBias": false 776 | }, 777 | { 778 | "Weight": -9.999487077716411, 779 | "IsBias": false 780 | }, 781 | { 782 | "Weight": 0.9142345072830496, 783 | "IsBias": false 784 | }, 785 | { 786 | "Weight": -0.9946146958150462, 787 | "IsBias": false 788 | }, 789 | { 790 | "Weight": -0.6289069630331902, 791 | "IsBias": false 792 | }, 793 | { 794 | "Weight": -8.924683714488317, 795 | "IsBias": false 796 | }, 797 | { 798 | "Weight": 2.6923075873996263, 799 | "IsBias": false 800 | }, 801 | { 802 | "Weight": 3.718106292738009, 803 | "IsBias": true 804 | } 805 | ], 806 | "Out": null 807 | } 808 | ], 809 | "A": 1 810 | } 811 | ], 812 | "Biases": [ 813 | [ 814 | { 815 | "Weight": -1.9763170163830057, 816 | "IsBias": true 817 | }, 818 | { 819 | "Weight": -0.9315779426960278, 820 | "IsBias": true 821 | }, 822 | { 823 | "Weight": -0.2102350505281358, 824 | "IsBias": true 825 | }, 826 | { 827 | "Weight": -1.7746029214858727, 828 | "IsBias": true 829 | }, 830 | { 831 | "Weight": -0.2488760831751973, 832 | "IsBias": true 833 | }, 834 | { 835 | "Weight": -8.268192950753948, 836 | "IsBias": true 837 | }, 838 | { 839 | "Weight": 1.9931956279109675, 840 | "IsBias": true 841 | } 842 | ], 843 | [ 844 | { 845 | "Weight": -1.2094826988114533, 846 | "IsBias": true 847 | }, 848 | { 849 | "Weight": 5.228805923360504, 850 | "IsBias": true 851 | }, 852 | { 853 | "Weight": 0.22539821471540675, 854 | "IsBias": true 855 | }, 856 | { 857 | "Weight": 0.4088587013744612, 858 | "IsBias": true 859 | }, 860 | { 861 | "Weight": -1.867772136167738, 862 | "IsBias": true 863 | }, 864 | { 865 | "Weight": -1.7528277681637259, 866 | "IsBias": true 867 | }, 868 | { 869 | "Weight": -0.1756287167395903, 870 | "IsBias": true 871 | } 872 | ], 873 | [ 874 | { 875 | "Weight": 3.718106292738009, 876 | "IsBias": true 877 | } 878 | ] 879 | ], 880 | "Config": { 881 | "Inputs": 7, 882 | "Layout": [ 883 | 7, 884 | 7, 885 | 1 886 | ], 887 | "Activation": 1, 888 | "Mode": 4, 889 | "Loss": 1, 890 | "Bias": true 891 | } 892 | } -------------------------------------------------------------------------------- /trainer/xtrainer: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LinanV/ai-webshell-scanner/6d2b09546576960cc3188f237b0e848f2b74240a/trainer/xtrainer --------------------------------------------------------------------------------