-
Notifications
You must be signed in to change notification settings - Fork 0
/
penland.go
142 lines (128 loc) · 3.22 KB
/
penland.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
package main
import (
"encoding/json"
"flag"
"fmt"
"io"
"os"
"net/http"
"strings"
"time"
)
// Define a struct to match the JSON structure
type Writeups struct {
Data []struct {
Links []struct {
Title string `json:"Title"`
Link string `json:"Link"`
} `json:"Links"`
Programs []string `json:"Programs"`
Bugs []string `json:"Bugs"`
} `json:"data"`
}
// Result struct for the desired output JSON format
type Result struct {
URL string `json:"url"`
Targets []string `json:"target"`
Bugs []string `json:"Bugs"`
}
type Results struct {
Result []Result `json:"result"`
}
// Flags to capture user input
var (
title = flag.String("title", "", "Filter by the title of the writeup")
program = flag.String("program", "", "Filter by the program involved in the writeup")
bug = flag.String("bug", "", "Filter by the bug types mentioned in the writeup")
output = flag.String("o", "", "Specify the output file name")
)
func main() {
flag.Parse() // Parse the provided flags
client := http.Client{
Timeout: 1 * time.Minute,
}
// Fetch the JSON data from the URL
req, err := http.NewRequest("GET", "https://pentester.land/writeups.json", nil)
if err != nil {
fmt.Printf("Failed to fetch data: %s\n", err)
return
}
response, err := client.Do(req)
if err != nil {
fmt.Println(err)
return
}
defer response.Body.Close()
// Read and parse the response body
body, err := io.ReadAll(response.Body)
if err != nil {
fmt.Printf("Failed to read data: %s\n", err)
return
}
var writeups Writeups
if err = json.Unmarshal(body, &writeups); err != nil {
fmt.Printf("Failed to parse JSON: %s\n", err)
return
}
var results Results
for _, data := range writeups.Data {
match := true
if *title != "" && !strings.Contains(strings.ToLower(data.Links[0].Title), strings.ToLower(*title)) {
match = false
}
if *program != "" {
programMatch := false
for _, program := range data.Programs {
if strings.Contains(strings.ToLower(program), strings.ToLower(program)) {
programMatch = true
break
}
}
if !programMatch {
match = false
}
}
if *bug != "" {
bugsMatch := false
for _, bug := range data.Bugs {
if strings.Contains(strings.ToLower(bug), strings.ToLower(bug)) {
bugsMatch = true
break
}
}
if !bugsMatch {
match = false
}
}
if match {
for _, link := range data.Links {
results.Result = append(results.Result, Result{
URL: link.Link,
Targets: data.Programs,
Bugs: data.Bugs,
})
}
}
}
if *output == "" {
// Print results to the console if output is not provided or default
for _, result := range results.Result {
fmt.Printf("URL: %s\n", result.URL)
fmt.Printf("Programs: %s\n", strings.Join(result.Targets, ", "))
fmt.Printf("Bugs: %s\n", strings.Join(result.Bugs, ", "))
fmt.Println("---")
}
} else {
// Write the results to a JSON file if output is provided
file, err := json.MarshalIndent(results, "", " ")
if err != nil {
fmt.Printf("Failed to marshal results: %s\n", err)
return
}
if err = os.WriteFile(*output, file, 0644); err != nil {
fmt.Printf("Failed to write to file: %s\n", err)
return
}
fmt.Printf("Results written to '%s'\n", *output)
}
}