├── .gitignore ├── data.go ├── demo ├── demo-linux ├── demo-windows.exe ├── demo_darwin ├── machine.go ├── run1.png └── run2.png ├── go.mod ├── go.sum ├── goos ├── common.go ├── linux.go ├── mac.go └── windows.go ├── interface.go ├── machine_darwin.go ├── machine_linux.go ├── machine_test.go ├── machine_windows.go ├── readme.md └── types └── type.go /.gitignore: -------------------------------------------------------------------------------- 1 | /testdata 2 | /doc 3 | /logs 4 | /build/ 5 | .idea -------------------------------------------------------------------------------- /data.go: -------------------------------------------------------------------------------- 1 | package machine_code 2 | 3 | import ( 4 | "github.com/super-l/machine-code/types" 5 | "net" 6 | "strings" 7 | ) 8 | 9 | var Machine types.MachineInformation 10 | var MachineErr []error 11 | 12 | // Obtain accurate export traffic IP information 13 | func GetIpAddr() (string, error) { 14 | conn, err := net.Dial("udp", "8.8.8.8:53") 15 | if err != nil { 16 | return "", err 17 | } 18 | localAddr := conn.LocalAddr().(*net.UDPAddr) 19 | ip := strings.Split(localAddr.String(), ":")[0] 20 | return ip, nil 21 | } 22 | 23 | // Get all IP addresses 24 | func GetIpAddrAll() ([]string, error) { 25 | var ipList []string 26 | addrList, err := net.InterfaceAddrs() 27 | if err != nil { 28 | return ipList, err 29 | } 30 | for _, address := range addrList { 31 | if ipNet, ok := address.(*net.IPNet); ok && !ipNet.IP.IsLoopback() && !ipNet.IP.IsLinkLocalUnicast() { 32 | if ipNet.IP.To4() != nil { 33 | ipList = append(ipList, ipNet.IP.To4().String()) 34 | } 35 | } 36 | } 37 | return ipList, nil 38 | } 39 | -------------------------------------------------------------------------------- /demo/demo-linux: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/super-l/machine-code/4cb40646debab63326c7964b1bf036d15b0f22be/demo/demo-linux -------------------------------------------------------------------------------- /demo/demo-windows.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/super-l/machine-code/4cb40646debab63326c7964b1bf036d15b0f22be/demo/demo-windows.exe -------------------------------------------------------------------------------- /demo/demo_darwin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/super-l/machine-code/4cb40646debab63326c7964b1bf036d15b0f22be/demo/demo_darwin -------------------------------------------------------------------------------- /demo/machine.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "encoding/json" 5 | "fmt" 6 | machine_code "github.com/super-l/machine-code" 7 | "strings" 8 | ) 9 | 10 | func main() { 11 | if machine_code.MachineErr != nil { 12 | fmt.Println("获取机器码信息错误:" + machine_code.MachineErr.Error()) 13 | return 14 | } 15 | 16 | machineJson, _ := json.Marshal(machine_code.Machine) 17 | fmt.Println("机器码信息汇总:" + string(machineJson)) 18 | 19 | trafficIp, _ := machine_code.GetIpAddr() 20 | fmt.Println("当前活跃IP:" + trafficIp) 21 | 22 | allIp, _ := machine_code.GetIpAddrAll() 23 | fmt.Println("所有IP:" + strings.Join(allIp, " ")) 24 | } 25 | -------------------------------------------------------------------------------- /demo/run1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/super-l/machine-code/4cb40646debab63326c7964b1bf036d15b0f22be/demo/run1.png -------------------------------------------------------------------------------- /demo/run2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/super-l/machine-code/4cb40646debab63326c7964b1bf036d15b0f22be/demo/run2.png -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/super-l/machine-code 2 | 3 | go 1.20 4 | -------------------------------------------------------------------------------- /go.sum: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/super-l/machine-code/4cb40646debab63326c7964b1bf036d15b0f22be/go.sum -------------------------------------------------------------------------------- /goos/common.go: -------------------------------------------------------------------------------- 1 | package goos 2 | 3 | import ( 4 | "errors" 5 | "net" 6 | "runtime" 7 | "strings" 8 | ) 9 | 10 | // determine whether it is a Windows system 11 | func IsWindows() bool { 12 | return strings.EqualFold(runtime.GOOS, "windows") 13 | } 14 | 15 | func IsMac() bool { 16 | return strings.EqualFold(runtime.GOOS, "darwin") 17 | } 18 | 19 | // IsLinux 判断当前操作系统是否为Linux系统 20 | func IsLinux() bool { 21 | return strings.EqualFold(runtime.GOOS, "linux") 22 | } 23 | 24 | // Obtain MAC address 25 | func GetMACAddress() (string, error) { 26 | netInterfaces, err := net.Interfaces() 27 | if err != nil { 28 | return "", err 29 | } 30 | var mac string 31 | var bakMac1 string 32 | var bakMac2 string 33 | 34 | for i := 0; i < len(netInterfaces); i++ { 35 | flags := netInterfaces[i].Flags.String() 36 | if strings.Contains(flags, "up") && 37 | strings.Contains(flags, "broadcast") && 38 | strings.Contains(flags, "running") && 39 | !strings.Contains(flags, "loopback") { 40 | 41 | if strings.Contains(netInterfaces[i].Name, "WLAN") { 42 | mac = netInterfaces[i].HardwareAddr.String() 43 | return mac, nil 44 | } 45 | // 感谢@lazyphp 优化windows系统下,启用了WSL系统导致MAC获取地址变化的问题 46 | if !strings.Contains(netInterfaces[i].Name, "VMware") && !strings.Contains(netInterfaces[i].Name, "WSL") { 47 | bakMac1 = netInterfaces[i].HardwareAddr.String() 48 | } else { 49 | bakMac2 = netInterfaces[i].HardwareAddr.String() 50 | } 51 | } 52 | } 53 | if mac == "" { 54 | if bakMac1 != "" { 55 | return bakMac1, nil 56 | } 57 | return bakMac2, nil 58 | } 59 | return mac, errors.New("unable to get the correct MAC address") 60 | } 61 | -------------------------------------------------------------------------------- /goos/linux.go: -------------------------------------------------------------------------------- 1 | //go:build linux 2 | // +build linux 3 | 4 | package goos 5 | 6 | import ( 7 | "bytes" 8 | "crypto/md5" 9 | "encoding/hex" 10 | "errors" 11 | "fmt" 12 | "github.com/super-l/machine-code/types" 13 | "os" 14 | "os/exec" 15 | "path/filepath" 16 | "strings" 17 | ) 18 | 19 | type LinuxMachine struct{} 20 | 21 | const DiskByIDPath = "/dev/disk/by-id/" 22 | const DiskByUUIDPath = "/dev/disk/by-uuid/" 23 | 24 | func (linux LinuxMachine) GetMachine() (types.MachineInformation, []error) { 25 | var errs []error 26 | 27 | platformUUID, err := linux.GetUUID() 28 | if err != nil { 29 | errs = append(errs, err) 30 | } 31 | boardSerialNumber, err := linux.GetBoardSerialNumber() 32 | if err != nil { 33 | errs = append(errs, err) 34 | } 35 | 36 | cpuSerialNumber, err := linux.GetCpuSerialNumber() 37 | if err != nil { 38 | errs = append(errs, err) 39 | } 40 | 41 | diskSerialNumber, err := linux.GetDiskSerialNumber() 42 | if err != nil { 43 | errs = append(errs, err) 44 | } 45 | 46 | macAddr, err := GetMACAddress() 47 | if err != nil { 48 | errs = append(errs, err) 49 | } 50 | 51 | machineData := types.MachineInformation{ 52 | UUID: platformUUID, 53 | BoardSerialNumber: boardSerialNumber, 54 | CpuSerialNumber: cpuSerialNumber, 55 | DiskSerialNumber: diskSerialNumber, 56 | Mac: macAddr, 57 | } 58 | return machineData, errs 59 | } 60 | 61 | // 主板序列码 62 | func (linux LinuxMachine) GetBoardSerialNumber() (serialNumber string, err error) { 63 | // dmidecode -s system-serial-number 64 | var cmd *exec.Cmd 65 | cmd = exec.Command("dmidecode", "-s", "system-serial-number") 66 | var out bytes.Buffer 67 | cmd.Stdout = &out 68 | cmd.Stderr = os.Stderr 69 | 70 | err = cmd.Start() 71 | if err != nil { 72 | return "", err 73 | } 74 | err = cmd.Wait() 75 | if err == nil { 76 | serial_number := out.String() 77 | serial_number = strings.Replace(serial_number, "\n", "", -1) 78 | return serial_number, nil 79 | } 80 | return "", err 81 | } 82 | 83 | // CPU序列码 84 | func (linux LinuxMachine) GetCpuSerialNumber() (cpuId string, err error) { 85 | // dmidecode -t processor |grep ID |head -1 86 | cmds := []*exec.Cmd{ 87 | exec.Command("dmidecode", "-t", "processor"), 88 | exec.Command("grep", "ID"), 89 | exec.Command("head", "-1"), 90 | } 91 | cpuId, err = linux.execPipeLine(cmds...) 92 | cpuId = strings.TrimSpace(cpuId) 93 | cpuId = strings.Replace(cpuId, "ID: ", "", -1) 94 | cpuId = strings.Replace(cpuId, "\t", "", -1) 95 | cpuId = strings.Replace(cpuId, "\n", "", -1) 96 | cpuId = strings.Replace(cpuId, " ", "-", -1) 97 | return 98 | } 99 | 100 | // 获取硬盘编号 101 | func (linux LinuxMachine) GetDiskSerialNumber() (serialNumber string, err error) { 102 | id, err1 := linux.GetDiskSerialNumberById() 103 | uuid, err2 := linux.GetDiskSerialNumberByUUID() 104 | 105 | if err1 != nil && err2 != nil { 106 | return "", err1 107 | } 108 | return fmt.Sprintf("id:%s uuid_md5:%s", id, uuid), nil 109 | } 110 | 111 | // 获取硬盘编号 112 | func (linux LinuxMachine) GetDiskSerialNumberById() (serialNumber string, err error) { 113 | // ls /dev/disk/by-id -al 114 | entries, err := os.ReadDir(DiskByIDPath) 115 | if err != nil { 116 | return "", errors.New(fmt.Sprintf("Error reading disk directory: %s", err)) 117 | } 118 | 119 | for _, entry := range entries { 120 | if entry.IsDir() { 121 | continue 122 | } 123 | 124 | linkPath := filepath.Join(DiskByIDPath, entry.Name()) 125 | _, err = os.Readlink(linkPath) 126 | if err != nil { 127 | continue 128 | } 129 | if strings.Contains(entry.Name(), "ata-") { 130 | parts := strings.Split(entry.Name(), "-") 131 | if len(parts) > 1 { 132 | serialNumber = parts[1] 133 | } else { 134 | serialNumber = entry.Name() 135 | } 136 | } 137 | } 138 | if serialNumber == "" { 139 | return "", errors.New("disk id serial number not found") 140 | } 141 | return serialNumber, nil 142 | } 143 | 144 | // 获取硬盘编号 145 | func (linux LinuxMachine) GetDiskSerialNumberByUUID() (string, error) { 146 | var result []string 147 | entries, err := os.ReadDir(DiskByUUIDPath) 148 | if err != nil { 149 | return "", errors.New(fmt.Sprintf("error reading disk directory:", err)) 150 | } 151 | 152 | for _, entry := range entries { 153 | if entry.IsDir() { 154 | continue 155 | } 156 | name := entry.Name() 157 | linkPath := filepath.Join(DiskByUUIDPath, entry.Name()) 158 | _, err = os.Readlink(linkPath) 159 | if err != nil { 160 | continue 161 | } 162 | result = append(result, name) 163 | } 164 | 165 | if len(result) == 0 { 166 | return "", errors.New("disk uuid serial number not found") 167 | } 168 | 169 | idListStr := strings.Join(result, "|") 170 | s := md5.New() 171 | s.Write([]byte(idListStr)) 172 | md5Result := hex.EncodeToString(s.Sum(nil)) 173 | 174 | return md5Result, nil 175 | } 176 | 177 | // 设备唯一UUID 178 | func (linux LinuxMachine) GetUUID() (UUID string, err error) { 179 | // dmidecode -s system-uuid UUID 180 | var cmd *exec.Cmd 181 | cmd = exec.Command("dmidecode", "-s", "system-uuid") 182 | var out bytes.Buffer 183 | cmd.Stdout = &out 184 | cmd.Stderr = os.Stderr 185 | 186 | err = cmd.Start() 187 | if err != nil { 188 | return "", err 189 | } 190 | err = cmd.Wait() 191 | if err == nil { 192 | uuid := out.String() 193 | uuid = strings.Replace(uuid, "\n", "", -1) 194 | return uuid, nil 195 | } 196 | return "", err 197 | } 198 | 199 | func (linux LinuxMachine) GetCpuSerialNumber2() (cpuId string, err error) { 200 | // dmidecode -t processor |grep ID |head -1 201 | var cmd *exec.Cmd 202 | cmd = exec.Command("dmidecode", "-t", "processor", "|grep ID |head -1") 203 | 204 | var out bytes.Buffer 205 | cmd.Stdout = &out 206 | cmd.Stderr = os.Stderr 207 | 208 | err = cmd.Start() 209 | if err != nil { 210 | return "", err 211 | } 212 | err = cmd.Wait() 213 | if err == nil { 214 | uuid := out.String() 215 | //uuid = strings.Replace(uuid, "\n", "", -1) 216 | return uuid, nil 217 | } 218 | return "", err 219 | } 220 | 221 | func (LinuxMachine) pipeline(cmds ...*exec.Cmd) (pipeLineOutput, collectedStandardError []byte, pipeLineError error) { 222 | if len(cmds) < 1 { 223 | return nil, nil, nil 224 | } 225 | 226 | var output bytes.Buffer 227 | var stderr bytes.Buffer 228 | 229 | last := len(cmds) - 1 230 | for i, cmd := range cmds[:last] { 231 | var err error 232 | if cmds[i+1].Stdin, err = cmd.StdoutPipe(); err != nil { 233 | return nil, nil, err 234 | } 235 | cmd.Stderr = &stderr 236 | } 237 | 238 | cmds[last].Stdout, cmds[last].Stderr = &output, &stderr 239 | 240 | for _, cmd := range cmds { 241 | if err := cmd.Start(); err != nil { 242 | return output.Bytes(), stderr.Bytes(), err 243 | } 244 | } 245 | 246 | for _, cmd := range cmds { 247 | if err := cmd.Wait(); err != nil { 248 | return output.Bytes(), stderr.Bytes(), err 249 | } 250 | } 251 | 252 | return output.Bytes(), stderr.Bytes(), nil 253 | } 254 | 255 | func (linux LinuxMachine) execPipeLine(cmds ...*exec.Cmd) (string, error) { 256 | output, stderr, err := linux.pipeline(cmds...) 257 | if err != nil { 258 | return "", err 259 | } 260 | 261 | if len(output) > 0 { 262 | return string(output), nil 263 | } 264 | 265 | if len(stderr) > 0 { 266 | return string(stderr), nil 267 | } 268 | return "", errors.New("no returns") 269 | } 270 | -------------------------------------------------------------------------------- /goos/mac.go: -------------------------------------------------------------------------------- 1 | //go:build darwin 2 | // +build darwin 3 | 4 | package goos 5 | 6 | import ( 7 | "bytes" 8 | "encoding/xml" 9 | "github.com/super-l/machine-code/types" 10 | "os" 11 | "os/exec" 12 | "strings" 13 | ) 14 | 15 | type MacMachine struct{} 16 | 17 | var macMachineData types.MachineInformation 18 | 19 | type macXmlStruct struct { 20 | XMLName xml.Name `xml:"plist"` 21 | Array macDataArrayStruct `xml:"array"` 22 | } 23 | 24 | type macDataArrayStruct struct { 25 | Dict macDictStruct `xml:"dict"` // 读取user数组 26 | } 27 | 28 | type macDictStruct struct { 29 | Key []string `xml:"key"` 30 | Real []string `xml:"real"` 31 | String []string `xml:"string"` 32 | Array macDictArrayStruct `xml:"array"` 33 | } 34 | 35 | type macDictArrayStruct struct { 36 | Dict macDictItemStruct `xml:"dict"` // 读取user数组 37 | } 38 | 39 | type macDictItemStruct struct { 40 | Key []string `xml:"key"` 41 | Integer []int `xml:"integer"` 42 | String []string `xml:"string"` 43 | } 44 | 45 | func (mac MacMachine) GetMachine() (types.MachineInformation, []error) { 46 | var errs []error 47 | 48 | platformUUID, err := mac.GetUUID() 49 | if err != nil { 50 | errs = append(errs, err) 51 | } 52 | boardSerialNumber, err := mac.GetBoardSerialNumber() 53 | if err != nil { 54 | errs = append(errs, err) 55 | } 56 | 57 | cpuSerialNumber, err := mac.GetCpuSerialNumber() 58 | if err != nil { 59 | errs = append(errs, err) 60 | } 61 | 62 | diskSerialNumber, err := mac.GetDiskSerialNumber() 63 | if err != nil { 64 | errs = append(errs, err) 65 | } 66 | 67 | macAddr, err := GetMACAddress() 68 | if err != nil { 69 | errs = append(errs, err) 70 | } 71 | 72 | machineData := types.MachineInformation{ 73 | UUID: platformUUID, 74 | BoardSerialNumber: boardSerialNumber, 75 | CpuSerialNumber: cpuSerialNumber, 76 | DiskSerialNumber: diskSerialNumber, 77 | Mac: macAddr, 78 | } 79 | return machineData, errs 80 | } 81 | 82 | func (mac MacMachine) GetBoardSerialNumber() (data string, err error) { 83 | sysInfo, err := mac.GetMacSysInfo() 84 | if err != nil { 85 | return "", err 86 | } 87 | return sysInfo.BoardSerialNumber, err 88 | } 89 | 90 | func (mac MacMachine) GetUUID() (UUID string, err error) { 91 | sysInfo, err := mac.GetMacSysInfo() 92 | if err != nil { 93 | return "", err 94 | } 95 | return sysInfo.UUID, err 96 | } 97 | 98 | func (mac MacMachine) GetCpuSerialNumber() (cpuId string, err error) { 99 | sysInfo, err := mac.GetMacSysInfo() 100 | if err != nil { 101 | return "", err 102 | } 103 | return sysInfo.CpuSerialNumber, err 104 | } 105 | 106 | // 获取硬盘编号 107 | func (mac MacMachine) GetDiskSerialNumber() (serialNumber string, err error) { 108 | return "xxx", nil 109 | } 110 | 111 | func (mac MacMachine) GetMacSysInfo() (data types.MachineInformation, err error) { 112 | var cmd *exec.Cmd 113 | cmd = exec.Command("system_profiler", "SPHardwareDataType", "-xml") 114 | 115 | var out bytes.Buffer 116 | cmd.Stdout = &out 117 | cmd.Stderr = os.Stderr 118 | 119 | err = cmd.Start() 120 | if err != nil { 121 | return types.MachineInformation{}, err 122 | } 123 | 124 | err = cmd.Wait() 125 | if err == nil { 126 | macMachineData, err = mac.macXmlToData(out.String()) 127 | if err == nil { 128 | macMachineData.CpuSerialNumber, _ = mac.getCpuSerialNumberBase() 129 | } 130 | return macMachineData, nil 131 | } 132 | return types.MachineInformation{}, err 133 | } 134 | 135 | func (MacMachine) macXmlToData(xmlcontent string) (types.MachineInformation, error) { 136 | x := macXmlStruct{} 137 | err := xml.Unmarshal([]byte(xmlcontent), &x) 138 | if err != nil { 139 | return types.MachineInformation{}, err 140 | } 141 | count := len(x.Array.Dict.Array.Dict.String) 142 | serialData := types.MachineInformation{ 143 | UUID: x.Array.Dict.Array.Dict.String[count-2], 144 | BoardSerialNumber: x.Array.Dict.Array.Dict.String[count-1], 145 | CpuSerialNumber: "", 146 | } 147 | return serialData, nil 148 | } 149 | 150 | func (mac MacMachine) getCpuSerialNumberBase() (cpuId string, err error) { 151 | //sysctl -x machdep.cpu.signature 152 | var cmd *exec.Cmd 153 | cmd = exec.Command("sysctl", "-x", "machdep.cpu.signature") 154 | 155 | var out bytes.Buffer 156 | cmd.Stdout = &out 157 | cmd.Stderr = os.Stderr 158 | 159 | err = cmd.Start() 160 | if err != nil { 161 | return "", err 162 | } 163 | err = cmd.Wait() 164 | if err == nil { 165 | cpuId = out.String() 166 | cpuId = strings.Replace(cpuId, " ", "", -1) 167 | cpuId = strings.Replace(cpuId, "\n", "", -1) 168 | cpuId = strings.Replace(cpuId, "machdep.cpu.signature:", "", -1) 169 | return cpuId, nil 170 | } 171 | return "", err 172 | } 173 | -------------------------------------------------------------------------------- /goos/windows.go: -------------------------------------------------------------------------------- 1 | //go:build windows 2 | // +build windows 3 | 4 | package goos 5 | 6 | import ( 7 | "errors" 8 | "fmt" 9 | "github.com/super-l/machine-code/types" 10 | "os/exec" 11 | "strings" 12 | "syscall" 13 | ) 14 | 15 | type WindowsMachine struct{} 16 | 17 | func (w WindowsMachine) GetMachine() (types.MachineInformation, []error) { 18 | var errs []error 19 | 20 | platformUUID, err := w.GetUUID() 21 | if err != nil { 22 | errs = append(errs, err) 23 | } 24 | boardSerialNumber, err := w.GetBoardSerialNumber() 25 | if err != nil { 26 | errs = append(errs, err) 27 | } 28 | 29 | cpuSerialNumber, err := w.GetCpuSerialNumber() 30 | if err != nil { 31 | errs = append(errs, err) 32 | } 33 | 34 | diskSerialNumber, err := w.GetDiskSerialNumber() 35 | if err != nil { 36 | errs = append(errs, err) 37 | } 38 | 39 | macAddr, err := GetMACAddress() 40 | if err != nil { 41 | errs = append(errs, err) 42 | } 43 | 44 | machineData := types.MachineInformation{ 45 | UUID: platformUUID, 46 | BoardSerialNumber: boardSerialNumber, 47 | CpuSerialNumber: cpuSerialNumber, 48 | DiskSerialNumber: diskSerialNumber, 49 | Mac: macAddr, 50 | } 51 | return machineData, errs 52 | } 53 | 54 | // 获取主板编号 55 | func (WindowsMachine) GetBoardSerialNumber() (string, error) { 56 | cmd := exec.Command("wmic", "baseboard", "get", "serialnumber") 57 | cmd.SysProcAttr = &syscall.SysProcAttr{HideWindow: true} // @bestK 提交 58 | b, err := cmd.CombinedOutput() 59 | if err == nil { 60 | serialNumber := string(b) 61 | serialNumber = serialNumber[12 : len(serialNumber)-2] 62 | serialNumber = strings.ReplaceAll(serialNumber, "\n", "") 63 | serialNumber = strings.ReplaceAll(serialNumber, " ", "") 64 | serialNumber = strings.ReplaceAll(serialNumber, "\r", "") 65 | return serialNumber, nil 66 | } 67 | return "", err 68 | } 69 | 70 | // 获取硬盘编号 71 | func (WindowsMachine) GetDiskSerialNumber() (serialNumber string, err error) { 72 | cmd := exec.Command("wmic", "diskdrive", "get", "serialnumber") 73 | cmd.SysProcAttr = &syscall.SysProcAttr{HideWindow: true} // @bestK 提交 74 | output, err := cmd.Output() 75 | if err != nil { 76 | return "", err 77 | } 78 | result := strings.TrimSpace(string(output)) 79 | lines := strings.Split(result, "\n") 80 | if len(lines) > 1 { 81 | return strings.TrimSpace(lines[1]), nil 82 | } 83 | return "", fmt.Errorf("diskdrive serial number not found") 84 | } 85 | 86 | // 获取系统UUID 87 | func (WindowsMachine) GetUUID() (string, error) { 88 | // wmic csproduct get uuid || wmic csproduct list full | findstr UUID 89 | var cmd *exec.Cmd 90 | cmd = exec.Command("wmic", "csproduct", "get", "uuid") 91 | cmd.SysProcAttr = &syscall.SysProcAttr{HideWindow: true} // @bestK 提交 92 | b, err := cmd.CombinedOutput() 93 | 94 | var uuid string 95 | if err == nil { 96 | uuid = string(b) 97 | uuid = uuid[4 : len(uuid)-1] 98 | uuid = strings.ReplaceAll(uuid, "\n", "") 99 | uuid = strings.ReplaceAll(uuid, " ", "") 100 | uuid = strings.ReplaceAll(uuid, "\r", "") 101 | return uuid, nil 102 | } 103 | return "", errors.New("csproduct uuid not found") 104 | } 105 | 106 | // 获取CPU序列号 107 | func (WindowsMachine) GetCpuSerialNumber() (string, error) { 108 | // wmic cpu get processorid 109 | var cpuid string 110 | cmd := exec.Command("wmic", "cpu", "get", "processorid") 111 | cmd.SysProcAttr = &syscall.SysProcAttr{HideWindow: true} // @bestK 提交 112 | b, err := cmd.CombinedOutput() 113 | if err == nil { 114 | cpuid = string(b) 115 | cpuid = cpuid[12 : len(cpuid)-2] 116 | cpuid = strings.ReplaceAll(cpuid, "\n", "") 117 | cpuid = strings.ReplaceAll(cpuid, " ", "") 118 | cpuid = strings.ReplaceAll(cpuid, "\r", "") 119 | return cpuid, err 120 | } 121 | return "", errors.New("cpu processorid not found") 122 | } 123 | -------------------------------------------------------------------------------- /interface.go: -------------------------------------------------------------------------------- 1 | package machine_code 2 | 3 | import "github.com/super-l/machine-code/types" 4 | 5 | type OsMachineInterface interface { 6 | GetMachine() (types.MachineInformation, []error) 7 | GetBoardSerialNumber() (string, error) 8 | GetCpuSerialNumber() (string, error) 9 | GetDiskSerialNumber() (string, error) 10 | GetUUID() (string, error) 11 | } 12 | -------------------------------------------------------------------------------- /machine_darwin.go: -------------------------------------------------------------------------------- 1 | //go:build darwin 2 | // +build darwin 3 | 4 | package machine_code 5 | 6 | import "github.com/super-l/machine-code/goos" 7 | 8 | func init() { 9 | Machine, MachineErr = goos.MacMachine{}.GetMachine() 10 | } 11 | -------------------------------------------------------------------------------- /machine_linux.go: -------------------------------------------------------------------------------- 1 | //go:build linux 2 | // +build linux 3 | 4 | package machine_code 5 | 6 | import "github.com/super-l/machine-code/goos" 7 | 8 | func init() { 9 | Machine, MachineErr = goos.LinuxMachine{}.GetMachine() 10 | } 11 | -------------------------------------------------------------------------------- /machine_test.go: -------------------------------------------------------------------------------- 1 | package machine_code 2 | 3 | import ( 4 | "encoding/json" 5 | "fmt" 6 | "testing" 7 | ) 8 | 9 | func TestGetMachine(t *testing.T) { 10 | if MachineErr != nil { 11 | fmt.Println(MachineErr) 12 | return 13 | } 14 | 15 | machineJson, _ := json.Marshal(Machine) 16 | fmt.Println(string(machineJson)) 17 | } 18 | -------------------------------------------------------------------------------- /machine_windows.go: -------------------------------------------------------------------------------- 1 | //go:build windows 2 | // +build windows 3 | 4 | package machine_code 5 | 6 | import "github.com/super-l/machine-code/goos" 7 | 8 | func init() { 9 | Machine, MachineErr = goos.WindowsMachine{}.GetMachine() 10 | } 11 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # 简介 2 | 3 | machine-code,是忘忧草安全团队出品的一款使用GO语言实现的跨平台机器码(硬件信息)获取程序。 4 | 5 | 能获取的信息包括系统UUID、主板序列号、CPU序列号、MAC网卡信息、硬盘序列号等。主要用于设备特征识别、商业软件授权CDKEY生成等等。 6 | 7 | 同时支持windows、Linux、mac等系统,引入本库后,可与您的项目代码无缝集成,并且同时支持跨平台编译。 8 | 9 | # 更新 10 | 11 | 12 | ## 2024-11-21 v1.3 13 | 14 | 1. 优化与修复windows下获取硬盘编号异常的问题; 15 | 2. 如果获取某个序列号失败,不会再直接返回以及终止其他序列号的获取逻辑。同时返回的错误信息可以存在多个。 16 | 3. mac系统下获取硬盘序列号的代码暂时以返回"xxx"代替,待回家找到mac本本实测后再补充(老版本逻辑依赖lsblk导致不好用)。 17 | 18 | 19 | ## 2024-11-18 v1.2 20 | 21 | 1. 优化linux下获取硬盘ID序列码。避免序列码太多导致拼接起来太长,使用MD5算法二次加密。 22 | 23 | 24 | ## 2024-11-18 v1.1 25 | 26 | 1. 项目重写与优化,调整项目文件结构; 27 | 2. 添加编译时变量,可直接无需调整任何代码,编译生成多个系统的目标文件不会出现编译错误; 28 | 3. linux下获取磁盘系列号方案更新; 29 | 4. 本着精简,能不用其他库就不用的原则,本项目不再使用其他三方库如wmi。 30 | 5. 迁移与合并码友对老版本的改进代码。 31 | 32 | 33 | ## 2021-07-20 v1.0 34 | 1. 只是简单的做个分享 35 | 36 | 37 | # 安装说明 38 | 39 | ``` 40 | go get github.com/super-l/machine-code 41 | ``` 42 | 43 | 44 | # 使用方法 45 | 46 | 具体可查看项目的demo目录。并且提供编译好的demo测试程序,以及运行截图。 47 | 48 | 使用代码如: 49 | 50 | ``` 51 | package main 52 | 53 | import ( 54 | "encoding/json" 55 | "fmt" 56 | machine_code "github.com/super-l/machine-code" 57 | "strings" 58 | ) 59 | 60 | func main() { 61 | if machine_code.MachineErr != nil { 62 | fmt.Println("获取机器码信息错误:" + machine_code.MachineErr.Error()) 63 | return 64 | } 65 | 66 | machineJson, _ := json.Marshal(machine_code.Machine) 67 | fmt.Println("机器码信息汇总:" + string(machineJson)) 68 | 69 | trafficIp, _ := machine_code.GetIpAddr() 70 | fmt.Println("当前活跃IP:" + trafficIp) 71 | 72 | allIp, _ := machine_code.GetIpAddrAll() 73 | fmt.Println("所有IP:" + strings.Join(allIp, " ")) 74 | } 75 | 76 | ``` 77 | 78 | # 运行截图 79 | 80 | ![image1](https://github.com/super-l/machine-code/blob/master/demo/run1.png) 81 | 82 | ![image2](https://github.com/super-l/machine-code/blob/master/demo/run2.png) 83 | 84 | # 注意事项 85 | 86 | windows下使用的是wmi相关命令来获取系统信息。理论上99.99%成功率。但不排除部分电脑的wmi关闭或损坏等。 87 | 88 | linux下主要是使用的基于特定系统文件读取信息。 89 | 90 | 91 | # 其他 92 | 93 | 如果能帮到您,如果您觉得不错,请给项目点个赞(star)吧,您的支持是我前进的动力,谢谢! 94 | 95 | ```html 96 | 技术交流QQ群:50246933 97 | 技术博客: http://www.xiao6.net 98 | ``` 99 | 100 | 感谢 @lazyphp 和 @bestK 的改进提交! -------------------------------------------------------------------------------- /types/type.go: -------------------------------------------------------------------------------- 1 | package types 2 | 3 | type MachineInformation struct { 4 | UUID string `json:"uuid"` 5 | BoardSerialNumber string `json:"boardSerialNumber"` // 主板序列号 6 | CpuSerialNumber string `json:"cpuSerialNumber"` // cpu序列号 7 | DiskSerialNumber string `json:"diskSerialNumber"` // 硬盘序列号 8 | Mac string `json:"mac"` // 本地网卡mac相关信息 9 | } 10 | --------------------------------------------------------------------------------