├── README.md └── ms17-010.ps1 /README.md: -------------------------------------------------------------------------------- 1 | # ms17-010-Scanner 2 | 3 | Test for MS17-010 in PS 4 | -------------------------------------------------------------------------------- /ms17-010.ps1: -------------------------------------------------------------------------------- 1 | $Source = @" 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Diagnostics; 5 | using System.IO; 6 | using System.Net; 7 | using System.Net.Sockets; 8 | using System.Text; 9 | 10 | namespace PingCastle.Scanners 11 | { 12 | public class ms17_010scanner 13 | { 14 | static public bool ScanForMs17_010(string computer) 15 | { 16 | Trace.WriteLine("Checking " + computer + " for MS17-010"); 17 | TcpClient client = new TcpClient(); 18 | client.Connect(computer, 445); 19 | try 20 | { 21 | NetworkStream stream = client.GetStream(); 22 | byte[] negotiatemessage = GetNegotiateMessage(); 23 | stream.Write(negotiatemessage, 0, negotiatemessage.Length); 24 | stream.Flush(); 25 | byte[] response = ReadSmbResponse(stream); 26 | if (!(response[8] == 0x72 && response[9] == 00)) 27 | { 28 | throw new InvalidOperationException("invalid negotiate response"); 29 | } 30 | byte[] sessionSetup = GetSessionSetupAndXRequest(response); 31 | stream.Write(sessionSetup, 0, sessionSetup.Length); 32 | stream.Flush(); 33 | response = ReadSmbResponse(stream); 34 | if (!(response[8] == 0x73 && response[9] == 00)) 35 | { 36 | throw new InvalidOperationException("invalid sessionSetup response"); 37 | } 38 | byte[] treeconnect = GetTreeConnectAndXRequest(response, computer); 39 | stream.Write(treeconnect, 0, treeconnect.Length); 40 | stream.Flush(); 41 | response = ReadSmbResponse(stream); 42 | if (!(response[8] == 0x75 && response[9] == 00)) 43 | { 44 | throw new InvalidOperationException("invalid TreeConnect response"); 45 | } 46 | byte[] peeknamedpipe = GetPeekNamedPipe(response); 47 | stream.Write(peeknamedpipe, 0, peeknamedpipe.Length); 48 | stream.Flush(); 49 | response = ReadSmbResponse(stream); 50 | if (response[8] == 0x25 && response[9] == 0x05 && response[10] ==0x02 && response[11] ==0x00 && response[12] ==0xc0 ) 51 | { 52 | return true; 53 | } 54 | } 55 | catch (Exception) 56 | { 57 | throw; 58 | } 59 | return false; 60 | } 61 | 62 | private static byte[] ReadSmbResponse(NetworkStream stream) 63 | { 64 | byte[] temp = new byte[4]; 65 | stream.Read(temp, 0, 4); 66 | int size = temp[3] + temp[2] * 0x100 + temp[3] * 0x10000; 67 | byte[] output = new byte[size + 4]; 68 | stream.Read(output, 4, size); 69 | Array.Copy(temp, output, 4); 70 | return output; 71 | } 72 | 73 | static byte[] GetNegotiateMessage() 74 | { 75 | byte[] output = new byte[] { 76 | 0x00,0x00,0x00,0x00, // Session Message 77 | 0xff,0x53,0x4d,0x42, // Server Component: SMB 78 | 0x72, // SMB Command: Negotiate Protocol (0x72) 79 | 0x00, // Error Class: Success (0x00) 80 | 0x00, // Reserved 81 | 0x00,0x00, // Error Code: No Error 82 | 0x18, // Flags 83 | 0x01,0x28, // Flags 2 84 | 0x00,0x00, // Process ID High 0 85 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // Signature 86 | 0x00,0x00, // Reserved 87 | 0x00,0x00, // Tree id 0 88 | 0x44,0x6d, // Process ID 27972 89 | 0x00,0x00, // User ID 0 90 | 0x42,0xc1, // Multiplex ID 49474 91 | 0x00, // WCT 0 92 | 0x31,0x00, // BCC 49 93 | 0x02,0x4c,0x41,0x4e,0x4d,0x41,0x4e,0x31,0x2e,0x30,0x00, // LANMAN1.0 94 | 0x02,0x4c,0x4d,0x31,0x2e,0x32,0x58,0x30,0x30,0x32,0x00, // LM1.2X002 95 | 0x02,0x4e,0x54,0x20,0x4c,0x41,0x4e,0x4d,0x41,0x4e,0x20,0x31,0x2e,0x30,0x00, // NT LANMAN 1.0 96 | 0x02,0x4e,0x54,0x20,0x4c,0x4d,0x20,0x30,0x2e,0x31,0x32,0x00, // NT LM 0.12 97 | }; 98 | return EncodeNetBiosLength(output); 99 | } 100 | 101 | static byte[] GetSessionSetupAndXRequest(byte[] data) 102 | { 103 | byte[] output = new byte[] { 104 | 0x00,0x00,0x00,0x00, // Session Message 105 | 0xff,0x53,0x4d,0x42, // Server Component: SMB 106 | 0x73, // SMB Command: Session Setup AndX (0x73) 107 | 0x00, // Error Class: Success (0x00) 108 | 0x00, // Reserved 109 | 0x00,0x00, // Error Code: No Error 110 | 0x18, // Flags 111 | 0x01,0x28, // Flags 2 112 | 0x00,0x00, // Process ID High 0 113 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // Signature 114 | 0x00,0x00, // Reserved 115 | data[28],data[29],data[30],data[31],data[32],data[33], 116 | 0x42,0xc1, // Multiplex ID 49474 117 | 0x0d, // WCT 0 118 | 0xff, // AndXCommand: No further commands (0xff) 119 | 0x00, // Reserved 00 120 | 0x00,0x00, // AndXOffset: 0 121 | 0xdf,0xff, // Max Buffer: 65503 122 | 0x02,0x00, // Max Mpx Count: 2 123 | 0x01,0x00, // VC Number: 1 124 | 0x00,0x00,0x00,0x00, // Session Key: 0x00000000 125 | 0x00,0x00, // ANSI Password Length: 0 126 | 0x00,0x00, // Unicode Password Length: 0 127 | 0x00,0x00,0x00,0x00, // Reserved: 00000000 128 | 0x40,0x00,0x00,0x00, // Capabilities: 0x00000040, NT Status Codes 129 | 0x26,0x00, // Byte Count (BCC): 38 130 | 0x00, // Account: 131 | 0x2e,0x00, // Primary Domain: . 132 | 0x57,0x69,0x6e,0x64,0x6f,0x77,0x73,0x20,0x32,0x30,0x30,0x30,0x20,0x32,0x31,0x39,0x35,0x00, // Native OS: Windows 2000 2195 133 | 0x57,0x69,0x6e,0x64,0x6f,0x77,0x73,0x20,0x32,0x30,0x30,0x30,0x20,0x35,0x2e,0x30,0x00 // Native LAN Manager: Windows 2000 5.0 134 | }; 135 | return EncodeNetBiosLength(output); 136 | } 137 | 138 | private static byte[] EncodeNetBiosLength(byte[] input) 139 | { 140 | byte[] len = BitConverter.GetBytes(input.Length-4); 141 | input[3] = len[0]; 142 | input[2] = len[1]; 143 | input[1] = len[2]; 144 | return input; 145 | } 146 | 147 | static byte[] GetTreeConnectAndXRequest(byte[] data, string computer) 148 | { 149 | MemoryStream ms = new MemoryStream(); 150 | BinaryReader reader = new BinaryReader(ms); 151 | byte[] part1 = new byte[] { 152 | 0x00,0x00,0x00,0x00, // Session Message 153 | 0xff,0x53,0x4d,0x42, // Server Component: SMB 154 | 0x75, // SMB Command: Tree Connect AndX (0x75) 155 | 0x00, // Error Class: Success (0x00) 156 | 0x00, // Reserved 157 | 0x00,0x00, // Error Code: No Error 158 | 0x18, // Flags 159 | 0x01,0x28, // Flags 2 160 | 0x00,0x00, // Process ID High 0 161 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // Signature 162 | 0x00,0x00, // Reserved 163 | data[28],data[29],data[30],data[31],data[32],data[33], 164 | 0x42,0xc1, // Multiplex ID 49474 165 | 0x04, // WCT 4 166 | 0xff, // AndXCommand: No further commands (0xff) 167 | 0x00, // Reserved: 00 168 | 0x00,0x00, // AndXOffset: 0 169 | 0x00,0x00, // Flags: 0x0000 170 | 0x01,0x00, // Password Length: 1 171 | 0x19,0x00, // Byte Count (BCC): 25 172 | 0x00, // Password: 00 173 | 0x5c,0x5c}; 174 | byte[] part2 = new byte[] { 175 | 0x5c,0x49,0x50,0x43,0x24,0x00, // Path: \\ip_target\IPC$ 176 | 0x3f,0x3f,0x3f,0x3f,0x3f,0x00 177 | }; 178 | ms.Write(part1, 0, part1.Length); 179 | byte[] encodedcomputer = new ASCIIEncoding().GetBytes(computer); 180 | ms.Write(encodedcomputer, 0, encodedcomputer.Length); 181 | ms.Write(part2, 0, part2.Length); 182 | ms.Seek(0, SeekOrigin.Begin); 183 | byte[] output = reader.ReadBytes((int) reader.BaseStream.Length); 184 | return EncodeNetBiosLength(output); 185 | } 186 | 187 | static byte[] GetPeekNamedPipe(byte[] data) 188 | { 189 | byte[] output = new byte[] { 190 | 0x00,0x00,0x00,0x00, // Session Message 191 | 0xff,0x53,0x4d,0x42, // Server Component: SMB 192 | 0x25, // SMB Command: Trans (0x25) 193 | 0x00, // Error Class: Success (0x00) 194 | 0x00, // Reserved 195 | 0x00,0x00, // Error Code: No Error 196 | 0x18, // Flags 197 | 0x01,0x28, // Flags 2 198 | 0x00,0x00, // Process ID High 0 199 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // Signature 200 | 0x00,0x00, // Reserved 201 | data[28],data[29],data[30],data[31],data[32],data[33], 202 | 0x42,0xc1, // Multiplex ID 49474 203 | 0x10, // Word Count (WCT): 16 204 | 0x00,0x00, // Total Parameter Count: 0 205 | 0x00,0x00, // Total Data Count: 0 206 | 0xff,0xff, // Max Parameter Count: 65535 207 | 0xff,0xff, // Max Data Count: 65535 208 | 0x00, // Max Setup Count: 0 209 | 0x00, // Reserved: 00 210 | 0x00,0x00, // Flags: 0x0000 211 | 0x00,0x00,0x00,0x00, // Timeout: Return immediately (0) 212 | 0x00,0x00, // Reserved: 0000 213 | 0x00,0x00, // Parameter Count: 0 214 | 0x4a,0x00, // Parameter Offset: 74 215 | 0x00,0x00, // Data Count: 0 216 | 0x4a,0x00, // Data Offset: 74 217 | 0x02, // Setup Count: 2 218 | 0x00, // Reserved: 00 219 | 0x23,0x00, // Function: PeekNamedPipe (0x0023) 220 | 0x00,0x00, // FID: 0x0000 221 | 0x07,0x00, // Byte Count (BCC): 7 222 | 0x5c,0x50,0x49,0x50,0x45,0x5c,0x00 // Transaction Name: \PIPE\ 223 | }; 224 | return EncodeNetBiosLength(output); 225 | } 226 | } 227 | } 228 | "@ 229 | Add-Type -TypeDefinition $Source 230 | 231 | [PingCastle.Scanners.ms17_010scanner]::ScanForMs17_010("192.168.0.25") 232 | --------------------------------------------------------------------------------