11package main
22
33import (
4+ "archive/zip"
45 "crypto/md5"
56 "crypto/sha1"
67 "crypto/sha256"
@@ -10,6 +11,7 @@ import (
1011 "strings"
1112
1213 "github.com/dlclark/regexp2"
14+ "github.com/h2non/filetype"
1315)
1416
1517// PathsFinder try to match regular expressions in file paths slice
@@ -29,45 +31,66 @@ func PathsFinder(files *[]string, patterns []*regexp2.Regexp) *[]string {
2931}
3032
3133// FindInFiles check for pattern or checksum match in files slice
32- func FindInFiles (files * []string , patterns []string , checksum []string ) * []string {
34+ func FindInFiles (files * []string , patterns []string , hashList []string ) * []string {
3335 var matchingFiles []string
3436 InitProgressbar (int64 (len (* files )))
35- for _ , f := range * files {
37+ for _ , path := range * files {
3638 ProgressBarStep ()
37- b , err := ioutil .ReadFile (f )
39+ b , err := ioutil .ReadFile (path )
3840 if err != nil {
39- LogMessage (LOG_ERROR , "[ERROR]" , "Unable to read file" , f )
41+ LogMessage (LOG_ERROR , "[ERROR]" , "Unable to read file" , path )
4042 continue
4143 }
4244
4345 // cancel analysis if file size is greater than 2Gb
4446 if len (b ) > 1024 * 1024 * 2048 {
45- LogMessage (LOG_ERROR , "[ERROR]" , "File size is greater than 2Gb, skipping" , f )
47+ LogMessage (LOG_ERROR , "[ERROR]" , "File size is greater than 2Gb, skipping" , path )
4648 continue
4749 }
4850
49- // if checksum is not empty, calculate md5/sha1/sha256 for every file
50- if len (checksum ) > 0 {
51- var hashs []string
52- hashs = append (hashs , fmt .Sprintf ("%x" , md5 .Sum (b )))
53- hashs = append (hashs , fmt .Sprintf ("%x" , sha1 .Sum (b )))
54- hashs = append (hashs , fmt .Sprintf ("%x" , sha256 .Sum256 (b )))
55-
56- for _ , c := range hashs {
57- if Contains (checksum , c ) && ! Contains (matchingFiles , f ) {
58- matchingFiles = append (matchingFiles , f )
59- LogMessage (LOG_INFO , "[ALERT]" , "File match on" , f )
60- }
51+ // get file type
52+ filetype , err := filetype .Match (b )
53+ if err != nil {
54+ LogMessage (LOG_ERROR , "[ERROR]" , "Unable to get file type" , path )
55+ }
56+
57+ for _ , m := range CheckFileChecksumAndContent (path , b , hashList , patterns ) {
58+ if ! Contains (matchingFiles , m ) {
59+ LogMessage (LOG_INFO , "[ALERT]" , "File match on" , path )
60+ matchingFiles = append (matchingFiles , m )
6161 }
6262 }
6363
64- for _ , expression := range patterns {
65- if strings .Contains (string (b ), expression ) {
66- if ! Contains (matchingFiles , f ) {
67- matchingFiles = append (matchingFiles , f )
68- LogMessage (LOG_INFO , "[ALERT]" , "File match on" , f )
64+ // if file type is an archive, extract and calculate checksum for every file inside
65+ if Contains ([]string {"application/x-tar" , "application/x-7z-compressed" , "application/zip" , "application/vnd.rar" }, filetype .MIME .Value ) {
66+ zr , err := zip .OpenReader (path )
67+ if err != nil {
68+ fmt .Printf ("cant't open archive file: %s: %v\n " , path , err )
69+ continue
70+ }
71+
72+ for _ , subFile := range zr .File {
73+ fr , err := subFile .Open ()
74+ if err != nil {
75+ fmt .Printf ("can't open archive file member for reading: %s (%s): %v\n " , path , subFile .Name , err )
76+ continue
77+ }
78+ defer fr .Close ()
79+
80+ body , err := ioutil .ReadAll (fr )
81+ if err != nil {
82+ LogMessage (LOG_ERROR , "[ERROR]" , "Unable to read file archive member: %s (%s): %v\n " , path , subFile .Name , err )
83+ continue
84+ }
85+
86+ for _ , m := range CheckFileChecksumAndContent (path , body , hashList , patterns ) {
87+ if ! Contains (matchingFiles , m ) {
88+ LogMessage (LOG_INFO , "[ALERT]" , "File match on" , path )
89+ matchingFiles = append (matchingFiles , m )
90+ }
6991 }
7092 }
93+
7194 }
7295
7396 // cleaning memory if file size is greater than 512Mb
@@ -78,3 +101,44 @@ func FindInFiles(files *[]string, patterns []string, checksum []string) *[]strin
78101
79102 return & matchingFiles
80103}
104+
105+ // CheckFileChecksumAndContent check for pattern or checksum match in files slice
106+ func CheckFileChecksumAndContent (path string , content []byte , hashList []string , patterns []string ) (matchingFiles []string ) {
107+ // compare file checksum with hashList
108+ if len (hashList ) > 0 {
109+ matchingFiles = append (matchingFiles , checkForChecksum (path , content , hashList )... )
110+ }
111+
112+ // compare file content with patterns
113+ if len (patterns ) > 0 {
114+ matchingFiles = append (matchingFiles , checkForStringPattern (path , content , patterns )... )
115+ }
116+
117+ return matchingFiles
118+ }
119+
120+ // checkForChecksum calculate content checksum and check if it is in hashlist
121+ func checkForChecksum (path string , content []byte , hashList []string ) (matchingFiles []string ) {
122+ var hashs []string
123+ hashs = append (hashs , fmt .Sprintf ("%x" , md5 .Sum (content )))
124+ hashs = append (hashs , fmt .Sprintf ("%x" , sha1 .Sum (content )))
125+ hashs = append (hashs , fmt .Sprintf ("%x" , sha256 .Sum256 (content )))
126+
127+ for _ , c := range hashs {
128+ if Contains (hashList , c ) && ! Contains (matchingFiles , path ) {
129+ matchingFiles = append (matchingFiles , path )
130+ }
131+ }
132+
133+ return matchingFiles
134+ }
135+
136+ // checkForStringPattern check if file content matches any specified pattern
137+ func checkForStringPattern (path string , content []byte , patterns []string ) (matchingFiles []string ) {
138+ for _ , expression := range patterns {
139+ if strings .Contains (string (content ), expression ) {
140+ matchingFiles = append (matchingFiles , path )
141+ }
142+ }
143+ return matchingFiles
144+ }
0 commit comments