github.com/iDigitalFlame/xmt@v0.5.4/device/xy_nix_crypt.go (about) 1 //go:build !windows && !js && crypt 2 // +build !windows,!js,crypt 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 device 21 22 import ( 23 "io" 24 "os" 25 "runtime" 26 "strings" 27 28 "github.com/iDigitalFlame/xmt/cmd/filter" 29 "github.com/iDigitalFlame/xmt/data" 30 "github.com/iDigitalFlame/xmt/util" 31 "github.com/iDigitalFlame/xmt/util/crypt" 32 "github.com/iDigitalFlame/xmt/util/xerr" 33 ) 34 35 var ( 36 // Shell is the default machine specific command shell. 37 Shell = crypt.Get(32) // /bin/sh 38 // ShellArgs is the default machine specific command shell arguments to run 39 // commands. 40 ShellArgs = "-c" 41 // PowerShell is the path to the PowerShell binary, which is based on the 42 // underlying OS type. 43 PowerShell = crypt.Get(33) // pwsh 44 ) 45 46 // IsDebugged returns true if the current process is attached by a debugger. 47 func IsDebugged() bool { 48 for _, e := range data.ReadSplit(crypt.Get(34), "\n") { // /proc/self/status 49 if len(e) <= 9 { 50 continue 51 } 52 if e[9] == ':' && e[8] == 'd' && e[0] == 'T' && e[1] == 'r' && e[5] == 'r' { 53 return e[len(e)-1] != '0' && e[len(e)-2] != ' ' && e[len(e)-2] != 9 && e[len(e)-2] != '\t' 54 } 55 } 56 return false 57 } 58 59 // UserHomeDir returns the current user's home directory. 60 // 61 // On Unix, including macOS, it returns the $HOME environment variable. 62 // On Windows, it returns %USERPROFILE%. 63 // On Plan 9, it returns the $home environment variable. 64 // On JS/WASM it returns and empty string. 65 // 66 // Golang compatibility helper function. 67 func UserHomeDir() string { 68 if OS == Plan9 { 69 return os.Getenv(strings.ToLower(crypt.Get(35))) // HOME 70 } 71 if v := os.Getenv(crypt.Get(35)); len(v) > 0 { // HOME 72 return v 73 } 74 switch OS { 75 case IOS: 76 return "/" 77 case Android: 78 return os.Getenv(crypt.Get(36)) // /sdcard 79 } 80 return "" 81 } 82 83 // Logins returns an array that contains information about current logged 84 // in users. 85 // 86 // This call is OS-independent but many contain invalid session types. 87 // 88 // Always returns an EINVAL on WSAM/JS. 89 func Logins() ([]Login, error) { 90 b, err := data.ReadFile(crypt.Get(37)) // /var/run/utmp 91 if err != nil { 92 return nil, err 93 } 94 return readWhoEntries(b), nil 95 } 96 97 // Mounts attempts to get the mount points on the local device. 98 // 99 // On Windows devices, this is the drive letters available, otherwise on nix* 100 // systems, this will be the mount points on the system. 101 // 102 // The return result (if no errors occurred) will be a string list of all the 103 // mount points (or Windows drive letters). 104 func Mounts() ([]string, error) { 105 // 0 - READONLY 106 f, err := os.OpenFile(crypt.Get(38), 0, 0) // /proc/self/mounts 107 if err != nil { 108 // 0 - READONLY 109 if f, err = os.OpenFile(crypt.Get(39), 0, 0); err != nil { // /etc/mtab 110 return nil, xerr.Wrap("cannot find mounts", err) 111 } 112 } 113 b, err := data.ReadAll(f) 114 if f.Close(); err != nil { 115 return nil, err 116 } 117 var ( 118 e = strings.Split(string(b), "\n") 119 m = make([]string, 0, len(e)) 120 ) 121 for _, v := range e { 122 x, l := 0, 0 123 for s := 0; s < 2; s++ { 124 for l = x; x < len(v)-1 && v[x] != ' ' && v[x] != 9; x++ { 125 } 126 if x < len(v)-1 && s == 0 { 127 x++ 128 } 129 } 130 if l == x { 131 continue 132 } 133 m = append(m, v[l:x]) 134 } 135 return m, nil 136 } 137 138 // DumpProcess will attempt to copy the memory of the targeted Filter to the 139 // supplied Writer. This fill select the first process that matches the Filter. 140 // 141 // If the Filter is nil or empty or if an error occurs during reading/writing 142 // an error will be returned. 143 // 144 // This function may fail if attempting to dump a process that is a different CPU 145 // architecture that the host process. 146 func DumpProcess(f *filter.Filter, w io.Writer) error { 147 if f.Empty() { 148 return filter.ErrNoProcessFound 149 } 150 p, err := f.SelectFunc(nil) 151 if err != nil { 152 return err 153 } 154 v := crypt.Get(11) + util.Uitoa(uint64(p)) // /proc/ 155 b, err := data.ReadFile(v + crypt.Get(40)) // /maps 156 if err != nil { 157 return err 158 } 159 // 0 - READONLY 160 d, err := os.OpenFile(v+crypt.Get(41), 0, 0) // /mem 161 if err != nil { 162 return err 163 } 164 for _, e := range strings.Split(string(b), "\n") { 165 if err = parseLine(e, d, w); err != nil { 166 break 167 } 168 } 169 d.Close() 170 runtime.GC() 171 FreeOSMemory() 172 return err 173 }