New upstream snapshot.
Kali Janitor
1 year, 6 months ago
0 | --- | |
1 | name: Bug report | |
2 | about: Create a report to help us improve | |
3 | title: '' | |
4 | labels: '' | |
5 | assignees: '' | |
6 | ||
7 | --- | |
8 | ||
9 | **Describe the bug** | |
10 | A clear and concise description of what the bug is. | |
11 | ||
12 | **To Reproduce** | |
13 | Steps to reproduce the behavior: | |
14 | 1. Go to '...' | |
15 | 2. Command 1 '....' | |
16 | 3. Command 2 '....' | |
17 | 4. See error | |
18 | ||
19 | **Expected behavior** | |
20 | A clear and concise description of what you expected to happen. | |
21 | ||
22 | **Screenshots** | |
23 | If applicable, add screenshots to help explain your problem. | |
24 | ||
25 | **Desktop (please complete the following information):** | |
26 | - OS: [e.g. MacOS] | |
27 | - Version [e.g. v0.0.5] | |
28 | ||
29 | **Additional context** | |
30 | Add any other context about the problem here. |
0 | --- | |
1 | name: Feature request | |
2 | about: Suggest an idea for this project | |
3 | title: '' | |
4 | labels: '' | |
5 | assignees: '' | |
6 | ||
7 | --- | |
8 | ||
9 | **Is your feature request related to a problem? Please describe.** | |
10 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] | |
11 | ||
12 | **Describe the solution you'd like** | |
13 | A clear and concise description of what you want to happen. | |
14 | ||
15 | **Describe alternatives you've considered** | |
16 | A clear and concise description of any alternative solutions or features you've considered. | |
17 | ||
18 | **Additional context** | |
19 | Add any other context or screenshots about the feature request here. |
0 | name: "CodeQL Security Checks" | |
1 | ||
2 | queries: | |
3 | - name: Security and Quality | |
4 | uses: security-extended | |
5 | paths: | |
6 | - server | |
7 | - client |
0 | # Basic set up for three package managers | |
1 | ||
2 | version: 2 | |
3 | updates: | |
4 | ||
5 | # Maintain dependencies for GitHub Actions | |
6 | - package-ecosystem: "github-actions" | |
7 | directory: "/" | |
8 | schedule: | |
9 | interval: "weekly" | |
10 | ||
11 | # Maintain dependencies for go | |
12 | - package-ecosystem: "gomod" | |
13 | directory: "/" | |
14 | schedule: | |
15 | interval: "weekly" |
0 | name: Release | |
1 | ||
2 | on: | |
3 | push: | |
4 | tags: ["v[1-9]+.[0-9]+.[0-9]+"] | |
5 | branches: [master] | |
6 | ||
7 | jobs: | |
8 | linux-windows-build: | |
9 | name: Linux & Windows Build | |
10 | if: startsWith( github.ref, 'refs/tags/v') | |
11 | runs-on: ubuntu-latest | |
12 | timeout-minutes: 45 | |
13 | steps: | |
14 | - name: Go 1.19 | |
15 | uses: actions/setup-go@v3 | |
16 | with: | |
17 | go-version: "^1.19" | |
18 | ||
19 | - name: OS Packages | |
20 | run: | | |
21 | sudo apt-get update --fix-missing && sudo apt-get -y install \ | |
22 | git build-essential zlib1g zlib1g-dev wget zip unzip \ | |
23 | mingw-w64 binutils-mingw-w64 g++-mingw-w64 gcc-multilib | |
24 | ||
25 | - name: Check out code into the Go module directory | |
26 | uses: actions/checkout@v3 | |
27 | ||
28 | - name: Git Fetch Tags | |
29 | run: git fetch --prune --unshallow --tags -f | |
30 | ||
31 | - name: Go Assets | |
32 | run: ./go-assets.sh | |
33 | ||
34 | - name: Make | |
35 | env: | |
36 | ARTIFACT_SUFFIX: _linux | |
37 | run: export PATH=/home/runner/go/bin/:$PATH && make linux | |
38 | ||
39 | - name: Linux Artifacts | |
40 | uses: actions/upload-artifact@v3 | |
41 | with: | |
42 | name: linux | |
43 | path: ./sliver-* | |
44 | ||
45 | - name: Make Windows | |
46 | env: | |
47 | ARTIFACT_SUFFIX: _windows | |
48 | run: | | |
49 | make clean | |
50 | export PATH=/home/runner/go/bin/:$PATH && make windows | |
51 | ||
52 | - name: Windows Artifacts | |
53 | uses: actions/upload-artifact@v3 | |
54 | with: | |
55 | name: windows | |
56 | path: ./sliver-* | |
57 | ||
58 | macos-build: | |
59 | name: MacOS Build | |
60 | if: startsWith( github.ref, 'refs/tags/v') | |
61 | runs-on: macos-latest | |
62 | timeout-minutes: 45 | |
63 | steps: | |
64 | - name: Go 1.19 | |
65 | uses: actions/setup-go@v3 | |
66 | with: | |
67 | go-version: "1.19.1" | |
68 | ||
69 | - name: Mingw | |
70 | run: brew install mingw-w64 | |
71 | ||
72 | - name: Check out code into the Go module directory | |
73 | uses: actions/checkout@v3 | |
74 | ||
75 | - name: Git Fetch Tags | |
76 | run: git fetch --prune --unshallow --tags -f | |
77 | ||
78 | - name: Go Assets | |
79 | run: ./go-assets.sh | |
80 | ||
81 | - name: Make AMD64 | |
82 | env: | |
83 | ARTIFACT_SUFFIX: _macos | |
84 | run: make macos | |
85 | ||
86 | - name: Make ARM64 | |
87 | env: | |
88 | ARTIFACT_SUFFIX: _macos-arm64 | |
89 | run: make macos-arm64 | |
90 | ||
91 | - name: MacOS Artifacts | |
92 | uses: actions/upload-artifact@v3 | |
93 | with: | |
94 | name: macos | |
95 | path: ./sliver-* | |
96 | ||
97 | tagged-release: | |
98 | needs: [linux-windows-build, macos-build] | |
99 | ||
100 | name: "Tagged Release" | |
101 | if: startsWith( github.ref, 'refs/tags/v') | |
102 | runs-on: ubuntu-latest | |
103 | timeout-minutes: 45 | |
104 | ||
105 | steps: | |
106 | - run: mkdir -p ./builds | |
107 | - uses: actions/download-artifact@v3 | |
108 | with: | |
109 | path: ./builds | |
110 | ||
111 | - name: Extract Artifacts | |
112 | run: | | |
113 | mkdir -p ./artifacts | |
114 | cp ./builds/linux/* ./artifacts | |
115 | cp ./builds/windows/* ./artifacts | |
116 | cp ./builds/macos/* ./artifacts | |
117 | ||
118 | - id: install-secret-key | |
119 | name: GPG Key(s) | |
120 | run: | | |
121 | cat <(echo -e "${{ secrets.SLIVER_GPG }}") | gpg --batch --import | |
122 | gpg --list-secret-keys --keyid-format LONG | |
123 | ||
124 | # Linux | |
125 | - name: Linux AMD64 | |
126 | run: | | |
127 | gpg --default-key 4449039C --output ./artifacts/sliver-server_linux.sig --detach-sig ./artifacts/sliver-server_linux | |
128 | gpg --default-key 4449039C --output ./artifacts/sliver-client_linux.sig --detach-sig ./artifacts/sliver-client_linux | |
129 | ||
130 | # Windows | |
131 | - name: Windows AMD64 | |
132 | run: | | |
133 | gpg --default-key 4449039C --output ./artifacts/sliver-server_windows.sig --detach-sig ./artifacts/sliver-server_windows.exe | |
134 | gpg --default-key 4449039C --output ./artifacts/sliver-client_windows.sig --detach-sig ./artifacts/sliver-client_windows.exe | |
135 | ||
136 | # MacOS AMD64 | |
137 | - name: MacOS AMD64 | |
138 | run: | | |
139 | gpg --default-key 4449039C --output ./artifacts/sliver-server_macos.sig --detach-sig ./artifacts/sliver-server_macos | |
140 | gpg --default-key 4449039C --output ./artifacts/sliver-client_macos.sig --detach-sig ./artifacts/sliver-client_macos | |
141 | ||
142 | # MacOS ARM64 | |
143 | - name: Package MacOS ARM64 | |
144 | run: | | |
145 | gpg --default-key 4449039C --output ./artifacts/sliver-server_macos-arm64.sig --detach-sig ./artifacts/sliver-server_macos-arm64 | |
146 | gpg --default-key 4449039C --output ./artifacts/sliver-client_macos-arm64.sig --detach-sig ./artifacts/sliver-client_macos-arm64 | |
147 | ||
148 | - name: "Publish Release" | |
149 | uses: "marvinpinto/action-automatic-releases@latest" | |
150 | with: | |
151 | repo_token: "${{ secrets.GITHUB_TOKEN }}" | |
152 | prerelease: true | |
153 | files: | | |
154 | ./artifacts/* |
0 | name: "Code Scanning" | |
1 | ||
2 | on: | |
3 | push: | |
4 | branches: | |
5 | - test/* | |
6 | pull_request: | |
7 | branches: | |
8 | - master | |
9 | ||
10 | jobs: | |
11 | CodeQL-Build: | |
12 | name: CodeQL Security Scan | |
13 | runs-on: ubuntu-latest | |
14 | timeout-minutes: 90 | |
15 | ||
16 | steps: | |
17 | # Setup go environment | |
18 | - name: Go 1.19 | |
19 | uses: actions/setup-go@v3 | |
20 | with: | |
21 | go-version: "^1.19" | |
22 | ||
23 | - name: Checkout repository | |
24 | uses: actions/checkout@v3 | |
25 | with: | |
26 | # Must fetch at least the immediate parents so that if this is | |
27 | # a pull request then we can checkout the head of the pull request. | |
28 | # Only include this option if you are running this workflow on pull requests. | |
29 | if: ${{ github.event_name == 'pull_request' }} | |
30 | fetch-depth: 2 | |
31 | ||
32 | - name: OS Packages | |
33 | run: | | |
34 | sudo apt-get update --fix-missing && sudo apt-get -y install \ | |
35 | git build-essential zlib1g zlib1g-dev wget zip unzip \ | |
36 | mingw-w64 binutils-mingw-w64 g++-mingw-w64 | |
37 | ||
38 | - name: Check out code into the Go module directory | |
39 | uses: actions/checkout@v3 | |
40 | ||
41 | - name: Go Assets | |
42 | run: ./go-assets.sh | |
43 | ||
44 | # Initializes the CodeQL tools for scanning. | |
45 | - name: Initialize CodeQL | |
46 | uses: github/codeql-action/init@v2 | |
47 | with: | |
48 | config-file: ./.github/codeql/codeql-config.yml | |
49 | languages: go | |
50 | ||
51 | # Build the server ... is this necessary though? | |
52 | - run: | | |
53 | make | |
54 | ||
55 | - name: Perform CodeQL Analysis | |
56 | uses: github/codeql-action/analyze@v2 | |
57 | env: | |
58 | VERSION: ${{github.sha}} |
0 | name: Build & Test | |
1 | on: | |
2 | pull_request: | |
3 | branches: | |
4 | - master | |
5 | types: | |
6 | - opened | |
7 | - reopened | |
8 | - synchronize | |
9 | - ready_for_review | |
10 | ||
11 | jobs: | |
12 | linux-windows-build: | |
13 | name: Linux & Windows Build | |
14 | runs-on: ubuntu-latest | |
15 | timeout-minutes: 90 | |
16 | steps: | |
17 | - name: Go 1.19 | |
18 | uses: actions/setup-go@v3 | |
19 | with: | |
20 | go-version: "^1.19" | |
21 | ||
22 | - name: OS Packages | |
23 | run: | | |
24 | sudo apt-get update --fix-missing && sudo apt-get -y install \ | |
25 | git build-essential zlib1g zlib1g-dev wget zip unzip \ | |
26 | mingw-w64 binutils-mingw-w64 g++-mingw-w64 gcc-multilib | |
27 | ||
28 | - name: Check out code into the Go module directory | |
29 | uses: actions/checkout@v3 | |
30 | ||
31 | - name: Git Fetch Tags | |
32 | run: git fetch --prune --unshallow --tags -f | |
33 | ||
34 | - name: Go Assets | |
35 | run: ./go-assets.sh | |
36 | ||
37 | - name: Make | |
38 | run: make linux | |
39 | ||
40 | - name: Test | |
41 | run: ./sliver-server unpack --force && ./go-tests.sh | |
42 | ||
43 | - name: Make Windows | |
44 | run: make windows | |
45 | ||
46 | macos-build: | |
47 | name: MacOS Build | |
48 | runs-on: macos-latest | |
49 | timeout-minutes: 90 | |
50 | steps: | |
51 | - name: Go 1.19 | |
52 | uses: actions/setup-go@v3 | |
53 | with: | |
54 | go-version: "^1.19" | |
55 | ||
56 | - name: Mingw | |
57 | run: brew install mingw-w64 | |
58 | ||
59 | - name: Check out code into the Go module directory | |
60 | uses: actions/checkout@v3 | |
61 | ||
62 | - name: Git Fetch Tags | |
63 | run: git fetch --prune --unshallow --tags -f | |
64 | ||
65 | - name: Go Assets | |
66 | run: ./go-assets.sh | |
67 | ||
68 | - name: Make | |
69 | run: make macos | |
70 | ||
71 | - name: Test | |
72 | env: | |
73 | SLIVER_CC_32: /usr/local/bin/i686-w64-mingw32-gcc | |
74 | SLIVER_CC_64: /usr/local/bin/x86_64-w64-mingw32-gcc | |
75 | run: ./sliver-server unpack --force && ./go-tests.sh |
0 | /.vscode/* | |
1 | /.devcontainer | |
2 | /.idea | |
3 | ||
4 | /Dockerfile.* | |
5 | /*.sdk.tar.xz | |
6 | ||
7 | /release-* | |
8 | ||
9 | # Diffs | |
10 | *.orig | |
11 | ||
12 | # Binaries | |
13 | /sliver-server | |
14 | /sliver-server_arm64 | |
15 | /sliver.exe | |
16 | ||
17 | /sliver-client | |
18 | /sliver-client_arm64 | |
19 | /sliver-client.exe | |
20 | ||
21 | sliver-server-linux.zip | |
22 | sliver-server-macos.zip | |
23 | sliver-server-windows.zip | |
24 | ||
25 | ||
26 | # Binaries for programs and plugins | |
27 | *.exe | |
28 | *.dll | |
29 | *.so | |
30 | *.dylib | |
31 | ||
32 | # Test binary, build with `go test -c` | |
33 | /*.test | |
34 | ||
35 | # Output of the go coverage tool, specifically when used with LiteIDE | |
36 | /*.out | |
37 | ||
38 | # Project-local glide cache, RE: https://github.com/Masterminds/glide/issues/736 | |
39 | .glide/ | |
40 | ||
41 | .DS_Store | |
42 | ||
43 | dist/ |
46 | 46 | -X $(CLIENT_ASSETS_PKG).DefaultArmoryPublicKey=$(ARMORY_PUB_KEY) \ |
47 | 47 | -X $(CLIENT_ASSETS_PKG).DefaultArmoryRepoURL=$(ARMORY_REPO_URL)" |
48 | 48 | |
49 | # Debug builds can't be stripped (-s -w flags) | |
50 | LDFLAGS_DEBUG = -ldflags "-X $(VERSION_PKG).Version=$(VERSION) \ | |
51 | -X \"$(VERSION_PKG).GoVersion=$(GO_VERSION)\" \ | |
52 | -X $(VERSION_PKG).CompiledAt=$(COMPILED_AT) \ | |
53 | -X $(VERSION_PKG).GithubReleasesURL=$(RELEASES_URL) \ | |
54 | -X $(VERSION_PKG).GitCommit=$(GIT_COMMIT) \ | |
55 | -X $(VERSION_PKG).GitDirty=$(GIT_DIRTY) \ | |
56 | -X $(CLIENT_ASSETS_PKG).DefaultArmoryPublicKey=$(ARMORY_PUB_KEY) \ | |
57 | -X $(CLIENT_ASSETS_PKG).DefaultArmoryRepoURL=$(ARMORY_REPO_URL)" | |
49 | 58 | |
50 | 59 | SED_INPLACE := sed -i |
51 | 60 | STATIC_TARGET := linux |
145 | 154 | protoc -I protobuf/ protobuf/dnspb/dns.proto --go_out=paths=source_relative:protobuf/ |
146 | 155 | protoc -I protobuf/ protobuf/rpcpb/services.proto --go_out=paths=source_relative:protobuf/ --go-grpc_out=protobuf/ --go-grpc_opt=paths=source_relative |
147 | 156 | |
157 | .PHONY: debug | |
158 | debug: clean | |
159 | $(ENV) $(GO) build -mod=vendor $(TAGS),server $(LDFLAGS_DEBUG) -o sliver-server$(ARTIFACT_SUFFIX) ./server | |
160 | $(ENV) $(GO) build -mod=vendor $(TAGS),client $(LDFLAGS_DEBUG) -o sliver-client$(ARTIFACT_SUFFIX) ./client | |
161 | ||
148 | 162 | validate-go-version: |
149 | 163 | @if [ $(GO_MAJOR_VERSION) -gt $(MIN_SUPPORTED_GO_MAJOR_VERSION) ]; then \ |
150 | 164 | exit 0 ;\ |
1964 | 1964 | f.Bool("4", "ip4", true, "display information about IPv4 sockets") |
1965 | 1965 | f.Bool("6", "ip6", false, "display information about IPv6 sockets") |
1966 | 1966 | f.Bool("l", "listen", false, "display information about listening sockets") |
1967 | f.Bool("n", "numeric", false, "display numeric addresses (disable hostname resolution)") | |
1967 | 1968 | f.Int("t", "timeout", defaultTimeout, "command timeout in seconds") |
1968 | 1969 | }, |
1969 | 1970 | HelpGroup: consts.SliverHelpGroup, |
43 | 43 | ip6 := ctx.Flags.Bool("ip6") |
44 | 44 | tcp := ctx.Flags.Bool("tcp") |
45 | 45 | udp := ctx.Flags.Bool("udp") |
46 | numeric := ctx.Flags.Bool("numeric") | |
46 | 47 | |
47 | 48 | implantPID := getPID(session, beacon) |
48 | 49 | activeC2 := getActiveC2(session, beacon) |
66 | 67 | con.PrintErrorf("Failed to decode response %s\n", err) |
67 | 68 | return |
68 | 69 | } |
69 | PrintNetstat(netstat, implantPID, activeC2, con) | |
70 | PrintNetstat(netstat, implantPID, activeC2, numeric, con) | |
70 | 71 | }) |
71 | 72 | con.PrintAsyncResponse(netstat.Response) |
72 | 73 | } else { |
73 | PrintNetstat(netstat, implantPID, activeC2, con) | |
74 | PrintNetstat(netstat, implantPID, activeC2, numeric, con) | |
74 | 75 | } |
75 | 76 | } |
76 | 77 | |
77 | func PrintNetstat(netstat *sliverpb.Netstat, implantPID int32, activeC2 string, con *console.SliverConsoleClient) { | |
78 | func PrintNetstat(netstat *sliverpb.Netstat, implantPID int32, activeC2 string, numeric bool, con *console.SliverConsoleClient) { | |
78 | 79 | lookup := func(skaddr *sliverpb.SockTabEntry_SockAddr) string { |
79 | const IPv4Strlen = 17 | |
80 | 80 | addr := skaddr.Ip |
81 | 81 | names, err := net.LookupAddr(addr) |
82 | 82 | if err == nil && len(names) > 0 { |
83 | 83 | addr = names[0] |
84 | } | |
85 | if len(addr) > IPv4Strlen { | |
86 | addr = addr[:IPv4Strlen] | |
87 | 84 | } |
88 | 85 | return fmt.Sprintf("%s:%d", addr, skaddr.Port) |
89 | 86 | } |
97 | 94 | if entry.Process != nil { |
98 | 95 | pid = fmt.Sprintf("%d/%s", entry.Process.Pid, entry.Process.Executable) |
99 | 96 | } |
100 | srcAddr := lookup(entry.LocalAddr) | |
101 | dstAddr := lookup(entry.RemoteAddr) | |
97 | srcAddr := fmt.Sprintf("%s:%d", entry.LocalAddr.Ip, entry.LocalAddr.Port) | |
98 | dstAddr := fmt.Sprintf("%s:%d", entry.RemoteAddr.Ip, entry.RemoteAddr.Port) | |
99 | if !numeric { | |
100 | srcAddr = lookup(entry.LocalAddr) | |
101 | dstAddr = lookup(entry.RemoteAddr) | |
102 | } | |
102 | 103 | if entry.Process != nil && entry.Process.Pid == implantPID { |
103 | 104 | tw.AppendRow(table.Row{ |
104 | 105 | fmt.Sprintf(console.Green+"%s"+console.Normal, entry.Protocol), |
29 | 29 | |
30 | 30 | // TerminateCmd - Terminate a process on the remote system |
31 | 31 | func TerminateCmd(ctx *grumble.Context, con *console.SliverConsoleClient) { |
32 | session := con.ActiveTarget.GetSessionInteractive() | |
33 | if session == nil { | |
32 | session, beacon := con.ActiveTarget.GetInteractive() | |
33 | if session == nil && beacon == nil { | |
34 | con.PrintErrorf("No active session or beacon\n") | |
34 | 35 | return |
35 | 36 | } |
36 | 37 |
431 | 431 | con.PrintErrorf("Failed to fetch beacon: %s\n", err) |
432 | 432 | return |
433 | 433 | } |
434 | network.PrintNetstat(netstat, beacon.PID, beacon.ActiveC2, con) | |
434 | network.PrintNetstat(netstat, beacon.PID, beacon.ActiveC2, false, con) | |
435 | 435 | |
436 | 436 | // --------------------- |
437 | 437 | // Privilege commands |
0 | sliver (1.5.31+git20221110.1.d699a8d-0kali1) UNRELEASED; urgency=low | |
1 | ||
2 | * New upstream snapshot. | |
3 | ||
4 | -- Kali Janitor <[email protected]> Sun, 13 Nov 2022 01:36:47 -0000 | |
5 | ||
0 | 6 | sliver (1.5.31-0kali1) kali-dev; urgency=medium |
1 | 7 | |
2 | 8 | * New upstream version 1.5.31 |
19 | 19 | github.com/desertbit/grumble v1.1.1 |
20 | 20 | github.com/desertbit/readline v1.5.1 |
21 | 21 | github.com/fatih/color v1.13.0 |
22 | github.com/gofrs/uuid v4.3.0+incompatible | |
22 | github.com/gofrs/uuid v4.3.1+incompatible | |
23 | 23 | github.com/google/uuid v1.3.0 |
24 | 24 | github.com/gorilla/mux v1.8.0 |
25 | 25 | github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 |
26 | github.com/jedib0t/go-pretty/v6 v6.4.0 | |
26 | github.com/jedib0t/go-pretty/v6 v6.4.2 | |
27 | 27 | github.com/kbinani/screenshot v0.0.0-20191211154542-3a185f1ce18f |
28 | 28 | github.com/lesnuages/go-winio v0.4.19 |
29 | 29 | github.com/lesnuages/snitch v0.6.0 |
31 | 31 | github.com/miekg/dns v1.1.50 |
32 | 32 | github.com/moloch--/memmod v0.0.0-20211120144554-8b37cc654945 |
33 | 33 | github.com/pquerna/otp v1.3.0 |
34 | github.com/shirou/gopsutil/v3 v3.22.9 | |
34 | github.com/shirou/gopsutil/v3 v3.22.10 | |
35 | 35 | github.com/sirupsen/logrus v1.9.0 |
36 | 36 | github.com/spf13/cobra v1.6.1 |
37 | 37 | github.com/stretchr/testify v1.8.1 |
38 | 38 | github.com/things-go/go-socks5 v0.0.3-0.20210722055343-24af464efe43 |
39 | github.com/xlab/treeprint v1.1.0 | |
39 | 40 | github.com/yiya1989/sshkrb5 v0.0.0-20201110125252-a1455b75a35e |
40 | 41 | golang.org/x/crypto v0.0.0-20220829220503-c86fa9a7ed90 |
41 | 42 | golang.org/x/net v0.0.0-20220722155237-a158d28d115b |
108 | 109 | github.com/rivo/uniseg v0.2.0 // indirect |
109 | 110 | github.com/spf13/pflag v1.0.5 // indirect |
110 | 111 | github.com/thedevsaddam/gojsonq/v2 v2.5.2 // indirect |
111 | github.com/xlab/treeprint v1.1.0 // indirect | |
112 | 112 | github.com/yusufpapurcu/wmi v1.2.2 // indirect |
113 | 113 | golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 // indirect |
114 | 114 | golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba // indirect |
121 | 121 | github.com/gobwas/ws v1.1.0 h1:7RFti/xnNkMJnrK7D1yQ/iCIB5OrrY/54/H930kIbHA= |
122 | 122 | github.com/gobwas/ws v1.1.0/go.mod h1:nzvNcVha5eUziGrbxFCo6qFIojQHjJV5cLYIbezhfL0= |
123 | 123 | github.com/gofrs/uuid v4.0.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= |
124 | github.com/gofrs/uuid v4.3.0+incompatible h1:CaSVZxm5B+7o45rtab4jC2G37WGYX1zQfuU2i6DSvnc= | |
125 | github.com/gofrs/uuid v4.3.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= | |
124 | github.com/gofrs/uuid v4.3.1+incompatible h1:0/KbAdpx3UXAx1kEOWHJeOkpbgRFGHVgv+CFIY7dBJI= | |
125 | github.com/gofrs/uuid v4.3.1+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= | |
126 | 126 | github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= |
127 | 127 | github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= |
128 | 128 | github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= |
227 | 227 | github.com/jackc/puddle v1.3.0/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= |
228 | 228 | github.com/jcmturner/gofork v1.0.0 h1:J7uCkflzTEhUZ64xqKnkDxq3kzc96ajM1Gli5ktUem8= |
229 | 229 | github.com/jcmturner/gofork v1.0.0/go.mod h1:MK8+TM0La+2rjBD4jE12Kj1pCCxK7d2LK/UM3ncEo0o= |
230 | github.com/jedib0t/go-pretty/v6 v6.4.0 h1:YlI/2zYDrweA4MThiYMKtGRfT+2qZOO65ulej8GTcVI= | |
231 | github.com/jedib0t/go-pretty/v6 v6.4.0/go.mod h1:MgmISkTWDSFu0xOqiZ0mKNntMQ2mDgOcwOkwBEkMDJI= | |
230 | github.com/jedib0t/go-pretty/v6 v6.4.2 h1:DcJNSNIb1E17Tvy9w9S7z+sExvWvvjNbFdyr6C+FUL0= | |
231 | github.com/jedib0t/go-pretty/v6 v6.4.2/go.mod h1:MgmISkTWDSFu0xOqiZ0mKNntMQ2mDgOcwOkwBEkMDJI= | |
232 | 232 | github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E= |
233 | 233 | github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc= |
234 | 234 | github.com/jinzhu/now v1.1.4/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= |
331 | 331 | github.com/rs/zerolog v1.15.0/go.mod h1:xYTKnLHcpfU2225ny5qZjxnj9NvkumZYjJHlAThCjNc= |
332 | 332 | github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= |
333 | 333 | github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= |
334 | github.com/shirou/gopsutil/v3 v3.22.9 h1:yibtJhIVEMcdw+tCTbOPiF1VcsuDeTE4utJ8Dm4c5eA= | |
335 | github.com/shirou/gopsutil/v3 v3.22.9/go.mod h1:bBYl1kjgEJpWpxeHmLI+dVHWtyAwfcmSBLDsp2TNT8A= | |
334 | github.com/shirou/gopsutil/v3 v3.22.10 h1:4KMHdfBRYXGF9skjDWiL4RA2N+E8dRdodU/bOZpPoVg= | |
335 | github.com/shirou/gopsutil/v3 v3.22.10/go.mod h1:QNza6r4YQoydyCfo6rH0blGfKahgibh4dQmV5xdFkQk= | |
336 | 336 | github.com/shopspring/decimal v0.0.0-20180709203117-cd690d0c9e24/go.mod h1:M+9NzErvs504Cn4c5DxATwIqPbtswREoFCre64PpcG4= |
337 | 337 | github.com/shopspring/decimal v1.2.0 h1:abSATXmQEYyShuxI4/vyW3tV1MrKAJzCZ/0zLUXYbsQ= |
338 | 338 | github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= |
23 | 23 | "fmt" |
24 | 24 | "io" |
25 | 25 | "os" |
26 | "runtime" | |
26 | 27 | |
27 | 28 | // {{if .Config.Debug}} |
28 | 29 | "log" |
36 | 37 | "github.com/bishopfox/sliver/implant/sliver/registry" |
37 | 38 | "github.com/bishopfox/sliver/implant/sliver/service" |
38 | 39 | "github.com/bishopfox/sliver/implant/sliver/spoof" |
40 | "github.com/bishopfox/sliver/implant/sliver/syscalls" | |
39 | 41 | "github.com/bishopfox/sliver/implant/sliver/taskrunner" |
40 | 42 | "github.com/bishopfox/sliver/protobuf/commonpb" |
41 | 43 | "github.com/bishopfox/sliver/protobuf/sliverpb" |
119 | 121 | return windowsHandlers |
120 | 122 | } |
121 | 123 | |
124 | func WrapperHandler(handler RPCHandler, data []byte, resp RPCResponse) { | |
125 | if priv.CurrentToken != 0 { | |
126 | err := syscalls.ImpersonateLoggedOnUser(priv.CurrentToken) | |
127 | if err != nil { | |
128 | // {{if .Config.Debug}} | |
129 | log.Printf("Error: %v\n", err) | |
130 | // {{end}} | |
131 | } | |
132 | runtime.LockOSThread() | |
133 | defer runtime.UnlockOSThread() | |
134 | } | |
135 | handler(data, resp) | |
136 | if priv.CurrentToken != 0 { | |
137 | err := priv.TRevertToSelf() | |
138 | if err != nil { | |
139 | // {{if .Config.Debug}} | |
140 | log.Printf("Error: %v\n", err) | |
141 | // {{end}} | |
142 | } | |
143 | } | |
144 | } | |
145 | ||
122 | 146 | // ---------------- Windows Handlers ---------------- |
123 | 147 | |
124 | 148 | func impersonateHandler(data []byte, resp RPCResponse) { |
280 | 280 | } |
281 | 281 | entries = append(entries, &sliverpb.SockTabEntry{ |
282 | 282 | LocalAddr: &sliverpb.SockTabEntry_SockAddr{ |
283 | Ip: e.LocalAddr.String(), | |
283 | Ip: e.LocalAddr.IP.String(), | |
284 | 284 | Port: uint32(e.LocalAddr.Port), |
285 | 285 | }, |
286 | 286 | RemoteAddr: &sliverpb.SockTabEntry_SockAddr{ |
287 | Ip: e.RemoteAddr.String(), | |
287 | Ip: e.RemoteAddr.IP.String(), | |
288 | 288 | Port: uint32(e.RemoteAddr.Port), |
289 | 289 | }, |
290 | 290 | SkState: e.State.String(), |
95 | 95 | } |
96 | 96 | |
97 | 97 | func RevertToSelf() error { |
98 | err := windows.RevertToSelf() | |
99 | if err != nil { | |
100 | // {{if .Config.Debug}} | |
101 | log.Printf("RevertToSelf Error: %v\n", err) | |
102 | // {{end}} | |
103 | } | |
104 | err = windows.CloseHandle(windows.Handle(CurrentToken)) | |
105 | if err != nil { | |
106 | // {{if .Config.Debug}} | |
107 | log.Printf("CloseHandle Error: %v\n", err) | |
108 | // {{end}} | |
109 | } | |
98 | 110 | CurrentToken = windows.Token(0) |
111 | return err | |
112 | } | |
113 | ||
114 | func TRevertToSelf() error { | |
99 | 115 | return windows.RevertToSelf() |
100 | 116 | } |
101 | 117 |
41 | 41 | "io/ioutil" |
42 | 42 | // {{end}} |
43 | 43 | |
44 | // {{if eq .Config.GOOS "windows"}} | |
45 | "github.com/bishopfox/sliver/implant/sliver/priv" | |
46 | "github.com/bishopfox/sliver/implant/sliver/syscalls" | |
47 | ||
48 | // {{end}} | |
49 | ||
50 | 44 | consts "github.com/bishopfox/sliver/implant/sliver/constants" |
51 | 45 | "github.com/bishopfox/sliver/implant/sliver/handlers" |
52 | 46 | "github.com/bishopfox/sliver/implant/sliver/hostuuid" |
47 | "github.com/bishopfox/sliver/implant/sliver/limits" | |
53 | 48 | "github.com/bishopfox/sliver/implant/sliver/locale" |
54 | "github.com/bishopfox/sliver/implant/sliver/limits" | |
55 | 49 | "github.com/bishopfox/sliver/implant/sliver/pivots" |
56 | 50 | "github.com/bishopfox/sliver/implant/sliver/transports" |
57 | 51 | "github.com/bishopfox/sliver/implant/sliver/version" |
126 | 120 | var isRunning bool = false |
127 | 121 | |
128 | 122 | // StartW - Export for shared lib build |
123 | // | |
129 | 124 | //export StartW |
130 | 125 | func StartW() { |
131 | 126 | if !isRunning { |
138 | 133 | //https://github.com/Ne0nd0g/merlin/blob/master/cmd/merlinagentdll/main.go#L65 |
139 | 134 | |
140 | 135 | // VoidFunc is an exported function used with PowerSploit's Invoke-ReflectivePEInjection.ps1 |
136 | // | |
141 | 137 | //export VoidFunc |
142 | 138 | func VoidFunc() { main() } |
143 | 139 | |
144 | 140 | // DllInstall is used when executing the Sliver implant with regsvr32.exe (i.e. regsvr32.exe /s /n /i sliver.dll) |
145 | 141 | // https://msdn.microsoft.com/en-us/library/windows/desktop/bb759846(v=vs.85).aspx |
142 | // | |
146 | 143 | //export DllInstall |
147 | 144 | func DllInstall() { main() } |
148 | 145 | |
149 | 146 | // DllRegisterServer - is used when executing the Sliver implant with regsvr32.exe (i.e. regsvr32.exe /s sliver.dll) |
150 | 147 | // https://msdn.microsoft.com/en-us/library/windows/desktop/ms682162(v=vs.85).aspx |
148 | // | |
151 | 149 | //export DllRegisterServer |
152 | 150 | func DllRegisterServer() { main() } |
153 | 151 | |
154 | 152 | // DllUnregisterServer - is used when executing the Sliver implant with regsvr32.exe (i.e. regsvr32.exe /s /u sliver.dll) |
155 | 153 | // https://msdn.microsoft.com/en-us/library/windows/desktop/ms691457(v=vs.85).aspx |
154 | // | |
156 | 155 | //export DllUnregisterServer |
157 | 156 | func DllUnregisterServer() { main() } |
158 | 157 | |
408 | 407 | wg.Add(1) |
409 | 408 | data := task.Data |
410 | 409 | taskID := task.ID |
410 | // {{if eq .Config.GOOS "windows" }} | |
411 | go handlers.WrapperHandler(handler, data, func(data []byte, err error) { | |
412 | resultsMutex.Lock() | |
413 | defer resultsMutex.Unlock() | |
414 | defer wg.Done() | |
415 | // {{if .Config.Debug}} | |
416 | if err != nil { | |
417 | log.Printf("[beacon] handler function returned an error: %s", err) | |
418 | } | |
419 | log.Printf("[beacon] task completed (id: %d)", taskID) | |
420 | // {{end}} | |
421 | results = append(results, &sliverpb.Envelope{ | |
422 | ID: taskID, | |
423 | Data: data, | |
424 | }) | |
425 | }) | |
426 | // {{else}} | |
411 | 427 | go handler(data, func(data []byte, err error) { |
412 | 428 | resultsMutex.Lock() |
413 | 429 | defer resultsMutex.Unlock() |
423 | 439 | Data: data, |
424 | 440 | }) |
425 | 441 | }) |
442 | // {{end}} | |
426 | 443 | } else if task.Type == sliverpb.MsgOpenSession { |
427 | 444 | go openSessionHandler(task.Data) |
428 | 445 | resultsMutex.Lock() |
565 | 582 | // only applies the token to the calling thread, we need to call it before every task. |
566 | 583 | // It's fucking gross to do that here, but I could not come with a better solution. |
567 | 584 | |
568 | // {{if eq .Config.GOOS "windows" }} | |
569 | if priv.CurrentToken != 0 { | |
570 | err := syscalls.ImpersonateLoggedOnUser(priv.CurrentToken) | |
571 | if err != nil { | |
572 | // {{if .Config.Debug}} | |
573 | log.Printf("Error: %v\n", err) | |
574 | // {{end}} | |
575 | } | |
576 | } | |
577 | // {{end}} | |
578 | ||
579 | 585 | // {{if .Config.Debug}} |
580 | 586 | log.Printf("[recv] sysHandler %d", envelope.Type) |
581 | 587 | // {{end}} |
588 | ||
589 | // {{if eq .Config.GOOS "windows" }} | |
590 | go handlers.WrapperHandler(handler, envelope.Data, func(data []byte, err error) { | |
591 | // {{if .Config.Debug}} | |
592 | if err != nil { | |
593 | log.Printf("[session] handler function returned an error: %s", err) | |
594 | } | |
595 | // {{end}} | |
596 | connection.Send <- &sliverpb.Envelope{ | |
597 | ID: envelope.ID, | |
598 | Data: data, | |
599 | } | |
600 | }) | |
601 | // {{else}} | |
582 | 602 | go handler(envelope.Data, func(data []byte, err error) { |
583 | 603 | // {{if .Config.Debug}} |
584 | 604 | if err != nil { |
590 | 610 | Data: data, |
591 | 611 | } |
592 | 612 | }) |
613 | // {{end}} | |
593 | 614 | } else if handler, ok := tunHandlers[envelope.Type]; ok { |
594 | 615 | // {{if .Config.Debug}} |
595 | 616 | log.Printf("[recv] tunHandler %d", envelope.Type) |
26 | 26 | "github.com/bishopfox/sliver/protobuf/clientpb" |
27 | 27 | "github.com/bishopfox/sliver/protobuf/commonpb" |
28 | 28 | "github.com/bishopfox/sliver/protobuf/sliverpb" |
29 | "github.com/bishopfox/sliver/server/codenames" | |
29 | 30 | "github.com/bishopfox/sliver/server/core" |
30 | 31 | "github.com/bishopfox/sliver/server/cryptography" |
31 | 32 | "github.com/bishopfox/sliver/server/generate" |
76 | 77 | return nil, fmt.Errorf("please select a profile targeting a shellcode format") |
77 | 78 | } |
78 | 79 | |
80 | if p.Config.Name == "" { | |
81 | p.Config.Name, err = codenames.GetCodename() | |
82 | if err != nil { | |
83 | return nil, err | |
84 | } | |
85 | } | |
86 | ||
79 | 87 | name, config := generate.ImplantConfigFromProtobuf(p.Config) |
80 | 88 | otpSecret, _ := cryptography.TOTPServerSecret() |
81 | 89 | err = generate.GenerateConfig(name, config, true) |
284 | 284 | } |
285 | 285 | |
286 | 286 | tn := g.epochFunc() |
287 | ms := uint64(tn.UnixMilli()) | |
287 | ms := uint64(tn.Unix())*1e3 + uint64(tn.Nanosecond())/1e6 | |
288 | 288 | u[0] = byte(ms >> 40) |
289 | 289 | u[1] = byte(ms >> 32) |
290 | 290 | u[2] = byte(ms >> 24) |
363 | 363 | |
364 | 364 | func (t *Table) renderTitle(out *strings.Builder) { |
365 | 365 | if t.title != "" { |
366 | colors := t.style.Title.Colors | |
366 | 367 | rowLength := t.maxRowLength |
367 | 368 | if t.allowedRowLength != 0 && t.allowedRowLength < rowLength { |
368 | 369 | rowLength = t.allowedRowLength |
369 | 370 | } |
370 | 371 | if t.style.Options.DrawBorder { |
371 | 372 | lenBorder := rowLength - text.RuneWidthWithoutEscSequences(t.style.Box.TopLeft+t.style.Box.TopRight) |
372 | out.WriteString(t.style.Box.TopLeft) | |
373 | out.WriteString(text.RepeatAndTrim(t.style.Box.MiddleHorizontal, lenBorder)) | |
374 | out.WriteString(t.style.Box.TopRight) | |
373 | out.WriteString(colors.Sprint(t.style.Box.TopLeft)) | |
374 | out.WriteString(colors.Sprint(text.RepeatAndTrim(t.style.Box.MiddleHorizontal, lenBorder))) | |
375 | out.WriteString(colors.Sprint(t.style.Box.TopRight)) | |
375 | 376 | } |
376 | 377 | |
377 | 378 | lenText := rowLength - text.RuneWidthWithoutEscSequences(t.style.Box.PaddingLeft+t.style.Box.PaddingRight) |
380 | 381 | } |
381 | 382 | titleText := text.WrapText(t.title, lenText) |
382 | 383 | for _, titleLine := range strings.Split(titleText, "\n") { |
383 | t.renderTitleLine(out, lenText, titleLine) | |
384 | } | |
385 | } | |
386 | } | |
387 | ||
388 | func (t *Table) renderTitleLine(out *strings.Builder, lenText int, titleLine string) { | |
384 | t.renderTitleLine(out, lenText, titleLine, colors) | |
385 | } | |
386 | } | |
387 | } | |
388 | ||
389 | func (t *Table) renderTitleLine(out *strings.Builder, lenText int, titleLine string, colors text.Colors) { | |
389 | 390 | titleLine = strings.TrimSpace(titleLine) |
390 | 391 | titleLine = t.style.Title.Format.Apply(titleLine) |
391 | 392 | titleLine = t.style.Title.Align.Apply(titleLine, lenText) |
392 | 393 | titleLine = t.style.Box.PaddingLeft + titleLine + t.style.Box.PaddingRight |
393 | titleLine = t.style.Title.Colors.Sprint(titleLine) | |
394 | 394 | |
395 | 395 | if out.Len() > 0 { |
396 | 396 | out.WriteRune('\n') |
397 | 397 | } |
398 | 398 | if t.style.Options.DrawBorder { |
399 | out.WriteString(t.style.Box.Left) | |
400 | } | |
401 | out.WriteString(titleLine) | |
399 | out.WriteString(colors.Sprint(t.style.Box.Left)) | |
400 | } | |
401 | out.WriteString(colors.Sprint(titleLine)) | |
402 | 402 | if t.style.Options.DrawBorder { |
403 | out.WriteString(t.style.Box.Right) | |
404 | } | |
405 | } | |
403 | out.WriteString(colors.Sprint(t.style.Box.Right)) | |
404 | } | |
405 | } |
0 | package table | |
1 | ||
2 | // renderHint has hints for the Render*() logic | |
3 | type renderHint struct { | |
4 | isAutoIndexColumn bool // auto-index column? | |
5 | isAutoIndexRow bool // auto-index row? | |
6 | isBorderBottom bool // bottom-border? | |
7 | isBorderTop bool // top-border? | |
8 | isFirstRow bool // first-row of header/footer/regular-rows? | |
9 | isFooterRow bool // footer row? | |
10 | isHeaderRow bool // header row? | |
11 | isLastLineOfRow bool // last-line of the current row? | |
12 | isLastRow bool // last-row of header/footer/regular-rows? | |
13 | isSeparatorRow bool // separator row? | |
14 | rowLineNumber int // the line number for a multi-line row | |
15 | rowNumber int // the row number/index | |
16 | } | |
17 | ||
18 | func (h *renderHint) isRegularRow() bool { | |
19 | return !h.isHeaderRow && !h.isFooterRow | |
20 | } | |
21 | ||
22 | func (h *renderHint) isRegularNonSeparatorRow() bool { | |
23 | return !h.isHeaderRow && !h.isFooterRow && !h.isSeparatorRow | |
24 | } | |
25 | ||
26 | func (h *renderHint) isHeaderOrFooterSeparator() bool { | |
27 | return h.isSeparatorRow && !h.isBorderBottom && !h.isBorderTop && | |
28 | ((h.isHeaderRow && !h.isLastRow) || (h.isFooterRow && (!h.isFirstRow || h.rowNumber > 0))) | |
29 | } | |
30 | ||
31 | func (h *renderHint) isLastLineOfLastRow() bool { | |
32 | return h.isLastLineOfRow && h.isLastRow | |
33 | } |
370 | 370 | } |
371 | 371 | |
372 | 372 | func (t *Table) getBorderColors(hint renderHint) text.Colors { |
373 | if hint.isFooterRow { | |
373 | if hint.isHeaderRow { | |
374 | return t.style.Color.Header | |
375 | } else if hint.isFooterRow { | |
374 | 376 | return t.style.Color.Footer |
375 | 377 | } else if t.autoIndex { |
376 | 378 | return t.style.Color.IndexColumn |
377 | 379 | } |
378 | return t.style.Color.Header | |
380 | return t.style.Color.Row | |
379 | 381 | } |
380 | 382 | |
381 | 383 | func (t *Table) getBorderLeft(hint renderHint) string { |
556 | 558 | return maxColumnLength |
557 | 559 | } |
558 | 560 | |
561 | // getMergedColumnIndices returns a map of colIdx values to all the other colIdx | |
562 | // values (that are being merged) and their lengths. | |
563 | func (t *Table) getMergedColumnIndices(row rowStr, hint renderHint) map[int]map[int]bool { | |
564 | if !t.getRowConfig(hint).AutoMerge { | |
565 | return nil | |
566 | } | |
567 | ||
568 | rsp := make(map[int]map[int]bool) | |
569 | appendColumnsToResponse := func(colIdx, otherColIdx int) { | |
570 | if rsp[colIdx] == nil { | |
571 | rsp[colIdx] = make(map[int]bool) | |
572 | } | |
573 | if rsp[otherColIdx] == nil { | |
574 | rsp[otherColIdx] = make(map[int]bool) | |
575 | } | |
576 | rsp[colIdx][otherColIdx] = true | |
577 | rsp[otherColIdx][colIdx] = true | |
578 | } | |
579 | for colIdx := 0; colIdx < t.numColumns-1; colIdx++ { | |
580 | // look backward | |
581 | for otherColIdx := colIdx - 1; colIdx >= 0 && otherColIdx >= 0; otherColIdx-- { | |
582 | if row[colIdx] != row[otherColIdx] { | |
583 | break | |
584 | } | |
585 | appendColumnsToResponse(colIdx, otherColIdx) | |
586 | } | |
587 | // look forward | |
588 | for otherColIdx := colIdx + 1; colIdx < len(row) && otherColIdx < len(row); otherColIdx++ { | |
589 | if row[colIdx] != row[otherColIdx] { | |
590 | break | |
591 | } | |
592 | appendColumnsToResponse(colIdx, otherColIdx) | |
593 | } | |
594 | } | |
595 | return rsp | |
596 | } | |
597 | ||
559 | 598 | func (t *Table) getRow(rowIdx int, hint renderHint) rowStr { |
560 | 599 | switch { |
561 | 600 | case hint.isHeaderRow: |
624 | 663 | } |
625 | 664 | } |
626 | 665 | return false |
627 | } | |
628 | ||
629 | func (t *Table) initForRender() { | |
630 | // pick a default style if none was set until now | |
631 | t.Style() | |
632 | ||
633 | // initialize the column configs and normalize them | |
634 | t.initForRenderColumnConfigs() | |
635 | ||
636 | // initialize and stringify all the raw rows | |
637 | t.initForRenderRows() | |
638 | ||
639 | // find the longest continuous line in each column | |
640 | t.initForRenderColumnLengths() | |
641 | ||
642 | // generate a separator row and calculate maximum row length | |
643 | t.initForRenderRowSeparator() | |
644 | ||
645 | // reset the counter for the number of lines rendered | |
646 | t.numLinesRendered = 0 | |
647 | } | |
648 | ||
649 | func (t *Table) initForRenderColumnConfigs() { | |
650 | t.columnConfigMap = map[int]ColumnConfig{} | |
651 | for _, colCfg := range t.columnConfigs { | |
652 | // find the column number if none provided; this logic can work only if | |
653 | // a header row is present and has a column with the given name | |
654 | if colCfg.Number == 0 { | |
655 | for _, row := range t.rowsHeaderRaw { | |
656 | colCfg.Number = row.findColumnNumber(colCfg.Name) | |
657 | if colCfg.Number > 0 { | |
658 | break | |
659 | } | |
660 | } | |
661 | } | |
662 | if colCfg.Number > 0 { | |
663 | t.columnConfigMap[colCfg.Number-1] = colCfg | |
664 | } | |
665 | } | |
666 | } | |
667 | ||
668 | func (t *Table) initForRenderColumnLengths() { | |
669 | t.maxColumnLengths = make([]int, t.numColumns) | |
670 | t.parseRowForMaxColumnLengths(t.rowsHeader) | |
671 | t.parseRowForMaxColumnLengths(t.rows) | |
672 | t.parseRowForMaxColumnLengths(t.rowsFooter) | |
673 | ||
674 | // restrict the column lengths if any are over or under the limits | |
675 | for colIdx := range t.maxColumnLengths { | |
676 | maxWidth := t.getColumnWidthMax(colIdx) | |
677 | if maxWidth > 0 && t.maxColumnLengths[colIdx] > maxWidth { | |
678 | t.maxColumnLengths[colIdx] = maxWidth | |
679 | } | |
680 | minWidth := t.getColumnWidthMin(colIdx) | |
681 | if minWidth > 0 && t.maxColumnLengths[colIdx] < minWidth { | |
682 | t.maxColumnLengths[colIdx] = minWidth | |
683 | } | |
684 | } | |
685 | 666 | } |
686 | 667 | |
687 | 668 | func (t *Table) hideColumns() map[int]int { |
717 | 698 | return colIdxMap |
718 | 699 | } |
719 | 700 | |
701 | func (t *Table) initForRender() { | |
702 | // pick a default style if none was set until now | |
703 | t.Style() | |
704 | ||
705 | // initialize the column configs and normalize them | |
706 | t.initForRenderColumnConfigs() | |
707 | ||
708 | // initialize and stringify all the raw rows | |
709 | t.initForRenderRows() | |
710 | ||
711 | // find the longest continuous line in each column | |
712 | t.initForRenderColumnLengths() | |
713 | ||
714 | // generate a separator row and calculate maximum row length | |
715 | t.initForRenderRowSeparator() | |
716 | ||
717 | // reset the counter for the number of lines rendered | |
718 | t.numLinesRendered = 0 | |
719 | } | |
720 | ||
721 | func (t *Table) initForRenderColumnConfigs() { | |
722 | t.columnConfigMap = map[int]ColumnConfig{} | |
723 | for _, colCfg := range t.columnConfigs { | |
724 | // find the column number if none provided; this logic can work only if | |
725 | // a header row is present and has a column with the given name | |
726 | if colCfg.Number == 0 { | |
727 | for _, row := range t.rowsHeaderRaw { | |
728 | colCfg.Number = row.findColumnNumber(colCfg.Name) | |
729 | if colCfg.Number > 0 { | |
730 | break | |
731 | } | |
732 | } | |
733 | } | |
734 | if colCfg.Number > 0 { | |
735 | t.columnConfigMap[colCfg.Number-1] = colCfg | |
736 | } | |
737 | } | |
738 | } | |
739 | ||
740 | func (t *Table) initForRenderColumnLengths() { | |
741 | t.maxColumnLengths = make([]int, t.numColumns) | |
742 | t.parseRowForMaxColumnLengths(t.rowsHeader, renderHint{isHeaderRow: true}) | |
743 | t.parseRowForMaxColumnLengths(t.rows, renderHint{}) | |
744 | t.parseRowForMaxColumnLengths(t.rowsFooter, renderHint{isFooterRow: true}) | |
745 | ||
746 | // increase the column lengths if any are under the limits | |
747 | for colIdx := range t.maxColumnLengths { | |
748 | minWidth := t.getColumnWidthMin(colIdx) | |
749 | if minWidth > 0 && t.maxColumnLengths[colIdx] < minWidth { | |
750 | t.maxColumnLengths[colIdx] = minWidth | |
751 | } | |
752 | } | |
753 | } | |
754 | ||
720 | 755 | func (t *Table) initForRenderHideColumns() { |
721 | 756 | if !t.hasHiddenColumns() { |
722 | 757 | return |
849 | 884 | return t.indexColumn == colIdx+1 || hint.isAutoIndexColumn |
850 | 885 | } |
851 | 886 | |
852 | func (t *Table) parseRowForMaxColumnLengths(rows []rowStr) { | |
853 | for _, row := range rows { | |
887 | func (t *Table) parseRowForMaxColumnLengths(rows []rowStr, hint renderHint) { | |
888 | getMergedColumnsTotalLength := func(colIdx int, mergedColumns map[int]bool) int { | |
889 | mergedColLength := t.maxColumnLengths[colIdx] | |
890 | for otherColIdx := range mergedColumns { | |
891 | mergedColLength += t.maxColumnLengths[otherColIdx] | |
892 | } | |
893 | return mergedColLength | |
894 | } | |
895 | separatorLength := text.RuneWidthWithoutEscSequences(t.style.Box.MiddleSeparator) | |
896 | ||
897 | for rowIdx, row := range rows { | |
898 | hint.rowNumber = rowIdx + 1 | |
899 | mergedColumnsMap := t.getMergedColumnIndices(row, hint) | |
854 | 900 | for colIdx, colStr := range row { |
855 | 901 | longestLineLen := text.LongestLineLen(colStr) |
856 | if longestLineLen > t.maxColumnLengths[colIdx] { | |
902 | maxColWidth := t.getColumnWidthMax(colIdx) | |
903 | if maxColWidth > 0 && maxColWidth < longestLineLen { | |
904 | longestLineLen = maxColWidth | |
905 | } | |
906 | mergedColumnsForCol := mergedColumnsMap[colIdx] | |
907 | mergedColumnsLength := getMergedColumnsTotalLength(colIdx, mergedColumnsForCol) | |
908 | if longestLineLen > mergedColumnsLength { | |
909 | if mergedColumnsLength > 0 { | |
910 | numMergedColumns := len(mergedColumnsForCol) + 1 | |
911 | longestLineLen -= (numMergedColumns - 1) * separatorLength | |
912 | maxLengthSplitAcrossColumns := longestLineLen / numMergedColumns | |
913 | if maxLengthSplitAcrossColumns > t.maxColumnLengths[colIdx] { | |
914 | t.maxColumnLengths[colIdx] = maxLengthSplitAcrossColumns | |
915 | } | |
916 | for otherColIdx := range mergedColumnsForCol { | |
917 | if maxLengthSplitAcrossColumns > t.maxColumnLengths[otherColIdx] { | |
918 | t.maxColumnLengths[otherColIdx] = maxLengthSplitAcrossColumns | |
919 | } | |
920 | } | |
921 | } else { | |
922 | t.maxColumnLengths[colIdx] = longestLineLen | |
923 | } | |
924 | } else if maxColWidth == 0 && longestLineLen > t.maxColumnLengths[colIdx] { | |
857 | 925 | t.maxColumnLengths[colIdx] = longestLineLen |
858 | 926 | } |
859 | 927 | } |
963 | 1031 | rowWrapped := make(rowStr, len(row)) |
964 | 1032 | for colIdx, colStr := range row { |
965 | 1033 | widthEnforcer := t.columnConfigMap[colIdx].getWidthMaxEnforcer() |
966 | rowWrapped[colIdx] = widthEnforcer(colStr, t.maxColumnLengths[colIdx]) | |
1034 | maxWidth := t.getColumnWidthMax(colIdx) | |
1035 | if maxWidth == 0 { | |
1036 | maxWidth = t.maxColumnLengths[colIdx] | |
1037 | } | |
1038 | rowWrapped[colIdx] = widthEnforcer(colStr, maxWidth) | |
967 | 1039 | colNumLines := strings.Count(rowWrapped[colIdx], "\n") + 1 |
968 | 1040 | if colNumLines > colMaxLines { |
969 | 1041 | colMaxLines = colNumLines |
971 | 1043 | } |
972 | 1044 | return colMaxLines, rowWrapped |
973 | 1045 | } |
974 | ||
975 | // renderHint has hints for the Render*() logic | |
976 | type renderHint struct { | |
977 | isAutoIndexColumn bool // auto-index column? | |
978 | isAutoIndexRow bool // auto-index row? | |
979 | isBorderBottom bool // bottom-border? | |
980 | isBorderTop bool // top-border? | |
981 | isFirstRow bool // first-row of header/footer/regular-rows? | |
982 | isFooterRow bool // footer row? | |
983 | isHeaderRow bool // header row? | |
984 | isLastLineOfRow bool // last-line of the current row? | |
985 | isLastRow bool // last-row of header/footer/regular-rows? | |
986 | isSeparatorRow bool // separator row? | |
987 | rowLineNumber int // the line number for a multi-line row | |
988 | rowNumber int // the row number/index | |
989 | } | |
990 | ||
991 | func (h *renderHint) isRegularRow() bool { | |
992 | return !h.isHeaderRow && !h.isFooterRow | |
993 | } | |
994 | ||
995 | func (h *renderHint) isRegularNonSeparatorRow() bool { | |
996 | return !h.isHeaderRow && !h.isFooterRow && !h.isSeparatorRow | |
997 | } | |
998 | ||
999 | func (h *renderHint) isHeaderOrFooterSeparator() bool { | |
1000 | return h.isSeparatorRow && !h.isBorderBottom && !h.isBorderTop && | |
1001 | ((h.isHeaderRow && !h.isLastRow) || (h.isFooterRow && (!h.isFirstRow || h.rowNumber > 0))) | |
1002 | } | |
1003 | ||
1004 | func (h *renderHint) isLastLineOfLastRow() bool { | |
1005 | return h.isLastLineOfRow && h.isLastRow | |
1006 | } |
0 | # text | |
1 | ||
2 | [![Go Reference](https://pkg.go.dev/badge/github.com/jedib0t/go-pretty/v6.svg)](https://pkg.go.dev/github.com/jedib0t/go-pretty/v6/text) | |
3 | ||
4 | Package with utility functions to manipulate strings/text. | |
5 | ||
6 | Used heavily in the other packages in this repo ([list](../list), | |
7 | [progress](../progress), and [table](../table)).⏎ |
0 | package common | |
1 | ||
2 | import "fmt" | |
3 | ||
4 | type Warnings struct { | |
5 | List []error | |
6 | Verbose bool | |
7 | } | |
8 | ||
9 | func (w *Warnings) Add(err error) { | |
10 | w.List = append(w.List, err) | |
11 | } | |
12 | ||
13 | func (w *Warnings) Reference() error { | |
14 | if len(w.List) > 0 { | |
15 | return w | |
16 | } | |
17 | return nil | |
18 | } | |
19 | ||
20 | func (w *Warnings) Error() string { | |
21 | if w.Verbose { | |
22 | str := "" | |
23 | for i, e := range w.List { | |
24 | str += fmt.Sprintf("\tError %d: %s\n", i, e.Error()) | |
25 | } | |
26 | return str | |
27 | } | |
28 | return fmt.Sprintf("Number of warnings: %v", len(w.List)) | |
29 | } |
195 | 195 | ## explicit; go 1.15 |
196 | 196 | github.com/gobwas/ws |
197 | 197 | github.com/gobwas/ws/wsutil |
198 | # github.com/gofrs/uuid v4.3.0+incompatible | |
198 | # github.com/gofrs/uuid v4.3.1+incompatible | |
199 | 199 | ## explicit |
200 | 200 | github.com/gofrs/uuid |
201 | 201 | # github.com/golang/protobuf v1.5.2 |
268 | 268 | ## explicit |
269 | 269 | github.com/jcmturner/gofork/encoding/asn1 |
270 | 270 | github.com/jcmturner/gofork/x/crypto/pbkdf2 |
271 | # github.com/jedib0t/go-pretty/v6 v6.4.0 | |
271 | # github.com/jedib0t/go-pretty/v6 v6.4.2 | |
272 | 272 | ## explicit; go 1.16 |
273 | 273 | github.com/jedib0t/go-pretty/v6/table |
274 | 274 | github.com/jedib0t/go-pretty/v6/text |
347 | 347 | # github.com/rivo/uniseg v0.2.0 |
348 | 348 | ## explicit; go 1.12 |
349 | 349 | github.com/rivo/uniseg |
350 | # github.com/shirou/gopsutil/v3 v3.22.9 | |
350 | # github.com/shirou/gopsutil/v3 v3.22.10 | |
351 | 351 | ## explicit; go 1.15 |
352 | 352 | github.com/shirou/gopsutil/v3/internal/common |
353 | 353 | github.com/shirou/gopsutil/v3/mem |