github.com/iDigitalFlame/xmt@v0.5.4/c2/task/result/v_no_implant.go (about) 1 //go:build !implant 2 // +build !implant 3 4 // Copyright (C) 2020 - 2023 iDigitalFlame 5 // 6 // This program is free software: you can redistribute it and/or modify 7 // it under the terms of the GNU General Public License as published by 8 // the Free Software Foundation, either version 3 of the License, or 9 // any later version. 10 // 11 // This program is distributed in the hope that it will be useful, 12 // but WITHOUT ANY WARRANTY; without even the implied warranty of 13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 // GNU General Public License for more details. 15 // 16 // You should have received a copy of the GNU General Public License 17 // along with this program. If not, see <https://www.gnu.org/licenses/>. 18 // 19 20 // Package result contains many helper functions to gather matching output 21 // from Job result packets. 22 package result 23 24 import ( 25 "io" 26 "os" 27 "time" 28 29 "github.com/iDigitalFlame/xmt/c2" 30 "github.com/iDigitalFlame/xmt/cmd" 31 "github.com/iDigitalFlame/xmt/com" 32 "github.com/iDigitalFlame/xmt/data" 33 "github.com/iDigitalFlame/xmt/device" 34 "github.com/iDigitalFlame/xmt/device/regedit" 35 ) 36 37 // Window is a struct that represents a Windows Window. The handles are the same 38 // for the duration of the Window's existence. 39 // 40 // Copied here from the winapi package. 41 type Window struct { 42 _ [0]func() 43 Name string 44 Flags uint8 45 Handle uintptr 46 X, Y int32 47 Width, Height int32 48 } 49 type fileInfo struct { 50 _ [0]func() 51 mod time.Time 52 name string 53 size int64 54 mode os.FileMode 55 } 56 57 // FuncEntry is a simple struct that is used to describe the current status of 58 // function mappings. This struct is returned by a call to 'FuncRemaps' in a 59 // slice of current remaps. 60 // 61 // Copied here from the winapi package. 62 type FuncEntry struct { 63 _ [0]func() 64 Hash uint32 65 Swapped uintptr 66 Original uintptr 67 } 68 69 func (f fileInfo) Size() int64 { 70 return f.size 71 } 72 func (f fileInfo) IsDir() bool { 73 return f.mode.IsDir() 74 } 75 func (f fileInfo) Name() string { 76 return f.name 77 } 78 func (fileInfo) Sys() interface{} { 79 return nil 80 } 81 82 // IsMinimized returns true if the Window state was minimized at the time of 83 // discovery. 84 func (w Window) IsMinimized() bool { 85 return w.Flags&0x2 != 0 86 } 87 88 // IsMaximized returns true if the Window state was maximized at the time of 89 // discovery. 90 func (w Window) IsMaximized() bool { 91 return w.Flags&0x1 != 0 92 } 93 func (f fileInfo) Mode() os.FileMode { 94 return f.mode 95 } 96 func (f fileInfo) ModTime() time.Time { 97 return f.mod 98 } 99 100 // Pwd will parse the RvResult Packet from a MvPwd task. 101 // 102 // The return result is the current directory the client is located in. 103 // 104 // This function returns an error if any reading errors occur, the Packet is not 105 // in the expected format or the Packet is nil or empty. 106 func Pwd(n *com.Packet) (string, error) { 107 if n == nil || n.Empty() || n.Flags&com.FlagError != 0 { 108 return "", c2.ErrMalformedPacket 109 } 110 return n.StringVal() 111 } 112 113 // Spawn will parse the RvResult Packet from a MvSpawn task. 114 // 115 // The return result is the new PID of the resulting Spawn operation. 116 // 117 // This function returns an error if any reading errors occur, the Packet is not 118 // in the expected format or the Packet is nil or empty. 119 func Spawn(n *com.Packet) (uint32, error) { 120 if n == nil || n.Empty() || n.Flags&com.FlagError != 0 { 121 return 0, c2.ErrMalformedPacket 122 } 123 return n.Uint32() 124 } 125 126 // CheckDLL will parse the RvResult Packet from a TvCheck task. 127 // 128 // The return result is true if the DLL provided is NOT hooked. A return value 129 // of false indicates that the DLL memory space differs from the on-disk value, 130 // which is an indicator of hooks. 131 // 132 // This function returns an error if any reading errors occur, the Packet is not 133 // in the expected format or the Packet is nil or empty. 134 func CheckDLL(n *com.Packet) (bool, error) { 135 if n == nil || n.Empty() || n.Flags&com.FlagError != 0 { 136 return false, c2.ErrMalformedPacket 137 } 138 return n.Bool() 139 } 140 141 // Mounts will parse the RvResult Packet from a MvMounts task. 142 // 143 // The return result is a string list of all the exposed mount points on the 144 // client (drive letters on Windows). 145 // 146 // This function returns an error if any reading errors occur, the Packet is not 147 // in the expected format or the Packet is nil or empty. 148 func Mounts(n *com.Packet) ([]string, error) { 149 if n == nil || n.Empty() || n.Flags&com.FlagError != 0 { 150 return nil, c2.ErrMalformedPacket 151 } 152 var s []string 153 return s, data.ReadStringList(n, &s) 154 } 155 156 // IsDebugged will parse the RvResult Packet from a TvCheckDebug task. 157 // 158 // The return result is True if a debugger is detected, false otherwise. 159 // 160 // This function returns an error if any reading errors occur, the Packet is not 161 // in the expected format or the Packet is nil or empty. 162 func IsDebugged(n *com.Packet) (bool, error) { 163 if n == nil || n.Empty() || n.Flags&com.FlagError != 0 { 164 return false, c2.ErrMalformedPacket 165 } 166 return n.Bool() 167 } 168 169 // Ls will parse the RvResult Packet from a MvList task. 170 // 171 // The return result is a slice of FileInfo interfaces that will return the 172 // data of the directory targeted. 173 // 174 // This function returns an error if any reading errors occur, the Packet is not 175 // in the expected format or the Packet is nil or empty. 176 func Ls(n *com.Packet) ([]os.FileInfo, error) { 177 if n == nil || n.Empty() || n.Flags&com.FlagError != 0 { 178 return nil, c2.ErrMalformedPacket 179 } 180 c, err := n.Uint32() 181 if err != nil || c == 0 { 182 return nil, err 183 } 184 e := make([]os.FileInfo, c) 185 for i := range e { 186 var v fileInfo 187 if err = n.ReadString(&v.name); err != nil { 188 return nil, err 189 } 190 if err = n.ReadUint32((*uint32)(&v.mode)); err != nil { 191 return nil, err 192 } 193 if err = n.ReadInt64(&v.size); err != nil { 194 return nil, err 195 } 196 t, err := n.Int64() 197 if err != nil { 198 return nil, err 199 } 200 v.mod = time.Unix(t, 0) 201 e[i] = v 202 } 203 return e, nil 204 } 205 206 // Netcat will parse the RvResult Packet from a TvNetcat task. 207 // 208 // The return result is a Reader with the resulting output data from the read 209 // request. If reading was not done, this will just return nil. 210 // 211 // This function returns an error if any reading errors occur, the Packet is not 212 // in the expected format or the Packet is nil. 213 func Netcat(n *com.Packet) (io.Reader, error) { 214 if n == nil || n.Flags&com.FlagError != 0 { 215 return nil, c2.ErrMalformedPacket 216 } 217 if n.Empty() { 218 return nil, nil 219 } 220 return n, nil 221 } 222 223 // WindowList will parse the RvResult Packet from a TvWindows task. 224 // 225 // The return result is a slice of 'Window' structs that will indicate 226 // the current Windows open on the target device. 227 // 228 // This function returns an error if any reading errors occur, the Packet is not 229 // in the expected format or the Packet is nil or empty. 230 func WindowList(n *com.Packet) ([]Window, error) { 231 if n == nil || n.Empty() || n.Flags&com.FlagError != 0 { 232 return nil, c2.ErrMalformedPacket 233 } 234 c, err := n.Uint32() 235 if err != nil { 236 return nil, err 237 } 238 e := make([]Window, c) 239 for i := range e { 240 if err = e[i].UnmarshalStream(n); err != nil { 241 return nil, err 242 } 243 } 244 return e, nil 245 } 246 247 // ScreenShot will parse the RvResult Packet from a TvScreenShot task. 248 // 249 // The return result is a Reader with the resulting screenshot data encoded as 250 // a PNG image inside. (This can be directly written to disk as a PNG file). 251 // 252 // This function returns an error if any reading errors occur, the Packet is not 253 // in the expected format or the Packet is nil or empty. 254 func ScreenShot(n *com.Packet) (io.Reader, error) { 255 return ProcessDump(n) 256 } 257 258 // Script will parse the RvResult Packet from a MvScript task. 259 // 260 // The return result is a slice of the resulting Packet output. Some flags may 261 // have their error values set, so it is important to check beforehand. 262 // 263 // This function returns an error if any reading errors occur, the Packet is not 264 // in the expected format or the Packet is nil or empty. 265 func Script(n *com.Packet) ([]*com.Packet, error) { 266 if n == nil || n.Empty() || n.Flags&com.FlagError != 0 { 267 return nil, c2.ErrMalformedPacket 268 } 269 var ( 270 d []byte 271 r []*com.Packet 272 e bool 273 err error 274 ) 275 for err == nil { 276 var v com.Packet 277 if err = n.ReadUint8(&v.ID); err != nil { 278 break 279 } 280 if err = n.ReadBool(&e); err != nil { 281 break 282 } 283 if !e { 284 var m string 285 if err = n.ReadString(&m); err != nil { 286 break 287 } 288 v.Flags = com.FlagError 289 v.WriteString(m) 290 r = append(r, &v) 291 continue 292 } 293 if err = n.ReadBytes(&d); err != nil && err != io.EOF { 294 break 295 } 296 v.Grow(len(d)) 297 v.Write(d) 298 d, r, err = nil, append(r, &v), nil 299 } 300 if err == io.EOF { 301 return r, nil 302 } 303 return r, err 304 } 305 306 // ProcessDump will parse the RvResult Packet from a TvProcDump task. 307 // 308 // The return result is a Reader with the resulting dump data inside. 309 // 310 // This function returns an error if any reading errors occur, the Packet is not 311 // in the expected format or the Packet is nil or empty. 312 func ProcessDump(n *com.Packet) (io.Reader, error) { 313 if n == nil || n.Empty() || n.Flags&com.FlagError != 0 { 314 return nil, c2.ErrMalformedPacket 315 } 316 return n, nil 317 } 318 319 // Upload will parse the RvResult Packet from a TvUpload task. 320 // 321 // The return result is the expended full file path on the host as a string, and 322 // the resulting count of bytes written to disk. 323 // 324 // This function returns an error if any reading errors occur, the Packet is not 325 // in the expected format or the Packet is nil or empty. 326 func Upload(n *com.Packet) (string, uint64, error) { 327 if n == nil || n.Empty() || n.Flags&com.FlagError != 0 { 328 return "", 0, c2.ErrMalformedPacket 329 } 330 var ( 331 s string 332 c uint64 333 err = n.ReadString(&s) 334 ) 335 if err != nil { 336 return "", 0, err 337 } 338 if err = n.ReadUint64(&c); err != nil { 339 return "", 0, err 340 } 341 return s, c, nil 342 } 343 344 // Whoami will parse the RvResult Packet from a MvWhoami task. 345 // 346 // The return result is the current username the client is running under and the 347 // path if the current Process. 348 // 349 // This function returns an error if any reading errors occur, the Packet is not 350 // in the expected format or the Packet is nil or empty. 351 func Whoami(n *com.Packet) (string, string, error) { 352 if n == nil || n.Empty() || n.Flags&com.FlagError != 0 { 353 return "", "", c2.ErrMalformedPacket 354 } 355 var u, p string 356 if err := n.ReadString(&u); err != nil { 357 return "", "", err 358 } 359 if err := n.ReadString(&p); err != nil { 360 return "", "", err 361 } 362 return u, p, nil 363 } 364 365 // UnmarshalStream transforms this struct from a binary format that is read from 366 // the supplied data.Reader. 367 func (w *Window) UnmarshalStream(r data.Reader) error { 368 v, err := r.Uint64() 369 if err != nil { 370 return err 371 } 372 w.Handle = uintptr(v) 373 if err = r.ReadString(&w.Name); err != nil { 374 return err 375 } 376 if err = r.ReadUint8(&w.Flags); err != nil { 377 return err 378 } 379 if err = r.ReadInt32(&w.X); err != nil { 380 return err 381 } 382 if err = r.ReadInt32(&w.Y); err != nil { 383 return err 384 } 385 if err = r.ReadInt32(&w.Width); err != nil { 386 return err 387 } 388 return r.ReadInt32(&w.Height) 389 } 390 391 // FuncRemapList will parse the RvResult Packet from a TvFuncMapList task. 392 // 393 // The return result is a slice of 'FuncEntry' structs that will indicate 394 // the current function mappings on the target device. 395 // 396 // This function returns an error if any reading errors occur, the Packet is not 397 // in the expected format or the Packet is nil or empty. 398 func FuncRemapList(n *com.Packet) ([]FuncEntry, error) { 399 if n == nil || n.Empty() || n.Flags&com.FlagError != 0 { 400 return nil, c2.ErrMalformedPacket 401 } 402 c, err := n.Uint32() 403 if err != nil { 404 return nil, err 405 } 406 e := make([]FuncEntry, c) 407 for i := range e { 408 if err = e[i].UnmarshalStream(n); err != nil { 409 return nil, err 410 } 411 } 412 return e, nil 413 } 414 415 // UserLogins will parse the RvResult Packet from a TvLogins task. 416 // 417 // The return result is a slice of 'device.Login' structs that will indicate 418 // the current active Sessions (Logins) on the target device. 419 // 420 // This function returns an error if any reading errors occur, the Packet is not 421 // in the expected format or the Packet is nil or empty. 422 func UserLogins(n *com.Packet) ([]device.Login, error) { 423 if n == nil || n.Empty() || n.Flags&com.FlagError != 0 { 424 return nil, c2.ErrMalformedPacket 425 } 426 c, err := n.Uint16() 427 if err != nil { 428 return nil, err 429 } 430 e := make([]device.Login, c) 431 for i := range e { 432 if err = e[i].UnmarshalStream(n); err != nil { 433 return nil, err 434 } 435 } 436 return e, nil 437 } 438 439 // DLL will parse the RvResult Packet from a TvDLL task. 440 // 441 // The return result is a handle to the memory location of the DLL (as an 442 // uintptr), the resulting PID of the DLL "host" and the exit code of the 443 // primary thread (if wait was specified, otherwise this is zero). 444 // 445 // This function returns an error if any reading errors occur, the Packet is not 446 // in the expected format or the Packet is nil or empty. 447 func DLL(n *com.Packet) (uintptr, uint32, int32, error) { 448 return Assembly(n) 449 } 450 451 // UnmarshalStream transforms this struct from a binary format that is read from 452 // the supplied data.Reader. 453 func (e *FuncEntry) UnmarshalStream(r data.Reader) error { 454 if err := r.ReadUint32(&e.Hash); err != nil { 455 return err 456 } 457 v, err := r.Uint64() 458 if err != nil { 459 return err 460 } 461 e.Original = uintptr(v) 462 if v, err = r.Uint64(); err != nil { 463 return err 464 } 465 e.Swapped = uintptr(v) 466 return nil 467 } 468 469 // ProcessList will parse the RvResult Packet from a TvProcList task. 470 // 471 // The return result is a slice of 'cmd.ProcessInfo' structs that will indicate 472 // the current processes running on the target device. 473 // 474 // This function returns an error if any reading errors occur, the Packet is not 475 // in the expected format or the Packet is nil or empty. 476 func ProcessList(n *com.Packet) ([]cmd.ProcessInfo, error) { 477 if n == nil || n.Empty() || n.Flags&com.FlagError != 0 { 478 return nil, c2.ErrMalformedPacket 479 } 480 c, err := n.Uint32() 481 if err != nil { 482 return nil, err 483 } 484 e := make([]cmd.ProcessInfo, c) 485 for i := range e { 486 if err = e[i].UnmarshalStream(n); err != nil { 487 return nil, err 488 } 489 } 490 return e, nil 491 } 492 493 // SystemIO will parse the RvResult Packet from a TvSystemIO task. 494 // 495 // The return result is dependent on the resulting operation. If the result is 496 // from a 'Move' or 'Copy' operation, this will return the resulting path and 497 // new file size. 498 // 499 // The boolean value will return true if the result was a valid command that 500 // returns no output, such as a Touch, Delete or Kill operation. 501 // 502 // This function returns an error if any reading errors occur, the Packet is not 503 // in the expected format or the Packet is nil or empty. 504 func SystemIO(n *com.Packet) (string, uint64, bool, error) { 505 if n == nil || n.Empty() || n.Flags&com.FlagError != 0 { 506 return "", 0, false, c2.ErrMalformedPacket 507 } 508 o, err := n.Uint8() 509 if err != nil { 510 return "", 0, false, c2.ErrMalformedPacket 511 } 512 if o != 2 && o != 3 { 513 return "", 0, true, nil 514 } 515 var ( 516 i uint64 517 v string 518 ) 519 if err = n.ReadString(&v); err != nil { 520 return "", 0, false, err 521 } 522 if err = n.ReadUint64(&i); err != nil { 523 return "", 0, false, err 524 } 525 return v, i, true, nil 526 } 527 528 // Registry will parse the RvResult Packet from a TvRegistry task. 529 // 530 // The return result is dependent on the resulting operation. If the result is 531 // from a 'RegLs' or 'RegGet' operation, this will return the resulting entries 532 // found (only one entry if this was a Get operation). 533 // 534 // The boolean value will return true if the result was a valid registry command 535 // that returns no output, such as a Set operation. 536 // 537 // This function returns an error if any reading errors occur, the Packet is not 538 // in the expected format or the Packet is nil or empty. 539 func Registry(n *com.Packet) ([]regedit.Entry, bool, error) { 540 if n == nil || n.Empty() || n.Flags&com.FlagError != 0 { 541 return nil, false, c2.ErrMalformedPacket 542 } 543 o, err := n.Uint8() 544 if err != nil { 545 return nil, false, c2.ErrMalformedPacket 546 } 547 if o > 1 { 548 return nil, o < 13, nil 549 } 550 var c uint32 551 if o == 0 { 552 if err = n.ReadUint32(&c); err != nil { 553 return nil, false, err 554 } 555 if c == 0 { 556 return nil, false, nil 557 } 558 } else { 559 c = 1 560 } 561 r := make([]regedit.Entry, c) 562 for i := range r { 563 if err = r[i].UnmarshalStream(n); err != nil { 564 return nil, false, err 565 } 566 } 567 return r, true, nil 568 } 569 570 // Pull will parse the RvResult Packet from a TvPull task. 571 // 572 // The return result is the expended full file path on the host as a string, and 573 // the resulting count of bytes written to disk. 574 // 575 // If the Pull path was empty, the returned results will instead be returned 576 // via the supplied Reader, which will not be nil. When this occurs the string 577 // and size values will be "" and zero. 578 // 579 // This function returns an error if any reading errors occur, the Packet is not 580 // in the expected format or the Packet is nil or empty. 581 func Pull(n *com.Packet) (string, uint64, io.Reader, error) { 582 if n == nil || n.Empty() || n.Flags&com.FlagError != 0 { 583 return "", 0, nil, c2.ErrMalformedPacket 584 } 585 var ( 586 s string 587 c uint64 588 err = n.ReadString(&s) 589 ) 590 if err != nil { 591 return "", 0, nil, err 592 } 593 if err = n.ReadUint64(&c); err != nil { 594 return "", 0, nil, err 595 } 596 if len(s) == 0 && c == 0 { 597 return "", 0, n, nil 598 } 599 return s, c, nil, nil 600 } 601 602 // Assembly will parse the RvResult Packet from a TvAssembly task. 603 // 604 // The return result is a handle to the memory location of the Assembly code (as 605 // an uintptr), the resulting PID of the Assembly "host" and the exit code of the 606 // primary thread (if wait was specified, otherwise this is zero). 607 // 608 // This function returns an error if any reading errors occur, the Packet is not 609 // in the expected format or the Packet is nil or empty. 610 func Assembly(n *com.Packet) (uintptr, uint32, int32, error) { 611 if n == nil || n.Empty() || n.Flags&com.FlagError != 0 { 612 return 0, 0, 0, c2.ErrMalformedPacket 613 } 614 var ( 615 h uint64 616 p uint32 617 x int32 618 err = n.ReadUint64(&h) 619 ) 620 if err != nil { 621 return 0, 0, 0, err 622 } 623 if err = n.ReadUint32(&p); err != nil { 624 return 0, 0, 0, err 625 } 626 if err = n.ReadInt32(&x); err != nil { 627 return 0, 0, 0, err 628 } 629 return uintptr(h), p, x, nil 630 } 631 632 // Zombie will parse the RvResult Packet from a TvZombie task. 633 // 634 // The return result is the spawned PID of the new process and the resulting 635 // exit code and Stdout/Stderr data (if wait was specified, otherwise this the 636 // return code is zero and the reader will be empty). 637 // 638 // This function returns an error if any reading errors occur, the Packet is not 639 // in the expected format or the Packet is nil or empty. 640 func Zombie(n *com.Packet) (uint32, int32, io.Reader, error) { 641 return Process(n) 642 } 643 644 // Process will parse the RvResult Packet from a TvExecute task. 645 // 646 // The return result is the spawned PID of the new process and the resulting 647 // exit code and Stdout/Stderr data (if wait was specified, otherwise this the 648 // return code is zero and the reader will be empty). 649 // 650 // This function returns an error if any reading errors occur, the Packet is not 651 // in the expected format or the Packet is nil or empty. 652 func Process(n *com.Packet) (uint32, int32, io.Reader, error) { 653 if n == nil || n.Empty() || n.Flags&com.FlagError != 0 { 654 return 0, 0, nil, c2.ErrMalformedPacket 655 } 656 var ( 657 p uint32 658 x int32 659 err = n.ReadUint32(&p) 660 ) 661 if err != nil { 662 return 0, 0, nil, err 663 } 664 if err = n.ReadInt32(&x); err != nil { 665 return 0, 0, nil, err 666 } 667 return p, x, n, nil 668 } 669 670 // PullExec will parse the RvResult Packet from a TvPullExecute task. 671 // 672 // The return result is the spawned PID of the new process and the resulting 673 // exit code and Stdout/Stderr data (if wait was specified, otherwise this the 674 // return code is zero and the reader will be empty). 675 // 676 // This function returns an error if any reading errors occur, the Packet is not 677 // in the expected format or the Packet is nil or empty. 678 func PullExec(n *com.Packet) (uint32, int32, io.Reader, error) { 679 return Process(n) 680 } 681 682 // UserProcessList will parse the RvResult Packet from a TvLoginsProc task. 683 // 684 // The return result is a slice of 'cmd.ProcessInfo' structs that will indicate 685 // the current processes running on the target device. 686 // 687 // This function returns an error if any reading errors occur, the Packet is not 688 // in the expected format or the Packet is nil or empty. 689 func UserProcessList(n *com.Packet) ([]cmd.ProcessInfo, error) { 690 return ProcessList(n) 691 } 692 693 // Download will parse the RvResult Packet from a TvDownload task. 694 // 695 // The return result is the expended full file path on the host as a string, 696 // a boolean representing if the path requested is a directory (true if the path 697 // is a directory, false otherwise), the size of the data in bytes (zero if the 698 // target is a directory) and a reader with the resulting file data (empty if 699 // the target is a directory). 700 // 701 // This function returns an error if any reading errors occur, the Packet is not 702 // in the expected format or the Packet is nil or empty. 703 func Download(n *com.Packet) (string, bool, uint64, io.Reader, error) { 704 if n == nil || n.Empty() || n.Flags&com.FlagError != 0 { 705 return "", false, 0, nil, c2.ErrMalformedPacket 706 } 707 var ( 708 s string 709 d bool 710 c uint64 711 err = n.ReadString(&s) 712 ) 713 if err != nil { 714 return "", false, 0, nil, err 715 } 716 if err = n.ReadBool(&d); err != nil { 717 return "", false, 0, nil, err 718 } 719 if err = n.ReadUint64(&c); err != nil { 720 return "", false, 0, nil, err 721 } 722 return s, d, c, n, nil 723 }