| skipped 9 lines |
10 | 10 | | "net/http" |
11 | 11 | | "os" |
12 | 12 | | "strings" |
13 | | - | "sync" |
14 | 13 | | "reflect" |
| 14 | + | "sync" |
15 | 15 | | |
16 | 16 | | "github.com/logrusorgru/aurora" |
17 | 17 | | "github.com/projectdiscovery/iputil" |
| skipped 9 lines |
27 | 27 | | Vulns []string |
28 | 28 | | } |
29 | 29 | | |
| 30 | + | var ( |
| 31 | + | urls bool |
| 32 | + | noCPEs bool |
| 33 | + | noTags bool |
| 34 | + | noVulns bool |
| 35 | + | noColor bool |
| 36 | + | verbose bool |
| 37 | + | noHostnames bool |
| 38 | + | jsonFile string |
| 39 | + | compareFile string |
| 40 | + | concurrency int |
| 41 | + | ) |
| 42 | + | |
30 | 43 | | func main() { |
31 | 44 | | |
32 | | - | var noCPEs bool |
33 | 45 | | flag.BoolVar(&noCPEs, "nc", false, "Hide CPEs") |
34 | | - | |
35 | | - | var noHostnames bool |
36 | 46 | | flag.BoolVar(&noHostnames, "nh", false, "Hide hostnames") |
37 | | - | |
38 | | - | var noTags bool |
39 | 47 | | flag.BoolVar(&noTags, "nt", false, "Hide tags") |
40 | | - | |
41 | | - | var noVulns bool |
42 | 48 | | flag.BoolVar(&noVulns, "nv", false, "Hide vulnerabilities") |
43 | | - | |
44 | | - | var noColor bool |
45 | 49 | | flag.BoolVar(&noColor, "nocolor", false, "Disable color in output") |
46 | | - | |
47 | | - | var jsonFile string |
48 | 50 | | flag.StringVar(&jsonFile, "json", "", "Save output to JSON format") |
49 | | - | |
50 | | - | var verbose bool |
51 | 51 | | flag.BoolVar(&verbose, "v", false, "Verbose") |
52 | | - | |
53 | | - | var compareFile string |
54 | 52 | | flag.StringVar(&compareFile, "compare", "", "Compare new results with a JSON file") |
55 | | - | |
56 | | - | var url bool |
57 | | - | flag.BoolVar(&url, "url", false, "Show only IP and Port") |
58 | | - | |
| 53 | + | flag.BoolVar(&urls, "url", false, "Show only IP and Port") |
| 54 | + | flag.IntVar(&concurrency, "c", 5, "Concurrency") |
59 | 55 | | flag.Parse() |
60 | 56 | | |
61 | 57 | | |
| skipped 11 lines |
73 | 69 | | } |
74 | 70 | | } |
75 | 71 | | |
76 | | - | targets = loadTargets(inputs, verbose) |
| 72 | + | targets = loadTargets(inputs) |
| 73 | + | |
| 74 | + | allData := make([]Response, len(targets)) |
| 75 | + | var validData []Response |
77 | 76 | | |
78 | | - | channel := make(chan Response, 10) |
79 | 77 | | var wg sync.WaitGroup |
| 78 | + | var ch = make(chan int, len(targets)) |
| 79 | + | |
| 80 | + | wg.Add(concurrency) |
| 81 | + | |
| 82 | + | for i := 0; i < concurrency; i++ { |
| 83 | + | go func() { |
| 84 | + | for { |
| 85 | + | a, ok := <-ch |
| 86 | + | if !ok { |
| 87 | + | wg.Done() |
| 88 | + | return |
| 89 | + | } |
| 90 | + | jsonData := getData(targets[a]) |
| 91 | + | allData[a] = jsonData |
| 92 | + | } |
| 93 | + | }() |
| 94 | + | } |
80 | 95 | | |
81 | 96 | | for i := 0; i < len(targets); i++ { |
82 | | - | wg.Add(1) |
| 97 | + | ch <- i |
| 98 | + | } |
83 | 99 | | |
84 | | - | i := i |
| 100 | + | close(ch) |
| 101 | + | wg.Wait() |
85 | 102 | | |
86 | | - | go func() { |
87 | | - | jsonData := getData(&wg, targets[i], verbose) |
88 | | - | channel <- jsonData |
89 | | - | }() |
| 103 | + | for i := 0; i < len(allData); i++ { |
| 104 | + | if allData[i].IP != "" { |
| 105 | + | validData = append(validData, allData[i]) |
| 106 | + | } |
90 | 107 | | } |
91 | 108 | | |
92 | 109 | | if jsonFile == "" && compareFile == "" { |
93 | | - | for i := 0; i < len(targets); i++ { |
94 | | - | printResult(<-channel, noCPEs, noHostnames, noTags, noVulns, noColor, url) |
| 110 | + | for i := 0; i < len(validData); i++ { |
| 111 | + | printResult(validData[i]) |
95 | 112 | | } |
96 | 113 | | } |
97 | 114 | | |
98 | | - | go func() { |
99 | | - | wg.Wait() |
100 | | - | close(channel) |
101 | | - | }() |
102 | | - | |
103 | 115 | | if jsonFile != "" { |
104 | | - | saveJson(channel, jsonFile) |
| 116 | + | saveJson(validData, jsonFile) |
105 | 117 | | return |
106 | 118 | | } |
107 | 119 | | |
108 | 120 | | if compareFile != "" { |
109 | 121 | | newData := make(map[string]Response) |
110 | | - | for ret := range channel { |
111 | | - | if ret.IP != "" { |
112 | | - | newData[ret.IP] = ret |
113 | | - | } |
| 122 | + | for _, ret := range validData { |
| 123 | + | newData[ret.IP] = ret |
114 | 124 | | } |
115 | | - | monitorData(newData, compareFile) |
| 125 | + | monitorData(newData) |
| 126 | + | saveJson(validData, compareFile) |
116 | 127 | | |
117 | | - | var jsonDatas []Response |
118 | | - | for _, jsonData := range newData { |
119 | | - | if jsonData.IP != "" { |
120 | | - | jsonDatas = append(jsonDatas, jsonData) |
121 | | - | } |
122 | | - | } |
123 | | - | if len(jsonDatas) != 0 { |
124 | | - | stringData, _ := json.Marshal(jsonDatas) |
125 | | - | _ = ioutil.WriteFile(compareFile, stringData, 0644) |
126 | | - | } |
127 | 128 | | return |
128 | 129 | | } |
129 | 130 | | } |
130 | 131 | | |
131 | 132 | | |
132 | | - | func monitorData(newData map[string]Response, jsonFile string) { |
| 133 | + | func monitorData(newData map[string]Response) { |
133 | 134 | | |
134 | 135 | | var jsonDatas []Response |
135 | 136 | | oldData := make(map[string]Response) |
136 | 137 | | |
137 | | - | theFile, err := os.Open(jsonFile) |
| 138 | + | theFile, err := os.Open(compareFile) |
138 | 139 | | if err != nil { |
139 | 140 | | fmt.Println(err) |
140 | 141 | | } |
| skipped 14 lines |
155 | 156 | | newPorts := nData.Ports |
156 | 157 | | ports := strings.Trim(strings.Join(strings.Fields(fmt.Sprint(newPorts)), ", "), "[]") |
157 | 158 | | fmt.Println(nData.IP) |
158 | | - | fmt.Println(ports) |
| 159 | + | fmt.Println(ports + "\n") |
159 | 160 | | } |
160 | 161 | | } |
161 | | - | |
162 | 162 | | return |
163 | 163 | | } |
164 | 164 | | |
| skipped 31 lines |
196 | 196 | | } |
197 | 197 | | |
198 | 198 | | |
199 | | - | func loadTargets(inputs []string, verbose bool) []string { |
| 199 | + | func loadTargets(inputs []string) []string { |
200 | 200 | | |
201 | 201 | | var targets []string |
202 | 202 | | |
| skipped 18 lines |
221 | 221 | | } |
222 | 222 | | |
223 | 223 | | |
224 | | - | func getData(wg *sync.WaitGroup, ip string, verbose bool) Response { |
225 | | - | |
226 | | - | defer wg.Done() |
| 224 | + | func getData(ip string) Response { |
227 | 225 | | |
228 | 226 | | res, err := http.Get( |
229 | 227 | | fmt.Sprintf("https://internetdb.shodan.io/%s", ip), |
| skipped 33 lines |
263 | 261 | | } |
264 | 262 | | |
265 | 263 | | |
266 | | - | func saveJson(chData chan Response, jsonFile string) { |
267 | | - | |
268 | | - | var jsonDatas []Response |
269 | | - | for jsonData := range chData { |
270 | | - | if jsonData.IP != "" { |
271 | | - | jsonDatas = append(jsonDatas, jsonData) |
272 | | - | } |
273 | | - | } |
| 264 | + | func saveJson(jsonDatas []Response, outputFile string) { |
274 | 265 | | |
275 | 266 | | if len(jsonDatas) != 0 { |
276 | 267 | | stringData, _ := json.Marshal(jsonDatas) |
277 | | - | _ = ioutil.WriteFile(jsonFile, stringData, 0644) |
| 268 | + | _ = ioutil.WriteFile(outputFile, stringData, 0644) |
278 | 269 | | } |
279 | 270 | | } |
280 | 271 | | |
281 | 272 | | |
282 | | - | func printResult(jsonData Response, noCPEs bool, noHostnames bool, noTags bool, noVulns bool, noColor bool, url bool) { |
| 273 | + | func printResult(jsonData Response) { |
283 | 274 | | |
284 | 275 | | builder := &strings.Builder{} |
285 | 276 | | |
| skipped 3 lines |
289 | 280 | | |
290 | 281 | | ports := strings.Trim(strings.Join(strings.Fields(fmt.Sprint(jsonData.Ports)), ", "), "[]") |
291 | 282 | | |
292 | | - | if url { |
| 283 | + | if urls { |
293 | 284 | | if (jsonData.Ports == nil) { |
294 | 285 | | return |
295 | 286 | | } |
| skipped 52 lines |