├── LICENSE ├── README.md └── dcerpc_os_info.go /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 W01fh4cker 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # DceRPC-OS-Info 2 | `golang`实现通过`dcerpc`和`ntlmssp`获取`Windows`远程主机信息 3 | 4 | 由于某些原因需要把`komomon`师傅写的脚本转化成`golang`的形式,源仓库链接如下: 5 | 6 | > https://github.com/komomon/Dcerpc_Find_OSInfo 7 | 8 | 9 | 简单实现,有需要的话请自行修改代码。 10 | ```powershell 11 | go build dcerpc_os_info.go 12 | ``` 13 | 14 | 扫描单独`ip`: 15 | 16 | ![](https://cdn.jsdelivr.net/gh/W01fh4cker/blog_image@main/image-20240416200622839.png) 17 | 18 | 扫描`C`段: 19 | 20 | ![](https://cdn.jsdelivr.net/gh/W01fh4cker/blog_image@main/image-20240416205535385.png) 21 | -------------------------------------------------------------------------------- /dcerpc_os_info.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "bytes" 5 | "fmt" 6 | "net" 7 | "sync" 8 | "time" 9 | ) 10 | 11 | const TIME_OUT = 5 * time.Second 12 | 13 | func attributeName(TargetInfoBytes []byte, length int) (string, int) { 14 | attNameLength := int(TargetInfoBytes[length+2]) | (int(TargetInfoBytes[length+3]) << 8) 15 | attName := bytes.ReplaceAll(TargetInfoBytes[length+4:length+4+attNameLength], []byte{0x00}, []byte("")) 16 | length += 4 + attNameLength 17 | return string(attName), length 18 | } 19 | 20 | func sendPacket(ip string) string { 21 | conn, err := net.DialTimeout("tcp", ip+":135", TIME_OUT) 22 | if err != nil { 23 | return "-1" 24 | } 25 | defer conn.Close() 26 | 27 | _, err = conn.Write([]byte{0x05, 0x00, 0x0b, 0x03, 0x10, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xb8, 0x10, 0xb8, 0x10, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x08, 0x83, 0xaf, 0xe1, 0x1f, 0x5d, 0xc9, 0x11, 0x91, 0xa4, 0x08, 0x00, 0x2b, 0x14, 0xa0, 0xfa, 0x03, 0x00, 0x00, 0x00, 0x33, 0x05, 0x71, 0x71, 0xba, 0xbe, 0x37, 0x49, 0x83, 0x19, 0xb5, 0xdb, 0xef, 0x9c, 0xcc, 0x36, 0x01, 0x00, 0x00, 0x00}) 28 | if err != nil { 29 | return "-1" 30 | } 31 | 32 | buffer1 := make([]byte, 1024) 33 | _, err = conn.Read(buffer1) 34 | if err != nil { 35 | return "-1" 36 | } 37 | 38 | digit := "x86" 39 | if bytes.Contains(buffer1, []byte{0x33, 0x05, 0x71, 0x71, 0xBA, 0xBE, 0x37, 0x49, 0x83, 0x19, 0xB5, 0xDB, 0xEF, 0x9C, 0xCC, 0x36}) { 40 | digit = "x64" 41 | } 42 | 43 | return digit 44 | } 45 | 46 | func getOSInfo(ip string) map[string]interface{} { 47 | osInfo := map[string]interface{}{ 48 | "NetBIOS_domain_name": "", 49 | "DNS_domain_name": "", 50 | "DNS_computer_name": "", 51 | "DNS_tree_name": "", 52 | } 53 | 54 | conn, err := net.DialTimeout("tcp", ip+":135", TIME_OUT) 55 | if err != nil { 56 | return nil 57 | } 58 | defer func(conn net.Conn) { 59 | err := conn.Close() 60 | if err != nil { 61 | return 62 | } 63 | }(conn) 64 | length := 0 65 | _, err = conn.Write([]byte{0x05, 0x00, 0x0b, 0x03, 0x10, 0x00, 0x00, 0x00, 0x78, 0x00, 0x28, 0x00, 0x03, 0x00, 0x00, 0x00, 0xb8, 0x10, 0xb8, 0x10, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0xa0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0x00, 0x00, 0x00, 0x00, 0x04, 0x5d, 0x88, 0x8a, 0xeb, 0x1c, 0xc9, 0x11, 0x9f, 0xe8, 0x08, 0x00, 0x2b, 0x10, 0x48, 0x60, 0x02, 0x00, 0x00, 0x00, 0x0a, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4e, 0x54, 0x4c, 0x4d, 0x53, 0x53, 0x50, 0x00, 0x01, 0x00, 0x00, 0x00, 0x07, 0x82, 0x08, 0xa2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x01, 0xb1, 0x1d, 0x00, 0x00, 0x00, 0x0f}) 66 | if err != nil { 67 | return nil 68 | } 69 | 70 | buffer2 := make([]byte, 4096) 71 | _, err = conn.Read(buffer2) 72 | if err != nil { 73 | return nil 74 | } 75 | digit := sendPacket(ip) 76 | 77 | OSVersionBytes := buffer2[0xa0-54+10 : 0xa0-54+18] 78 | majorVersion := int(OSVersionBytes[0]) 79 | minorVersion := int(OSVersionBytes[1]) 80 | buildNumber := int(OSVersionBytes[2]) | (int(OSVersionBytes[3]) << 8) 81 | OSVersion := fmt.Sprintf("Windows Version %d.%d Build %d %s", majorVersion, minorVersion, buildNumber, digit) 82 | 83 | TargetInfoLengthBytes := buffer2[int(0xa0)-54+2 : int(0xa0)-54+4] 84 | TargetInfoLength := int(TargetInfoLengthBytes[0]) | (int(TargetInfoLengthBytes[1]) << 8) 85 | trimmedBuffer2 := bytes.TrimRight(buffer2, "\x00") 86 | bufferLength := len(trimmedBuffer2) 87 | TargetInfoBytes := trimmedBuffer2[bufferLength-TargetInfoLength+4 : bufferLength] 88 | fmt.Println("[*] " + ip) 89 | fmt.Println("\t[->] OS_Version :", OSVersion) 90 | for k := range osInfo { 91 | osInfo[k], _ = attributeName(TargetInfoBytes, length) 92 | fmt.Println("\t[->]", k, ":", osInfo[k]) 93 | } 94 | 95 | osInfo["OS_Version"] = OSVersion 96 | result := map[string]interface{}{ip: osInfo} 97 | return result 98 | } 99 | 100 | //func main() { 101 | // ip := "192.168.198.142" 102 | // getOSInfo(ip) 103 | //} 104 | 105 | func main() { 106 | ipPrefix := "192.168.198." 107 | threadCount := 20 108 | 109 | var wg sync.WaitGroup 110 | wg.Add(threadCount) 111 | 112 | for i := 0; i < threadCount; i++ { 113 | go func(start int) { 114 | defer wg.Done() 115 | for j := start; j < start+256/threadCount; j++ { 116 | ip := fmt.Sprintf("%s%d", ipPrefix, j) 117 | getOSInfo(ip) 118 | } 119 | }(i * 256 / threadCount) 120 | } 121 | 122 | wg.Wait() 123 | } 124 | --------------------------------------------------------------------------------