github.com/iDigitalFlame/xmt@v0.5.4/cmd/asm.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 cmd 18 19 import ( 20 "context" 21 "time" 22 ) 23 24 // Assembly is a struct that can be used to contain and run shellcode on Windows devices. 25 // This struct has many of the functionalities of the standard 'cmd.Program' function. 26 // 27 // The 'SetParent*' function will attempt to set the target that runs the shellcode. 28 // If none are specified, the shellcode will be injected into the current process. 29 // 30 // This struct only works on Windows devices. 31 // All calls on non-Windows devices will return 'ErrNoWindows'. 32 // 33 // TODO(dij): Add Linux shellcode execution support. 34 type Assembly struct { 35 Data []byte 36 t thread 37 Timeout time.Duration 38 } 39 40 // Run will start the Assembly thread and wait until it completes. This function 41 // will return the same errors as the 'Start' function if they occur or the 42 // 'Wait' function if any errors occur during thread runtime. 43 // 44 // Always returns nil on non-Windows devices. 45 func (a *Assembly) Run() error { 46 if err := a.Start(); err != nil { 47 return err 48 } 49 return a.Wait() 50 } 51 52 // Stop will attempt to terminate the currently running thread. 53 // 54 // Always returns nil on non-Windows devices. 55 func (a *Assembly) Stop() error { 56 return a.t.Stop() 57 } 58 59 // Wait will block until the thread completes or is terminated by a call to 60 // Stop. 61 // 62 // This function will return 'ErrNotStarted' if the thread has not been started. 63 func (a *Assembly) Wait() error { 64 if !a.t.Running() { 65 if err := a.Start(); err != nil { 66 return err 67 } 68 } 69 return a.t.Wait() 70 } 71 72 // NewAsm creates a new Assembly thread instance that uses the supplied byte 73 // array as the Data buffer. Similar to '&Assembly{Data: b}'. 74 func NewAsm(b []byte) *Assembly { 75 return &Assembly{Data: b} 76 } 77 78 // Running returns true if the current thread is running, false otherwise. 79 func (a *Assembly) Running() bool { 80 return a.t.Running() 81 } 82 83 // Release will attempt to release the resources for this Assembly thread, 84 // including handles. 85 // 86 // After the first call to this function, all other function calls will fail 87 // with errors. Repeated calls to this function return nil and are a NOP. 88 func (a *Assembly) Release() error { 89 return a.t.Release() 90 } 91 92 // SetSuspended will delay the execution of this thread and will put the 93 // thread in a suspended state until it is resumed using a Resume call. 94 // 95 // This function has no effect if the device is not running Windows. 96 func (a *Assembly) SetSuspended(s bool) { 97 a.t.SetSuspended(s) 98 } 99 100 // ExitCode returns the Exit Code of the thread. If the thread is still running or 101 // has not been started, this function returns an 'ErrNotCompleted' error. 102 func (a *Assembly) ExitCode() (int32, error) { 103 return a.t.ExitCode() 104 } 105 106 // Handle returns the handle of the current running thread. The return is an uintptr 107 // that can converted into a Handle. 108 // 109 // This function returns an error if the thread was not started. The handle is 110 // not expected to be valid after the thread exits or is terminated. 111 func (a *Assembly) Handle() (uintptr, error) { 112 return a.t.Handle() 113 } 114 115 // Location returns the in-memory Location of the current Assembly thread, if running. 116 // The return is an uintptr that can converted into a Handle. 117 // 118 // This function returns an error if the Assembly thread was not started. The 119 // handle is not expected to be valid after the thread exits or is terminated. 120 func (a *Assembly) Location() (uintptr, error) { 121 return a.t.Location() 122 } 123 124 // NewAsmContext creates a new Code thread instance that uses the supplied byte 125 // array as the Data buffer. 126 // 127 // This function accepts a context that can be used to control the cancellation 128 // of the thread. 129 func NewAsmContext(x context.Context, b []byte) *Assembly { 130 return &Assembly{Data: b, t: threadInit(x)} 131 }